import type { FrictionItem } from "../io/frictionCapture.js"; import type { FrictionCaptureArtifact } from "../io/frictionCapture.js"; import type { FrictionCategory } from "./frictionRecord.js"; /** * CE-005 — the single shared workflow step-boundary chokepoint. * * Every mechanically observed friction fact flows through `captureStepBoundaryFriction` * (single-sourced here, consumed by BOTH orchestrators) so the fact list is * structural/extensible, not a snapshot a sixth fact can silently bypass. The * workflow already computes each of these facts at its own step boundary — phase * re-emit counts, artifact rejection, repair rounds, post-repair re-derive, * no-change merge, and the intent-gate lock-across-judge fallback. Routing them * all through one chokepoint with ZERO host discretion (INV-O1-1 / * OBL-m-friction-inv-1) means a new workflow fact is added by routing * it through this same emitter, never by extending a closed enum elsewhere. * * CE-006 — the event id is a STRUCTURED, collision-free key. Its components * {event_type, runId, discriminator} are individually percent-encoded and joined * with a delimiter (`:`) that CANNOT appear in any encoded component, so a * `:`-bearing reused discriminator (e.g. an M-IDEMPOTENCY split key) can never * make the de-dup key ambiguous: two distinct facts never flatten to one key, and * one fact never expands to two (OBL-m-friction-inv-6 / fail-2). The encoding is * deterministic, so re-recording the same fact is a guaranteed no-op (INV-O1-6). * * The capture itself rides `captureFrictionEvent` — best-effort, non-fatal, * de-duped, OS/path-agnostic (INV-O1-5 / fail-5). A contended or failed capture * never throws into the in-flight obligation. */ /** * The mechanically observed step-boundary fact kinds. OPEN/EXTENSIBLE — this union is * the documented catalogue, but the chokepoint accepts any string `event_type` * so a new workflow fact routes through the SAME emitter without forking a closed * enum (CE-005). The named members below are the facts the contract pins: * * - `phase_reemit` — a phase re-emitting the SAME gate errors / leftovers. * - `artifact_rejected` — an artifact rejected / archived (referential-integrity * reject, deemed_inappropriate, archive-consumed-inputs). * - `repair_round` — one bounded contract-repair stage firing. * - `post_repair_rederive` — a staleness re-derive after a repair / redispatch. * - `no_change_merge` — a resolved_no_change node merged with no diff. * - `intent_gate_fallback` — intent_checkpoint gate lock-across-judge fallback. * - `coverage_total_lines_mismatch` — an AuditResult whose * `file_coverage[].total_lines` disagrees with the * file's actual line count (discriminator: the result * index + the mismatching path). * - `node_quarantine` — an implement node that committed edits but hard-failed * the tool's verify/scope/merge; work preserved under a * quarantine ref, NOT landed (discriminator: the node id). */ export type StepBoundaryEventType = "phase_reemit" | "artifact_rejected" | "repair_round" | "post_repair_rederive" | "no_change_merge" | "intent_gate_fallback" | "coverage_total_lines_mismatch" | "node_quarantine" | (string & {}); /** * The REAL close-out friction category for a step-boundary fact kind. Total: an * unknown event type degrades to `inefficient_feeding` so the mapping is never * undefined and a captured event is ALWAYS tagged with a real category. */ export declare function stepBoundaryFrictionCategory(eventType: StepBoundaryEventType): FrictionCategory; /** * Build the STRUCTURED, collision-free de-dup id for a step-boundary fact. * Components are individually percent-encoded then joined with `:` — a delimiter * that cannot survive the encoding inside any component, so the mapping * {event_type, runId, discriminator} → id is injective (CE-006). */ export declare function stepBoundaryEventId(eventType: StepBoundaryEventType, runId: string, discriminator: string): string; /** The structured fact a caller routes through the chokepoint. */ export interface StepBoundaryFriction { /** Mechanically observed fact kind (one of the named members, or a new string). */ eventType: StepBoundaryEventType; /** * A stable discriminator distinguishing this fact instance within the run * (e.g. the phase id + attempt, the artifact id, the node id). May contain any * characters — it is percent-encoded before flattening, so `:` is safe. */ discriminator: string; /** Human-readable summary for the triage prompt. */ note: string; severity?: FrictionItem["severity"]; category?: FrictionItem["category"]; area?: string; /** * Optional artifact/subject key this fact concerns (e.g. the node id, the * contract id). The aggregation axis for the derived per-category observation: * N facts on the SAME artifact collapse to one `inefficient_feeding` line. * Falls back to `area`, then the discriminator, when unset. */ artifact?: string; } /** * Route one mechanically observed step-boundary fact through the single chokepoint. * * Best-effort and non-fatal: delegates to `captureFrictionEvent`, which swallows * every failure so the in-flight obligation is never broken (INV-O1-5). De-duped * on the structured collision-free id, so re-entrant boundary passes (re-dispatch, * retry, re-derive) never double-count the same fact (INV-O1-6). */ export declare function captureStepBoundaryFriction(artifactsDir: string, runId: string, fact: StepBoundaryFriction, tool: FrictionCaptureArtifact["tool"]): Promise; //# sourceMappingURL=stepBoundaryCapture.d.ts.map