/** * The gates `transitionRequestArtifact` applies on `rd → implemented`, * `rd → qa-handoff` and `rd → handed-off`: the per-file size ratchet and the * declared-type corroboration. Extracted so `request-artifact-service.ts` * (already over its cap) grows by one call instead of two blocks, and so the * checks run for EVERY caller — not only the CLI flag path. * * ONE ENUMERATION PER TRANSITION. At `implemented` the change set is read once * and shared: the type rule judges every path (deletions included, rename * sources included), while the size scan measures the A/M/R/untracked subset. * `qa-handoff` / `handed-off` run only the type rule (two git spawns); the size * ratchet keeps the single state it has always judged. * * THE TYPE RULE IS SCOPED TO THE RID — WITH AN ANTI-LIE FALLBACK. A rid * declares the paths it touched in its own artifact's `## Changed paths` * section, and the rule judges THAT set instead of the whole working tree: the * old judgement blamed a docs rid for another slice's `src/**` change, because * it read the working tree rather than the request. * * SCOPING ALONE WOULD BE AN ESCAPE HATCH ("this rid did not change it" would * pass anything), so the fallback runs beside it: a product-source change in the * working tree that NO rid claimed is still refused. The fallback only runs * when EVERY rid artifact in the session declares its paths — an incomplete * table cannot prove "nobody claimed it", and guessing there would blame one * slice for another's change. When it does not run, the returned note says so: * a silently skipped check is indistinguishable from a passing one. */ import type { RequestType } from './artifact-prerequisites.js'; import { type RequestArtifactState } from './request-artifact-state-helpers.js'; export type RdGatePhase = 'implemented' | 'qa-handoff' | 'handed-off'; /** * True for the three states the RD gates judge. A type PREDICATE, so a caller * that filters on it keeps the narrowed state — the old inline `||` chain did * the same narrowing, and losing it would make the phase un-assignable. */ export declare function isRdGatePhase(state: RequestArtifactState): state is RdGatePhase; /** The three ways the declared-type rule can refuse. */ export type RdGateViolationKind = 'source-touched' | 'source-unclaimed' | 'diff-unavailable'; export type RdGateViolation = { ok: false; kind: RdGateViolationKind; message: string; }; export declare class TypeCorroborationViolationError extends Error { readonly code = "TYPE_CORROBORATION_VIOLATION"; readonly declaredType: RequestType; readonly kind: RdGateViolationKind; constructor(declaredType: RequestType, verdict: RdGateViolation); } /** Written into the artifact when `--allow-incomplete` skips a gate that COULD * have judged this type: a silent bypass is indistinguishable from a pass. */ export declare function rdGatesBypassNote(phase: RdGatePhase): string; export declare function runRdTransitionGates(options: { projectRoot: string; declaredType: RequestType; allowIncomplete: boolean; phase: RdGatePhase; requestId: string; sessionId: string; }): string | null;