/** * ollama_change_pack — THIRD PACK. Change-centered review job. * * Change-first, not repo-first: this pack is about the DELTA, not a * general tour. Corpus/context is pulled in only when the caller opts * in — otherwise the pack works strictly from diff_text + source_paths * (and optionally a CI log_text that caused the review). * * Fixed pipeline: * 1. assemble evidence (diff + paths + corpus if given) * 2. ollama_triage_logs (ONLY when log_text is provided) * 3. ollama_change_brief (via synthesizeChangeBrief — evidence reused) * 4. ollama_extract (narrow) (scripts_touched / config_surfaces / * runtime_hints — fixed review schema) * 5. artifact_write (deterministic markdown + JSON) * * Release-note draft discipline: the draft lives in the brief's * `release_note_draft` field under a prompt that already forbids * promotional copy. The markdown renders it as a blockquote to signal * "DRAFT the operator reviews" — not final copy. * * No VCS integration. Strong job shape without control-plane creep. */ import { z } from "zod"; import type { Envelope } from "../../envelope.js"; import type { RunContext } from "../../runContext.js"; import { type TriageLogsResult } from "../triageLogs.js"; import { type ChangeBriefResult } from "../changeBrief.js"; export declare const changePackSchema: z.ZodObject<{ diff_text: z.ZodOptional; source_paths: z.ZodOptional>>; log_text: z.ZodOptional; corpus: z.ZodOptional; corpus_query: z.ZodOptional; title: z.ZodOptional; artifact_dir: z.ZodOptional; per_file_max_chars: z.ZodOptional; max_breakpoints: z.ZodOptional; max_validation_checks: z.ZodOptional; }, z.core.$strip>; export type ChangePackInput = z.infer; export interface ChangeFacts { scripts_touched?: string[]; config_surfaces?: string[]; runtime_hints?: string[]; } /** * Sanitize untrusted extract output into the ChangeFacts shape. * * extract.handleExtract returns ExtractResult.data as `unknown` — the model * may have produced "string-instead-of-array" / null entries / mixed types. * A bare cast `as ChangeFacts` would compile but throw at render time when * `.map()` hits a non-array. * * Rules: * - Returns a fully-shaped object with safe defaults (empty arrays). * - Drops non-string entries from string arrays. * - Coerces a single string-where-array-was-expected into a 1-element array. * - Never throws on malformed input — only sanitizes. */ export declare function coerceChangeFacts(data: unknown): ChangeFacts; export interface StepEntry { tool: string; ok: boolean; elapsed_ms: number; warnings?: string[]; artifact_written?: boolean; } export interface ChangePackSummary { affected_surfaces_count: number; likely_breakpoints_count: number; validation_checks_count: number; release_note_present: boolean; extracted_facts_present: boolean; triage_ran: boolean; weak: boolean; corpus_used: { name: string; chunks_used: number; } | null; } export interface ChangePackResult { artifact: { /** * Path to the written markdown artifact. `null` when the artifact * write failed — the pack still ran successfully, but the caller * MUST NOT pass this to artifact_read (which would surface a * confusing SOURCE_PATH_NOT_FOUND with no link back to the original * write error). When `null`, see `artifact.error` for the operator- * facing reason, and `summary` for the data that would have been * persisted. */ markdown_path: string | null; /** Path to the written JSON artifact. `null` on write failure — same contract as `markdown_path`. */ json_path: string | null; /** * Populated only when the write failed. Names the path the pack * attempted to write to and the underlying filesystem error, so the * caller can surface a single coherent error instead of a * write-failure → later-read-failure chain. */ error?: { attempted_markdown_path: string; attempted_json_path: string; reason: string; }; }; summary: ChangePackSummary; steps: StepEntry[]; } declare function buildSlug(opts: { title?: string; summaryHead?: string; when: Date; }): string; declare function renderMarkdown(args: { title: string; generatedAt: string; hardwareProfile: string; triage: TriageLogsResult | null; brief: ChangeBriefResult; facts: ChangeFacts | null; steps: StepEntry[]; }): string; export declare function handleChangePack(input: ChangePackInput, ctx: RunContext): Promise>; export interface ChangePackArtifact { schema_version: 1; pack: "change_pack"; generated_at: string; hardware_profile: string; title: string; slug: string; input: { has_diff_text: boolean; has_log_text: boolean; source_paths: string[]; corpus: string | null; corpus_query: string | null; }; triage: TriageLogsResult | null; brief: ChangeBriefResult; extracted_facts: ChangeFacts | null; steps: StepEntry[]; artifact: { markdown_path: string; json_path: string; }; } export declare const __internal: { buildSlug: typeof buildSlug; renderMarkdown: typeof renderMarkdown; CHANGE_EXTRACT_SCHEMA: { readonly type: "object"; readonly properties: { readonly scripts_touched: { readonly type: "array"; readonly items: { readonly type: "string"; }; readonly description: "Names of scripts or commands altered by this change (npm scripts, Makefile targets, task runners)."; }; readonly config_surfaces: { readonly type: "array"; readonly items: { readonly type: "string"; }; readonly description: "Configuration files or settings changed by this delta."; }; readonly runtime_hints: { readonly type: "array"; readonly items: { readonly type: "string"; }; readonly description: "Runtime or version requirements stated or altered (Node version, Python version, compiler target)."; }; }; }; }; export {}; //# sourceMappingURL=changePack.d.ts.map