/** * Terminal dispositions for decision drafts (change: explain-decision-rejection). * * `record_decision` writes a draft and a background consolidator decides its * fate. Before this module a draft that was not promoted simply stopped * existing: no verdict, no reason, nothing the author could read. Guessing * whether the call failed, the wording was wrong, or the evidence was missing is * not a reasonable thing to ask of a caller. * * Every input draft now reaches one of four states, each with a stable reason * code from the registry below: * pending — consolidation has not run yet (an honest "not decided", * never a rejection by omission) * promoted — it survived, as recorded or with re-derived wording * merged-into — it was absorbed, and the surviving decision is named * rejected — it did not survive, and the reason says why * * The mapping is DERIVED, deterministic, and computed with no LLM: it reads the * consolidation output against the input drafts. Where attribution is genuinely * ambiguous — a draft absent from a multi-decision consolidated set with no * unique overlap — it reports `rejected / not-in-consolidated-set` rather than * inventing a merge target. An honest "it did not survive" beats a fabricated * lineage. */ import type { AuthorStatement, DecisionDisposition, DecisionDispositionReason, DecisionStore, PendingDecision } from '../../types/index.js'; /** * Source-declared reason registry. A code that is not here cannot be emitted; * the description is what a human reads, and `nextAction` is what they do about * it. Same discipline as the governance FINDING_CODE_REGISTRY. */ export declare const DECISION_DISPOSITION_REASONS: Record; /** One draft's verdict. */ export interface DraftDisposition { id: string; disposition: DecisionDisposition; reason: DecisionDispositionReason; /** Set exactly when `disposition` is `merged-into`. */ mergedIntoId?: string; /** Internal lineage used to prove that a verification replacement was persisted. */ replacementId?: string; } /** True when consolidation re-derived the wording rather than keeping the author's. */ export declare function contentWasRewritten(draft: PendingDecision, consolidated: PendingDecision): boolean; /** The author's words, kept verbatim for a decision whose content was re-derived. */ export declare function authorStatementOf(draft: PendingDecision): AuthorStatement; /** * Derive one verdict per input draft. Total by construction: the returned array * has exactly one entry per draft, in input order. * * Attribution rules, in order: * 1. The draft's id appears in the consolidated set → promoted (rewrite noted). * 2. The draft was explicitly superseded → rejected/superseded. * 3. Exactly one consolidated decision exists, or exactly one shares a file * with the draft → merged-into that id. * 4. Otherwise → rejected/not-in-set. */ export declare function computeDraftDispositions(input: { drafts: readonly PendingDecision[]; consolidated: readonly PendingDecision[]; supersededIds?: readonly string[]; }): DraftDisposition[]; /** * Fold the verification outcome into the verdicts: a decision the verifier could * not tie to a change in the diff (phantom) is rejected with `no-supporting-diff`, * even if consolidation had promoted it. Verification is the later, stronger * signal — and "no evidence in the diff" is precisely the reason an author most * needs to be told. */ export declare function withVerificationOutcome(dispositions: readonly DraftDisposition[], phantomIds: ReadonlySet): DraftDisposition[]; /** * Atomically apply every state transition produced by one consolidation run. * `originalDraftIds` is captured before the LLM call, so drafts recorded while * consolidation is in flight remain untouched in the fresh CAS snapshot. * * Rejected originals stay in the store as an audit trail; verified/phantom * survivors replace source drafts with the same deterministic id. Dispositions * are applied last so both survivors and absorbed originals carry their verdict. */ export declare function applyConsolidationOutcome(store: DecisionStore, result: { originalDraftIds: ReadonlySet; originalDrafts?: readonly PendingDecision[]; capturedDecisions?: readonly PendingDecision[]; verified: readonly PendingDecision[]; phantom: readonly PendingDecision[]; unassessed?: readonly PendingDecision[]; supersededIds: readonly string[]; dispositions: readonly DraftDisposition[]; }): DecisionStore; /** * Write the verdicts onto the store. Pure — the caller persists through the CAS * path. A decision that already carries a terminal disposition is not re-stamped; * a `pending` one is. */ export declare function applyDispositions(store: DecisionStore, dispositions: readonly DraftDisposition[], at?: string): DecisionStore; /** * The disposition of a stored record, filling in the honest defaults: a draft * with no disposition is awaiting consolidation; any other status with no * disposition predates this field and reads `legacy-unknown` — an unknown * outcome, explicitly not a rejection. */ export declare function readDisposition(d: PendingDecision): { disposition: DecisionDisposition; reason: DecisionDispositionReason; mergedIntoId?: string; }; /** One human-readable line: the verdict, why, and what to do next. */ export declare function describeDisposition(d: PendingDecision): string; //# sourceMappingURL=disposition.d.ts.map