/** * ollama_code_review — FT-001. Structured code review of a diff. * * Given a unified diff (and optionally the full source paths the diff * touches), returns a structured list of review findings. Each finding * has severity + category + file + line + symbol + description + * recommendation. Output is filtered by `severity_floor` and truncated * to `max_findings`. * * Tier: workhorse by default; callers can opt up to deep for * security-critical or high-stakes reviews. Instant is also allowed for * fast smoke passes on small diffs. * * Shape discipline: mirrors `refactor_plan` / `multi_file_refactor_propose` * — JSON mode, runner-resolved tier/model, coerce-before-trust on the * model output so malformed entries are dropped rather than crashing the * tool. The result envelope's `result.findings` is the operator-facing * surface; `result.summary` is a 1-2 sentence overall verdict; * `result.diff_size_bytes` lets receipts spot when a diff was clipped. * * Registration note for backend-core: this tool exports its handler + * schema but does NOT self-register on the MCP server (server.tool * registration lives in src/index.ts, outside the tools agent's scope). * Add the registration block to src/index.ts: * * import { codeReviewSchema, handleCodeReview } from "./tools/codeReview.js"; * * server.tool( * "ollama_code_review", * "REVIEW. Structured code review of a unified diff. Pass `diff` (required, 1-2MB), optional `source_paths[]` for full file context, optional `severity_floor` (default 'low'), `max_findings` (default 50, max 200), `tier` (default 'workhorse'; 'deep' for high-stakes, 'instant' for fast smoke passes). Returns `{findings:[{severity, category, file, line, symbol?, description, recommendation}], summary, diff_size_bytes}` — severity is critical|high|medium|low, category is bug|security|performance|style|maintainability. Malformed entries are dropped server-side (never throws on model output shape).", * codeReviewSchema.shape, * (args) => wrap(handleCodeReview(args, ctx)), * ); */ import { z } from "zod"; import type { Envelope } from "../envelope.js"; import type { RunContext } from "../runContext.js"; declare const SEVERITIES: readonly ["critical", "high", "medium", "low"]; declare const CATEGORIES: readonly ["bug", "security", "performance", "style", "maintainability"]; export type Severity = (typeof SEVERITIES)[number]; export type Category = (typeof CATEGORIES)[number]; export declare const codeReviewSchema: z.ZodObject<{ diff_text: z.ZodString; source_paths: z.ZodOptional>; severity_floor: z.ZodOptional>>; max_findings: z.ZodOptional>; tier: z.ZodOptional>>; }, z.core.$strip>; export type CodeReviewInput = z.infer; export interface CodeReviewFinding { severity: Severity; category: Category; file: string; /** 1-based source line. 0 means "could not localize". */ line: number; /** Optional symbol the finding pertains to (function, method, struct name). */ symbol?: string; description: string; recommendation: string; } export interface CodeReviewResult { findings: CodeReviewFinding[]; /** 1-2 sentence overall verdict — drives operator triage at a glance. */ summary: string; /** Byte size of the input diff — surfaces clipping when a diff was truncated upstream. */ diff_size_bytes: number; } /** * Coerce a single model-emitted finding to a CodeReviewFinding. * * Returns null when the entry is too malformed to use (missing required * fields, unknown severity, unknown category). Drops are silent — the * batch-truncation message in the model prompt explains that bad * entries are dropped, so an operator sees "fewer findings than * expected" rather than a tool crash. * * Rules: * - severity + category MUST be from the closed enums (else drop) * - file MUST be a non-empty string (else drop) * - line is coerced to int; non-finite or negative becomes 0 (= "unknown") * - symbol is optional; non-string is dropped * - description + recommendation must each be non-empty strings (else drop) * * Why "drop" instead of "throw": one malformed entry never explodes the * whole review. Same discipline as coerceOnboardingFacts in repoPack. */ declare function coerceFinding(entry: Record): CodeReviewFinding | null; /** * Coerce the model's full output into a CodeReviewResult. * * Mirrors the coerceOnboardingFacts pattern from repoPack: * - null/non-object → empty findings + empty summary * - malformed entries dropped, never thrown * - severity_floor filter applied AFTER drops so the operator sees * "drops + filtered" honestly (not "filtered first, dropping any * pre-filtered count makes the post-filter total wrong") * - max_findings truncation is the LAST step so the cap reflects the * filtered set, not the raw model output * * Findings are returned in the model's emit order. Stable ordering * lets a snapshot test compare runs without sorting. */ declare function coerceReview(data: unknown, opts: { severityFloor: Severity; maxFindings: number; diffSize: number; }): CodeReviewResult; export declare function handleCodeReview(input: CodeReviewInput, ctx: RunContext): Promise>; export declare const __internal: { coerceFinding: typeof coerceFinding; coerceReview: typeof coerceReview; SEVERITY_RANK: Record<"high" | "medium" | "low" | "critical", number>; }; export {}; //# sourceMappingURL=codeReview.d.ts.map