@vostride/agent-qa-agent 0.0.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +105 -0
- package/NOTICE.md +11 -0
- package/dist/index.cjs +11107 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5134 -0
- package/dist/index.d.ts +5134 -0
- package/dist/index.js +11123 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/functions/declaration-projection.ts","../src/functions/ops/agent-ask.ts","../src/functions/spec.ts","../src/functions/ops/analysis-get.ts","../src/analysis/cluster.ts","../src/functions/ops/evidence-presence.ts","../src/analysis/quote-text.ts","../src/analysis/render-sentence.ts","../src/jobs/kinds.ts","../src/jobs/analyze-run-author.ts","../src/prompt/tiered-prompt-builder.ts","../src/jobs/evidence-diet.ts","../src/jobs/chain-identity.ts","../src/jobs/kind-registry.ts","../src/functions/ops/runs-get.ts","../src/functions/ops/authoring-draft-edit.ts","../src/authoring/entity-binding.ts","../src/authoring/loop.ts","../src/authoring/brief-blocks.ts","../src/authoring/dedup.ts","../src/authoring/adds-value.ts","../src/authoring/refine.ts","../src/authoring/stated-values.ts","../src/authoring/repair.ts","../src/authoring/router.ts","../src/functions/ops/authoring-draft-write.ts","../src/functions/ops/authoring-funnel-get.ts","../src/authoring/funnel.ts","../src/functions/ops/authoring-verify-draft.ts","../src/authoring/verify-draft.ts","../src/authoring/assertion-strength.ts","../src/authoring/stability-gates.ts","../src/functions/ops/config-auth-set.ts","../src/functions/ops/config-propose-verdict.ts","../src/config-mutation/construct.ts","../src/config-mutation/cross-boundary.ts","../src/config-mutation/hostname-gate.ts","../src/functions/ops/config-field-set.ts","../src/functions/ops/config-hook-add.ts","../src/functions/ops/config-get.ts","../src/functions/ops/config-target-create.ts","../src/functions/ops/config-project-scaffold.ts","../src/functions/ops/config-target-edit.ts","../src/functions/ops/entities-get.ts","../src/functions/entity-cards/card-context.ts","../src/functions/entity-cards/produce-card.ts","../src/functions/ops/entities-ids.ts","../src/functions/ops/knowledge-brief-why.ts","../src/functions/ops/knowledge-record-show.ts","../src/functions/ops/knowledge-review-ids.ts","../src/functions/ops/runs-start.ts","../src/functions/entity-cards/actions.ts","../src/functions/entity-cards/key-facts.ts","../src/functions/ops/explain.ts","../src/explain/renderer.ts","../src/explain/scorer.ts","../src/functions/ops/entities-resolve.ts","../src/functions/ops/knowledge-accept-propose.ts","../src/functions/ops/knowledge-change-verdict.ts","../src/functions/ops/knowledge-bundles-list.ts","../src/functions/ops/knowledge-gates-list.ts","../src/functions/ops/knowledge-forget-propose.ts","../src/functions/ops/knowledge-records-diff.ts","../src/functions/ops/knowledge-records-inspect.ts","../src/functions/ops/knowledge-reject-propose.ts","../src/functions/ops/quarantine-add.ts","../src/functions/ops/quarantine-list.ts","../src/functions/ops/quarantine-release.ts","../src/functions/ops/runs-events.ts","../src/functions/ops/runs-live-url.ts","../src/functions/live-url.ts","../src/functions/ops/editor-live-url.ts","../src/functions/ops/runs-digest.ts","../src/analysis/render-cluster-block.ts","../src/functions/ops/runs-post-processing.ts","../src/functions/ops/runs-artifact.ts","../src/functions/ops/runs-detail.ts","../src/functions/ops/runs-evidence.ts","../src/functions/ops/runs-knowledge.ts","../src/functions/ops/secret-mask.ts","../src/functions/ops/runs-list.ts","../src/functions/ops/runs-mark.ts","../src/functions/ops/runs-mark-preview.ts","../src/functions/ops/runs-marks-history.ts","../src/functions/ops/runs-overview.ts","../src/functions/registry.ts","../src/functions/classify.ts","../src/functions/invoke.ts","../src/config-mutation/write-test-route.ts","../src/chat/config-drift.ts","../src/chat/compaction.ts","../src/chat/resolver-table.ts","../src/chat/retired-chat-verbs.ts","../src/chat/session-repair.ts","../src/chat/session-stamps.ts","../src/chat/turn-engine.ts","../src/chat/tool-names.ts","../src/chat/reconcile.ts","../src/chat/clause-split.ts","../src/chat/chat-state.ts","../src/chat/banner.ts","../src/chat/scenario-loader.ts","../src/chat/ceiling.ts","../src/chat/scenarios/manifest.ts","../src/chat/planner-stage.ts","../src/chat/chat-prompt.ts","../src/chat/planner-tools.ts","../src/ports/gates.ts","../src/ports/job-store.ts","../src/jobs/engine.ts","../src/jobs/record-llm-authorship.ts"],"sourcesContent":["// The declaration's contract projection (Phase 384, Plan 09 — BL-01 / D-14 / T-384-14).\n//\n// One pure function: take a live zod schema, hand back an inert JSON-Schema document that\n// nothing can run and nothing can rewrite. `declarationView` calls it so a listing carries\n// a DESCRIPTION of the contract rather than a handle on the validator that enforces it.\n//\n// 2026-09-28 (431-03, D-03 · research A1): the 396 same-object recipe — the schema a surface\n// advertises IS the schema `invokeFunction` validates — now reads as one enforcing schema plus its\n// canonical companion. A branded run id or a preserved `__proto__` variable makes zod's output-mode\n// conversion throw, which is why both sides were projected in input mode below. An op whose output\n// carries such a transform may declare an `OutputContract` whose `runtimeSchema` is its `output`\n// object; the registry checks that identity, and the output side is then read from the companion's\n// explicit output document. Validation is unchanged: the companion's own validate delegates to the\n// same object.\n//\n// Depends on zod and the schema package's contract types alone. It reaches for no port, no host builtin and no sibling module other\n// than the contract types, which is why the surface firewall has nothing to say about it.\n\nimport type { OutputContract } from '@vostride/agent-qa-schema'\nimport { z } from 'zod'\n\nimport type { FunctionSchemaProjection } from './spec.js'\n\n/**\n * Freeze a value and everything reachable through its own enumerable properties.\n *\n * Shallow freezing is not enough and the difference is the whole defect: sealing the top\n * object leaves every nested schema node writable, so the escape simply moves one level\n * down. The `seen` set keeps the walk terminating on a self-referential document — zod\n * emits `$ref` strings rather than object cycles today, but a guard that depends on that\n * staying true would be one library release away being wrong.\n */\nfunction deepFreeze<Value>(value: Value, seen: WeakSet<object>): Value {\n if (typeof value !== 'object' || value === null) return value\n\n const node = value as unknown as object\n if (seen.has(node)) return value\n seen.add(node)\n\n for (const nested of Object.values(node as Record<string, unknown>)) {\n deepFreeze(nested, seen)\n }\n return Object.freeze(value)\n}\n\n/**\n * Project one declared contract into the inert form a listing publishes.\n *\n * `io: 'input'` is used for BOTH sides on purpose. Several contracts here are built over\n * branded ids whose zod definition carries a transform, and zod refuses to represent a\n * transform in its default output mode — measured over all twelve schemas this phase\n * registers (six inputs, six outputs): `input` mode succeeds for every one of them, while\n * `output` mode throws for six. Since `declarationView` runs for every registered spec on\n * every `list()` call, a mode that throws for any single schema would break listing for\n * every caller, so the mode that succeeds universally is the only correct choice. The\n * resulting document is the wire shape a caller would send or receive, which is also the\n * shape an MCP tool listing wants.\n */\nexport function toSchemaProjection(schema: z.ZodType): FunctionSchemaProjection {\n const projected = z.toJSONSchema(schema, { io: 'input' }) as Record<string, unknown>\n return deepFreeze(projected, new WeakSet())\n}\n\n/**\n * Project a declared output: the companion's output document when the spec has one, otherwise\n * the input-mode projection above.\n */\nexport function toOutputProjection(\n output: z.ZodType,\n outputRepresentation: OutputContract | undefined,\n): FunctionSchemaProjection {\n if (outputRepresentation === undefined) return toSchemaProjection(output)\n const projected = outputRepresentation['~standard'].jsonSchema.output({ target: 'draft-2020-12' })\n return deepFreeze(projected, new WeakSet())\n}\n","// `agent.ask` — the chat turn entry, as a registered capability (Phase 392, D-24).\n//\n// THIS FILE IS THE L10 ANSWER. §3's \"no private powers\" law says a surface may not hold a\n// capability the function layer does not, and a chat REPL that owned its turn engine directly would\n// be the largest such power in the system — an orchestrator that can reach every op, reachable\n// itself through nothing the catalogue declares. Registering the turn entry inverts that: the REPL\n// and the `ask` verb are CLIENTS of `agent.ask` exactly as they are clients of `runs.list`, 396's\n// MCP projection picks it up from the registry with no chat-specific code, and 397's parity suite\n// asserts chat ≡ registry without a carve-out.\n//\n// OP CALLS OP, WHICH IS ORDINARY COMPOSITION. A turn invokes other capabilities, and each of those\n// invocations crosses `invokeFunction` on its own with the caller the composition minted for its\n// stage — so a clause the turn runs passes the same pipeline as the turn itself: input validation,\n// the binding check and output validation, each clause with its own receipt.\n//\n// NO SCOPE AND NO ORIGIN RULE (2026-10-01, 432-26, D-10/D-12). This op once declared\n// `requiredScopes: ['read']` as the right to START a turn, with the per-clause scope checks and\n// `requiresHumanOrigin` deciding each clause's reach. All three are deleted: every door can call\n// every operation, so a turn and the clauses it plans are served to any caller alike.\n//\n// `agent.chat` IS DELIBERATELY NOT HERE. The session-stateful sibling waits for a consumer\n// (RESEARCH Open Q3): shipping it now would mint a second entry with no client, and 397's parity\n// suite would then require a stub of it on every surface.\n\nimport { AgentAskInputSchema, AgentAskResultSchema } from '@vostride/agent-qa-schema'\nimport type { AgentAskInput, AgentAskResult } from '@vostride/agent-qa-schema'\n\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionDeps, FunctionSpec } from '../spec.js'\n\n/**\n * Lowercase dot taxonomy (384 D-15): the `agent.` domain's first verb.\n *\n * The literal appears exactly once, here. Every surface that names it — the `ask` command today,\n * the REPL and the MCP projection later — imports this constant, so the parity suite and the\n * catalogue read the same string as the dispatcher.\n */\nexport const AGENT_ASK_FUNCTION_ID = 'agent.ask'\n\nexport const agentAskSpec: FunctionSpec<AgentAskInput, AgentAskResult> = {\n id: AGENT_ASK_FUNCTION_ID,\n // THE SUMMARY SAYS \"ENTRY POINT\", and that wording is a fix rather than a flourish (392-09, from\n // the first live gate run). D-07 projects every registry op 1:1 into the planner's tool set, so\n // this op is a tool the planner is offered WHILE IT IS INSIDE ONE OF ITS OWN TURNS. Described as\n // \"run one conversational turn\", it read to the model as the natural home for any conversational\n // request: a plain request to list runs was planned as `agent.ask` twice out of two live runs,\n // and the recursive turn then failed — so a person asking for a capability in prose got a failed\n // turn instead of the capability. The repair is DESCRIPTION, not exclusion. Hiding a tool would\n // break the always-send-all law and D-07's registry projection, and it would be the wrong\n // diagnosis anyway: the tool was not misclassified, it was misdescribed. Every consumer of this\n // string — the catalogue, `fn --list`, 396's MCP listing, the planner — is better served by the\n // sentence that says what the op is FOR.\n summary: 'The chat entry point: begin ONE new conversational turn from outside a conversation. '\n + 'Surfaces (a REPL, the ask verb, an MCP client) call this to START a turn — it is not a way '\n + 'to carry out a request while a turn is already running. It routes the utterance, executes '\n + 'what it resolves to, and answers with per-clause receipts.',\n resultKind: 'unary',\n // Bound where a composition assembles a turn engine. A host with no engine lists this\n // `unbound` BY NAME rather than answering an empty turn — which would tell a person their\n // request was understood and produced nothing, the one wrong answer that stops them asking.\n boundThrough: 'chatTurn',\n input: AgentAskInputSchema,\n output: AgentAskResultSchema,\n // `readOnly: false`, and the honesty matters more here than on any other op in the catalogue: a\n // turn is a variable-reach capability, so describing it as a read would let a risk ladder treat\n // the door to every write verb as the cheapest thing in the registry. (2026-10-01, 432-26: the\n // descriptor is a classification; no gate reads it to ask or deny.)\n risk: { name: `fn:${AGENT_ASK_FUNCTION_ID}`, recognized: true, readOnly: false },\n /**\n * A TURN's own report of how it went (2026-08-20, Phase 399.1 D-01/D-02/D-12).\n *\n * A TURN IS A COMPOSITION, SO ITS VERDICT IS A FOLD OF ITS CLAUSES' VERDICTS. This used to fold\n * the turn STATUS alone, on the argument that the per-clause verdicts were already receipts and\n * reading them here would be a second opinion. That argument is the recorded belief that produced\n * gap 1: a turn whose only clause was REFUSED by a credential guardrail reported `executed` one\n * composition layer up, and the person reading the outer line was told a blocked mutation had been\n * carried out. The receipts are not a second opinion about the turn — they ARE the turn, and the\n * status is a summary of them. Success is the one claim a fold may never default to (D-03's\n * asymmetry): where the clauses do not support it, the outer word must say what they do support.\n *\n * `fail_closed` IS `failed` AND NOT `refused`. D-02 minted `refused` for a GUARDRAIL declining an\n * op; a fail-closed turn is the ENGINE abandoning the clauses after one of them broke, which is\n * an operation that did not complete. Reporting it `refused` would tell a person a control\n * declined their request when what happened is that something went wrong.\n *\n * AND THERE IS DELIBERATELY NO `failed` SCAN OVER THE RECEIPTS HERE (D-12). Post-399.1-09 the\n * engine derives its aggregate from the same vocabulary, so it can no longer answer `completed`\n * over a `failed` receipt; a second mechanism second-guessing the first is the redundant-mechanism\n * failure mode this project has already paid for, and it would hide a regression in the engine\n * rather than surface it.\n */\n classify(output): ClauseVerdict {\n switch (output.status) {\n case 'completed': {\n // THE REFUSAL FACT TRAVELS ON `receipts[]` (D-12 point 3): the turn-status vocabulary stays\n // three members, and this is where a refused clause becomes the outer clause's own word.\n const refused = output.receipts.filter((receipt) => receipt.status === 'refused').length\n if (refused > 0) {\n return {\n status: 'refused',\n outcome:\n `turn completed — ${refused} of ${output.receipts.length} clause(s) refused`,\n }\n }\n return {\n status: 'executed',\n outcome: `turn completed — ${output.results.length} clause result(s)`,\n }\n }\n case 'fail_closed':\n return { status: 'failed', outcome: 'fail_closed: the turn carried nothing out' }\n case 'failed':\n return { status: 'failed', outcome: 'the turn failed' }\n default:\n return output.status satisfies never\n }\n },\n async invoke(input, deps: FunctionDeps) {\n const turn = deps.chatTurn\n // An explicit presence check rather than a try/catch, on the `runs-digest.ts` reasoning:\n // swallowing would also swallow a real failure inside a bound engine.\n if (turn === undefined) {\n throw new FunctionNotBoundError(AGENT_ASK_FUNCTION_ID)\n }\n return turn.runTurn(input)\n },\n}\n","// The function-layer contract types (Phase 384, FUNC-01 / D-08 / D-09 / D-14 / D-15).\n//\n// `FunctionDeclaration` is the public, capability-free VIEW of an op: everything a\n// surface needs to discover, describe, and project the capability (MCP tool listings,\n// the 397 golden snapshot, the `agent-qa fn --list` catalog) and nothing that runs it.\n// `FunctionSpec` adds the LIVE input/output validators and the implementation, and NEVER\n// leaves this directory — the package barrel exports the declaration type only, so no\n// surface can acquire a dispatch path that skips `invokeFunction`'s gate call (T-384-01),\n// nor a handle on the schema objects that dispatch enforces with (T-384-14).\n\nimport type { EventLogPort } from '@vostride/agent-qa-runner'\nimport type { z } from 'zod'\n\nimport type {\n AgentAskInput,\n AgentAskResult,\n OutputContract,\n ClauseReceiptStatus,\n CompletedRunHandoff,\n CommitReceipt,\n CurationSnapshot,\n EntityDescriptor,\n EntityResolution,\n ForgetReceiptV1,\n FeedbackPort,\n FeedbackReadsPort,\n InspectRecordView,\n JobStatus,\n KnowledgeAcceptInput,\n KnowledgeBundleSummary,\n KnowledgeCandidateInjectionResult,\n KnowledgeChangeOutput,\n KnowledgeGatesListResult,\n KnowledgeForgetInput,\n KnowledgeMarkInput,\n KnowledgeRecordShowInput,\n KnowledgeRecordShowResult,\n KnowledgeTargetRef,\n LiveStreamDeclaration,\n LiveUrlSigner,\n KnowledgeRecordsDiffInput,\n KnowledgeRecordsInspectInput,\n KnowledgeRejectInput,\n EvidenceBlobLookup,\n EvidenceBlobPresence,\n MaskFn,\n MaskedResolvedConfig,\n PostProcessingStageDetail,\n QuarantineOperationsPort,\n RecordChange,\n RecordedTargets,\n RiskActionDescriptor,\n RunAnalysisArtifact,\n RunDetailRows,\n RunId,\n RunNotification,\n RunsStartInput,\n StepEvidence,\n} from '@vostride/agent-qa-schema'\n\nimport type { AuthoringFunnelPortLike } from '../authoring/funnel.js'\nimport type {\n ConfigFilesPortLike,\n ConfigScaffoldContentPortLike,\n ConfigValidatePortLike,\n ConfigWritePortLike,\n} from '../config-mutation/ports.js'\nimport type { CapabilityCatalogPort } from '../explain/port.js'\nimport type { EvaluateDraftPorts } from '../authoring/verify-draft.js'\nimport type {\n AuthoringReadPortLike,\n AuthoringScopePortLike,\n DraftShelfPortLike,\n ParsedDraftLike,\n} from '../authoring/ports.js'\nimport type { RecurrenceProvider } from '../analysis/render-sentence.js'\nimport type { ChainJobIds } from '../jobs/chain-identity.js'\nimport type { JobIdSource } from '../jobs/engine.js'\n\n/**\n * How an op returns its result (D-08).\n *\n * `unary` resolves ONE value, validated against the spec's `output` contract.\n * `stream` resolves a {@link FunctionStream} whose elements each honour that same\n * `output` contract — the contract describes one element, never the iterable.\n */\nexport type FunctionResultKind = 'unary' | 'stream'\n\n/**\n * A stream op's result (D-08): a typed async iterable of seq-stamped elements.\n *\n * Connection-independent by construction — every element carries its own resume token, so\n * a caller that observed token N re-invokes with that token and receives N + 1 onward.\n * Nothing about the iterable is bound to the transport that produced it, which is why\n * 386's live attach and this phase's completed-run replay are the SAME contract.\n */\nexport type FunctionStream<Element = unknown> = AsyncIterable<Element>\n\n/**\n * One replayed run event, defined AS the element type the runner's `EventLogPort.read`\n * yields. Binding it to the runner contract rather than restating the envelope means the\n * layer cannot drift out of step with the log the runner actually writes.\n */\nexport type ReplayedRunEvent = ReturnType<EventLogPort['read']>[number]\n\n/**\n * Whether the op's implementation is bound in THIS composition (D-09). A declared-but-\n * unbound op is a visible state, never a silent gap: coverage checks must treat\n * `unbound` as covered-but-unbound rather than as an absent capability.\n *\n * It is a property of a COMPOSITION, not of a spec, and since 385 (D-16) it is computed\n * that way: the field lives on {@link FunctionDeclaration} — which a registry mints from\n * the deps it was handed — and on no spec. A spec that carried a static `'bound'` would be\n * making a claim about compositions it is not part of, and the first composition that\n * omitted the implementation would report `bound` and lie. There is no literal to flip.\n */\nexport type FunctionBindingStatus = 'bound' | 'unbound'\n\n/**\n * The OPTIONAL members of {@link FunctionDeps} — the deps whose presence varies by host.\n *\n * A spec naming one of these in {@link FunctionSpec.boundThrough} is bound exactly in the\n * compositions that supplied it. This union is the whole vocabulary: a capability cannot\n * become conditionally bound on something the deps record does not declare, so \"which\n * compositions can run this op\" is answerable by reading two lines.\n */\nexport type OptionalFunctionDepKey =\n | 'liveView'\n | 'runInvocation'\n | 'knowledgeReview'\n | 'postProcessing'\n | 'runDetail'\n | 'evidenceBlobs'\n | 'analysis'\n | 'recurrence'\n | 'quarantine'\n | 'chatTurn'\n | 'draftEvaluation'\n | 'authoringRead'\n | 'authoringScope'\n | 'draftShelf'\n | 'authoringFunnel'\n | 'configFiles'\n | 'configValidate'\n | 'scaffoldContent'\n | 'capabilityCatalog'\n | 'feedback' // 2026-09-08, 419 GATE3-01: the Gate-3 mark port\n | 'feedbackReads' // 2026-09-15, 423 D-19/D-16: read-only mark history and preview, no writer authority\n | 'configWrite' // 2026-09-30, 432-07 D-05/D-07: the direct config writer, no proposal and no git\n | 'secretMask' // 2026-10-14, 441-16 D-06: the declared-secret mask the run reads project through\n\n/**\n * 419 GATE3-01: the union previously had only a type-level pin, invisible to vitest.\n * Like DELTA_ORIGINS and MARKS, this runtime projection makes removal measurable.\n */\nexport const OPTIONAL_FUNCTION_DEP_KEYS = [\n 'liveView',\n 'runInvocation',\n 'knowledgeReview',\n 'postProcessing',\n 'runDetail',\n 'evidenceBlobs',\n 'analysis',\n 'recurrence',\n 'quarantine',\n 'chatTurn',\n 'draftEvaluation',\n 'authoringRead',\n 'authoringScope',\n 'draftShelf',\n 'authoringFunnel',\n 'configFiles',\n 'configValidate',\n 'scaffoldContent',\n 'capabilityCatalog',\n 'feedback',\n 'feedbackReads',\n 'configWrite',\n 'secretMask',\n] as const satisfies readonly OptionalFunctionDepKey[]\n\ntype ExactlyEqual<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false\ntype _Cover = ExactlyEqual<(typeof OPTIONAL_FUNCTION_DEP_KEYS)[number], OptionalFunctionDepKey>\nconst _optionalFunctionDepKeysCover: _Cover = true\nvoid _optionalFunctionDepKeysCover\n\n/**\n * The capability is declared, but no implementation is bound in THIS composition (D-09).\n *\n * Deliberately distinct from `UnknownFunctionError`: the contract exists, is listed, and\n * projects into a catalog — what is absent is the binding. A caller (or a coverage check)\n * that could not tell those two apart would read a staged capability as a hole in the API,\n * which is the silent gap `bindingStatus` exists to prevent.\n *\n * Declared here beside {@link FunctionBindingStatus} rather than beside the pipeline's\n * other refusals so an unbound op can throw it without an op → invoke → registry → op\n * import cycle; `invoke.ts` re-exports it, so the layer's refusal vocabulary still reads\n * as one set at the call site.\n */\nexport class FunctionNotBoundError extends Error {\n constructor(readonly functionId: string) {\n super(`${functionId} is declared but not bound in this composition`)\n this.name = 'FunctionNotBoundError'\n }\n}\n\n/**\n * The scalar metadata every capability carries, shared by the public view and the\n * internal spec.\n *\n * `id` is dot-namespaced `domain.verb` (D-15) over ONE canonical domain taxonomy.\n *\n * 2026-08-16 (397 D-18): this docstring used to repeat D-15's original eight domains\n * (tests · runs · memory · analysis · eval · gates · config · agent), and six later phases\n * shipped ids in domains that list does not contain — so the sentence had been false for a\n * month by the time anyone checked it. The taxonomy is now DATA rather than prose, pinned in\n * the conformance suite's `domain-list.ts` with a one-line charter apiece and censused\n * against this registry in both directions. An id in an unpinned domain is a named RED\n * there; widening the taxonomy is a reviewed one-line diff to that table. Ids are never\n * renamed to suit it — they are the shipped, locked contract, and the taxonomy serves them.\n *\n * The two CONTRACT fields are deliberately NOT here. They are the one place the view and\n * the spec must differ in kind — a projection on one, a live validator on the other — and\n * splitting them out is what makes that difference a property of the type system rather\n * than a rule someone has to remember at the seam (BL-01 / T-384-08).\n */\nexport interface FunctionMetadata {\n id: string\n /** One-line human description; rendered by catalogs and `agent-qa fn --list`. */\n summary: string\n // 2026-10-02 (432-39, D-10/D-12): no `requiredScopes` and no `requiresHumanOrigin`. Both were\n // retired and unread since 432-20 and every op spec stopped spelling them by 432-27; the members\n // are deleted with the capability-scope union, so no metadata, spec or declaration can carry either.\n resultKind: FunctionResultKind\n /** The risk descriptor of this op: listings, MCP tool annotations and the read scope read it (no gate since 432-13). */\n risk: RiskActionDescriptor\n}\n\n/**\n * An INERT description of one declared contract: a JSON-Schema document, deep-frozen.\n *\n * A projection has no `parse` and no `safeParse` — there is nothing on it to run and\n * nothing on it to replace. That is the whole point. The surface-visible view used to\n * carry the live `z.ZodType`, and because ops assign the schema package's own exported\n * validators, a single write reached through a permitted `registry.list()` replaced the\n * contract vocabulary every firewalled surface imports, for the whole process. Publishing\n * a projection removes the object that write needed rather than adding a rule about it.\n *\n * D-14 already named the input contract \"also the JSON-Schema projection source\"; on the\n * declaration that description is now literal, and it is the shape 396's MCP tool listing\n * consumes.\n */\nexport type FunctionSchemaProjection = Readonly<Record<string, unknown>>\n\n/**\n * What one clause's result MEANT, as the op that produced it reports (Phase 399.1, D-01/D-02/D-03).\n *\n * TWO FIELDS AND NO THIRD. `status` is the one bit a surface must not get wrong — whether the thing\n * was carried out — and `outcome` is the sentence that says which road it came in by. Anything\n * larger would be a second payload channel, and the payload has one (`results[]`).\n *\n * `not-run` IS ABSENT FROM THE STATUS SET, AND ITS ABSENCE IS THE POINT. That member describes a\n * clause the ENGINE deliberately never attempted after an earlier one failed — a fact about the\n * turn, which no op can know and none may claim. The three a classifier may return are derived from\n * the schema's own vocabulary rather than re-spelled, so a fifth receipt status cannot appear here\n * without somebody deciding whether an op may return it.\n *\n * THE `failed` MEMBER IS WHAT MAKES THIS FAIL-CLOSED POSSIBLE (D-03). A result the declared fold\n * cannot read reports `failed` with a named outcome, never `executed`: an unreadable result might be\n * a refusal, so success is the one claim a receipt must never default to.\n */\nexport interface ClauseVerdict {\n readonly status: Exclude<ClauseReceiptStatus, 'not-run'>\n /**\n * WHICH road, in the op's own vocabulary — `schema-fail`, `refs-only`, a proposal id.\n *\n * The empty string means \"this op has nothing to add\", and the engine falls back to the line it\n * has always printed. It is not a second spelling of absence: a fold that had nothing to say and a\n * fold that was never declared reach the same rendered line, which is the honest outcome for both.\n */\n readonly outcome: string\n}\n\n/**\n * The public, capability-free description of one registered capability.\n *\n * Carries no live validator and nothing runnable: every value reachable through a\n * declaration is data. `invokeFunction` reads the enforcing schema off the {@link\n * FunctionSpec} instead, which never leaves this directory.\n */\nexport interface FunctionDeclaration extends FunctionMetadata {\n /**\n * Whether THIS composition can run the op (D-09/D-16).\n *\n * Computed by the registry from the deps it was constructed with, never copied off a\n * spec. A listing is therefore a fact about the host a caller is talking to: the same\n * capability reads `bound` from a composition that supplied its implementation and\n * `unbound` from one that did not, and `invokeFunction` refuses on exactly that answer.\n */\n bindingStatus: FunctionBindingStatus\n // 2026-10-02 (432-42, D-14): no `discloses` flag. It projected the presence of the per-op\n // disclosure a confirm prompt showed; the prompt and the method are deleted, and so is the column.\n /**\n * This op folds its OWN result into a clause verdict (2026-08-20, Phase 399.1 D-01).\n *\n * PRESENCE, AS DATA — never the callable: {@link FunctionSpec.classify} stays where it is, and a\n * function-valued field on {@link FunctionMetadata} would put something runnable back on every\n * listing (BL-01).\n *\n * WHAT THE PROJECTION IS FOR, AND WHY IT IS NOT DECORATION. D-01 puts refusal knowledge in a\n * per-op fold rather than in a chat-side rule that pattern-matches values, because a rule that\n * can only refuse what it can NAME cannot be driven to zero by naming more things. The cost of\n * that choice is coverage: an op that never declared a fold reports the legacy `executed` for\n * every result it can return, silently. This boolean is what makes that countable — the census in\n * `packages/cli` cannot reach a spec by construction, so without it the coverage question could\n * only be answered by somebody reading forty-three op files.\n *\n * `true` is the only value: `false` and an absent key would be two spellings of one fact, and a\n * present `undefined` would make a golden column read `null` for an op that simply has no fold.\n */\n classifies?: true\n /**\n * This op composes its own human-facing lines on top of the default payload render (399.1 D-04).\n *\n * PRESENCE, AS DATA, on the two flags above. The fold ADDS legibility and can never suppress: the\n * default render is the complete payload and a declared fold is printed beside it, never instead\n * of it. That is a property of the render path rather than of this flag, and the flag is here so\n * a listing — and the golden ledger — can say which ops carry one.\n */\n rendersResult?: true\n /** Inert JSON-Schema projection of the runtime input contract (D-14). */\n input: FunctionSchemaProjection\n /**\n * Inert JSON-Schema projection of the runtime output contract (D-14).\n *\n * For a `unary` op the underlying contract describes the whole result. For a `stream`\n * op it describes ONE element, never the iterable, and a catalog reads this projection\n * as the element schema its transport (SSE frame, MCP notification) carries.\n */\n output: FunctionSchemaProjection\n}\n\n/**\n * INTERNAL: metadata plus the LIVE contracts plus the implementation. Deliberately absent\n * from the package barrel — exporting this type (or any helper taking one and running it)\n * would hand a surface a private power, which is precisely what the function layer\n * abolishes.\n *\n * A spec is NOT a declaration: it extends the shared scalar metadata and re-declares the\n * two contract fields as live `z.ZodType`s. `invokeFunction` is the only reader of those,\n * and it reaches them through the module-private internals seam.\n */\nexport interface FunctionSpec<Input = unknown, Output = unknown> extends FunctionMetadata {\n /**\n * The OPTIONAL dep this implementation dispatches through, when it has one (D-16).\n *\n * Absent — the ordinary case — means the implementation needs only the required deps,\n * which every composition supplies by type, so the op is bound wherever it is registered.\n * Present means the op is bound exactly in the compositions that supplied that dep, and\n * `unbound` everywhere else. This field is the whole of a spec's say in the matter: a\n * spec states what its implementation NEEDS, and the composition's answer to that need is\n * what the declaration reports.\n */\n boundThrough?: OptionalFunctionDepKey\n /** Runtime input contract (D-14) — the validator `invokeFunction` enforces with. */\n input: z.ZodType<Input>\n /**\n * Runtime output contract (D-14).\n *\n * For a `unary` op this is the contract for the whole result, and `invokeFunction`\n * validates against it. For a `stream` op it is the contract for ONE element: parsing\n * the iterable itself against it would be a category error.\n */\n output: z.ZodType<Output>\n /**\n * The canonical output document's companion, for an output zod cannot convert in output mode\n * (2026-09-28, 431-03 · D-03, research A1).\n *\n * OPTIONAL, and it never validates anything: `output` stays the one enforcing schema, and the\n * registry refuses a companion whose `runtimeSchema` is not that same object. What it changes is\n * only the declaration's output projection, which is read from the companion's output document\n * instead of the input-mode conversion.\n */\n outputRepresentation?: OutputContract<z.ZodType<Output>>\n // 2026-10-02 (432-42, D-14/D-15): no `disclose` method. It composed the per-invocation cost line\n // a confirm prompt showed before a person approved; no door asks, so nothing calls it.\n /**\n * What this op's OWN result means, as a clause verdict (2026-08-20, Phase 399.1 D-01/D-02).\n *\n * THE OP FOLDS ITS OWN UNION, AND NOTHING ELSE MAY. Chat cannot tell a refusal from a success by\n * looking at a result: 399's UAT measured a credential-blocked config mutation, a validation\n * failure and a real proposal all reported as `executed` in green, because the engine derived the\n * status from throw-vs-return and every one of the three RETURNED. The knowledge of which arm of\n * `ConfigProposeOutput` is a refusal lives in exactly one place — the op that declared the union —\n * and this is that place. The alternative D-01 rejects by name is a chat-side rule matching values\n * or field names, which can only ever refuse what somebody has already thought to name.\n *\n * IT LIVES ON THE SPEC, NOT ON {@link FunctionMetadata}, and its presence projects onto the\n * declaration as {@link FunctionDeclaration.classifies}: the callable stays here and only the\n * boolean fact crosses to a listing.\n *\n * PURE BY CONTRACT: it runs on the composition root's return path with the op's\n * own output in hand, and a port reached from here would be I/O between an act and the report of\n * what the act was.\n *\n * IT DECIDES NOTHING AND CANNOT WIDEN ANYTHING. The op has already run,\n * and the audit row is already written when this is called. What it produces is the REPORT.\n *\n * REQUIRED AS OF 2026-08-20 (399.1 plan 04), AND ENFORCED IN TWO PLACES THAT SEE DIFFERENT\n * THINGS. It was optional for one plan while the fan-out landed, and an op that declared none\n * reported the legacy `{ status: 'executed', outcome: '' }` — the same line every op reported\n * before this member existed. Forty ops reported it for two phases, silently, which is the cost\n * D-01 accepted when it put refusal knowledge on the op instead of in a chat-side rule.\n *\n * LAYER ONE IS `tsc`, AT THE KEYSTROKE. An op file that omits this does not compile, so the\n * ordinary way of shipping an unclassified op is closed at the moment it is written.\n *\n * LAYER TWO IS THE CONFORMANCE CENSUS ON THE SHIPPED REGISTRY\n * (`packages/cli/src/__tests__/conformance/classifier-census.test.ts`), AND IT IS NOT A\n * RESTATEMENT OF LAYER ONE. The type is defeatable: `registry.ts` already registers\n * `runsEventsSpec as FunctionSpec`, and an `as`-cast, a spread of a partial literal, or a\n * registry assembled from another type all satisfy `tsc` while shipping an op with no fold. The\n * census reads what the product CONTAINS — the declarations a composed root lists — so it answers\n * the question the type cannot, by op id, in both directions.\n *\n * AND THE RUNTIME NO LONGER DEFAULTS. `foldFunctionResult` used to answer `executed` for an\n * absent classifier; it answers `failed`/`unclassifiable-result` now, because with this member\n * required an absent one means a cast got past both layers, and success is the one claim a\n * receipt must never default to (D-03).\n */\n classify(output: Output): ClauseVerdict\n /**\n * Extra human lines this op's result deserves, on top of the complete payload render (399.1 D-04).\n *\n * ADDITIVE BY CONTRACT. The default render is the whole masked payload, pretty-printed, and a\n * declared fold is printed BESIDE it — never instead of it, never as a filter over it. D-04 makes\n * that a law rather than a convention because RC-2's lesson is that a hand-picked field join is a\n * drop site: the fan-out report and the explain lines are legibility a person is glad of, and\n * neither is a reason to stop showing them what the op actually returned.\n *\n * PURE BY CONTRACT and PRESENCE-PROJECTED as {@link FunctionDeclaration.rendersResult}, on\n * `classify`'s arrangement above.\n */\n renderResult?(output: Output): readonly string[]\n invoke(input: Input, deps: FunctionDeps): Promise<Output>\n}\n\n/**\n * INTERNAL: metadata plus live contracts plus the implementation for a `stream` op (D-08).\n *\n * `Element` is what the declared `output` contract describes — ONE element, never the\n * iterable. The stream is ACQUIRED inside `invoke` rather than lazily on first iteration,\n * so an acquisition refusal (a resume token below the replay floor, say) surfaces as an\n * invocation failure instead of as a stream that dies half-delivered.\n *\n * A stream spec is registered by widening to {@link FunctionSpec}: the registry stores one\n * spec shape, and `invokeFunction` branches on the DECLARED `resultKind`, never on what\n * the implementation happens to return.\n */\nexport interface FunctionStreamSpec<Input = unknown, Element = unknown>\n extends FunctionMetadata {\n boundThrough?: OptionalFunctionDepKey\n resultKind: 'stream'\n input: z.ZodType<Input>\n output: z.ZodType<Element>\n /**\n * What a stream op's RESULT meant, folded over the acquisition rather than over an element\n * (2026-08-20, Phase 399.1 D-01).\n *\n * IT IS HANDED THE STREAM, NOT AN ELEMENT, AND THE TYPE SAYS SO. `foldFunctionResult` runs on the\n * composition root's return path with whatever `invoke` answered in hand, and for a stream op\n * that is the iterable. Declaring this over `Element` would have been a signature promising an\n * argument the runtime never passes.\n *\n * IT MUST NOT CONSUME WHAT IT IS GIVEN. Reading an element to decide a verdict would eat the\n * first event of the caller's replay — a side effect, on a member both this and\n * {@link FunctionSpec.classify} contract as pure. What a stream op can honestly report is that\n * the acquisition SUCCEEDED, which is a real fact here: the header above insists the stream is\n * acquired inside `invoke` precisely so an acquisition refusal is a throw rather than a stream\n * that dies half-delivered.\n *\n * REQUIRED, on {@link FunctionSpec.classify}'s reasoning and for a sharper reason here: a stream\n * spec reaches the registry through `runsEventsSpec as FunctionSpec`, so this shape's own `tsc`\n * layer is the ONLY one that fires at the keystroke for it. An optional member here would leave\n * stream ops with no type-level census at all.\n */\n classify(output: FunctionStream<Element>): ClauseVerdict\n invoke(input: Input, deps: FunctionDeps): Promise<FunctionStream<Element>>\n}\n\n/**\n * Injected read port over the completed runs recorded for a project.\n *\n * `packages/agent` is `storageNeutral`: no host builtin is importable here. Every byte of run\n * state arrives through this port, built at the composition root over the concrete\n * `runner-local` handoff store.\n */\nexport interface RunsReaderPort {\n /** Every completed run this project can load. Missing run storage yields `[]`. */\n list(): Promise<readonly CompletedRunHandoff[]>\n /**\n * One completed run by id, or `undefined` when no such run is recorded.\n *\n * Absence is a RESULT, not an error: the typed refusal is the op's to throw, so the\n * \"not found\" vocabulary lives in this layer rather than in every composition root.\n * Implementations resolve the id against the runs they already enumerate — never by\n * joining a caller-supplied string onto a filesystem path (T-384-08).\n */\n get(runId: RunId): Promise<CompletedRunHandoff | undefined>\n /**\n * Replay one run's recorded event stream, starting at `fromSeq` and in `seq` order.\n *\n * The exact `EventLogPort.read(fromSeq)` contract the v49 bus already replays against,\n * lifted behind a port so this layer needs no host access. A run with no recorded\n * events replays as an ordinary empty result — nothing was truncated, so nothing is\n * refused. When events below `fromSeq` existed but are no longer available, the\n * implementation rejects with the runner's `ReplayIncompleteError` carrying the lowest\n * seq it can still serve; the op turns that into the layer's typed refusal. Serving a\n * silently truncated prefix is the one thing an implementation may never do.\n */\n readEvents(runId: RunId, fromSeq: number): Promise<readonly ReplayedRunEvent[]>\n /**\n * Read back ONE step's persisted evidence — the substrate `knowledge.brief.why` answers\n * from (Phase 387, KREV-02 / D-15).\n *\n * On the RUNS port and not on the knowledge port, and that placement is the whole honesty\n * argument rather than filing. A step's evidence is a record of what happened during a run;\n * the knowledge index is a record of what is true now. Answering \"why did the brief say\n * this\" out of the second would answer a different question than the one asked, and the op\n * that answers it is given no serving capability at all, so re-running retrieval is not a\n * temptation it has to resist.\n */\n readStepEvidence(\n runId: RunId,\n address: StepEvidenceAddress,\n ): Promise<StepEvidenceLookup>\n /**\n * The target names one completed run recorded WHEN IT RAN (431 D-08), never current\n * configuration. `unknown` when the run has no readable snapshot, including one that vanished\n * after `list()` answered. Optional: an unbound reader leaves every run unknown, and an unknown\n * run never matches a requested target. Implementations resolve only runs they enumerate.\n */\n getRecordedTargets?(runId: RunId): Promise<RecordedTargets>\n}\n\n/**\n * Which step's evidence is wanted.\n *\n * `testId` is optional and its optionality is the never-guess contract, not a convenience:\n * `StepEvidence.stepIndex` is numbered per MEMBER TEST, so a run with two tests has two step\n * 0s and `(runId, stepIndex)` addresses neither of them. A single-test run needs no\n * disambiguator; a multi-test run that omits it has asked an ambiguous question, and the\n * lookup says so by name rather than answering about whichever test happened to be first.\n */\nexport interface StepEvidenceAddress {\n readonly stepIndex: number\n readonly testId?: string\n}\n\n/**\n * What a step-evidence read found — four situations a caller phrases four different ways.\n *\n * A bare `StepEvidence | undefined` was the obvious shape and it is the wrong one: it\n * collapses \"no such run was ever recorded\", \"that run has no such step\" and \"your address\n * matches more than one step\" into one silence. The why-verb has to distinguish the first two\n * (its no-trace vocabulary already does, and a surface tells the reader to go looking in one\n * case and not the other), and it must never treat the third as an absence — an ambiguous\n * address answered with a `not found` would be a wrong answer wearing an honest one's clothes.\n */\nexport type StepEvidenceLookup =\n | { readonly kind: 'found'; readonly evidence: StepEvidence }\n | { readonly kind: 'run-not-recorded' }\n | { readonly kind: 'step-not-found' }\n | { readonly kind: 'ambiguous-step-address'; readonly testIds: readonly string[] }\n\n/**\n * Injected read port over the committed knowledge store.\n *\n * Backed by the knowledge-local `/reader` package entry at the composition root. The\n * writer-gated main entry is unreachable from this layer by construction.\n */\nexport interface KnowledgeReaderPort {\n /**\n * 2026-09-06, 416 D-17: gate history and the current verdict. Optional so existing\n * implementations and fakes remain type-valid; an unbound read refuses by name.\n */\n gateReceipts?(input: { candidateId: string }): Promise<KnowledgeGatesListResult>\n /**\n * 2026-09-07, 417 D-01: the DATA the Gate-1 bridge carries in. Optional so existing\n * implementations and fakes stay type-valid; an unbound read refuses by name.\n */\n candidateInjection?(input: { candidateId: string }): Promise<KnowledgeCandidateInjectionResult>\n /** Every committed bundle, already projected to the schema-owned listing row. */\n listBundles(): Promise<readonly KnowledgeBundleSummary[]>\n /**\n * The maintenance view of every record matching a closed structural filter (KREV-01).\n *\n * Wiring over the reader entry's own `inspectRecords`, and the return type says so: it is\n * that function's view schema and not a paraphrase of it. KREV-01's \"no new memidex code\"\n * claim survives only while that stays literally true, and the first field of a paraphrase\n * to drift would be the one nobody looked at.\n */\n inspectRecords(input: KnowledgeRecordsInspectInput): Promise<readonly InspectRecordView[]>\n /** Every record change since a build ordinal — the reader entry's `diffSince`, wired. */\n diffSince(input: KnowledgeRecordsDiffInput): Promise<readonly RecordChange[]>\n /**\n * One record with the provenance that justifies it, or a named absence.\n *\n * Absence is a RESULT here rather than a refusal the port throws, because a record id that\n * names nothing is an ordinary reviewer question and not a broken store. The op renders the\n * answer; it never decides what \"found\" means.\n */\n showRecord(input: KnowledgeRecordShowInput): Promise<KnowledgeRecordShowResult>\n /**\n * Current maintenance content for caller-supplied identities, in first-request order\n * with duplicates removed. Missing records remain per-ID results; an incomplete scan\n * retains the maintenance reader's typed failure for the caller to report honestly.\n * Optional for existing hosts: consumers refuse an unbound capability by name.\n * This read does not sight identities or change storage.\n */\n showRecords?(input: { recordIds: readonly string[] }): Promise<readonly KnowledgeRecordShowResult[]>\n /**\n * What became of the canary lines THIS run served (2026-08-29, Phase 407 · D-08).\n *\n * ONE ROW PER TUPLE ASKED ABOUT, in the order asked. The caller supplies the served-canary\n * tuples it already holds from the run's own evidence — `candidateId` is the served channel-1\n * line's id, which IS the curation candidate id — and the reader answers with the observation\n * id each tuple's outcome event would carry, plus that outcome when a surviving attributed\n * event exists. `outcome` ABSENT means \"no attributed event survives for this tuple\", which is\n * an ordinary state (curation has not settled, or it settled and attributed nothing) and NOT\n * an error; `observationId` is always present because it is DERIVED from the tuple —\n * `canaryOutcomeObservationId({ candidateId, runId, testId, testIndex, stepIndex })` — rather\n * than looked up, so a caller can name the event it is waiting for before that event exists.\n *\n * ON THE READER PORT AND NOT THE RUNS PORT, unlike `readStepEvidence` one interface up: the\n * SERVING half of a canary (the marker) is a fact about the run and is read from its evidence,\n * but the ATTRIBUTED half is a fact about the committed knowledge store's outcomes log. Asking\n * the runs port for it would be asking a record of what happened for a record of what is true.\n *\n * OPTIONAL, so every existing port implementation and every test fake stays type-valid. The\n * `/reader` entry implements it in 407-04 and agent-local binds it there; until then a caller\n * sees `undefined` and renders the honest not-yet-attributed state rather than a wrong badge.\n *\n * THE ANSWER CARRIES ITS OWN PARTIALITY (407-19, REVIEW WR-03). `skippedBundles` is the walk's\n * count of bundles it could not load — corrupt, truncated, or failing the integrity check that\n * catches tampering. `> 0` means the answer is PARTIAL, and a caller must not render an absent\n * `outcome` as a positive `not attributed`: on a partial walk that absence means \"not found in\n * the part of the store I could read\", which is a different sentence. The count rides HERE, on\n * the read that degraded, rather than being inferred from a sibling read failing on the same\n * file — an inference that does not survive the two reads seeing different stores.\n */\n canaryAttributions?(input: {\n runId: string\n tuples: readonly {\n candidateId: string\n testId: string\n testIndex: number\n stepIndex: number\n }[]\n }): Promise<{\n readonly rows: readonly {\n candidateId: string\n testIndex: number\n stepIndex: number\n observationId: string\n outcome?: 'confirmed' | 'contradicted' | 'helpful' | 'harmful'\n }[]\n readonly skippedBundles: number\n }>\n}\n\n/**\n * Injected WRITE capability over knowledge review — accept, reject and forget (Phase 387,\n * KREV-01 / D-17, declared here and implemented in 387-08; direct since 432-12).\n *\n * A SEPARATE port from {@link KnowledgeReaderPort}, and separate is the point. Widening the\n * reader with a write member would have handed a write path to every composition that only\n * ever wanted to list bundles — including the read-only surfaces the physically-separate\n * reader entry exists to keep write-free — and no lint could have told the two apart\n * afterwards, because they would have been one type. The split is what keeps \"this host can\n * read knowledge\" and \"this host can change it\" two different, separately answerable\n * questions.\n *\n * OPTIONAL on {@link FunctionDeps} and joined to {@link OptionalFunctionDepKey} for the same\n * reason `runInvocation` is: a host that cannot mutate knowledge — a listing registry, a\n * read-only surface — must report that as a VISIBLE `unbound` on the verbs by name, not as a call\n * that fails somewhere far away.\n *\n * 2026-09-30, 432-12 (D-04/D-05/D-09): `change` applies an explicit accept, reject or forget in the\n * call, through the explicit writer, in every execution context, under the writer lease. It is the\n * member every change op reaches. 2026-10-01 (432-17): `propose` and `apply` are deleted with the\n * proposal inbox; old proposal files are never read again (D-22).\n */\nexport interface KnowledgeReviewPort {\n /**\n * Apply one explicit knowledge change in the call and answer what it changed (432-12).\n *\n * Validation, target resolution, the writer lease, delegation to a live holder, delta\n * validation, bundle egress and every promotion gate belong to the writer behind this member.\n * A repeated `operationId` is the same change and lands once; an absent one is minted.\n */\n change(request: KnowledgeChangeRequest): Promise<KnowledgeChangeOutput>\n}\n\n/**\n * One explicit knowledge change (432-12): the verb, the input that verb takes, and the caller's\n * stable identity for it when the caller has one.\n *\n * Discriminated so `reject`'s required reason cannot be omitted by asking for an accept. A mark is\n * not here: it changes knowledge through `runs.mark`, which owns its own identity and checkpoints.\n */\nexport type KnowledgeChangeRequest = (\n | { readonly verb: 'accept'; readonly input: KnowledgeAcceptInput }\n | { readonly verb: 'reject'; readonly input: KnowledgeRejectInput }\n | { readonly verb: 'forget'; readonly input: KnowledgeForgetInput }\n) & { readonly operationId?: string }\n\n/**\n * Injected read port over the entity directory (Phase 387, ENTY-01 / D-09).\n *\n * Two verbs, and the split is the never-guess contract expressed as a type. `resolve` takes\n * anything a human or a model might say and answers with a closed three-arm union, so a\n * caller is structurally unable to receive a maybe. `get` takes an address that already\n * exists and answers with the entity or with nothing.\n *\n * Descriptor-level on purpose. The port carries FACTS about an entity and never a card,\n * which is what leaves exactly one card producer in this layer (ENTY-02): a composition\n * cannot render, because it is handed no vocabulary in which to do so.\n *\n * `get` may not mint. `resolve` sights, and sighting is what assigns a permanent address\n * (D-01); a `get` that could write would make every card render on every surface a\n * potential mutation of the one durable store this system never rebuilds.\n */\nexport interface EntityDirectoryPort {\n resolve(ref: string): Promise<EntityResolution>\n get(ref: string): Promise<EntityDescriptor | undefined>\n}\n\n/**\n * One post-run chain job as the chip projection needs to see it (Phase 388, D-14).\n *\n * Status and claim drive the chips; optional recorded facts drive the stage detail (423 D-12).\n * The claim remains separate from status, so running does not widen the job vocabulary.\n * Missing facts stay absent, including on older reader implementations.\n */\nexport interface PostProcessingJobRow extends Readonly<PostProcessingStageDetail> {\n readonly status: JobStatus\n /** Whether a drainer holds this job right now. `false` covers queued and terminal alike. */\n readonly claimed: boolean\n}\n\n/**\n * What one run's post-run chain has durably recorded, by member (Phase 388, D-14; narrowed to\n * the two chip stages — Phase 404, D-01, 2026-08-26).\n *\n * Every member is OPTIONAL, and each absence is a real, different situation: no analyze-run row\n * means nothing was ever enqueued for this run; no curate-memory row means the analysis has not\n * chained yet. Padding either of them with a synthetic row would erase exactly the distinction\n * the projection reads.\n *\n * 423 D-12 reports all three durable stage rows. Proposals contributes detail only;\n * the chip set remains analysis and curation.\n *\n * 2026-09-01 (Phase 409): the chain's third derived id left with the Issue-slot cleanup.\n * 2026-09-11 (Phase 422, D-13): a third derived id returns, without a third chip.\n */\nexport interface PostProcessingChainState {\n readonly analyzeRun?: PostProcessingJobRow\n readonly curateMemory?: PostProcessingJobRow\n readonly proposeImprovements?: PostProcessingJobRow\n /** Completed curation facts, available before the proposals stage reaches terminal. */\n readonly curationSnapshot?: CurationSnapshot\n /** The chain-terminal record, once the terminal transaction wrote it (D-09). */\n readonly notification?: RunNotification\n}\n\n/**\n * Injected read port over the durable post-run chain state (Phase 388, D-14).\n *\n * OPTIONAL on {@link FunctionDeps}, so a host with no queue storage lists `runs.postProcessing`\n * as `unbound` BY NAME rather than answering a confident all-pending about a chain it has no\n * way to see.\n *\n * The port carries the host's `idSource` rather than resolving ids itself, and that placement\n * is the load-bearing part. Chain identity is DERIVED (RESEARCH Pattern 2), and it must be\n * derived through the same source the host's queue enqueued with — a reader that owned its own\n * derivation would address rows under other ids the moment a composition configured a different\n * source, and would report `pending` about a chain that had already finished. So the function\n * layer derives, once, through `chainJobIdsForRun`, and the port only reads what it is handed.\n *\n * Reads are fence-free by design: reading claims no authority, so a status query neither adopts\n * an epoch nor competes with the drainer that holds one.\n */\nexport interface PostProcessingReaderPort {\n /** The id source THIS host's queue derives job ids with. */\n readonly idSource: JobIdSource\n /**\n * Durable state for the ids given, or `undefined` when this project holds no queue database\n * at all. Chain identity is still the job-kind layer's to derive, and this port only reads\n * what it is handed: all three ids, with the proposals row used only for detail (423 D-12).\n * It may not derive an id of its own.\n *\n * 2026-09-01 (Phase 409): the width dropped from three to two.\n * 2026-09-11 (Phase 422, D-13): three again, and no longer equal to the state's member count.\n *\n * `undefined` is a distinct answer from an empty state and both are honest: the first says\n * nothing has ever been enqueued here, the second says this chain's rows are not among the\n * ones that have. An implementation MUST NOT bring a database into existence to answer —\n * a status read that materialized a queue would make asking a question change the answer.\n */\n readChain(ids: ChainJobIds, runId: string): Promise<PostProcessingChainState | undefined>\n}\n\n/**\n * Injected read port over ONE run's durable dashboard projection (Phase 405, D-03).\n *\n * `packages/agent` is `storageNeutral`: no host builtin is importable here, so every row arrives\n * through this port, built at the composition root over the concrete dashboard SQLite database.\n * The port answers ROWS — members, steps, sub-actions — and nothing derived; the D-06 token sum is\n * the op's, computed once in the layer that owns the contract rather than once per host that\n * happens to hold a database.\n *\n * ABSENCE IS A RESULT, NEVER A PATH JOIN ON CALLER INPUT (the `RunsReaderPort.get` law, T-384-08).\n * A run id that names nothing answers `undefined`, and turning that into the layer's typed refusal\n * is `runs.detail`'s job — so the \"not found\" vocabulary lives here in one place rather than in\n * every composition root. An implementation resolves the id against the rows it already\n * enumerates; joining a caller-supplied string onto a filesystem path is the one thing it may\n * never do.\n *\n * OPTIONAL on {@link FunctionDeps} for the reason `postProcessing` is: a host with no dashboard\n * database genuinely cannot say what a run's steps were, and the alternative to reporting that by\n * name is answering an empty projection about a run it has never been able to see — a wrong answer\n * wearing a correct one's clothes.\n */\nexport interface RunDetailReaderPort {\n /** One run's projected rows, or `undefined` when the runs database holds no such run or does not exist yet. */\n read(runId: RunId): Promise<RunDetailRows | undefined>\n /**\n * 2026-10-18 (444-12, D-14): the run's own row status, or `undefined` when no row is recorded.\n * Optional: a host without it derives no `no-verdict` fact, because absence is not a status.\n */\n readRecord?(runId: RunId): Promise<{ status: string } | undefined>\n}\n\n/**\n * Injected read port over ONE run's content-addressed evidence blobs (Phase 405, D-12/D-13).\n *\n * `packages/agent` is `storageNeutral`: no filesystem is importable here, so the bytes arrive\n * through this port, built at the composition root over the SAME `FsEvidenceArtifactStore` the\n * runner wrote them with. The port answers BYTES and nothing derived — the content-type sniff is\n * `runs.artifact`'s, computed once in the layer that owns the contract rather than once per host\n * that happens to hold a runtime root.\n *\n * ABSENCE IS A RESULT, AND IT IS TWO RESULTS (D-15). See {@link EvidenceBlobLookup}: the concrete\n * store collapses \"no such run\" and \"no such blob\" into one `undefined`, and an implementation of\n * this port is where that distinction is recovered — because above it the two are different things\n * a page has to render. Turning either arm into a typed refusal is the op's job, so the \"not\n * found\" vocabulary lives in one place rather than in every composition root.\n *\n * THE PORT NEVER JOINS CALLER INPUT ONTO A PATH (the `RunsReaderPort.get` law, T-384-08 /\n * T-405-14). Containment is the STORE's own rule — `slugBranch` over the runId and a\n * 64-lowercase-hex check over the sha, both inside `FsEvidenceArtifactStore` — and an\n * implementation that assembled a path itself would be a second containment rule, free to be\n * weaker than the one the runner writes through.\n *\n * OPTIONAL on {@link FunctionDeps} for the reason `postProcessing` is, and for a sharper one: the\n * alternative was widening the REQUIRED {@link RunsReaderPort} with a blob verb, which every\n * daemon, MCP and test implementer of that port would then have to satisfy with storage most of\n * them do not have.\n */\nexport interface EvidenceBlobReaderPort {\n /** One blob's bytes, or which KIND of absence this host is reporting. */\n read(runId: RunId, sha: string): Promise<EvidenceBlobLookup>\n stat?(runId: RunId, sha: string): Promise<\n { status: 'found'; byteLength: number } | { status: 'unknown_run' | 'blob_absent' }\n >\n readRange?(runId: RunId, sha: string, start: number, end: number): Promise<EvidenceBlobLookup>\n /**\n * The same question asked as a STAT — are the bytes still there — for read-time presence\n * annotation on the durable reads (Phase 406, D-17).\n *\n * OPTIONAL SO THAT EVERY EXISTING IMPLEMENTATION AND FAKE KEEPS COMPILING, and for the sharper\n * reason that absence here is a real host condition rather than an oversight: a host that cannot\n * cheaply stat its blobs is not lying about anything, and an op that finds this member missing\n * OMITS presence rather than reporting refs it never looked at as absent. A claimed absence is\n * the one answer this field must never be able to give by accident, because it renders honest\n * evidence as `evidence-incomplete`.\n *\n * IT ANSWERS THE SAME THREE WORDS `read` DOES, so the two cannot disagree about WHICH absence a\n * ref is in — the read is this answer plus the bytes, never a second rule.\n */\n has?(runId: RunId, sha: string): Promise<EvidenceBlobPresence>\n}\n\n/**\n * Injected read port over a run's persisted analysis artifact (Phase 389, D-10/D-11).\n *\n * `analysis.json` is the analyze-run job's own receipt; the only legal reader routes its\n * bytes through `guardRunAnalysisArtifact` (the version guard), and an implementation of\n * this port does exactly that at the composition root — the op receives a guarded document\n * or a typed absence, never raw bytes.\n *\n * `undefined` is an ANSWER, not an error: a run whose analysis never ran (budget spent,\n * daemon down, chain still in flight) has no artifact, and the ops answer it through the\n * D-10 accessor's handoff floor. That is why `runs.get` treats an UNBOUND port the same\n * way — artifact-absent — while `analysis.get` refuses by name: a listing that cannot see\n * artifacts still lists truthfully off the floor, but a caller asking for THE analysis of\n * a run must be told this host cannot serve one.\n */\nexport interface AnalysisArtifactReaderPort {\n /** The guarded artifact for one run, or `undefined` when none is on disk. */\n getArtifact(runId: string): RunAnalysisArtifact | undefined\n}\n\n/**\n * Injected read port over the resolved project configuration.\n *\n * The port's name says what its security contract is: it yields a config whose\n * secret-bearing values were dropped while the DTO was CONSTRUCTED. There is deliberately\n * no unmasked variant on this port — a capability that could ask for one would make the\n * masking optional, and optional masking is not masking (T-384-07).\n */\nexport interface ConfigReaderPort {\n getMasked(): Promise<MaskedResolvedConfig>\n}\n\n/**\n * Injected capability that STARTS a run (D-16, Phase 385).\n *\n * Its one verb resolves the identity of the run it started and nothing else. That narrowness\n * is the point: the acknowledgment a caller receives is not assembled from what this port\n * SAYS happened, it is read back off the run's own durable record through\n * {@link RunsReaderPort} — the same port `runs.get` answers from. A host that returned an id\n * without running anything therefore fails at the join rather than at a promise nobody can\n * check.\n *\n * Owning the process model is what makes this a port rather than shared code (the plan-08\n * dissection rule): a terminal host runs a suite one way, a daemon another, and neither\n * would call the other's orchestration as written.\n */\nexport interface RunInvocationPort {\n /**\n * Start a run for this request and resolve when the run has been recorded.\n *\n * Rejects if the run could not be started or did not complete. An implementation that\n * cannot honour the request must throw, never resolve a run id it did not produce.\n */\n start(request: RunsStartInput): Promise<StartedRun>\n}\n\n/** What {@link RunInvocationPort.start} reports: the identity of the run it started. */\nexport interface StartedRun {\n readonly runId: RunId\n}\n\n/**\n * The injected-dependency record every op implementation receives. Ops are pure\n * functions of (validated input, deps) — they never reach for a host API.\n *\n * The four READ ports are required and non-partial on purpose: a composition that omits one\n * fails to typecheck. Phase 387 adds `entities` as the fourth, and it joins as REQUIRED\n * rather than optional deliberately — every host that can list a capability can also resolve\n * an address, so a host that omitted it would not be reporting a real absence, it would be\n * reporting that somebody forgot. That is precisely the state the required/optional split\n * exists to distinguish, and widening the optional side to cover a forgetting would have\n * made `unbound` mean two different things.\n *\n * The OPTIONAL members' optionality is not a relaxation of that discipline but the mechanism\n * behind it. Not every host can start a run — a read-only surface, a registry built for a\n * listing, 386's daemon before it wires its own executor — and D-09 requires that state to be\n * VISIBLE rather than a call that fails somewhere far away. Omitting `runInvocation` makes\n * `runs.start` list as `unbound` and refuse by name; supplying it makes the same capability\n * bound. Any further optional member must join {@link OptionalFunctionDepKey} so the same\n * reporting applies to it.\n *\n * `knowledgeReview` (387, KREV-01) is the second, and it is the one that makes the required/\n * optional split earn its keep on the WRITE side: the ability to read committed knowledge and\n * the ability to change it are separate powers, so they are separate members. A host that\n * supplies only the reader lists the mutating verbs as `unbound` by name — which is a true\n * statement about that host, and is exactly what widening the reader port with a write member\n * would have made unsayable.\n */\n/**\n * The live-view seam `runs.liveurl` mints through (403 D-03).\n *\n * OPTIONAL, and its absence is a GENUINE HOST FACT rather than a degraded mode: a CLI run in a\n * terminal serves no origin, so there is no URL it could honestly hand back. A host that binds it\n * supplies the per-process signer, the origin it is actually listening on, and a read of the live\n * run registry — never a token, and never a parse.\n *\n * `capabilityOf` answers `undefined` for a run this host has no live session for (the op turns\n * that into `unknown_run`) and a `LiveStreamDeclaration` — possibly `{ kind: 'none' }` — otherwise.\n * `onMinted` observes every minted token value. 2026-10-14 (441-16, D-01): no shipped host binds it\n * (a minted token is not a declared secret); tests use it to capture what the op really minted.\n *\n * `editorCapabilityOf` is the editor subject's read (428 D-07), through which `editor.liveurl`\n * mints. ABSENT means this host serves no live editor — the standalone MCP host and the MCP App\n * host never bind it, and the op refuses by name. `undefined` means no such live editor session.\n * It is a separate lookup from `capabilityOf` so an editor session can never be addressed as a run.\n */\nexport interface LiveViewPort {\n signer: LiveUrlSigner\n origin(): string | undefined\n now(): number\n capabilityOf(runId: string, handle: number): LiveStreamDeclaration | undefined\n editorCapabilityOf?(sessionId: string): LiveStreamDeclaration | undefined\n onMinted?(token: string): void\n}\n\nexport interface FunctionDeps {\n runs: RunsReaderPort\n knowledge: KnowledgeReaderPort\n config: ConfigReaderPort\n entities: EntityDirectoryPort\n runInvocation?: RunInvocationPort\n /**\n * 403 D-03: the live-view mint seam. See {@link LiveViewPort} — absent means this host has no\n * served origin, and `runs.liveurl` refuses by name rather than minting a link to nowhere.\n */\n liveView?: LiveViewPort\n knowledgeReview?: KnowledgeReviewPort\n /**\n * 388 D-14: the durable post-run chain read. The third optional member, and it joins for the\n * reason the other two did rather than by analogy — a host with no queue storage genuinely\n * cannot answer \"what became of that run's analysis\", and the alternative to reporting that\n * by name is answering `pending` about a chain it has never been able to see, which is a\n * wrong answer wearing a correct one's clothes.\n */\n postProcessing?: PostProcessingReaderPort\n /**\n * 405 D-03: the durable run-detail projection read. See {@link RunDetailReaderPort} — absent\n * means this host owns no dashboard projection database, and `runs.detail` refuses BY NAME\n * rather than answering an empty run about a projection it cannot observe. The CLI host binds it\n * over the configured or default runs database path whenever its config parses (a read before\n * that file exists answers not recorded in the runs database); the dashboard passes its own handle.\n */\n runDetail?: RunDetailReaderPort\n /**\n * 405 D-12/D-13: the run-scoped evidence-blob read. See {@link EvidenceBlobReaderPort} — absent\n * means this host owns no runtime root, and `runs.artifact` refuses BY NAME rather than\n * answering `blob_absent` about every artifact in the product, which would read to an operator\n * as storage loss. Bound on every LOCAL host, which is exactly the set that has run directories.\n */\n evidenceBlobs?: EvidenceBlobReaderPort\n /**\n * 389 D-10/D-11: the analysis-artifact read. `analysis.get` binds through it and refuses\n * by name where it is absent; `runs.get` reads it opportunistically and treats an unbound\n * port as artifact-absent (the floor), because the cheapest read must stay cheap and a\n * listing off the deterministic floor is honest, not degraded. Bound in plan 06's\n * composition root over the run-directory `analysis.json` + version guard.\n */\n analysis?: AnalysisArtifactReaderPort\n /**\n * 389 D-08: the live recurrence seam the one renderer joins through. OPTIONAL because a\n * host without the knowledge index genuinely has no history to answer with — and the\n * renderer's contract turns that absence into the explicit no-history clause rather than\n * a refusal, so `analysis.get` stays bound wherever `analysis` is. Bound in plan 06 to\n * v51's run-outcome projection; 390 rebinds the SAME seam to its fingerprint window.\n */\n recurrence?: RecurrenceProvider\n /**\n * 390 D-12/D-13: the committed quarantine ledger's three verbs — list, release, add.\n *\n * OPTIONAL for the reason `knowledgeReview` is, and not by analogy: a host with no knowledge\n * root genuinely cannot enumerate quarantine state, and the alternative to saying so by name\n * is answering an empty list about a ledger it has never been able to read — a wrong answer\n * wearing a correct one's clothes. On the write side the stakes are higher still: an unbound\n * `add` that no-opped would report a test as quarantined while it kept failing every build.\n *\n * ONE port for all three verbs rather than a reader/writer split, because the read/write\n * asymmetry is already stated on each op's risk descriptor — `quarantine.list` declares a\n * read-only descriptor, `release` and `add` declare `readOnly: false` — so a second port would\n * restate at the composition root a distinction the descriptors already carry. 2026-10-02\n * (432-39, D-12): no op declares a scope and no gate enforces the split at a call; it lives only\n * on the descriptors. The port TYPE is minted in schema, so knowledge-local can implement it\n * without depending on the function layer.\n */\n quarantine?: QuarantineOperationsPort\n /**\n * 419 GATE3-01: the mark port — assembled by the cli host over eval-local + the review\n * port; absent on hosts that cannot freeze gold.\n */\n feedback?: FeedbackPort\n /**\n * 423 D-19: read-only feedback observations. Separate from `feedback` so a host can serve\n * history without mark authority; absent means `runs.marks.history` is unbound by name.\n * 423 D-16: the same binding carries `preview`, runs.mark's plan for an exact input with no\n * write; a binding without that verb leaves `runs.mark.preview` unbound by name.\n */\n feedbackReads?: FeedbackReadsPort\n /**\n * 392 D-24: the assembled chat turn engine, behind which `agent.ask` runs.\n *\n * OPTIONAL for the reason its neighbours are, and the honest absence matters more here than\n * anywhere else in this record: a host with no engine — a remote read surface, a daemon before\n * a chat host exists — genuinely cannot run a turn, and the alternative to reporting that by\n * name is answering an EMPTY turn. A person told \"I understood you and did nothing\" stops\n * asking, which is the same failure the unbound proposals inbox was reasoned about avoiding.\n *\n * The port is a single verb by design. Anything wider — a session lister, a history reader —\n * would be reach the turn entry does not need and would give a surface holding this dep a way\n * into session state without a registered op declaring it.\n */\n chatTurn?: ChatTurnPort\n /**\n * 393 D-01 / D-15: the two host halves one draft evaluation needs — resolve a caller's path to a\n * parsed draft, and assemble the ports the four gates run against.\n *\n * ONE BUNDLED CAPABILITY rather than five separate deps, on the `runInvocation` precedent. The\n * receipts store, the suite fingerprint index, the text corpus and the run pair are not\n * independently bindable: an index scoped to a different product than the runs were taken under\n * would compare a draft against another project's suite, and a host that could supply three of\n * the five would list this op `bound` and then fail somewhere far from the composition that\n * forgot one. Bundling makes \"can this host verify a draft\" a single fact.\n *\n * OPTIONAL for the reason `runInvocation` is, and here it says two things at once: a host that\n * cannot PARSE a test file and a host that cannot START a run are both hosts that cannot verify\n * a draft, and `composeLocalAgent()` binds this only when it has both.\n *\n * WHY RESOLUTION IS A SEPARATE VERB FROM EVALUATION. `packages/agent` is `storageNeutral`: it\n * cannot stat a path, read a file, or know where the workspace ends. So the three refusals that\n * need a filesystem are ANSWERED by the host and NAMED by the op — `resolveDraft` returns a\n * typed outcome and never throws a host error through the layer, and\n * `functions/ops/authoring-verify-draft.ts` maps each arm onto its own caller-facing class. The\n * alternative — a single `evaluate(draftPath)` — would have put the refusal vocabulary in\n * whichever package happened to own the syscall, one layer below where a caller catches it.\n */\n draftEvaluation?: DraftEvaluationPort\n /**\n * 394 D-01 / WTST-01: the authoring loop's read half — the brief, and the authored suite as\n * text (stages 1-2).\n *\n * OPTIONAL for the reason `draftEvaluation` is, and the honest absence is load-bearing here in\n * a way it is nowhere else in this record. A host with no knowledge index cannot serve an\n * authoring brief, and the alternative to saying so by name is compiling a test from an EMPTY\n * brief — which produces a plausible draft, authored against nothing this project knows, and\n * says so nowhere. That is a wrong answer wearing a correct one's clothes, and it is wearing\n * them into a file the user is asked to commit.\n */\n authoringRead?: AuthoringReadPortLike\n /**\n * 394-26 / WTST-01: which scope this project authors for, when the caller named none.\n *\n * OPTIONAL and consulted ONLY on absence. `authoring.draft.write`'s `scope` is optional at the\n * registry (the `runs.start` law), so an input carrying just an intent has to be resolved\n * before the loop runs — and the resolution reads the config and the workspace, which\n * `packages/agent` cannot do. A composition that binds the loop's other halves and forgets this\n * one refuses BY NAME on a scope-less call rather than authoring against a default: a guessed\n * product is a draft written for the wrong application, which is the one failure mode a silent\n * fallback here would produce.\n */\n authoringScope?: AuthoringScopePortLike\n /**\n * 394 D-01 / WTST-01: the authoring loop's compile half — the model, and the draft shelf\n * (stage 3).\n *\n * Bound with `authoringRead` or not at all: `composeLocalAgent()` supplies the pair, because a\n * host that can read but not write is not a degraded author, it is a host that must say\n * `unbound` by name. `authoring.draft.write` names THIS key in `boundThrough` — it is the half\n * that makes the op mutating — and refuses on either half's absence at the invoke, so an\n * in-layer caller holding the spec directly gets the same named error.\n */\n draftShelf?: DraftShelfPortLike\n /**\n * 394-07 D-12 / WTST-05: the honesty funnel's reads — the receipts store and (optionally within\n * the bundle) the outcome projection and quarantine ledger D-14 consults. 2026-10-01 (432-17): the\n * proposals inbox the `accepted` stage read is deleted; 2026-10-02 (quick 261002-ctr) that stage\n * is `writeEligible`, read off the receipts (see `projectAuthoringFunnel`).\n *\n * OPTIONAL, and the stakes sit on the READ side. A host with no agent-qa runtime root cannot list draft receipts, and the alternative to\n * saying so by name is answering an all-zero funnel — which does not merely under-report, it\n * reports a loop that filtered everything, the one reading of a zero funnel that FLATTERS the\n * loop this measurement exists to keep honest.\n */\n authoringFunnel?: AuthoringFunnelPortLike\n /**\n * 395 D-03/D-17 · CFGM-01/04: the pinned config file SET as RAW BYTES, plus the comment-preserving\n * field edit over them.\n *\n * DELIBERATELY NOT A WIDENING OF {@link ConfigReaderPort}, which is masked-only by contract and\n * must stay so — a capability that could ask it for unmasked values would make masking optional,\n * and optional masking is not masking. This port answers a different question: what bytes are\n * COMMITTED in the person's repository. Those carry no resolved secrets, because D-11 makes\n * committed config refs-only by law.\n *\n * The EDIT rides the same port as the read because both are host facts. `yaml`'s Document API is\n * an external dependency `packages/agent`'s ownership contract does not admit, and admitting one\n * to bring the edit in-layer would widen a boundary rather than respect it.\n */\n configFiles?: ConfigFilesPortLike\n /**\n * 395 CFGM-01: whole-config validation, which runs BEFORE a change is written.\n *\n * A PORT because `AgentQaConfigSchema` and `validateProject` live in `@vostride/agent-qa-core`\n * and this package does not depend on it — `validate:arch` reds that edge with no legal repair.\n * The capability is declared here and bound in `cli`.\n */\n configValidate?: ConfigValidatePortLike\n /**\n * 395-08 D-04 · CFGM-05: the shared scaffold CONTENT, rendered by the host that owns it.\n *\n * THE ONE DEP `config.project.scaffold` HAS AND THE OTHER FIVE CHANGE OPS DO NOT. D-04's claim\n * is that `agent-qa init` and the scaffold change write one substance; that substance lives\n * beside `init`'s filesystem machinery in `packages/cli`, which this package may not import. Its\n * absence makes exactly one op unavailable, and it says so by name.\n */\n scaffoldContent?: ConfigScaffoldContentPortLike\n /**\n * 2026-09-30, 432-07 D-05/D-07: the direct config writer. Field changes merge in the config\n * path's shared write turn and whole files publish over the digest they were built from. No\n * proposal is filed and no git process runs.\n */\n configWrite?: ConfigWritePortLike\n /**\n * 2026-08-17 (398 D-09/D-11 · XPLN-02): the four host halves one `explain` needs — the committed\n * catalog as data, the model's citation over it, and the two coverage hooks.\n *\n * ONE PORT AND NOT FOUR DEPS, on the `draftEvaluation` bundle's stated reasoning: a host that\n * could load the catalog but not cite over it would list `agent.explain` as `bound` and then\n * answer every question with a ghost citation, which abstains — safe, and useless, and reported\n * nowhere. \"Can this host explain itself\" is one fact.\n *\n * OPTIONAL for the reason `analysis` is, and the honest absence is unusually load-bearing here.\n * `packages/agent` is storageNeutral: it cannot read the committed artifact, so a composition\n * that omitted the port and got a degraded answer would be answering FROM MODEL MEMORY, which is\n * the single behaviour XPLN-02 exists to make impossible. The op refuses BY NAME instead.\n */\n capabilityCatalog?: CapabilityCatalogPort\n /** 441 D-06: the host's declared-secret mask for projected run text; absent or throwing, run reads fail closed. */\n readonly secretMask?: MaskFn\n}\n\n/**\n * What a host can tell the layer about a caller-supplied draft path (393, T-393-01).\n *\n * A discriminated union rather than `ParsedDraftLike | undefined`: \"there is no file there\", \"that\n * is a directory\", \"that is outside this workspace\" and \"that file is not a test\" are four\n * different things to tell a person, and collapsing them into an absence would make the op answer\n * all four with one message. Every arm but `parsed` becomes a NAMED error at the invoke.\n */\nexport type DraftResolution =\n | { readonly kind: 'parsed'; readonly draft: ParsedDraftLike }\n | { readonly kind: 'not-found' }\n | { readonly kind: 'not-a-file' }\n | { readonly kind: 'outside-workspace' }\n | { readonly kind: 'unparsable'; readonly reason: string }\n\n/**\n * The capability `authoring.draft.verify` binds through (393 D-01).\n *\n * `openEvaluation` takes the resolved draft because two of the four ports depend on WHICH draft is\n * being evaluated: the suite comparison must exclude the draft's own identity from both of gate\n * 3's lanes, or a draft that already lives in the authored suite would be measured against itself\n * and could never be shown to add value. It is a separate call from `resolveDraft` so a refused\n * path costs no database handle and no suite walk.\n */\nexport interface DraftEvaluationPort {\n resolveDraft(draftPath: string): Promise<DraftResolution>\n openEvaluation(draft: ParsedDraftLike): Promise<EvaluateDraftPorts>\n}\n\n/**\n * The one verb `agent.ask` binds through (392 D-24).\n *\n * Typed against the SCHEMA contracts rather than against the engine's own types, which is what\n * lets the composition root hand this layer an engine without the function layer depending on how\n * a turn is assembled — and what lets 396's MCP projection describe the same shape.\n */\nexport interface ChatTurnPort {\n runTurn(input: AgentAskInput): Promise<AgentAskResult>\n}\n","// `analysis.get` — one run's full analysis, served once (Phase 389, D-10/D-11/D-14/D-15).\n//\n// THE single producer of resolved verdicts + rendered sentences + clusters. Plan 07's CLI\n// print, M5's run page and 392's chat all call this op; none of them re-derives a verdict,\n// composes a second sentence or folds its own clusters — the sentence renderer and the\n// cluster function are the same pure symbols this file calls, so every surface is\n// byte-identical by construction (SC3, the L10 thin-client law).\n//\n// Absence discipline (D-10/D-11): a composition with no analysis port refuses BY NAME; a\n// bound port with no artifact on disk answers the handoff FLOOR — verdicts through the D-10\n// accessor, sentences from the honest template parts — because \"the analysis never ran\" is\n// a true state of a run, not an error. A run with no failures answers empty lists.\n\nimport {\n AnalysisGetInputSchema,\n AnalysisGetOutputSchema,\n errorTextOf,\n exercisedAnchors,\n failingStepOf,\n failureFingerprint,\n projectVerdictMisdirection,\n resolveRunVerdicts,\n slugBranch,\n} from '@vostride/agent-qa-schema'\nimport type {\n AnalysisGetInput,\n AnalysisGetOutput,\n AnalysisSentence,\n CompletedRunHandoff,\n PerTestOutcome,\n RunAnalysisArtifact,\n Verdict,\n VerdictSentenceParts,\n} from '@vostride/agent-qa-schema'\n\nimport { clusterVerdicts } from '../../analysis/cluster.js'\nimport { annotatePresence } from './evidence-presence.js'\nimport { renderVerdictSentence } from '../../analysis/render-sentence.js'\nimport { templateSentenceParts } from '../../jobs/kinds.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionDeps, FunctionSpec } from '../spec.js'\nimport { RunNotFoundError } from './runs-get.js'\n\n/**\n * Lowercase dot taxonomy (D-15): the locked `analysis` domain, one noun. The exported\n * constant is what plan 07's CLI and every later surface name; the literal appears here\n * once, and the parity-coverage suite picks the id up from the registry automatically.\n */\nexport const ANALYSIS_GET_FUNCTION_ID = 'analysis.get'\n\n/**\n * Join one verdict to its authored parts, or mint the honest floor (D-06/D-07).\n *\n * Artifact present → the authored parts record joined by `perTest` (never array position).\n * Artifact absent — or an artifact member with no parts record, a shape the guard admits —\n * → the SAME producer-keyed template rule the author uses (`templateSentenceParts`,\n * imported, not respelled), so sentence existence never depends on what got persisted.\n */\nfunction partsFor(\n verdict: Verdict,\n artifact: RunAnalysisArtifact | undefined,\n handoff: CompletedRunHandoff,\n): VerdictSentenceParts {\n return (\n artifact?.parts.find((candidate) => candidate.perTest === verdict.perTest)\n ?? templateSentenceParts(verdict, handoff)\n )\n}\n\n/**\n * The window key one failure is counted under (390 D-07), or nothing.\n *\n * Every input rule is IMPORTED from schema and none is respelled here: which step the failure\n * is about (`failingStepOf`), which recorded bytes describe it (`errorTextOf`), which anchors\n * it touched (`exercisedAnchors`), and how those compose into the frozen recipe\n * (`failureFingerprint`). That matters because the projection's WRITER composes the window key\n * from the very same four symbols — a second spelling here would mean the clause counts a\n * window nothing ever wrote to.\n *\n * The class folded in is the RESOLVED one (389 D-13's `::class` suffix), so an artifact\n * upgrading a member `unknown → flake` queries a different window on purpose.\n *\n * `undefined` for a member with no failing step to key from — a zero-step failure, or a\n * verdict whose `perTest` names no member. The recipe would happily key those through its\n * error arm, but the value it would produce is a stand-in for evidence that was never\n * recorded, and the query travels perfectly well on identity alone.\n */\nfunction fingerprintFor(\n verdict: Verdict,\n test: PerTestOutcome | undefined,\n): string | undefined {\n if (test === undefined) return undefined\n const step = failingStepOf(test)\n if (step === undefined) return undefined\n return failureFingerprint(\n { anchors: exercisedAnchors(step), errorText: errorTextOf(step, test) },\n verdict.class,\n )\n}\n\nexport const analysisGetSpec: FunctionSpec<AnalysisGetInput, AnalysisGetOutput> = {\n id: ANALYSIS_GET_FUNCTION_ID,\n summary: \"Read one run's resolved verdicts, rendered sentences and failure clusters.\",\n resultKind: 'unary',\n // Bound exactly where a composition supplies the artifact reader (D-16 idiom). The\n // OPTIONAL `recurrence` dep is deliberately NOT the binding key: a host without history\n // still serves sentences — the renderer answers the explicit no-history clause — so tying\n // the binding to it would refuse a capability this host can honestly run.\n boundThrough: 'analysis',\n input: AnalysisGetInputSchema,\n output: AnalysisGetOutputSchema,\n risk: { name: `fn:${ANALYSIS_GET_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * An analysis is an ANSWER, and its verdicts are what it answered (399.1 D-01).\n *\n * COUNTS AND THE RUN REF, never a sentence out of the artifact: the receipt is a map (392's\n * charter) and every verdict sentence is on `results[]`, which D-04 renders in full beside it.\n */\n classify(output): ClauseVerdict {\n return {\n status: 'executed',\n outcome: `analysis for ${output.runId} — ${output.verdicts.length} verdict(s), `\n + `${output.clusters.length} cluster(s)`,\n }\n },\n async invoke(input, deps: FunctionDeps) {\n const analysis = deps.analysis\n if (analysis === undefined) {\n throw new FunctionNotBoundError(ANALYSIS_GET_FUNCTION_ID)\n }\n\n const runId = String(input.runId)\n const document = await deps.runs.get(input.runId)\n if (document === undefined) {\n throw new RunNotFoundError(runId)\n }\n\n const artifact = analysis.getArtifact(runId)\n // The ONE verdict read path (D-10): artifact verdicts when present, the handoff's\n // deterministic floor when absent — never a per-consumer merge.\n const resolved = resolveRunVerdicts(artifact, document)\n // The projection's key law: stable test identity is (product, filePath, testName),\n // with product derived exactly as the outcome projection partitions it.\n const product = slugBranch(document.scope.key)\n\n const sentences: AnalysisSentence[] = resolved.map((verdict) => {\n const test = document.tests.find((candidate) => candidate.testIndex === verdict.perTest)\n const fingerprint = fingerprintFor(verdict, test)\n const sentence = renderVerdictSentence(\n verdict,\n partsFor(verdict, artifact, document),\n // Recurrence is a LIVE join through the D-08 seam, per call — an absent dep renders\n // the explicit no-history clause, never a dropped section.\n deps.recurrence,\n {\n product,\n filePath: test?.filePath ?? '',\n testName: test?.testName ?? '',\n // OMITTED, not `undefined`: the leg's absence is a fact about this member, and a\n // present-but-empty key would look like a window with no occurrences in it.\n ...(fingerprint === undefined ? {} : { fingerprint }),\n },\n )\n return { perTest: verdict.perTest, testId: test?.testId ?? '', sentence }\n })\n\n const sentenceByPerTest = new Map(sentences.map((entry) => [entry.perTest, entry.sentence]))\n\n return {\n runId,\n // The verdict's OWN evidence, projected (406 D-01) — cited steps and cited artifacts as the\n // resolved verdict already held them, so the failure view's links are this op's refs and not\n // a second join over `analysis.json`. Presence is consulted OPPORTUNISTICALLY through the\n // optional blob port: `boundThrough` stays `analysis`, because a host with no runtime root\n // still serves a complete analysis — it simply cannot say whether the screenshots survive.\n verdicts: await Promise.all(resolved.map(async (verdict) => {\n const test = document.tests.find((candidate) => candidate.testIndex === verdict.perTest)\n const cited = verdict.evidence.citedArtifacts\n // 422 D-17/D-19/D-20: what THIS verdict said about the memory it was served, thinned by\n // the DTO's own projection. OMITTED for a verdict that said nothing — the deterministic\n // floor's minted `unknown` and every verdict written before 422 — so a run with no\n // arbiter reaches the failure view exactly as it did, with no member to misread.\n const misdirection = projectVerdictMisdirection(verdict)\n return {\n perTest: verdict.perTest,\n testId: test?.testId ?? '',\n class: verdict.class,\n producer: verdict.producer,\n confidence: verdict.confidence,\n evidence: {\n citedSteps: [...verdict.evidence.citedSteps],\n citedArtifacts: await annotatePresence(deps.evidenceBlobs, input.runId, cited),\n },\n ...(misdirection === undefined ? {} : { misdirection }),\n }\n })),\n sentences,\n // Render-time clustering through the ONE pure fold (D-14); the representative carries\n // its already-composed sentence (D-15) — looked up, never re-rendered, so cluster and\n // per-test presentation cannot drift.\n clusters: clusterVerdicts(resolved, document).map((cluster) => ({\n fingerprint: cluster.fingerprint,\n count: cluster.count,\n members: cluster.members,\n representative: {\n testIndex: cluster.representative.testIndex,\n sentence: sentenceByPerTest.get(cluster.representative.testIndex) ?? '',\n },\n })),\n }\n },\n}\n","// Render-time pure clustering over resolved verdicts (Phase 389, D-13..D-16).\n//\n// Called inside the `analysis.get` op and nowhere else persistent (D-14): CLI, run page and\n// chat get byte-identical clusters because there is nothing here to go stale — no store, no\n// port, no cache. Groups key on the ONE exported fingerprint vocabulary (`failureFingerprint`,\n// D-13) over the ONE exported input rule (`failingStepOf`/`errorTextOf`, hoisted into schema by\n// 390 plan 02), so 390's recurrence window and this presentation cannot disagree about what \"the\n// same failure\" means — not by convention, but because there is a single spelling of each.\n//\n// D-16 — clusters mint NO identity. A cluster carries the fingerprint VALUE, its\n// occurrence count and member refs, and nothing else:\n// a cluster or verdict has no short-ID and no `agentqa://` address.\n// 2026-09-02 (Phase 410): the sixth entity kind left with the Issue-slot cleanup.\n\nimport {\n errorTextOf,\n exercisedAnchors,\n failingStepOf,\n failureFingerprint,\n} from '@vostride/agent-qa-schema'\nimport type { CompletedRunHandoff, Verdict } from '@vostride/agent-qa-schema'\n\n/** One member ref: the join keys a surface needs to expand a cluster, nothing more. */\nexport interface AnalysisClusterMember {\n testIndex: number\n testId: string\n}\n\n/** Fingerprint value, count, member refs, representative ref — the whole DTO (D-16). */\nexport interface AnalysisCluster {\n fingerprint: string\n count: number\n /** Ordered by `testIndex`, ascending — stable across calls and processes. */\n members: AnalysisClusterMember[]\n /** The highest-confidence member; equal confidence breaks to the LOWEST testIndex. */\n representative: { testIndex: number }\n}\n\ninterface GroupedMember extends AnalysisClusterMember {\n confidence: number\n}\n\n/**\n * Group resolved verdicts by failure fingerprint (D-14) — a total, deterministic pure\n * function. Identical fingerprints merge; the same anchor under two classes stays two\n * clusters (the recipe's `::class` suffix). Output order: occurrence count descending,\n * then fingerprint lexicographic byte order; members by testIndex ascending. Empty input\n * answers an empty list, never a throw.\n */\nexport function clusterVerdicts(\n resolvedVerdicts: readonly Verdict[],\n handoff: CompletedRunHandoff,\n): AnalysisCluster[] {\n const groups = new Map<string, GroupedMember[]>()\n for (const verdict of resolvedVerdicts) {\n const test = handoff.tests.find((candidate) => candidate.testIndex === verdict.perTest)\n // A verdict whose perTest names no member test still keys deterministically: no anchors,\n // empty error text — the fingerprint recipe is total over that too.\n const step = test === undefined ? undefined : failingStepOf(test)\n const anchors = step === undefined ? [] : exercisedAnchors(step)\n const fingerprint = failureFingerprint(\n { anchors, errorText: test === undefined ? '' : errorTextOf(step, test) },\n verdict.class,\n )\n const members = groups.get(fingerprint) ?? []\n members.push({\n testIndex: verdict.perTest,\n testId: test?.testId ?? '',\n confidence: verdict.confidence,\n })\n groups.set(fingerprint, members)\n }\n\n return [...groups.entries()]\n .map(([fingerprint, grouped]) => {\n const members = [...grouped].sort((left, right) => left.testIndex - right.testIndex)\n // Walking testIndex-ascending with a STRICT > keeps the first (lowest testIndex)\n // member on equal confidence — the D-15 tie-break, deterministic by construction.\n let representative = members[0] as GroupedMember\n for (const member of members) {\n if (member.confidence > representative.confidence) representative = member\n }\n return {\n fingerprint,\n count: members.length,\n members: members.map(({ testIndex, testId }) => ({ testIndex, testId })),\n representative: { testIndex: representative.testIndex },\n }\n })\n .sort((left, right) => (\n right.count - left.count\n || (left.fingerprint < right.fingerprint ? -1 : left.fingerprint > right.fingerprint ? 1 : 0)\n ))\n}\n","// Read-time presence for artifact refs — the ONE rule both durable reads call (Phase 406, D-17).\n//\n// `runs.detail` and `analysis.get` each hand a page a list of artifact refs, and neither could say\n// whether the bytes behind them still exist. A ref recorded at write time survives a GC, a pruned\n// run directory and a hand-deleted blob; a link drawn from it 404s on click, which reads to an\n// operator as a broken product rather than as collected evidence. So presence is asked at READ\n// time, in one place, and both ops annotate through this function.\n//\n// BOTH ABSENCES ARE `false`, AND THAT IS NOT A COLLAPSE OF THE D-15 SPLIT. `blob_absent` and\n// `unknown_run` stay two words at the port, because `runs.artifact` refuses differently for each.\n// Here the question is narrower — are the bytes there — and the answer is no either way. A page\n// rendering \"evidence incomplete\" has the same thing to say about a pruned run and a pruned blob.\n//\n// UNKNOWN LEAVES THE KEY ABSENT, WHICH IS THE WHOLE POINT (D-17). Presence unknown is not an\n// absence, and reporting `present: false` for refs this host never looked at would render honest,\n// intact evidence as incomplete. The refs come back untouched — copies, so a caller cannot mutate\n// the port's rows — and the page's `present === false` predicate stays false.\n//\n// THERE ARE TWO WAYS TO NOT KNOW, AND BOTH TAKE THE SAME EXIT. A port with no `has` never looked;\n// a `has` that REJECTED looked and did not come back. `present` is derived from an answer that is\n// in hand, never from a lookup miss — `answers.get(sha) === 'found'` would read the second case as\n// a claimed absence, which is the one answer this field must never give by accident.\n//\n// AND A REJECTED STAT IS NEVER A FAILED READ. Every surface reading this calls it opportunistic:\n// \"a host with no runtime root still serves a complete analysis\" (`analysis-get.ts`), \"this is not\n// a binding condition\" (`runs-detail.ts`), \"a host that cannot cheaply stat its blobs is not lying\n// about anything\" (`spec.ts`). A rejection escaping here throws out of `invoke` and the routes map\n// it to `read_failed` — an optional annotation taking down the whole run-detail page and the whole\n// failure view. The bundled local `existsSync` cannot throw, but the port is shaped for hosts that\n// do not hold blobs locally, i.e. hosts whose `has` is a network call.\n//\n// STATS ARE DEDUPED BY SHA WITHIN ONE CALL, AND ONE CALL IS ONE REF LIST — NOT ONE RUN (T-406-12).\n// `new Set(refs.map(...))` collapses the duplicates in the list it was handed, which is the refs\n// ONE verdict cites or the refs ONE sub-action produced. Both callers invoke this inside a\n// `Promise.all` — `analysis-get` per verdict, `runs-detail` per sub-action — so a 40-failure run\n// citing the same decision screenshot from every member still takes 40 stats, and a ref repeated\n// across a page's steps is stat'd once per step.\n//\n// THAT RESIDUAL IS RECORDED, NOT MITIGATED, and an earlier spelling of this note claimed the\n// opposite by citing exactly those two cross-call examples as things it collapsed. The fix, if it\n// ever needs one, is to hoist to one probe per read and join back by sha. It is not taken here:\n// v1 excludes performance work, the bundled `has` is a single `existsSync`, and the bound is\n// refs-per-member rather than refs-per-run. A note describing a mitigation the code does not\n// implement is worse than the syscalls, because the next reader budgets against it.\n\nimport type { EvidenceBlobPresence, RunId } from '@vostride/agent-qa-schema'\n\nimport type { EvidenceBlobReaderPort } from '../spec.js'\n\nexport async function annotatePresence<T extends { sha: string }>(\n port: EvidenceBlobReaderPort | undefined,\n runId: RunId,\n refs: readonly T[],\n): Promise<(T & { present?: boolean })[]> {\n const has = port?.has\n if (has === undefined) return refs.map((ref) => ({ ...ref }))\n\n const distinct = [...new Set(refs.map((ref) => ref.sha))]\n const answers = new Map<string, EvidenceBlobPresence | undefined>(\n await Promise.all(distinct.map(async (sha): Promise<[string, EvidenceBlobPresence | undefined]> => {\n // PER SHA, so one host that cannot answer about one blob costs presence on that blob only.\n // Absorbing at the `Promise.all` instead would lose every sibling answer already in hand.\n try {\n return [sha, await has.call(port, runId, sha)]\n } catch {\n return [sha, undefined]\n }\n })),\n )\n\n return refs.map((ref) => {\n const answer = answers.get(ref.sha)\n return answer === undefined ? { ...ref } : { ...ref, present: answer === 'found' }\n })\n}\n","// The D-12 quote cleaner: rendering noise out, meaning in (Phase 406, DETL-04).\n//\n// The 399 seeded-red sentence embedded Playwright's raw error verbatim — SGR escapes, a\n// \"Call log\" block, embedded newlines — inside `observed (step 1): \"…\"`, and it read as an\n// escape stream on the CLI, in 392's chat and on the run page alike. D-12 puts the cleaning in\n// the ONE renderer's quote leg (`groundingSegment`), so every surface inherits it through the\n// single code path rather than each sanitizing at its own boundary — two surfaces reading two\n// sentences for one verdict is the exact drift the decision rejects.\n//\n// WHY NOT `util.stripVTControlCharacters`. RESEARCH recommended Node's built-in stripper.\n// `packages/agent` is classed `storageNeutral`, and `PACKAGE_CLASS_RULES.storageNeutral`\n// forbids the WHOLE `node:` namespace (`packages/arch/src/contract-types.ts`), so\n// `validate:arch` would reject the import. The architecture rule wins; the coverage below\n// mirrors what the built-in strips — CSI (including SGR), OSC, the two-byte escape forms and\n// the remaining C0/C1 control characters — as pure ECMAScript regexes with no import at all.\n//\n// WHAT THIS IS NOT. It is not a masker. A declared `[secret:<name>]` marker and an old\n// `<SECRET_n>` placeholder are ordinary printable text here and cross byte-identical; masking\n// happens before anything is recorded (441 D-28). Sanitization also happens at RENDER time only,\n// never at authorship: `validateGroundingQuote` still checks the quote against the raw artifact bytes,\n// so a display rule can never reject a verdict that honestly quoted what was captured.\n\n/**\n * A CSI sequence: `ESC [`, parameter bytes, intermediate bytes, one final byte in `@`–`~`.\n *\n * This is the arm that carries SGR (`ESC[2m`, `ESC[22m`) and every cursor-movement form.\n */\nconst CSI_SEQUENCE = /\\u001b\\[[0-?]*[ -/]*[@-~]/g\n\n/**\n * An OSC sequence: `ESC ]` … terminated by BEL or by the `ESC \\` string terminator.\n *\n * Matched NON-greedily and stripped BEFORE the two-byte escape forms, whose final-byte range\n * includes `]` and would otherwise eat the introducer and leave the payload as literal text —\n * an OSC title-set surviving into a terminal print is the T-406-13 injection this closes.\n */\nconst OSC_SEQUENCE = /\\u001b\\][\\s\\S]*?(?:\\u0007|\\u001b\\\\)/g\n\n/** The two-byte `ESC <final>` forms (`ESC c`, `ESC (`, the C1 introducers), whatever remains. */\nconst ESCAPE_PAIR = /\\u001b[ -~]/g\n\n/**\n * Remaining C0 and C1 control characters — everything except `\\t`–`\\r`, which are WHITESPACE.\n *\n * The whitespace controls are deliberately spared here so the collapse below sees them: a\n * newline between two words must become the space that keeps them apart, not vanish and join\n * them into one token.\n */\nconst NON_WHITESPACE_CONTROL = /[\\u0000-\\u0008\\u000e-\\u001f\\u007f-\\u009f]/g\n\n/**\n * One quoted piece of producer text, made legible without changing what it says.\n *\n * Control sequences are removed and every whitespace run collapses to a single space, trimmed.\n * Nothing is truncated and nothing is reordered: each non-control word of the input survives,\n * in order, which is what lets a reader still recognise the locator in a Playwright timeout.\n */\nexport function sanitizeQuoteText(text: string): string {\n return text\n .replace(OSC_SEQUENCE, '')\n .replace(CSI_SEQUENCE, '')\n .replace(ESCAPE_PAIR, '')\n .replace(NON_WHITESPACE_CONTROL, '')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n","// The ONE deterministic sentence renderer (Phase 389, D-05/D-06/D-08).\n//\n// Every surface that shows a verdict sentence — plan 07's CLI print, M5's run page, 392's\n// chat — calls THIS function through the `analysis.get` op or directly, which is what makes\n// SC3's \"printed in CI and served through the function layer without a second code path\"\n// structural rather than a review rule. The renderer is a pure string composer in the\n// `renderChainTerminalLine` idiom (cli post-run-tail): no fs, no model, no store — absence\n// rendered as absence, never padded.\n//\n// Producer-keying (D-06) happens at AUTHORSHIP, and the renderer preserves it by composing\n// typed parts identically whoever authored them: `analyze-run` parts, the deterministic\n// template parts, and the honest root-cause-undetermined fallback all flow through this one\n// rule, so sentence EXISTENCE never depends on LLM availability.\n\nimport type {\n QuarantineLadderState,\n Verdict,\n VerdictSentenceParts,\n} from '@vostride/agent-qa-schema'\n\nimport { sanitizeQuoteText } from './quote-text.js'\n\n/**\n * The projection's key, spelled the way `run_test_outcomes` is keyed: stable test identity\n * is `(product, filePath, testName)` — NEVER `testId`, a per-run explicit id.\n *\n * 390 D-07 adds the FAILURE FINGERPRINT beside the identity, and the two legs answer two\n * different questions: recurrence is counted per `(product, fingerprint)` — the same failure\n * recurring, not the same test — while the quarantine ladder is keyed on the identity, which\n * is what the ledger records. A member with no failing step to key from (a zero-step failure)\n * omits the leg entirely rather than carrying a stand-in: a fabricated key would window a\n * failure against occurrences that are not its own.\n */\nexport interface RecurrenceQuery {\n readonly product: string\n readonly filePath: string\n readonly testName: string\n readonly fingerprint?: string\n}\n\n/**\n * The ladder rung this identity currently sits on (390 D-06/D-17), when it sits on one at all.\n *\n * `expiresAt` is the ISO deadline the ledger recorded. It is optional because `flagged` has no\n * deadline — flagging is visibility, not suppression — and because the ledger is committed text\n * a human may edit, so a recorded deadline is not guaranteed to parse.\n */\nexport interface RecurrenceLadder {\n readonly state: QuarantineLadderState\n readonly expiresAt?: string\n}\n\n/** Typed recurrence data in (\"Kth failure, window N\"); the renderer turns it into prose. */\nexport interface RecurrenceAnswer {\n readonly kth: number\n readonly windowBuilds: number\n /** Absent means this identity is on no rung — the clause is the occurrence count alone. */\n readonly ladder?: RecurrenceLadder\n}\n\n/**\n * The D-08 recurrence seam: recurrence context is a LIVE join at render time, resolved per\n * call through this provider — never baked into authored parts and never stored as prose.\n *\n * 389 bound this seam to v51's derived run-outcome projection (`readTestOutcomeHistory` +\n * `failureRecurrence`); 390-06 REBOUND the same seam at the same composition root to the\n * fingerprint-keyed recurrence window plus a per-call fold of the committed quarantine ledger,\n * which is what the ladder arms render. The seam itself did not change shape — the query gained\n * a fingerprint and the answer gained a rung. The author's prompt separately consumes failure\n * history as input-for-REASONING (plan 03's forced channel); this join is the rendered-CLAUSE\n * — two different things by decision.\n *\n * `undefined` means the provider has no history for this identity; the renderer answers\n * with an explicit no-history clause, so obligation c is always rendered, honestly.\n */\nexport interface RecurrenceProvider {\n failureRecurrence(query: RecurrenceQuery): RecurrenceAnswer | undefined\n}\n\n/** Between-segment separator; segment MARKERS (`observed`, `next:`, `see:`) do the locating. */\nconst SENTENCE_SEPARATOR = ' — '\n\n/**\n * Obligation a: the grounding quote with its ref. The `test-outcome` arm is the typed\n * alternative for zero-step failures — never a fabricated stepIndex.\n *\n * 406 D-12: the quote is cleaned HERE, in the one renderer, so the CLI print, 392's chat and\n * the run page read the same sentence through the single code path. `sanitizeQuoteText`\n * removes rendering noise only — no word is dropped, reordered or truncated — and it runs at\n * RENDER time, so `validateGroundingQuote` still holds the author to the raw captured bytes.\n */\nfunction groundingSegment(quote: VerdictSentenceParts['groundingQuote']): string {\n const text = sanitizeQuoteText(quote.quote)\n return 'stepIndex' in quote\n ? `observed (step ${quote.stepIndex}): \"${text}\"`\n : `observed (test outcome): \"${text}\"`\n}\n\n/** Month names, spelled here so the rendered deadline never depends on a host locale. */\nconst EXPIRY_MONTHS = [\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\n] as const\n\n/**\n * A recorded deadline as a short human date, in UTC.\n *\n * UTC rather than local time because the same sentence is rendered in CI, on a laptop and in\n * a dashboard, and a deadline that reads `Sep 4` in one place and `Sep 3` in another is a\n * deadline nobody can quote. An UNPARSEABLE value is shown VERBATIM: the ledger is committed\n * text a human may hand-edit (D-12), the fold already treats such an entry as lapsed, and\n * quoting what the file actually says is what lets the human find the line they broke.\n */\nfunction expiryPhrase(expiresAt: string | undefined): string {\n if (expiresAt === undefined) return 'an unrecorded date'\n const parsed = Date.parse(expiresAt)\n if (Number.isNaN(parsed)) return expiresAt\n const at = new Date(parsed)\n return `${EXPIRY_MONTHS[at.getUTCMonth()]} ${at.getUTCDate()}`\n}\n\n/**\n * D-17's locked clause structure, as a TOTAL table over the ladder vocabulary.\n *\n * `satisfies Record<QuarantineLadderState, …>` is the load-bearing part: a fourth ladder state\n * cannot compile until someone decides how it reads to a human. The alternative — a switch with\n * a default, or an `if` chain — would have rendered a future state as the bare occurrence count,\n * which is the one wrong answer here (a suppressed test whose sentence never says so).\n *\n * D-17's scope note is why only the deadline appears: expiry is the one detail that changes what\n * a reader does next. Owner and entry history live in the list verb and the entity card.\n */\nconst LADDER_CLAUSE_SUFFIXES = {\n flagged: () => '; suspected flaky',\n quarantined: (expiresAt) => `; quarantined until ${expiryPhrase(expiresAt)}`,\n expired: (expiresAt) =>\n `; quarantine expired ${expiryPhrase(expiresAt)} — failures count again`,\n} as const satisfies Record<QuarantineLadderState, (expiresAt: string | undefined) => string>\n\n/** The clause's fourth arm: absence. No rung means no suffix, not an empty-looking one. */\nfunction ladderSuffix(ladder: RecurrenceLadder | undefined): string {\n return ladder === undefined ? '' : LADDER_CLAUSE_SUFFIXES[ladder.state](ladder.expiresAt)\n}\n\n/**\n * Obligation c, always present: live data becomes prose, and every absence is an EXPLICIT\n * clause rather than a dropped segment — a sentence whose recurrence section silently\n * vanished would read as \"no history\" without ever saying so.\n *\n * The ladder suffix (390 D-17) rides ONLY the occurrence-count arm. Both honest-absence\n * clauses and the kth-0 clause stay byte-identical to 389 whatever the ladder says, because\n * \"no failure history is recorded for this test\" is the answer to the question actually asked,\n * and a quarantine note appended to it would trade an explicit absence for a partial answer.\n * A reader who needs the owner, the deadline or the entry history has `quarantine.list` and\n * the entity card, both of which enumerate entries the projection has no history for.\n */\nfunction recurrenceClause(answer: RecurrenceAnswer | undefined): string {\n if (answer === undefined || answer.windowBuilds === 0) {\n return 'no failure history is recorded for this test'\n }\n if (answer.kth === 0) {\n return `no prior failure of this test is recorded in the last ${answer.windowBuilds} builds`\n }\n return `failure ${answer.kth} of this test in the last ${answer.windowBuilds} builds`\n + ladderSuffix(answer.ladder)\n}\n\n/**\n * Compose one verdict's sentence from its typed parts (D-05).\n *\n * Fixed order: resolved-class frame, the quoted grounding observation with its step ref,\n * the discriminator, the recurrence clause (joined LIVE through `provider`), the\n * recommended next action, and the `agentqa://` links (rendered verbatim from\n * `parts.links`, already codec-validated at the artifact boundary; an empty list renders\n * no see-section). Byte-deterministic: the same (verdict, parts, provider answer) yields\n * the same string in every process.\n */\nexport function renderVerdictSentence(\n verdict: Verdict,\n parts: VerdictSentenceParts,\n provider: RecurrenceProvider | undefined,\n query: RecurrenceQuery,\n): string {\n const answer = provider?.failureRecurrence(query)\n const segments = [\n `${verdict.class}: ${groundingSegment(parts.groundingQuote)}`,\n parts.discriminator,\n recurrenceClause(answer),\n `next: ${parts.nextAction}`,\n ...(parts.links.length === 0 ? [] : [`see: ${parts.links.join(', ')}`]),\n ]\n return segments.join(SENTENCE_SEPARATOR)\n}\n","import type { CurationSnapshot } from '@vostride/agent-qa-schema'\n// The five real agent job kinds (Phase 385, D-09 / D-17 / D-18 / D-20).\n//\n// The kind set is closed and shipped, and this module declares every member of it. The\n// declarations are the CONTRACT this phase ships; the handler bodies are deterministic\n// stand-ins, and the two are not the same kind of thing. Real semantics for analyze-run and\n// curate-memory arrive with the phases that own them — what has to exist now is a complete,\n// registry-driven description of how each kind checkpoints, chains, retries and gives up,\n// because the crash matrix iterates THAT rather than a list of its own.\n//\n// The stand-ins are scripted by payload, in the style of the v51 drain fixture's scripted\n// author: a handler publishes its own declared schedule with its own bytes and then does\n// exactly what the payload asked for. That matters for two separate reasons. Distinguishable\n// bytes mean a matrix comparing five recovered histories is comparing five different things\n// rather than five copies of one. Scriptable outcomes mean the adversarial legs — a chain, a\n// retryable report, a permanent one — can be driven through the REAL kinds instead of through\n// a synthetic stand-in that a later refactor could leave behind.\n//\n// Deliberately absent from every published byte: the attempt number and any timestamp. A\n// checkpoint whose bytes changed with the attempt that wrote it would make an interrupted\n// history differ from an uninterrupted one for a reason that has nothing to do with recovery,\n// and the usual repair for a failing equality assertion is to loosen it.\n\nimport type { ReplayGatePort } from '../ports/gates.js'\nimport type {\n ChainedJobRequest,\n CompletedRunHandoff,\n ExecutionContext,\n GateReceipt,\n GateVerdict,\n JobHandlerOutcome,\n JobKind,\n KnowledgeBundleSummary,\n KnowledgeGatesListResult,\n MisdirectionRecordResult,\n MisdirectionRootPosture,\n PerTestOutcome,\n RunAnalysisArtifact,\n RunNotificationVerdictSummary,\n Verdict,\n VerdictGroundingQuote,\n VerdictSentenceParts,\n} from '@vostride/agent-qa-schema'\nimport {\n asRecordId,\n canonicalJson,\n CURRENT_ANALYSIS_SCHEMA_VERSION,\n CurationSnapshotSchema,\n errorTextOf,\n failingStepOf,\n MisdirectionRecordResultSchema,\n RunNotificationSchemaError,\n sha256hex,\n slugBranch,\n stepOutcomeUnproven,\n validateAnalysisAgainstHandoff,\n} from '@vostride/agent-qa-schema'\nimport type { JobCheckpointReadOutcome } from '../ports/job-store.js'\nimport { deterministicVerdict, UNKNOWN_SIGNAL_RATIONALE } from '@vostride/agent-qa-runner'\n\nimport {\n authorRunAnalysis,\n flippedRecordsOf,\n misdirectionValidationOptions,\n stampVerdictMisdirectionEvidence,\n} from './analyze-run-author.js'\nimport { UNKNOWN_VERDICTS_MARKER } from './chain-identity.js'\nimport { buildEvidencePacks } from './evidence-diet.js'\nimport type { EvidenceHistoryLookup } from './evidence-diet.js'\nimport { createJobKindRegistry } from './kind-registry.js'\nimport type {\n FallbackContinuationInput,\n JobHandler,\n JobHandlerContext,\n JobKindDeclaration,\n JobKindRegistry,\n} from './kind-registry.js'\n\n/**\n * What a stand-in handler will do, as read off the payload it was handed.\n *\n * Every field is optional and an absent field means the ordinary path, so a caller that knows\n * nothing about this module gets a job that publishes its schedule and completes.\n */\nexport interface StandInJobScript {\n /** Chain to every successor the kind declares. */\n readonly chain?: boolean\n /** Report a failure instead of completing. */\n readonly fail?: 'retryable' | 'permanent'\n readonly reason?: string\n}\n\nfunction readScript(payload: unknown): StandInJobScript {\n if (typeof payload !== 'object' || payload === null) return {}\n const record = payload as Record<string, unknown>\n const fail = record.fail === 'retryable' || record.fail === 'permanent' ? record.fail : undefined\n return {\n chain: record.chain === true,\n fail,\n reason: typeof record.reason === 'string' ? record.reason : undefined,\n }\n}\n\n/**\n * The successor instances a kind produces, derived from the predecessor's id.\n *\n * The key is derived rather than minted so the same logical continuation carries the same key\n * in every process and on every replay — which is what makes re-running a chain after a crash\n * a dedupe instead of a second job.\n */\nfunction successorsOf(\n declaration: Pick<JobKindDeclaration, 'kind' | 'allowedSuccessors'>,\n jobId: string,\n extra: Record<string, unknown> = {},\n): readonly ChainedJobRequest[] {\n return declaration.allowedSuccessors.map((successor) => ({\n kind: successor,\n payload: { from: declaration.kind, predecessor: jobId, ...extra },\n idempotencyKey: `${jobId}->${successor}`,\n }))\n}\n\nfunction standInHandler(\n kind: JobKind,\n checkpointSchedule: readonly string[],\n allowedSuccessors: readonly JobKind[],\n): JobHandler {\n return async (context) => {\n const script = readScript(context.payload)\n let step = 0\n for (const checkpointId of checkpointSchedule) {\n await context.publishCheckpoint(checkpointId, {\n kind,\n checkpointId,\n step,\n jobId: String(context.job.id),\n })\n step += 1\n }\n if (script.fail !== undefined) {\n return { status: script.fail, reason: script.reason ?? `${kind} stand-in scripted failure` }\n }\n return {\n status: 'complete',\n next: script.chain === true ? [...successorsOf({ kind, allowedSuccessors }, String(context.job.id))] : [],\n }\n }\n}\n\n/**\n * analyze-run's ratified disposition: the chain proceeds with unknown verdicts (spec §1.2).\n *\n * Its downstream jobs must never wait on a dead head, so a permanently failed analysis hands\n * them the same successors a successful one would, marked as carrying no verdicts. Nothing\n * here reaches a model, and nothing here can: what it is given is the failed job, the payload\n * that job was handed, and the reason.\n *\n * \"The same successors a successful one would\" is true by construction: this fallback maps\n * over the one successor constant below, the same list the success path's `next`, the scripted\n * stand-in and the declaration itself all read. Declared equals produced, so a dead analysis\n * hands on exactly what a live one would and no path can enqueue what the topology never declared.\n *\n * 2026-09-01 (Phase 409): the reserved sixth kind left with the Issue-slot cleanup, and 388\n * D-04's declared/produced split collapsed with it.\n *\n * The extra carries the run's identity and posture forward for the same reason the success\n * path does (Pitfall 6): the successor may be claimed by the daemon, which resolves posture\n * from `payload.executionContext` (386 D-09/D-12), and curation cannot fold a run directory\n * it was never told about. The unknown-verdicts marker travels with them so the chain\n * terminal can report the analysis stage honestly from a job that succeeded afterwards.\n */\nfunction analyzeRunFallback(input: FallbackContinuationInput): readonly ChainedJobRequest[] {\n const payload = asRecord(input.payload)\n return successorsOf(\n { kind: 'analyze-run', allowedSuccessors: ANALYZE_RUN_SUCCESSORS },\n String(input.job.id),\n {\n ...(typeof payload.runId === 'string' ? { runId: payload.runId } : {}),\n ...(payload.executionContext === undefined\n ? {}\n : { executionContext: payload.executionContext }),\n verdicts: UNKNOWN_VERDICTS_MARKER,\n failureReason: input.reason,\n },\n )\n}\n\nconst ANALYZE_RUN_SUCCESSORS = ['curate-memory'] as const satisfies readonly JobKind[]\n\n/**\n * The 422 D-13 edge, declared once and read by the declaration, the real handler and the\n * scripted stand-in alike — the same declared-equals-produced discipline the analyze-run edge\n * above rests on. `propose-improvements` is a kind this build has declared since 385; what this\n * constant adds is the successor relation that finally reaches it.\n */\n//\n// 2026-09-12, 422-22: stated as `as const satisfies readonly JobKind[]` rather than annotated,\n// so the literal members survive into the type. An annotation widens the entries to `JobKind`\n// and the edge stops being visible to anything reading the constant — which is the same D-22\n// bar every other closed set in this milestone is held to.\nconst CURATE_MEMORY_SUCCESSORS = ['propose-improvements'] as const satisfies readonly JobKind[]\n\n/**\n * The host powers the two real post-run handlers need, injected by the composition (D-01).\n *\n * Both are things `agent` cannot do and must never learn to: reading a file is a host API in\n * a storageNeutral package, and the curation drain lives two packages away behind the writer\n * lease. Passing them as capabilities is what lets the handler bodies be real here while the\n * bindings stay where the ownership is — and it is also the seam a test uses to drive the\n * chain without a knowledge root.\n *\n * The whole interface is OPTIONAL at construction. A registry built without it keeps the\n * scripted stand-ins byte-identically, because several shipped suites — engine semantics,\n * kind registry, the kill matrix — drive the REAL kinds by scripting their payloads, and a\n * build where those kinds could only do real work would have no way to express \"chain here,\n * fail permanently there\" without a knowledge root and a run directory per case.\n */\nexport interface PostRunJobCapabilities {\n /**\n * The run's persisted handoff, addressed by `runId` alone.\n *\n * Hard-fails typed on a missing or malformed document rather than answering `undefined`:\n * D-06 makes the PATH derived and the BYTES pinned, so \"there is no handoff for this run\"\n * is a permanent condition of that run, never a transient one worth retrying.\n */\n loadCompletedRunHandoff(runId: string): CompletedRunHandoff\n /**\n * The per-run fold, and the fold's own report of whether it FINISHED (WR-03).\n *\n * `complete` is not a nicety on the side of the counts: the v51 fold answers `false` for\n * candidate refusals, a cap exceeded, unresolved canaries, a failed outcome projection and\n * requeues, and in every one of those cases it writes NO receipt so the run refolds later.\n * Both production bindings used to return the counts alone, which is how a fold that refused\n * became a stage the durable notification row called `done` — the one place in this phase\n * where the record overstated what happened. It is part of the contract precisely so a\n * binding cannot drop it silently: omit it and the binding stops typechecking.\n */\n curateRun(input: {\n readonly runId: string\n readonly executionContext: unknown\n readonly deadlineMs?: number\n }): Promise<{\n readonly curated: number\n readonly deprecated: number\n readonly complete: boolean\n readonly snapshot?: CurationSnapshot\n /**\n * The candidates the fold's own receipt names, forwarded to the proposal stage (422 D-13).\n *\n * ADDITIVE-OPTIONAL rather than required, on this module's existing tolerance idiom, and the\n * distinction is carried through rather than flattened: ABSENT means the binding reported no\n * candidate ids at all, while `[]` means it reported that there were none. A required field\n * would have forced every host and every harness that scripts a fold to invent a value for a\n * question they are not the authority on — and the first thing a host invents here is `[]`,\n * which is the one answer that is indistinguishable from a real empty fold.\n */\n readonly candidateIds?: readonly string[]\n /** 2026-10-16 (442-10, D-17): why a fold that did not complete handed its run back. */\n readonly reason?: string\n }>\n /**\n * Put one run's analysis artifact durably on disk (389 D-09).\n *\n * Called INSIDE the author callback, before the verdicts-authored value is recorded — the\n * authorship primitive records only after the callback returns, so by the time any chip can\n * read `done` the sentence is already fetchable. Authored never overstates. The binding is\n * the host's (`agent-local` derives the path from `runId` the same way it derives the\n * handoff's — a job payload never carries a path); a synchronous throw here propagates out\n * of the author, no checkpoint is recorded, and the declared bound adjudicates the retry.\n */\n persistAnalysis(artifact: RunAnalysisArtifact): void\n /**\n * One test's recorded outcome history, keyed the projection's way — `product` =\n * `slugBranch(scope.key)` plus the stable test identity `filePath` + `testName`, NEVER\n * `testId` (389 plan 02's key law). Feeds D-02's forced prior-build channel and the\n * author's failure-history reasoning input. OPTIONAL: production hosts bind\n * knowledge-local's `readTestOutcomeHistory` in plan 06; unbound, the author runs with a\n * typed no-history diet — degraded, never a crash.\n */\n readTestHistory?(query: {\n readonly product: string\n readonly filePath: string\n readonly testName: string\n }): TestOutcomeHistoryLike | undefined\n /**\n * D-01's TokenAccounting substrate entering as DATA — the estimator and input budget the\n * author's compaction ladder walks against. OPTIONAL: plan 06 binds it from the same\n * profile resolution as the job model; unbound, the packs travel whole (no ladder) and\n * the model call carries whatever they weigh.\n */\n analysisTokenBudget?: {\n readonly estimate: (text: string) => number\n readonly inputBudget: number\n }\n /**\n * D-02's capability-gated screenshot bytes: the CASS-02 evidence-blob store read,\n * sha-addressed within one run's directory. OPTIONAL: plan 06 binds it at the production\n * hosts; unbound — or with a model that does not advertise vision — the author's request\n * is text-only, the L9 graceful degradation, never an error.\n */\n readEvidenceBlob?(runId: string, sha: string): Uint8Array | undefined\n /**\n * 2026-09-12, 422 D-19: which evaluation-root posture this run's circularity evidence was\n * produced under.\n *\n * The rows themselves cannot answer it. An ABSENT root and a BROKEN one both publish the same\n * empty ledger — that is precisely why 422-14 records the posture in its own durable file —\n * and only the first earns `backing: 'declared-only'`. Reading that file is a host API, so the\n * posture arrives here as a capability rather than as something this package learns to look up.\n *\n * OPTIONAL, and unbound is FAIL-CLOSED rather than permissive: a run whose posture nobody can\n * state is treated as an ordinary `'eval-root'`, which is 422-11's own default and which makes\n * an empty ledger an unresolved cross-check rather than a BYOM exemption. A throw is read the\n * same way — a posture this process could not obtain is not a posture it may assume.\n */\n readMisdirectionRootPosture?(runId: string): MisdirectionRootPosture | undefined\n /**\n * 2026-09-07, 417 D-18: typed now, bound nowhere in 417. Phase 422's\n * propose-improvements binds this seam; the five-kind chain is untouched.\n *\n * 2026-09-11, 422 D-14: the proposal stage CALLS it. Its resolved receipt means the writer\n * acknowledged persisting one (`ReplayGatePort`'s own contract) — anything else throws, and\n * the handler reads the throw as a charged slot with an unknown outcome rather than as a\n * screening result it may record.\n */\n runReplayGate?: ReplayGatePort['runReplayGate']\n /**\n * Every committed bundle, as the reader entry's listing row (422 D-14).\n *\n * Structurally `KnowledgeReaderPort['listBundles']`, declared here rather than imported so this\n * module keeps naming only schema DTOs. OPTIONAL: unbound, the Gate-1 leg is a typed no-op.\n */\n listBundles?(): Promise<readonly KnowledgeBundleSummary[]>\n /**\n * One record's gate history, standing evidence and live verdict (422 D-14).\n *\n * The SELECTION reads this, not a store: a candidate is ungated when it carries no standing\n * Gate-1 line under the current corpus digest, and that question is answerable from the\n * committed receipts alone. OPTIONAL on the same terms as the listing.\n */\n gateReceiptsFor?(input: { readonly candidateId: string }): Promise<KnowledgeGatesListResult>\n /**\n * Which corpus this product's Gate-1 evidence is currently measured against (422 D-14).\n *\n * The digest is what makes a standing receipt a DECISION rather than a historical note: a\n * receipt produced against a corpus that has since moved decided a different question. A\n * posture that cannot resolve — a broken root, an unreadable floor — completes the stage\n * `posture-unavailable` and spends nothing, which is a report rather than a retry loop.\n */\n readProposeCorpusPosture?(input: {\n readonly product: string\n }): Promise<ProposeCorpusPosture>\n /**\n * This job's durable Gate-1 charge, read back from the authoritative checkpoint (422 D-14).\n *\n * NARROW on purpose: one checkpoint, addressed by this job's own id, read-only. The handler is\n * not handed a store, a checkpoint reader or a path — the composition that owns the store binds\n * this one question, and `parseProposeGate1Allowance` below is the shape check it binds through.\n */\n readProposeGate1Allowance?(jobId: string): Promise<ProposeGate1AllowanceRead>\n /**\n * The operator's `eval.gate1.maxPerJob` override, already resolved by the host (422 D-14).\n *\n * DATA rather than a reader, because the handler must not learn to read configuration. Absent\n * means the recorded default, and the difference is disclosed on the charge as `cap.source` so\n * a reader can tell a deliberate bound from an inherited one.\n */\n proposeGate1MaxPerJob?: number\n /**\n * The third stage's work, as a NEUTRAL optional port (422 D-13).\n *\n * Optional on exactly the terms `readTestHistory` and `readEvidenceBlob` are: a host that does\n * not bind it is not a broken host, it is a host that stages nothing. The stage still RUNS —\n * it publishes its checkpoint, lands `done` and terminates the chain — and the record then\n * reports a proposal stage that reached the port and proposed nothing, with no counts at all.\n * That is a different sentence from `proposed: 0`, and the counts are omitted precisely so the\n * two cannot be confused.\n *\n * Neutral in the same sense the two real handlers' other capabilities are: it names no store,\n * no knowledge root and no model. The adversarial staging itself lives two packages away\n * behind an operator admission seam this package may not reach, and binding it here would be\n * the import edge the architecture refuses.\n */\n stageAdversarialProposal?(input: {\n readonly runId: string\n readonly executionContext: ExecutionContext | undefined\n readonly candidateIds: readonly string[]\n readonly upstream: ProposeImprovementsUpstream\n }): Promise<{ readonly proposed: number; readonly skipped: number }>\n}\n\n/**\n * The minimal structural mirror of knowledge-local's `TestOutcomeHistory` row (389 plan 02).\n *\n * Declared HERE rather than imported because the dependency points the other way — this\n * package never names knowledge-local — and structural typing makes the real\n * `readTestOutcomeHistory` record assignable unchanged at the plan 06 binding. It also\n * matches `evidence-diet.ts`'s `EvidenceTestHistory` member-for-member, so one capability\n * answer feeds both the diet's prior-build channel and the author's reasoning input.\n */\nexport interface TestOutcomeHistoryLike {\n readonly passes: number\n readonly failures: number\n readonly heals: number\n readonly flakeCount: number\n readonly lastOutcomes: readonly { readonly buildOrdinal: number; readonly passed: boolean }[]\n readonly lastBuildOrdinal: number | undefined\n}\n\n/**\n * The claim shape analyze-run is enqueued with (D-06). Anything else is unreadable input.\n *\n * The two markers below are ADDITIVE-OPTIONAL (393 D-20, WTST-06): the enqueue site copies them\n * from the loaded handoff, and every job already sitting in a durable queue predates them. They\n * are queue-level VISIBILITY, never integrity — the digest field above already covers the\n * handoff bytes these values also live inside, so a consumer that needs the authoritative\n * answer reads the handoff, not this copy.\n */\nexport interface AnalyzeRunPayload {\n readonly runId: string\n readonly handoffDigest: string\n readonly handoffSchemaVersion: number\n readonly executionContext: ExecutionContext | undefined\n /**\n * D-10's verify-before-present gate-run marker, mirroring the handoff carrier's `?: true`\n * idiom. A DISTINCT axis from `excludedFromOutcomes` — C8 ratified that gate runs DO feed\n * curation, so neither marker may be read as implying the other.\n */\n readonly gateRun?: true\n /** D-14 §6's outcome-exclusion marker, same carrier idiom, same literal-only rule. */\n readonly excludedFromOutcomes?: true\n /**\n * 422 D-17/D-18: the pre-enqueue arbiter's per-record cross-check rows, copied off the same\n * handoff `handoffDigest` names (422-14's enqueue site).\n *\n * ABSENT is not EMPTY here either: absent means the arbiter never ran (every job queued before\n * 422-14), `[]` means it ran and recorded nothing. The copy is VISIBILITY, exactly as the two\n * markers above are — the handoff is what the digest covers, so the handler reads its authority\n * off the loaded document and uses this copy only to notice a queue row that disagrees with the\n * bytes it points at.\n */\n readonly misdirectionEvidence?: readonly MisdirectionRecordResult[]\n /**\n * Set when the key was PRESENT and this build could not read it.\n *\n * Deliberately not folded into absence, on 422-08's `unreadable`-is-not-`absent` rule. Absence\n * says the arbiter never ran and turns the gate off; an unreadable claim says a producer wrote\n * something this build cannot check, and degrading that to \"never ran\" would silently disarm\n * the guard for exactly the payload that most deserves it. The handler refuses instead.\n */\n readonly misdirectionEvidenceUnreadable?: true\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n}\n\n/**\n * Deliberately NOT `AnalyzeRunPayloadSchema`, and deliberately additive-tolerant.\n *\n * This reader consumes payloads off a DURABLE queue, where a job may have been written by an\n * older build (no flags at all) or a newer one (a key this build has never heard of). Refusing\n * either would strand work rather than protect anything, so unknown keys stay ignored and only\n * the literal marker is read — a `false` on the wire degrades to absence rather than becoming a\n * third state a downstream `!== undefined` could misread. The strict half of the contract lives\n * on the PRODUCER side, at the enqueue mint, where a bad shape means a bug in code that just ran\n * and the refusal is actionable.\n *\n * Exported for the reader-arm suite: `analyze-run-payload-flags.test.ts` pins both generations\n * of the payload here and then re-enters through the real handler, so the direct cases cannot\n * quietly stop describing what the handler actually parses.\n */\nexport function readAnalyzeRunPayload(value: unknown): AnalyzeRunPayload | undefined {\n const record = asRecord(value)\n if (typeof record.runId !== 'string' || record.runId === '') return undefined\n if (typeof record.handoffDigest !== 'string' || record.handoffDigest === '') return undefined\n if (typeof record.handoffSchemaVersion !== 'number') return undefined\n return {\n runId: record.runId,\n handoffDigest: record.handoffDigest,\n handoffSchemaVersion: record.handoffSchemaVersion,\n executionContext:\n typeof record.executionContext === 'string'\n ? (record.executionContext as ExecutionContext)\n : undefined,\n ...(record.gateRun === true ? { gateRun: true as const } : {}),\n ...(record.excludedFromOutcomes === true\n ? { excludedFromOutcomes: true as const }\n : {}),\n ...readCarriedMisdirectionEvidence(record.misdirectionEvidence),\n }\n}\n\n/**\n * The additive-optional circularity copy, read the way this module reads every durable payload\n * member — tolerantly about GENERATION, strictly about SHAPE.\n *\n * An absent key is an older producer and stays absent. A present key whose rows all parse is\n * carried verbatim. A present key that does not parse is neither dropped nor guessed at: it is\n * marked unreadable, and the handler turns that into a permanent refusal. Dropping it would be\n * the one failure this whole block exists to prevent — a gated run quietly re-read as a\n * historical one, whose no-trust-change verdict is then accepted on its own word.\n */\nfunction readCarriedMisdirectionEvidence(\n value: unknown,\n): Pick<AnalyzeRunPayload, 'misdirectionEvidence' | 'misdirectionEvidenceUnreadable'> {\n if (value === undefined) return {}\n if (!Array.isArray(value)) return { misdirectionEvidenceUnreadable: true as const }\n const rows: MisdirectionRecordResult[] = []\n for (const candidate of value) {\n const parsed = MisdirectionRecordResultSchema.safeParse(candidate)\n if (!parsed.success) return { misdirectionEvidenceUnreadable: true as const }\n rows.push(parsed.data as MisdirectionRecordResult)\n }\n return { misdirectionEvidence: rows }\n}\n\n/**\n * What the two earlier stages already did, carried forward to the third (422 D-13).\n *\n * Every member is OPTIONAL and every absence is a real, different situation rather than a\n * default: no `analysisStatus` means this payload does not say what became of the analysis, and\n * no `curation` means it does not say what the fold committed. The terminal builder reads the\n * absences as absences — it never fills them with zeros — because this block exists precisely so\n * the record can report stages the finishing job did not run, and a block that guessed would be\n * a more confident lie than saying nothing.\n */\nexport interface ProposeImprovementsUpstream {\n readonly verdictSummary?: RunNotificationVerdictSummary\n readonly analysisStatus?: 'done' | 'failed'\n readonly curation?: {\n readonly curated?: number\n readonly deprecated?: number\n readonly complete?: true\n readonly curationSnapshot?: CurationSnapshot\n }\n}\n\n/**\n * The claim shape propose-improvements is enqueued with (422 D-13).\n *\n * `runId` is the only member the stage cannot work without, and it is also what makes the job a\n * RUN's chain member at all — the engine decides a chain terminal on it. Everything else\n * degrades: `candidateIds` to the empty list, `upstream` to a block that claims nothing.\n */\nexport interface ProposeImprovementsPayload {\n readonly runId: string\n readonly executionContext: ExecutionContext | undefined\n readonly candidateIds: readonly string[]\n readonly upstream: ProposeImprovementsUpstream\n}\n\n/**\n * Additive-tolerant, on exactly `readAnalyzeRunPayload`'s terms and for the same reason.\n *\n * These bytes come off a DURABLE queue: a job may have been written by an older build that had\n * no `upstream` block, or a newer one carrying a key this build has never heard of. Refusing\n * either would strand committed curation behind an unrunnable stage, so unknown keys are ignored\n * and unreadable members degrade to absence. The strict half of the contract lives on the\n * PRODUCER side — `realCurateMemoryHandler` below, where a bad shape means a bug in code that\n * just ran and the refusal is actionable.\n *\n * A non-string candidate id is DROPPED rather than stringified: an id this build cannot read is\n * not an id it may invent, and a `String(undefined)` reaching the staging port would address a\n * candidate that does not exist.\n */\nexport function readProposeImprovementsPayload(\n value: unknown,\n): ProposeImprovementsPayload | undefined {\n const record = asRecord(value)\n if (typeof record.runId !== 'string' || record.runId === '') return undefined\n\n const upstreamSource = asRecord(record.upstream)\n const curationSource = asRecord(upstreamSource.curation)\n const summary = asRecord(upstreamSource.verdictSummary)\n const snapshot = curationSource.curationSnapshot === undefined\n ? undefined\n : CurationSnapshotSchema.safeParse(curationSource.curationSnapshot)\n if (snapshot !== undefined && !snapshot.success) {\n throw new RunNotificationSchemaError('its curation snapshot is invalid')\n }\n const curation = {\n ...(isCount(curationSource.curated) ? { curated: curationSource.curated } : {}),\n ...(isCount(curationSource.deprecated) ? { deprecated: curationSource.deprecated } : {}),\n ...(curationSource.complete === true ? { complete: true as const } : {}),\n ...(snapshot?.success ? { curationSnapshot: snapshot.data } : {}),\n }\n\n return {\n runId: record.runId,\n executionContext:\n typeof record.executionContext === 'string'\n ? (record.executionContext as ExecutionContext)\n : undefined,\n candidateIds: Array.isArray(record.candidateIds)\n ? record.candidateIds.filter((id): id is string => typeof id === 'string')\n : [],\n upstream: {\n ...(isCount(summary.total)\n ? { verdictSummary: summary as unknown as RunNotificationVerdictSummary }\n : {}),\n ...(upstreamSource.analysisStatus === 'done' || upstreamSource.analysisStatus === 'failed'\n ? { analysisStatus: upstreamSource.analysisStatus }\n : {}),\n ...(Object.keys(curation).length === 0 ? {} : { curation }),\n },\n }\n}\n\n/** Non-negative whole numbers only — the counts idiom this module shares with the record. */\nfunction isCount(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0\n}\n\n/**\n * A permanent report, phrased once.\n *\n * Every unreadable-input path below is PERMANENT rather than retryable, and that is A1 rather\n * than pessimism: a payload whose shape is wrong, a handoff that is not there, bytes that\n * drifted — none of them becomes right on a second attempt, and retrying them would spend a\n * bound the poison-job case needs.\n */\nfunction permanently(reason: string): JobHandlerOutcome {\n return { status: 'permanent', reason }\n}\n\n/**\n * Members whose outcome is worth a root-cause verdict.\n *\n * The complement of the runner's own presence rule (373-07): clean passes, skipped and\n * cancelled members are not failures to explain. Everything else gets a verdict, which is\n * what keeps the checkpoint's array in step with what the analysis chip claims to cover.\n */\nfunction needsVerdict(test: PerTestOutcome): boolean {\n return test.outcome !== 'passed' && test.outcome !== 'skipped' && test.outcome !== 'cancelled'\n}\n\n/**\n * The D-02 bridge: PROJECT the verdicts the runner already persisted; never re-classify.\n *\n * Re-running the classifier here is not merely redundant, it is impossible to do faithfully —\n * it reads `TestResult.retryCount`, which `PerTestOutcome` deliberately does not carry, so a\n * handler that \"re-classified\" would be classifying from strictly less evidence and quietly\n * disagreeing with the verdict already on disk. An absent verdict is filled with the same\n * 'unknown' the classifier itself mints, so the array covers every failed member and 389 can\n * supersede exactly the ones that carry no signal.\n */\nfunction projectHandoffVerdicts(handoff: CompletedRunHandoff): Verdict[] {\n return handoff.tests\n .filter(needsVerdict)\n .map((test) => test.rootCause ?? deterministicVerdict(\n 'unknown',\n UNKNOWN_SIGNAL_RATIONALE,\n [],\n test.testIndex,\n ))\n}\n\n/** Per-class counts, carried forward so the chain terminal can report them without a re-read. */\nfunction summarizeVerdicts(verdicts: readonly Verdict[]): {\n total: number\n byClass: Partial<Record<Verdict['class'], number>>\n} {\n const byClass: Partial<Record<Verdict['class'], number>> = {}\n for (const verdict of verdicts) {\n byClass[verdict.class] = (byClass[verdict.class] ?? 0) + 1\n }\n return { total: verdicts.length, byClass }\n}\n\n/**\n * The one concrete next action a template sentence names, total over the verdict union\n * (389 D-06). A `Record` rather than an if-chain so an added class is a compile error here,\n * not an uncovered row — the 388-11 `postureOf` discipline.\n */\nconst TEMPLATE_NEXT_ACTION: Record<Verdict['class'], string> = {\n test_bug: 'update the test to match the behaviour the app now has',\n app_bug: 'file the failure against the application with the quoted evidence',\n environment: 'check the environment or infrastructure dependency the run relied on',\n flake: 'watch for recurrence before changing the test or the app',\n config_error: 'fix the run configuration the signal names',\n llm_error: 'retry the run; the failure originated in the model pipeline, not the app',\n unknown: 'inspect the run manually — no deterministic signal matched',\n timeout: 'investigate the slow dependency or raise the step timeout deliberately',\n}\n\n/**\n * A verbatim quote of captured evidence for one member test (389 D-06).\n *\n * Step selection and error-text precedence come from schema's ONE exported input rule\n * (`failingStepOf`/`errorTextOf`, hoisted by 390 plan 02): the first failed step else the last,\n * then the first sub-action error text else the verifier's own reasoning. This quote and the\n * fingerprint window are now the SAME rule by construction rather than by parallel maintenance.\n * A test that captured ZERO steps quotes its test-level outcome through the typed no-step arm —\n * never a fabricated stepIndex. Every branch quotes bytes the run actually recorded; templates\n * assemble around the quote, the quote itself is never authored.\n */\nfunction templateGroundingQuote(test: PerTestOutcome | undefined): VerdictGroundingQuote {\n if (test === undefined) return { source: 'test-outcome', quote: 'failed' }\n const step = failingStepOf(test)\n // `failingStepOf` answers undefined for exactly the zero-step test — the no-step arm.\n if (step === undefined) return { source: 'test-outcome', quote: test.outcome }\n return { stepIndex: step.stepIndex, quote: errorTextOf(step, test) }\n}\n\n/**\n * Producer-keyed template parts for one floor verdict (389 D-06).\n *\n * Deterministic classes get code-authored parts derived from the hard signal that minted the\n * class — the classifier's rationale IS that signal, so the discriminator carries it.\n * `unknown` gets the honest \"root cause undetermined\" discriminator and the manual-inspection\n * next action; plan 04's LLM upgrade replaces exactly those members through the same author\n * callback, and nothing else changes shape.\n *\n * Exported (module-level, NOT on the package barrel) for the `analysis.get` op's floor leg:\n * a run with no artifact renders honest parts through THIS same rule — a second spelling of\n * the template inside the op would be exactly the D-06 drift the one-rule law forbids.\n */\nexport function templateSentenceParts(\n verdict: Verdict,\n handoff: CompletedRunHandoff,\n): VerdictSentenceParts {\n const test = handoff.tests.find((candidate) => candidate.testIndex === verdict.perTest)\n return {\n perTest: verdict.perTest,\n groundingQuote: templateGroundingQuote(test),\n discriminator:\n verdict.class === 'unknown'\n ? 'root cause undetermined'\n : `${verdict.class}: ${verdict.evidence.rationale}`,\n nextAction: TEMPLATE_NEXT_ACTION[verdict.class],\n links: [],\n }\n}\n\n// ---- 422 D-17..D-20: the circularity guard, at the one seam that authors verdicts -----------\n//\n// 422-11 shipped the gate with BOTH options defaulting fail-closed and recorded the seam plainly:\n// no producer passes `gatedProducerEvidence` or a `rootPosture`, so the arm is off. 422-14 shipped\n// the producer. This is where the two meet, and the meeting has exactly one switch:\n//\n// the analysed handoff carries a `misdirectionEvidence` member -> the arm is ON\n// it does not -> the arm is OFF, historically\n//\n// The switch is the MEMBER's presence and not its contents, because that is what \"the arbiter ran\"\n// means: an empty ledger is a producer that ran and recorded nothing (a skipped run, an absent\n// root, a broken one), and an absent member is every run written before the producer existed.\n//\n// TURNING A FAIL-CLOSED DEFAULT ON IS THE RISKIEST EDIT IN THIS PHASE, so the off arm is not\n// merely \"the same code with a flag\" — it is the same CALL. `misdirectionValidationOptions`\n// answers `{}` for an absent ledger, which is the argument every caller passed before 422 and the\n// one `validateAnalysisAgainstHandoff` defaults to, and nothing below runs at all.\n\n/** The posture, fail-closed: unbound, unanswered and throwing all read as an ordinary root. */\nfunction readMisdirectionPosture(\n capabilities: PostRunJobCapabilities,\n runId: string,\n): MisdirectionRootPosture {\n try {\n return capabilities.readMisdirectionRootPosture?.(runId) ?? 'eval-root'\n } catch {\n return 'eval-root'\n }\n}\n\n/**\n * The honest floor for a verdict the evidence does not support (D-20).\n *\n * `unknown` rather than a softer class, because every other class either moves trust (and the\n * evidence cannot justify moving it) or claims no trust change (which is the claim just refused).\n * The floor keeps the refused verdict's CITED STEPS so the stamp that follows recomputes the same\n * path — an exposure dropped here would be an exposure the record stops disclosing — and it stops\n * claiming `memoryMisdirectionRuledOut`, which is the whole content of what was refused.\n */\nfunction honestUnknownFloor(refused: Verdict, test: PerTestOutcome | undefined): Verdict {\n const floor = deterministicVerdict(\n 'unknown',\n UNKNOWN_SIGNAL_RATIONALE,\n capturedStepsOnly(refused.evidence.citedSteps, test),\n refused.perTest,\n )\n return { ...floor, memoryMisdirectionRuledOut: false }\n}\n\n/**\n * Keep only the steps the member actually captured, in the member's own order.\n *\n * A citation is carried onto a floor verdict to preserve the disclosure it covered, and one way\n * to earn a refusal in the first place is to cite a step that does not exist. Carrying that\n * forward would persist an artifact the validator rejects for a reason this arm did not create.\n */\nfunction capturedStepsOnly(\n cited: readonly number[],\n test: PerTestOutcome | undefined,\n): number[] {\n if (test === undefined) return []\n const captured = new Set(test.steps.map((step) => step.stepIndex))\n return test.steps\n .map((step) => step.stepIndex)\n .filter((stepIndex) => captured.has(stepIndex) && cited.includes(stepIndex))\n}\n\n/**\n * Give a member the author degraded back the citation of the claim that was refused (422-15).\n *\n * ONLY under a published ledger, and only for a member that actually fell to the floor. The\n * widening exists so the circularity disclosure survives the fall: without it a member refused\n * because a record on a CITED step flipped lands as an `unknown` beside the failing step's own\n * held ledger, with no trace of the record that caused it. For a run whose arbiter never ran\n * there is no disclosure to preserve, and the floor stays byte-identical to what 389 wrote.\n */\nfunction widenRefusedFloorPaths(\n verdicts: readonly Verdict[],\n degradedPaths: readonly { readonly perTest: number; readonly citedSteps: readonly number[] }[],\n handoff: CompletedRunHandoff,\n): Verdict[] {\n if (degradedPaths.length === 0) return [...verdicts]\n const testsByIndex = new Map(handoff.tests.map((test) => [test.testIndex, test]))\n return verdicts.map((verdict) => {\n const refused = degradedPaths.find((path) => path.perTest === verdict.perTest)\n if (refused === undefined || verdict.class !== 'unknown') return verdict\n const widened = capturedStepsOnly(\n [...verdict.evidence.citedSteps, ...refused.citedSteps],\n testsByIndex.get(verdict.perTest),\n )\n if (widened.length === verdict.evidence.citedSteps.length) return verdict\n return {\n ...verdict,\n evidence: { ...verdict.evidence, citedSteps: widened },\n } as Verdict\n })\n}\n\n/**\n * Stamp every verdict, then enforce the floor over the whole artifact (D-17/D-18/D-20).\n *\n * THE DOUBLE VALIDATION IS THE POINT. The gated posture and the historical one are run over the\n * same stamped artifact, and only a member the GATED posture refuses and the historical one\n * accepts is downgraded. Anything both refuse is a pre-existing condition that has nothing to do\n * with this arm — a verdict citing a step that does not exist was already being persisted that\n * way — and this plan deliberately leaves it exactly where it was. What is measured is the\n * DIFFERENCE the arm makes, which is also the only thing the arm is entitled to change.\n *\n * DETERMINISTIC VERDICTS GO THROUGH THIS TOO. The author upgrades `unknown` floor members and\n * nothing else, so before today a persisted `app_bug` or a classifier-minted `environment` reached\n * the artifact having never met the gate at all. A guard with a hole the size of the classifier is\n * not a guard, and the cross-check does not care which producer wrote the sentence it refutes.\n */\nfunction enforceMisdirectionFloor(input: {\n readonly verdicts: readonly Verdict[]\n readonly handoff: CompletedRunHandoff\n readonly runId: string\n readonly evidence: readonly MisdirectionRecordResult[] | undefined\n readonly rootPosture: MisdirectionRootPosture\n readonly partsOf: (verdicts: readonly Verdict[]) => VerdictSentenceParts[]\n}): { readonly verdicts: Verdict[]; readonly parts: VerdictSentenceParts[] } {\n const { handoff, runId, evidence, rootPosture, partsOf } = input\n const testsByIndex = new Map(handoff.tests.map((test) => [test.testIndex, test]))\n const stampAll = (verdicts: readonly Verdict[], parts: readonly VerdictSentenceParts[]) =>\n verdicts.map((verdict, index) =>\n stampVerdictMisdirectionEvidence({\n verdict,\n parts: parts[index],\n test: testsByIndex.get(verdict.perTest),\n evidence,\n rootPosture,\n }),\n )\n\n const parts = partsOf(input.verdicts)\n // The arbiter never ran: nothing is stamped, nothing is validated, nothing moves.\n if (evidence === undefined) return { verdicts: [...input.verdicts], parts }\n\n const stamped = stampAll(input.verdicts, parts)\n const artifact: RunAnalysisArtifact = {\n schemaVersion: CURRENT_ANALYSIS_SCHEMA_VERSION,\n runId,\n verdicts: stamped,\n parts,\n }\n const gated = validateAnalysisAgainstHandoff(\n artifact,\n handoff,\n misdirectionValidationOptions(evidence, rootPosture),\n )\n let downgraded = stamped\n if (!gated.ok) {\n const historical = validateAnalysisAgainstHandoff(artifact, handoff)\n const preExisting = new Set(historical.ok ? [] : historical.rejects.map((r) => r.perTest))\n const newlyRefused = new Set(\n gated.rejects.map((reject) => reject.perTest).filter((perTest) => !preExisting.has(perTest)),\n )\n if (newlyRefused.size > 0) {\n downgraded = input.verdicts.map((verdict) =>\n newlyRefused.has(verdict.perTest)\n ? honestUnknownFloor(verdict, testsByIndex.get(verdict.perTest))\n : verdict,\n )\n }\n }\n\n // Parts are recomputed BEFORE the final stamp: a downgraded member's producer moved back to the\n // classifier, so its sentence is now the template's honest \"root cause undetermined\" — and the\n // grounding step that sentence quotes is part of the path the stamp recomputes over. Stamping\n // against the pre-downgrade parts would declare a membership the validator no longer recomputes.\n const finalParts = partsOf(downgraded)\n const finalVerdicts = stampAll(downgraded, finalParts).map(withCausalAttribution)\n return { verdicts: finalVerdicts, parts: finalParts }\n}\n\n/**\n * Name the harm, and name it narrowly (D-20).\n *\n * Only an `unknown` verdict carries attribution from here — a verdict that kept its class was not\n * harmed by the memory — and only the records an actual FLIP supports are named. A held sibling of\n * a flipped record stays in `memoryOnPath` and out of `attribution`: disclosed, never accused.\n */\nfunction withCausalAttribution(verdict: Verdict): Verdict {\n if (verdict.class !== 'unknown') return verdict\n const flipped = flippedRecordsOf(verdict)\n if (flipped.length === 0) return verdict\n return {\n ...verdict,\n memoryMisdirectionRuledOut: false,\n attribution: { records: flipped.map((record) => asRecordId(record)), anchors: [] },\n } as Verdict\n}\n\n/**\n * The real analyze-run body (D-02 / D-06 / 389 D-09).\n *\n * Reads the run's handoff through the injected capability, refuses anything that is not the\n * document the enqueuer measured, authors the verdicts through `recordLlmAuthorship`, and\n * hands curation the one successor D-04 allows. The recorded SHAPE — `{runId, verdicts}` —\n * is the frozen 388 D-02 byte-shape; sentence parts live in the analysis artifact the author\n * persists BEFORE its value is recorded, never on the checkpoint.\n */\nfunction realAnalyzeRunHandler(capabilities: PostRunJobCapabilities): JobHandler {\n return async (context) => {\n const payload = readAnalyzeRunPayload(context.payload)\n if (payload === undefined) {\n return permanently(\n 'the analyze-run payload does not name a run, a handoff digest and a handoff schema ' +\n 'version, so there is nothing for this job to analyse',\n )\n }\n\n let handoff: CompletedRunHandoff\n try {\n handoff = capabilities.loadCompletedRunHandoff(payload.runId)\n } catch (error) {\n return permanently(\n `the handoff for ${payload.runId} could not be read: ` +\n (error instanceof Error ? error.message : String(error)),\n )\n }\n\n if (handoff.schemaVersion !== payload.handoffSchemaVersion) {\n return permanently(\n `the handoff for ${payload.runId} declares schema version ` +\n `${String(handoff.schemaVersion)} and the job was enqueued against ` +\n String(payload.handoffSchemaVersion),\n )\n }\n // D-06's bytes-drifted rule. The digest is the whole reason the payload carries no path:\n // it pins that the bytes being analysed are the bytes the tail measured, whoever rewrote\n // the file in between.\n if (sha256hex(canonicalJson(handoff)) !== payload.handoffDigest) {\n return permanently(\n `the handoff for ${payload.runId} no longer digests to the bytes this job was ` +\n 'enqueued against, so analysing it would answer about a different run',\n )\n }\n\n // 422 D-17/D-18: the payload's circularity copy must agree with the bytes the digest above\n // just pinned, BEFORE anything uses either. The handoff is the authority — it is what\n // `handoffDigest` covers — so the copy can neither weaken nor strengthen it; what a copy CAN\n // do is disagree, and a queue row that disagrees with the document it points at is not a row\n // about this run's evidence. Both refusals are permanent for the same reason every other\n // unreadable-input refusal here is: a second attempt reads the same bytes.\n if (payload.misdirectionEvidenceUnreadable === true) {\n return permanently(\n `the analyze-run payload for ${payload.runId} carries a circularity ledger this build ` +\n 'cannot read, and a claim that cannot be checked is not a claim that may be ignored',\n )\n }\n const publishedEvidence = handoff.misdirectionEvidence\n if (\n payload.misdirectionEvidence !== undefined &&\n (publishedEvidence === undefined ||\n canonicalJson(payload.misdirectionEvidence) !== canonicalJson(publishedEvidence))\n ) {\n return permanently(\n `the analyze-run payload for ${payload.runId} carries circularity evidence that is not ` +\n 'the evidence in the analysed handoff bytes; the digest covers the handoff, so a copy ' +\n 'that disagrees with it is not about these bytes',\n )\n }\n const rootPosture = readMisdirectionPosture(capabilities, payload.runId)\n\n // The author swap (389 D-09/JOBQ-03). On a fresh pass the callback runs exactly once:\n // floor projected, template parts authored, the artifact made durable through\n // `persistAnalysis`, and only THEN is the returned value recorded on the declared\n // checkpoint — the primitive awaits the record before handing the value back, so the\n // artifact-before-checkpoint ordering is structural, not scheduled. On a resume with a\n // recorded value, control never reaches this callback: the author is not re-invoked and\n // the artifact is not rewritten (the recorded-value path).\n const authored = await context.recordLlmAuthorship(\n 'verdicts-authored',\n // The full author (389 plan 04): the model capability arrives ONLY as this\n // callback's argument. Unknown floor members are authored through\n // `authorRunAnalysis` — one whole-run call, one repair, per-test degrade — and\n // everything else passes through byte-identical; a floor with no unknown members\n // (or no failures at all) reaches no model. Signature, artifact-write position and\n // returned shape are final from plan 01.\n async (model) => {\n const floor = projectHandoffVerdicts(handoff)\n // 436 D-12: a limit stop is the run running out of limit, and 439 D-07: a step the\n // verifier left unverified or inconclusive is unproven, not an application failure.\n // Neither is something a model may label; their floor verdicts pass through byte-identical.\n const limitStopped = new Set(\n handoff.tests\n .filter((test) =>\n test.steps.some((step) => step.limitStop !== undefined || stepOutcomeUnproven(step)),\n )\n .map((test) => test.testIndex),\n )\n const unknownTests = floor\n .filter((verdict) => verdict.class === 'unknown' && !limitStopped.has(verdict.perTest))\n .map((verdict) => verdict.perTest)\n\n let verdicts = floor\n const authoredParts = new Map<number, VerdictSentenceParts>()\n if (unknownTests.length > 0) {\n // The projection's product key, spelled the projection's way (plan 02 key law).\n const product = slugBranch(handoff.scope.key)\n const history: EvidenceHistoryLookup = (identity) =>\n capabilities.readTestHistory?.({\n product,\n filePath: identity.filePath,\n testName: identity.testName,\n })\n const result = await authorRunAnalysis(model, {\n handoff,\n floor,\n packs: buildEvidencePacks(handoff, unknownTests, history),\n history,\n // The ledger reaches the author as DATA and the gate as AUTHORITY (D-20). Absent, it\n // does neither: the request is byte-identical to the pre-422 one and the author's own\n // validation runs under the historical options.\n ...(publishedEvidence === undefined\n ? {}\n : { misdirectionEvidence: publishedEvidence, rootPosture }),\n ...(capabilities.analysisTokenBudget === undefined\n ? {}\n : { tokenBudget: capabilities.analysisTokenBudget }),\n // runId-curried so the author sees the plain `(sha) => bytes` shape.\n ...(capabilities.readEvidenceBlob === undefined\n ? {}\n : {\n readEvidenceBlob: (sha: string) =>\n capabilities.readEvidenceBlob?.(payload.runId, sha),\n }),\n })\n // 422-15: a member the author refused keeps the citation of the claim it refused, so\n // the circularity disclosure computed below still covers every exposure that claim did.\n // Gated on a published ledger: with none there is nothing to disclose and the floor\n // stays exactly the array 389 wrote.\n verdicts =\n publishedEvidence === undefined\n ? result.verdicts\n : widenRefusedFloorPaths(result.verdicts, result.degradedPaths, handoff)\n for (const parts of result.authoredParts) authoredParts.set(parts.perTest, parts)\n }\n\n // D-06's ONE producer-keyed parts rule: LLM parts for upgraded members, template\n // parts for deterministic members — which is also what hands a degraded/unfilled\n // `unknown` its honest \"root cause undetermined\" sentence.\n const partsOf = (candidates: readonly Verdict[]): VerdictSentenceParts[] =>\n candidates.map((verdict) =>\n verdict.producer === 'analyze-run'\n ? authoredParts.get(verdict.perTest) ?? templateSentenceParts(verdict, handoff)\n : templateSentenceParts(verdict, handoff),\n )\n // 422 D-17/D-18: the code-owned stamp and the honest floor, over EVERY member — the\n // author's upgrades and the members that never reached it alike.\n const guarded = enforceMisdirectionFloor({\n verdicts,\n handoff,\n runId: payload.runId,\n evidence: publishedEvidence,\n rootPosture,\n partsOf,\n })\n capabilities.persistAnalysis({\n schemaVersion: CURRENT_ANALYSIS_SCHEMA_VERSION,\n runId: payload.runId,\n verdicts: guarded.verdicts,\n parts: guarded.parts,\n })\n return { runId: payload.runId, verdicts: guarded.verdicts }\n },\n )\n const verdicts = authored.verdicts\n\n return {\n status: 'complete',\n next: [\n ...successorsOf(\n { kind: 'analyze-run', allowedSuccessors: ANALYZE_RUN_SUCCESSORS },\n String(context.job.id),\n {\n // Pitfall 6: a successor payload without these two is the DAEM-02 bug class — the\n // daemon resolves a claimed job's posture from `payload.executionContext` (386\n // D-09/D-12), and curation cannot find a run directory it was never told about.\n runId: payload.runId,\n executionContext: payload.executionContext ?? handoff.executionContext,\n verdictSummary: summarizeVerdicts(verdicts),\n },\n ),\n ],\n }\n }\n}\n\n/**\n * The real curate-memory body (D-01).\n *\n * The v51 curation fold runs INSIDE this job rather than beside it, which is what makes one\n * canonical pipeline out of two — and what makes the curation chip incapable of lying about\n * who did the work. The drain itself arrives as a capability: it needs the writer lease, a\n * knowledge root and a run directory, none of which this package may name.\n *\n * A capability that throws is reported as nothing at all: the engine catches it, spends an\n * attempt, and decides between a retry and a permanent failure from the declared bound. That\n * asymmetry is deliberate — this handler cannot know whether a drain failure is transient.\n */\nfunction realCurateMemoryHandler(capabilities: PostRunJobCapabilities): JobHandler {\n return async (context) => {\n const record = asRecord(context.payload)\n if (typeof record.runId !== 'string' || record.runId === '') {\n return permanently(\n 'the curate-memory payload names no run, so there is no run directory to fold and no ' +\n 'receipt to write',\n )\n }\n await context.publishCheckpoint('candidates-authored', { runId: record.runId })\n const counts = await capabilities.curateRun({\n runId: record.runId,\n executionContext: record.executionContext,\n })\n // WR-03. The gate sits BEFORE the publish, not after it: `bundle-committed` is named for an\n // event, and a fold that refused wrote no bundle. Publishing it and then reporting the\n // failure would leave the chain terminal reading counts off a checkpoint whose event never\n // happened. Retryable rather than permanent because the fold's own recovery IS a refold —\n // it withheld the receipt precisely so the run folds again — and the declared bound\n // (maxAttempts: 3, onPermanentFailure: 'halt-chain') is what decides when refolding stops.\n if (!counts.complete) {\n return {\n status: 'retryable',\n reason: counts.reason\n ?? 'the curation fold did not complete and wrote no receipt; the stage will retry '\n + 'under its declared bound',\n }\n }\n // WR-02. The bundles are committed by now: a snapshot that does not validate is omitted and the\n // legacy counts are published alone, rather than throwing into a retry of a finished fold.\n const parsedSnapshot = counts.snapshot === undefined\n ? undefined\n : CurationSnapshotSchema.safeParse(counts.snapshot)\n const curationSnapshot = parsedSnapshot?.success === true ? parsedSnapshot.data : undefined\n await context.publishCheckpoint('bundle-committed', {\n runId: record.runId,\n curated: counts.curated,\n deprecated: counts.deprecated,\n ...(curationSnapshot === undefined\n ? {}\n : { curationSnapshot }),\n })\n // 422 D-13. The successor is produced for EVERY completed fold, including one that curated\n // nothing: zero work is still work that finished, and a successor gated on the counts would\n // drop exactly the quiet runs — which reads, to every later reader, like a chain that stalled.\n //\n // What travels with it is the upstream truth, and it travels because it has to: the job that\n // lands the chain terminal from here on is the proposal job, which did not do the analysis and\n // did not do this fold. Whatever is not on this payload is not in the durable record.\n return {\n status: 'complete',\n next: [\n ...successorsOf(\n { kind: 'curate-memory', allowedSuccessors: CURATE_MEMORY_SUCCESSORS },\n String(context.job.id),\n {\n // Pitfall 6 / 386 D-09, one edge further along: without these two the\n // daemon-claimed successor resolves a drain-scoped posture and cannot address\n // the run it is proposing about.\n runId: record.runId,\n ...(record.executionContext === undefined\n ? {}\n : { executionContext: record.executionContext }),\n // Absent when the fold reported none — see the capability's own comment for why the\n // empty list and the missing field are deliberately not the same answer.\n ...(counts.candidateIds === undefined\n ? {}\n : { candidateIds: [...counts.candidateIds] }),\n upstream: {\n ...(record.verdictSummary === undefined\n ? {}\n : { verdictSummary: record.verdictSummary }),\n // The dead-analysis marker, restated where the next stage will look for it. The\n // root of THIS payload belongs to the analysis; the root of the next belongs to\n // the fold, so the fact has to be re-carried or it is lost at this edge.\n analysisStatus: record.verdicts === UNKNOWN_VERDICTS_MARKER ? 'failed' : 'done',\n curation: {\n curated: counts.curated,\n deprecated: counts.deprecated,\n complete: true,\n ...(curationSnapshot === undefined ? {} : { curationSnapshot }),\n },\n },\n },\n ),\n ],\n }\n }\n}\n\n\n// ---- 422 D-14: the per-job Gate-1 allowance ------------------------------------------------\n//\n// THE PROBLEM THIS SHAPE EXISTS FOR. A Gate-1 call is replay work no later run can recover, so\n// the job needs a bound on how many it may spend. The naive bound — \"look at what is still\n// ungated and stop at N\" — is not a bound at all across a retry, because the thing that makes a\n// candidate look ungated is the very evidence an interrupted attempt failed to persist. Two\n// interruption windows make that concrete, and they fail in opposite directions:\n//\n// 1. The replay finished and the receipt write was refused or never answered. Nothing is\n// standing, so a retry re-selects the same candidate and spends a second call for it.\n// 2. The receipt IS durable and the checkpoint recording the result never landed. The standing\n// receipt correctly suppresses that candidate — and its allowance is now invisible, so the\n// retry admits a DIFFERENT candidate and the job exceeds its own cap without ever\n// re-screening anything.\n//\n// So the charge is durable and it precedes the spend: the selected slots are published as a\n// checkpoint BEFORE the first port call, and a resumed job reads that charge back and treats\n// every slot in it as consumed. It is an upper bound on calls that may have been attempted, not\n// evidence that any of them ran — which is why a resumed attempt reports three separate things\n// (acknowledged, recovered, unknown) rather than one count.\n//\n// 422-06 solved the structurally identical problem for probe authoring one wave earlier and its\n// answer is the same one: the interrupted state is DERIVED from a charge with no completion,\n// never written by the code that failed to run.\n\n/** The checkpoint the durable per-job Gate-1 charge is published on, before any invocation. */\nexport const PROPOSE_GATE1_ALLOWANCE_CHECKPOINT = 'gate1-allowance-reserved'\n\n/**\n * How many Gate-1 calls ONE proposal job may spend (422 D-14).\n *\n * Four, beside the phase's other two Gate-1-adjacent recorded defaults, and the unit is the one\n * this layer always knows exactly: a CALL. A per-job bound rather than a per-run one because\n * the job is what carries a durable charge; and a bound at all because a fold that committed\n * forty candidates would otherwise hand the pump forty replays before the next run's tail could\n * get a lease. The number is a STATED budget with a stated rationale — bounded per-job replay\n * work — and not a measured one; nothing in this repo yet measures what a proposal stage should\n * be allowed to spend.\n */\nexport const PROPOSE_DEFAULT_MAX_GATE1_PER_JOB = 4\n\n/** Where the bound came from, disclosed beside it so an operator can tell a default from a choice. */\nexport interface ProposeGate1Cap {\n readonly value: number\n readonly source: 'config' | 'default'\n}\n\n/**\n * The durable charge, published before the first Gate-1 invocation (422 D-14).\n *\n * Every member is part of the IDENTITY of the charge rather than decoration. `jobId` and `runId`\n * are what let a resumed attempt refuse a reservation that belongs to somebody else instead of\n * silently adopting it. `product` and `corpusDigest` freeze what the selection was made against,\n * so a corpus that moved between the attempts cannot re-open a slot. `cap` travels with it\n * because a config change during a retry must not enlarge a charge already made. And\n * `selectedCandidateIds` is the charge itself: those slots are spent, whatever became of them.\n */\nexport interface ProposeGate1Allowance {\n readonly jobId: string\n readonly runId: string\n readonly product: string\n readonly corpusDigest: string\n readonly cap: ProposeGate1Cap\n readonly selectedCandidateIds: readonly string[]\n}\n\n/**\n * What reading the persisted charge found.\n *\n * Three arms, and `unreadable` is NOT folded into `absent` — that is the whole safety property.\n * An absent charge permits a first selection; a charge this build cannot read means a previous\n * attempt may have spent slots this one cannot account for, and the only honest response is to\n * spend nothing.\n */\nexport type ProposeGate1AllowanceRead =\n | { readonly kind: 'absent' }\n | { readonly kind: 'claimed'; readonly allowance: ProposeGate1Allowance }\n | { readonly kind: 'unreadable'; readonly reason: string }\n\n/** What corpus the selection is made against, and whether it can be known at all. */\nexport type ProposeCorpusPosture =\n | { readonly kind: 'resolved'; readonly corpusDigest: string }\n | { readonly kind: 'unavailable'; readonly reason: string }\n | { readonly kind: 'no-root' }\n\n/** One candidate whose Gate-1 receipt exists and is readable, with the verdict it carries. */\nexport interface ProposeGate1Screened {\n readonly candidateId: string\n readonly verdict: GateVerdict\n}\n\n/**\n * What the proposal stage's Gate-1 leg did, as the durable record reports it (422 D-14).\n *\n * The four candidate-state members are deliberately NOT summable into one count:\n *\n * `screenedGate1` this attempt called the port and the writer acknowledged a receipt\n * `recoveredGate1Receipts` a valid receipt was already on disk under the saved identity —\n * found, never generated here, and never claimed as this attempt's work\n * `interruptedGate1` a charged slot with no acknowledged and no recovered receipt. UNKNOWN,\n * which is its own outcome and not a quiet zero\n * `ungatedRemaining` eligible work the cap did not admit; it waits for a later run's\n * distinct job or the operator's replay-gate verb, and is never a refund\n */\nexport interface ProposeGate1Report {\n readonly disposition:\n | 'unbound'\n | 'no-candidates'\n | 'posture-unavailable'\n | 'allowance-unavailable'\n | 'claimed'\n | 'resumed'\n readonly reason?: string\n readonly cap?: ProposeGate1Cap\n readonly reservedGate1: readonly string[]\n readonly screenedGate1: readonly ProposeGate1Screened[]\n readonly recoveredGate1Receipts: readonly ProposeGate1Screened[]\n readonly interruptedGate1: readonly string[]\n readonly ungatedRemaining: readonly string[]\n readonly kindExcluded: readonly string[]\n readonly stale: readonly string[]\n}\n\n/** What `proposals-authored` carries. `gate1` is ABSENT when no gate capability was bound. */\nexport interface ProposeImprovementsCheckpoint {\n readonly runId: string\n readonly candidateIds: readonly string[]\n readonly proposed?: number\n readonly skipped?: number\n readonly gate1?: ProposeGate1Report\n}\n\n/**\n * The record kinds Gate 1 does not judge (417 D-19's tier abstention, restated as a filter).\n *\n * Selecting one would buy a `tier-not-implemented` abstention for a full replay's price, which\n * is the one way to spend a charged slot and learn nothing at all.\n */\nconst GATE1_EXCLUDED_RECORD_KINDS: readonly string[] = ['procedure', 'policy']\n\nfunction isPositiveInteger(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value > 0\n}\n\n/**\n * Read the durable charge back out of a checkpoint read (422 D-14).\n *\n * STRICT, unlike this module's two payload readers, and the asymmetry is the point. Those read\n * bytes off a durable queue that an older build may have written, where refusing would strand\n * real work. This reads THIS job's own charge ledger, written by this build moments ago — so a\n * shape this build cannot read is not a generation gap, it is a ledger that cannot be trusted to\n * say what was already spent. Degrading it to `absent` would license a second selection against\n * a charge that already exists, which is exactly the over-spend the ledger exists to prevent.\n *\n * Exported so the composition that owns the store can bind a one-line reader: the envelope peel\n * and the shape check live HERE, where the shape is declared, rather than in each host.\n */\nexport function parseProposeGate1Allowance(\n outcome: JobCheckpointReadOutcome,\n): ProposeGate1AllowanceRead {\n if (!outcome.found) return { kind: 'absent' }\n // Exactly one level, unconditionally — the engine's own rule. `publishCheckpoint` is the only\n // writer of these bytes and it always wraps the value in a `JobCheckpointRecord`.\n const value = asRecord((outcome.payload as { readonly value?: unknown } | undefined)?.value)\n const cap = asRecord(value.cap)\n const ids = value.selectedCandidateIds\n const unreadable = (reason: string): ProposeGate1AllowanceRead => ({ kind: 'unreadable', reason })\n if (\n typeof value.jobId !== 'string' || value.jobId === '' ||\n typeof value.runId !== 'string' || value.runId === '' ||\n typeof value.product !== 'string' || value.product === '' ||\n typeof value.corpusDigest !== 'string' || value.corpusDigest === '' ||\n !isPositiveInteger(cap.value) ||\n (cap.source !== 'config' && cap.source !== 'default') ||\n !Array.isArray(ids) ||\n !ids.every((id): id is string => typeof id === 'string' && id !== '')\n ) {\n return unreadable('the persisted Gate-1 allowance is not a readable charge')\n }\n if (ids.length > cap.value) {\n return unreadable('the persisted Gate-1 allowance charges more slots than its own cap')\n }\n return {\n kind: 'claimed',\n allowance: {\n jobId: value.jobId,\n runId: value.runId,\n product: value.product,\n corpusDigest: value.corpusDigest,\n cap: { value: cap.value, source: cap.source },\n selectedCandidateIds: [...(ids as readonly string[])],\n },\n }\n}\n\n/** The one standing Gate-1 line, if the record carries one at all. */\nfunction standingGate1(standing: readonly GateReceipt[]): Extract<GateReceipt, { gate: 1 }> | undefined {\n for (const receipt of standing) if (receipt.gate === 1) return receipt\n return undefined\n}\n\n/**\n * Payload candidates first, then the same product's older candidates (422 D-14/D-15).\n *\n * The payload's ids come first because they are the ones this run's fold just committed — the\n * work the chain is actually about. The sweep exists so a corpus that accumulated ungated\n * candidates while nobody was screening does not stay that way forever, and it is ordered\n * OLDEST-first with the record id as a stable tie-break so two hosts walking one corpus at the\n * same ordinal agree on what \"next\" means.\n *\n * The product comes from the payload rather than from configuration: a proposal job is about one\n * run, a run is about one product, and a sweep scoped by anything else would spend this run's\n * charge on a corpus it has no evidence about.\n */\nfunction orderProposalCandidates(\n bundles: readonly KnowledgeBundleSummary[],\n payloadCandidateIds: readonly string[],\n): { readonly product: string | undefined; readonly ordered: readonly KnowledgeBundleSummary[] } {\n const byId = new Map<string, KnowledgeBundleSummary>()\n for (const bundle of bundles) if (!byId.has(bundle.bundleId)) byId.set(bundle.bundleId, bundle)\n const named: KnowledgeBundleSummary[] = []\n const seen = new Set<string>()\n for (const id of payloadCandidateIds) {\n if (seen.has(id)) continue\n seen.add(id)\n const row = byId.get(id)\n if (row !== undefined) named.push(row)\n }\n const product = named[0]?.product\n if (product === undefined) return { product: undefined, ordered: [] }\n const sweep = bundles\n .filter(\n (bundle) =>\n bundle.product === product && !seen.has(bundle.bundleId) && bundle.status === 'candidate',\n )\n .sort(\n (left, right) =>\n left.openedAtOrdinal - right.openedAtOrdinal ||\n (left.bundleId < right.bundleId ? -1 : left.bundleId > right.bundleId ? 1 : 0),\n )\n return { product, ordered: [...named, ...sweep] }\n}\n\nconst NO_GATE1_WORK = {\n reservedGate1: [] as readonly string[],\n screenedGate1: [] as readonly ProposeGate1Screened[],\n recoveredGate1Receipts: [] as readonly ProposeGate1Screened[],\n interruptedGate1: [] as readonly string[],\n ungatedRemaining: [] as readonly string[],\n kindExcluded: [] as readonly string[],\n stale: [] as readonly string[],\n} as const\n\n/**\n * Reconcile a charge a previous attempt already made — WITHOUT spending anything (422 D-14).\n *\n * Zero port calls on this path, by construction rather than by a counter: `runReplayGate` is not\n * reachable from here. The charge's own identity is what the standing receipts are checked\n * against, so a corpus that moved between the attempts leaves a slot UNKNOWN rather than\n * silently recovering a receipt about a different corpus.\n */\nasync function reconcileGate1Allowance(\n allowance: ProposeGate1Allowance,\n gateReceiptsFor: NonNullable<PostRunJobCapabilities['gateReceiptsFor']>,\n): Promise<ProposeGate1Report> {\n const recovered: ProposeGate1Screened[] = []\n const interrupted: string[] = []\n for (const candidateId of allowance.selectedCandidateIds) {\n let standing: Extract<GateReceipt, { gate: 1 }> | undefined\n try {\n const gates = await gateReceiptsFor({ candidateId })\n standing = gates.kind === 'found' ? standingGate1(gates.standing) : undefined\n } catch {\n // An unreadable store makes the slot's outcome UNKNOWN, which is what `interrupted` says.\n standing = undefined\n }\n if (standing !== undefined && standing.corpusVersion.corpusDigest === allowance.corpusDigest) {\n recovered.push({ candidateId, verdict: standing.verdict })\n } else {\n interrupted.push(candidateId)\n }\n }\n return {\n ...NO_GATE1_WORK,\n disposition: 'resumed',\n cap: allowance.cap,\n reservedGate1: [...allowance.selectedCandidateIds],\n recoveredGate1Receipts: recovered,\n interruptedGate1: interrupted,\n }\n}\n\n/**\n * Select, charge, then spend — in that order, and never the other way round (422 D-14/D-15).\n */\nasync function screenGate1(\n capabilities: PostRunJobCapabilities,\n context: JobHandlerContext,\n payload: ProposeImprovementsPayload,\n): Promise<ProposeGate1Report> {\n const runReplayGate = capabilities.runReplayGate\n const readAllowance = capabilities.readProposeGate1Allowance\n const listBundles = capabilities.listBundles\n const gateReceiptsFor = capabilities.gateReceiptsFor\n const readCorpusPosture = capabilities.readProposeCorpusPosture\n // A host that bound no replay gate, no allowance reader, no corpus reader — a typed no-op,\n // not a failure. It is the posture 417 shipped and 422-07 shipped after it, and a stage that\n // refused to complete over it would strand the chain terminal for every such host.\n if (\n runReplayGate === undefined || readAllowance === undefined || listBundles === undefined ||\n gateReceiptsFor === undefined || readCorpusPosture === undefined\n ) {\n return { ...NO_GATE1_WORK, disposition: 'unbound' }\n }\n\n const jobId = String(context.job.id)\n // THE LEDGER IS READ FIRST, before anything is selected. A charge that already exists decides\n // this attempt entirely; nothing below it may enlarge, refill or replace one.\n let read: ProposeGate1AllowanceRead\n try {\n read = await readAllowance(jobId)\n } catch (error) {\n return {\n ...NO_GATE1_WORK,\n disposition: 'allowance-unavailable',\n reason: `the persisted Gate-1 allowance could not be read: ${errorTextOfUnknown(error)}`,\n }\n }\n if (read.kind === 'unreadable') {\n return { ...NO_GATE1_WORK, disposition: 'allowance-unavailable', reason: read.reason }\n }\n if (read.kind === 'claimed') {\n const allowance = read.allowance\n if (allowance.jobId !== jobId || allowance.runId !== payload.runId) {\n return {\n ...NO_GATE1_WORK,\n disposition: 'allowance-unavailable',\n reason: 'the persisted Gate-1 allowance was charged for another job or run',\n }\n }\n return await reconcileGate1Allowance(allowance, gateReceiptsFor)\n }\n\n const cap: ProposeGate1Cap = isPositiveInteger(capabilities.proposeGate1MaxPerJob)\n ? { value: capabilities.proposeGate1MaxPerJob, source: 'config' }\n : { value: PROPOSE_DEFAULT_MAX_GATE1_PER_JOB, source: 'default' }\n\n const { product, ordered } = orderProposalCandidates(await listBundles(), payload.candidateIds)\n if (product === undefined) {\n return { ...NO_GATE1_WORK, disposition: 'no-candidates' }\n }\n const posture = await readCorpusPosture({ product })\n if (posture.kind !== 'resolved') {\n return {\n ...NO_GATE1_WORK,\n disposition: 'posture-unavailable',\n cap,\n reason: posture.kind === 'no-root'\n ? 'no committed corpus root, so nothing can be screened against one'\n : posture.reason,\n }\n }\n\n const kindExcluded: string[] = []\n const stale: string[] = []\n const ungated: string[] = []\n for (const row of ordered) {\n if (GATE1_EXCLUDED_RECORD_KINDS.includes(row.kind)) {\n kindExcluded.push(row.bundleId)\n continue\n }\n if (row.status !== 'candidate') continue\n const gates = await gateReceiptsFor({ candidateId: row.bundleId })\n if (gates.kind !== 'found') continue\n if (GATE1_EXCLUDED_RECORD_KINDS.includes(gates.recordKind)) {\n kindExcluded.push(row.bundleId)\n continue\n }\n const standing = standingGate1(gates.standing)\n // A standing Gate-1 line under the CURRENT corpus digest is a decision, whatever it decided:\n // a fail and an abstain are screening results, and re-buying them would spend the charge on\n // a question this corpus has already answered.\n if (standing !== undefined && standing.corpusVersion.corpusDigest === posture.corpusDigest) {\n continue\n }\n if (standing !== undefined) stale.push(row.bundleId)\n ungated.push(row.bundleId)\n }\n\n const selected = ungated.slice(0, cap.value)\n const remaining = ungated.slice(cap.value)\n if (selected.length === 0) {\n return {\n ...NO_GATE1_WORK,\n disposition: 'claimed',\n cap,\n ungatedRemaining: remaining,\n kindExcluded,\n stale,\n }\n }\n\n // THE CHARGE, durable, BEFORE the first call. `publishCheckpoint` resolves only once the store\n // has it; if it throws, no call is made at all, and if the process dies between the write and\n // the acknowledgement the next attempt reads the charge back and spends nothing.\n const allowance: ProposeGate1Allowance = {\n jobId,\n runId: payload.runId,\n product,\n corpusDigest: posture.corpusDigest,\n cap,\n selectedCandidateIds: selected,\n }\n await context.publishCheckpoint(PROPOSE_GATE1_ALLOWANCE_CHECKPOINT, allowance)\n\n const screened: ProposeGate1Screened[] = []\n const interrupted: string[] = []\n // SEQUENTIALLY, and once each. Concurrency here would put several replays under one writer\n // lease at once for no gain the cap can express.\n for (const candidateId of selected) {\n try {\n const receipt = await runReplayGate(asRecordId(candidateId))\n // The port resolves only on an ACKNOWLEDGED receipt (422 D-14, the T1 contract), so this\n // is a screening result the store agrees with rather than one this process remembers.\n screened.push({ candidateId, verdict: receipt.verdict })\n } catch {\n // Refused, unknown, or lost. The slot stays charged and reports no screened success — the\n // one thing that must never happen here is a refusal reading as a quiet nothing.\n interrupted.push(candidateId)\n }\n }\n\n return {\n disposition: 'claimed',\n cap,\n reservedGate1: [...selected],\n screenedGate1: screened,\n recoveredGate1Receipts: [],\n interruptedGate1: interrupted,\n ungatedRemaining: remaining,\n kindExcluded,\n stale,\n }\n}\n\nfunction errorTextOfUnknown(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\n/**\n * The real propose-improvements body (422 D-13).\n *\n * The third and last stage of the post-run chain. It runs on candidates the fold's receipt named\n * and on the upstream truth the fold forwarded, and it stages its proposals through an OPTIONAL\n * neutral port — so a host that binds nothing still lands the stage, publishes its checkpoint and\n * terminates the chain honestly rather than leaving the run's record unwritten.\n *\n * It cannot undo the curation behind it, and nothing here tries. A permanent failure halts the\n * chain (the declaration below), the committed bundle stays committed, and the terminal record\n * reports a `done` curation beside a `failed` proposal stage — which is what actually happened.\n *\n * A port that throws is reported as nothing at all, exactly as the fold's is: the engine catches\n * it, spends an attempt and decides between a retry and a permanent failure from the declared\n * bound, because this handler cannot know whether a staging failure is transient.\n */\nfunction realProposeImprovementsHandler(capabilities: PostRunJobCapabilities): JobHandler {\n return async (context) => {\n const payload = readProposeImprovementsPayload(context.payload)\n if (payload === undefined) {\n return permanently(\n 'the propose-improvements payload names no run, so there is no curated run to propose ' +\n 'improvements about',\n )\n }\n\n // 422 D-14: the Gate-1 leg runs FIRST and charges its own allowance before it spends one.\n // It is deliberately ahead of the staging: a screening refusal must not be erasable by a\n // staging success published over the top of it, and both land on one checkpoint below.\n const gate1 = await screenGate1(capabilities, context, payload)\n\n const staged = capabilities.stageAdversarialProposal === undefined\n ? undefined\n : await capabilities.stageAdversarialProposal({\n runId: payload.runId,\n executionContext: payload.executionContext,\n candidateIds: payload.candidateIds,\n upstream: payload.upstream,\n })\n\n // Published AFTER the staging, on the fold's `bundle-committed` discipline: the checkpoint is\n // named for an event, and counts recorded before the port answered would name an event that\n // had not happened yet. The counts are omitted entirely when no port was bound, so the\n // terminal record can tell \"staged nothing\" from \"staged zero\".\n //\n // `gate1` is omitted on exactly the same terms: a host that bound no gate capability did not\n // screen zero candidates, it did not screen. Absence is what says so, and it is what keeps\n // every record written before this widening describing the same thing it always did.\n const checkpoint: ProposeImprovementsCheckpoint = {\n runId: payload.runId,\n candidateIds: [...payload.candidateIds],\n ...(staged === undefined ? {} : { proposed: staged.proposed, skipped: staged.skipped }),\n ...(gate1.disposition === 'unbound' ? {} : { gate1 }),\n }\n await context.publishCheckpoint('proposals-authored', checkpoint)\n return { status: 'complete', next: [] }\n }\n}\n\n/**\n * Every kind, keyed by itself.\n *\n * `satisfies Record<JobKind, JobKindDeclaration>` is the compile-time half of D-09's\n * completeness: a sixth kind added to the shipped vocabulary fails to typecheck here until\n * it is declared. The registry-driven conformance test is the runtime half, and the two catch\n * different drifts — a missing entry versus an entry whose own `kind` field disagrees with\n * the slot it sits in.\n */\nfunction declarationsFor(capabilities?: PostRunJobCapabilities) {\n return {\n // JOBQ-04 / C9. Chat is NOT a checkpointed job and never becomes one: its state of record\n // is the append-only session log, and the queue's checkpoint discipline covers background\n // work only. One attempt, because there is no durable progress for a second one to resume.\n chat: {\n kind: 'chat',\n checkpointed: false,\n checkpointSchedule: [],\n allowedSuccessors: [],\n maxAttempts: 1,\n backoff: { kind: 'none' },\n onPermanentFailure: 'halt-chain',\n handler: standInHandler('chat', [], []),\n },\n\n // The chain's head. Its verdicts feed curate-memory — the one kind it declares and the one\n // it produces — and its permanent failure proceeds with unknown verdicts into that same kind.\n 'analyze-run': {\n kind: 'analyze-run',\n checkpointed: true,\n checkpointSchedule: ['verdicts-authored'],\n allowedSuccessors: ANALYZE_RUN_SUCCESSORS,\n maxAttempts: 3,\n backoff: { kind: 'exponential', initialDelayMs: 1_000, factor: 2, maxDelayMs: 30_000 },\n onPermanentFailure: analyzeRunFallback,\n handler: capabilities === undefined\n ? standInHandler('analyze-run', ['verdicts-authored'], ANALYZE_RUN_SUCCESSORS)\n : realAnalyzeRunHandler(capabilities),\n },\n\n // Two checkpoints, mirroring the v51 curation lifecycle: candidates are authored, then the\n // bundle is committed. The second is the one whose recovery actually matters.\n //\n // 422 D-13: it now chains onward to the proposal stage, and `halt-chain` survives that\n // unchanged — deliberately. A fold that gave up permanently committed no bundle, so there is\n // nothing for a proposal stage to propose about; handing it a successor would mint a job whose\n // whole premise is a fold that did not happen.\n 'curate-memory': {\n kind: 'curate-memory',\n checkpointed: true,\n checkpointSchedule: ['candidates-authored', 'bundle-committed'],\n allowedSuccessors: CURATE_MEMORY_SUCCESSORS,\n maxAttempts: 3,\n backoff: { kind: 'exponential', initialDelayMs: 1_000, factor: 2, maxDelayMs: 30_000 },\n onPermanentFailure: 'halt-chain',\n handler: capabilities === undefined\n ? standInHandler(\n 'curate-memory',\n ['candidates-authored', 'bundle-committed'],\n CURATE_MEMORY_SUCCESSORS,\n )\n : realCurateMemoryHandler(capabilities),\n },\n\n consolidate: {\n kind: 'consolidate',\n checkpointed: true,\n checkpointSchedule: ['consolidation-authored'],\n allowedSuccessors: [],\n maxAttempts: 2,\n backoff: { kind: 'fixed', delayMs: 5_000 },\n onPermanentFailure: 'halt-chain',\n handler: standInHandler('consolidate', ['consolidation-authored'], []),\n },\n\n // The chain's tail since 422 D-13. It declares NO successor — a fourth stage would be one\n // nothing derives an id for — and halts its chain on permanent failure, which here means only\n // that nothing further is enqueued: the curation behind it is committed and stays committed.\n //\n // 422 D-14 adds `gate1-allowance-reserved` AHEAD of `proposals-authored`, and the order is the\n // contract rather than a listing convention: the charge is what a resumed attempt reads to\n // learn what a previous one may already have spent, so it has to be durable before any call\n // is made and therefore before the checkpoint that reports the result.\n 'propose-improvements': {\n kind: 'propose-improvements',\n checkpointed: true,\n checkpointSchedule: [PROPOSE_GATE1_ALLOWANCE_CHECKPOINT, 'proposals-authored'],\n allowedSuccessors: [],\n maxAttempts: 2,\n backoff: { kind: 'fixed', delayMs: 5_000 },\n onPermanentFailure: 'halt-chain',\n handler: capabilities === undefined\n ? standInHandler(\n 'propose-improvements',\n [PROPOSE_GATE1_ALLOWANCE_CHECKPOINT, 'proposals-authored'],\n [],\n )\n : realProposeImprovementsHandler(capabilities),\n },\n } satisfies Record<JobKind, JobKindDeclaration>\n}\n\n/**\n * The five declarations as a list, in the order the kind vocabulary declares them.\n *\n * The NO-CAPABILITY set: analyze-run and curate-memory carry their scripted stand-ins here,\n * byte-identically to what 385 shipped. Everything registry-driven that does not compose a\n * host — the conformance suite, the crash matrix, the kill matrix's adversarial legs — reads\n * this list, and every one of them scripts those two kinds by payload.\n */\nexport const REAL_JOB_KIND_DECLARATIONS: readonly JobKindDeclaration[] = Object.freeze(\n Object.values(declarationsFor()) as readonly JobKindDeclaration[],\n)\n\n/**\n * A registry over exactly the five real kinds.\n *\n * A fresh registry per call rather than a module-level singleton: a registry is a small,\n * cheap value, and one shared instance is how a test that registers something extra ends up\n * changing what every other test in the process sees.\n *\n * With `capabilities`, analyze-run and curate-memory dispatch their REAL bodies (388 D-01 /\n * D-02); without, they keep the scripted stand-ins. The stand-ins are the HARNESS affordance,\n * not a shipped posture: both production compositions bind capabilities — `composeLocalAgent`\n * when the run tail supplies its curation drain (plan 02), and the daemon's own composition\n * through the same input. A caller that gets a stand-in is a caller that asked for one.\n *\n * The DECLARATIONS are identical in both cases. Only the two handler slots move, so a matrix\n * that derives its crash points from the declared schedule covers the real bodies with no\n * harness change at all — which is the design intent 385 D-09 stated and this is the phase\n * that spends it.\n */\nexport function createRealJobKindRegistry(\n capabilities?: PostRunJobCapabilities,\n): JobKindRegistry {\n return createJobKindRegistry(\n capabilities === undefined\n ? REAL_JOB_KIND_DECLARATIONS\n : (Object.values(declarationsFor(capabilities)) as readonly JobKindDeclaration[]),\n )\n}\n","// The whole-run analyze-run author (Phase 389, plan 04 — D-01/D-02/D-03, ANLZ-02).\n//\n// ONE `model.generate` call authors every unknown-verdict failure together (D-01): the\n// author sees the cross-test pattern (\"40 reds, one cause\") that clustering and the\n// discriminator feed on, matches the once-per-run heartbeat unit, and never fans out\n// per test or adds a second LLM stage inside the one-checkpoint schedule.\n//\n// The model's answer is UNTRUSTED. It is parsed with the curator's deterministic repair\n// idiom (fence strip, trailing-comma removal — COPIED from `cli/src/curation/\n// curator-author.ts`, never imported: agent→cli is a banned direction), shaped by zod, and\n// then validated cross-document by schema's `validateAnalysisAgainstHandoff`. Rejects feed\n// exactly ONE repair round-trip (D-03) whose feedback names each failing test and reason;\n// whatever still fails degrades to the deterministic unknown floor member for THAT test\n// only — valid siblings persist, and job-level retries stay reserved for transport\n// failures, which propagate out of this function uncaught.\n//\n// The merge law lives here and nowhere else: a floor verdict is replaced iff its class is\n// `unknown` AND a validated author verdict exists for its perTest; everything else passes\n// through byte-identical. `producer: 'analyze-run'` is forced code-side — model output\n// never chooses producer.\n//\n// D-02's screenshot channel rides the same single request: when the capability advertises\n// `vision` and a blob reader is bound and the post-compaction packs still carry\n// screenshotRefs, the failing steps' decision-screenshot bytes attach as the request's\n// optional `images`; every other posture is the L9 text-only degradation — a request\n// structurally identical to the pre-widening text request. The repair round-trip reuses\n// the same image set, never a re-fetch.\n//\n// The model arrives ONLY as the `JobModelCapability` argument the `recordLlmAuthorship`\n// callback hands its author — this module never imports a provider SDK.\n\nimport type {\n AnalysisValidationOptions,\n ArtifactRef,\n CompletedRunHandoff,\n MisdirectionEvidence,\n MisdirectionRecordResult,\n MisdirectionRootPosture,\n PerTestOutcome,\n StepEvidence,\n Verdict,\n VerdictGroundingQuote,\n VerdictSentenceParts,\n} from '@vostride/agent-qa-schema'\nimport {\n canonicalJson,\n CURRENT_ANALYSIS_SCHEMA_VERSION,\n deriveMemoryOnPath,\n deriveMemoryOnPathSites,\n failingStepOf,\n QUOTE_SEARCHED_STEP_FIELDS,\n validateAnalysisAgainstHandoff,\n} from '@vostride/agent-qa-schema'\nimport { z } from 'zod'\n\nimport { buildTieredPrompt } from '../prompt/tiered-prompt-builder.js'\nimport type { PromptTierBlock } from '../prompt/tiered-prompt-builder.js'\nimport { compactEvidencePacks } from './evidence-diet.js'\nimport type {\n CompactedEvidence,\n EvidenceHistoryLookup,\n EvidencePack,\n} from './evidence-diet.js'\nimport type { JobModelCapability, JobModelRequest } from './record-llm-authorship.js'\n\n/**\n * The single in-attempt repair round-trip (D-03).\n *\n * Pinned, not config (386 D-15); retune from operational evidence: raise only if real\n * transcripts show a second repair regularly rescuing tests the first one could not —\n * every extra round-trip is a model call inside a job attempt whose transport failures\n * already carry their own 3-attempt bound.\n */\nexport const AUTHOR_REPAIR_CAP = 1\n\n/**\n * The cap on decision-screenshot image parts attached to the one request (D-02).\n *\n * Pinned, not config (386 D-15); retune from operational evidence: raise if real\n * multi-failure transcripts show discriminating screenshots being cut at this cap, lower\n * if image payloads dominate request cost without moving verdict quality.\n */\nexport const MAX_AUTHOR_IMAGES = 6\n\n// ---------------------------------------------------------------------------------------\n// 422 D-17..D-20: the code-owned circularity stamp, applied BEFORE validation.\n//\n// The evidence a no-trust-change verdict rests on is produced by the pre-enqueue arbiter\n// (422-14) and travels on the run's own handoff. It reaches a verdict through THIS function and\n// through no other route: whatever the model answered about `memoryOnPath` or\n// `misdirectionRuledOut` is overwritten, so an authored copy can never become authority.\n//\n// It lives beside the validator call it precedes rather than in the handler, because the\n// ordering is the contract — a stamp applied after `validateAnalysisAgainstHandoff` would leave\n// the gate deciding about a verdict that carries no evidence while the persisted artifact ends\n// up carrying some, which is the one shape that looks right afterwards and was wrong at the\n// instant it mattered.\n// ---------------------------------------------------------------------------------------\n\nexport interface MisdirectionStampInput {\n readonly verdict: Verdict\n /** The verdict's sentence parts, when they exist — the grounding quote joins the path. */\n readonly parts: VerdictSentenceParts | undefined\n readonly test: PerTestOutcome | undefined\n /**\n * The run-level ledger the arbiter published, or ABSENT when it never ran. Absent is not\n * empty: a run with no member is a pre-422 run and nothing is stamped onto it at all.\n */\n readonly evidence: readonly MisdirectionRecordResult[] | undefined\n readonly rootPosture: MisdirectionRootPosture\n}\n\n/**\n * The steps a verdict's evidence touches — cited steps, the grounding quote's step, and the\n * run's ACTUAL failing step.\n *\n * The TWIN of `pathStepsOf` inside `schema/src/verdict/validate-analysis.ts`, which is module\n * private there. The two must agree: the stamp writes a `memoryOnPath` DECLARATION and the\n * validator recomputes membership over its own path, so a rule that drifted here would make\n * every stamped verdict disagree with its own recomputation. `misdirection-analysis.test.ts`\n * measures the agreement against the real validator — including the case where the author cites\n * a clean neighbour and never mentions the step that failed — rather than restating the rule.\n */\nexport function misdirectionPathSteps(\n verdict: Verdict,\n parts: VerdictSentenceParts | undefined,\n test: PerTestOutcome,\n): StepEvidence[] {\n const indexes = new Set<number>(verdict.evidence.citedSteps)\n if (parts !== undefined && 'stepIndex' in parts.groundingQuote) {\n indexes.add(parts.groundingQuote.stepIndex)\n }\n const failing = failingStepOf(test)\n if (failing !== undefined) indexes.add(failing.stepIndex)\n return test.steps.filter((step) => indexes.has(step.stepIndex))\n}\n\n/**\n * The validator posture this run is entitled to (422-11's two fail-closed options).\n *\n * ABSENT evidence keeps the historical surface byte-for-byte: `{}` is what every caller passed\n * before 422 and what `validateAnalysisAgainstHandoff` defaults to, so a run whose arbiter never\n * ran is validated exactly as it was. A PRESENT ledger — even an empty one — means the arbiter\n * ran and said something, which is what makes this run's producer a current gated one.\n */\nexport function misdirectionValidationOptions(\n evidence: readonly MisdirectionRecordResult[] | undefined,\n rootPosture: MisdirectionRootPosture,\n): AnalysisValidationOptions {\n return evidence === undefined ? {} : { gatedProducerEvidence: true, rootPosture }\n}\n\n/** One exposure's key: the (step, record) pair, never the record alone. */\nfunction exposureKey(stepIndex: number, recordId: string): string {\n return `${String(stepIndex)}\\u001f${recordId}`\n}\n\n/**\n * The block's one-word summary, in precedence order: a flip outranks everything, an explicitly\n * inconclusive row outranks an incomplete ledger, and `held` requires EVERY exposure covered by a\n * held row. An uncovered exposure reads `not-run` here and stays individually visible in\n * `results` — and the aggregate the validator computes reads the ROWS, never this word, so a\n * summary can never be the thing that exonerates a verdict.\n */\nfunction summarizeCrossCheck(\n rows: readonly MisdirectionRecordResult[],\n sites: readonly { readonly stepIndex: number; readonly recordId: string }[],\n): MisdirectionEvidence['crossCheck'] {\n if (rows.some((row) => row.crossCheck === 'flipped')) return 'flipped'\n if (rows.some((row) => row.crossCheck === 'inconclusive')) return 'inconclusive'\n const covered = new Set(rows.map((row) => exposureKey(row.stepIndex, String(row.recordId))))\n const complete = sites.every((site) =>\n covered.has(exposureKey(site.stepIndex, String(site.recordId))),\n )\n return complete && rows.every((row) => row.crossCheck === 'held') ? 'held' : 'not-run'\n}\n\n/** Why an empty ledger is empty — D-19's two postures do not mean the same thing. */\nfunction postureReason(posture: MisdirectionRootPosture): string | undefined {\n if (posture === 'no-eval-root') {\n return 'no evaluation root existed, so no record on this path could be cross-checked'\n }\n if (posture === 'broken-eval-root') {\n return 'the evaluation root could not be consulted, so no record on this path was cross-checked'\n }\n return undefined\n}\n\n/**\n * Stamp ONE verdict with the code-owned membership and the code-owned ledger.\n *\n * Three postures, and each is a different fact:\n *\n * - the arbiter never ran (`evidence === undefined`): the verdict is returned byte-identical,\n * because a run nobody measured is not a run this job may make new claims about;\n * - it ran and this verdict's path carries no low-trust record: nothing is stamped, and a\n * declaration the verdict arrived with is REMOVED rather than carried — there is no claim\n * here to back, so a block would be an answer to a question nobody asked;\n * - it ran and the path carries exposures: both members are replaced with values derived from\n * the run's own served briefs and the published rows, filtered to THIS member and to THIS\n * verdict's own exposures.\n *\n * The filter matters twice over. Rows for another member would be refused by the aggregate's key\n * integrity, and rows for an exposure this verdict's path does not contain would be refused as\n * \"an exposure no served brief recorded on this path\" — both correct refusals, and both avoidable\n * by handing the gate exactly the rows it is entitled to.\n */\nexport function stampVerdictMisdirectionEvidence(input: MisdirectionStampInput): Verdict {\n const { verdict, parts, test, evidence, rootPosture } = input\n if (evidence === undefined || test === undefined) return verdict\n\n const steps = misdirectionPathSteps(verdict, parts, test)\n const sites = deriveMemoryOnPathSites(steps)\n if (sites.length === 0) {\n if (verdict.memoryOnPath === undefined && verdict.misdirectionRuledOut === undefined) {\n return verdict\n }\n const bare = { ...verdict } as Record<string, unknown>\n delete bare.memoryOnPath\n delete bare.misdirectionRuledOut\n return bare as unknown as Verdict\n }\n\n const keys = new Set(sites.map((site) => exposureKey(site.stepIndex, String(site.recordId))))\n const rows = evidence.filter(\n (row) =>\n row.perTest === verdict.perTest && keys.has(exposureKey(row.stepIndex, String(row.recordId))),\n )\n const reason = postureReason(rootPosture)\n const block: MisdirectionEvidence = {\n crossCheck: summarizeCrossCheck(rows, sites),\n results: rows,\n ...(reason === undefined ? {} : { reason }),\n // D-19: the ONE exemption is ABSENCE, and only absence. A broken root publishes the same\n // empty ledger and earns nothing. The `rows.length === 0` clause is not belt-and-braces: the\n // validator answers on the backing BEFORE it reads the rows, so a marker beside a real ledger\n // would skip the ledger entirely.\n ...(rootPosture === 'no-eval-root' && rows.length === 0\n ? { backing: 'declared-only' as const }\n : {}),\n }\n return {\n ...verdict,\n memoryOnPath: deriveMemoryOnPath(steps),\n misdirectionRuledOut: block,\n } as Verdict\n}\n\n/** The flipped records a stamped block names — the only records harm may be attributed to. */\nexport function flippedRecordsOf(verdict: Verdict): string[] {\n const rows = verdict.misdirectionRuledOut?.results ?? []\n const records: string[] = []\n for (const row of rows) {\n if (row.crossCheck !== 'flipped') continue\n if (!records.includes(String(row.recordId))) records.push(String(row.recordId))\n }\n return records\n}\n\nexport interface AuthorTokenBudget {\n readonly estimate: (text: string) => number\n readonly inputBudget: number\n}\n\nexport interface AuthorRunAnalysisInput {\n readonly handoff: CompletedRunHandoff\n /** The deterministic floor exactly as the handler projects it — the merge base. */\n readonly floor: readonly Verdict[]\n /** One evidence pack per unknown member (plan 03's diet), pre-compaction. */\n readonly packs: readonly EvidencePack[]\n /** Per-test failure history for the context tier (D-08's input-for-reasoning). */\n readonly history: EvidenceHistoryLookup\n /**\n * D-01's TokenAccounting substrate entering as data. Absent → no compaction ladder\n * (rung 0, packs whole) — a host without accounting still authors, it just cannot\n * pre-shrink.\n */\n readonly tokenBudget?: AuthorTokenBudget\n /**\n * D-02's capability-gated screenshot bytes, sha-addressed. Absent ⇒ text-only per L9.\n */\n readonly readEvidenceBlob?: (sha: string) => Uint8Array | undefined\n /** The §1.4 `agent_context` parameter; defaults to the analyze-run provenance line. */\n readonly agentContext?: string\n /**\n * 422 D-17/D-20: the run-level circularity ledger the pre-enqueue arbiter published, exactly\n * as it reached the analysed handoff bytes.\n *\n * It enters the request as DATA — one context-tier block per analyzed member — and it enters\n * the gate as AUTHORITY, through {@link stampVerdictMisdirectionEvidence}, which overwrites\n * whatever the model answered about it. The author is still asked for\n * `memoryMisdirectionRuledOut`: the boolean is the author's own claim and the ledger is what\n * decides whether that claim is worth anything.\n *\n * ABSENT means the arbiter never ran, and absence is the whole of the transition guarantee —\n * the validator is then called with the historical options and no verdict is stamped at all.\n */\n readonly misdirectionEvidence?: readonly MisdirectionRecordResult[]\n /** D-19's posture; read only when a ledger is present. Fail-closed default: `'eval-root'`. */\n readonly rootPosture?: MisdirectionRootPosture\n}\n\nexport interface AuthorRunAnalysisResult {\n /** The merged array: floor order, unknown members upgraded, all else byte-identical. */\n readonly verdicts: Verdict[]\n /** LLM sentence parts for the UPGRADED members only, joined by perTest (D-06). */\n readonly authoredParts: VerdictSentenceParts[]\n /** The D-01 ladder outcome, surfaced — `overBudget` is never swallowed. */\n readonly compaction: {\n readonly rung: CompactedEvidence['rung']\n readonly overBudget: boolean\n readonly estimatedTokens: number\n }\n /** Analyzed tests that failed validation after the single repair and kept their floor. */\n readonly degradedTests: number[]\n /**\n * For each degraded member, the cited steps of the LAST candidate the author built for it.\n *\n * The floor a refused member falls back to cites nothing, which is correct for a verdict that\n * asserts nothing — but the circularity disclosure is computed over the verdict's PATH, so a\n * floor with no citation discloses only the failing step's exposures. A claim refused because a\n * record on a cited step flipped would then land as an `unknown` beside a HELD ledger, having\n * forgotten the record that caused it. The handler unions these back in (422-15).\n */\n readonly degradedPaths: readonly {\n readonly perTest: number\n readonly citedSteps: readonly number[]\n }[]\n /**\n * What this authorship SPENT, recorded once (422 D-20).\n *\n * Once, because `recordLlmAuthorship` memoizes: a resumed job reads the recorded value and\n * never reaches this function, so the calls below can happen exactly one time across every\n * attempt of one job. Capped, because the loop runs at most `1 + AUTHOR_REPAIR_CAP` times\n * however persistent the answer is — the evidence-informed repair is the SAME budget the\n * parse-repair round-trip already had, never a second one bought by the ledger.\n */\n readonly usage: {\n readonly modelCalls: number\n readonly repairCalls: number\n /** The compaction ladder's estimate; `0` when no accounting substrate was injected. */\n readonly estimatedTokens: number\n }\n}\n\n// ---------------------------------------------------------------------------------------\n// The wire contract: what the model is asked to return, and the zod shape that reads it.\n// `class` and `confidence` are deliberately loose here — the closed union and the exact\n// [0,1] bound are enforced per-test by `validateAnalysisAgainstHandoff`, so a wrong value\n// becomes a NAMED per-test reject feeding the repair message instead of an opaque\n// whole-output parse failure.\n// ---------------------------------------------------------------------------------------\n\nconst GroundingQuoteWire = z.union([\n z.object({ stepIndex: z.number(), quote: z.string() }),\n z.object({ source: z.literal('test-outcome'), quote: z.string() }),\n])\n\nconst AuthoredTestWire = z.object({\n testIndex: z.number(),\n class: z.string(),\n confidence: z.number(),\n memoryMisdirectionRuledOut: z.boolean(),\n citedSteps: z.array(z.number()),\n citedArtifacts: z.array(z.object({ id: z.string(), sha: z.string() })).default([]),\n rationale: z.string(),\n groundingQuote: GroundingQuoteWire,\n discriminator: z.string(),\n nextAction: z.string(),\n links: z.array(z.string()).default([]),\n})\n\nconst AuthorOutputWire = z.object({\n tests: z.array(AuthoredTestWire),\n patternNote: z.string().optional(),\n})\n\ntype AuthoredTestEntry = z.infer<typeof AuthoredTestWire>\n\n/** One restatement of the output contract — the stable tier and the repair message share it. */\nconst OUTPUT_CONTRACT =\n 'Return exactly ONE JSON object, no markdown fences, shaped {\"tests\": [...]} with one ' +\n 'entry per analyzed test. Each entry carries: testIndex (number, copied from the ' +\n 'evidence), class (one of test_bug, app_bug, environment, flake, config_error, ' +\n 'llm_error, unknown, timeout — unknown is an honest abstention), confidence (a number ' +\n 'inside [0, 1]), memoryMisdirectionRuledOut (boolean), citedSteps (array of stepIndex ' +\n 'numbers you actually relied on), citedArtifacts (array of {id, sha} artifact refs, [] ' +\n 'when none), rationale (your reasoning trace — advisory, never shown as the sentence), ' +\n 'groundingQuote ({\"stepIndex\": n, \"quote\": s} quoting captured evidence VERBATIM, or ' +\n '{\"source\": \"test-outcome\", \"quote\": s} for a test with zero captured steps), ' +\n 'discriminator (what distinguishes THIS failure), nextAction (the one concrete next ' +\n 'step), and links (agentqa:// entity URIs, [] when none). An optional top-level ' +\n '\"patternNote\" string may describe a cross-test pattern.'\n\n// ---------------------------------------------------------------------------------------\n// Deterministic JSON repair — the curator-author idiom, copied (agent may not import cli).\n// Fence strip, first-object extraction, trailing-comma removal; anything still unreadable\n// throws and becomes a whole-output reject for every pending test.\n// ---------------------------------------------------------------------------------------\n\nfunction removeTrailingCommas(json: string): string {\n let output = ''\n let inString = false\n let escaped = false\n for (let index = 0; index < json.length; index += 1) {\n const char = json[index]!\n if (inString) {\n output += char\n if (escaped) escaped = false\n else if (char === '\\\\') escaped = true\n else if (char === '\"') inString = false\n continue\n }\n if (char === '\"') {\n inString = true\n output += char\n continue\n }\n if (char === ',') {\n let lookahead = index + 1\n while (/\\s/.test(json[lookahead] ?? '')) lookahead += 1\n if (json[lookahead] === '}' || json[lookahead] === ']') continue\n }\n output += char\n }\n return output\n}\n\nfunction parseJsonWithRepair(text: string): unknown {\n const fenced = /```(?:json)?[ \\t]*\\r?\\n?([\\s\\S]*?)```/i.exec(text)\n const source = (fenced?.[1] ?? text).trim()\n const objectStart = source.indexOf('{')\n if (objectStart < 0) throw new Error('no JSON object found in the output')\n\n const expectedClosers: Array<'}' | ']'> = []\n let inString = false\n let escaped = false\n let objectEnd = -1\n for (let index = objectStart; index < source.length; index += 1) {\n const char = source[index]!\n if (inString) {\n if (escaped) escaped = false\n else if (char === '\\\\') escaped = true\n else if (char === '\"') inString = false\n continue\n }\n if (char === '\"') inString = true\n else if (char === '{') expectedClosers.push('}')\n else if (char === '[') expectedClosers.push(']')\n else if (char === '}' || char === ']') {\n const expected = expectedClosers.pop()\n if (expected !== char) throw new Error(`mismatched JSON delimiter ${char}`)\n if (expectedClosers.length === 0) {\n objectEnd = index\n break\n }\n }\n }\n if (inString) throw new Error('unterminated JSON string in the output')\n\n const candidate =\n objectEnd >= 0\n ? source.slice(objectStart, objectEnd + 1)\n : `${source.slice(objectStart)}${[...expectedClosers].reverse().join('')}`\n\n try {\n return JSON.parse(removeTrailingCommas(candidate))\n } catch {\n throw new Error('JSON parse failed after deterministic repair')\n }\n}\n\n// ---------------------------------------------------------------------------------------\n// Prompt composition: plan 03's stages, composed — never reimplemented.\n// ---------------------------------------------------------------------------------------\n\nfunction stableTier(): PromptTierBlock[] {\n return [\n {\n title: 'Role',\n body:\n 'You are the analyze-run verdict author. A test run has finished with failed ' +\n 'member tests whose deterministic classifier found no signal; you classify each ' +\n 'one from its captured evidence and author the typed parts of one honest sentence ' +\n 'a QA engineer can act on. Never invent an observation: every groundingQuote must ' +\n 'be a verbatim contiguous substring of the captured evidence you cite ' +\n `(searched fields: ${QUOTE_SEARCHED_STEP_FIELDS.join(', ')}).`,\n },\n { title: 'Output contract', body: OUTPUT_CONTRACT },\n {\n title: 'The four obligations',\n body:\n 'For every analyzed test: (a) ground the sentence in a QUOTED observation from ' +\n 'captured evidence; (b) state a discriminator — what distinguishes this failure ' +\n 'from its neighbours, e.g. whether the same step passed on the previous build; ' +\n '(c) recurrence context is rendered LIVE by the product from recorded history — ' +\n 'never bake counts into your prose; (d) recommend the one concrete next action.',\n },\n {\n title: 'Memory misdirection',\n body:\n 'Each failing step shows the memory brief that was served to it. Before answering ' +\n 'a class that moves no trust (app_bug, flake, environment, config_error) while ' +\n 'candidate or low-trust memory was on the failing path, you must have explicitly ' +\n 'ruled out that the served memory misdirected the run — set ' +\n 'memoryMisdirectionRuledOut true only when the evidence supports it; otherwise ' +\n 'answer unknown or a trust-moving class.',\n },\n {\n title: 'Cross-test patterns',\n body:\n 'You see the WHOLE run at once on purpose. Look for one cause behind many reds — ' +\n 'a shared failing element, route or infrastructure signal across tests — and let ' +\n 'it inform each verdict and discriminator; note it in patternNote when present.',\n },\n ]\n}\n\nfunction historyLine(pack: EvidencePack, history: EvidenceHistoryLookup): string {\n const record = history({ filePath: pack.filePath, testName: pack.testName })\n if (record === undefined) {\n return `- test ${pack.testIndex} (${pack.testName}): no recorded history`\n }\n const window = record.lastOutcomes\n .map((entry) => `build ${entry.buildOrdinal}: ${entry.passed ? 'passed' : 'failed'}`)\n .join(', ')\n return (\n `- test ${pack.testIndex} (${pack.testName}): ${record.passes} passes, ` +\n `${record.failures} failures, ${record.heals} heals, flakeCount ${record.flakeCount}` +\n (window === '' ? '' : `; recent: ${window}`)\n )\n}\n\n/**\n * One cross-check row, rendered for the prompt (422 D-20).\n *\n * The row's identity digests are deliberately NOT rendered: they are integrity material for the\n * gate, they cost tokens, and an author cannot act on them. What an author can act on is which\n * record was checked, on which step, and what removing it did.\n */\nfunction crossCheckLine(row: MisdirectionRecordResult): string {\n const samples = row.samples === undefined ? '' : `; k=${String(row.samples.k)}`\n const reason = row.reason === undefined ? '' : `; ${row.reason}`\n return (\n `- test ${String(row.perTest)}, step ${String(row.stepIndex)}, record ` +\n `${String(row.recordId)}: ${row.crossCheck}${reason}${samples}`\n )\n}\n\n/**\n * The arbiter's own answer about this run, as reasoning input (422 D-20).\n *\n * DATA, not an instruction. The block tells the author what the deterministic removal cross-check\n * measured for the records this run served on its failing paths; the author still answers\n * `memoryMisdirectionRuledOut` for itself, and the code still decides — after the author has\n * spoken — whether the ledger supports the class the author chose. Omitted entirely when the\n * arbiter never ran, so a pre-422 run's request is byte-identical to what it always was.\n */\nfunction crossCheckTier(\n packs: readonly EvidencePack[],\n evidence: readonly MisdirectionRecordResult[] | undefined,\n): PromptTierBlock[] {\n if (evidence === undefined) return []\n const analyzed = new Set(packs.map((pack) => pack.testIndex))\n const rows = evidence.filter((row) => analyzed.has(row.perTest))\n return [\n {\n title: 'Memory misdirection cross-check (reasoning input)',\n body:\n 'The deterministic removal cross-check already ran for the low-trust records this run ' +\n 'served on the failing paths below. `flipped` means removing the record changed the ' +\n 'outcome — the served memory is implicated. `held` means it did not. `inconclusive` ' +\n 'and `not-run` mean nothing was established:\\n' +\n (rows.length === 0\n ? '- no record on an analyzed test\\u2019s failing path was cross-checked'\n : rows.map(crossCheckLine).join('\\n')),\n },\n ]\n}\n\nfunction contextTier(\n handoff: CompletedRunHandoff,\n packs: readonly EvidencePack[],\n history: EvidenceHistoryLookup,\n evidence: readonly MisdirectionRecordResult[] | undefined,\n): PromptTierBlock[] {\n return [\n {\n title: 'Run facts',\n body:\n `Run ${String(handoff.runId)} on product scope ${handoff.scope.key} ` +\n `(build ${handoff.buildOrdinal}, ${handoff.executionContext}); aggregate verdict ` +\n `${handoff.aggregateVerdict}; ${handoff.tests.length} member tests, ` +\n `${packs.length} analyzed here (the unknown-verdict failures).`,\n },\n {\n title: 'Failure history (reasoning input)',\n body:\n 'Recorded outcome history per analyzed test — evidence for flake-vs-app_bug ' +\n 'reasoning, not prose to restate:\\n' +\n packs.map((pack) => historyLine(pack, history)).join('\\n'),\n },\n ...crossCheckTier(packs, evidence),\n ]\n}\n\nfunction volatileTier(packs: readonly EvidencePack[]): PromptTierBlock[] {\n return packs.map((pack) => ({\n title: `Test ${pack.testIndex}: ${pack.testName}`,\n body: canonicalJson(pack),\n }))\n}\n\n// ---------------------------------------------------------------------------------------\n// The D-02 request gate: images attach iff vision + reader + surviving refs.\n// ---------------------------------------------------------------------------------------\n\nfunction collectImages(\n packs: readonly EvidencePack[],\n readEvidenceBlob: ((sha: string) => Uint8Array | undefined) | undefined,\n vision: boolean,\n): Uint8Array[] {\n if (!vision || readEvidenceBlob === undefined) return []\n const seen = new Set<string>()\n const images: Uint8Array[] = []\n for (const pack of packs) {\n for (const ref of pack.screenshotRefs) {\n if (images.length >= MAX_AUTHOR_IMAGES) return images\n if (seen.has(ref.sha)) continue\n seen.add(ref.sha)\n const bytes = readEvidenceBlob(ref.sha)\n if (bytes === undefined) continue\n images.push(bytes)\n }\n }\n return images\n}\n\n// ---------------------------------------------------------------------------------------\n// Candidate assembly and the merge law.\n// ---------------------------------------------------------------------------------------\n\ninterface CandidatePair {\n readonly verdict: Verdict\n readonly parts: VerdictSentenceParts\n}\n\n/** Build the candidate pair for one wire entry — producer FORCED code-side (never the model). */\nfunction candidateOf(entry: AuthoredTestEntry): CandidatePair {\n const citedArtifacts: ArtifactRef[] = entry.citedArtifacts.map((ref) => ({\n id: ref.id,\n sha: ref.sha,\n }))\n const verdict = {\n class: entry.class,\n producer: 'analyze-run',\n confidence: entry.confidence,\n evidence: {\n citedSteps: [...entry.citedSteps],\n citedAnchors: [],\n citedArtifacts,\n rationale: entry.rationale,\n },\n memoryMisdirectionRuledOut: entry.memoryMisdirectionRuledOut,\n perTest: entry.testIndex,\n } as Verdict\n const parts: VerdictSentenceParts = {\n perTest: entry.testIndex,\n groundingQuote: entry.groundingQuote as VerdictGroundingQuote,\n discriminator: entry.discriminator,\n nextAction: entry.nextAction,\n links: [...entry.links],\n }\n return { verdict, parts }\n}\n\ninterface AttemptOutcome {\n readonly accepted: Map<number, CandidatePair>\n readonly rejects: { perTest: number; reason: string }[]\n /**\n * The cited steps of the candidate built for each pending test — accepted or refused.\n *\n * Kept because a REFUSED claim's citation is the only record of which steps the analysis was\n * actually about, and the floor it degrades to cites nothing. The circularity disclosure is\n * computed over a verdict's path, so a floor that forgot the citation would also forget every\n * exposure outside the failing step — including, in the worst case, the record that flipped.\n */\n readonly citedByTest: Map<number, readonly number[]>\n}\n\n/**\n * Parse one model answer and validate the candidates for the still-pending tests.\n * A whole-output parse failure rejects every pending test with one named reason; a\n * per-test validation failure rejects that test alone.\n */\nfunction evaluateAttempt(\n text: string,\n pending: ReadonlySet<number>,\n input: AuthorRunAnalysisInput,\n): AttemptOutcome {\n const handoff = input.handoff\n let entries: AuthoredTestEntry[]\n try {\n const wire = AuthorOutputWire.parse(parseJsonWithRepair(text))\n entries = wire.tests\n } catch (error) {\n const reason =\n 'the output was not one parseable JSON object matching the contract: ' +\n (error instanceof Error ? error.message : String(error))\n return {\n accepted: new Map(),\n rejects: [...pending].map((perTest) => ({ perTest, reason })),\n citedByTest: new Map(),\n }\n }\n\n // First entry per testIndex wins; entries for tests outside the pending analyzed set are\n // discarded — the author upgrades unknown floor members ONLY, so a re-classing of a\n // deterministic member is not even a candidate.\n const byTest = new Map<number, AuthoredTestEntry>()\n for (const entry of entries) {\n if (!pending.has(entry.testIndex) || byTest.has(entry.testIndex)) continue\n byTest.set(entry.testIndex, entry)\n }\n\n const rejects: { perTest: number; reason: string }[] = []\n const candidates = new Map<number, CandidatePair>()\n const citedByTest = new Map<number, readonly number[]>()\n const testsByIndex = new Map(handoff.tests.map((test) => [test.testIndex, test]))\n const rootPosture = input.rootPosture ?? 'eval-root'\n for (const perTest of pending) {\n const entry = byTest.get(perTest)\n if (entry === undefined) {\n rejects.push({ perTest, reason: `the output carries no entry for testIndex ${perTest}` })\n continue\n }\n const pair = candidateOf(entry)\n citedByTest.set(perTest, [...pair.verdict.evidence.citedSteps])\n // THE STAMP GOES ON BEFORE THE GATE SEES THE CANDIDATE (422 D-17/D-18). Stamping after\n // validation would hand the gate a verdict carrying no evidence — which it would refuse for\n // the wrong reason, spending the one repair on a message the author cannot act on — and then\n // decorate the refused verdict afterwards. The evidence is code-owned either way; what the\n // ordering decides is whether the gate got to USE it.\n candidates.set(perTest, {\n ...pair,\n verdict: stampVerdictMisdirectionEvidence({\n verdict: pair.verdict,\n parts: pair.parts,\n test: testsByIndex.get(perTest),\n evidence: input.misdirectionEvidence,\n rootPosture,\n }),\n })\n }\n\n if (candidates.size > 0) {\n const ordered = [...candidates.values()]\n const validation = validateAnalysisAgainstHandoff(\n {\n schemaVersion: CURRENT_ANALYSIS_SCHEMA_VERSION,\n runId: String(handoff.runId),\n verdicts: ordered.map((pair) => pair.verdict),\n parts: ordered.map((pair) => pair.parts),\n },\n handoff,\n misdirectionValidationOptions(input.misdirectionEvidence, rootPosture),\n )\n if (!validation.ok) {\n const rejectedTests = new Set(validation.rejects.map((reject) => reject.perTest))\n rejects.push(...validation.rejects)\n for (const perTest of rejectedTests) candidates.delete(perTest)\n }\n }\n\n return { accepted: candidates, rejects, citedByTest }\n}\n\nfunction repairFeedback(rejects: readonly { perTest: number; reason: string }[]): string {\n return [\n '## Validation feedback',\n '',\n 'Your previous output failed validation for the tests below. Return ONE corrected ' +\n 'JSON object with an entry for EVERY analyzed test, correcting each named failure:',\n ...rejects.map((reject) => `- test ${reject.perTest}: ${reject.reason}`),\n '',\n OUTPUT_CONTRACT,\n ].join('\\n')\n}\n\n/**\n * The author: compose plan 03's stages around ONE `model.generate` call, repair once,\n * degrade per test, merge upgrade-only-unknown. Transport failures propagate uncaught —\n * the job's declared bound adjudicates those, never this function.\n */\nexport async function authorRunAnalysis(\n model: JobModelCapability,\n input: AuthorRunAnalysisInput,\n): Promise<AuthorRunAnalysisResult> {\n // The ladder runs iff the accounting substrate was injected; a host without it authors\n // over the packs whole (rung 0) — doc'd on `tokenBudget`.\n const compacted: CompactedEvidence =\n input.tokenBudget === undefined\n ? {\n packs: input.packs,\n rung: 0,\n overBudget: false,\n estimatedTokens: 0,\n }\n : compactEvidencePacks(input.packs, input.tokenBudget.estimate, input.tokenBudget.inputBudget)\n\n const unknownFloor = new Set(\n input.floor.filter((verdict) => verdict.class === 'unknown').map((verdict) => verdict.perTest),\n )\n // POST-compaction packs on purpose: rung 1 stripping the refs IS the ladder's text-only\n // degradation, so the vision gate must never re-read refs from the uncompacted packs.\n const analyzed = compacted.packs\n .map((pack) => pack.testIndex)\n .filter((testIndex) => unknownFloor.has(testIndex))\n\n const baseRequest = buildTieredPrompt({\n agent_context:\n input.agentContext ??\n 'analyze-run: authoring root-cause verdicts and sentence parts for one completed run',\n stable: stableTier(),\n context: contextTier(input.handoff, compacted.packs, input.history, input.misdirectionEvidence),\n volatile: volatileTier(compacted.packs),\n })\n const images = collectImages(compacted.packs, input.readEvidenceBlob, model.vision === true)\n const request: JobModelRequest =\n images.length === 0 ? baseRequest : { ...baseRequest, images }\n\n const accepted = new Map<number, CandidatePair>()\n let pending = new Set(analyzed)\n let lastRejects: readonly { perTest: number; reason: string }[] = []\n const lastCited = new Map<number, readonly number[]>()\n let modelCalls = 0\n\n for (let attempt = 0; attempt <= AUTHOR_REPAIR_CAP && pending.size > 0; attempt += 1) {\n const attemptRequest: JobModelRequest =\n attempt === 0\n ? request\n : { ...request, prompt: `${request.prompt}\\n\\n${repairFeedback(lastRejects)}` }\n const output = await model.generate(attemptRequest)\n modelCalls += 1\n const outcome = evaluateAttempt(output.text, pending, input)\n for (const [perTest, cited] of outcome.citedByTest) lastCited.set(perTest, cited)\n for (const [perTest, pair] of outcome.accepted) accepted.set(perTest, pair)\n pending = new Set([...pending].filter((perTest) => !accepted.has(perTest)))\n lastRejects = outcome.rejects\n }\n\n // The merge law, in one place: replace iff the floor member is `unknown` AND a validated\n // candidate exists; every other member passes through byte-identical.\n const verdicts = input.floor.map((floorVerdict) => {\n if (floorVerdict.class !== 'unknown') return floorVerdict\n return accepted.get(floorVerdict.perTest)?.verdict ?? floorVerdict\n })\n const authoredParts = analyzed\n .filter((testIndex) => accepted.has(testIndex))\n .map((testIndex) => (accepted.get(testIndex) as CandidatePair).parts)\n\n return {\n verdicts,\n authoredParts,\n compaction: {\n rung: compacted.rung,\n overBudget: compacted.overBudget,\n estimatedTokens: compacted.estimatedTokens,\n },\n degradedTests: analyzed.filter((testIndex) => !accepted.has(testIndex)),\n degradedPaths: analyzed\n .filter((testIndex) => !accepted.has(testIndex))\n .map((perTest) => ({ perTest, citedSteps: lastCited.get(perTest) ?? [] })),\n usage: {\n modelCalls,\n repairCalls: Math.max(0, modelCalls - 1),\n estimatedTokens: compacted.estimatedTokens,\n },\n }\n}\n","// The one tiered prompt builder (Phase 389, plan 03 — spec `qa-agent-and-surfaces.md` §1.4, D-04).\n//\n// THE TIER LAW. Every job prompt is three tiers assembled in one fixed order:\n//\n// stable role, output contract, invariant instructions — renders into `system`. These\n// bytes lead and never vary per run, so provider prompt caches see the same\n// prefix every call.\n// context run-level facts — renders first into `prompt`.\n// volatile per-test evidence packs — renders last into `prompt`.\n//\n// `agent_context` names the calling agent and purpose, and lands in the stable tier:\n// analyze-run passes its own (plan 04); 392's chat passes chat's. That parameter — not a\n// second builder, not a persona fork — is how the six job types share ONE prompt idiom\n// (§1.4: \"parameterized, not separate personas\").\n//\n// THE 392-EXTENDS CONTRACT. This module ships the SHAPE and the renderer only. What goes in\n// each tier — the analyze-run section content — is authored by the caller (plan 04 first,\n// 392's chat after). A caller extends this builder by passing richer blocks, never by\n// editing the assembly order or minting a sibling renderer; two prompt idioms is exactly\n// the refactor D-04 exists to prevent.\n//\n// TEXT BY DESIGN. The output is the TEXT legs of `JobModelRequest` — `{system?, prompt}`.\n// D-02's capability-gated screenshot channel rides the request's optional images leg,\n// attached by the AUTHOR at request assembly (plan 04): image parts are evidence payload,\n// not tier prose, so the renderer has no image awareness and 392 inherits a clean text\n// contract.\n//\n// Deterministic by construction: pure string assembly over the inputs, no clock, no\n// randomness, no host APIs — identical tier inputs produce byte-identical output.\n\nimport type { JobModelRequest } from '../jobs/record-llm-authorship.js'\n\n/**\n * One named section inside a tier. `title` renders as a `##` header; `body` is the\n * caller's prose, carried verbatim.\n */\nexport interface PromptTierBlock {\n readonly title: string\n readonly body: string\n}\n\nexport interface TieredPromptInput {\n /** Who is asking and why — stable-tier provenance (§1.4's `agent_context` parameter). */\n readonly agent_context: string\n /** Invariant instructions: role, output contract. Renders into `system`. */\n readonly stable: readonly PromptTierBlock[]\n /** Run-level facts. Renders into `prompt`, before the volatile tier. */\n readonly context: readonly PromptTierBlock[]\n /** Per-test evidence. Renders into `prompt`, last — the cache-hostile bytes trail. */\n readonly volatile: readonly PromptTierBlock[]\n}\n\n/** The stable separator between rendered blocks — one blank line, never accumulated. */\nconst BLOCK_SEPARATOR = '\\n\\n'\n\nfunction renderBlock(block: PromptTierBlock): string {\n return `## ${block.title}${BLOCK_SEPARATOR}${block.body}`\n}\n\n/**\n * Assemble the three tiers into the text legs of a `JobModelRequest`.\n *\n * An empty tier contributes zero bytes — no dangling header, no trailing separator —\n * because blocks are joined, never appended, so structure exists only where content does.\n */\nexport function buildTieredPrompt(input: TieredPromptInput): JobModelRequest {\n const system = [\n `Agent context: ${input.agent_context}`,\n ...input.stable.map(renderBlock),\n ].join(BLOCK_SEPARATOR)\n\n const prompt = [...input.context.map(renderBlock), ...input.volatile.map(renderBlock)].join(\n BLOCK_SEPARATOR,\n )\n\n return { system, prompt }\n}\n","// The D-02 evidence diet and the D-01 compaction ladder (Phase 389, plan 03).\n//\n// WHAT A PACK IS. One per unknown-verdict failed test: the failing step plus a bounded\n// neighbor window, QUOTING StepEvidence fields verbatim — `stepText`,\n// `verifierVerdict.reasoning`, each sub-action's `plan` and `result.error`, and the\n// reportedValue/aiJudgment/assertOutcome/termination/limitStop/conditionVerdicts blocks when\n// present — so the authored sentence can cite captured bytes rather than paraphrase them.\n// Assembly (here) is kept separate from rendering (plan 04's author feeds packs into the\n// prompt's volatile tier), which is what makes the ladder testable on bytes.\n//\n// THE TWO FORCED CHANNELS (D-02). Every pack carries (1) the test's prior-build outcome,\n// derived from a caller-injected history record, and (2) the failing step's `servedBrief`\n// plus its serve-time `retrievalTrace` — rendered so the author can honestly set\n// memoryMisdirectionRuledOut. Compaction squeezes the WINDOW, never these channels\n// (house law: efficacy over token economy); they are byte-identical through every rung.\n//\n// THE SCREENSHOT CHANNEL (D-02, L9). The failing step's `subActions[].decisionScreenshotRef`\n// entries travel as REFS deduped by sha, never bytes: this package has no fs. Plan 04's\n// author resolves bytes through the readEvidenceBlob capability (bound in plan 06) and\n// attaches image parts only when the v46 vision negotiation allows. Rung 1 of the ladder\n// strips the refs — text-only BYOM degradation is a deterministic rung, not an ad-hoc drop.\n//\n// NO IMPORTED ESTIMATOR (D-01). Token estimation arrives as injected data — a\n// `(text) => number` plus a numeric budget — satisfying the TokenAccounting substrate\n// without this package importing model. Plan 06's binding passes\n// `TokenAccounting.estimate` through the capability.\n\nimport { canonicalJson } from '@vostride/agent-qa-schema'\nimport type {\n AiJudgmentEvidence,\n ArtifactRef,\n AssertValueEvidence,\n CompletedRunHandoff,\n ConditionVerdictsEvidence,\n LimitStopEvidence,\n MemberTestOutcome,\n PerTestOutcome,\n ServedBrief,\n ServedRetrievalTraceV1,\n StepEvidence,\n TerminationEvidence,\n} from '@vostride/agent-qa-schema'\n\n/**\n * Neighbor steps quoted either side of the failing step.\n *\n * Pinned, not config (386 D-15); retune from operational evidence: raise if discriminators\n * in real transcripts routinely cite out-of-window steps; never add a knob for it.\n */\nexport const EVIDENCE_WINDOW_STEPS = 2\n\n/**\n * The rung-4 per-field quote cap, in characters.\n *\n * Pinned, not config (386 D-15); retune from operational evidence: raise if discriminating\n * error text is routinely cut mid-signal at this cap in real over-budget transcripts.\n */\nexport const QUOTE_FIELD_CAP = 500\n\n/** The stable test identity the history lookup is keyed by — filePath + testName, NEVER testId. */\nexport interface EvidenceTestIdentity {\n readonly filePath: string\n readonly testName: string\n}\n\nexport interface EvidenceOutcomeEntry {\n readonly buildOrdinal: number\n readonly passed: boolean\n}\n\n/**\n * Minimal structural mirror of knowledge-local's `TestOutcomeHistory` (plan 02). Declared\n * locally on purpose: this package never imports knowledge-local; the capability that feeds\n * it is declared in plan 04's kinds.ts change and bound in plan 06, and structural typing\n * makes the real record assignable here unchanged.\n */\nexport interface EvidenceTestHistory {\n readonly passes: number\n readonly failures: number\n readonly heals: number\n readonly flakeCount: number\n readonly lastOutcomes: readonly EvidenceOutcomeEntry[]\n readonly lastBuildOrdinal: number | undefined\n}\n\nexport type EvidenceHistoryLookup = (\n identity: EvidenceTestIdentity,\n) => EvidenceTestHistory | undefined\n\n/**\n * Forced channel 1: the prior-build outcome, always typed, never faked. `no-history` = the\n * lookup answered nothing for this identity; `no-prior-build` = history exists but holds no\n * entry STRICTLY below the current build — mirroring plan 02's `priorBuildOutcome` law\n * (greatest ordinal strictly below current, typed absence otherwise).\n */\nexport type PriorBuildChannel =\n | { readonly kind: 'no-history' }\n | { readonly kind: 'no-prior-build' }\n | { readonly kind: 'prior-build'; readonly buildOrdinal: number; readonly passed: boolean }\n\n/**\n * Forced channel 2: the failing step's served brief and serve-time retrieval trace,\n * verbatim. `no-failing-step` is the zero-step posture — a suite-bootstrap failure recorded\n * no step, so there is no brief to quote and none is fabricated.\n */\nexport type MemoryChannel =\n | { readonly kind: 'no-failing-step' }\n | {\n readonly kind: 'served'\n readonly servedBrief: ServedBrief\n readonly retrievalTrace: ServedRetrievalTraceV1 | undefined\n }\n\nexport interface EvidenceSubActionQuote {\n readonly plan: string\n readonly error?: string\n}\n\nexport interface EvidenceStepQuote {\n readonly stepIndex: number\n readonly role: 'failing' | 'neighbor'\n readonly stepText: string\n readonly verifierReasoning: string\n readonly subActions: readonly EvidenceSubActionQuote[]\n readonly reportedValue?: string\n readonly aiJudgment?: AiJudgmentEvidence\n readonly assertOutcome?: AssertValueEvidence\n readonly termination?: TerminationEvidence\n readonly limitStop?: LimitStopEvidence\n readonly conditionVerdicts?: ConditionVerdictsEvidence\n}\n\nexport interface EvidencePack {\n readonly testIndex: number\n readonly filePath: string\n readonly testName: string\n readonly outcome: MemberTestOutcome\n /** The failing step's recorded index. Absent exactly when the test captured zero steps. */\n readonly failingStepIndex?: number\n readonly steps: readonly EvidenceStepQuote[]\n /** The zero-step posture: the test-level outcome quoted verbatim, no fabricated step. */\n readonly testLevelQuote?: string\n /** The failing step's decision-screenshot refs, deduped by sha. Refs only, never bytes. */\n readonly screenshotRefs: readonly ArtifactRef[]\n readonly priorBuild: PriorBuildChannel\n readonly memory: MemoryChannel\n}\n\n/**\n * The failing step: the FIRST step whose verifier verdict failed, else the LAST step (a\n * failed test whose steps all verified — e.g. a timeout after the last verified step —\n * still has its most recent step as the evidence anchor). Returns the ARRAY position, so\n * the window below can never index outside `steps[]` whatever the recorded `stepIndex`\n * values are.\n */\nfunction failingStepPosition(steps: readonly StepEvidence[]): number {\n const failed = steps.findIndex((step) => !step.verifierVerdict.pass)\n return failed === -1 ? steps.length - 1 : failed\n}\n\nfunction quoteStep(step: StepEvidence, role: 'failing' | 'neighbor'): EvidenceStepQuote {\n return {\n stepIndex: step.stepIndex,\n role,\n stepText: step.stepText,\n verifierReasoning: step.verifierVerdict.reasoning,\n subActions: step.subActions.map((subAction) => ({\n plan: subAction.plan,\n ...(subAction.result.error === undefined ? {} : { error: subAction.result.error }),\n })),\n ...(step.reportedValue === undefined ? {} : { reportedValue: step.reportedValue.value }),\n ...(step.aiJudgment === undefined ? {} : { aiJudgment: step.aiJudgment }),\n ...(step.assertOutcome === undefined ? {} : { assertOutcome: step.assertOutcome }),\n ...(step.termination === undefined ? {} : { termination: step.termination }),\n ...(step.limitStop === undefined ? {} : { limitStop: step.limitStop }),\n ...(step.conditionVerdicts === undefined\n ? {}\n : { conditionVerdicts: withoutFileText(step.conditionVerdicts) }),\n }\n}\n\n/** A saved file's text never enters a prompt (439 D-17, 436 D-20): keep only its verdicts. */\nfunction withoutFileText(block: ConditionVerdictsEvidence): ConditionVerdictsEvidence {\n return {\n ...block,\n conditions: block.conditions.map(({ file, ...condition }) => ({\n ...condition,\n ...(file === undefined ? {} : { file: { name: file.name, content: file.content } }),\n })),\n }\n}\n\n/** Dedupe by sha, first occurrence wins — the refs are content-addressed, so equal sha = equal bytes. */\nfunction collectScreenshotRefs(step: StepEvidence): ArtifactRef[] {\n const seen = new Set<string>()\n const refs: ArtifactRef[] = []\n for (const subAction of step.subActions) {\n const ref = subAction.decisionScreenshotRef\n if (ref === undefined || seen.has(ref.sha)) continue\n seen.add(ref.sha)\n refs.push(ref)\n }\n return refs\n}\n\n/** Plan 02's strictly-below law, mirrored: the greatest ordinal STRICTLY below current. */\nfunction priorBuildChannel(\n history: EvidenceTestHistory | undefined,\n currentBuildOrdinal: number,\n): PriorBuildChannel {\n if (history === undefined) return { kind: 'no-history' }\n let prior: EvidenceOutcomeEntry | undefined\n for (const entry of history.lastOutcomes) {\n if (entry.buildOrdinal >= currentBuildOrdinal) continue\n if (prior === undefined || entry.buildOrdinal >= prior.buildOrdinal) prior = entry\n }\n if (prior === undefined) return { kind: 'no-prior-build' }\n return { kind: 'prior-build', buildOrdinal: prior.buildOrdinal, passed: prior.passed }\n}\n\nfunction packFor(\n test: PerTestOutcome,\n currentBuildOrdinal: number,\n history: EvidenceHistoryLookup,\n): EvidencePack {\n const priorBuild = priorBuildChannel(\n history({ filePath: test.filePath, testName: test.testName }),\n currentBuildOrdinal,\n )\n\n if (test.steps.length === 0) {\n return {\n testIndex: test.testIndex,\n filePath: test.filePath,\n testName: test.testName,\n outcome: test.outcome,\n steps: [],\n testLevelQuote: test.outcome,\n screenshotRefs: [],\n priorBuild,\n memory: { kind: 'no-failing-step' },\n }\n }\n\n const failingAt = failingStepPosition(test.steps)\n const failingStep = test.steps[failingAt] as StepEvidence\n const windowStart = Math.max(0, failingAt - EVIDENCE_WINDOW_STEPS)\n const windowEnd = Math.min(test.steps.length, failingAt + EVIDENCE_WINDOW_STEPS + 1)\n const steps = test.steps\n .slice(windowStart, windowEnd)\n .map((step, offset) =>\n quoteStep(step, windowStart + offset === failingAt ? 'failing' : 'neighbor'),\n )\n\n return {\n testIndex: test.testIndex,\n filePath: test.filePath,\n testName: test.testName,\n outcome: test.outcome,\n failingStepIndex: failingStep.stepIndex,\n steps,\n screenshotRefs: collectScreenshotRefs(failingStep),\n priorBuild,\n memory: {\n kind: 'served',\n servedBrief: failingStep.servedBrief,\n retrievalTrace: failingStep.retrievalTrace,\n },\n }\n}\n\n/**\n * Build one evidence pack per requested test, in trajectory order.\n *\n * `unknownTests` is the caller's selection — testIndex values of the unknown-verdict failed\n * tests (plan 04 selects them through `resolveRunVerdicts`); an index with no matching test\n * contributes nothing. `history` is keyed by the stable test identity — filePath + testName,\n * never testId (per-test-outcome.ts identity law) — and is consulted exactly once per pack.\n */\nexport function buildEvidencePacks(\n handoff: CompletedRunHandoff,\n unknownTests: readonly number[],\n history: EvidenceHistoryLookup,\n): EvidencePack[] {\n const requested = new Set(unknownTests)\n return handoff.tests\n .filter((test) => requested.has(test.testIndex))\n .map((test) => packFor(test, handoff.buildOrdinal, history))\n}\n\nexport type EvidenceTokenEstimator = (text: string) => number\n\nexport interface CompactedEvidence {\n readonly packs: readonly EvidencePack[]\n /** The first rung at which the estimate fit — or 4 with `overBudget` when none did. */\n readonly rung: 0 | 1 | 2 | 3 | 4\n /**\n * True = even rung 4 exceeds the budget. The rung-4 result is still returned whole — the\n * model call may yet succeed, and silently dropping tests or forced channels is exactly\n * what this module refuses to do; the author surfaces the flag.\n */\n readonly overBudget: boolean\n /** The estimator's answer for the returned packs' canonical bytes. */\n readonly estimatedTokens: number\n}\n\nfunction truncateQuote(text: string): string {\n return text.length <= QUOTE_FIELD_CAP ? text : text.slice(0, QUOTE_FIELD_CAP)\n}\n\nfunction truncateStepQuote(quote: EvidenceStepQuote): EvidenceStepQuote {\n return {\n ...quote,\n stepText: truncateQuote(quote.stepText),\n verifierReasoning: truncateQuote(quote.verifierReasoning),\n subActions: quote.subActions.map((subAction) => ({\n plan: truncateQuote(subAction.plan),\n ...(subAction.error === undefined ? {} : { error: truncateQuote(subAction.error) }),\n })),\n ...(quote.reportedValue === undefined\n ? {}\n : { reportedValue: truncateQuote(quote.reportedValue) }),\n ...(quote.aiJudgment === undefined\n ? {}\n : {\n aiJudgment: {\n ...quote.aiJudgment,\n ...(quote.aiJudgment.rationale === undefined\n ? {}\n : { rationale: truncateQuote(quote.aiJudgment.rationale) }),\n },\n }),\n ...(quote.assertOutcome === undefined\n ? {}\n : {\n assertOutcome: {\n ...quote.assertOutcome,\n ...(quote.assertOutcome.expected === undefined\n ? {}\n : { expected: truncateQuote(quote.assertOutcome.expected) }),\n ...(quote.assertOutcome.actual === undefined || quote.assertOutcome.actual === null\n ? {}\n : { actual: truncateQuote(quote.assertOutcome.actual) }),\n },\n }),\n ...(quote.termination === undefined\n ? {}\n : {\n termination: {\n ...quote.termination,\n reason: truncateQuote(quote.termination.reason),\n },\n }),\n ...(quote.limitStop === undefined\n ? {}\n : {\n limitStop: {\n ...quote.limitStop,\n reason: truncateQuote(quote.limitStop.reason),\n ...(quote.limitStop.lastVerifierRejection === undefined\n ? {}\n : { lastVerifierRejection: truncateQuote(quote.limitStop.lastVerifierRejection) }),\n ...(quote.limitStop.lastPlannerReasoning === undefined\n ? {}\n : { lastPlannerReasoning: truncateQuote(quote.limitStop.lastPlannerReasoning) }),\n },\n }),\n }\n}\n\n/** Keep quotes within `radius` ARRAY positions of the failing quote; zero-step packs pass through. */\nfunction shrinkWindow(pack: EvidencePack, radius: number): EvidencePack {\n const failingAt = pack.steps.findIndex((quote) => quote.role === 'failing')\n if (failingAt === -1) return pack\n return {\n ...pack,\n steps: pack.steps.filter((_, position) => Math.abs(position - failingAt) <= radius),\n }\n}\n\n/**\n * The pinned rung table, applied CUMULATIVELY in order — a later rung never re-introduces\n * what an earlier one removed. The failing step and both forced channels survive every\n * rung untouched; rung 4 caps quote-field lengths only.\n *\n * rung 1 strip screenshotRefs from every pack (D-02/L9 text-only degradation)\n * rung 2 shrink the neighbor window to ±1\n * rung 3 drop neighbor steps entirely — the failing step stays whole\n * rung 4 truncate per-field quote lengths to QUOTE_FIELD_CAP\n */\nconst COMPACTION_RUNGS: readonly ((packs: readonly EvidencePack[]) => EvidencePack[])[] = [\n (packs) => packs.map((pack) => ({ ...pack, screenshotRefs: [] })),\n (packs) => packs.map((pack) => shrinkWindow(pack, 1)),\n (packs) => packs.map((pack) => shrinkWindow(pack, 0)),\n (packs) =>\n packs.map((pack) => ({\n ...pack,\n steps: pack.steps.map(truncateStepQuote),\n ...(pack.testLevelQuote === undefined\n ? {}\n : { testLevelQuote: truncateQuote(pack.testLevelQuote) }),\n })),\n]\n\n/**\n * Walk the pinned rungs until the estimate fits the budget. Deterministic over the injected\n * estimator: same packs, same estimator, same budget — same rung, same bytes. The estimate\n * is taken over the packs' `canonicalJson` bytes, a stable proxy for the volatile-tier text\n * plan 04's author renders from them.\n */\nexport function compactEvidencePacks(\n packs: readonly EvidencePack[],\n estimate: EvidenceTokenEstimator,\n inputBudget: number,\n): CompactedEvidence {\n let current: readonly EvidencePack[] = packs\n let estimated = estimate(canonicalJson(current))\n if (estimated <= inputBudget) {\n return { packs: current, rung: 0, overBudget: false, estimatedTokens: estimated }\n }\n for (const [position, rung] of COMPACTION_RUNGS.entries()) {\n current = rung(current)\n estimated = estimate(canonicalJson(current))\n if (estimated <= inputBudget) {\n return {\n packs: current,\n rung: (position + 1) as 1 | 2 | 3 | 4,\n overBudget: false,\n estimatedTokens: estimated,\n }\n }\n }\n return { packs: current, rung: 4, overBudget: true, estimatedTokens: estimated }\n}\n","// The post-run chain's derived facts (Phase 388, RESEARCH Pattern 2).\n//\n// Everything the chain needs to know about itself is COMPUTED from `runId`, and that is the\n// mechanism the whole phase rests on rather than a convenience. Job ids are derived from\n// `(kind, idempotencyKey)` through an injected source, and successor keys are derived from\n// the predecessor's id — so given a run id alone, any process can name every job the chain\n// would have enqueued without reading a row, without a chains table, and without parent\n// pointers. The chip projection addresses exactly these ids; the chain-terminal check asks\n// which of them exist and whether each is terminal.\n//\n// The alternative — recording chain membership as state — would need a second durable fact\n// to be kept in step with the first, and the first thing a stale chain table does is report\n// a chain complete because it never heard about the job that is still running.\n//\n// The derivation is stated ONCE, here, and imported by everything that needs it. Two copies\n// of a hash input differing by a space are two different chains that look identical in\n// review.\n\nimport type { JobId, JobKind, RunNotification, Verdict } from '@vostride/agent-qa-schema'\nimport {\n CURRENT_RUN_NOTIFICATION_SCHEMA_VERSION, CurationSnapshotSchema, RunNotificationSchemaError,\n} from '@vostride/agent-qa-schema'\n\nimport type { JobIdSource } from './engine.js'\n\n/**\n * The kinds whose finish can BE the chain's terminal in this build.\n *\n * Every kind the chain derives an id for is a member, so this list IS the kind set\n * `chainJobIdsForRun` below asks the id source for — there is no declared-but-empty slot left\n * to ask about. `__tests__/chain-identity.test.ts` pins the two against each other by name, so\n * a chain that grows an id without extending this list, or extends this list without deriving\n * the id, reds there rather than reporting a terminal one job early.\n *\n * Membership does NOT mean \"usually terminates the chain\". `curate-memory` is a member because\n * its permanent failure halts the chain and its own finish is then the last thing that happens\n * to the run; on the ordinary path it chains onward and `chainTerminalFor` declines it on the\n * successors it produced. A kind is listed here when its finish CAN be the last one.\n *\n * 2026-09-01 (Phase 409): the third chain id left with the Issue-slot cleanup.\n * 2026-09-11 (Phase 422, D-13): a third stage returns — `propose-improvements`, a kind declared\n * since 385, reached by a new successor edge from `curate-memory`. The vocabulary of job kinds\n * is untouched at five; what grew is the topology and the id set that addresses it.\n */\nexport const POST_RUN_CHAIN_TERMINAL_KINDS: readonly JobKind[] = Object.freeze([\n 'analyze-run',\n 'curate-memory',\n 'propose-improvements',\n])\n\n/**\n * 2026-09-12, 422-22 (D-13): the key set the derivation addresses, as a pinned literal list.\n *\n * The D-22 bar idiom, applied to a KEY SET rather than to a union of values: `satisfies` refuses a\n * name this interface does not declare, and the independent oracles in\n * `__tests__/422-chain-closed-sets.test.ts` / `.test-d.ts` pin the other direction, which is the\n * one that matters here. A fourth id added to `ChainJobIds` alone would leave this list naming\n * three and `satisfies` perfectly happy — nothing in a green suite fails when a set GROWS, which\n * is exactly why the reverse-membership cells exist.\n *\n * The width has moved twice and both moves were authorised: 409's Issue-slot cleanup took it from\n * three to two, and 422 D-13 restored a third for `propose-improvements`. Stating it as data is\n * what makes the next move announce itself.\n */\nexport const CHAIN_JOB_ID_KEYS = [\n 'analyzeRun',\n 'curateMemory',\n 'proposeImprovements',\n] as const satisfies readonly (keyof ChainJobIds)[]\n\n/** The three job ids one run's chain addresses, whether or not any of them exists. */\nexport interface ChainJobIds {\n readonly analyzeRun: JobId\n readonly curateMemory: JobId\n readonly proposeImprovements: JobId\n}\n\n/**\n * Every id the chain for `runId` would carry, from `runId` and the id source alone.\n *\n * The successor keys mirror `successorsOf` in kinds.ts verbatim — `${predecessorId}->${kind}`\n * — because they ARE the same keys: this function predicts what that function will ask for.\n * If the two ever disagree, the projection addresses rows that exist under other ids, which\n * is the failure the shared derivation exists to make impossible.\n *\n * The third id is addressed from the SECOND, not from the run: chaining is transitive and each\n * key is built from its own predecessor, so a chain whose head id source changed moves all\n * three together rather than leaving the tail addressing a row nobody minted (422 D-13). It is\n * deliberately not keyed by candidate: candidates are discovered by the fold and a chain whose\n * identity depended on them could not be predicted before the fold ran.\n */\nexport function chainJobIdsForRun(runId: string, idSource: JobIdSource): ChainJobIds {\n const analyzeRun = idSource.jobIdFor('analyze-run', runId)\n const curateMemory = idSource.jobIdFor(\n 'curate-memory',\n `${String(analyzeRun)}->curate-memory`,\n )\n return {\n analyzeRun,\n curateMemory,\n proposeImprovements: idSource.jobIdFor(\n 'propose-improvements',\n `${String(curateMemory)}->propose-improvements`,\n ),\n }\n}\n\n/**\n * The marker a permanently failed analysis leaves on the successors it hands on (D-20).\n *\n * Read by the notification builder to report the analysis stage honestly: the chain proceeded\n * with no verdicts, and the record has to say so even though the job that reports the\n * terminal is the one that succeeded afterwards.\n */\nexport const UNKNOWN_VERDICTS_MARKER = 'unknown'\n\nexport interface ChainTerminalNotificationInput {\n readonly runId: string\n /** The kind whose finish is landing the chain terminal. */\n readonly finishingKind: JobKind\n /** How that job itself ended. */\n readonly finished: 'done' | 'failed'\n /** The payload it was claimed with — the carrier of the upstream stages' provenance. */\n readonly payload: unknown\n /** The values this attempt published, by checkpoint id. Empty on a job that published none. */\n readonly publishedValues: ReadonlyMap<string, unknown>\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n}\n\nfunction isCount(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0\n}\n\n/**\n * The verdict summary the analysis stage put on its successor's payload.\n *\n * Absent is not a failure and not a zero-filled guess — it is a chain whose analysis never\n * produced verdicts, which the fallback marker reports separately. An unreadable summary\n * degrades to the empty one rather than refusing: this record is written inside the\n * transaction that lands a job terminal, and a guard that threw here would trade a slightly\n * poorer notification for a rolled-back completion.\n *\n * Read from the payload ROOT first and from the forwarded upstream block second (422 D-13).\n * The two are the same fact carried by two generations of payload: a curate-memory job is\n * claimed with the summary at the root, and the propose-improvements job one edge further on\n * is claimed with it nested under `upstream`, because by then the root belongs to the fold.\n * Root-first rather than upstream-first so the nearer producer wins, which is also the reading\n * that makes a curate-memory terminal behave exactly as it did before this stage existed.\n */\nfunction readVerdictSummary(payload: Record<string, unknown>): RunNotification['verdictSummary'] {\n const direct = asRecord(payload.verdictSummary)\n const summary = isCount(direct.total)\n ? direct\n : asRecord(asRecord(payload.upstream).verdictSummary)\n const byClassSource = asRecord(summary.byClass)\n if (!isCount(summary.total)) return { total: 0, byClass: {} }\n const byClass: Partial<Record<Verdict['class'], number>> = {}\n for (const [className, count] of Object.entries(byClassSource)) {\n if (isCount(count)) byClass[className as Verdict['class']] = count\n }\n return { total: summary.total, byClass }\n}\n\n/**\n * Assemble the record from what the engine holds at the terminal — nothing is read back.\n *\n * Every stage's outcome is derivable from three facts already in hand: which kind is\n * finishing, how it ended, and what its payload says about the stages upstream of it. That\n * matters because this runs immediately before the terminal transaction; a builder that\n * needed a query would be reading rows the same transaction is about to change.\n */\nexport function buildChainTerminalNotification(\n input: ChainTerminalNotificationInput,\n): RunNotification {\n const payload = asRecord(input.payload)\n const upstream = asRecord(payload.upstream)\n\n // The fallback marker travels FORWARD on the successor payload, so a curate-memory job that\n // succeeded after a dead analysis still knows the analysis died. Without it the record\n // would report the only stage it watched and call the chain done.\n //\n // 422 D-13 adds the second carrier for the same fact, one edge further on: by the time the\n // proposal job is claimed the root marker belongs to the fold's own payload, so the fold\n // restates the analysis outcome under `upstream`. BOTH are read — a build that dropped the\n // root marker would stop reporting dead analyses on chains whose fold was reached by the\n // fallback, which is precisely the population where the report matters most.\n const analysisFailed =\n payload.verdicts === UNKNOWN_VERDICTS_MARKER ||\n asRecord(payload.upstream).analysisStatus === 'failed' ||\n (input.finishingKind === 'analyze-run' && input.finished === 'failed')\n\n // THE TERMINAL TRAP (422-PATTERNS A5), closed here. Before the third stage, the finishing job\n // WAS the curation job, so its published `bundle-committed` value was the counts and its own\n // disposition was the stage's outcome. A proposal job publishes neither: it is downstream of a\n // fold that already committed. Reading only what the finishing job published would have\n // reported every completed curation as a failure and lost its counts on every three-stage run.\n //\n // Reaching the proposal stage at all is itself the proof the fold completed: the successor is\n // produced only by `realCurateMemoryHandler`'s success path, and a permanently failed fold\n // halts the chain with no successor at all. So the STATUS is derived from the finishing kind\n // and only the COUNTS are read from the forwarded block — which is why a payload that lost its\n // counts degrades to a countless `done` rather than to a fabricated failure.\n const proposalTerminal = input.finishingKind === 'propose-improvements'\n const committed = proposalTerminal\n ? asRecord(upstream.curation)\n : asRecord(input.publishedValues.get('bundle-committed'))\n const curationSucceeded =\n proposalTerminal || (input.finishingKind === 'curate-memory' && input.finished === 'done')\n const snapshot = curationSucceeded && committed.curationSnapshot !== undefined\n ? CurationSnapshotSchema.safeParse(committed.curationSnapshot)\n : undefined\n if (snapshot !== undefined && !snapshot.success) {\n throw new RunNotificationSchemaError('its curation snapshot is invalid')\n }\n const curation: RunNotification['stages']['curation'] = curationSucceeded\n ? {\n status: 'done',\n // Counts only when a bundle was actually committed. Zeros on a stage that never got\n // there would claim it curated nothing, which is a different sentence.\n ...(isCount(committed.curated) ? { curated: committed.curated } : {}),\n ...(isCount(committed.deprecated) ? { deprecated: committed.deprecated } : {}),\n ...(snapshot?.success ? { curationSnapshot: snapshot.data } : {}),\n }\n : { status: 'failed' }\n\n // Present ONLY when the proposal job is the one landing the terminal, which is exactly when\n // the stage ran. A chain that halted at the fold omits the member, and the absence is read\n // downstream as \"not recorded\" rather than as a stage that failed (422 D-15).\n const authored = asRecord(input.publishedValues.get('proposals-authored'))\n const proposalsSucceeded = proposalTerminal && input.finished === 'done'\n const proposals: RunNotification['stages']['proposals'] | undefined = !proposalTerminal\n ? undefined\n : proposalsSucceeded\n ? {\n status: 'done',\n ...(isCount(authored.proposed) ? { proposed: authored.proposed } : {}),\n ...(isCount(authored.skipped) ? { skipped: authored.skipped } : {}),\n }\n : { status: 'failed' }\n\n return {\n schemaVersion: CURRENT_RUN_NOTIFICATION_SCHEMA_VERSION,\n runId: input.runId,\n outcome:\n analysisFailed || !curationSucceeded || (proposalTerminal && !proposalsSucceeded)\n ? 'failed'\n : 'done',\n verdictSummary: readVerdictSummary(payload),\n stages: {\n analysis: { status: analysisFailed ? 'failed' : 'done' },\n curation,\n ...(proposals === undefined ? {} : { proposals }),\n },\n }\n}\n","// Per-kind declarations for the agent job queue (Phase 385, D-09 / D-17 / D-18 / D-20).\n//\n// A kind cannot be registered without saying whether it checkpoints, WHICH checkpoints it\n// publishes, which successors it may chain to, how many attempts it gets, how those attempts\n// are spaced, and what becomes of its chain when it gives up. That is not documentation: the\n// engine reads every one of those fields, so a kind whose declaration lies about its\n// checkpoints refuses at the publish call rather than producing a job whose recovery\n// behaviour nobody can predict. It is also what lets a later harness iterate the registry —\n// kinds x declared checkpoints — instead of maintaining its own list that can silently fall\n// behind.\n//\n// Two refusal classes, with different jobs. An INCOMPLETE declaration is missing a field\n// entirely and is refused by field name, on the same discipline the function layer uses for\n// its required audit sink: substituting a default would mean a kind's recovery behaviour was\n// decided by whoever wrote the default rather than by whoever wrote the kind. An INCONSISTENT\n// declaration has every field and still cannot be true of any kind — and the case that\n// matters most is `checkpointed: true` beside an EMPTY schedule. A registry-driven crash\n// matrix derives its crash points from the declared schedule, so such a kind contributes\n// zero crash points: the matrix passes for it vacuously while its coverage table reports it\n// covered. Refusing the pair at construction makes that hole unrepresentable rather than\n// merely absent today.\n\nimport type { ChainedJobRequest, Job, JobHandlerOutcome, JobKind } from '@vostride/agent-qa-schema'\n\nimport type { BoundRecordLlmAuthorship } from './record-llm-authorship.js'\n\n/** What a handler is handed. Checkpoint publication is a capability, never an import. */\nexport interface JobHandlerContext {\n readonly job: Job\n /**\n * The work the enqueuer described.\n *\n * Carried beside the job rather than on it: the `Job` DTO is the queue's public row and the\n * payload is opaque input that only this kind's handler knows how to read. A handler that\n * could not see it could not do any real work at all — every kind would be a function of\n * its own id.\n */\n readonly payload: unknown\n publishCheckpoint(checkpointId: string, value: unknown): Promise<void>\n /**\n * The ONE path from a job to a model (D-10 / D-11 layer 2).\n *\n * What is absent from this interface is the contract: there is no model member here, and\n * this member's own signature is the only place a capability appears. A handler therefore\n * cannot reach a model except by asking this primitive to record the asking — which is what\n * makes a resumed job's re-invocation impossible by control flow rather than by discipline.\n * The member set of this interface is pinned for exact equality by a test, so an ambient\n * accessor cannot be added quietly beside it.\n */\n readonly recordLlmAuthorship: BoundRecordLlmAuthorship\n}\n\n/**\n * What a handler reports (D-17/D-18).\n *\n * 385 plan 02 replaced this module's own outcome shape with the schema DTO. The two were the\n * same concept described twice, and the local one could not say a handler had FAILED at all —\n * a bare optional successor list makes \"finished, chaining nothing\" and \"gave up\" identical.\n * The TOPOLOGY of what may chain to what is still declared here, on the kind; only the\n * INSTANCES come back from the handler, which is what keeps an outcome-dependent chain\n * ordinary data while leaving the whole graph auditable in one place.\n */\nexport type JobHandler = (context: JobHandlerContext) => Promise<JobHandlerOutcome>\n\n/**\n * How a kind's retries are spaced (D-18) — DATA, never a function.\n *\n * A callback would let a kind compute its own delay from whatever it liked, including the\n * wall clock, and the engine could then neither describe a kind's retry behaviour without\n * running it nor keep a dump deterministic. As data, the delay for attempt N is a pure\n * function of the policy and N, which is exactly what the driver computes and hands back to\n * whichever host decides when to pump next.\n */\nexport type JobBackoffPolicy =\n | { readonly kind: 'none' }\n | { readonly kind: 'fixed'; readonly delayMs: number }\n | {\n readonly kind: 'exponential'\n readonly initialDelayMs: number\n readonly factor: number\n readonly maxDelayMs: number\n }\n\n/**\n * Everything a fallback continuation is allowed to know.\n *\n * The absences are the contract (D-20 / D-11 layer 2). There is no model capability here and\n * no place to pass one, so a producer cannot invoke a model however it is written — which is\n * what puts the permanent-failure path on the resume-legal side of the queue by construction\n * rather than by review.\n */\nexport interface FallbackContinuationInput {\n readonly job: Job\n readonly payload: unknown\n readonly reason: string\n}\n\n/**\n * The deterministic continuation a kind produces when it has permanently failed.\n *\n * SYNCHRONOUS on purpose, and that is the load-bearing half of the guarantee above: a\n * producer that returned a promise could await anything at all, including a model call. One\n * that must return its instances immediately can only compute them from what it was handed.\n */\nexport type FallbackContinuationProducer = (\n input: FallbackContinuationInput,\n) => readonly ChainedJobRequest[]\n\n/**\n * What a kind declares should happen to its chain when it gives up (D-20).\n *\n * `'halt-chain'` enqueues nothing. A producer names the successors the chain proceeds with\n * instead — the analyze-run posture, whose downstream jobs must never wait on a dead head.\n */\nexport type JobPermanentFailureDisposition = 'halt-chain' | FallbackContinuationProducer\n\nexport interface JobKindDeclaration {\n readonly kind: JobKind\n /** `false` means the kind resumes NOTHING after a crash — chat's posture (JOBQ-04). */\n readonly checkpointed: boolean\n /** The complete set of checkpoint ids this kind may publish, in schedule order. */\n readonly checkpointSchedule: readonly string[]\n readonly allowedSuccessors: readonly JobKind[]\n /** Attempts are spent at CLAIM (D-18), so this bound holds even for a job that never returns. */\n readonly maxAttempts: number\n readonly backoff: JobBackoffPolicy\n readonly onPermanentFailure: JobPermanentFailureDisposition\n readonly handler: JobHandler\n}\n\n/** Thrown at construction when two declarations claim the same kind — never last-wins. */\nexport class DuplicateJobKindError extends Error {\n override readonly name = 'DuplicateJobKindError'\n\n constructor(readonly jobKind: JobKind) {\n super(`Duplicate agent job kind: ${jobKind}`)\n }\n}\n\n/** Thrown when the engine is asked to act on a kind no declaration covers. */\nexport class UnknownJobKindError extends Error {\n override readonly name = 'UnknownJobKindError'\n\n constructor(readonly jobKind: string) {\n super(\n `Unknown agent job kind: ${jobKind}. A kind must be declared before it can be ` +\n 'enqueued or run, so an undeclared kind cannot reach a handler at all.',\n )\n }\n}\n\n/** Thrown at construction when a declaration omits a field the engine reads (D-09). */\nexport class IncompleteJobKindDeclarationError extends Error {\n override readonly name = 'IncompleteJobKindDeclarationError'\n\n constructor(\n readonly jobKind: string,\n readonly field: string,\n ) {\n super(\n `Agent job kind ${jobKind} declares no ${field}. Every field of a kind declaration is ` +\n 'read by the engine, and a default supplied here would decide a kind\\'s recovery ' +\n 'behaviour on behalf of whoever wrote the kind.',\n )\n }\n}\n\n/** Thrown at construction when a complete declaration still cannot be true of any kind. */\nexport class InconsistentJobKindDeclarationError extends Error {\n override readonly name = 'InconsistentJobKindDeclarationError'\n\n constructor(\n readonly jobKind: string,\n readonly detail: string,\n ) {\n super(`Agent job kind ${jobKind} has an inconsistent declaration: ${detail}`)\n }\n}\n\nexport interface JobKindRegistry {\n /** Declarations in kind order, so any registry-driven harness is order-stable. */\n list(): readonly JobKindDeclaration[]\n get(kind: JobKind): JobKindDeclaration | undefined\n /** `get`, but refusing rather than returning `undefined` for an undeclared kind. */\n require(kind: JobKind): JobKindDeclaration\n}\n\n/**\n * Checked in this order, so the field a caller is told about is deterministic.\n *\n * `kind` is first because every other refusal message names it.\n */\nconst REQUIRED_FIELDS = [\n 'kind',\n 'checkpointed',\n 'checkpointSchedule',\n 'allowedSuccessors',\n 'maxAttempts',\n 'backoff',\n 'onPermanentFailure',\n 'handler',\n] as const\n\nfunction requireFields(declaration: JobKindDeclaration): void {\n const record = declaration as unknown as Record<string, unknown>\n const named = typeof record.kind === 'string' ? record.kind : '<undeclared>'\n for (const field of REQUIRED_FIELDS) {\n const value = record[field]\n if (value === undefined || value === null) {\n throw new IncompleteJobKindDeclarationError(named, field)\n }\n }\n}\n\nfunction requireCheckpointSchedule(declaration: JobKindDeclaration): void {\n const { kind, checkpointed, checkpointSchedule } = declaration\n if (!Array.isArray(checkpointSchedule)) {\n throw new InconsistentJobKindDeclarationError(kind, 'the checkpoint schedule is not a list')\n }\n // The vacuous-coverage hole, closed in both directions.\n if (checkpointed && checkpointSchedule.length === 0) {\n throw new InconsistentJobKindDeclarationError(\n kind,\n 'it checkpoints but names no checkpoint. A crash matrix derives its crash points from ' +\n 'the declared schedule, so an empty one would report full coverage of a kind it never ' +\n 'interrupted even once.',\n )\n }\n if (!checkpointed && checkpointSchedule.length > 0) {\n throw new InconsistentJobKindDeclarationError(\n kind,\n 'it does not checkpoint yet names checkpoints. Publishing any of them would be refused ' +\n 'at the call, so the schedule describes state nothing could ever resume from.',\n )\n }\n const seen = new Set<string>()\n for (const checkpointId of checkpointSchedule) {\n if (typeof checkpointId !== 'string' || checkpointId.trim() === '') {\n throw new InconsistentJobKindDeclarationError(kind, 'a checkpoint id is not a usable id')\n }\n if (seen.has(checkpointId)) {\n throw new InconsistentJobKindDeclarationError(\n kind,\n `checkpoint ${checkpointId} is declared twice, so two crash points would carry one name`,\n )\n }\n seen.add(checkpointId)\n }\n}\n\nfunction requireSuccessors(declaration: JobKindDeclaration): void {\n const { kind, allowedSuccessors } = declaration\n if (!Array.isArray(allowedSuccessors)) {\n throw new InconsistentJobKindDeclarationError(kind, 'the successor topology is not a list')\n }\n const seen = new Set<string>()\n for (const successor of allowedSuccessors) {\n if (seen.has(successor)) {\n throw new InconsistentJobKindDeclarationError(kind, `successor ${successor} is declared twice`)\n }\n seen.add(successor)\n }\n}\n\nfunction requireAttemptBound(declaration: JobKindDeclaration): void {\n const { kind, maxAttempts } = declaration\n if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {\n throw new InconsistentJobKindDeclarationError(\n kind,\n `maxAttempts ${String(maxAttempts)} is not a whole number of attempts of at least one`,\n )\n }\n}\n\nfunction requireBackoff(declaration: JobKindDeclaration): void {\n const { kind, backoff } = declaration\n const nonNegative = (value: number): boolean => Number.isFinite(value) && value >= 0\n if (backoff.kind === 'none') return\n if (backoff.kind === 'fixed') {\n if (!nonNegative(backoff.delayMs)) {\n throw new InconsistentJobKindDeclarationError(kind, 'the fixed backoff delay is not a delay')\n }\n return\n }\n if (backoff.kind === 'exponential') {\n if (!nonNegative(backoff.initialDelayMs) || !nonNegative(backoff.maxDelayMs)) {\n throw new InconsistentJobKindDeclarationError(\n kind,\n 'an exponential backoff bound is not a delay',\n )\n }\n if (!Number.isFinite(backoff.factor) || backoff.factor < 1) {\n // A factor below one is a backoff that gets FASTER as a job keeps failing.\n throw new InconsistentJobKindDeclarationError(\n kind,\n `the exponential backoff factor ${String(backoff.factor)} does not grow the delay`,\n )\n }\n if (backoff.maxDelayMs < backoff.initialDelayMs) {\n throw new InconsistentJobKindDeclarationError(\n kind,\n 'the exponential backoff ceiling is below its own first delay',\n )\n }\n return\n }\n throw new InconsistentJobKindDeclarationError(\n kind,\n `${String((backoff as { kind: unknown }).kind)} is not a backoff policy this build applies`,\n )\n}\n\nfunction requireDisposition(declaration: JobKindDeclaration): void {\n const { kind, onPermanentFailure } = declaration\n if (onPermanentFailure === 'halt-chain') return\n if (typeof onPermanentFailure === 'function') return\n throw new InconsistentJobKindDeclarationError(\n kind,\n 'the permanent-failure disposition is neither a halt nor a continuation producer',\n )\n}\n\nfunction requireHandler(declaration: JobKindDeclaration): void {\n if (typeof declaration.handler !== 'function') {\n throw new InconsistentJobKindDeclarationError(declaration.kind, 'the handler is not callable')\n }\n}\n\n/**\n * Validate one declaration completely before it can be registered.\n *\n * A type binds only the callers the compiler sees; these checks bind an in-workspace cast and\n * a plain-JS consumer of the published package as well, which is the same reason the function\n * layer refuses a hollow audit sink at runtime rather than trusting its own signature.\n */\nfunction validate(declaration: JobKindDeclaration): void {\n requireFields(declaration)\n requireCheckpointSchedule(declaration)\n requireSuccessors(declaration)\n requireAttemptBound(declaration)\n requireBackoff(declaration)\n requireDisposition(declaration)\n requireHandler(declaration)\n}\n\nexport function createJobKindRegistry(\n declarations: readonly JobKindDeclaration[],\n): JobKindRegistry {\n const byKind = new Map<JobKind, JobKindDeclaration>()\n for (const declaration of declarations) {\n validate(declaration)\n if (byKind.has(declaration.kind)) {\n throw new DuplicateJobKindError(declaration.kind)\n }\n byKind.set(\n declaration.kind,\n Object.freeze({\n ...declaration,\n checkpointSchedule: Object.freeze([...declaration.checkpointSchedule]),\n allowedSuccessors: Object.freeze([...declaration.allowedSuccessors]),\n }),\n )\n }\n\n const sorted = [...byKind.values()].sort((left, right) =>\n left.kind < right.kind ? -1 : left.kind > right.kind ? 1 : 0,\n )\n\n return {\n list: () => sorted,\n get: (kind) => byKind.get(kind),\n require: (kind) => {\n const declaration = byKind.get(kind)\n if (declaration === undefined) {\n throw new UnknownJobKindError(kind)\n }\n return declaration\n },\n }\n}\n","// `runs.get` — one completed run, projected in full (Phase 384, D-06).\n//\n// A pure function of (validated input, injected deps). The port resolves the id against the\n// runs it already enumerates and reports absence as `undefined`; turning that absence into a\n// typed refusal is this module's job, so every surface sees the same error vocabulary.\n\nimport { RunDetailSchema, RunsGetInputSchema, resolveRunVerdicts } from '@vostride/agent-qa-schema'\nimport type {\n CompletedRunHandoff,\n PerTestOutcome,\n RunDetail,\n RunId,\n RunTestDetail,\n RunsGetInput,\n Verdict,\n} from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict, FunctionDeps, FunctionSpec, ReplayedRunEvent } from '../spec.js'\n\nexport const RUNS_GET_FUNCTION_ID = 'runs.get'\n\n/**\n * No completed run is recorded under the requested id.\n *\n * A caller-facing refusal rather than an internal invariant violation: asking for a run that\n * has not happened is an ordinary thing for a surface to do, and the answer has to be\n * distinguishable from a run that exists and recorded no member tests.\n */\nexport class RunNotFoundError extends Error {\n constructor(readonly runId: string, where = '') {\n super(`No completed run recorded for id: ${runId}${where}`)\n this.name = 'RunNotFoundError'\n }\n}\n\n// 2026-10-18 (444-13, D-17): the run exists but never reached a verdict. `recorded` says whether\n// its runs.db row exists (the dashboard holds its record) or only its event log does.\nexport class RunEndedWithoutVerdictError extends Error {\n constructor(readonly runId: string, readonly recorded: boolean) {\n super(recorded\n ? `Run ${runId} ended before it reached a verdict. Its record is in the dashboard.`\n : `Run ${runId} did not reach a verdict.`)\n this.name = 'RunEndedWithoutVerdictError'\n }\n}\n\nexport class RunNotFinishedError extends Error {\n constructor(readonly runId: string) {\n super(`Run ${runId} has not reached a verdict yet.`)\n this.name = 'RunNotFinishedError'\n }\n}\n\nconst IN_FLIGHT_ROW_STATUSES: ReadonlySet<string> = new Set(['running', 'pending'])\n\n// 2026-10-18 (444-13, D-17): the refusal for a run with no handoff. A sentence is given only when\n// the row and the log were both read and the log holds no verdict; an unbound port or a failed\n// read falls back to not-found, because absence is not a status.\nexport async function refuseMissingHandoff(runId: RunId, deps: FunctionDeps): Promise<never> {\n const id = String(runId)\n const reader = deps.runDetail\n if (reader?.readRecord === undefined) throw new RunNotFoundError(id)\n let record: { status: string } | undefined\n let events: readonly ReplayedRunEvent[]\n try {\n record = await reader.readRecord(runId)\n events = await deps.runs.readEvents(runId, 1)\n } catch {\n throw new RunNotFoundError(id)\n }\n if (events.some(event => event.type === 'verdict')) throw new RunNotFoundError(id)\n if (record !== undefined) {\n throw IN_FLIGHT_ROW_STATUSES.has(record.status)\n ? new RunNotFinishedError(id)\n : new RunEndedWithoutVerdictError(id, true)\n }\n if (events.length > 0) throw new RunEndedWithoutVerdictError(id, false)\n throw new RunNotFoundError(id)\n}\n\n/** Where `runs.detail` and `runs.evidence` looked. */\nexport const IN_RUNS_DATABASE = ' in the runs database'\n\n\nfunction toRunTestDetail(\n test: PerTestOutcome,\n resolved: Verdict | undefined,\n): RunTestDetail {\n return {\n testId: test.testId,\n testName: test.testName,\n filePath: test.filePath,\n testIndex: test.testIndex,\n outcome: test.outcome,\n // Step evidence stays in the handoff document; 389's evidence links address it by\n // runId + testIndex. Projecting it here would make the cheapest read the most expensive.\n // The same law covers sentences (389 D-11): this projection carries class/producer/\n // confidence from the resolved verdict and NEVER a rendered sentence — an unbound\n // analysis port answers as artifact-absent (the deterministic floor), so the cheapest\n // read stays cheap in every composition.\n stepCount: test.steps.length,\n ...(resolved === undefined ? {} : {\n rootCause: {\n class: resolved.class,\n producer: resolved.producer,\n confidence: resolved.confidence,\n rationale: resolved.evidence.rationale,\n },\n }),\n }\n}\n\n/**\n * Project one handoff over its RESOLVED verdicts (389 D-10/D-11): the summary block sources\n * class/producer/confidence from `resolveRunVerdicts` — artifact verdicts when the analysis\n * upgraded them, the handoff's deterministic floor when not — joined per member by `perTest`.\n * A member the accessor holds no verdict for (clean pass, skipped, cancelled) projects no\n * `rootCause`, exactly as the handoff's own absence used to read.\n */\nexport function toRunDetail(\n document: CompletedRunHandoff,\n resolvedVerdicts: readonly Verdict[] = resolveRunVerdicts(undefined, document),\n): RunDetail {\n const verdictByPerTest = new Map(\n resolvedVerdicts.map((verdict) => [verdict.perTest, verdict]),\n )\n return {\n runId: document.runId,\n scope: document.scope,\n buildOrdinal: document.buildOrdinal,\n executionContext: document.executionContext,\n aggregateVerdict: document.aggregateVerdict,\n configDigests: document.configDigests,\n startedAt: document.startedAt,\n endedAt: document.endedAt,\n // Both durable markers are copied VERBATIM and stay independent axes: absence in the\n // handoff is absence in the projection, never a rendered `false`.\n ...(document.gateRun === undefined ? {} : { gateRun: document.gateRun }),\n ...(document.excludedFromOutcomes === undefined\n ? {}\n : { excludedFromOutcomes: document.excludedFromOutcomes }),\n tests: document.tests.map((test) => (\n toRunTestDetail(test, verdictByPerTest.get(test.testIndex))\n )),\n }\n}\n\nexport const runsGetSpec: FunctionSpec<RunsGetInput, RunDetail> = {\n id: RUNS_GET_FUNCTION_ID,\n summary: 'Read one completed run in full, including its member-test outcomes.',\n resultKind: 'unary',\n input: RunsGetInputSchema,\n output: RunDetailSchema,\n risk: { name: `fn:${RUNS_GET_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * A run that came back is a run that was found (399.1 D-01).\n *\n * Absence is `RunNotFoundError`, a throw, which already reaches the engine's `failed` mapping.\n * The verdict a run ENDED with is not this clause's verdict: a failing run is a successful read.\n */\n classify(output): ClauseVerdict {\n return {\n status: 'executed',\n outcome: `${output.runId} — ${output.aggregateVerdict}, ${output.tests.length} test(s)`,\n }\n },\n async invoke(input, deps) {\n const document = await deps.runs.get(input.runId)\n if (document === undefined) {\n throw new RunNotFoundError(input.runId)\n }\n // 389 D-11: the rootCause block reads through the ONE accessor. An unbound analysis\n // port is treated as artifact-absent — the floor — never as a refusal: this op stays\n // bound in every composition, and its answer off the floor is honest, not degraded.\n return toRunDetail(\n document,\n resolveRunVerdicts(deps.analysis?.getArtifact(String(input.runId)), document),\n )\n },\n}\n","// `authoring.draft.edit` — the user-facing test edit as a catalogued capability (394-09, D-21).\n//\n// WHY IT REGISTERS, AND WHY NOW. \"Edit that test to also verify the coupon banner\" is a thing a\n// person asks, and 392 D-07 binds every registered op into the chat planner's toolset 1:1 — so\n// registering it is what makes the sentence work from chat, MCP and the CLI on the day it lands,\n// through one implementation rather than three. The timing is the other half: 394-03 minted the\n// RFC-6902 vocabulary and the CST applier, and until this op existed the repair loop was its only\n// consumer. A contract with one consumer is a contract shaped like its one caller, and this\n// project has already paid for that (the two-sided contract law, 388/390/392). Two real consumers\n// from day one is the whole reason D-21 puts the edit verb in 394 instead of the next phase.\n//\n// THE ID IS `authoring.draft.edit` — three lowercase dot segments, no underscore, `draft` the\n// subject and `edit` the verb, so the family reads `authoring.draft.{write, verify, edit}`. The two\n// shipped mechanisms that force the spelling were re-measured for this op rather than inherited:\n// 1. `parity-coverage.test.ts` requires every registered id to match `^[a-z]+(?:\\.[a-z]+)+$` off\n// the registry; `authoring.draft.edit` matches and `authoring.draft_edit` does not.\n// 2. `chat/tool-names.ts` maps ids onto provider-safe tool names by `.` ↔ `_` and REFUSES an id\n// already carrying `_`, because such a name has two pre-images under the inverse — so an\n// underscore id would raise `ChatToolNameError` for the WHOLE projection (T-394-07).\n//\n// IT IS NOT A LOOP STAGE, which is the argument `loop-ordering.test.ts` requires beside the name.\n// That pin exists to forbid promoting a stage of `authoring.draft.write` to its own registered op,\n// since a planner holding one could run compile without dedup or verify without either. This verb\n// is not a stage of anything: it takes an existing COMMITTED test and a change to make to it, it\n// has no place in the six-stage order, and invoking it before, during or after a loop invocation\n// answers the same question. It widens the domain without widening the loop's entry surface.\n//\n// NO SCOPES (2026-10-01, 432-24, D-12). This op once declared `test-write` and `read`, and left\n// `run` out on purpose so a grant issued for \"let it edit my tests\" could not also buy child runs\n// (T-394-37). Grants and scopes are gone; every door can call every operation. What survives of\n// T-394-37 is the behaviour itself: this op edits a committed test and starts no run at all.\n//\n// IT DOES NOT RE-RUN THE GATES, and CONTEXT leaves that call to this plan, so it is made here and\n// written down. An edit to an already-committed test does not automatically re-verify: the\n// standalone `authoring.draft.verify` op exists for exactly the question \"is this test worth\n// keeping\", and folding it in would fire a nine-run fan-out on every one-line edit — the cost\n// WTST-08's preview exists to keep a person in charge of. One verb per question. A caller who wants\n// gate coverage over the edited draft invokes the verify op with the returned `draftRef.filePath`,\n// which since 432 D-06 is the written test file itself.\n//\n// THE WRITE IS THE END OF THIS OP (432 D-06/D-07, superseding 394's propose-plus-apply). The edited\n// document is staged on the draft shelf, then written over the file it edited through the shelf's\n// direct writer — guarded by the digest of the bytes this op read, so a file that changed in the\n// meantime is refused rather than overwritten. No git, no proposal waiting for a person. The answer\n// points at the written file, so `agent_qa_refine_test`'s verify arm judges the test as written.\n\nimport {\n AuthoringDraftEditInputSchema,\n AuthoringDraftEditOutputSchema,\n TestEditPatchSetSchema,\n isEditablePointer,\n} from '@vostride/agent-qa-schema'\nimport type {\n AuthoringDraftEditInput,\n AuthoringDraftEditOutput,\n PatchOp,\n TestEditPatchSet,\n} from '@vostride/agent-qa-schema'\n\nimport { bindEntityNames } from '../../authoring/entity-binding.js'\nimport type { EntityBinding } from '../../authoring/entity-binding.js'\nimport { refuseLiteralSecretMarkers } from '../../authoring/loop.js'\nimport { buildTieredPrompt } from '../../prompt/tiered-prompt-builder.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport const AUTHORING_DRAFT_EDIT_FUNCTION_ID = 'authoring.draft.edit'\n\n/**\n * The `agent_context` this op carries into the ONE tiered prompt builder (389 D-04).\n *\n * Pinned, and distinct from the loop's two, for the reason those are pinned: it lands in the stable\n * tier, which is the byte prefix a provider's prompt cache keys on.\n */\nexport const AUTHORING_EDIT_AGENT_CONTEXT =\n 'authoring.draft.edit — express a requested change to an existing test as RFC-6902 patches'\n\n/** The bound ref named a file this host cannot resolve to a parsable test. */\nexport class EditTargetUnreadableError extends Error {\n constructor(readonly testRef: string, readonly reason: string) {\n super(`${AUTHORING_DRAFT_EDIT_FUNCTION_ID}: ${testRef} is not an editable test: ${reason}`)\n this.name = 'EditTargetUnreadableError'\n }\n}\n\n/**\n * The ref bound to an entity this build cannot open a file for.\n *\n * A NAMED refusal rather than a guess at a path. A resolved descriptor names a real entity, and a\n * store that did not report a test identity has told this layer it cannot say which file that is —\n * recovering one from the entity's title would be exactly the plausible-but-wrong attribution the\n * render-never-recompute boundary exists to refuse.\n */\nexport class EditTargetHasNoFileError extends Error {\n constructor(readonly testRef: string, readonly boundRef: string) {\n super(\n `${AUTHORING_DRAFT_EDIT_FUNCTION_ID}: \"${testRef}\" bound to ${boundRef}, which names a real `\n + 'entity that this host cannot resolve to a test file; nothing was edited',\n )\n this.name = 'EditTargetHasNoFileError'\n }\n}\n\n/** The model emitted something that is not a `{thoughts, patches}` set. */\nexport class EditPatchSetUnparsableError extends Error {\n constructor(readonly reason: string) {\n super(`${AUTHORING_DRAFT_EDIT_FUNCTION_ID}: the emitted edit is not a patch set: ${reason}`)\n this.name = 'EditPatchSetUnparsableError'\n }\n}\n\n/**\n * A patch addressed a document root outside the editable region (T-394-36).\n *\n * THE SAME PREDICATE THE APPLIER USES, ASKED ON THIS SIDE OF THE PORT. `isEditablePointer` is\n * exported from `schema` precisely so the fence is expressible where the applier is not, and the\n * host runs it again over the whole set before any mutation. That is the two-sided posture this\n * phase applies to every rule that matters — not a second fence with its own idea of the region,\n * because both sides read the one exported predicate over the one pinned root set.\n *\n * The value of asking here is that a retarget is refused before a model's emission reaches the\n * host at all, and the refusal is a class a caller in this layer can catch by name rather than a\n * host error arriving as prose.\n */\nexport class EditRegionRefusedError extends Error {\n constructor(readonly offendingPaths: readonly string[]) {\n super(\n `${AUTHORING_DRAFT_EDIT_FUNCTION_ID}: ${offendingPaths.length} patch path(s) address a `\n + `document root outside the editable region (${offendingPaths.join(', ')}); the WHOLE set `\n + 'was refused and nothing was staged',\n )\n this.name = 'EditRegionRefusedError'\n }\n}\n\n/** The patched document no longer parses as a test. Nothing was staged. */\nexport class EditResultUnparsableError extends Error {\n constructor(readonly reason: string) {\n super(\n `${AUTHORING_DRAFT_EDIT_FUNCTION_ID}: applying the edit produced a document that is not a `\n + `parsable test, so nothing was staged: ${reason}`,\n )\n this.name = 'EditResultUnparsableError'\n }\n}\n\n/**\n * The WHOLE set is refused on the first offending path, never partially applied.\n *\n * The applier's own posture (394-03) and the repair fence's (394-06), for the same reason: a\n * per-op check would already have rewritten the legitimate target before it refused the retarget,\n * which leaves a half-edited document behind on the one path where correctness matters most.\n */\nfunction fenceRegion(patchSet: TestEditPatchSet): void {\n const offending = patchSet.patches\n .map((patch: PatchOp) => patch.path)\n .filter((path) => !isEditablePointer(path))\n if (offending.length > 0) throw new EditRegionRefusedError(offending)\n}\n\n/** The bound target's identity, or the named refusal for a binding with no file behind it. */\nfunction identityOf(binding: EntityBinding, testRef: string) {\n if (binding.identity === undefined) throw new EditTargetHasNoFileError(testRef, binding.ref)\n return binding.identity\n}\n\nexport const authoringDraftEditSpec: FunctionSpec<\n AuthoringDraftEditInput,\n AuthoringDraftEditOutput\n> = {\n id: AUTHORING_DRAFT_EDIT_FUNCTION_ID,\n summary: 'Apply a requested change to an existing test and write it, answering the diff it applied.',\n resultKind: 'unary',\n // The WRITE half — a host with no model and no shelf cannot express an edit at all. The read\n // half (`draftEvaluation`, which resolves and parses the committed target) is checked by the same\n // name inside the invoke, on `authoring-draft-write.ts`'s precedent: `boundThrough` names one\n // key, and a host missing the other would otherwise list this op `bound` and then fail far from\n // whichever half was forgotten.\n boundThrough: 'draftShelf',\n input: AuthoringDraftEditInputSchema,\n output: AuthoringDraftEditOutputSchema,\n // `mutating-local`, and the contrast with `authoring.draft.write` is deliberate. That op declares\n // `mutating-shared` because it spends up to nine child `agent-qa run` processes of a person's\n // compute (D-10). This op takes ONE model call, starts zero runs, and writes one file — the test\n // it edited, over the exact bytes it read (432 D-06). 2026-10-01 (432-19/432-24, D-12/D-15): the\n // tiers once decided who was asked and where an unanswerable ask denied; nothing asks or denies\n // on a tier now, and the tier stays the honest classification of what the op touches.\n //\n // The mechanics: `recognized: true` with no `readOnly` puts the classifier's floor at\n // mutating-local, `declaredTier` states that tier rather than relying on the floor, and the name\n // tokens (fn · authoring · draft · edit) hit neither destructive lexicon.\n risk: {\n name: `fn:${AUTHORING_DRAFT_EDIT_FUNCTION_ID}`,\n recognized: true,\n declaredTier: 'mutating-local',\n },\n /**\n * An edit that returned STAGED a draft — there is no arm where it did not (399.1 D-01).\n *\n * Every refusal this op can make is a THROW (the never-guess binder, the region fence, the\n * parser), which already reaches the engine's own `failed` mapping. What returns is one shape,\n * and the honest report of it is what was edited and how much changed.\n */\n classify(output): ClauseVerdict {\n const file = output.written\n if (file.kind === 'not-written') {\n return {\n status: file.reason === 'write-failed' ? 'failed' : 'refused',\n outcome: `not edited ${output.editedFrom.testName} — ${file.reason}`,\n }\n }\n return {\n status: 'executed',\n outcome: `edited ${output.editedFrom.testName} — ${output.patches.length} patch op(s) written `\n + `to ${file.filePath}`,\n }\n },\n async invoke(input, deps) {\n const shelf = deps.draftShelf\n const evaluation = deps.draftEvaluation\n if (shelf === undefined || evaluation === undefined) {\n throw new FunctionNotBoundError(AUTHORING_DRAFT_EDIT_FUNCTION_ID)\n }\n\n // 1. WHICH TEST. Never guessed at (D-19): an exact address is parsed, and anything else goes to\n // the house resolver, whose ambiguity and low-confidence arms are typed refusals that end\n // this invocation with nothing edited.\n const [binding] = await bindEntityNames([input.testRef], { entities: deps.entities })\n if (binding === undefined) throw new EditTargetUnreadableError(input.testRef, 'no binding')\n const identity = identityOf(binding, input.testRef)\n\n // 2. ITS BYTES, through the shipped resolution that already answers the workspace-boundary\n // question by name. The refusal arms collapse to one class here because the caller's next\n // move is the same for all of them — the ref named something this host will not edit — and\n // the arm is carried as the reason rather than lost.\n const resolution = await evaluation.resolveDraft(identity.filePath)\n if (resolution.kind !== 'parsed') {\n throw new EditTargetUnreadableError(input.testRef, resolution.kind)\n }\n // The bound NAME must be the test that is actually there. A file whose single test has been\n // renamed since the ref was minted would otherwise be edited under somebody else's name.\n if (resolution.draft.testName !== identity.testName) {\n throw new EditTargetUnreadableError(\n input.testRef,\n `the file holds \"${resolution.draft.testName}\", not \"${identity.testName}\"`,\n )\n }\n\n // 3. ONE model call through the ONE builder, and one only. A retry hidden here would make this\n // verb's cost a number nobody counted.\n const request = buildTieredPrompt({\n agent_context: AUTHORING_EDIT_AGENT_CONTEXT,\n stable: [\n {\n title: 'Role',\n body: 'You edit an existing agent-qa test document. Reply with ONE JSON object and '\n + 'nothing else: {\"thoughts\": string, \"patches\": [...]}, where each patch is an '\n + 'RFC-6902 op with \"op\" one of add/remove/replace, a JSON Pointer \"path\", and for '\n + 'add/replace a string \"value\". Only /steps, /name and /context may be addressed — '\n + 'the target application and the test identity are not yours to change. Change as '\n + 'little as the request needs.',\n },\n ],\n context: [\n { title: 'The requested change', body: input.intent },\n {\n title: 'The test as it stands',\n body: [\n `Test name: ${resolution.draft.testName}`,\n 'Steps, in order:',\n ...resolution.draft.steps.map((step, index) => ` ${index}. ${step}`),\n ].join('\\n'),\n },\n ],\n volatile: [],\n })\n\n const model = await shelf.model()\n const emitted = await model.generate(request)\n\n // 4. THE CONTRACT, then the FENCE, then the mutation — in that order, because a set that is\n // refused must be refused before anything is staged.\n let json: unknown\n try {\n json = JSON.parse(emitted.text)\n } catch (error) {\n throw new EditPatchSetUnparsableError(`it is not JSON (${(error as Error).message})`)\n }\n const parsed = TestEditPatchSetSchema.safeParse(json)\n if (!parsed.success) {\n throw new EditPatchSetUnparsableError(parsed.error.issues[0]?.message ?? 'shape refused')\n }\n fenceRegion(parsed.data)\n\n // 5. THE SAME APPLIER THE REPAIR LOOP USES, reached through the port because it needs the yaml\n // CST and this package may not depend on `core`. Reusing it is what makes \"an edit never\n // reformats an untouched line\" a property this op inherits from a frozen byte-diff corpus\n // rather than one it would have to re-prove for a second implementation.\n const staged = await shelf.applyPatches(resolution.draft, parsed.data)\n if (staged.kind === 'unparsable') throw new EditResultUnparsableError(staged.reason)\n\n // 6. 2026-10-14 (441-03, D-10): the loop's literal-marker check, before anything is written.\n refuseLiteralSecretMarkers(staged.draft)\n\n const stagedRef = {\n filePath: staged.draft.filePath,\n testId: staged.draft.testId,\n testName: staged.draft.testName,\n contentDigest: staged.draft.contentDigest,\n }\n\n // 7. THE WRITE (432 D-06/D-07), over the file this op read, and only if it still holds exactly\n // the bytes it read. The parser, the patch schema, the region fence and the marker check\n // above have all passed by now; the writer adds the workspace boundary and the digest guard.\n const written = await shelf.publish({\n draftPath: staged.draft.filePath,\n targetPath: identity.filePath,\n sourceDigest: resolution.draft.contentDigest,\n })\n const draftRef = written.kind === 'written'\n ? { ...stagedRef, filePath: written.filePath }\n : stagedRef\n\n return {\n draftRef,\n editedFrom: {\n filePath: identity.filePath,\n testName: identity.testName,\n boundBy: binding.source,\n },\n patches: parsed.data.patches,\n thoughts: parsed.data.thoughts,\n written,\n }\n },\n}\n","// Never-guess binding for an LLM-supplied entity name (394-09, D-19 · T-394-35).\n//\n// A name a model chose decides WHICH of a person's tests an edit rewrites. D-19's rule is that such\n// a name binds only on a UNIQUE HIGH-CONFIDENCE hit; ambiguity, weakness and absence are each a\n// typed refusal, and none of them is ever a silent guess into a file this project keeps.\n//\n// THE HOUSE RESOLVER ALREADY IS THAT RULE, WHICH IS WHY THERE IS NO SECOND MATCHER HERE. The spec's\n// §8.1 sketch is a fuse.js threshold of about 0.4 applied at the authoring surface. This project\n// shipped the same decision as a three-tier resolver in 387 — an exact-address tier, a strong-hit\n// tier gated on BOTH an absolute score and a margin over the runner-up, and a disambiguation tier —\n// and its `applyStrongHitRule` answers `none` for a lone candidate that clears neither. So the\n// binding below REUSES that contract rather than restating it: adding a matcher and a threshold\n// here would be a second answer to \"which entity did the model mean\", free to disagree with the\n// first, and this codebase's arch lints exist because that class of drift is expensive. If the\n// resolver's tiers are ever measured wrong for authoring, that is a change to the resolver.\n//\n// THE ONE PLACE THIS FILE DECIDES ANYTHING is what to do with `none.closestSuggestion`. The resolver\n// attaches it when a single candidate ranked but did not clear the bar — which is EXACTLY the\n// low-confidence lone match D-19 names — and it is offered so a surface can say \"did you mean\". A\n// binder that promoted a suggestion to a binding would turn the resolver's refusal back into the\n// guess it refused, one field away, and would look entirely reasonable in review. It is refused\n// here by name, and the refusal carries the suggestion so a person can still be asked.\n//\n// WHY THIS REACHES THE PORT RATHER THAN THE REGISTERED OP. `entities.resolve` renders CARDS, and a\n// card deliberately carries no test identity — D-12's render-never-recompute boundary drops it, so\n// the op's answer cannot say which file a bound test lives in, and a binder reading one would have\n// to recover a path from a title, which is the plausible-but-wrong attribution that boundary exists\n// to prevent. `EntityDirectoryPort` is the SAME port that op invokes, on every op's `FunctionDeps`,\n// and it answers descriptors. Nothing is widened by reaching it: the resolution is a read, the op\n// that performs this binding declares `read`, and `entities.resolve` requires exactly `read` — so\n// every caller who can reach this binding could already have called that op directly.\n\nimport { suiteTestRef } from '@vostride/agent-qa-schema'\nimport type { EntityDescriptor } from '@vostride/agent-qa-schema'\n\nimport type { EntityDirectoryPort } from '../functions/spec.js'\n\n/** The identity halves a bound test is addressed by — never `testId`, which is per-run. */\nexport interface BoundTestIdentity {\n readonly filePath: string\n readonly testName: string\n}\n\n/**\n * What one name bound to.\n *\n * `source` is on the record rather than inferred, because the two tiers answer with different\n * confidence in different senses and a consumer that has to know which one it holds should not be\n * reconstructing it from which optional fields happen to be present. An exact reference is a parse;\n * a resolver hit is a ranking that cleared a bar.\n *\n * `identity` is OPTIONAL and its absence is honest rather than degraded: a resolved descriptor for\n * a kind that is not a test, or for a store that did not report a test identity, names a real\n * entity that this build cannot open a file for. The op that needs a file refuses on the absence by\n * name instead of guessing at one.\n */\nexport interface EntityBinding {\n /** The name as it arrived — what a refusal message and a receipt both have to echo. */\n readonly name: string\n readonly source: 'exact-ref' | 'resolver'\n /** The canonical reference this name bound to, in the one house spelling. */\n readonly ref: string\n readonly identity?: BoundTestIdentity\n}\n\n/**\n * The name matched more than one entity (D-19, T-394-35).\n *\n * A SEPARATE CLASS from {@link UnresolvedEntityNameError} rather than one error with a kind, on the\n * `authoring-verify-draft.ts` precedent, and here the distinction is what a caller does next:\n * ambiguity has candidates to put in front of a person — 387's disambiguation card — while an\n * unresolved name has nothing to choose between and needs a different question. A caller reading a\n * string to tell those apart is a caller that will one day read it wrong.\n */\nexport class AmbiguousEntityNameError extends Error {\n constructor(\n readonly entityName: string,\n /** The candidates the resolver offered, best-first, in its own words. */\n readonly candidates: readonly { readonly ref: string; readonly title: string; readonly score: number }[],\n ) {\n super(\n `the name \"${entityName}\" matches ${candidates.length} entities `\n + `(${candidates.map((candidate) => candidate.ref).join(', ')}); `\n + 'it was NOT bound — a name that matches several tests must be chosen between, never picked',\n )\n this.name = 'AmbiguousEntityNameError'\n }\n}\n\n/**\n * The name matched nothing the binder may act on.\n *\n * ONE class for two situations that are the same DECISION — nothing was bound — and different\n * facts, which is why `closestSuggestion` is a field rather than a second class: an honest miss and\n * a lone weak match both leave the caller with no binding, and the only thing a surface does\n * differently is offer the near miss. Splitting them would make every catch site handle two classes\n * to take one action.\n */\nexport class UnresolvedEntityNameError extends Error {\n constructor(\n readonly entityName: string,\n readonly reason: string,\n /** The near miss the resolver declined to bind, when it offered one. NEVER auto-applied. */\n readonly closestSuggestion?: string,\n ) {\n super(\n `the name \"${entityName}\" resolved to nothing this binding may act on (${reason})`\n + (closestSuggestion === undefined\n ? ''\n : `; the closest match was ${closestSuggestion}, which did not clear the resolver's bar `\n + 'and is offered as a question rather than applied'),\n )\n this.name = 'UnresolvedEntityNameError'\n }\n}\n\nexport interface BindEntityNamesDeps {\n readonly entities: EntityDirectoryPort\n}\n\n/**\n * The exact-address tier: `<filePath>::<testName>`, the ONE spelling this project prints.\n *\n * Deterministic, no scoring, no model — the same posture the resolver's own tier (a) takes for an\n * address, and for the same reason: answering an exact address with whatever happened to rank is\n * the silent guess the whole mechanism exists to prevent. It matters that this tier exists at all,\n * because it is the spelling a dedup refusal already hands a person (`AuthoringDedupRefusal`), so\n * \"edit that one\" round-trips without a fuzzy match ever being consulted.\n *\n * The separator is required on BOTH sides: a ref with an empty path or an empty name is not an\n * address, and treating it as one would open a file this host never named.\n */\nfunction parseExactRef(name: string): BoundTestIdentity | undefined {\n const separator = name.indexOf('::')\n if (separator <= 0) return undefined\n const filePath = name.slice(0, separator)\n const testName = name.slice(separator + 2)\n return testName.length === 0 ? undefined : { filePath, testName }\n}\n\n/** A descriptor's identity halves, when its owning store reported them. See {@link EntityBinding}. */\nfunction identityOf(descriptor: EntityDescriptor): BoundTestIdentity | undefined {\n const identity = descriptor.testIdentity\n return identity === undefined\n ? undefined\n : { filePath: identity.filePath, testName: identity.testName }\n}\n\n/**\n * Bind every supplied name, or refuse by name on the first one that cannot be bound.\n *\n * REFUSES ON THE FIRST FAILURE, and refuses the WHOLE set — the applier's own posture (394-03) and\n * the repair fence's (394-06). Binding what it could and reporting the rest would hand a caller a\n * partially-bound edit, which is the shape in which somebody eventually applies the bound half.\n *\n * Order is preserved, so a caller that supplied `[testRef]` reads its answer at index 0 without\n * having to search for it.\n */\nexport async function bindEntityNames(\n names: readonly string[],\n deps: BindEntityNamesDeps,\n): Promise<readonly EntityBinding[]> {\n const bindings: EntityBinding[] = []\n\n for (const name of names) {\n const exact = parseExactRef(name)\n if (exact !== undefined) {\n bindings.push({\n name,\n source: 'exact-ref',\n ref: suiteTestRef(exact.filePath, exact.testName),\n identity: exact,\n })\n continue\n }\n\n const resolution = await deps.entities.resolve(name)\n switch (resolution.kind) {\n case 'resolved': {\n const identity = identityOf(resolution.descriptor)\n bindings.push({\n name,\n source: 'resolver',\n ref: resolution.descriptor.uri,\n ...(identity === undefined ? {} : { identity }),\n })\n break\n }\n case 'ambiguous':\n throw new AmbiguousEntityNameError(\n name,\n resolution.candidates.map((candidate) => ({\n ref: candidate.descriptor.uri,\n title: candidate.descriptor.title,\n score: candidate.score,\n })),\n )\n case 'none':\n // THE LOW-CONFIDENCE DIRECTION, and it is the one a permissive implementation gets wrong.\n // `closestSuggestion` is passed through as EVIDENCE and never as a fallback binding.\n throw new UnresolvedEntityNameError(\n name,\n resolution.reason,\n resolution.closestSuggestion,\n )\n }\n }\n\n return bindings\n}\n","// The six-stage authoring loop (Phase 394, D-01/D-02 · WTST-01).\n//\n// ONE function takes a plain-English intent to a verified draft with a real receipt. The six\n// stages are evaluated in THIS order, once each, and the order is the contract rather than an\n// implementation detail — D-01 puts the whole loop inside one registered op precisely so that no\n// caller, including the chat planner that binds every registered op 1:1, can reorder a stage, skip\n// one, or reach a later one without the earlier ones having happened.\n//\n// 1. brief Read what this project already knows about the intent's scope. Stage 3 compiles\n// from this and from nothing else the host had lying around; an absent brief is a\n// refusal at the op, never an empty one served silently.\n// 2. dedup Screen the intent against the authored suite BEFORE a byte is authored. Being\n// first is the whole of \"dedup-before-author\": there is exactly one call site and\n// it is here, so the property is structural rather than a habit of this code.\n// 3. compile ONE model call emits a WHOLE document (D-02: creation is not an edit — a new\n// file has no untouched lines to preserve, so WTST-07's letter holds). What it\n// emitted is parsed before it becomes bytes; an unparsable draft is a named\n// refusal and leaves nothing on disk.\n// 4. verify The staged draft is judged by `authoring.draft.verify`, dispatched as the\n// REGISTERED op. No gate is re-implemented here and no disposition is re-derived\n// here — `computeDraftDisposition` is the one site, and the receipt already\n// carries what it decided.\n// 5. route Turn the receipt into an outcome. Deterministic by contract (D-08): a clean\n// definitive assertion-fail must never reach repair, because \"repairing\" one means\n// rewriting the expectation to match what the app shows, which is oracle capture.\n// 6. compound NO CODE, AND THAT IS THE POINT. `projectProcedureTargets` already fires for every\n// verified-PASS multi-step trajectory on every drain, and a gate-run reaches it\n// because `runs.start` spawns a full child `agent-qa run` (C8: gate-runs curate).\n// D-07's induction therefore needs no write path from here, and adding one would be\n// a SECOND Curator write path for a fact the existing one already records. The\n// stage is entered and recorded so the loop's own trace states the six, and so a\n// later reader finds this paragraph instead of an apparent gap.\n//\n// WHAT THIS TRACER IMPLEMENTS AND WHAT IT DOES NOT. Stage 2 walks the corpus and reports the\n// closest match; the REFUSING arm and its pinned threshold land in plan 04, RED-first against a\n// frozen corpus, so no constant is minted here for a later plan to re-litigate. Stage 5 answers\n// `drafted` for a receipt the gates were able to judge and refuses BY NAME for the dispositions\n// plans 05 and 06 own — a named refusal that a later plan replaces with a branch, never a wrong\n// answer returned in the meantime. {@link AuthoringLoopOutcome} declares all four arms today so\n// those plans add a case behind a discriminant every consumer already reads.\n\nimport { literalSecretMarkerRefusal } from '@vostride/agent-qa-runner'\nimport {\n DRAFT_STABILITY_RUNS_N,\n authoredSuiteTargetPath,\n NO_RUNS_FAN_OUT_BOUND,\n buildFanOutReport,\n computeFanOutBound,\n draftDispositionWritesTarget,\n draftGateBooleans,\n} from '@vostride/agent-qa-schema'\nimport type {\n AuthoringBrief,\n CompletedRunHandoff,\n ConsumedRun,\n DraftDisposition,\n DraftReceipt,\n DraftRef,\n FanOutBound,\n AuthoringDraftWriteOutput,\n FanOutReport,\n ScopeKey,\n WrittenTestReceipt,\n} from '@vostride/agent-qa-schema'\n\nimport {\n CONFIGURED_TARGETS_BLOCK_TITLE,\n PROCEDURE_BY_REFERENCE_INSTRUCTION,\n REQUEST_WINS_INSTRUCTION,\n TEST_DOCUMENT_FORMAT_BLOCK_TITLE,\n TEST_DOCUMENT_FORMAT_INSTRUCTION,\n configuredTargetsBlockBody,\n exemplarBlockBody,\n knowledgeBlockBody,\n} from './brief-blocks.js'\nimport { dedupBeforeAuthor } from './dedup.js'\nimport type { DedupScreening } from './dedup.js'\nimport type {\n AuthoringReadPortLike,\n DraftRunPortLike,\n DraftShelfPortLike,\n ParsedDraftLike,\n} from './ports.js'\nimport { refineDraft } from './refine.js'\nimport type { RefinementOutcome } from './refine.js'\nimport { REPAIR_ITERATION_CAP, repairDraft } from './repair.js'\nimport type { RepairAbandonment, RepairOutcome } from './repair.js'\nimport { extractStatedValues, missingStatedValues } from './stated-values.js'\nimport {\n AuthoringRouterUnroutableError,\n routeRepairOrStop,\n stopRouteForAbandonedRepair,\n} from './router.js'\nimport type { StopRoute } from './router.js'\nimport { buildTieredPrompt } from '../prompt/tiered-prompt-builder.js'\n\n/**\n * The stage vocabulary, closed and ordered.\n *\n * The DECLARATION ORDER is the execution order, and `loop-ordering.test.ts` asserts the observed\n * trace equals this array — sequence equality over the whole run rather than a set of per-stage\n * \"was it called\" checks, because what has to be pinned is that nothing ran out of order and\n * nothing was skipped, which a call count cannot say.\n */\nexport const AUTHORING_LOOP_STAGES = [\n 'brief',\n 'dedup',\n 'compile',\n 'verify',\n 'route',\n 'compound',\n] as const\n\nexport type AuthoringLoopStage = (typeof AUTHORING_LOOP_STAGES)[number]\n\n/**\n * The `agent_context` every compile call carries into the ONE tiered prompt builder (389 D-04).\n *\n * A pinned string rather than a computed one: it lands in the stable tier, which is the byte\n * prefix provider prompt caches key on, so a per-invocation value would defeat the caching the\n * tier law exists to enable.\n */\nexport const AUTHORING_COMPILE_AGENT_CONTEXT =\n 'authoring.draft.write — compile a whole test document from an intent and a brief'\n\n/**\n * How one loop invocation ended.\n *\n * Discriminated on the CLOSED schema vocabulary, and all four arms are declared here in the\n * tracer even though only `drafted` is reachable from it. See the vocabulary's own doc block: a\n * union that grew an arm per plan would make plans 04-06 changes to the shape every consumer\n * branches on rather than new cases behind a discriminant they already read.\n *\n * The `stopped` arm carries the ROUTE and the abandonment facts and writes nothing — the op\n * projects the result's `stop` payload from it (411 D-05).\n *\n * 2026-09-30, 432 D-06: the `drafted` and `repaired` arms carry the WRITTEN-TEST RECEIPT where they\n * used to carry a proposal for a person to accept. The final draft is written to its target unless\n * its final receipt is `rejected`, and the receipt says which file was written or why none was.\n */\nexport type AuthoringLoopOutcome =\n | {\n readonly kind: 'drafted'\n readonly draftRef: DraftRef\n readonly receipt: DraftReceipt\n readonly written: WrittenTestReceipt\n }\n | {\n readonly kind: 'refused'\n readonly draftRef?: DraftRef\n readonly receipt?: DraftReceipt\n readonly statedValueRefusal?: NonNullable<AuthoringDraftWriteOutput['statedValueRefusal']>\n }\n | {\n readonly kind: 'repaired'\n readonly draftRef: DraftRef\n readonly receipt: DraftReceipt\n readonly written: WrittenTestReceipt\n /** Repair iterations spent reaching the repaired draft, fenced ones included. */\n readonly repairIterations: number\n }\n | {\n readonly kind: 'stopped'\n readonly draftRef: DraftRef\n readonly receipt: DraftReceipt\n readonly route: StopRoute\n /**\n * ITS KIND AND ITS SPEND ARE ONE PARAMETER, so `repairAbandonment` and `repairIterations`\n * land on the op's payload together or not at all (394-21, WR-09). Present as one object or\n * absent — never two independent optionals, which could disagree: a kind with no spend, or a\n * spend on a stop repair never touched, which reads as \"repair was tried and cost nothing\".\n *\n * `iterations` is `RepairOutcome.iterations` INCLUDING iterations a fence refused, which\n * started nothing — which is why it is not derivable from the run ids `fanOut` counts (D-08).\n */\n readonly abandonment?: {\n readonly kind: RepairAbandonment['kind']\n readonly iterations: number\n }\n }\n\nexport interface AuthoringLoopInput {\n readonly intent: string\n readonly scope: ScopeKey\n /** Handed straight through to stage 4. See the op's input contract for what it costs. */\n readonly draftMode?: true\n /**\n * The invoking session, threaded to EVERY receipt this invocation mints (394-17, D-12).\n *\n * Both of them: stage 4's own evaluation and the final stability gate a repaired candidate goes\n * through. A thread that stopped at the first would attribute first-try drafts and silently\n * unattribute every draft that needed repairing — the population a keep rate most needs.\n */\n readonly sessionRef?: string\n}\n\n/**\n * The fan-out ONE invocation of this loop can cost, in child `agent-qa run` processes (D-03/D-10).\n *\n * THE SINGLE PLACE THE THREE TERMS ARE ASSEMBLED, and the only caller of `computeFanOutBound` in\n * this package. The dispatch confirm renders what this returns and the finished proposal reports\n * against it, so the number a person consents on and the number they are shown afterwards are the\n * same function of the same input rather than two agreeing arithmetics. A surface recomputing\n * `N + K + N` for itself would be free to drift the moment either constant moved — which is what\n * mutation I of the phase's mutation driver (since removed) demonstrated rather than asserted.\n *\n * DRAFT MODE IS THE CASE WHERE THE TWO N TERMS DIFFER. A draft-mode caller asks for ONE cheap gate\n * run (rule 1 of the disposition table), but the FINAL stability gate still runs the pinned N on\n * the repaired candidate — `repairDraft` deliberately drops the draft-mode marker for it. So the\n * bound is `1 + K + N`, not `2 * 1 + K`, and it is the configuration the schema cells use to prove\n * the two terms stay separate: with the shipped constants they are both 3, and a collapse would be\n * invisible under default values.\n */\nexport function authoringFanOutBound(input: { readonly draftMode?: true }): FanOutBound {\n return computeFanOutBound({\n initialN: input.draftMode === true ? 1 : DRAFT_STABILITY_RUNS_N,\n probeK: REPAIR_ITERATION_CAP,\n finalN: DRAFT_STABILITY_RUNS_N,\n })\n}\n\nexport interface AuthoringLoopDeps {\n readonly read: AuthoringReadPortLike\n /**\n * The compile half, plus stage 5's run reader (394-06).\n *\n * The run capability rides this bundle rather than arriving as a third dep: see the port's own\n * `runs` doc. What it buys the loop is that \"can this host author\" stays ONE question with one\n * answer, which is the property D-01's composition rests on.\n */\n readonly shelf: DraftShelfPortLike\n}\n\n/**\n * What one invocation produced, and the stages it actually entered.\n *\n * `stages` is DATA the loop answers with, not a test hook. Plan 04's refusal ends an invocation\n * at stage 2 and plan 05's repair re-enters stages 3-4, so \"where did this stop\" and \"how many\n * times did it iterate\" are questions about a real invocation that a caller — and the funnel's\n * side counters (D-15) — has to be able to ask. It is also what makes the ordering claim\n * checkable at all: the trace is pushed by each stage as it is entered, so a reordered loop\n * reports a reordered trace.\n */\nexport interface AuthoringLoopResult {\n readonly outcome: AuthoringLoopOutcome\n readonly stages: readonly AuthoringLoopStage[]\n readonly dedup: DedupScreening\n /** Which named side counters this invocation incremented. See the vocabulary's doc block. */\n readonly sideCounters: readonly AuthoringLoopSideCounter[]\n /**\n * What was previewed at dispatch, beside the runs this invocation actually spent (WTST-08).\n *\n * ON THE RESULT AND NOT ONLY ON THE PROPOSAL ARM, because a stage-2 refusal has no arm — D-04\n * ends it with no draft, no receipt and no envelope — and \"this invocation cost nothing\" is a\n * fact a caller is entitled to for every outcome, not only the ones that produced something.\n */\n readonly fanOut: FanOutReport\n /**\n * What stage 3's one refinement round did (D-18).\n *\n * ABSENT exactly when the round never ran — a stage-2 refusal, or a compile refusal for a lost\n * stated value — and present on every other invocation, including the ones where the round\n * changed nothing. The\n * distinction the field exists to keep is between a round that found nothing (`no-op`) and one\n * whose emission could not be used (`not-applied`): both leave the draft alone, and only one of\n * them is the loop working as designed.\n */\n readonly refinement?: RefinementOutcome\n}\n\n/**\n * Facts about an invocation that are counted BESIDE the funnel, never as a stage of it (D-15).\n *\n * A dedup refusal is the first member, and the distinction is the whole reason the vocabulary\n * exists. Plan 07 projects the loop as a funnel — how many intents reached compile, verify, a\n * keep-eligible receipt — and a refusal that was folded into a funnel stage would read as an\n * invocation the pipeline FILTERED. It is not: it is an invocation the pipeline never entered,\n * refused for a working-as-intended reason before any cost was incurred. Counting it inside the\n * funnel would inflate the filter rate with successes and break comparison against the reference\n * distribution, which is exactly the number the funnel exists to be compared against.\n */\nexport const AUTHORING_LOOP_SIDE_COUNTERS = ['dedup-refused'] as const\n\nexport type AuthoringLoopSideCounter = (typeof AUTHORING_LOOP_SIDE_COUNTERS)[number]\n\n/**\n * The model emitted something that is not a parsable test document.\n *\n * A NAMED refusal and not a retry: this tracer takes one model call by design, and a second\n * attempt hidden inside the first would make the fan-out preview (D-03) a number that does not\n * describe what happens. The bytes were never written — the shelf parses before it writes — so\n * there is no partial draft to clean up either (T-394-06).\n */\nexport class AuthoringDraftUnparsableError extends Error {\n constructor(readonly reason: string) {\n super(\n 'authoring.draft.write: the compiled draft is not a parsable test document, '\n + `so nothing was written to the shelf: ${reason}`,\n )\n this.name = 'AuthoringDraftUnparsableError'\n }\n}\n\n/**\n * The model emitted a `target` this project does not declare (394-37, WR-04).\n *\n * A REFUSAL AND NOT A REPAIR, and the two halves of that are separate facts. It cannot be\n * repaired: `target` is outside `EDITABLE_POINTER_ROOTS`, so no patch the repair loop may emit\n * reaches the key. And it must not be run: `runs.start` spawns a real child `agent-qa run`, whose\n * own `resolveTarget` throws on the name — so the cost of discovering this downstream is up to\n * `DRAFT_STABILITY_RUNS_N` real child processes (nine across a repaired invocation), a receipt on\n * disk, and a draft nothing can fix.\n *\n * IT NAMES BOTH SIDES OF THE COMPARISON. A message carrying only the emitted name would leave a\n * person unable to tell whether the target was misspelled or the config was, which is the same\n * D-19 posture `AuthoringScopeUnresolvableError` takes one file over: refuse, and hand over the\n * evidence the refusal was made on.\n */\nexport class AuthoringDraftUnconfiguredTargetError extends Error {\n constructor(\n readonly target: string,\n readonly configuredTargets: readonly string[],\n ) {\n super(\n `authoring.draft.write: the compiled draft names target \"${target}\", which this project `\n + `does not declare, so no gate run was started: configured targets are `\n + `${configuredTargets.join(', ')}`,\n )\n this.name = 'AuthoringDraftUnconfiguredTargetError'\n }\n}\n\nexport class DraftSecretMarkerRefusedError extends Error {\n constructor(\n readonly location: string,\n refusal: string,\n readonly stepIndex?: number,\n ) {\n super(`${location}: ${refusal}`)\n this.name = 'DraftSecretMarkerRefusedError'\n }\n}\n\nexport function refuseLiteralSecretMarkers(draft: {\n readonly testName: string\n readonly steps: readonly string[]\n readonly context?: string\n}): void {\n const locations: readonly { text: string; label: string; stepIndex?: number }[] = [\n { text: draft.testName, label: 'the test name' },\n ...(draft.context === undefined ? [] : [{ text: draft.context, label: 'the test context' }]),\n ...draft.steps.map((text, index) => ({ text, label: `step ${index + 1}`, stepIndex: index })),\n ]\n for (const location of locations) {\n const refusal = literalSecretMarkerRefusal(location.text)\n if (refusal === undefined) continue\n throw new DraftSecretMarkerRefusedError(location.label, refusal, location.stepIndex)\n }\n}\n\n/**\n * The router could not place a rejected receipt's evidence.\n *\n * The honest answer for the one case stage 5 genuinely cannot decide: the gates said no, and the\n * run record the receipt names is not readable, or holds no member with this draft's identity. That\n * is a broken precondition rather than an ambiguous signal — reporting an evidence-less stop would\n * report an application bug nobody observed, which is the cardinal error pointed the other way.\n */\nexport class AuthoringLoopUnroutableEvidenceError extends Error {\n constructor(readonly disposition: DraftDisposition, readonly cause: Error) {\n super(\n `authoring.draft.write: a ${disposition} receipt could not be routed — ${cause.message}`,\n )\n this.name = 'AuthoringLoopUnroutableEvidenceError'\n }\n}\n\n/**\n * THE FINAL-WRITE BRANCH (432 D-06, EDGE-09): whether a final draft is written to its target.\n *\n * It is also the set stage 5 answers `drafted` for, because the two are one fact: the gates did\n * not say no. `unverified` is a DRAFT-MODE evaluation whose gates 1, 3 and 4 passed (rule 1 of the\n * disposition table; 261003-cpv, WR-09), and such a draft is neither a stop — no run said the\n * application is wrong — nor repairable — no mechanics evidence exists to repair against — so it\n * is written, and its receipt says it is unverified. `rejected` is the only disposition that\n * routes and the only one never written, because it is the only one a gate actually refused. A\n * rejected draft whose run passed has nothing to route either; `routeAfterVerify` answers it\n * `drafted`, not written, with the rejecting gates on its receipt.\n */\nfunction writesFinalDraft(disposition: DraftDisposition): boolean {\n return draftDispositionWritesTarget(disposition)\n}\n\n/** The draft's identity as the receipt and both envelope arms spell it. */\nfunction draftRefOf(draft: ParsedDraftLike): DraftRef {\n return {\n filePath: draft.filePath,\n testId: draft.testId,\n testName: draft.testName,\n contentDigest: draft.contentDigest,\n }\n}\n\n/**\n * Write the final draft, or say why it was not written (432 D-06/D-07).\n *\n * The target is derived from where the DRAFT already sits (394-10's recipe). There is deliberately\n * no `sourceDigest`: a loop-authored draft is a NEW file (D-02 — creation is not an edit), so the\n * writer re-checks the target as still absent. That is the collision guard for two drafts whose\n * names slug the same way, and it fails toward `target-changed` rather than an overwrite.\n *\n * The receipt carries the disposition and the four gate booleans whatever happened to the file, so\n * the author always learns how well the draft was verified beside where it went.\n */\nasync function writeFinalDraft(\n draft: ParsedDraftLike,\n receipt: DraftReceipt,\n shelf: DraftShelfPortLike,\n statedValues: readonly string[],\n): Promise<FinalWrite> {\n const gates = draftGateBooleans(receipt.gates)\n const targetPath = authoredSuiteTargetPath(draft.filePath, draft.testName)\n if (!writesFinalDraft(receipt.disposition)) {\n return {\n written: {\n file: { kind: 'not-written', targetPath, reason: 'rejected' },\n disposition: receipt.disposition,\n gates,\n },\n }\n }\n // 2026-10-12 (440-05, D-08): the exact draft about to be written is checked here, the only door\n // to publish, so no route can write a draft that lost a stated value.\n const missingValues = missingStatedValues(statedValues, draft.steps)\n if (missingValues.length > 0) return { missingValues }\n const file = await shelf.publish({ draftPath: draft.filePath, targetPath })\n return { written: { file, disposition: receipt.disposition, gates } }\n}\n\ntype FinalWrite =\n | { readonly written: WrittenTestReceipt }\n | { readonly missingValues: readonly string[] }\n\nfunction keepRefusal(\n draftRef: DraftRef,\n receipt: DraftReceipt,\n missingValues: readonly string[],\n fanOut: FanOutReport,\n): AuthoringLoopRouting {\n return {\n outcome: {\n kind: 'refused',\n draftRef,\n receipt,\n statedValueRefusal: { stage: 'keep', missingValues: [...missingValues] },\n },\n fanOut,\n }\n}\n\n/**\n * Stage 3, first half — ONE model call, one whole document, parsed before it is written.\n *\n * The prompt extends the ONE tiered builder through `agent_context` (389 D-04's law); there is no\n * second renderer and no persona fork here. What the model returns is handed to the shelf, which\n * parses it and answers `unparsable` without writing when it is not a test.\n *\n * The two brief renderers live in `brief-blocks.ts` because the refinement round reads the same\n * substrate; see that module's header for why they are shared rather than copied.\n */\nasync function compileDraft(\n input: AuthoringLoopInput,\n brief: AuthoringBrief,\n shelf: DraftShelfPortLike,\n read: AuthoringReadPortLike,\n): Promise<ParsedDraftLike> {\n // WR-07: the `target` vocabulary, read HERE rather than threaded in from the caller. It is\n // needed by exactly one prompt and nothing else in the invocation consults it, so a value\n // fetched at the top of `runAuthoringLoop` would be a read the dedup refusal path pays for and\n // never uses — and one more argument that could be edited in transit.\n const targetNames = await read.configuredTargetNames()\n\n const request = buildTieredPrompt({\n agent_context: AUTHORING_COMPILE_AGENT_CONTEXT,\n stable: [\n {\n title: 'Role',\n body: 'You author agent-qa test documents. Emit ONE complete YAML test document and '\n + 'nothing else — no prose, no fences, no partial edit. Steps are natural language, one '\n + 'per line, and at least one of them must assert concrete expected content. '\n + REQUEST_WINS_INSTRUCTION,\n },\n // The document schema, on the same placement argument and for WINDOWS 111's reason: a brief\n // serving no exemplars must still teach the format. See the constant's own header.\n {\n title: TEST_DOCUMENT_FORMAT_BLOCK_TITLE,\n body: TEST_DOCUMENT_FORMAT_INSTRUCTION,\n },\n // D-17's syntactic half, in the STABLE tier beside the role it qualifies. It is a standing\n // rule about how any step is written rather than a fact about this intent, so it belongs\n // where the byte prefix is shared across invocations.\n { title: 'Procedures', body: PROCEDURE_BY_REFERENCE_INSTRUCTION },\n ],\n context: [\n { title: 'Intent', body: input.intent },\n { title: 'Scope', body: `${input.scope.tier}:${input.scope.key}` },\n // WR-07, AND IT RIDES BESIDE THE BLOCK IT CORRECTS. `Scope` renders `${tier}:${key}` and\n // that key is a PRODUCT — `deriveDefaultAuthoringScope` answers `target.product ??\n // targetName` — so a stage asked for a `target` while served only the Scope block was being\n // asked to guess on every project where the two differ. CONTEXT tier and not stable: these\n // names are per-project facts, and the stable tier's shared byte prefix must stay\n // project-independent for the prompt cache the tier law exists to enable.\n {\n title: CONFIGURED_TARGETS_BLOCK_TITLE,\n body: configuredTargetsBlockBody(targetNames),\n },\n { title: 'What this project knows', body: knowledgeBlockBody(brief) },\n ],\n volatile: [{ title: 'Exemplar tests', body: exemplarBlockBody(brief) }],\n })\n\n const model = await shelf.model()\n const emitted = await model.generate(request)\n const staged = await shelf.write(emitted.text)\n if (staged.kind === 'unparsable') throw new AuthoringDraftUnparsableError(staged.reason)\n\n // THE VOCABULARY IS SERVED AND THEN CHECKED (394-37, WR-04). Round 5 read `targetNames` for the\n // prompt above and compared it against nothing, and a prompt is ADVICE: a model that skips the\n // `target` bullet — copying the block's own example, say — emits a name this project does not\n // declare, and the check that would have caught it is eight lines up in a local variable.\n //\n // THE REFUSAL BELONGS HERE, BEFORE THE FIRST GATE RUN, on two facts that hold together.\n // `runs.start` types this value into a live application and `resolveTarget` THROWS on it inside\n // a real child process, so the downstream cost is up to `DRAFT_STABILITY_RUNS_N` spawns (nine\n // with repair) rather than one comparison. And `target` is outside `EDITABLE_POINTER_ROOTS`, so\n // the repair loop those runs would feed cannot correct the value it discovers is wrong — the\n // spend buys nothing at all. D-19's refuse-rather-than-guess posture, applied to the loop's own\n // emission instead of to its inputs.\n //\n // THE EMPTY-VOCABULARY ARM STAYS PERMISSIVE, DELIBERATELY. A project that declares no targets\n // has nothing for this to compare against, and refusing there would turn a derivation problem\n // (`deriveDefaultAuthoringScope` already refuses such a project by name) into a compile-stage\n // refusal that names the wrong cause. `configuredTargetsBlockBody` tells the model the same\n // thing in the same case: ask, do not invent.\n if (targetNames.length > 0 && !targetNames.includes(staged.draft.target)) {\n throw new AuthoringDraftUnconfiguredTargetError(staged.draft.target, targetNames)\n }\n return staged.draft\n}\n\n/**\n * What stage 5 answers: the outcome, and the runs the whole invocation spent reaching it.\n *\n * The fan-out report rides OUT of stage 5 rather than being assembled by the caller, because stage\n * 5 is the only place that knows what repair spent. A caller totalling it from the outside would be\n * counting attempts it can see rather than runs that happened.\n */\nexport interface AuthoringLoopRouting {\n readonly outcome: AuthoringLoopOutcome\n readonly fanOut: FanOutReport\n}\n\n/**\n * The gate runs a receipt names, as consumed runs with their completion times.\n *\n * The time is read from the run's OWN record rather than stamped here: `GateRunRecord` carries a\n * run id and the draft's member outcome, not a clock, and a timestamp minted at read time would\n * order the sequence by when somebody looked rather than by when the runs finished. A record that\n * cannot be read still COUNTS — the run happened — and simply carries no time, which is what the\n * report's ordering rule has an unknown-time arm for.\n */\nasync function consumedGateRuns(\n receipt: DraftReceipt,\n runs: DraftRunPortLike,\n): Promise<readonly ConsumedRun[]> {\n const consumed: ConsumedRun[] = []\n for (const record of receipt.gateRuns) {\n const document = await runs.get(record.runId)\n consumed.push({\n runId: record.runId,\n purpose: 'gate',\n ...(document?.endedAt === undefined ? {} : { completedAt: document.endedAt }),\n })\n }\n return consumed\n}\n\n/** The probe runs a repair sequence started, on `consumedGateRuns`' terms. */\nasync function consumedProbeRuns(\n probeRunIds: readonly string[],\n runs: DraftRunPortLike,\n): Promise<readonly ConsumedRun[]> {\n const consumed: ConsumedRun[] = []\n for (const runId of probeRunIds) {\n const document = await runs.get(runId)\n consumed.push({\n runId,\n purpose: 'probe',\n ...(document?.endedAt === undefined ? {} : { completedAt: document.endedAt }),\n })\n }\n return consumed\n}\n\n/**\n * The run whose evidence stage 5 routes on: the LAST gate run the receipt names.\n *\n * ONE ANSWER TO A QUESTION THE DERIVATION DELIBERATELY DOES NOT OWN. `routeRepairOrStop` takes\n * a single run document because a routing rule that also chose its own evidence would be two rules\n * in one function. Which of an evaluation's several runs supplies that document is a fact about\n * the EVALUATION, and it is answered here: the last one taken, because gate 2 early-stops on a\n * verdict flip (D-17) and the run that stopped it is the one carrying the failure the gates\n * ultimately reported. An absent record yields `undefined`, which the router refuses BY NAME\n * rather than routing on.\n */\nasync function routingHandoff(\n receipt: DraftReceipt,\n runs: DraftRunPortLike,\n): Promise<CompletedRunHandoff | undefined> {\n const lastRun = receipt.gateRuns.at(-1)\n return lastRun === undefined ? undefined : await runs.get(lastRun.runId)\n}\n\n/**\n * THE PRODUCTION READ of `abandonment.error`, and the only one: its typed coordinates.\n *\n * A prefix-regressed abandonment means a PROBE run showed a step that used to pass now failing, and\n * `PassingPrefixRegressedError` carries the whole coordinate: which run, which member of it, and\n * which step. That is an addressable, replayable coordinate into a durable record — the same thing\n * every other `evidenceRefs` entry is — so the stop a person reads can reach the run that ended\n * the repair instead of merely stating that one did. Appended BESIDE the routed run's own refs: the\n * routed run says why the draft failed, this says why repair stopped, and they are different runs.\n *\n * ALL FOUR FIELDS COME FROM THE ERROR, AND THAT IS THE FIX RATHER THAN A TIDY-UP (CR-01). This used\n * to take `filePath`/`testName` from the invocation's `draftRef`, which is the PRE-repair draft: a\n * probe runs the candidate `applyPatches` just staged, and staging addresses a draft by the digest\n * of its new bytes, so the two paths differ by construction on every iteration that reached a run.\n * The persisted coordinate named a real run and a file that run never opened, and a reader joining\n * on the four-tuple found nothing — a stop nobody can audit. The error is built at the\n * one site that held the probed member, which is also why this stays a read of typed facts and not\n * a second walk of the run store (394-24's one-derivation law).\n *\n * WHAT IS DELIBERATELY NOT READ: `error.message`, and through it `RepairExhaustedError.lastRefusal`,\n * which ends in the model's own bytes. There is no prose field on the stop payload for it to reach\n * (411 D-05), and this read stays a read of typed coordinates.\n *\n * The exhausted arm gets no such ref because it has no such coordinate — its last iteration may have\n * been a fenced patch or an unparsable emission, neither of which started a run.\n */\nfunction withRegressedProbeEvidence(\n route: StopRoute,\n abandonment: RepairAbandonment,\n): StopRoute {\n if (abandonment.kind !== 'prefix-regressed') return route\n return {\n kind: 'stop',\n signalClass: route.signalClass,\n failurePoint: route.failurePoint,\n evidenceRefs: [\n ...route.evidenceRefs,\n {\n runId: abandonment.error.runId,\n filePath: abandonment.error.filePath,\n testName: abandonment.error.testName,\n stepIndex: abandonment.error.stepIndex,\n channel: 'step-trace',\n },\n ],\n }\n}\n\n/**\n * Stage 5 — the receipt becomes an outcome; the drafted and repaired ones carry their envelope arm.\n *\n * The stopped outcome carries the ROUTE the loop derived and nothing is minted for it (411 D-10).\n *\n * 2026-09-02 (Phase 411): the proposal arm for a correctly-failing draft left with the Issue-slot\n * cleanup.\n *\n * TWO DERIVATIONS, ASKED IN ORDER, NEITHER RE-IMPLEMENTED HERE. The first is\n * `computeDraftDisposition`'s, already stored on the receipt: did the gates say no. The second is\n * `routeRepairOrStop`'s, over the run's own evidence: is a rejection the DRAFT's problem or the\n * APPLICATION's. This function asks them; it answers neither. The two are separate functions\n * rather than one because they read different things — a disposition reads four booleans and two\n * counts, a route reads per-step execution evidence — and a single function taking both would be\n * a parameter list through which a gate verdict could influence the branch.\n *\n * THE REPAIR ARM IS ENTERED ONLY THROUGH A `RepairRoute`. `repairDraft` cannot be handed the stop\n * arm — the two route types are mutually non-assignable — so the app-broken branch is structurally\n * unable to reach repair rather than merely not wired to it (SC-2, T-394-22).\n *\n * A REPAIR THAT DID NOT SUCCEED BECOMES A STOP, not a silent failure. The draft failed, repair was\n * allowed K attempts and none produced a passing probe, and the honest thing to hand a person is\n * the evidence plus what was tried. The route's own evidence refs are what the stop carries, so an\n * exhausted repair and a first-pass stop are the same artifact class differing only in how much was\n * spent before the loop stopped.\n */\nexport async function routeAfterVerify(\n draft: ParsedDraftLike,\n receipt: DraftReceipt,\n deps: AuthoringLoopDeps,\n statedValues: readonly string[],\n previewed: FanOutBound = NO_RUNS_FAN_OUT_BOUND,\n /**\n * The suite the draft proposes to JOIN, threaded to repair's final stability gate (394-19).\n *\n * HANDED IN rather than re-derived here, on the `sessionRef` posture one field over: the caller\n * computed it once for stage 4's own verify, and a second `authoredSuiteTargetPath` call at this\n * site would be a second answer to a question the invocation already answered. Absent — every\n * caller that is not the loop — leaves the repaired draft on the standalone fallback.\n */\n targetSuitePath?: string,\n): Promise<AuthoringLoopRouting> {\n const draftRef = draftRefOf(draft)\n // The runs the EVALUATION already spent, read off the receipt's own record of them. It is the\n // receipt's list rather than a count this function keeps, because the receipt is what was\n // durably written — a tally maintained here could drift from the evidence a person later reads.\n const gateRuns = await consumedGateRuns(receipt, deps.shelf.runs)\n\n if (writesFinalDraft(receipt.disposition)) {\n const fanOut = buildFanOutReport({ previewed, runs: gateRuns })\n const final = await writeFinalDraft(draft, receipt, deps.shelf, statedValues)\n if ('missingValues' in final) return keepRefusal(draftRef, receipt, final.missingValues, fanOut)\n return { outcome: { kind: 'drafted', draftRef, receipt, written: final.written }, fanOut }\n }\n\n const handoff = await routingHandoff(receipt, deps.shelf.runs)\n let route\n try {\n route = routeRepairOrStop(draftRef, handoff)\n } catch (error) {\n if (!(error instanceof AuthoringRouterUnroutableError)) throw error\n // 2026-10-03 (quick 261003-cpv, 432 review WR-09): THE RUN PASSED AND A GATE STILL SAID NO —\n // the draft adds nothing to the suite, asserts nothing falsifiable, or flipped and then passed.\n // Nothing failed, so there is nothing to repair and no application bug to stop on; the honest\n // answer is the draft, not written, with the gates that rejected it. Draft mode reaches this\n // since rule 1 rejects on gates 1, 3 and 4, and a missing run record still refuses by name.\n if (error.signalClass === 'no-failure') {\n const fanOut = buildFanOutReport({ previewed, runs: gateRuns })\n const final = await writeFinalDraft(draft, receipt, deps.shelf, statedValues)\n if ('missingValues' in final) {\n return keepRefusal(draftRef, receipt, final.missingValues, fanOut)\n }\n return { outcome: { kind: 'drafted', draftRef, receipt, written: final.written }, fanOut }\n }\n throw new AuthoringLoopUnroutableEvidenceError(receipt.disposition, error)\n }\n\n if (route.kind === 'stop') {\n return {\n outcome: { kind: 'stopped', draftRef, receipt, route },\n fanOut: buildFanOutReport({ previewed, runs: gateRuns }),\n }\n }\n\n // `handoff` is defined here: the router refuses `no-run-evidence` by name, and that refusal was\n // already converted above — so reaching a repair arm at all means a run document was read.\n // THE SESSION IS READ OFF THE RECEIPT THAT WAS JUST MINTED, never threaded a second time\n // (394-17, D-12). The repaired candidate belongs to the same invocation as the draft that\n // failed, so its receipt must carry the same attribution — and taking it from the record stage 4\n // already wrote makes that true by construction instead of by two threads agreeing. An\n // unattributed evaluation stays unattributed through repair for the same reason.\n const repaired: RepairOutcome = await repairDraft(route, {\n draft,\n handoff: handoff as CompletedRunHandoff,\n shelf: deps.shelf,\n runs: deps.shelf.runs,\n statedValues,\n ...(receipt.sessionRef === undefined ? {} : { sessionRef: receipt.sessionRef }),\n // The repaired candidate joins the SAME suite the draft proposed to join, so the final\n // stability gate reads the same target — one source for the whole invocation.\n ...(targetSuitePath === undefined ? {} : { targetSuitePath }),\n })\n\n // EVERY RUN THIS INVOCATION SPENT, in one list: the evaluation's gate runs, repair's probes, and\n // the FINAL stability gate's runs off the repaired receipt. The report counts distinct ids, so a\n // run appearing in two of these three lists contributes once — and a fenced iteration, which\n // started nothing, contributes nothing.\n const probes: readonly ConsumedRun[] = await consumedProbeRuns(\n repaired.probeRunIds,\n deps.shelf.runs,\n )\n\n if (repaired.kind === 'repaired') {\n const repairedRef = draftRefOf(repaired.draft)\n const finalGateRuns = await consumedGateRuns(repaired.receipt, deps.shelf.runs)\n const fanOut = buildFanOutReport({\n previewed,\n runs: [...gateRuns, ...probes, ...finalGateRuns],\n })\n // The repaired draft's FINAL receipt decides, exactly as a first-pass one does: a final\n // stability gate that rejects it leaves it on the shelf, reported as not written.\n const final = await writeFinalDraft(repaired.draft, repaired.receipt, deps.shelf, statedValues)\n if ('missingValues' in final) {\n return keepRefusal(repairedRef, repaired.receipt, final.missingValues, fanOut)\n }\n return {\n outcome: {\n kind: 'repaired',\n draftRef: repairedRef,\n receipt: repaired.receipt,\n written: final.written,\n repairIterations: repaired.iterations,\n },\n fanOut,\n }\n }\n\n // THE ABANDONED ARM READS THE RUN IT WAS ROUTED ON (CR-02). It used to be an empty literal —\n // `failurePoint: null`, `evidenceRefs: []` — built with `handoff` and `route.failingStepIndex`\n // both in scope, so a person was handed a durable stop naming no step, no run and no trace. The\n // derivation is the router's, shared with the ordinary stop arm rather than repeated here: an\n // exhausted repair and a first-pass stop are the same artifact class, and this function's own\n // header says so. `handoff` is defined for the reason given at the repair call above — the router\n // refuses `no-run-evidence` by name and that refusal was already converted.\n const exhaustedRoute: StopRoute = withRegressedProbeEvidence(\n stopRouteForAbandonedRepair(draftRef, handoff as CompletedRunHandoff, route.failingStepIndex),\n repaired.abandonment,\n )\n return {\n outcome: {\n kind: 'stopped',\n draftRef,\n receipt,\n route: exhaustedRoute,\n abandonment: { kind: repaired.abandonment.kind, iterations: repaired.iterations },\n },\n fanOut: buildFanOutReport({ previewed, runs: [...gateRuns, ...probes] }),\n }\n}\n\nexport async function runAuthoringLoop(\n input: AuthoringLoopInput,\n deps: AuthoringLoopDeps,\n): Promise<AuthoringLoopResult> {\n const stages: AuthoringLoopStage[] = []\n // The SAME function the dispatch confirm rendered, over the SAME input. Not a number handed in\n // from the op — a threaded value could be edited in transit, and then the receipt would report a\n // preview nobody was shown. One function, two callers, identical arguments.\n const previewed = authoringFanOutBound(input)\n\n stages.push('brief')\n const brief = await deps.read.getAuthoringBrief(input.intent, input.scope)\n\n stages.push('dedup')\n const dedup = dedupBeforeAuthor(input.intent, await deps.read.suiteTextCorpus())\n\n // THE INVOCATION ENDS HERE, and it ends BEFORE `compileDraft` — which is the only place a model\n // is reached. D-04: the refusal is a typed op result, fail-closed and stateless. There is no\n // suspended-op state and no in-turn \"continue anyway\": chat renders the refusal with its link\n // and its two continuations, and the user re-invokes deliberately. An in-turn continue would\n // need a suspended op to resume into, which is machinery this phase does not build and which\n // would turn a refusal a user must read into one they can dismiss.\n //\n // `stages` stops at `dedup`, so the trace says WHERE this invocation ended rather than claiming\n // six stages ran. The `refused` arm carries neither a `draftRef` nor a `receipt` because there\n // is no draft and no gate-run to have produced one; the evidence lives on `dedup`, which is a\n // fact about the SCREENING rather than about the outcome.\n if (dedup.kind === 'duplicate') {\n return {\n outcome: { kind: 'refused' },\n stages,\n dedup,\n sideCounters: ['dedup-refused'],\n // ZERO PREVIEWED AND ZERO CONSUMED, and the first of those is a decision. The dispatch\n // confirm disclosed the worst case for these inputs, as it must — it fires before anything\n // is known. This report describes the INVOCATION, and this invocation ended before a draft\n // existed, so nothing was ever going to run. `NO_RUNS_FAN_OUT_BOUND` is that fact; carrying\n // the dispatch bound here would report a fan-out for a path that has none.\n fanOut: buildFanOutReport({ previewed: NO_RUNS_FAN_OUT_BOUND, runs: [] }),\n }\n }\n\n const statedValues = extractStatedValues(input.intent)\n\n stages.push('compile')\n const compiled = await compileDraft(input, brief, deps.shelf, deps.read)\n // 2026-10-12 (440-02, D-05): a compiled draft that loses a stated value is refused before refine,\n // with no retry and no run spent.\n const missing = missingStatedValues(statedValues, compiled.steps)\n if (missing.length > 0) {\n return {\n outcome: {\n kind: 'refused',\n draftRef: draftRefOf(compiled),\n statedValueRefusal: { stage: 'compile', missingValues: [...missing] },\n },\n stages,\n dedup,\n sideCounters: [],\n fanOut: buildFanOutReport({ previewed: NO_RUNS_FAN_OUT_BOUND, runs: [] }),\n }\n }\n // THE ROUND IS UNCONDITIONAL AND IT IS INSIDE STAGE 3 (D-18). Unconditional: there is no `if`\n // above this line and no argument that could turn it off — see `refine.ts` for why a trigger\n // heuristic is the thing D-18 rules out rather than the thing it configures. Inside stage 3\n // rather than beside it: `AUTHORING_LOOP_STAGES` is a pinned six, refining is part of producing\n // the draft, and a seventh stage would have re-opened an ordering contract that plans 02-08 all\n // built against for a step that has no independent entry point.\n const refinement = await refineDraft(compiled, input, deps)\n const draft = refinement.draft\n\n // 2026-10-14 (441-03, D-10): a draft that would type a literal [secret:NAME] ends here.\n refuseLiteralSecretMarkers(draft)\n\n // 2026-10-01 (432-19, D-15): the dispatch runs directly. The optional dispatch-grant scope that\n // used to wrap stages 4-6 is deleted; no host bound it after 432-18 and nothing asks for an\n // approval a gate run could collect.\n return await runAuthoringLoopDispatch(input, deps, {\n stages,\n previewed,\n dedup,\n draft,\n refinement,\n statedValues,\n })\n}\n\n/**\n * Stages 4-6 — the dispatch: verification, routing and the final write.\n *\n * `stages`, `previewed` and `dedup` are threaded rather than recomputed: `previewed` in\n * particular must stay the SAME value the caller derived, because the fan-out report's whole claim\n * is that the number a person approved and the number they are shown afterwards are one function\n * of one input.\n */\nasync function runAuthoringLoopDispatch(\n input: AuthoringLoopInput,\n deps: AuthoringLoopDeps,\n carried: {\n readonly stages: AuthoringLoopStage[]\n readonly previewed: FanOutBound\n readonly dedup: DedupScreening\n readonly draft: ParsedDraftLike\n readonly refinement: RefinementOutcome\n readonly statedValues: readonly string[]\n },\n): Promise<AuthoringLoopResult> {\n const { stages, previewed, dedup, draft, refinement, statedValues } = carried\n\n stages.push('verify')\n // WHERE THE FINAL WRITE WILL PUT IT, computed ONCE for the whole invocation through the SAME\n // exported recipe the final write uses (`writeFinalDraft`'s `targetPath`) — so the suite the\n // stability read consults and the suite the draft is written into cannot disagree (394-19, D-14).\n // ONE DERIVATION IS ONLY ENOUGH BECAUSE THE INPUT THAT MOVES DOES NOT REACH THE ANSWER: this value\n // is derived here from the PRE-repair draft and recomputed at the write from the REPAIRED draft,\n // whose shelf path is a DIFFERENT file — repair re-stages every patched candidate under its new\n // digest — and `authoredSuiteTargetPath` drops that filename, keeping only the suite directory and\n // a slug of the test NAME. The name is therefore the one input a repair could move the target\n // with, and that is now ENFORCED rather than assumed — `fencePatchAgainstDraftIdentity` refuses a\n // repair patch addressing `/name` (WR-01), so both ends of the recipe read the same name.\n // Without it the read targets `draft.filePath`, a one-test shelf artifact whose only member is\n // the draft itself, and `neighbours-flaky` is unreachable from this entry point for any app.\n const targetSuitePath = authoredSuiteTargetPath(draft.filePath, draft.testName)\n const receipt = await deps.shelf.verifyDraft({\n draftPath: draft.filePath,\n targetSuitePath,\n ...(input.draftMode === undefined ? {} : { draftMode: input.draftMode }),\n ...(input.sessionRef === undefined ? {} : { sessionRef: input.sessionRef }),\n })\n\n stages.push('route')\n const routed = await routeAfterVerify(\n draft,\n receipt,\n deps,\n statedValues,\n previewed,\n targetSuitePath,\n )\n\n stages.push('compound')\n\n return {\n outcome: routed.outcome,\n stages,\n dedup,\n sideCounters: [],\n fanOut: routed.fanOut,\n refinement,\n }\n}\n","// The authoring brief as prompt blocks — ONE rendering, read by stage 3's two model calls.\n//\n// Stage 3 makes two calls (D-02 whole-document compile, then D-18's one refinement round) and both\n// are given the same substrate in the same words. These renderers were private to `loop.ts` while\n// there was one caller; they moved here when the second arrived, rather than being copied, because\n// two renderings of one brief would let the refinement reason over a differently-worded view of the\n// facts it is refining against — and a difference nobody intended is exactly what a second copy\n// produces the first time either side is edited.\n//\n// WHAT A PROCEDURE CONTRIBUTES, AND WHAT IT MUST NOT (D-17 · T-394-38). `ProcedureMatch` carries\n// `id`, a learned-shelf record id. This module reads `flowAnchor` and never `id`, so the vocabulary\n// a step is authored in is the record's own words while the record's ADDRESS never reaches the\n// model at all. That ordering is the whole mitigation: bytes a model was never shown are bytes it\n// cannot paste into a committed test, and the authored shelf therefore carries nothing that\n// supersession or garbage collection could later turn into a dangling reference.\n\nimport { procedureStepVocabulary } from '@vostride/agent-qa-schema'\nimport type { AuthoringBrief } from '@vostride/agent-qa-schema'\n\n/**\n * The instruction that turns a served procedure into an ordinary step (D-17).\n *\n * Pinned as a constant for the reason {@link AUTHORING_COMPILE_AGENT_CONTEXT} is: it lands in the\n * stable prompt tier, which is the byte prefix a provider's prompt cache keys on, so a\n * per-invocation wording would defeat the caching the tier law exists to enable.\n *\n * It asks for PROSE and forbids a citation, which is the syntactic half of D-17 stated where a\n * model can read it. The semantic half is the vocabulary itself, rendered below.\n */\nexport const PROCEDURE_BY_REFERENCE_INSTRUCTION =\n 'This project already knows how to perform some flows. Where a step of yours is one of the '\n + 'flows listed under PROCEDURE, write that step in that flow\\'s own words, as an ordinary '\n + 'natural-language step. Do NOT cite a record, an id or a reference of any kind, and do not '\n + 'invent a special syntax: the test file stays plain prose, and the flow is recognised when the '\n + 'test runs. A step that matches no listed flow is simply written as you would write any other.'\n\n// 2026-10-12 (440-02, D-04): appended to the compile and refine `Role` bodies.\nexport const REQUEST_WINS_INSTRUCTION =\n 'The request\\'s stated subject, values and checks win over what this project knows: use '\n + 'project knowledge only to decide how to reach them, never to replace them, and keep every '\n + 'quoted string, number, price and date from the request word for word.'\n\n/** The title of the stable block {@link TEST_DOCUMENT_FORMAT_INSTRUCTION} renders under. */\nexport const TEST_DOCUMENT_FORMAT_BLOCK_TITLE = 'Test document format'\n\n/**\n * The title of the CONTEXT block serving this project's `target` vocabulary (394-33, WR-07).\n *\n * CONTEXT AND NOT STABLE, unlike its neighbour above. Target names are per-project facts, and the\n * stable tier is the byte prefix a provider's prompt cache keys on — a project-dependent body\n * there would defeat the sharing the tier law exists to enable. It rides beside the Scope block,\n * which is the block it corrects: `Scope` names a PRODUCT and a `target` is a TARGET NAME, and\n * until this constant existed nothing in the prompt said the two were different kinds of value.\n *\n * The title is referenced BY NAME from {@link TEST_DOCUMENT_FORMAT_INSTRUCTION}'s `target` bullet,\n * so the vocabulary is not merely present in the prompt but is where the instruction sends a\n * reader. A served-but-unreferenced block is a block a model may never look at.\n */\nexport const CONFIGURED_TARGETS_BLOCK_TITLE = 'Configured targets'\n\n/**\n * The served names, one per line — or the honest answer when a project declares none.\n *\n * ONE NAME PER LINE AND NOTHING ELSE around them: no bullets, no quoting, no count. Anything\n * rendered beside a name is something a model can mistake FOR a name, and this is the one block\n * whose whole purpose is that the value it produces is copied out of it verbatim.\n */\nexport function configuredTargetsBlockBody(names: readonly string[]): string {\n if (names.length === 0) {\n return 'This project declares no targets. Ask which target this test should run against '\n + 'rather than inventing one.'\n }\n return names.join('\\n')\n}\n\n/** The line the canonical example follows, and the last prose in the block. */\nexport const TEST_DOCUMENT_FORMAT_EXAMPLE_MARKER = 'A complete document looks exactly like this:'\n\n/**\n * The canonical minimal document, in neutral values.\n *\n * Composed INTO {@link TEST_DOCUMENT_FORMAT_INSTRUCTION} rather than typed twice, so the bytes a\n * test stages through the real parser are the bytes the model is shown.\n */\nexport const TEST_DOCUMENT_FORMAT_EXAMPLE = `name: Confirm the sign-in page shows its heading\ntest-id: t_amber-cotton-ledger-marble-quartz-signal-timber-violet-walnut-yellow\ntarget: sign-in\nsteps:\n - Open the sign-in page\n - Verify the page heading says \"Sign in\"\n`\n\n/**\n * The document SCHEMA, served through a channel that does not depend on memory (WINDOWS 111).\n *\n * Pinned as a constant and landed in the stable tier for the reason\n * {@link PROCEDURE_BY_REFERENCE_INSTRUCTION} is: it is a standing rule about how any document is\n * written rather than a fact about this intent, so it belongs where the byte prefix is shared.\n *\n * A zero-exemplar brief is the bootstrap case — a fresh project has no memory by definition — and\n * `exemplarBlockBody` answers the empty string of prose there. A format rule carried only by the\n * exemplar block is therefore a format rule the first authored test never sees.\n *\n * EVERY SENTENCE HERE IS TRUE AGAINST `TestDefinitionSchema` (394-33, WR-06), AND THAT IS A\n * STANDING OBLIGATION RATHER THAN A ONE-TIME EDIT. A prompt that pins a schema by enumeration is a\n * SECOND SPELLING of that schema, free to drift from the first the moment either side is touched —\n * the same hazard `TEST_DOCUMENT_FORMAT_EXAMPLE` is composed in rather than retyped to avoid. The\n * first draft of this block claimed four keys were all a document may carry, and the cost was\n * specific: `context` is one of the three `EDITABLE_POINTER_ROOTS` and the root `ParsedDraftLike`\n * was widened for in 394-15 so the draft check could read it — and a stage forbidden to\n * emit it could never populate it. The accepted set is `name`, `test-id`, `target`, `steps`,\n * `context`, `use`, `meta`, `setup`, `teardown`, and the schema is `.strict()`, which is the half\n * of the old closing claim that was always true.\n *\n * WHAT IS NAMED BUT NOT TAUGHT. `use`, `meta`, `setup` and `teardown` are accepted by the parser\n * and are stated here as accepted, because a rejection sentence that swept them up would be false\n * again in the other direction. They are not TAUGHT — no shape, no example — because this stage\n * authors a first draft and a hook id it invented would name a hook no project has.\n */\nexport const TEST_DOCUMENT_FORMAT_INSTRUCTION =\n 'A test document has these four required top-level keys:\\n'\n + '- `name`: the test\\'s display name, one line of plain English.\\n'\n + '- `test-id`: a stable identifier — the letters `t_` followed by exactly ten lowercase words '\n + 'joined by hyphens. Choose ten words of your own rather than copying the example\\'s.\\n'\n + '- `target`: the test\\'s target, chosen from the names in the Configured targets block — '\n + 'never invented. The Scope block names a PRODUCT, which is not always one of those names.\\n'\n + '- `steps`: a YAML list of natural-language step strings, at least one of which asserts '\n + 'concrete expected content.\\n'\n + '`context` is optional: one paragraph of standing background the whole test assumes.\\n'\n + 'The schema also accepts `use`, `meta`, `setup` and `teardown`; this stage does not teach them, '\n + 'so leave them out. Any top-level key outside the ones named here is rejected without the '\n + 'document being read.\\n'\n + 'When the Exemplar tests block carries tests, it shows this project\\'s house style and takes '\n + 'precedence on every question of style; this block is the floor beneath it, not a rival.\\n\\n'\n + `${TEST_DOCUMENT_FORMAT_EXAMPLE_MARKER}\\n\\n${TEST_DOCUMENT_FORMAT_EXAMPLE}`\n\n/** The brief's exemplars, as the context block a model reads them as. */\nexport function exemplarBlockBody(brief: AuthoringBrief): string {\n if (brief.exemplars.length === 0) {\n return 'No exemplar tests were served for this scope. Follow the house YAML test style.'\n }\n return brief.exemplars\n .map((exemplar) => `- ${exemplar.filePath} · ${exemplar.testName}\\n${exemplar.excerpt}`)\n .join('\\n')\n}\n\n/**\n * The brief's cautions, procedures and facts, in the precedence the brief itself locked (ABRF-01).\n *\n * The procedure line renders {@link procedureStepVocabulary} over the flow anchor. The previous\n * form printed `JSON.stringify(flowAnchor)` for any arm that was not a flow, which put a serialized\n * object in front of a model asked to write English; the shared vocabulary function answers every\n * arm in the record's own words and cannot be handed an id to print.\n */\nexport function knowledgeBlockBody(brief: AuthoringBrief): string {\n const lines = [\n ...brief.cautions.map((caution) => `CAUTION: ${caution.summary}`),\n ...brief.procedures.map(\n (procedure) => `PROCEDURE: ${procedureStepVocabulary(procedure.flowAnchor)}`,\n ),\n ...brief.facts.map((fact) => `FACT: ${fact.summary}`),\n ]\n return lines.length === 0 ? 'This scope has no served knowledge yet.' : lines.join('\\n')\n}\n","// Stage 2 — dedup-before-author, the deterministic suite-wide text lane (Phase 394, D-04/D-16).\n//\n// WHAT THIS LANE DOES, in order:\n//\n// 1. Score the caller's INTENT against every test in the authored suite, through the shipped\n// `textOverlap` and no other recipe, on the two axes an intent and a test can actually be\n// COMPARED on — the test's whole document, and the test's name alone — keeping the larger.\n// 2. Keep the highest-scoring member, breaking a tie on the lexicographically smallest\n// workspace-relative identity path.\n// 3. Refuse when that score is at or above the pinned threshold, naming the member, the score,\n// the shared-token count that produced it, and the two continuations an author can take.\n// 4. Otherwise admit, still reporting the closest member so a caller can see what it was\n// nearly.\n//\n// WHY IT IS DETERMINISTIC, and why that is the point rather than a limitation. An intent has no\n// execution fingerprint — nothing has been run, and nothing has even been authored — so 393's\n// anchor-sequence recipe cannot fire here at all, and it is the reason this screen is worth doing\n// before a model call rather than after one. No model judges duplication either: a\n// non-deterministic filter cannot be proven against a frozen corpus, and a filter nobody can prove\n// is a filter whose false-refusal rate is a matter of opinion. What this lane trades away is\n// recall on a crafted paraphrase, and that is bounded rather than unowned — gate 3 remains the\n// anchor-level backstop for near-duplicates that slip the text screen (T-394-15).\n//\n// WHY THE FAILURE DIRECTION IS TOWARD REFUSE. Not re-argued here: `adds-value.ts`'s own comment on\n// `TEXT_FALLBACK_SIMILARITY_THRESHOLD` states the asymmetry for the same comparison on the same\n// normalizer, and one statement of a rule is the whole point of reusing the mechanics.\n//\n// WHAT IT COSTS TO BE WRONG, per direction, is what the threshold comment below measures.\n\nimport { AUTHORING_DEDUP_CONTINUATIONS, suiteTestRef } from '@vostride/agent-qa-schema'\nimport type { AuthoringDedupContinuation } from '@vostride/agent-qa-schema'\n\nimport { textOverlap } from './adds-value.js'\nimport type { SuiteTestIdentity, SuiteTextCorpusEntryLike } from './ports.js'\n\n/**\n * Similarity at or above which an intent is refused as a near-duplicate of an existing test.\n *\n * A PINNED CONSTANT, never config (386 D-15).\n *\n * IT SITS BELOW GATE 3's, DELIBERATELY. `TEXT_FALLBACK_SIMILARITY_THRESHOLD` is 0.5; this is 0.45.\n * The two answer different questions on the same scale — gate 3 asks whether a draft that has\n * already been authored and run adds value, and this asks whether an intent already exists — and\n * the costs of being wrong are not symmetric between them. An over-flagging pre-run screen costs\n * ONE refused invocation the user can re-issue deliberately after reading which test it matched.\n * An under-flagging one costs a duplicate test in the suite, which is paid on every run forever\n * and which nothing downstream will remove.\n *\n * RETUNE, AND IT IS A MEASUREMENT RATHER THAN A PREFERENCE. Before moving this number, re-run the\n * frozen corpus at `__tests__/fixtures/dedup-corpus/expectations.json` and report three things.\n * ALL THREE WERE RE-MEASURED 2026-08-13 on the producible input distribution; the numbers this\n * comment carried until then were taken over whole test DOCUMENTS, which no caller can send, and\n * so described a lane nobody was ever running (394-31, WINDOWS 118).\n * (a) WHICH ROWS MOVE. The corpus carries a boundary triple — 0.4444444444, 0.4500000000 and\n * 0.4545454545 — so the immediate neighbourhood is already instrumented. The value is\n * 0.45 rather than a rounder number because 0.45 is the value the corpus can sit EXACTLY\n * on: the at-threshold utterance's nine tokens are all `uat-381-ladder` tokens, so its\n * Jaccard is 9/20, which is the same IEEE-754 double as the literal here. A pin no row can\n * land on to the digit makes the `>=` direction a coin flip with a constant next to it.\n * Re-measured against the fixed recipe, EVERY row moved up or stayed where it was — max is\n * monotone, so it cannot do anything else — and the pin was not touched. That is what \"no\n * retune was required\" means here: not that nothing moved, but that nothing crossed.\n * (b) THE FALSE-REFUSAL RATE ON THE ACCEPT CONTROLS. The corpus's accept control tops out at\n * 0.4166666667 against the suite, so there is 0.0333 of headroom below and it is the\n * narrowest margin among the rows standing for genuinely new intents. The boundary rows sit\n * closer — below-threshold is 0.0056 under — but they are instrumentation aimed at the pin,\n * not controls, and reading them as controls would report a false-refusal risk the corpus\n * deliberately manufactured. Note that this number MOVES with the comparison universe:\n * 393 measured the same text at 0.4074 by scoring it against one file, and reading the whole\n * suite raised it. A threshold inherited from a narrower universe is measured on a different\n * instrument. It also moves with the AXIS: the same control scores 0.1724 on the whole\n * document and 0.4167 on the name, and the name axis is the one that decides it — so the\n * margin this clause reports is a margin on the axis that actually binds.\n * (c) THE WALL-CLOCK COST PER REFUSED INVOCATION. A refusal here is strictly cheaper than the\n * alternative — TWO token-set intersections per suite member against one model call plus N\n * gate-runs at roughly 22s each — which is why over-flagging is affordable at all. The\n * second axis was expected to double the per-comparison work and MEASURED 1.30×, because\n * the name axis re-tokenizes only a name where the document axis tokenizes every step:\n * 0.0179ms → 0.0232ms per invocation over 6 members, and 0.0369ms over the 10-member demo\n * suite, each the mean of 100000 invocations, measured 2026-08-13. That is roughly six\n * hundred thousand times cheaper than one gate-run it can avoid. Report it rather than\n * assuming it — including the factor, which was assumed 2× and is not — because it is the\n * number that stops being true first if the lane ever grows a per-comparison cost.\n *\n * A retune that only argues from intuition is the failure this comment exists to prevent.\n */\nexport const DEDUP_REFUSE_SIMILARITY_THRESHOLD = 0.45\n\n/**\n * What a refusal NAMES. Every field is evidence a reader can act on, not a summary of a verdict.\n *\n * `matchedRef` is the reference a caller hands to `entities.resolve`, spelled\n * `<filePath>::<testName>` — the same spelling `adds-value.ts`'s gate reason already prints, so\n * the two surfaces that name a suite test name it the same way.\n *\n * IT IS NOT A `TST-###` SHORT-ID, and that is measured rather than an omission. `ENTITY_KINDS`\n * reserves `TST`, but a short-ID exists only once something SIGHTS the entity, and sighting is\n * what mints the permanent address — `resolver/resolve.ts` states that no creation path anywhere\n * calls the ledger, so a refusal could not mint one without becoming a write on a read path.\n * Measured further: `composeLocalAgent()` wires exactly one sighting source, the memory one, so\n * NO suite test has a `TST-###` on any host in this build. Printing one would publish an address\n * that resolves to nothing, which is precisely ENTY-01's never-guess failure. The durable identity\n * is what this build can name truthfully, so it is what the refusal names; when a `TST` sighting\n * source lands, this field is the one place that has to change.\n *\n * `threshold` rides along because a refusal that reports 0.52 without reporting what it was\n * compared to tells an author nothing about whether their draft was borderline.\n */\nexport interface DedupEvidence {\n readonly score: number\n readonly matched: SuiteTestIdentity\n readonly matchedRef: string\n readonly sharedTokens: number\n readonly threshold: number\n}\n\n/** The closest suite member, reported on BOTH arms so an admit can say what it was nearly. */\nexport interface DedupClosest {\n readonly filePath: string\n readonly testName: string\n readonly similarity: number\n}\n\n/**\n * How stage 2 read the suite, and the arm it took.\n *\n * `comparedTests` is on both arms and is the universe claim in one number: the comparison\n * population is EVERY test in the suite, not the fingerprint-covered subset gate 3's primary lane\n * speaks for. A draft duplicating a test the derived index has no rows for is still refused, and a\n * lane that filtered its input would report a smaller count before it reported a wrong match.\n *\n * `closest` is present whenever the corpus was non-empty. On the `duplicate` arm it is the same\n * member `evidence` names — two readings of one comparison, kept so a consumer that only wants\n * \"what was it nearest\" reads one field on both arms.\n */\nexport type DedupScreening =\n | {\n readonly kind: 'no-duplicate'\n readonly comparedTests: number\n readonly closest?: DedupClosest\n }\n | {\n readonly kind: 'duplicate'\n readonly comparedTests: number\n readonly closest: DedupClosest\n readonly evidence: DedupEvidence\n readonly continuations: readonly AuthoringDedupContinuation[]\n }\n\n/**\n * The `entities.resolve` reference for a suite test — the house spelling, in one place.\n *\n * DELEGATES to `suiteTestRef` rather than re-forming the string (394-09). Two spellings of one\n * reference were live in the tree — this one and the schema's, minted there with the words \"so no\n * surface invents a second\" — and while they agreed the drift was invisible. The one that survives\n * is the one in `schema`, because the binder that CONSUMES this ref lives on the other side of the\n * package boundary from the lane that produces it.\n */\nexport function dedupMatchRef(identity: SuiteTestIdentity): string {\n return suiteTestRef(identity.filePath, identity.testName)\n}\n\n/**\n * How alike are an INTENT and a committed test — on the two axes the two can be compared on.\n *\n * WHY TWO. `textOverlap` is a token-set Jaccard, so the denominator is the UNION. An intent is one\n * sentence and has no steps; a suite entry is a name plus every step it runs. Scoring the intent\n * against the entry's whole document therefore puts tokens in the denominator the intent\n * structurally cannot supply, and the resulting score is bounded far below 1 no matter how exactly\n * the two agree. That is not a tuning problem, it is a comparison between things of different\n * kinds, and it made this lane's refusal arm arithmetically unreachable: an intent that was a\n * committed test's name VERBATIM — the strongest duplicate signal that can exist — scored 0.2917\n * against a 0.45 pin, and across the whole shipping demo suite the best such score was 0.40. Ten\n * of ten committed tests were un-refusable, measured live and then generalised (394-30 leg D,\n * 394-VERIFICATION round 4, WINDOWS 118).\n *\n * So the entry is also read on the axis an intent CAN saturate: its name alone. A name and a\n * sentence are both one line of description, and their union carries nothing neither side could\n * have said.\n *\n * THE LARGER WINS, and the direction is the safe one twice over. Max is monotone upward, so no\n * pair the whole-document axis already refused can flip to admit — the change can only add\n * refusals, which is the direction this threshold's own comment spends forty lines arguing for.\n * And a duplicate is a duplicate on EITHER reading: an utterance reciting a procedure a test\n * already performs is caught on the document axis, an utterance naming a test that already exists\n * is caught on the name axis, and neither catches the other's case.\n *\n * BOTH AXES GO THROUGH THE ONE SHIPPED `textOverlap`. Two axes are not two recipes — what differs\n * is which text is compared, never how. A second tokenizer or a second notion of similarity is\n * what D-16 forbids, and nothing here defines either.\n */\nfunction scoreIntentAgainst(\n intent: string,\n entry: SuiteTextCorpusEntryLike,\n): { readonly score: number; readonly sharedTokens: number } {\n const wholeDocument = textOverlap({ testName: intent, steps: [] }, entry)\n const nameOnly = textOverlap(\n { testName: intent, steps: [] },\n { filePath: entry.filePath, testName: entry.testName, stepsText: [] },\n )\n // Strictly greater, so the whole-document axis keeps the reading on a tie. It is the axis this\n // lane shipped with and the one gate 3 screens on, so the evidence a refusal names stays the\n // evidence the post-run gate would name for the same pair whenever the two axes agree.\n return nameOnly.score > wholeDocument.score ? nameOnly : wholeDocument\n}\n\n/**\n * Stage 2 — screen the intent against the authored suite, BEFORE anything is authored.\n *\n * The intent stands in for the draft's text because at this point there IS no draft, which is what\n * makes the screen worth doing at all. It is scored through `textOverlap`, the shipped comparison\n * gate 3's degraded lane already screens with (393 D-16), rather than through a second recipe: two\n * notions of \"how alike are these two tests\" would let the pre-authoring screen and the post-run\n * gate disagree about the same pair. Which TEXTS that recipe is pointed at is\n * {@link scoreIntentAgainst}'s subject.\n *\n * THE TIE-BREAK IS PART OF THE CONTRACT, not an implementation detail. Two suite tests can score\n * identically — most easily when a suite carries the same test at two paths — and a lane that took\n * whichever the host happened to yield first would report a different duplicate on a re-run over\n * the same suite, which makes the refusal's link unreliable at exactly the moment a user is\n * deciding whether to trust it. The smallest workspace-relative identity path wins, so two\n * invocations against one suite name one test.\n */\nexport function dedupBeforeAuthor(\n intent: string,\n corpus: readonly SuiteTextCorpusEntryLike[],\n): DedupScreening {\n let best: { readonly entry: SuiteTextCorpusEntryLike; readonly overlap: { score: number; sharedTokens: number } } | undefined\n\n for (const entry of corpus) {\n const overlap = scoreIntentAgainst(intent, entry)\n if (\n best === undefined\n || overlap.score > best.overlap.score\n // Strictly smaller, so the running best is only displaced by a genuinely earlier path. A\n // `<=` here would make the LAST of a tied group win and re-introduce iteration order.\n || (overlap.score === best.overlap.score && entry.filePath < best.entry.filePath)\n ) {\n best = { entry, overlap }\n }\n }\n\n if (best === undefined) return { kind: 'no-duplicate', comparedTests: corpus.length }\n\n const closest: DedupClosest = {\n filePath: best.entry.filePath,\n testName: best.entry.testName,\n similarity: best.overlap.score,\n }\n\n // `>=`, so a score sitting exactly on the pin reads as duplicate and the intent is refused.\n // Over-flagging toward refuse is the safe failure here for the reason the threshold's own\n // comment measures, and it is what makes a pin the corpus can land on exactly usable at all.\n if (best.overlap.score < DEDUP_REFUSE_SIMILARITY_THRESHOLD) {\n return { kind: 'no-duplicate', comparedTests: corpus.length, closest }\n }\n\n const matched: SuiteTestIdentity = {\n filePath: best.entry.filePath,\n testName: best.entry.testName,\n }\n return {\n kind: 'duplicate',\n comparedTests: corpus.length,\n closest,\n evidence: {\n score: best.overlap.score,\n matched,\n matchedRef: dedupMatchRef(matched),\n sharedTokens: best.overlap.sharedTokens,\n threshold: DEDUP_REFUSE_SIMILARITY_THRESHOLD,\n },\n continuations: AUTHORING_DEDUP_CONTINUATIONS,\n }\n}\n","// Gate 3 — adds-value (Phase 393, D-13/D-14/D-16 · WTST-02).\n//\n// SET SEMANTICS, NO THRESHOLD, ON THE PRIMARY LANE (D-14, spec §6.3 verbatim). The draft adds\n// value when at least one of its fingerprint elements is absent from the union of the suite's.\n// There is no similarity score here and therefore no magic constant to defend: conservatism lives\n// in the normalizer, where \"near-same elements are the same element\" already has exactly one\n// definition. The receipt NAMES the uncovered elements rather than counting them, because a gate\n// that says \"0.31\" tells an author nothing they can act on.\n//\n// BOTH SIDES OF THE COMPARISON ARE MINTED BY ONE FUNCTION. The suite union is folded from\n// `testFingerprintElements`; so is the draft's own element list, from the draft's member outcome\n// inside its gate-run document. The elements arrive here already computed — see `verify-draft.ts`\n// — and this module never derives them, which is what stops a second recipe from appearing on the\n// draft side and turning a comparison of two tests into a comparison of two derivations.\n//\n// THE TEXT LANE IS DEGRADED, AND SAYS SO PER TEST (D-16). A suite test the derived index has no\n// evidence for cannot join the set comparison at all, and dropping it would let a draft look novel\n// purely because the thing it duplicates has never been run. So those tests join on text\n// similarity instead, over-flagging toward \"already covered\" — the safe direction, symmetric with\n// the ratified dedup posture — and every compared test carries the lane that answered for it, so a\n// fingerprint-lane fact and a text-lane guess can never be read as the same claim.\n//\n// DECIDER PRECEDENCE, AND IT IS NOT SYMMETRIC (D-14 over D-16 · CR-01). Wherever the fingerprint\n// lane CAN speak — a non-empty suite union — it is the whole verdict, and the text lane's\n// resemblances are recorded per compared test without deciding. Only when the union is empty, so\n// the primary lane has nothing to say, does the text lane decide. The shipped decider was\n// `novel > 0 && textCovered.length === 0`, which is the other arrangement: a 0.5 Jaccard guess\n// vetoing a fingerprint fact, and — because the derived index is gitignored and therefore empty on\n// every fresh checkout and every CI job — the SOLE decider in the common case, on a threshold D-14\n// says this gate does not have. Two concurrent deciders is the defect, not the ordering of them.\n// If a future change gives the text lane a say where a union exists, it is re-minting that defect.\n\nimport type { AddsValueFinding } from '@vostride/agent-qa-schema'\n\nimport type { SuiteFingerprintIndexLike, SuiteTextCorpusEntryLike } from './ports.js'\n\n/**\n * Similarity at or above which an evidence-less suite test counts as already covering the draft.\n *\n * A PINNED CONSTANT, never config (386 D-15). It is the only number in this gate, and it exists\n * only on the degraded lane — the fingerprint lane has none by ratified design.\n *\n * RETUNE COMMENT — and this one comes with its measurement. The pair the constant has to separate\n * is the frozen corpus's own: `gate3-near-duplicate.yaml` was authored to mirror\n * `uat-381-local-form.yaml`'s anchors in different words, and `accept-control.yaml` was authored\n * not to. Against uat-381 those two score **0.5000** and **0.4074** respectively under\n * `textSimilarity` below (measured 2026-08-10), so this value sits exactly ON the duplicate and\n * 0.093 above the control — the whole usable band is under a tenth of a point, and the duplicate\n * has zero margin above the line. That is the honest reason D-16 calls this lane a fallback rather\n * than a comparison: two tests of the same small app share most of their tokens whatever they do,\n * so the signal lives in the tail. Two consequences follow, both deliberate. The comparison is\n * `>=`, so a tie reads as covered and the draft loses — over-flagging toward covered is the safe\n * failure, and it is what makes a value sitting exactly on the duplicate usable at all. And RAISING\n * this number immediately stops catching the duplicate, while LOWERING it has room down to 0.4074\n * before it starts refusing the accept control; the asymmetry is worth knowing before reaching for\n * the knob.\n *\n * Before moving it, re-measure BOTH corpus scores (the test\n * `separates the corpus near-duplicate from the corpus accept control` prints the pair by\n * failing), and re-run the frozen expectations table — a widening that catches one more duplicate\n * while failing the accept control has moved the gate's numerator in the direction that costs a\n * user a good test.\n */\nexport const TEXT_FALLBACK_SIMILARITY_THRESHOLD = 0.5\n\nexport interface DraftTextLike {\n readonly testName: string\n readonly steps: readonly string[]\n}\n\nexport interface AddsValueGateInput {\n /** The draft's identity name and pre-interpolation step text, for the text lane. */\n readonly draft: DraftTextLike\n /** The draft's own fingerprint elements, in exercised order. */\n readonly draftElements: readonly string[]\n readonly index: SuiteFingerprintIndexLike\n /** D-16's evidence-less population: the authored suite MINUS `index.coveredTests()`. */\n readonly textCorpus: readonly SuiteTextCorpusEntryLike[]\n}\n\nexport interface AddsValueGateResult {\n readonly pass: boolean\n readonly finding: AddsValueFinding\n readonly reason: string\n}\n\n/**\n * Normalized tokens: lowercase, split on anything that is not a letter or digit, empties dropped.\n *\n * No stopword list. A closed set of English function words would be a fifth lexicon to maintain\n * and retune, and its effect here is small in a fixed direction: shared function words inflate\n * every pair's score roughly equally, which the threshold absorbs once rather than per comparison.\n */\nfunction tokens(texts: readonly string[]): Set<string> {\n const set = new Set<string>()\n for (const text of texts) {\n for (const token of text.toLowerCase().split(/[^a-z0-9]+/)) {\n if (token !== '') set.add(token)\n }\n }\n return set\n}\n\n/**\n * What one text comparison produced: the Jaccard score AND the intersection size behind it.\n *\n * TWO READINGS OF ONE COMPARISON, not two comparisons. `textSimilarity` is the score alone and is\n * what this gate decides on; 394's stage-2 dedup refusal has to NAME the evidence that produced\n * its verdict (D-04), and a shared-token count recomputed on the other side of that seam would be\n * a second tokenizer — the one thing D-16 says must not exist, since two normalizers let a\n * pre-authoring screen and a post-run gate disagree about the same pair. So the count is reported\n * out of the same traversal over the same {@link tokens} normalizer, and there is still exactly\n * one definition of how alike two tests are.\n */\nexport interface TextOverlap {\n /** Token-set Jaccard, symmetric and bounded. */\n readonly score: number\n /** How many normalized tokens the two texts share — the numerator, reported. */\n readonly sharedTokens: number\n}\n\n/**\n * Token-set Jaccard between a draft and a suite test's text (D-16's fallback comparison).\n *\n * Symmetric and bounded, and TWO EMPTY TEXTS SCORE 0 rather than 1: the degenerate `0/0` is not\n * an identity, and reading it as one would let a single empty text-corpus entry cover every draft\n * ever evaluated — an over-flag so complete it would turn the safe direction into a gate that\n * always says no. A zero score on an empty side reports zero shared tokens, which is the true\n * count rather than a sentinel.\n */\nexport function textOverlap(draft: DraftTextLike, entry: SuiteTextCorpusEntryLike): TextOverlap {\n const left = tokens([draft.testName, ...draft.steps])\n const right = tokens([entry.testName, ...entry.stepsText])\n if (left.size === 0 || right.size === 0) return { score: 0, sharedTokens: 0 }\n\n let shared = 0\n for (const token of left) if (right.has(token)) shared += 1\n return { score: shared / (left.size + right.size - shared), sharedTokens: shared }\n}\n\n/** The score half of {@link textOverlap} — this gate's whole reading of a text comparison. */\nexport function textSimilarity(draft: DraftTextLike, entry: SuiteTextCorpusEntryLike): number {\n return textOverlap(draft, entry).score\n}\n\n/** The draft's elements that no suite test has exercised, deduplicated, in first-seen order. */\nfunction novelElementsOf(\n draftElements: readonly string[],\n union: ReadonlySet<string>,\n): string[] {\n const novel: string[] = []\n const seen = new Set<string>()\n for (const element of draftElements) {\n if (union.has(element) || seen.has(element)) continue\n seen.add(element)\n novel.push(element)\n }\n return novel\n}\n\n/**\n * The stable identity as one comparable key.\n *\n * The separator is written as the ESCAPE `\\u0000`, never as a raw control byte in this source.\n * 393-05 shipped a module carrying a literal NUL and `file(1)` classified the whole file `data`,\n * so `grep` reported it as empty — a false CLEAN verdict from the exact instrument this phase's\n * posture checks rely on. (This very function was written with a raw 0x1F first; `file(1)` said\n * `data` and the lesson landed a second time in one phase.) A separator is still needed, because\n * concatenation alone lets (\"ab\", \"c\") and (\"a\", \"bc\") collide.\n */\nfunction identityKey(filePath: string, testName: string): string {\n return `${filePath}\\u0000${testName}`\n}\n\n/**\n * Gate 3 over an already-minted draft element list.\n *\n * The gate is answered even when gate 1 failed and the draft produced little or no evidence —\n * D-04 forbids short-circuiting, and a gate that returned a default in that case would make the\n * corpus's independence claim unprovable. What it returns then is `false` with a reason naming the\n * absence, which is the honest reading: nothing was shown to be novel, which is not the same claim\n * as \"this draft duplicates the suite\" and the reason string keeps the two apart.\n */\nexport function addsValueGate(input: AddsValueGateInput): AddsValueGateResult {\n const union = input.index.elementUnion()\n const covered = input.index.coveredTests()\n\n // D-16: a truly empty suite trivially passes — everything is uncovered. Stated as its own rule\n // rather than left to fall out of the novel-element count, which answers `false` for a draft\n // with no elements and would deny the first test a project ever writes.\n if (union.size === 0 && input.textCorpus.length === 0) {\n return {\n pass: true,\n finding: { novelElements: [...new Set(input.draftElements)], comparedTests: [] },\n reason: 'the suite is empty — no fingerprint coverage and no comparable text, so every '\n + 'element is uncovered (D-16)',\n }\n }\n\n const novelElements = novelElementsOf(input.draftElements, union)\n const draftElementSet = new Set(input.draftElements)\n\n const comparedTests: AddsValueFinding['comparedTests'] = covered.map((identity) => {\n const suiteElements = new Set(\n input.index.elementsForTest(identity.filePath, identity.testName),\n )\n return {\n filePath: identity.filePath,\n testName: identity.testName,\n lane: 'fingerprint' as const,\n // Does THIS test on its own subsume everything the draft exercised — the per-test statement\n // behind a union-level verdict, so an author told \"already covered\" can be told by what.\n covered: draftElementSet.size > 0\n && [...draftElementSet].every((element) => suiteElements.has(element)),\n }\n })\n\n // The text lane, over identities the fingerprint lane could not speak for. A host that hands\n // over an identity WITH evidence anyway is answered by the lane that has it: one test may appear\n // once, or the receipt would carry two lanes for one comparison and contradict itself.\n const fingerprintIdentities = new Set(\n covered.map((identity) => identityKey(identity.filePath, identity.testName)),\n )\n const textCovered: SuiteTextCorpusEntryLike[] = []\n for (const entry of input.textCorpus) {\n if (fingerprintIdentities.has(identityKey(entry.filePath, entry.testName))) continue\n const similar = textSimilarity(input.draft, entry) >= TEXT_FALLBACK_SIMILARITY_THRESHOLD\n if (similar) textCovered.push(entry)\n comparedTests.push({\n filePath: entry.filePath,\n testName: entry.testName,\n lane: 'text',\n covered: similar,\n })\n }\n\n // D-14 outranks D-16 wherever the primary lane has evidence: a non-empty union means the\n // fingerprint lane spoke, and its answer is the verdict. The text lane decides only in the state\n // it was ratified for — an index that can say nothing at all.\n const pass = union.size > 0\n ? novelElements.length > 0\n : novelElements.length > 0 && textCovered.length === 0\n\n return { pass, finding: { novelElements, comparedTests }, reason: gateReason({\n pass,\n novelElements,\n unionSize: union.size,\n draftElementCount: draftElementSet.size,\n textCovered,\n }) }\n}\n\nfunction gateReason(input: {\n pass: boolean\n novelElements: readonly string[]\n unionSize: number\n draftElementCount: number\n textCovered: readonly SuiteTextCorpusEntryLike[]\n}): string {\n // Every branch NAMES THE LANE THAT ANSWERED. The verdict is one boolean over two possible\n // sources, so a receipt that does not say which one decided cannot be audited for whether a\n // fingerprint fact or a degraded-lane guess produced it.\n if (input.pass && input.unionSize > 0) {\n const decided = `${input.novelElements.length} element(s) absent from the suite union of `\n + `${input.unionSize} — the fingerprint lane decided (D-14)`\n if (input.textCovered.length === 0) {\n return `${decided}, and no evidence-less suite test resembles the draft (D-16)`\n }\n return `${decided}; ${input.textCovered.length} evidence-less suite test(s) resemble the draft `\n + 'on the degraded text lane and are recorded per compared test without deciding (D-16)'\n }\n if (input.pass) {\n return 'the suite fingerprint index is empty, so the degraded text lane decided: no '\n + 'evidence-less suite test resembles the draft (D-16)'\n }\n if (input.unionSize === 0 && input.textCovered.length > 0) {\n return 'the text fallback lane matched '\n + input.textCovered.map((entry) => `${entry.filePath}::${entry.testName}`).join(', ')\n + ` at or above ${TEXT_FALLBACK_SIMILARITY_THRESHOLD} similarity — an evidence-less suite `\n + 'test this draft resembles, flagged toward already-covered (D-16)'\n }\n if (input.draftElementCount === 0) {\n return 'the draft produced no fingerprint elements, so nothing could be shown to be novel — '\n + 'not a finding that it duplicates the suite (check gate 1 first)'\n }\n return `every element the draft exercised (${input.draftElementCount}) is already in the suite `\n + `union of ${input.unionSize} (D-14)`\n}\n","// The one unconditional draft-as-query refinement round (394-09, D-18 · WTST-01/WTST-07).\n//\n// After the whole-document compile, the loop re-retrieves keyed on the DRAFT'S OWN steps and\n// anchors and gives the model exactly one pass to improve what it just wrote — emitted as RFC-6902\n// patches through the shipped CST applier, never as a second whole document.\n//\n// WHY THE ROUND IS UNCONDITIONAL, which is the decision rather than the mechanism. The obvious\n// alternative is a trigger: refine only when the first retrieval came back thin, or when the draft\n// is long, or when some score is low. Every one of those is a RULE ABOUT WHEN KNOWLEDGE MATTERS,\n// and that rule rots faster than the knowledge does — the moment the brief's contents shift, a\n// threshold calibrated against last quarter's corpus starts skipping exactly the drafts that most\n// needed a second look, silently and with no failing test anywhere. Retrieval here is local and\n// cheap, so the argument for one round is not that a round is expensive; it is that the loop's\n// shape stays deterministic and its fan-out preview keeps describing what actually happens.\n//\n// WHY THE QUERY IS THE DRAFT AND NOT THE INTENT. The intent has already been retrieved against, at\n// stage 1, and re-asking it would return the brief the compile was given — a second call over the\n// same substrate, which can only confirm. The compiled steps name things the intent did not: a\n// concrete flow, a page, an element, a phrase that matches a caution nobody thought to ask for. So\n// this round asks the question the intent could not, which is what makes it a round rather than a\n// retry.\n// 2026-10-12 (440, D-06): the prompt carries the request too; only the retrieval query stays the draft's words.\n//\n// WHY A FAILED REFINEMENT DOES NOT FAIL THE INVOCATION. What arrives is a model emission, and the\n// three ways it can be unusable — not a patch set at all, a patch set the fence or the applier\n// refuses, a patched document that no longer parses — are all facts about the REFINEMENT and not\n// about the compiled draft, which was already parsed and staged before this ran. Ending the whole\n// invocation on any of them would let an optional improvement destroy a good draft. So the outcome\n// is a discriminated union: the draft always survives, and the arm says what happened to it, which\n// is the difference between a degraded round a reader can see and one that quietly does nothing.\n\nimport { TestEditPatchSetSchema } from '@vostride/agent-qa-schema'\nimport type { ScopeKey, TestEditPatchSet } from '@vostride/agent-qa-schema'\n\nimport { exemplarBlockBody, knowledgeBlockBody, REQUEST_WINS_INSTRUCTION } from './brief-blocks.js'\nimport type {\n AuthoringReadPortLike,\n DraftShelfPortLike,\n ParsedDraftLike,\n} from './ports.js'\nimport {\n extractStatedValues,\n missingStatedValues,\n statedValuesMissingReason,\n} from './stated-values.js'\nimport { buildTieredPrompt } from '../prompt/tiered-prompt-builder.js'\n\n/**\n * How many refinement rounds run per compiled draft. Exactly one, always (D-18).\n *\n * RETUNE — what a change to this number has to report, and what it may not be.\n *\n * It may NOT become a condition. Raising it to 2 is a retune; making the second round fire only\n * when some signal says the first one found something is not a retune, it is the trigger heuristic\n * D-18 rules out, and it is ruled out for a stated reason rather than a preference: a trigger is a\n * rule about when this project's own knowledge is worth consulting, and nothing in the codebase\n * fails when that rule goes stale.\n *\n * A retune must report, over the frozen draft corpus: how many drafts a second round CHANGES at\n * all (a round that emits no patches on every member is a round nobody needs), how many of those\n * changes survive the gates that the one-round draft did not, and the token cost of the extra call\n * priced per additional keep. Two of those three are cheap to get wrong in the flattering\n * direction — \"the model emitted patches\" is not \"the draft got better\" — so the middle number is\n * the one that decides, and it is the one a receipt can settle rather than an impression.\n *\n * Lowering it to 0 is also a retune, and it needs the same evidence pointed the other way: the\n * round's contribution measured, not assumed absent.\n */\nexport const REFINEMENT_ROUNDS = 1\n\n/**\n * The `agent_context` the refinement call carries into the ONE tiered prompt builder (389 D-04).\n *\n * A pinned string, distinct from the compile call's, for the reason that one is pinned: it lands in\n * the stable tier, which is the byte prefix a provider's prompt cache keys on. Distinct because the\n * two calls ask genuinely different questions — write a document, versus change one that exists —\n * and a shared context line would tell the model neither.\n */\nexport const AUTHORING_REFINE_AGENT_CONTEXT =\n 'authoring.draft.write — refine a compiled draft against newly retrieved facts and procedures'\n\n/**\n * What one refinement round did to the draft it was given.\n *\n * THREE ARMS AND THE DRAFT ON EVERY ONE. The loop continues with `outcome.draft` whatever happened,\n * so no caller has to remember which arms carry a replacement — and no arm can be read as \"the\n * draft is gone\".\n *\n * `refined` patches applied; `draft` is the patched, re-parsed, re-staged document.\n * `no-op` the model emitted zero patches. A VALID answer, not an error: it saw nothing new.\n * `not-applied` the emission or its application was refused. The compiled draft continues, and\n * `reason` is the refusal, kept so a receipt reader can tell a round that found\n * nothing apart from a round that could not be used.\n */\nexport type RefinementOutcome =\n | {\n readonly kind: 'refined'\n readonly draft: ParsedDraftLike\n readonly patchCount: number\n readonly thoughts: string\n }\n | { readonly kind: 'no-op'; readonly draft: ParsedDraftLike; readonly thoughts: string }\n | { readonly kind: 'not-applied'; readonly draft: ParsedDraftLike; readonly reason: string }\n\nexport interface RefineDraftDeps {\n readonly read: AuthoringReadPortLike\n readonly shelf: DraftShelfPortLike\n}\n\n/**\n * The draft, as the retrieval query for its own second round (D-18).\n *\n * The test's NAME and its STEP TEXT, in document order, and nothing else. Not the intent — see the\n * header. Not the file path or the digest either: those are addresses this host minted, they name\n * no fact about an application, and a retrieval keyed partly on a content digest would return a\n * different brief for two drafts that say the same thing.\n *\n * Exported because it is the claim worth pinning on its own: a cell can assert the query carries\n * the draft's words and not the intent's without having to reconstruct a prompt to find out.\n */\nexport function draftRetrievalQuery(draft: ParsedDraftLike): string {\n return [draft.testName, ...draft.steps].join('\\n')\n}\n\n/** The draft as the model is shown it for refinement — the same two facts the query is built on. */\nfunction draftBlockBody(draft: ParsedDraftLike): string {\n return [\n `Test name: ${draft.testName}`,\n 'Steps, in order:',\n ...draft.steps.map((step, index) => ` ${index}. ${step}`),\n ].join('\\n')\n}\n\n/**\n * What came back, parsed as a patch set — or the reason it could not be.\n *\n * The emission is JSON text a model produced, so BOTH failure modes are ordinary rather than\n * exceptional: bytes that are not JSON, and JSON that is not this contract. Neither throws out of\n * here; the caller turns them into the `not-applied` arm with the reason attached.\n */\nfunction parsePatchSet(text: string): { patchSet: TestEditPatchSet } | { reason: string } {\n let json: unknown\n try {\n json = JSON.parse(text)\n } catch (error) {\n return { reason: `the refinement emission is not JSON: ${(error as Error).message}` }\n }\n const parsed = TestEditPatchSetSchema.safeParse(json)\n return parsed.success\n ? { patchSet: parsed.data }\n : { reason: `the refinement emission is not a patch set: ${parsed.error.issues[0]?.message}` }\n}\n\n/**\n * Run THE refinement round. Unconditional: there is no early return above the retrieval.\n *\n * Read the body top to bottom and there is no `if` between the entry and the model call — no\n * emptiness check on the first brief, no length test on the draft, no cached-result short circuit.\n * That absence is the contract, and `refine.test.ts` drives the case a trigger would skip: a draft\n * whose first retrieval already returned facts still gets its round.\n */\nexport async function refineDraft(\n draft: ParsedDraftLike,\n input: { readonly scope: ScopeKey; readonly intent: string },\n deps: RefineDraftDeps,\n): Promise<RefinementOutcome> {\n const brief = await deps.read.getAuthoringBrief(draftRetrievalQuery(draft), input.scope)\n\n const request = buildTieredPrompt({\n agent_context: AUTHORING_REFINE_AGENT_CONTEXT,\n stable: [\n {\n title: 'Role',\n body: 'You improve an agent-qa test document that has already been written. Reply with '\n + 'ONE JSON object and nothing else: {\"thoughts\": string, \"patches\": [...]}, where each '\n + 'patch is an RFC-6902 op with \"op\" one of add/remove/replace, a JSON Pointer \"path\", '\n + 'and for add/replace a string \"value\". Only /steps, /name and /context may be '\n + 'addressed. Emit an EMPTY patches array when the knowledge below adds nothing — that '\n + 'is a correct answer, and inventing a change to look useful is not. '\n + REQUEST_WINS_INSTRUCTION,\n },\n ],\n context: [\n { title: 'Intent', body: input.intent },\n { title: 'The draft as it stands', body: draftBlockBody(draft) },\n { title: 'What this project knows about these steps', body: knowledgeBlockBody(brief) },\n ],\n volatile: [{ title: 'Exemplar tests', body: exemplarBlockBody(brief) }],\n })\n\n const model = await deps.shelf.model()\n const emitted = await model.generate(request)\n\n const parsed = parsePatchSet(emitted.text)\n if ('reason' in parsed) return { kind: 'not-applied', draft, reason: parsed.reason }\n\n // AN EMPTY SET SHORT-CIRCUITS THE APPLIER, and that is not an optimisation. 394-03's corpus pins\n // that an empty set renders byte-identical output, so routing one through would be a provably\n // no-op re-stage — but it would still be a WRITE, and a round that touched the shelf on every\n // invocation would make \"this refinement changed nothing\" indistinguishable, on disk, from one\n // that did. The arm says it instead.\n if (parsed.patchSet.patches.length === 0) {\n return { kind: 'no-op', draft, thoughts: parsed.patchSet.thoughts }\n }\n\n // THE SAME APPLIER THE REPAIR LOOP AND THE EDIT OP USE, reached through the port for the reason\n // stated on the port itself: it needs the yaml CST, which lives in a package this one may not\n // depend on. A refusal here — the region fence, an unresolvable pointer, a patched document that\n // no longer parses — arrives as a throw or as the `unparsable` arm, and both mean the same thing\n // to this round: the compiled draft stands.\n let staged\n try {\n staged = await deps.shelf.applyPatches(draft, parsed.patchSet)\n } catch (error) {\n return { kind: 'not-applied', draft, reason: (error as Error).message }\n }\n if (staged.kind === 'unparsable') return { kind: 'not-applied', draft, reason: staged.reason }\n\n // 2026-10-12 (440-04, D-06): a patch that loses a stated value is dropped; the compiled draft\n // already passed the same check at compile.\n const missing = missingStatedValues(extractStatedValues(input.intent), staged.draft.steps)\n if (missing.length > 0) {\n return { kind: 'not-applied', draft, reason: statedValuesMissingReason(missing) }\n }\n\n return {\n kind: 'refined',\n draft: staged.draft,\n patchCount: parsed.patchSet.patches.length,\n thoughts: parsed.patchSet.thoughts,\n }\n}\n","// 2026-10-12 (440-01, D-03): the request's stated values and the draft steps that lose them. Pure,\n// linear and model-free, because the request is untrusted text from any caller.\n\ntype QuoteKind = 'double' | 'curly' | 'single'\ntype Span = { readonly start: number; readonly end: number }\ntype Run = { next: number; delimiter: string; pending: Span[]; sentenceLike: boolean }\ntype Part = { readonly start: number; readonly end: number; readonly quoted?: string }\ntype RunStart = 'at-once' | 'pending'\n\nconst CURRENCY_SYMBOLS = '$€£¥₹'\nconst NUMBER_SEPARATORS = '.,:/-'\nconst SINGLE_QUOTE_OPENS_AFTER = ' ([\\n'\nconst SINGLE_QUOTE_CLOSES_BEFORE = ' .,;:!?)]\\n'\nconst LINE_BREAKS = '\\n\\r
'\nconst LIST_RUN_STARTS_AFTER = ':.!?'\nconst QUOTE_MASK = '\"'\n\nconst MONTH =\n '(?:January|February|March|April|May|June|July|August|September|October|November|December' +\n '|Sept|Jan|Feb|Mar|Apr|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\\\\.?'\nconst DAY = '\\\\d{1,2}(?:st|nd|rd|th)?'\nconst MONTH_NAME_DATE =\n `(?<![\\\\p{L}\\\\p{N}])(?:${MONTH} ${DAY}(?:,? \\\\d{4})?|${DAY} ${MONTH}(?: \\\\d{4})?)` +\n '(?![\\\\p{L}\\\\p{N}])'\nconst STEP_LABEL =\n '(?<![\\\\p{L}\\\\p{N}])(?:Step|step|STEP) ([0-9]+)(?=([:)]|\\\\.(?=\\\\s|$)| [-–—]))'\nconst MONTH_BEFORE = new RegExp(`(?<![\\\\p{L}\\\\p{N}])${MONTH} $`, 'u')\n\nconst HOST_AND_PORT = /^[A-Za-z][A-Za-z0-9.-]*:\\d+(?:\\/\\S*)?[.,;!?)\\]]*$/\nconst IPV4_ADDRESS = /^\\d{1,3}(?:\\.\\d{1,3}){3}(?::\\d+)?(?:\\/\\S*)?[.,;!?)\\]]*$/\nconst BRACKETED_IPV6 = /^\\[[0-9A-Fa-f.:]+\\](?::\\d+)?(?:\\/\\S*)?[.,;!?)\\]]*$/\nconst DECADE_ELISION = /^\\d0s(?![\\p{L}\\p{N}'’])/u\nconst LEADING_UPPERCASE = /^\\p{Lu}/u\nconst LEADING_LETTER_OR_NUMBER = /^[\\p{L}\\p{N}]/u\nconst TRAILING_LETTER_OR_NUMBER = /[\\p{L}\\p{N}]$/u\n\nfunction tidy(text: string): string {\n return text.normalize('NFC').replace(/\\s+/g, ' ').trim()\n}\n\nfunction isDigit(char: string | undefined): boolean {\n return char !== undefined && char >= '0' && char <= '9'\n}\n\nfunction isSeparator(char: string | undefined): boolean {\n return char !== undefined && char.length === 1 && NUMBER_SEPARATORS.includes(char)\n}\n\nfunction letterOrNumberBefore(text: string, index: number): boolean {\n return TRAILING_LETTER_OR_NUMBER.test(text.slice(Math.max(0, index - 2), index))\n}\n\nfunction letterOrNumberAt(text: string, index: number): boolean {\n return LEADING_LETTER_OR_NUMBER.test(text.slice(index, index + 2))\n}\n\n// 2026-10-12 (440-08, WR-01): an inch mark (`15\"`) and a leading elision (`'90s`) open no quote.\n// 2026-10-12 (440-10, WR-06): only a decade such as `'90s` is an elision, so `'4K'` is a value.\nfunction openerAt(text: string, index: number): QuoteKind | undefined {\n const char = text[index]\n if (char === '\"') return letterOrNumberBefore(text, index) ? undefined : 'double'\n if (char === '“') return 'curly'\n if (char !== \"'\" && char !== '‘') return undefined\n const before = text[index - 1]\n if (before !== undefined && !SINGLE_QUOTE_OPENS_AFTER.includes(before)) return undefined\n return DECADE_ELISION.test(text.slice(index + 1, index + 5)) ? undefined : 'single'\n}\n\nfunction closerOf(text: string, kind: QuoteKind, from: number): number {\n if (kind === 'double') return text.indexOf('\"', from)\n if (kind === 'curly') return text.indexOf('”', from)\n for (let index = from; index < text.length; index += 1) {\n const char = text[index]\n if (char !== \"'\" && char !== '’') continue\n const after = text[index + 1]\n if (after === undefined || SINGLE_QUOTE_CLOSES_BEFORE.includes(after)) return index\n }\n return -1\n}\n\n// 2026-10-12 (440-10, WR-07): an IPv6 literal holds `::` or at least six colons, so a bracketed\n// time or ratio is a value.\nfunction holdsIpv6Groups(inside: string): boolean {\n return inside.includes('::') || inside.split(':').length > 6\n}\n\n// 2026-10-12 (440-08, WR-03): an IP or bracketed IPv6 host, with or without a port, states nothing.\nfunction isAddress(chunk: string): boolean {\n const bare = chunk.startsWith('(') ? chunk.slice(1) : chunk\n return (\n bare.includes('://') ||\n bare.startsWith('www.') ||\n HOST_AND_PORT.test(bare) ||\n IPV4_ADDRESS.test(bare) ||\n (BRACKETED_IPV6.test(bare) && holdsIpv6Groups(bare.slice(1, bare.indexOf(']'))))\n )\n}\n\nfunction collapsedSpace(space: string): string {\n return [...space].some((char) => LINE_BREAKS.includes(char)) ? '\\n' : ' '\n}\n\nfunction isSpace(char: string | undefined): boolean {\n return char === ' ' || char === '\\n'\n}\n\nfunction blank(chars: string[], span: Span): void {\n for (let index = span.start; index < span.end; index += 1) chars[index] = ' '\n}\n\nfunction runStartAt(text: string, index: number): RunStart | undefined {\n if (index === 0 || (index === 1 && isSpace(text[0]))) return 'at-once'\n const before = text[index - 1]\n if (before === '\\n') return 'at-once'\n if (before === ' ' && LIST_RUN_STARTS_AFTER.includes(text[index - 2] ?? ' ')) return 'pending'\n return undefined\n}\n\nfunction endsSentence(text: string, tokenEnd: number): boolean {\n return isSpace(text[tokenEnd]) && LEADING_UPPERCASE.test(text.slice(tokenEnd + 1, tokenEnd + 3))\n}\n\n// 2026-10-12 (440-11, WR-05): a step label counts like a list marker, from a run start and by the\n// next number.\n// 2026-10-12 (440-13, WR-09): a held step label and its next label that each end a sentence wait for a third, as list markers do.\n// 2026-10-12 (440-13, WR-11): the open run and the held candidate are kept apart, so a held 1 inside an item never takes over its list.\nfunction blankStepLabels(text: string, chars: string[]): void {\n const open: Run = { next: 0, delimiter: '', pending: [], sentenceLike: false }\n const held: Run = { next: 0, delimiter: '', pending: [], sentenceLike: false }\n for (const match of text.matchAll(new RegExp(STEP_LABEL, 'gu'))) {\n const digits = match[1] ?? ''\n const mark = match[2] ?? ''\n const delimiter = mark.startsWith(' ') ? '-' : mark\n const end = match.index + match[0].length\n const span = { start: end - digits.length, end }\n const start = runStartAt(text, match.index)\n const headingEnds = endsSentence(text, end + mark.length)\n const continues = (run: Run) =>\n run.next >= 2 &&\n digits === String(run.next) &&\n (delimiter === run.delimiter || start !== undefined)\n if (digits === '1' && start === 'at-once') {\n open.next = 2\n open.delimiter = delimiter\n blank(chars, span)\n held.next = 0\n held.pending = []\n } else if (digits === '1' && start === 'pending') {\n held.next = 2\n held.delimiter = delimiter\n held.pending = [span]\n held.sentenceLike = headingEnds\n } else if (continues(open)) {\n blank(chars, span)\n open.next += 1\n open.delimiter = delimiter\n } else if (continues(held)) {\n held.next += 1\n if (held.pending.length === 1 && held.sentenceLike && headingEnds) {\n held.pending.push(span)\n continue\n }\n for (const waiting of held.pending) blank(chars, waiting)\n blank(chars, span)\n open.next = held.next\n open.delimiter = delimiter\n held.next = 0\n held.pending = []\n }\n }\n}\n\n// 2026-10-12 (440-07, CR-01): a list counts from 1 at a line, sentence or colon start, and each\n// next number with the same delimiter continues it.\n// 2026-10-12 (440-11, WR-08): a run starting after a colon or a sentence end waits for its 2, and\n// two numbers that each end a sentence wait for a 3.\n// 2026-10-12 (440-13, WR-11): the open run and the held candidate are kept apart, so a held 1 inside an item never takes over its list.\n// 2026-10-12 (440-13, WR-10): a held 1) or (1) gets the sentence guard too.\n// 2026-10-12 (440-15, WR-12): a number right after a month name is that date's day, never a list marker.\n// 2026-10-12 (440-16, round-4 regression): a skipped day at the held start or next clears it.\nfunction blankListMarkers(text: string, chars: string[]): void {\n const open: Run = { next: 0, delimiter: '', pending: [], sentenceLike: false }\n const held: Run = { next: 0, delimiter: '', pending: [], sentenceLike: false }\n let index = 0\n while (index < text.length) {\n const tokenStarts = index === 0 || isSpace(text[index - 1])\n const opens = text[index] === '('\n const digitsStart = opens ? index + 1 : index\n let end = digitsStart\n while (tokenStarts && isDigit(text[end])) end += 1\n if (end === digitsStart) {\n index += 1\n continue\n }\n const closer = text[end]\n let delimiter: string | undefined\n if (opens) delimiter = closer === ')' ? '()' : undefined\n else if (closer === '.' || closer === ')') delimiter = closer\n const tokenEnd = end + 1\n if (delimiter === undefined || !isSpace(text[tokenEnd])) {\n index = end\n continue\n }\n const digits = text.slice(digitsStart, end)\n const span = { start: index, end: tokenEnd }\n const start = digits === '1' ? runStartAt(text, index) : undefined\n index = tokenEnd\n if (!opens && MONTH_BEFORE.test(text.slice(Math.max(0, span.start - 12), span.start))) {\n const heldNext =\n held.next >= 2 && delimiter === held.delimiter && digits === String(held.next)\n if (start === 'pending' || heldNext) {\n held.next = 0\n held.delimiter = ''\n held.pending = []\n }\n continue\n }\n if (start === 'at-once') {\n open.next = 2\n open.delimiter = delimiter\n blank(chars, span)\n held.next = 0\n held.delimiter = ''\n held.pending = []\n } else if (start === 'pending') {\n held.next = 2\n held.delimiter = delimiter\n held.pending = [span]\n held.sentenceLike = endsSentence(text, tokenEnd)\n } else if (delimiter === open.delimiter && digits === String(open.next)) {\n blank(chars, span)\n open.next += 1\n } else if (delimiter === held.delimiter && digits === String(held.next)) {\n held.next += 1\n if (held.pending.length === 1 && held.sentenceLike && endsSentence(text, tokenEnd)) {\n held.pending.push(span)\n continue\n }\n for (const waiting of held.pending) blank(chars, waiting)\n blank(chars, span)\n open.next = held.next\n open.delimiter = delimiter\n held.next = 0\n held.delimiter = ''\n held.pending = []\n }\n }\n}\n\nfunction unquotedValues(segment: string): string[] {\n const found: { readonly at: number; readonly value: string }[] = []\n let text = segment\n .replaceAll('\\n', ' ')\n .split(' ')\n .map((chunk) => (isAddress(chunk) ? ' '.repeat(chunk.length) : chunk))\n .join(' ')\n\n const dates = [...text.matchAll(new RegExp(MONTH_NAME_DATE, 'gu'))]\n for (const match of dates) found.push({ at: match.index, value: match[0] })\n const pieces: string[] = []\n let cursor = 0\n for (const match of dates) {\n pieces.push(text.slice(cursor, match.index), ' '.repeat(match[0].length))\n cursor = match.index + match[0].length\n }\n pieces.push(text.slice(cursor))\n text = pieces.join('')\n\n let index = 0\n while (index < text.length) {\n if (!isDigit(text[index])) {\n index += 1\n continue\n }\n let start = index\n if (text[start - 1] === '-' && (start === 1 || ' ('.includes(text[start - 2] ?? '-'))) {\n start -= 1\n } else if (start > 0 && CURRENCY_SYMBOLS.includes(text[start - 1] ?? '-')) {\n start -= 1\n }\n let end = index\n while (isDigit(text[end])) end += 1\n while (isSeparator(text[end]) && isDigit(text[end + 1])) {\n end += 1\n while (isDigit(text[end])) end += 1\n }\n if (text[end] === '%') end += 1\n\n const startHolds =\n !letterOrNumberBefore(text, start) &&\n !(isSeparator(text[start - 1]) && isDigit(text[start - 2]))\n const endHolds =\n !letterOrNumberAt(text, end) && !(isSeparator(text[end]) && isDigit(text[end + 1]))\n if (startHolds && endHolds) found.push({ at: start, value: text.slice(start, end) })\n index = end\n }\n\n return found.sort((left, right) => left.at - right.at).map((entry) => entry.value)\n}\n\nexport function extractStatedValues(request: string): readonly string[] {\n const text = request.normalize('NFC').replace(/\\s+/g, collapsedSpace)\n const parts: Part[] = []\n // An opener with no closer has none at any later index either, so its kind stops searching.\n const unclosed = new Set<QuoteKind>()\n\n let segmentStart = 0\n let index = 0\n while (index < text.length) {\n const kind = openerAt(text, index)\n if (kind !== undefined && !unclosed.has(kind)) {\n const close = closerOf(text, kind, index + 1)\n if (close === -1) {\n unclosed.add(kind)\n } else if (kind === 'single' && close === index + 2 && text[index + 1] === 'n') {\n // 2026-10-12 (440-08, WR-01): `rock 'n' roll` is text, not a quoted `n`.\n } else {\n parts.push({ start: segmentStart, end: index })\n parts.push({ start: index, end: close + 1, quoted: tidy(text.slice(index + 1, close)) })\n index = close + 1\n segmentStart = index\n continue\n }\n }\n index += 1\n }\n parts.push({ start: segmentStart, end: text.length })\n\n // 2026-10-12 (440-11, WR-08): runs are read over the whole request with quoted values masked, so\n // a list is confirmed across a quoted value and no marker is read inside one.\n const masked = parts\n .map(({ start, end, quoted }) =>\n quoted === undefined ? text.slice(start, end) : QUOTE_MASK.repeat(end - start),\n )\n .join('')\n const chars = masked.split('')\n blankStepLabels(masked, chars)\n blankListMarkers(chars.join(''), chars)\n const blanked = chars.join('')\n\n const values: string[] = []\n const seen = new Set<string>()\n const add = (value: string) => {\n if (value === '' || seen.has(value)) return\n seen.add(value)\n values.push(value)\n }\n for (const { start, end, quoted } of parts) {\n if (quoted !== undefined) add(quoted)\n else for (const value of unquotedValues(blanked.slice(start, end))) add(value)\n }\n return values\n}\n\nfunction startEdgeHolds(step: string, at: number, value: string): boolean {\n if (!LEADING_LETTER_OR_NUMBER.test(value)) return true\n if (letterOrNumberBefore(step, at)) return false\n return !(isDigit(value[0]) && isSeparator(step[at - 1]) && isDigit(step[at - 2]))\n}\n\nfunction endEdgeHolds(step: string, end: number, value: string): boolean {\n if (!TRAILING_LETTER_OR_NUMBER.test(value)) return true\n if (letterOrNumberAt(step, end)) return false\n return !(isDigit(value.at(-1)) && isSeparator(step[end]) && isDigit(step[end + 1]))\n}\n\nfunction carries(step: string, value: string): boolean {\n let from = 0\n while (from <= step.length) {\n const at = step.indexOf(value, from)\n if (at === -1) return false\n if (startEdgeHolds(step, at, value) && endEdgeHolds(step, at + value.length, value)) return true\n from = at + 1\n }\n return false\n}\n\nexport function missingStatedValues(\n values: readonly string[],\n steps: readonly string[],\n): readonly string[] {\n const tidiedSteps = steps.map(tidy)\n return values.filter((value) => {\n const wanted = tidy(value)\n return !tidiedSteps.some((step) => carries(step, wanted))\n })\n}\n\nexport function statedValuesMissingReason(missing: readonly string[]): string {\n const listed = missing.map((value) => JSON.stringify(value)).join(', ')\n return `the request's stated values are missing: ${listed}`\n}\n","// Bounded repair, fenced on both sides of the passing prefix (Phase 394, D-09/D-10 · WTST-04).\n//\n// WHAT THIS FILE IS FOR. The router (`router.ts`) has already decided that a failing draft is the\n// DRAFT's problem rather than the application's. This file bounds what may be done about it: how\n// many attempts, what a patch is allowed to touch, and what has to still be true afterwards.\n// Nothing here re-asks the routing question, and nothing here derives a disposition — both are\n// answered in exactly one place each, and a second reading of either is the failure mode this\n// phase's whole arc is built to prevent.\n//\n// THE PASSING PREFIX IS PROTECTED TWICE, AND THE TWO HALVES CATCH DIFFERENT THINGS (D-09).\n//\n// STATIC `fencePatchAgainstPassingPrefix` reads every RFC-6902 path in the set and refuses the\n// WHOLE set if any of them addresses a step position inside the prefix. It runs before\n// anything executes, so a patch that names a protected step never costs a child process\n// against the user's application. The refusal is a VALUE, and the caller counts it\n// against K.\n// DYNAMIC After the probe run, the prefix steps are read back out of the run's own evidence. A\n// patch may name only unprotected steps and still break a protected one — a fill that\n// changes what a later page renders, a removed wait that makes an earlier assertion\n// race — and no amount of path inspection can see that. Only the run can.\n//\n// A patch inspection alone proves the fence reads paths. It does not prove the prefix survives,\n// which is what D-09 is actually about, and a plan shipping only the static half would have\n// measured the smaller claim and reported the larger one.\n//\n// A FENCED PATCH IS NOT A FAILURE MODE. A legitimate early-step fix that gets refused simply exits\n// repair, and the draft goes on to be a proposal or a finding a human looks at. That is the safe,\n// recoverable direction: the alternative — letting a repair rewrite a step that already passed —\n// is how a loop quietly turns a test that was verifying something into a test that is verifying\n// whatever the application happens to do now.\n//\n// THIS FILE CANNOT REACH THE APPLICATION'S OWN BRANCH. `repairDraft` takes a `RepairRoute`, and\n// `RepairRoute` and `StopRoute` are mutually non-assignable by construction (each carries a\n// required field the other does not have). So wiring the app-broken branch into repair is a\n// COMPILE error rather than a behaviour a corpus has to notice afterwards — T-394-22's mitigation\n// expressed as a type, pinned by the `@ts-expect-error` cell in `router.test-d.ts` and by the\n// second cell of the phase's mutation driver until that driver was removed.\n//\n// WHY THE PATCH APPLIER ARRIVES AS A PORT VERB RATHER THAN AS AN IMPORT. The RFC-6902 applier is\n// `applyPatchSetToTestDoc` in `core`, and this package's declared dependencies are `runner`,\n// `safety`, `schema`, `ai` and `zod` — an edge to `core` is a `validate:arch` violation with no\n// legal repair (the FUNC-02 firewall, and the same reason `stageDraft` lives at the host). So the\n// shelf carries `applyPatches`, the host binds it over that one applier, and the \"one patch\n// contract, two consumers\" property holds through the binding rather than through an import.\n\nimport {\n RUN_EVIDENCE_CHANNELS,\n TestEditPatchSetSchema,\n parseJsonPointer,\n} from '@vostride/agent-qa-schema'\nimport type {\n CompletedRunHandoff,\n DraftReceipt,\n DraftRef,\n PerTestOutcome,\n StepEvidence,\n TestEditPatchSet,\n} from '@vostride/agent-qa-schema'\n\n// `loop.ts` imports this module for `repairDraft`; both names are only touched inside a call.\nimport { DraftSecretMarkerRefusedError, refuseLiteralSecretMarkers } from './loop.js'\nimport type { DraftRunPortLike, DraftShelfPortLike, ParsedDraftLike } from './ports.js'\nimport type { RepairRoute } from './router.js'\nimport { missingStatedValues, statedValuesMissingReason } from './stated-values.js'\nimport { buildTieredPrompt } from '../prompt/tiered-prompt-builder.js'\n\n/**\n * K: how many repair iterations one draft gets. PINNED, never config (386 D-15).\n *\n * RETUNE NOTE. Raising this multiplies the fan-out preview LINEARLY — the bound a user approves at\n * dispatch is initial N + K probes + final N, so K=5 turns a 7-run preview into a 9-run one for\n * every draft, whether or not the extra iterations ever help. That makes a retune a measurement\n * rather than a preference. Before moving it, report on the FROZEN corpus: (a) how many additional\n * drafts reach a passing probe at each K between here and the proposed value — if the second and\n * third iterations rescue nothing, a fourth will not either; (b) the wall-clock cost per\n * additional keep, priced at the local-form run time (~22s per probe) times the drafts that spend\n * the extra iterations WITHOUT being rescued, which is the population that pays for the ones that\n * are; and (c) the token cost per additional keep, since every iteration is one more model call\n * carrying a full trace. A retune that only argues from intuition — \"three feels low\" — is exactly\n * what this comment exists to prevent. Three is the same order as the spec's own 3-5 suggestion\n * and one more than the single in-attempt round-trip `AUTHOR_REPAIR_CAP` already ships with.\n */\nexport const REPAIR_ITERATION_CAP = 3\n\n/**\n * The `agent_context` every repair call carries into the ONE tiered prompt builder (389 D-04).\n *\n * Pinned rather than computed, on `AUTHORING_COMPILE_AGENT_CONTEXT`'s reasoning: it lands in the\n * stable tier, which is the byte prefix a provider's prompt cache keys on, so a per-invocation\n * value would defeat the caching the tier law exists to enable. It names the SAME op as the\n * compile call because a repair is a stage of that op rather than an op of its own.\n */\nexport const REPAIR_AGENT_CONTEXT =\n 'authoring.draft.write — repair a draft that failed for a test reason'\n\n/**\n * The steps that already worked, and the run that says so.\n *\n * PREFIX IDENTITY, SPELLED ONCE (D-09): step POSITIONS in the BEST PRIOR RUN. `length` is the\n * count of leading steps that passed, so the protected set is `[0, length)` — a contiguous prefix\n * and not the set of every step that is not currently failing. The difference is load-bearing: a\n * step AFTER the failure never ran, so nobody has seen it pass, and protecting it would fence off\n * exactly the region a repair legitimately needs to work in.\n */\nexport interface PassingPrefix {\n /** The run this prefix was read out of — carried so a refusal can name its own evidence. */\n readonly runId: string\n /** Steps `[0, length)` passed. Zero means nothing is protected. */\n readonly length: number\n}\n\n/**\n * A patch named a step the prefix protects. A VALUE, never thrown.\n *\n * Returning it rather than raising is what lets the caller count the refusal against K without a\n * `try` around the one call in the loop body that is supposed to be able to say no — and a fenced\n * patch MUST consume an iteration, or a model that emits nothing but fenced patches never\n * terminates (T-394-23).\n */\nexport class PassingPrefixViolationError extends Error {\n constructor(\n readonly path: string,\n readonly stepIndex: number,\n readonly prefix: PassingPrefix,\n ) {\n super(\n `repair: the patch path ${path} addresses step ${stepIndex}, which is inside the `\n + `passing prefix of ${prefix.length} step(s) established by run ${prefix.runId}; `\n + 'the whole patch set is refused before anything runs',\n )\n this.name = 'PassingPrefixViolationError'\n }\n}\n\n/**\n * The probe showed a step that used to pass now failing. The dynamic half's refusal.\n *\n * Distinct from the static one by NAME rather than by a flag, because the two are evidence of\n * different things: a static violation says the model asked to touch a protected step, and this\n * says it broke one WITHOUT asking. The second is the more interesting signal and would be lost\n * inside a shared class.\n *\n * ITS FOUR FIELDS ARE ONE COORDINATE, AND THEY NAME THE PROBED MEMBER (CR-01). A run record is\n * addressed by (runId, filePath, testName, stepIndex), so the run id alone is half an address —\n * and the half a reader would otherwise supply from the PRE-repair draft names a file this probe\n * never opened, because every applied patch set re-stages the candidate under its new digest. All\n * four are minted by this package from the candidate it probed; none is model text.\n */\nexport class PassingPrefixRegressedError extends Error {\n constructor(\n readonly stepIndex: number,\n readonly runId: string,\n readonly filePath: string,\n readonly testName: string,\n ) {\n super(\n `repair: probe run ${runId} shows step ${stepIndex} failing, and that step passed in the `\n + 'best prior run; the candidate is discarded and repair ends',\n )\n this.name = 'PassingPrefixRegressedError'\n }\n}\n\n/**\n * K iterations were spent and none produced a passing probe.\n *\n * Carries the count and the LAST refusal so a caller can distinguish two very different reports: we\n * tried K times and the model kept missing, versus every patch it proposed was fenced. A bare\n * boolean collapses them, and they call for opposite things from the person reading the result.\n */\nexport class RepairExhaustedError extends Error {\n constructor(\n readonly iterations: number,\n readonly lastRefusal: string,\n ) {\n super(\n `repair: ${iterations} iteration(s) produced no passing probe; the last one ended with: `\n + lastRefusal,\n )\n this.name = 'RepairExhaustedError'\n }\n}\n\n/** Why repair stopped without a repaired draft. Two named reasons, never a bare `false`. */\nexport type RepairAbandonment =\n | { readonly kind: 'exhausted'; readonly error: RepairExhaustedError }\n | { readonly kind: 'prefix-regressed'; readonly error: PassingPrefixRegressedError }\n\n/**\n * What one repair sequence produced.\n *\n * `iterations` is on BOTH arms because the fan-out actually consumed is what the receipt and the\n * D-03 preview are compared against; reporting it only on the failing arm would make a successful\n * repair the one case whose cost nobody can state.\n */\nexport type RepairOutcome =\n | {\n readonly kind: 'repaired'\n readonly draft: ParsedDraftLike\n readonly receipt: DraftReceipt\n readonly iterations: number\n readonly probeRunIds: readonly string[]\n }\n | {\n readonly kind: 'abandoned'\n readonly abandonment: RepairAbandonment\n readonly iterations: number\n readonly probeRunIds: readonly string[]\n }\n\n/**\n * What repair needs from its host.\n *\n * `handoff` is the BEST PRIOR RUN — the run the receipt's gates judged — and it is where both the\n * prefix and the repair prompt's evidence come from. It is a parameter rather than something this\n * module fetches, on the router's own posture: choosing among an evaluation's several runs is the\n * stage-5 wiring's job, and a module that picked one itself would be a second answer to a question\n * the wiring already has to answer.\n */\nexport interface RepairDeps {\n readonly draft: ParsedDraftLike\n readonly handoff: CompletedRunHandoff\n readonly shelf: DraftShelfPortLike\n readonly runs: DraftRunPortLike\n /**\n * The session the invocation was entered with, carried to the final stability gate (394-17).\n *\n * Handed in rather than re-derived, and ABSENT when the invocation had none — the caller reads\n * it off the receipt stage 4 already minted, so there is one source for the whole invocation.\n */\n readonly sessionRef?: string\n /**\n * The suite the draft proposes to JOIN, carried to the final stability gate (394-19, D-14).\n *\n * Handed in rather than re-derived for `sessionRef`'s reason exactly: the repaired candidate is\n * the SAME draft with patched steps, so it joins the same suite, and a second derivation here\n * would be a second answer to a question the invocation already answered.\n */\n readonly targetSuitePath?: string\n // 2026-10-12 (440-05, D-07): the request's stated values, which no repair patch may lose.\n readonly statedValues: readonly string[]\n}\n\n// ---- the prefix ------------------------------------------------------------------------------\n\nfunction draftMember(\n draftRef: DraftRef | ParsedDraftLike,\n handoff: CompletedRunHandoff | undefined,\n): PerTestOutcome | undefined {\n return handoff?.tests.find(\n (member) => member.filePath === draftRef.filePath && member.testName === draftRef.testName,\n )\n}\n\nfunction stepFailed(step: StepEvidence): boolean {\n return step.verifierVerdict.pass === false\n}\n\n/**\n * The leading contiguous run of steps that passed, read out of the best prior run.\n *\n * A run with no member for this draft yields a prefix of zero, which protects nothing — the honest\n * answer, since a prefix asserted with no evidence behind it would fence a repair out of a region\n * nobody has ever seen work.\n */\nexport function derivePassingPrefix(\n draftRef: DraftRef | ParsedDraftLike,\n handoff: CompletedRunHandoff | undefined,\n): PassingPrefix {\n const runId = handoff?.runId ?? ''\n const member = draftMember(draftRef, handoff)\n if (member === undefined) return { runId, length: 0 }\n\n let length = 0\n for (const step of member.steps) {\n if (stepFailed(step)) break\n length += 1\n }\n return { runId, length }\n}\n\n/**\n * Which step position a pointer addresses, if any.\n *\n * `'all'` is not \"no step\" — it is EVERY step, and it is what the whole-document pointer and the\n * bare `/steps` pointer address. Both are treated as reaching into the prefix, because a patch\n * that replaces the step sequence wholesale reaches the protected part of it too.\n */\nfunction stepPositionAddressedBy(path: string): number | 'all' | null {\n const segments = parseJsonPointer(path)\n if (segments.length === 0) return 'all'\n if (segments[0] !== 'steps') return null\n if (segments.length === 1) return 'all'\n const index = Number(segments[1])\n return Number.isInteger(index) && index >= 0 ? index : 'all'\n}\n\n/**\n * The static half of D-09. Pure, total, and it refuses the WHOLE set on the first violation.\n *\n * A DISTINCT CONTROL FROM `EDITABLE_POINTER_ROOTS`, and neither substitutes for the other. That\n * fence bounds which PART OF THE DOCUMENT any patch may touch at all — it keeps a model-authored\n * pointer away from `target`, `use` and `meta`, so a patch cannot silently change which\n * application a test drives. This one bounds which STEPS a repair may touch, inside the region the\n * first one already allows. A document-region check cannot express \"step 1 is off limits and step\n * 2 is not\", and a prefix check cannot express \"the credentials block is off limits to everyone\".\n *\n * An `add` counts as addressing the position it names because it SHIFTS every later step: an\n * insert at index 0 renumbers the whole prefix, which is a change to those steps whether or not\n * any of their text moves.\n */\nexport function fencePatchAgainstPassingPrefix(\n patchSet: TestEditPatchSet,\n prefix: PassingPrefix,\n): PassingPrefixViolationError | null {\n for (const op of patchSet.patches) {\n const position = stepPositionAddressedBy(op.path)\n if (position === null) continue\n if (position === 'all') {\n if (prefix.length > 0) return new PassingPrefixViolationError(op.path, 0, prefix)\n continue\n }\n if (position < prefix.length) {\n return new PassingPrefixViolationError(op.path, position, prefix)\n }\n }\n return null\n}\n\n/**\n * A repair patch tried to change what the test IS. A VALUE, never thrown (WR-01).\n *\n * Returned rather than raised for {@link PassingPrefixViolationError}'s reason exactly: the caller\n * counts the refusal against K, so a model that emits nothing but renames still terminates.\n */\nexport class RepairIdentityViolationError extends Error {\n constructor(readonly path: string) {\n super(\n `repair: the patch path ${path} changes the test's identity rather than its mechanics; `\n + 'a renamed test is a different test, so the whole patch set is refused before anything runs',\n )\n this.name = 'RepairIdentityViolationError'\n }\n}\n\n/**\n * THE IDENTITY FENCE: no repair patch may rename the test. Pure, total, refuses the WHOLE set.\n *\n * WHY REPAIR CANNOT RENAME. The loop derives the suite an accepted draft would JOIN exactly once,\n * from the PRE-repair draft (`loop.ts`'s `targetSuitePath`), and the finished proposal recomputes\n * that same target from the REPAIRED ref through `testDraftProposal`. Both readings go through\n * `authoredSuiteTargetPath(filePath, testName)`, whose answer is the suite DIRECTORY plus a slug of\n * the NAME: the shelf filename is the segment it drops, which is exactly why re-staging the patched\n * draft under a new digest — which every applied set does — moves the path without moving the\n * target. The NAME is the input the answer turns on, so a rename in between is the one thing that\n * makes the suite the stability gate consulted and the suite an accept would write disagree — the\n * disagreement the single derivation is documented to prevent. Repair's grant is fixing MECHANICS\n * under anchors that forbid changing what the test claims, and the name is the loudest of those\n * claims.\n *\n * A THIRD CONTROL, AND NONE OF THE THREE SUBSTITUTES FOR ANOTHER. `EDITABLE_POINTER_ROOTS` bounds\n * which part of the DOCUMENT any patch may touch, and it admits `name` deliberately — a user asking\n * `authoring.draft.edit` for a rename is asking for something legitimate (D-21), and narrowing that\n * shared control would take the power away from the caller that is entitled to it.\n * `fencePatchAgainstPassingPrefix` bounds which STEPS a repair may touch and cannot express a rule\n * about a root that addresses no step. This one bounds what the REPAIR LANE may do, which is why it\n * lives beside that fence's call site rather than inside it.\n *\n * IT READS THE POINTER THROUGH `parseJsonPointer`, never by string prefix: `/named` starts with\n * `/name` as text and addresses a different root, and `~1` / `~0` escapes mean the decoded first\n * token is the only thing that says what a pointer addresses. One decoder, shared with the position\n * check above and with the applier in `core`.\n */\nexport function fencePatchAgainstDraftIdentity(\n patchSet: TestEditPatchSet,\n): RepairIdentityViolationError | null {\n for (const op of patchSet.patches) {\n if (parseJsonPointer(op.path)[0] === 'name') {\n return new RepairIdentityViolationError(op.path)\n }\n }\n return null\n}\n\n// 2026-10-12 (440-05, D-07): returned rather than thrown, so the caller counts it against K.\nexport class RepairStatedValueViolationError extends Error {\n constructor(readonly missingValues: readonly string[]) {\n super(\n `repair: ${statedValuesMissingReason(missingValues)}; `\n + 'the whole patch set is refused before anything runs',\n )\n this.name = 'RepairStatedValueViolationError'\n }\n}\n\nexport function fencePatchAgainstStatedValues(\n draft: ParsedDraftLike,\n statedValues: readonly string[],\n): RepairStatedValueViolationError | null {\n const missing = missingStatedValues(statedValues, draft.steps)\n return missing.length > 0 ? new RepairStatedValueViolationError(missing) : null\n}\n\n/**\n * The dynamic half of D-09: a prefix step that used to pass and now does not.\n *\n * An ABSENT prefix step is not a regression. A probe that stopped before reaching it recorded no\n * verdict about it, and \"we do not know\" is not the same answer as \"it broke\" — counting missing\n * evidence as a regression would end repair for an infrastructure hiccup, which is the direction\n * that costs a user a good test. It also cannot hide anything: a probe missing a prefix step\n * cannot have passed either, so the iteration is spent regardless.\n *\n * THE COORDINATE IS BUILT HERE BECAUSE THIS IS WHERE THE PROBED MEMBER IS IN HAND. `draft` is the\n * STAGED candidate the probe was started on, and `draftMember` above joined the run's member to it\n * on the same pair — so naming the pair costs nothing and no later reader has to guess which of the\n * invocation's several drafts the run executed.\n */\nfunction prefixRegression(\n draft: ParsedDraftLike,\n probe: CompletedRunHandoff | undefined,\n prefix: PassingPrefix,\n): PassingPrefixRegressedError | null {\n const member = draftMember(draft, probe);\n if (member === undefined || probe === undefined) return null\n for (const step of member.steps) {\n if (step.stepIndex < prefix.length && stepFailed(step)) {\n return new PassingPrefixRegressedError(\n step.stepIndex,\n probe.runId,\n draft.filePath,\n draft.testName,\n )\n }\n }\n return null\n}\n\n/** Member outcomes that are a pass. A heal is a pass (393-01 F3); a skip never ran. */\nconst PROBE_PASSING_OUTCOMES: readonly string[] = ['passed', 'healed']\n\nfunction probePassed(draft: ParsedDraftLike, probe: CompletedRunHandoff | undefined): boolean {\n const member = draftMember(draft, probe)\n if (member === undefined) return false\n return PROBE_PASSING_OUTCOMES.includes(member.outcome) && !member.steps.some(stepFailed)\n}\n\n// ---- the repair prompt -------------------------------------------------------------------------\n\n/**\n * The failure, in the run's OWN words plus coordinates into its durable records.\n *\n * The trace is rendered as text because a prompt is text; the a11y screen states are rendered as\n * CHANNEL COORDINATES rather than as inlined snapshots, in the same map-not-territory posture the\n * finding arm takes. A pasted element tree would be a second copy of a record the run already\n * holds, and a large one — the model gets what it needs to ask for the right edit, not the whole\n * screen.\n */\nfunction failureBlockBody(route: RepairRoute, member: PerTestOutcome | undefined): string {\n const lines: string[] = []\n lines.push(`mechanics signals: ${route.mechanics.map((signal) => signal.signal).join(', ')}`)\n if (route.failingStepIndex === null) {\n lines.push('the failure is recorded at the member level, with no step to point at')\n }\n for (const step of member?.steps ?? []) {\n const marker = step.stepIndex === route.failingStepIndex ? ' <- FAILED HERE' : ''\n lines.push(`step ${step.stepIndex}: ${step.stepText}${marker}`)\n lines.push(` verdict: ${step.verifierVerdict.pass ? 'pass' : 'fail'} — ${step.verifierVerdict.reasoning}`)\n if (step.stepIndex !== route.failingStepIndex) continue\n step.subActions.forEach((subAction, subActionIndex) => {\n lines.push(` plan: ${subAction.plan}`)\n for (const channel of RUN_EVIDENCE_CHANNELS) {\n if (channel === 'step-trace') continue\n if (channel === 'state-after' && subAction.stateAfter === undefined) continue\n lines.push(` a11y ${channel}: step ${step.stepIndex} sub-action ${subActionIndex}`)\n }\n })\n }\n return lines.join('\\n')\n}\n\n/**\n * The repair prompt: two drafts, and the parameter names carry which is which.\n *\n * `originalDraft` is the draft the handoff's run EXECUTED, and the failure block joins on it. The\n * host mints a shelf path from the content digest, so `candidate` lives at a new `filePath` from\n * iteration 2 onward and joining the handoff on it returns no member at all — a block that\n * collapses to the mechanics-signals line with no arm and no counter. Two names rather than one\n * parameter and a comment, so the stability is visible in the signature.\n */\nfunction repairPromptFor(\n route: RepairRoute,\n originalDraft: ParsedDraftLike,\n candidate: ParsedDraftLike,\n handoff: CompletedRunHandoff,\n lastRefusal: string | undefined,\n): ReturnType<typeof buildTieredPrompt> {\n return buildTieredPrompt({\n agent_context: REPAIR_AGENT_CONTEXT,\n stable: [\n {\n title: 'Role',\n body: 'You repair the MECHANICS of an agent-qa test draft that could not be carried out. '\n + 'Emit ONE JSON object and nothing else: {\"thoughts\": string, \"patches\": [...]}, where '\n + 'each patch is an RFC-6902 add, remove or replace whose path is a JSON Pointer into '\n + 'the test document. You may not change what the test CLAIMS in order to make it pass, '\n + 'and you may not touch a step that already worked.',\n },\n ],\n context: [\n // The two titles carry the two numberings. An index in the block below addresses the run's\n // draft; an index in the block above addresses the candidate the next patch will be applied\n // to. They diverge as soon as a patch adds or removes a step.\n {\n title: 'The draft as it stands (numbered against the current candidate)',\n body: candidate.steps.map((step, index) => `${index}: ${step}`).join('\\n'),\n },\n {\n title: `What happened in run ${handoff.runId} (steps numbered against the draft that run executed)`,\n body: failureBlockBody(route, draftMember(originalDraft, handoff)),\n },\n ],\n volatile: lastRefusal === undefined\n ? []\n : [{ title: 'Why the previous attempt was not kept', body: lastRefusal }],\n })\n}\n\n/** Every probe is ONE gate-run over the draft file and nothing else. */\nfunction probeStartInput(draft: ParsedDraftLike): Parameters<DraftRunPortLike['start']>[0] {\n return { patterns: [draft.filePath], gateRun: true, excludedFromOutcomes: true }\n}\n\n// ---- the loop -----------------------------------------------------------------------------------\n\n/**\n * Repair a draft the router sent here, at most {@link REPAIR_ITERATION_CAP} times (D-09/D-10).\n *\n * ONE PROBE PER ITERATION, STABILISE AT THE END (D-10). Each iteration verifies with a single run,\n * because a full pinned-N stability gate per iteration would multiply the fan-out by N for\n * candidates that mostly do not survive. The pinned-N gate then runs ONCE, on the final candidate,\n * before any disposition exists — which is what makes a repaired draft keep-eligible at all: a\n * single-run evaluation is `unverified` at best by rule 1 of the disposition table, so a loop\n * that stopped at the probe could never produce a draft anyone is allowed to keep.\n *\n * PROBES MINT NO RECEIPT (T-394-24). A probe goes through the run port directly; only the final\n * gate goes through `verifyDraft`, which is the registered op that persists one. The receipt is\n * per DRAFT, and a funnel counting `1 + K` receipts for one draft would report a filter rate over\n * a denominator of attempts rather than of drafts.\n *\n * NO DISPOSITION IS DERIVED HERE. The final receipt carries the one `computeDraftDisposition`\n * produced, and this function neither reads nor recomputes it — 393 D-18 put that rule in one\n * place expressly so 394 would be structurally unable to grow a second reading of it.\n */\nexport async function repairDraft(route: RepairRoute, deps: RepairDeps): Promise<RepairOutcome> {\n const prefix = derivePassingPrefix(deps.draft, deps.handoff)\n const model = await deps.shelf.model()\n\n let candidate = deps.draft\n let lastRefusal = 'no iteration was taken'\n // 394-08 / WTST-08: the probe runs this sequence actually started, so the caller can report what\n // was CONSUMED rather than what was attempted. `iterations` cannot answer that question — a\n // fenced or unparsable emission spends an iteration and starts nothing — and an actual-runs\n // figure derived from the iteration count would over-report by exactly the refusals D-09 exists\n // to produce. Every element is appended at the ONE place a probe is started.\n const probeRunIds: string[] = []\n\n for (let iteration = 1; iteration <= REPAIR_ITERATION_CAP; iteration += 1) {\n const emitted = await model.generate(\n repairPromptFor(\n route,\n deps.draft,\n candidate,\n deps.handoff,\n iteration === 1 ? undefined : lastRefusal,\n ),\n )\n\n const parsed = parsePatchSet(emitted.text)\n if (typeof parsed === 'string') {\n // An unusable emission spends an iteration exactly as a fenced patch does. It is not retried\n // for free: a hidden retry would make the fan-out preview a number that does not describe\n // what happens, which is the same argument the compile stage's single model call rests on.\n lastRefusal = parsed\n continue\n }\n\n const violation = fencePatchAgainstPassingPrefix(parsed, prefix)\n if (violation !== null) {\n // THE ITERATION IS SPENT AND NOTHING RAN. Both halves matter: nothing ran, so a refused\n // patch costs no child process; and the iteration is spent, so a model emitting only fenced\n // patches still terminates.\n lastRefusal = violation.message\n continue\n }\n\n // WR-01, the same consequence one line up: a rename is refused, the iteration is spent, and no\n // child process runs. Beside the prefix fence rather than inside it — that function's contract\n // is step positions and its own cells pin it — and the two are asked in either order, since a\n // set violating both is refused whole by whichever answers first.\n const identityViolation = fencePatchAgainstDraftIdentity(parsed)\n if (identityViolation !== null) {\n lastRefusal = identityViolation.message\n continue\n }\n\n const staged = await deps.shelf.applyPatches(candidate, parsed)\n if (staged.kind === 'unparsable') {\n lastRefusal = `the patched document did not parse: ${staged.reason}`\n continue\n }\n\n // 2026-10-12 (440-05, D-07): the try is spent, nothing runs and `candidate` stays put.\n const valueViolation = fencePatchAgainstStatedValues(staged.draft, deps.statedValues)\n if (valueViolation !== null) {\n lastRefusal = valueViolation.message\n continue\n }\n\n // 2026-10-14 (441-03, D-10): a literal [secret:NAME] spends the try and starts no probe.\n try {\n refuseLiteralSecretMarkers(staged.draft)\n } catch (error) {\n if (!(error instanceof DraftSecretMarkerRefusedError)) throw error\n lastRefusal = error.message\n continue\n }\n\n const acknowledgement = await deps.runs.start(probeStartInput(staged.draft))\n probeRunIds.push(acknowledgement.runId)\n const probe = await deps.runs.get(acknowledgement.runId)\n\n const regression = prefixRegression(staged.draft, probe, prefix)\n if (regression !== null) {\n return {\n kind: 'abandoned',\n abandonment: { kind: 'prefix-regressed', error: regression },\n iterations: iteration,\n probeRunIds: [...probeRunIds],\n }\n }\n\n if (probePassed(staged.draft, probe)) {\n // The pinned-N gate, WITHOUT the draft-mode marker — the whole point of stabilising at the\n // end. `stabilityRunsRequested` reaching the disposition table as `DRAFT_STABILITY_RUNS_N`\n // rather than as 1 is what lets a repaired draft be anything other than `unverified`.\n const receipt = await deps.shelf.verifyDraft({\n draftPath: staged.draft.filePath,\n ...(deps.sessionRef === undefined ? {} : { sessionRef: deps.sessionRef }),\n ...(deps.targetSuitePath === undefined\n ? {}\n : { targetSuitePath: deps.targetSuitePath }),\n })\n return {\n kind: 'repaired',\n draft: staged.draft,\n receipt,\n iterations: iteration,\n probeRunIds: [...probeRunIds],\n }\n }\n\n candidate = staged.draft\n lastRefusal = `probe run ${acknowledgement.runId} did not pass`\n }\n\n return {\n kind: 'abandoned',\n abandonment: {\n kind: 'exhausted',\n error: new RepairExhaustedError(REPAIR_ITERATION_CAP, lastRefusal),\n },\n iterations: REPAIR_ITERATION_CAP,\n probeRunIds: [...probeRunIds],\n }\n}\n\n/**\n * The model's emission as a patch set, or the reason it is not one.\n *\n * A string return rather than a throw, because an unusable emission is an ordinary thing for a\n * model to produce and the loop's answer to it is to spend an iteration, not to fail the draft.\n */\nfunction parsePatchSet(text: string): TestEditPatchSet | string {\n let json: unknown\n try {\n json = JSON.parse(text)\n } catch (error) {\n return `the model did not emit JSON: ${error instanceof Error ? error.message : String(error)}`\n }\n const parsed = TestEditPatchSetSchema.safeParse(json)\n if (!parsed.success) {\n return `the model emitted JSON that is not a patch set: ${parsed.error.message}`\n }\n return parsed.data\n}\n\n// 394-08: `repairFanOutBound` used to live here, returning a bare number over its own `+`. It is\n// GONE, replaced by `authoringFanOutBound` in `loop.ts` over `computeFanOutBound` in `schema` —\n// which is the ONE arithmetic the dispatch confirm and the finished proposal both read. Two\n// additions of the same three terms is precisely how a preview begins promising a number the\n// report then contradicts, and a bare total could not have kept the two N terms apart.\n","// Stage 5's deterministic repair-vs-stop derivation (Phase 394 D-08 · WTST-04; 411 D-01).\n//\n// ONE function decides whether a failing draft is the DRAFT's problem or the APPLICATION's, and\n// this file is the only place that decision is made. The table below is the contract, not an\n// implementation detail; it is evaluated in this order, over the draft's OWN member inside one\n// run's evidence.\n//\n// 0. The run evidence holds no member with the draft's identity — or there is no run evidence\n// at all -> `no-run-evidence` -> REFUSED BY NAME. This is a broken precondition, not an\n// ambiguous signal: the router was not given the input it exists to read.\n// 1. The member did not fail — a terminal outcome of passed, healed or skipped with no step\n// verdict false -> `no-failure` -> REFUSED BY NAME. A healed pass is a pass (393-01 F3).\n// Nothing here is a routing question, and either arm would be a wrong answer wearing a\n// correct one's clothes.\n// 1b. SOME step carries a typed `limitStop` block -> `indefinitive-failure` -> STOP. The run ran\n// out of an action or planning-turn limit rather than into an answer, so it says nothing\n// about the application, and repairing it could iterate a dead control into a passing test\n// (436 D-14). Evaluated before rule 2, so a verdictSource on another step never makes it\n// definitive; a limit is never a mechanics signal.\n// 1c. SOME step the verifier left unproven (`stepOutcomeUnproven`: a condition unverified or\n// inconclusive, none not met) and carrying no mechanics signal -> `indefinitive-failure` ->\n// STOP. Nothing says the application failed, and repairing it would rewrite an unproven claim\n// into a passing one (439 D-07, after 436 D-14's limit stop). An infeasible step keeps its\n// termination as its primary reason (439 D-08) and routes by rule 3.\n// 2. SOME step is a CLEAN DEFINITIVE ASSERTION-FAIL — its verifier said no, a `verdictSource`\n// records which path produced that verdict, and that step carries no mechanics signal of\n// its own. Then:\n// 2a. no mechanics signal anywhere in the member\n// -> `clean-definitive-assertion-fail` -> STOP, unconditionally.\n// 2b. a mechanics signal somewhere else in the member\n// -> `mixed-evidence` -> STOP.\n// 3. A mechanics signal on any step, or a member outcome of timeout or cancelled\n// -> `execution-mechanics` -> REPAIR.\n// 4. Anything else -> `indefinitive-failure` -> STOP.\n//\n// WHY RULE 2 IS EVALUATED BEFORE RULE 3, AND WHY AMBIGUITY LANDS IN THE STOP ARM. Repairing a\n// clean assertion-fail can only mean rewriting what the test CLAIMS to match what the application\n// actually showed, which is oracle capture by construction — the draft class gate 4's corpus\n// exists to reject, manufactured by the very loop that is supposed to filter it. So D-08 says a\n// clean definitive assertion-fail routes to a stop ALWAYS, which is only true if the clean-fail\n// test is asked first; a mechanics-first table would let one unrelated timed-out step pull a\n// perfectly clean fail into the repair arm. The same asymmetry decides every remaining case: a\n// mis-filed test-wrong costs one human look and is undone by that look, while a mis-routed\n// application bug gets iterated into passing and is then indistinguishable from a test that\n// always worked. Only the second is unrecoverable, so every class this file cannot place with\n// confidence points at the stop arm.\n//\n// THE MECHANICS SCAN COVERS THE WHOLE MEMBER, NOT THE FAILING STEP. Rule 2's split between 2a and\n// 2b is what makes mixed evidence land in a stop, and narrowing the scan to the failing step\n// collapses that split: a termination on step 0 and a termination on the failing step would\n// classify identically. The frozen corpus carries that exact pair, differing in one integer.\n//\n// THE MODEL NEVER MAKES THIS DECISION. Both exported functions take a draft IDENTITY and one run\n// document. Neither takes a model, a prompt, or any string a model produced — `router.test-d.ts`\n// pins both parameter lists as exact tuples, so there is no argument for model output to arrive\n// through, and the identity is a lookup key rather than a decision input: every value that\n// decides is a field of the run's own `PerTestOutcome` or `StepEvidence`. The model writes nothing\n// this arm carries: the stop's payload is projected downstream from the route and from typed facts,\n// once the branch is already chosen, and no prose field survives on it (411 D-05).\n//\n// THE STOP CARRIES REFS, NEVER PAYLOADS (391 D-18, map not territory). WTST-04 asks the stop arm\n// to name the exact trace and the a11y snapshot at the failure point; both already live on the\n// handoff, the snapshots as `SubActionEvidence.stateBefore` and `stateAfter`, so this arm carries\n// coordinates into the run's own durable records. That is also why the loop binds\n// `DraftRunPortLike.get` rather than reading `runs.get`'s projection: the per-step sub-action\n// evidence these coordinates address does not survive that projection.\n//\n// THIS FILE DOES NOT WIRE ITSELF IN. Plan 06 owns the stage-5 call site, together with the repair\n// arm's consumer, so the two land in one commit and the wiring is never half-connected. `loop.ts`\n// keeps its own `routeAfterVerify`, which answers a DIFFERENT question — which outcome a\n// disposition implies — and the derivation here is named for the question it answers so the two\n// can coexist until plan 06 makes one call the other.\n\nimport { stepOutcomeUnproven } from '@vostride/agent-qa-schema'\nimport type {\n CompletedRunHandoff,\n DraftRef,\n MemberTestOutcome,\n PerTestOutcome,\n RunEvidenceRef,\n StepEvidence,\n VerdictSource,\n} from '@vostride/agent-qa-schema'\n\n/**\n * The closed vocabulary of what one member's failure evidence WAS.\n *\n * Six members, because refusing is a classification too: a router that could only answer `repair`\n * or `stop` would have to invent one of them for a run it should not have been handed, and the\n * two refusing classes are how the caller learns which of its own preconditions broke.\n */\nexport const ROUTER_SIGNAL_CLASSES = [\n 'execution-mechanics',\n 'clean-definitive-assertion-fail',\n 'mixed-evidence',\n 'indefinitive-failure',\n 'no-failure',\n 'no-run-evidence',\n] as const\n\nexport type RouterSignalClass = (typeof ROUTER_SIGNAL_CLASSES)[number]\n\n/** The single class the repair arm may carry. */\nexport type RouterRepairSignalClass = 'execution-mechanics'\n\n/** The three classes the stop arm may carry — one definitive, two ambiguous. */\nexport type RouterStopSignalClass =\n | 'clean-definitive-assertion-fail'\n | 'mixed-evidence'\n | 'indefinitive-failure'\n\n/**\n * The closed set of execution-mechanics signals, spelled once.\n *\n * The first two are read as PRESENCE exactly as gate 1 reads them: a recorded termination block is\n * a turn declaring the step could not be carried out, and narrowing that to today's single `kind`\n * literal would silently reclassify a later one as an assertion problem. The last two are\n * member-level and carried by the outcome rather than by any step, which is why a scan over\n * `StepEvidence` alone cannot see them.\n */\n// 2026-10-07 (436-06): 'cycle' and 'stagnation' left with the progress subsystem (D-14); their\n// blocks survive only in pre-change handoffs and are no longer read as mechanics.\nexport const ROUTER_MECHANICS_SIGNALS = [\n 'termination',\n 'planning-failure',\n 'member-timeout',\n 'member-cancelled',\n] as const\n\nexport type RouterMechanicsSignalName = (typeof ROUTER_MECHANICS_SIGNALS)[number]\n\n/** One mechanics signal and where it was found. `stepIndex: null` ⇒ carried by the member. */\nexport interface MechanicsSignal {\n readonly stepIndex: number | null\n readonly signal: RouterMechanicsSignalName\n}\n\n/** Where the failure was observed, in the run's own words. */\nexport interface RouterFailurePoint {\n readonly runId: string\n readonly stepIndex: number\n /** Pre-interpolation step text, the same rule every other authoring surface follows. */\n readonly stepText: string\n /** The verifier's own reasoning for saying no. */\n readonly reasoning: string\n /** Which path produced the verdict. Absent ⇒ the failure was not definitive. */\n readonly verdictSource?: VerdictSource\n}\n\n/**\n * The draft's mechanics need work; nothing here is a claim about the application.\n *\n * Carries `mechanics` and `failingStepIndex`, neither of which exists on {@link StopRoute}.\n * That is deliberate rather than incidental: two records differing only by a `kind` literal are\n * assignable in enough directions to make a type-level unreachability pin decorative, and SC-2's\n * claim is exactly an unreachability claim.\n */\nexport interface RepairRoute {\n readonly kind: 'repair'\n readonly signalClass: RouterRepairSignalClass\n /** Every signal found, with its location. Non-empty whenever this arm is produced. */\n readonly mechanics: readonly MechanicsSignal[]\n /** The first step whose verifier said no, or `null` for a member-level signal. */\n readonly failingStepIndex: number | null\n}\n\n/**\n * The application looks wrong, or the evidence does not say clearly enough to risk repairing — so\n * the loop STOPS here and reports what the run said.\n *\n * Carries `failurePoint` and `evidenceRefs`, neither of which exists on {@link RepairRoute}.\n * `failurePoint` is nullable because rule 4 admits a member that failed at the member level with\n * no step verdict to point at; `evidenceRefs` is not, because a stop a reader cannot trace is not\n * a report.\n *\n * 2026-09-02 (Phase 411): the proposal arm for a correctly-failing draft left with the Issue-slot\n * cleanup.\n */\nexport interface StopRoute {\n readonly kind: 'stop'\n readonly signalClass: RouterStopSignalClass\n readonly failurePoint: RouterFailurePoint | null\n readonly evidenceRefs: readonly RunEvidenceRef[]\n}\n\nexport type PostVerifyRoute = RepairRoute | StopRoute\n\n/**\n * The router was handed something that is not a routing question.\n *\n * Named rather than silently answered, on the loop's own precedent: an outcome invented for an\n * input the rules do not cover is a wrong answer at the exact seam where the cardinal error — a\n * real application bug iterated into a passing test — lives.\n */\nexport class AuthoringRouterUnroutableError extends Error {\n constructor(readonly signalClass: RouterSignalClass) {\n super(\n `authoring router: ${signalClass} is not a routable class; `\n + 'the router decides repair versus stop for a draft that FAILED, '\n + 'and this evidence poses no such question',\n )\n this.name = 'AuthoringRouterUnroutableError'\n }\n}\n\n/**\n * Which arm each class produces. THE ONE MAPPING SITE.\n *\n * A table rather than a chain of returns so that the routing decision has a single line per class\n * that a differential can edit and a reader can audit. The phase's mutation driver (since removed)\n * mutated exactly the clean-fail line here and required the corpus to red on the signature row by name.\n */\nconst ROUTE_ARM_BY_SIGNAL_CLASS = {\n 'execution-mechanics': 'repair',\n 'clean-definitive-assertion-fail': 'stop',\n 'mixed-evidence': 'stop',\n 'indefinitive-failure': 'stop',\n 'no-failure': 'refuse',\n 'no-run-evidence': 'refuse',\n} as const satisfies Record<RouterSignalClass, 'repair' | 'stop' | 'refuse'>\n\n/** Member outcomes that are not a failure. A heal is a pass; a skip never ran. */\nconst NON_FAILING_OUTCOMES: readonly MemberTestOutcome[] = ['passed', 'healed', 'skipped']\n\n/** Member outcomes that ARE an execution-mechanics fact rather than a verdict about the app. */\nconst MEMBER_MECHANICS: ReadonlyMap<MemberTestOutcome, RouterMechanicsSignalName> = new Map([\n ['timeout', 'member-timeout'],\n ['cancelled', 'member-cancelled'],\n])\n\n/** The mechanics signals recorded ON one step, in the declared vocabulary order. */\nfunction stepMechanics(step: StepEvidence): readonly RouterMechanicsSignalName[] {\n const found: RouterMechanicsSignalName[] = []\n if (step.termination !== undefined) found.push('termination')\n if (step.planningFailure !== undefined) found.push('planning-failure')\n return found\n}\n\n/** A step a per-step action or planning-turn limit stopped (436 D-12). Never a mechanics signal. */\nexport function stepLimitStopped(step: StepEvidence): boolean {\n return step.limitStop !== undefined\n}\n\n/** A step the verifier left unverified or inconclusive, with nothing not met (439 D-07). */\nexport function stepUnproven(step: StepEvidence): boolean {\n return stepOutcomeUnproven(step)\n}\n\n/** Rule 1c's step: unproven, and no mechanics signal of its own to route it to repair. */\nfunction unprovenWithoutMechanics(step: StepEvidence): boolean {\n return stepUnproven(step) && stepMechanics(step).length === 0\n}\n\n/** Every mechanics signal in the member: the whole step scan, then the member-level outcome. */\nfunction scanMechanics(member: PerTestOutcome): readonly MechanicsSignal[] {\n const signals: MechanicsSignal[] = []\n for (const step of member.steps) {\n for (const signal of stepMechanics(step)) signals.push({ stepIndex: step.stepIndex, signal })\n }\n const memberSignal = MEMBER_MECHANICS.get(member.outcome)\n if (memberSignal !== undefined) signals.push({ stepIndex: null, signal: memberSignal })\n return signals\n}\n\nfunction isFailedVerdict(step: StepEvidence): boolean {\n return step.verifierVerdict.pass === false\n}\n\n/**\n * A step whose failure is about WHAT THE TEST CLAIMS rather than how it acted.\n *\n * Three conjuncts, all required. The verifier said no; a `verdictSource` records which path\n * produced that verdict, so the answer is definitive rather than an unexplained negative; and the\n * step itself carries no mechanics signal, so the claim was actually evaluated against something.\n */\nfunction firstCleanDefinitiveFail(member: PerTestOutcome): StepEvidence | undefined {\n return member.steps.find(\n (step) =>\n isFailedVerdict(step)\n && step.verdictSource !== undefined\n && stepMechanics(step).length === 0\n && !stepLimitStopped(step),\n )\n}\n\n/** The draft's own member, keyed on the stable (filePath, testName) identity — never `testId`. */\nfunction memberFor(\n draftRef: DraftRef,\n handoff: CompletedRunHandoff | undefined,\n): PerTestOutcome | undefined {\n return handoff?.tests.find(\n (member) => member.filePath === draftRef.filePath && member.testName === draftRef.testName,\n )\n}\n\n/**\n * The ONE classification (the table above, in order). Pure and total over every input.\n *\n * The thin half of the scan, in the shipped `textSimilarity` idiom: this answers the class, and\n * the router below re-reads the same member for the evidence its arm has to carry. A caller that\n * wants only the class — a receipt, a counter, a log line — need not build a route to get it.\n */\nexport function classifyFailureEvidence(\n draftRef: DraftRef,\n handoff: CompletedRunHandoff | undefined,\n): RouterSignalClass {\n const member = memberFor(draftRef, handoff)\n if (member === undefined) return 'no-run-evidence'\n\n const failed = !NON_FAILING_OUTCOMES.includes(member.outcome) || member.steps.some(isFailedVerdict)\n if (!failed) return 'no-failure'\n if (member.steps.some(stepLimitStopped)) return 'indefinitive-failure'\n if (member.steps.some(unprovenWithoutMechanics)) return 'indefinitive-failure'\n\n const mechanics = scanMechanics(member)\n if (firstCleanDefinitiveFail(member) !== undefined) {\n return mechanics.length === 0 ? 'clean-definitive-assertion-fail' : 'mixed-evidence'\n }\n if (mechanics.length > 0) return 'execution-mechanics'\n return 'indefinitive-failure'\n}\n\n/** The coordinates addressing one step's trace and every a11y snapshot recorded under it. */\nfunction evidenceRefsFor(\n runId: string,\n member: PerTestOutcome,\n step: StepEvidence,\n): readonly RunEvidenceRef[] {\n const base = { runId, filePath: member.filePath, testName: member.testName, stepIndex: step.stepIndex }\n const refs: RunEvidenceRef[] = [{ ...base, channel: 'step-trace' }]\n step.subActions.forEach((subAction, subActionIndex) => {\n refs.push({ ...base, subActionIndex, channel: 'state-before' })\n if (subAction.stateAfter !== undefined) {\n refs.push({ ...base, subActionIndex, channel: 'state-after' })\n }\n })\n return refs\n}\n\n/**\n * THE stop arm's evidence, from ONE step of ONE member. One derivation, two callers.\n *\n * Both callers below build the same two fields from the same walk: `routeRepairOrStop`'s stop arm,\n * and {@link stopRouteForAbandonedRepair} for a repair that was abandoned. They are one function\n * rather than two similar blocks because the alternative was measured — the exhausted arm shipped\n * an empty literal (`failurePoint: null`, `evidenceRefs: []`) beside a routed handoff it never\n * read, and every cell over that arm passed (394-VERIFICATION, CR-02). A construction copied into\n * a second module drifts from this one the first time either side is edited.\n *\n * `undefined` in means the member has no step to point at, which is the ONLY case that yields a\n * null point and no refs — the nullability rule the stop arm has always documented.\n */\nfunction stopEvidenceFor(\n runId: string,\n member: PerTestOutcome,\n point: StepEvidence | undefined,\n): Pick<StopRoute, 'failurePoint' | 'evidenceRefs'> {\n if (point === undefined) return { failurePoint: null, evidenceRefs: [] }\n return {\n failurePoint: {\n runId,\n stepIndex: point.stepIndex,\n stepText: point.stepText,\n reasoning: point.verifierVerdict.reasoning,\n ...(point.verdictSource === undefined ? {} : { verdictSource: point.verdictSource }),\n },\n evidenceRefs: evidenceRefsFor(runId, member, point),\n }\n}\n\n/**\n * The stop arm for a repair the loop ABANDONED, over the run the router already read (CR-02).\n *\n * WHY IT LIVES HERE AND NOT AT THE CALL SITE. An exhausted or prefix-regressed repair produces the\n * same artifact class as a first-pass stop — `routeAfterVerify`'s own header says so — and that\n * class's evidence is derived in exactly one place. Building it in `loop.ts` would be a second\n * answer to \"which step does this stop point at\", assembled from the same fields, free to\n * disagree; building it from a literal is what shipped, and a durable stop with no failure point\n * and no refs is unauditable by construction (T-394-90).\n *\n * `signalClass` is `indefinitive-failure` and nothing else: the classification the run's own\n * evidence carried belonged to the REPAIR arm (`execution-mechanics`), and repair having failed is\n * a fact about the loop rather than a new reading of the run. A repair-prefixed class would be a\n * string outside {@link ROUTER_SIGNAL_CLASSES}, which is the WR-09 defect this file already closed.\n *\n * `failingStepIndex` is the repair route's own — the step the loop tried to fix — so the stop\n * points where the repair was aimed. `null` (a member-level signal) falls back to the first step\n * the verifier rejected, and a member with neither yields a null point rather than a fabricated one.\n */\nexport function stopRouteForAbandonedRepair(\n draftRef: DraftRef,\n handoff: CompletedRunHandoff,\n failingStepIndex: number | null,\n): StopRoute {\n const member = memberFor(draftRef, handoff)\n if (member === undefined) {\n // Unreachable through the loop — reaching a repair arm at all means this member was found —\n // and answered rather than thrown, because repair has already been spent by the time this is\n // called and a throw here would lose the abandonment the caller is filing.\n return {\n kind: 'stop',\n signalClass: 'indefinitive-failure',\n failurePoint: null,\n evidenceRefs: [],\n }\n }\n const named = failingStepIndex === null\n ? undefined\n : member.steps.find((step) => step.stepIndex === failingStepIndex)\n return {\n kind: 'stop',\n signalClass: 'indefinitive-failure',\n ...stopEvidenceFor(handoff.runId, member, named ?? member.steps.find(isFailedVerdict)),\n }\n}\n\n/**\n * The one deterministic repair-versus-stop derivation (D-08).\n *\n * Pure: it reads the run document and mutates nothing. Total over every classification the table\n * produces — the two non-routing classes refuse BY NAME rather than returning an arm, which is\n * the loop's own posture for a case a later plan owns.\n *\n * The caller supplies the handoff of the run whose evidence the receipt's gates judged; choosing\n * among an evaluation's several runs is the stage-5 wiring's job, and lands with plan 06.\n */\nexport function routeRepairOrStop(\n draftRef: DraftRef,\n handoff: CompletedRunHandoff | undefined,\n): PostVerifyRoute {\n const signalClass = classifyFailureEvidence(draftRef, handoff)\n const arm = ROUTE_ARM_BY_SIGNAL_CLASS[signalClass]\n if (arm === 'refuse') throw new AuthoringRouterUnroutableError(signalClass)\n\n const member = memberFor(draftRef, handoff)\n if (member === undefined || handoff === undefined) {\n throw new AuthoringRouterUnroutableError('no-run-evidence')\n }\n\n const failingStep = member.steps.find(isFailedVerdict)\n if (arm === 'repair') {\n return {\n kind: 'repair',\n signalClass: 'execution-mechanics',\n mechanics: scanMechanics(member),\n failingStepIndex: failingStep?.stepIndex ?? null,\n }\n }\n\n // The stop points at the step a limit stopped when there is one (that is why it stopped), then\n // at the step the verifier left unproven, then at the step whose CLAIM failed, and otherwise at\n // the first step the verifier rejected — never\n // at a step chosen because it carried a mechanics signal, which would name a symptom of the run\n // rather than the application behaviour.\n const point = member.steps.find(stepLimitStopped)\n ?? member.steps.find(unprovenWithoutMechanics)\n ?? firstCleanDefinitiveFail(member)\n ?? failingStep\n return {\n kind: 'stop',\n signalClass: signalClass as RouterStopSignalClass,\n ...stopEvidenceFor(handoff.runId, member, point),\n }\n}\n","// `authoring.draft.write` — the authoring loop as a catalogued capability (394, D-01).\n//\n// THE ONE PUBLIC ENTRY, AND THAT IS THE DESIGN. D-01 puts all six stages inside a single\n// registered op rather than registering a stage each, because the stage ORDER is an invariant and\n// a caller that could reach the stages independently could break it. 392 D-07 binds every registry\n// op into the chat planner's toolset 1:1, so a `authoring.draft.compile` beside a\n// `authoring.draft.verify` would be a planner that can verify a draft it never deduplicated, or\n// author one it never read a brief for — and \"dedup-before-author\" would degrade from a property\n// of the code into a hope about the plan the model happened to make. Everything below the surface\n// still crosses the function layer: the loop reaches `authoring.draft.verify` through\n// `invokeFunction`, so SC1's \"every stage is a gated function-layer call\" holds without the stages\n// being separately dispatchable.\n//\n// THE ID IS `authoring.draft.write`, three lowercase dot segments, no underscore — the spelling\n// `authoring-verify-draft.ts` reserved beside itself when it chose `authoring.draft.verify`. The\n// two shipped mechanisms that force it are unchanged and were re-measured for this op:\n// 1. `parity-coverage.test.ts` requires every registered id to match `^[a-z]+(?:\\.[a-z]+)+$`\n// off the registry. `authoring.draft.write` matches; `authoring.draft_write` does not.\n// 2. `chat/tool-names.ts` maps ids to provider-safe tool names by `.` ↔ `_` and REFUSES an id\n// that already carries `_`, because such a name has two pre-images under the inverse. Since\n// the planner binds every op, an underscore id would raise `ChatToolNameError` for the WHOLE\n// projection rather than merely looking unconventional (T-394-07).\n// `draft` is the subject and `write` is the verb, so the pair reads `authoring.draft.{write,\n// verify}` and 394's edit op joins as `authoring.draft.edit` (plan 09) with no renaming.\n//\n// NO SCOPES (2026-10-01, 432-23, D-12). This op once declared `test-write`, `run` and `read`, so a\n// caller holding only `run` + `read` could not reach a file write through a nested call (394-01\n// minted `test-write` for it). Every door can call every operation now, so there is nothing to\n// declare and nothing for a nested call to widen.\n//\n// THE MINTED CALLER IS ATTRIBUTION ONLY (T-394-05, re-spelled by 432-20/432-23). Stage 4 dispatches\n// `authoring.draft.verify` on a caller the composition mints with a surface and an origin; it\n// carries no grant, and the inner call reaches exactly what `authoring.draft.verify` itself does.\n//\n// INPUT REFUSAL IS THE FIRST HALF OF `invoke`, for the reason the evaluator states and one more:\n// `intent` is free text from an arbitrary caller that reaches an LLM and then becomes bytes on\n// disk (T-394-06). The schema refuses the shape; the shelf refuses what the model produced, by\n// parsing before it writes.\n\nimport {\n AuthoringDraftWriteInputSchema,\n AuthoringDraftWriteOutputSchema,\n FanOutReportSchema,\n renderFanOutReport,\n} from '@vostride/agent-qa-schema'\nimport type {\n AuthoringDraftWriteInput,\n AuthoringDraftWriteOutput,\n AuthoringStop,\n} from '@vostride/agent-qa-schema'\n\nimport { authoringFanOutBound, runAuthoringLoop } from '../../authoring/loop.js'\nimport type { AuthoringLoopOutcome } from '../../authoring/loop.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport const AUTHORING_DRAFT_WRITE_FUNCTION_ID = 'authoring.draft.write'\n\n/**\n * The `stopped` arm, projected onto the result's `stop` payload (411 D-05/D-06/D-08).\n *\n * THE OP PROJECTS; IT NEVER RE-DERIVES EVIDENCE. Every field here is copied from the route the\n * router derived or from the receipt's own LAST gate run — the same run stage 5 routed on and the\n * same one the attribution below borrows, so the verdict a caller reads and the evidence the\n * routing read are one answer rather than two. The abandonment's own error object is NOT read here\n * — its prose ends in the model's own bytes — and the payload has no prose field for model output\n * to arrive through at all.\n *\n * `String(verdictSource)` is the bridge the retired carrier used: the router's `VerdictSource` is\n * the run's own enum and the payload keeps the free-string posture, because the runner owns that\n * vocabulary and grows it.\n */\nexport function projectStop(\n outcome: Extract<AuthoringLoopOutcome, { kind: 'stopped' }>,\n): AuthoringStop {\n const last = outcome.receipt.gateRuns.at(-1)\n if (last === undefined) {\n throw new Error(\n 'authoring.draft.write: a stopped outcome names no gate run — stage 5 routes on the last '\n + 'gate run, so this cannot be a stopped outcome',\n )\n }\n const point = outcome.route.failurePoint\n return {\n runId: last.runId,\n memberOutcome: last.memberOutcome,\n signalClass: outcome.route.signalClass,\n failurePoint: point === null\n ? null\n : {\n stepIndex: point.stepIndex,\n stepText: point.stepText,\n reasoning: point.reasoning,\n ...(point.verdictSource === undefined\n ? {}\n : { verdictSource: String(point.verdictSource) }),\n },\n evidenceRefs: outcome.route.evidenceRefs,\n // ONE SPREAD, so the kind and the spend are present on exactly the same payloads (411 D-08).\n ...(outcome.abandonment === undefined\n ? {}\n : {\n repairAbandonment: outcome.abandonment.kind,\n repairIterations: outcome.abandonment.iterations,\n }),\n }\n}\n\nexport const authoringDraftWriteSpec: FunctionSpec<\n AuthoringDraftWriteInput,\n AuthoringDraftWriteOutput\n> = {\n id: AUTHORING_DRAFT_WRITE_FUNCTION_ID,\n summary: 'Author a test for an intent, verify it against the keep-gates, and return its receipt.',\n resultKind: 'unary',\n // The WRITE half, which is the half that makes this op mutating: a host with no model and no\n // shelf cannot author at all. The read half is bound with it or not at all — see the invoke's\n // second check, which refuses on either half by the same name.\n boundThrough: 'draftShelf',\n input: AuthoringDraftWriteInputSchema,\n output: AuthoringDraftWriteOutputSchema,\n // `mutating-shared`, AND THE CONTRAST WITH `authoring.draft.verify` IS THE POINT (394-08, D-03).\n //\n // The mechanics first: `recognized: true` with no `readOnly` puts the classifier's floor at\n // mutating-local, `declaredTier` raises it from there, and the name tokens (fn · authoring ·\n // draft · write) hit neither destructive lexicon — so the declared tier is what the gate sees.\n //\n // `authoring-verify-draft.ts` chose `mutating-local` and its argument was correct FOR IT: an\n // ask-tier op denies in every fail-closed context, and an evaluator that cannot verify a draft in\n // CI is a keep-filter that stops working exactly where it needs to run unattended. Verifying is\n // all cost and no consequence — gate-runs are `excludedFromOutcomes`, so they leave no trace a\n // colleague reads.\n //\n // THIS OP IS GENUINELY DIFFERENT, and it differs in the two ways that decide a tier. It SPENDS a\n // person's compute and model budget on their own machine — up to nine full child `agent-qa run`\n // processes against their application (D-10) — and since 432 D-06 the artifact it produces is\n // written straight into their suite.\n //\n // 2026-10-01 (432-19/432-23, 432 D-12/D-14/D-15): THE TIER NO LONGER ASKS. It was raised so a\n // dispatch confirm would show the fan-out before the loop started, and so a fail-closed context\n // (CI, the daemon) denied it with the gate's ways out (the session trust flag, a trust credential,\n // a standing approval). The gate, its confirm and those ways out are deleted: every door runs this\n // op without a prompt, and WTST-08's honest report on the verdict below is the control that\n // remains. One call starts a loop that runs to its end; there is no mid-loop approval state and\n // no approval token threaded through the stages.\n //\n // DO NOT HARMONISE THE TWO TIERS. They are different classifications because the ops differ;\n // the tier still says honestly which one shares more.\n risk: {\n name: `fn:${AUTHORING_DRAFT_WRITE_FUNCTION_ID}`,\n recognized: true,\n declaredTier: 'mutating-shared',\n },\n // 2026-10-02 (432-42, D-14/D-15): the per-invocation `disclose` method is deleted. It rendered the\n // fan-out preview for the dispatch confirm, which 432-19 deleted, and nothing called it since; the\n // fan-out report on the verdict below is what a caller reads.\n /**\n * This op's own outcome enum, folded into a clause verdict (2026-08-20, Phase 399.1 D-01/D-02),\n * carrying the invocation's FAN-OUT REPORT (394-14 · WTST-08 · D-18's one exception).\n *\n * `refused` IS THE MEASURED WITNESS. 399's live acceptance recorded this op returning its stage-2\n * dedup refusal while chat printed `executed authoring.draft.write completed`: the screen declined\n * to author, nothing was written, and the person was told it had been. The screen WORKED, so the\n * honest word is `refused` and not `failed` — the same reading D-02 minted the status for.\n *\n * THE OUTCOME CARRIES THE REFERENCE, because 394 D-04's requirement is refuse AND LINK: a person\n * told only \"duplicate\" has nothing to open, and `matchedRef` is precisely the string\n * `entities.resolve` takes. The refusal payload is optional on the contract, so an arm that says\n * `refused` without one still says `refused` — the status is the claim that must not be lost, and\n * a missing link degrades the sentence rather than the verdict.\n *\n * THE OTHER THREE ARMS RAN TO COMPLETION. `drafted`, `repaired` and `stopped` all end with a draft\n * and a receipt — a correctly-failing draft is a VERDICT about the application, not a failure of\n * this op — so each is `executed`, and the outcome names the test that was authored. A `stopped`\n * invocation therefore renders `stopped <testName> — <fan-out sentence>` under a status chat and\n * the parity walk already read: a spelling, never a shape (411 D-11).\n *\n * ---- the fan-out, migrated here from `turn-engine.ts` by 399.1-03 -----------------------------\n *\n * IT ARRIVES ON THE VERDICT AND NOT ON A RENDER FOLD, and the choice is load-bearing rather than\n * incidental. 394-14's second cell requires the sentence to reach the APPEND-ONLY LOG — \"the\n * return value is what one caller sees; the log is the triage report several surfaces render\" —\n * and the log carries `ClauseReceipt.outcome`, not the turn's answer. A `renderResult` fold would\n * have put this disclosure on the answer channel only, silently costing it the half that is\n * readable after the fact. `summariseOutcome` composed a RECEIPT LINE, so the seat it vacates is\n * this one; `explainAnswerLines` composed ANSWER TEXT, so its seat is `renderResult`. The two\n * hardcodes were never the same kind of thing.\n *\n * IT IS ADMITTED BY THE CHARTER RATHER THAN EXCEPTED FROM IT. D-18 says the receipt is a MAP, and\n * `FanOutReport` is counts, run REFERENCES and one boolean — no draft body, no receipt payload, no\n * step evidence. The written file and its receipt ride the op's `written` field, not this line.\n *\n * IT IS ONE FIELD ON ONE OP, AND NOW BY CONSTRUCTION. That used to be enforced by an id\n * comparison inside a shared function — a claim a later edit could widen by deleting one line. It\n * is a member of THIS spec now: no other op's line is touched, because no other op declares this.\n *\n * WHY THE DISCLOSURE IS THE WHOLE CONTROL. WTST-08's owner decision was preview plus honest\n * reporting with NO enforced budget, so the number a person is shown is all there is. The same\n * surface rendered the dispatch confirm they approved; a receipt omitting what was actually spent\n * would be the half that makes the other half checkable, missing. They agreed to nine runs and\n * had no way to learn eleven were taken.\n *\n * PARSED, NEVER CAST, AND THE PARSE CANNOT MOVE THE STATUS. `FanOutReportSchema` is `.strict()`,\n * so a malformed result cannot smuggle prose into a file several surfaces render; an unparsable\n * report costs the SENTENCE and never the verdict, which is `classify`'s fail-closed contract read\n * correctly — the disclosure degrades, the claim about what happened does not.\n *\n * THE SENTENCE IS `renderFanOutReport`'S AND NOTHING ELSE. A line composed here would be a second\n * prose form of one report, free to drift from the confirm's own wording the moment a phrase\n * moves — and mutation R of the phase's mutation driver (since removed) was the differential\n * that caught it.\n */\n classify(output): ClauseVerdict {\n const report = FanOutReportSchema.safeParse(output.fanOut)\n const spent = report.success ? ` — ${renderFanOutReport(report.data)}` : ''\n if (output.outcome === 'refused') {\n const stated = output.statedValueRefusal\n if (stated !== undefined) {\n const values = stated.missingValues.map((value) => JSON.stringify(value)).join(', ')\n return {\n status: 'refused',\n outcome: `stated-values-missing:${stated.stage} ${values}${spent}`,\n }\n }\n const matched = output.refusal?.matchedRef\n const named = matched === undefined ? 'duplicate' : `duplicate-of:${matched}`\n return { status: 'refused', outcome: `${named}${spent}` }\n }\n const authored = output.draftRef?.testName\n const named = authored === undefined ? output.outcome : `${output.outcome} ${authored}`\n // 432 D-06: the written file is part of the claim. A draft the writer refused or failed to\n // write is not reported as executed — the author asked for a test file and did not get one.\n const file = output.written?.file\n if (file?.kind === 'not-written' && file.reason !== 'rejected') {\n return {\n status: file.reason === 'write-failed' ? 'failed' : 'refused',\n outcome: `${named} — not written: ${file.reason}${spent}`,\n }\n }\n const wrote = file === undefined\n ? ''\n : file.kind === 'written' ? ` — wrote ${file.filePath}` : ' — not written: rejected'\n return { status: 'executed', outcome: `${named}${wrote}${spent}` }\n },\n async invoke(input, deps) {\n // `invokeFunction` already refused this composition on `draftShelf`, so reaching here with no\n // port means an in-layer caller holding the spec directly; the refusal is the same named error\n // either way (384, D-09).\n const shelf = deps.draftShelf\n const read = deps.authoringRead\n // BOTH halves, by the SAME name. `boundThrough` names one key, and a host missing the read\n // half would otherwise list this op `bound` and then serve an EMPTY brief — a draft compiled\n // against nothing this project knows, indistinguishable at the caller from one compiled\n // against everything it knows. That is the answer this check exists to make impossible.\n //\n // THE FILE HALF RIDES THE SHELF (432 D-06). The writer is `draftShelf.publish`, so a host that\n // can author is a host that can write what it authored — checked here, before any run is spent,\n // by the shelf's presence. 394-18's separate proposals port is no longer consulted: nothing is\n // filed for anybody to accept.\n if (shelf === undefined || read === undefined) {\n throw new FunctionNotBoundError(AUTHORING_DRAFT_WRITE_FUNCTION_ID)\n }\n\n // SCOPE IS RESOLVED HERE, ABOVE THE LOOP, AND NOWHERE ELSE (394-26, WINDOWS 110).\n //\n // The registry contract makes `scope` optional on the `runs.start` law — absent resolves from\n // the host — because a model cannot know this project's product keys and refuses the whole\n // call over a field it can only guess at. `AuthoringLoopInput.scope` stays REQUIRED: the loop\n // reads the brief at it and names it in the compile prompt, so it must be concrete by the\n // time the loop starts, and every read inside one invocation is then at one scope.\n //\n // A HOST WITH NO DERIVER REFUSES BY NAME. Not a default, and not the first configured\n // product: authoring against a guessed product writes a test for the wrong application, so\n // the missing binding is reported where the composition forgot it — the same named error the\n // three halves above use, checked only when the caller supplied nothing.\n const scope = input.scope ?? await (async () => {\n if (deps.authoringScope === undefined) {\n throw new FunctionNotBoundError(AUTHORING_DRAFT_WRITE_FUNCTION_ID)\n }\n return await deps.authoringScope.deriveDefault()\n })()\n\n const result = await runAuthoringLoop(\n {\n intent: input.intent,\n scope,\n ...(input.draftMode === undefined ? {} : { draftMode: input.draftMode }),\n // 394-17 / D-12: handed on exactly as supplied, and this op invents nothing. The session\n // is a fact about the SURFACE that dispatched the call — the chat engine stamps its own\n // id at the invoke boundary — so a default here would attribute a CLI draft to a session\n // that never asked for it.\n ...(input.sessionRef === undefined ? {} : { sessionRef: input.sessionRef }),\n },\n { read, shelf },\n )\n\n // Projected arm-agnostically, which is what lets plans 05-06 land a branch inside the loop and\n // reach this line unchanged. The two optional spreads carry a `drafted` invocation's draft and\n // receipt and are simply absent on a stage-2 refusal, which has neither.\n //\n // THE REFUSAL PAYLOAD IS READ OFF THE SCREENING, not off the outcome. The `refused` arm of\n // `AuthoringLoopOutcome` stays exactly the shape 394-02 declared — it is a discriminant, not a\n // carrier — and what a refusal has to NAME is a fact about the dedup screening that produced\n // it. Reading it here is what makes D-04's refuse-and-LINK reach a caller at all: a chat\n // surface told `refused` with no `refusal` could report that something matched but never say\n // what, and re-invoking is the only continuation this stateless design offers.\n //\n // THE FAN-OUT REPORT RIDES OUT (394-14 · WTST-08). The report is the recorded exception to the\n // output schema's no-payload rule and the argument is written there: it is counts and run refs\n // about the run budget, and WTST-08's owner decision made the honest report the second half of\n // the only control this op has. It is carried on EVERY arm the loop answers with a routing,\n // refusals included, because \"this invocation ran nothing\" is a number a caller is entitled to.\n const outcome = result.outcome\n const dedup = result.dedup\n\n // THE FINAL DRAFT IS ALREADY WRITTEN BY THE TIME THIS OP ANSWERS (432 D-06, superseding\n // 394-18's proposal filing). The loop wrote it — or, for a rejected final receipt, did not — and\n // the written-test receipt rides out on the `drafted` and `repaired` arms. Nothing is filed for a\n // person to accept, and the stopped and refused arms write nothing (411 D-10/D-12, D-04).\n return {\n outcome: outcome.kind,\n fanOut: result.fanOut,\n ...(outcome.draftRef === undefined ? {} : { draftRef: outcome.draftRef }),\n ...(outcome.receipt === undefined ? {} : { receipt: outcome.receipt }),\n ...(outcome.kind === 'stopped' ? { stop: projectStop(outcome) } : {}),\n ...(outcome.kind === 'drafted' || outcome.kind === 'repaired'\n ? { written: outcome.written }\n : {}),\n ...(outcome.kind === 'refused' && outcome.statedValueRefusal !== undefined\n ? {\n statedValueRefusal: {\n stage: outcome.statedValueRefusal.stage,\n missingValues: [...outcome.statedValueRefusal.missingValues],\n },\n }\n : {}),\n ...(dedup.kind === 'duplicate'\n ? {\n refusal: {\n filePath: dedup.evidence.matched.filePath,\n testName: dedup.evidence.matched.testName,\n matchedRef: dedup.evidence.matchedRef,\n score: dedup.evidence.score,\n threshold: dedup.evidence.threshold,\n sharedTokens: dedup.evidence.sharedTokens,\n comparedTests: dedup.comparedTests,\n continuations: [...dedup.continuations],\n },\n }\n : {}),\n }\n },\n}\n","// `authoring.funnel.get` — the honesty funnel as a catalogued capability (394-07, D-12 · WTST-05).\n//\n// ONE READ OP, AND ITS CALLERS RENDER ITS ANSWER (388 D-14's one-read-op law). What consumes it\n// TODAY is a function caller — the chat/MCP tool surface, and the CLI's generic `fn` dispatch,\n// which reaches the registered op rather than a render of its own. There is no CLI\n// funnel command and no per-run-digest funnel section; when one is written it is a client of this\n// projection, so \"how many drafts did this session keep, and did the loop actually filter any of\n// them\" has ONE answer by construction rather than by renderers agreeing. The op derives nothing:\n// `computeAuthoringFunnel` in `schema` owns every number, including the acceptance-failure flag,\n// and this file is the envelope.\n//\n// THE OP RE-SORTS AND RE-DERIVES NOTHING. `quarantine.list`'s house rule, inherited verbatim:\n// ordering is the port's law and a second sort here would be a second declaration of it, free to\n// agree today and disagree after the first tie-break change. The same argument applies with more\n// force to the numbers — a second keep-rate computation would be a second answer to the question\n// this whole capability exists to keep honest.\n//\n// THE INPUT CARRIES A WINDOW, AND THAT IS A DELIBERATE DIVERGENCE FROM `quarantine.list`. That\n// file's input carries no filter because \"a filter here would make the verb's answer depend on\n// how it was asked\", and the caller who most needs the full picture is the one who would have to\n// know to ask for it. D-12's `window` is not that: it is a SCOPE — which invocations the\n// projection is over, i.e. the denominator — rather than a predicate over rows already in hand.\n// Without it, \"how is THIS session doing\" is unanswerable from any surface, which is the exact\n// question WTST-05 asks. The divergence is recorded here and in the input schema's own doc block\n// so it reads as a decision on the record rather than as an erosion of the rule.\n//\n// IT EXPOSES PER-SESSION AUTHORING HISTORY TO ANY CALLER (T-394-26). How many drafts a user\n// produced and how many were kept is a fact about that person's work, and any caller can ask for\n// it. That is stated HERE, in the header, so a reviewer can object now rather than discover the\n// exposure later. The disposition is ACCEPT, and the argument is: the funnel reads a gitignored\n// local store of the caller's own project, the same callers already reach run history and the\n// quarantine ledger, and hiding it would make \"how is this session doing\" unanswerable from the\n// surfaces that ask it — which is precisely where 394 D-12 puts it. 2026-10-01 (432-23, 432\n// D-12): it was once declared behind the `read` scope; no scope is declared or checked now, and\n// every door can call every operation.\n\nimport {\n AuthoringFunnelGetInputSchema,\n AuthoringFunnelGetOutputSchema,\n} from '@vostride/agent-qa-schema'\nimport type { AuthoringFunnelGetInput, AuthoringFunnelGetOutput } from '@vostride/agent-qa-schema'\n\nimport { projectAuthoringFunnel } from '../../authoring/funnel.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionDeps, FunctionSpec } from '../spec.js'\n\n/**\n * Lowercase dot taxonomy (384 D-15), three segments: the shipped `authoring` domain, `funnel` as\n * the subject and `get` as the verb — the `authoring.draft.verify` / `authoring.draft.write`\n * precedent, which is itself the `knowledge.records.inspect` one.\n *\n * NO UNDERSCORE, and that is a constraint rather than a style: `parity-coverage.test.ts` requires\n * every id to match the dot taxonomy, and `chat/tool-names.ts` REFUSES an id already carrying `_`\n * because such a name has two pre-images under the `.` ↔ `_` inverse. Since 392 D-07 binds every\n * registry op into the planner's toolset, an underscore id would raise `ChatToolNameError` for\n * the whole projection rather than merely looking unconventional.\n *\n * `funnel` and not `drafts` because the subject is the MEASUREMENT, not the drafts: a second verb\n * about drafts would file under `authoring.draft.` beside its two siblings, and filing this one\n * there would have made \"get the drafts\" and \"get the funnel over the drafts\" indistinguishable at\n * exactly the point a reader is choosing between them.\n *\n * The literal appears here once; the parity-coverage suite picks the id up off the registry.\n */\nexport const AUTHORING_FUNNEL_GET_FUNCTION_ID = 'authoring.funnel.get'\n\nexport const authoringFunnelGetSpec: FunctionSpec<\n AuthoringFunnelGetInput,\n AuthoringFunnelGetOutput\n> = {\n id: AUTHORING_FUNNEL_GET_FUNCTION_ID,\n summary:\n 'Report the authoring funnel for a window — built, passed stably, added value, write-eligible — '\n + 'and flag a keep rate above the ceiling as the loop failing to filter.',\n resultKind: 'unary',\n // Bound exactly where a composition supplies the receipts store (the proposals inbox left in 432-17).\n // An unbound host answering an all-zero funnel would say \"this session authored nothing\" about\n // a store it has never been able to read — and worse, it would say the loop filtered\n // everything, which is the one reading of a zero funnel that flatters the loop. So it refuses\n // by name instead (D-09).\n boundThrough: 'authoringFunnel',\n input: AuthoringFunnelGetInputSchema,\n output: AuthoringFunnelGetOutputSchema,\n risk: { name: `fn:${AUTHORING_FUNNEL_GET_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * The funnel's OWN one line, not a second one composed here (399.1 D-01 · WTST-05).\n *\n * `line` is the single rendered sentence every surface prints, and it is screened against the\n * forbidden phrasings before the contract will carry it. Composing a receipt line out of the\n * counters instead would be a second funnel rendering — unscreened, and free to call a high keep\n * rate an achievement, which is the exact misreading D-13 exists to prevent.\n */\n classify(output): ClauseVerdict {\n return { status: 'executed', outcome: output.line }\n },\n async invoke(input, deps: FunctionDeps) {\n const authoringFunnel = deps.authoringFunnel\n if (authoringFunnel === undefined) {\n throw new FunctionNotBoundError(AUTHORING_FUNNEL_GET_FUNCTION_ID)\n }\n\n // An EMPTY funnel is a result, not an absence — a project that has authored nothing is the\n // starting state, and the computation reports it as an ABSENT keep rate rather than 0%.\n return await projectAuthoringFunnel(input.window, authoringFunnel)\n },\n}\n","// The funnel projection and the mixed-verdict stability gather (394-07, D-12/D-14 · WTST-05).\n//\n// A PROJECTION AND NOTHING ELSE. Everything here reads durable records this project already keeps\n// — the draft receipts, the run-outcome projection, the quarantine ledger —\n// scopes them to a window, and hands them to `computeAuthoringFunnel`, which owns every number.\n// NOTHING NEW IS PERSISTED (D-12): the receipts ARE the funnel's truth, so every caller of the one\n// read op — today, a read-scoped function caller; there is no CLI funnel command and no per-run\n// digest section — reads the same numbers by construction rather than by consumers agreeing to.\n// This module re-derives nothing and re-sorts nothing that the computation owns.\n//\n// THE WINDOW IS A SCOPE, NOT A FILTER. It selects which invocations the projection is over — the\n// denominator — rather than which rows survive a projection already taken. The `session` arm\n// compares `sessionRef` by EXACT STRING EQUALITY, and a receipt carrying NO ref is EXCLUDED rather\n// than defaulted in: folding an unattributed receipt into whichever session is asking would\n// attribute another author's drafts, and in the direction that matters it would inflate `built`\n// under somebody else's keep rate.\n//\n// THE STABILITY GATHER STARTS ZERO RUNS (D-14). It reads the outcome history and the quarantine\n// ledger, both of which are records of runs that already happened, and hands rows to the pure\n// `assessSuiteStability`. WTST-08's fan-out preview promises a bound before dispatch; a stability\n// check that took its own runs would make that promise one nobody could honour, which is why D-14\n// is read-side and why the port bundle below carries no run capability at all — the absence is\n// structural rather than a rule somebody has to remember.\n\nimport {\n assessSuiteStability,\n computeAuthoringFunnel,\n} from '@vostride/agent-qa-schema'\nimport type {\n AuthoringFunnel,\n AuthoringFunnelWindow,\n DraftReceipt,\n QuarantineEntryState,\n SuiteNeighbourRow,\n SuiteStabilityAssessment,\n} from '@vostride/agent-qa-schema'\n\nimport type { DraftReceiptsReadPortLike, SuiteTestIdentity } from './ports.js'\n\n/**\n * One test's recorded member outcomes, as the run-outcome projection already keys them.\n *\n * A STRUCTURAL MIRROR on this file's siblings' discipline: the real reader lives in\n * `knowledge-local` and this package may not name it. Outcomes are free strings in the run\n * store's own words — the runner owns that vocabulary and grows it, and a closed copy here would\n * read a newer runner's outcome as unknown.\n *\n * An EMPTY array is \"nothing recorded\", never \"recorded as fine\"; `assessSuiteStability` turns\n * that into the honest `no-history` posture rather than into a clean bill of health.\n */\nexport interface SuiteOutcomeHistoryPortLike {\n /**\n * The stable identities the target suite file has run evidence for, in ONE product.\n *\n * `product` LEADS BOTH VERBS because the projection these read is keyed\n * (product, filePath, testName) and nothing else is a stable identity there. A port shaped\n * without it could only be bound by guessing a product or by serving every product's history\n * under one file path — and the second would report another application's flakiness as this\n * target's, which is the whole failure the message exists to avoid (T-394-68).\n */\n testsIn(product: string, filePath: string): Promise<readonly SuiteTestIdentity[]>\n /** One identity's recorded member outcomes, newest last. */\n outcomesFor(product: string, filePath: string, testName: string): Promise<readonly string[]>\n}\n\n/**\n * The capability `authoring.funnel.get` binds through — the funnel's reads, bundled.\n *\n * 2026-10-01 (432-17, D-06): the proposals inbox read is deleted with the inbox. An authored test\n * that a keep-gate did not reject is written in its own call, so no person accepts it afterwards\n * and nothing records such a decision. The terminal stage reads the receipts alone (see\n * {@link projectAuthoringFunnel}).\n *\n * THE STABILITY HALVES RIDE THE SAME BUNDLE for the same argument, and they are OPTIONAL within\n * it: a host may genuinely have receipts and no outcome projection, and D-14's whole point is\n * that a missing history reads as `no-history` rather than as a refusal. What is NOT here is any\n * way to start a run.\n */\nexport interface AuthoringFunnelPortLike {\n readonly receipts: DraftReceiptsReadPortLike\n readonly outcomes?: SuiteOutcomeHistoryPortLike\n readonly quarantine?: { list(): Promise<readonly QuarantineEntryState[]> }\n}\n\n/**\n * Scope the receipt population to the window. PURE, exported so a cell can drive it alone.\n *\n * `last-n` orders by `evaluatedAt` DESC and takes n. The store's own `list()` order is\n * digest-lexicographic — deterministic, and deliberately not chronological — so a `last-n` that\n * inherited it would return an arbitrary n rather than the most recent n. Ties keep the store's\n * order, which is why the sort is stable rather than a comparator that reorders equal instants.\n */\nexport function scopeReceiptsToWindow(\n receipts: readonly DraftReceipt[],\n window: AuthoringFunnelWindow,\n): readonly DraftReceipt[] {\n switch (window.scope) {\n case 'all-time':\n return receipts\n case 'session':\n // EXACT string equality, and an ABSENT ref is excluded. See the header.\n return receipts.filter((receipt) => receipt.sessionRef === window.sessionRef)\n case 'last-n':\n return [...receipts]\n .map((receipt, index) => ({ receipt, index }))\n .sort((left, right) => (\n right.receipt.evaluatedAt - left.receipt.evaluatedAt || left.index - right.index\n ))\n .slice(0, window.n)\n .map((row) => row.receipt)\n }\n}\n\n/**\n * Project the funnel over one window.\n *\n * `dedupRefusals` is deliberately left ABSENT: a stage-2 refusal ends the invocation with nothing\n * authored — no draft, no receipt and no gate-run (D-04) — so nothing on this host durably records\n * one, and reporting `0` would say \"no author was ever refused\" about something nothing counts.\n *\n * THE TERMINAL STAGE IS READ OFF THE RECEIPTS (2026-10-02, quick 261002-ctr). It was `accepted`,\n * applied decisions read off `test-draft` proposal envelopes. Since 432-08 a draft a keep-gate did\n * not reject is written to its test path in the call that authored it and nothing is filed, and\n * 432-17 deleted the inbox, so `accepted` read 0 on every host. `writeEligible` counts the receipts\n * whose stored disposition D-06 writes, which `computeAuthoringFunnel` reads itself, so this\n * projection hands it nothing but the window's receipts.\n */\nexport async function projectAuthoringFunnel(\n window: AuthoringFunnelWindow,\n port: AuthoringFunnelPortLike,\n): Promise<AuthoringFunnel> {\n const receipts = scopeReceiptsToWindow(await port.receipts.list(), window)\n return computeAuthoringFunnel({ receipts, sideCounters: {} })\n}\n\n/**\n * Gather the target's existing tests and assess them. STARTS ZERO RUNS.\n *\n * The draft's OWN identity is excluded from its neighbours: a draft under evaluation is not\n * evidence about the suite it is trying to join, and counting its own flip as a neighbour's\n * would let every mixed verdict explain itself.\n *\n * An unbound outcome port is `no-history` rather than a refusal, which is D-14's degraded posture\n * arriving through the composition instead of through a special case: a host that cannot read the\n * projection genuinely has no history to report, and saying so is the honest answer.\n */\nexport async function gatherSuiteStability(\n input: {\n /**\n * The partition the outcome projection keys on — `slugBranch` of the run's own scope, as the\n * fold wrote it. REQUIRED and never defaulted: there is no correct product to fall back to,\n * and a caller that does not know one must not ask at all.\n */\n readonly product: string\n readonly targetFilePath: string\n readonly draftTestName?: string\n },\n port: AuthoringFunnelPortLike,\n): Promise<SuiteStabilityAssessment> {\n if (port.outcomes === undefined) {\n return assessSuiteStability({ targetFilePath: input.targetFilePath, neighbours: [] })\n }\n\n const quarantined = new Set(\n (await port.quarantine?.list() ?? [])\n .filter((entry) => entry.filePath === input.targetFilePath)\n .map((entry) => entry.testName),\n )\n\n const identities = (await port.outcomes.testsIn(input.product, input.targetFilePath))\n .filter((identity) => identity.testName !== input.draftTestName)\n\n const neighbours: SuiteNeighbourRow[] = []\n for (const identity of identities) {\n neighbours.push({\n filePath: identity.filePath,\n testName: identity.testName,\n outcomes: await port.outcomes.outcomesFor(\n input.product,\n identity.filePath,\n identity.testName,\n ),\n quarantined: quarantined.has(identity.testName),\n })\n }\n\n return assessSuiteStability({ targetFilePath: input.targetFilePath, neighbours })\n}\n","// `authoring.draft.verify` — the keep-gate evaluator as a catalogued capability (393, D-01).\n//\n// The four keep-gates are not a private power of whatever writes tests. D-01 registers the\n// evaluator so the corpus proof drives the REAL gated entry point (the produced-not-literal law),\n// so 397's registry-walk conformance and 396's MCP projection inherit it with no harness change,\n// and so the standalone question — \"is this existing test worth keeping?\" — is answerable from\n// every surface rather than only from inside 394's loop.\n//\n// THE ID IS `authoring.draft.verify`, NOT `authoring.verify_draft` (2026-08-10, this plan).\n// D-01 sketches the shape as `authoring.verify_draft(ref) → receipt` and leaves the exact naming\n// to 384's conventions. Two shipped mechanisms make the underscore spelling impossible, and both\n// were measured before choosing:\n// 1. `parity-coverage.test.ts` requires every id to match `^[a-z]+(?:\\.[a-z]+)+$` — the fixed\n// dot taxonomy of D-15. An underscore fails it, which is also why the shipped catalogue reads\n// `runs.postprocessing` rather than `runs.post_processing`.\n// 2. `chat/tool-names.ts` maps ids onto provider-safe tool names by `.` ↔ `_`, and REFUSES an id\n// already carrying `_` because such a name has two pre-images under the inverse. Since 392\n// D-07 binds every registry op into the planner's toolset, an underscore id would not merely\n// look unconventional — it would raise `ChatToolNameError` for the whole projection.\n// Three segments rather than two, on the `knowledge.records.inspect` precedent (and the deleted\n// `knowledge.proposal.apply`'s, 432-17): `draft` is the subject and `verify` is the verb, which keeps the ratified word in the\n// id and leaves 394 room for `authoring.draft.write` beside it.\n//\n// THE OP IS COMPOSITION, NOT MECHANISM. Every gate lives in `../../authoring/`; what is added here\n// is the entry point, its refusals, and the tier it is classified at. The four ports one\n// evaluation runs against are assembled at `composeLocalAgent()` (385 D-15) and arrive through the\n// OPTIONAL `draftEvaluation` dep, so a host that cannot parse a draft or start a run lists this\n// capability `unbound` BY NAME rather than as a hole in the catalogue (D-09).\n//\n// INPUT REFUSAL IS THE POINT OF THE FIRST HALF OF `invoke`. 392 D-07 makes this op chat-reachable\n// the moment it registers, so `draftPath` is a string an arbitrary caller chose. Every way it can\n// be wrong answers with a NAMED error rather than with a run started against a path nobody\n// checked (T-393-01).\n\nimport { AuthoringVerifyDraftInputSchema, DraftReceiptSchema } from '@vostride/agent-qa-schema'\nimport type { AuthoringVerifyDraftInput, DraftReceipt } from '@vostride/agent-qa-schema'\n\nimport { evaluateDraft } from '../../authoring/verify-draft.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport const AUTHORING_DRAFT_VERIFY_FUNCTION_ID = 'authoring.draft.verify'\n\n/**\n * The extensions a draft file may carry.\n *\n * A CLOSED SET checked on the whole suffix, never a substring: `notes.yaml.bak` ends in neither\n * member and is refused, which a `.includes('.yaml')` test would have accepted. The corpus and\n * every authored test in this project is YAML through `parseTestFile`, so there is no third\n * spelling to admit — and widening this is a retune with a visible edit rather than a silent\n * acceptance of whatever a caller names.\n */\nconst DRAFT_FILE_EXTENSIONS: readonly string[] = ['.yaml', '.yml']\n\n/**\n * The caller named a path this host cannot see.\n *\n * The FIRST of four refusals, and they are separate classes rather than one error with a `kind`\n * because a caller legitimately distinguishes them: a missing file is a typo or an unwritten\n * draft, a directory is a wrong argument, an escaping path is a boundary violation worth\n * reporting, and an unparsable file is a draft that needs fixing rather than moving. One class\n * with a discriminator would make every one of those `catch` blocks read a string.\n */\nexport class DraftFileNotFoundError extends Error {\n constructor(readonly draftPath: string) {\n super(`${AUTHORING_DRAFT_VERIFY_FUNCTION_ID}: no draft file exists at ${draftPath}`)\n this.name = 'DraftFileNotFoundError'\n }\n}\n\n/** The path resolves to something that is not a regular file — a directory, a device, a socket. */\nexport class DraftNotAFileError extends Error {\n constructor(readonly draftPath: string) {\n super(\n `${AUTHORING_DRAFT_VERIFY_FUNCTION_ID}: ${draftPath} is not a regular file, `\n + 'so there are no draft bytes to evaluate',\n )\n this.name = 'DraftNotAFileError'\n }\n}\n\n/**\n * The path names something outside the workspace this host serves (T-393-01).\n *\n * The boundary is enforced by the BOUND capability, because the resolved workspace root is a fact\n * only a host knows and `packages/agent` is `storageNeutral` — it cannot resolve a path, let alone\n * stat one. What lives here is the caller-facing NAME for the refusal, so the boundary check and\n * the vocabulary a caller catches do not have to live in the same package.\n */\nexport class DraftOutsideWorkspaceError extends Error {\n constructor(readonly draftPath: string) {\n super(\n `${AUTHORING_DRAFT_VERIFY_FUNCTION_ID}: ${draftPath} resolves outside the workspace `\n + 'this host serves; a draft is evaluated where it lives, never fetched from elsewhere',\n )\n this.name = 'DraftOutsideWorkspaceError'\n }\n}\n\n/** The file exists and is a file, and the test parser could not make a test out of it. */\nexport class DraftUnparsableError extends Error {\n constructor(readonly draftPath: string, readonly detail: string) {\n super(`${AUTHORING_DRAFT_VERIFY_FUNCTION_ID}: ${draftPath} is not a parsable test: ${detail}`)\n this.name = 'DraftUnparsableError'\n }\n}\n\n/** The path does not end in a test-file extension this host will read. */\nexport class DraftNotAYamlFileError extends Error {\n constructor(readonly draftPath: string) {\n super(\n `${AUTHORING_DRAFT_VERIFY_FUNCTION_ID}: ${draftPath} does not end in `\n + `${DRAFT_FILE_EXTENSIONS.join(' or ')}, so it is not a test file this host parses`,\n )\n this.name = 'DraftNotAYamlFileError'\n }\n}\n\nfunction hasDraftExtension(draftPath: string): boolean {\n const lowered = draftPath.toLowerCase()\n return DRAFT_FILE_EXTENSIONS.some((extension) => lowered.endsWith(extension))\n}\n\nexport const authoringVerifyDraftSpec: FunctionSpec<AuthoringVerifyDraftInput, DraftReceipt> = {\n id: AUTHORING_DRAFT_VERIFY_FUNCTION_ID,\n summary: 'Evaluate a draft test against the four keep-gates and return its receipt.',\n // 2026-10-01 (432-23, D-12): no scopes. The evaluation STARTS runs and READS the completed\n // records back, and the composition invokes those sibling ops on a caller it mints (D-02,\n // op-calls-op). The `run` + `read` pair once declared here kept a nested call from widening a\n // grant; with no grants to widen, every door can call this op and its siblings alike.\n resultKind: 'unary',\n boundThrough: 'draftEvaluation',\n input: AuthoringVerifyDraftInputSchema,\n output: DraftReceiptSchema,\n // The `runs.start` tier rationale, adapted — and it is the same argument because this op's whole\n // effect is the runs it takes:\n // `recognized: true` with NO `readOnly` puts the classifier's floor at mutating-local;\n // `declaredTier` states that tier explicitly rather than relying on the floor alone;\n // the name tokens (fn · authoring · draft · verify) hit neither destructive lexicon, so\n // nothing raises the tier above what is declared.\n // The tier was chosen when `mutating-shared` would have ASKED, and an ask in a fail-closed\n // context denied, leaving 394's authoring loop unable to verify a draft in CI, the one context\n // where the keep-filter most needs to run unattended. 2026-10-01 (432-19/432-23, D-12/D-15):\n // nothing asks or denies on a tier any more; the tier stays the honest classification.\n // Verifying a draft really is local: it spends this machine's resources, writes into this\n // project's run directory and its gitignored receipts store, and — because every gate-run is\n // flagged `excludedFromOutcomes` (WTST-06) — deliberately leaves no trace in the shared signals\n // a colleague reads.\n risk: {\n name: `fn:${AUTHORING_DRAFT_VERIFY_FUNCTION_ID}`,\n recognized: true,\n declaredTier: 'mutating-local',\n },\n /**\n * A RECEIPT'S VERDICT ABOUT A DRAFT IS AN ANSWER, not a refusal (399.1 D-01, plan 03's razor).\n *\n * `rejected` here is the gate saying what it found about somebody's draft — the verification ran\n * and produced its finding. `refused` is for a control declining an act it would otherwise have\n * carried out, and nothing was declined: the act WAS carrying out the verification.\n */\n classify(output): ClauseVerdict {\n return {\n status: 'executed',\n outcome: `verified — disposition ${output.disposition}, `\n + `${output.gateRuns.length} gate run(s)`,\n }\n },\n async invoke(input, deps) {\n // `invokeFunction` already refused this composition on the same fact, so reaching here with no\n // port means an in-layer caller holding the spec directly. The unbound state has no back door:\n // the refusal is the same named error either way (384, D-09).\n const draftEvaluation = deps.draftEvaluation\n if (draftEvaluation === undefined) {\n throw new FunctionNotBoundError(AUTHORING_DRAFT_VERIFY_FUNCTION_ID)\n }\n\n // The one refusal that needs no host: a suffix is a fact about the string. Checked BEFORE the\n // resolution so a caller who named `runs/` or a binary gets the answer that tells them what\n // this op reads, rather than a stat result about a path it was never going to parse.\n if (!hasDraftExtension(input.draftPath)) {\n throw new DraftNotAYamlFileError(input.draftPath)\n }\n\n const resolution = await draftEvaluation.resolveDraft(input.draftPath)\n switch (resolution.kind) {\n case 'not-found':\n throw new DraftFileNotFoundError(input.draftPath)\n case 'not-a-file':\n throw new DraftNotAFileError(input.draftPath)\n case 'outside-workspace':\n throw new DraftOutsideWorkspaceError(input.draftPath)\n case 'unparsable':\n throw new DraftUnparsableError(input.draftPath, resolution.reason)\n case 'parsed':\n break\n }\n\n // The ports are opened only once the draft is known good, so a refused path costs no database\n // handle and no suite walk. `draftMode` is spread rather than assigned through: the evaluator\n // reads absence, and a present `undefined` would be a second spelling of \"not draft mode\".\n // `sessionRef` rides the same idiom for a sharper reason — the receipt's absence-is-exclusion\n // rule means a present `undefined` and an absent key have to stay the same thing all the way\n // to the mint.\n const ports = await draftEvaluation.openEvaluation(resolution.draft)\n return evaluateDraft(\n {\n draft: resolution.draft,\n ...(input.draftMode === undefined ? {} : { draftMode: input.draftMode }),\n ...(input.sessionRef === undefined ? {} : { sessionRef: input.sessionRef }),\n // Same spread idiom, same reason: the evaluator reads ABSENCE as \"the draft's own file is\n // the target\", and a present `undefined` would be a second spelling of it.\n ...(input.targetSuitePath === undefined\n ? {}\n : { targetSuitePath: input.targetSuitePath }),\n },\n ports,\n )\n },\n}\n","// The gate evaluator (Phase 393, D-03/D-04/D-18 · WTST-02).\n//\n// ONE call takes a parsed draft to a persisted, schema-valid receipt: four separately-named gate\n// booleans, the per-step classification table, the per-run records, the adds-value finding, and a\n// disposition that this module does not compute.\n//\n// ALL FOUR GATES, ALWAYS (D-04). There is no short-circuit anywhere below, and the omission is\n// the point rather than an oversight. The frozen corpus proves gate INDEPENDENCE — the\n// \"page loaded\"-only draft must report executes ✓ · stable ✓ · adds-value ✓ · falsifiable ✗ so\n// that gate 4 is demonstrably the only catcher — and a vector with three of its four entries\n// missing proves nothing at all. Early-stop inside gate 2 (D-17) skips redundant RUNS; it never\n// skips a gate. The case that makes this concrete is a draft whose gate 1 fails: gates 2, 3 and 4\n// are still computed and still reported, and gate 3 in particular reports what the evidence\n// actually supports rather than a default.\n//\n// THE DISPOSITION IS NOT DERIVED HERE (D-18). `computeDraftDisposition` is imported and its\n// return is assigned. No `switch`, no `if` chain, no \"keep-eligible when all four are true\"\n// reading of the rule lives in this package — 394 consumes the disposition and must be\n// structurally unable to re-derive its own, which is only true if this side cannot either.\n//\n// MAP, NOT TERRITORY (D-19, T-393-02). The receipt is built strictly against `DraftReceiptSchema`:\n// run IDs as refs, pre-interpolation step text, findings. There is no field on it that could hold\n// a run payload or a resolved secret, and `.strict()` makes an attempt to add one a typed refusal\n// rather than a durable leak.\n\nimport {\n computeDraftDisposition,\n CURRENT_DRAFT_RECEIPT_SCHEMA_VERSION,\n DRAFT_STABILITY_RUNS_N,\n DraftReceiptSchema,\n testFingerprintElements,\n} from '@vostride/agent-qa-schema'\nimport type {\n DraftReceipt,\n PerTestOutcome,\n SuiteStabilityAssessment,\n} from '@vostride/agent-qa-schema'\n\nimport { addsValueGate } from './adds-value.js'\nimport { assertionStrengthGate } from './assertion-strength.js'\nimport { gatherSuiteStability } from './funnel.js'\nimport type { AuthoringFunnelPortLike } from './funnel.js'\nimport type {\n DraftReceiptsStoreLike,\n DraftRunPortLike,\n ParsedDraftLike,\n SuiteFingerprintIndexLike,\n SuiteTextCorpusEntryLike,\n} from './ports.js'\nimport { runStabilityGates } from './stability-gates.js'\n\n/**\n * A capability the evaluation needs was not supplied by the composition.\n *\n * The named-refusal idiom `FunctionNotBoundError` establishes for the function layer, applied one\n * level down: a host missing a run port cannot evaluate gates 1-2 at all, and the honest answer is\n * to say which port by name rather than to report four booleans computed from nothing.\n */\nexport class DraftEvaluationPortNotBoundError extends Error {\n constructor(readonly port: string) {\n super(`the draft gate evaluator has no ${port} port bound in this composition`)\n this.name = 'DraftEvaluationPortNotBoundError'\n }\n}\n\nexport interface EvaluateDraftInput {\n readonly draft: ParsedDraftLike\n /**\n * Draft mode: take ONE stability run instead of the pinned N.\n *\n * Consequential rather than a speed knob — `computeDraftDisposition` answers a one-run\n * evaluation `unverified` at best, so nothing evaluated this way is keep-eligible however its\n * four booleans read (D-18, SC3); a false gate 1, 3 or 4 still rejects it (261003-cpv, WR-09).\n */\n readonly draftMode?: boolean\n /**\n * The invoking session, spread onto the receipt when the caller supplied one (394-17, D-12).\n *\n * ABSENCE IS EXCLUSION AND THIS MODULE ADDS NO DEFAULT — the receipt schema's own rule, and the\n * reason the spread below is conditional rather than an assignment. A surface that owns a\n * session stamps it at the op boundary; every other caller mints an unattributed receipt, which\n * a session window then leaves out rather than folding into whoever is asking.\n */\n readonly sessionRef?: string\n /**\n * The suite file this draft proposes to JOIN — the stability read's target (394-19, D-14).\n *\n * CHOSEN BY THE CALLER, with the draft's own file as the fallback. The shelf path a loop-staged\n * draft carries is a STAGING fact, not a membership fact: it names a digest-named file holding\n * exactly one test, so a stability read pointed at it finds only the draft itself, which the\n * neighbour exclusion then removes. D-14 asks about the suite the draft would join, and only the\n * caller knows which that is.\n */\n readonly targetSuitePath?: string\n}\n\nexport interface EvaluateDraftPorts {\n readonly runs: DraftRunPortLike\n readonly fingerprints: SuiteFingerprintIndexLike\n /** D-16's evidence-less population. An empty array is a legitimate answer, not an absent port. */\n readonly textCorpus: readonly SuiteTextCorpusEntryLike[]\n readonly receipts: DraftReceiptsStoreLike\n /** Injected so a receipt's `evaluatedAt` is pinnable in a test. Defaults to the wall clock. */\n readonly now?: () => number\n /**\n * D-14's read side, consulted ONLY when gate 2 flips (394-17 · WTST-05).\n *\n * ONE BUNDLE OF TWO HALVES that are useless apart, on the `AuthoringFunnelPortLike` reasoning\n * one level down. `port` is the funnel's read bundle — which carries NO run capability at all,\n * so the zero-runs law is structural rather than remembered. `product` is the partition the\n * projection is keyed on, and it is a THUNK because the answer is OBSERVED rather than derived:\n * a composition learns it from the first gate-run acknowledgement, and D-04 forbids\n * short-circuiting, so by the time gate 2 can flip at least one run has been acknowledged. It\n * answers `undefined` when nothing was observed, and the consultation is then SKIPPED —\n * deriving a product from configuration instead would be a second rule for a fact the write\n * side already decides, and the first time the two disagreed this message would report another\n * application's flakiness as this target's (T-394-68).\n */\n readonly suiteStability?: {\n readonly port: AuthoringFunnelPortLike\n product(): string | undefined\n }\n}\n\n/**\n * The draft's own fingerprint elements, from its own gate-run evidence.\n *\n * WHY EVIDENCE AND NOT STEP TEXT. A suite element is minted from what the run actually resolved —\n * `{kind, type, anchor: {t:'el', role, name, ordinal}}` after normalization — so its bytes encode\n * facts (the element's a11y role, its normalized accessible name, its ordinal among peers) that\n * exist only after a browser rendered the page. Deriving the draft's side from the NL step text\n * instead would have to invent those facts, and an invented anchor matches a resolved one only by\n * accident: every draft element would come out novel and gate 3 would return `true` for every\n * draft ever evaluated, including the corpus's own near-duplicate rejector. A gate that cannot\n * return false is not a gate. Gates 1-2 have already executed the draft by the time this runs, so\n * the evidence is in hand and no extra run is taken for it.\n *\n * WHICH RUN'S EVIDENCE. The newest run that yielded any elements, which is the suite fold's own\n * rule applied to the draft: newest evidence wins, and a run contributing zero elements never\n * erases what an earlier one observed. The alternative — unioning across runs — would make the\n * draft's element set grow with N while every suite identity's stays fixed at one run's worth,\n * which is an asymmetry that would quietly make longer evaluations look more novel.\n */\nfunction draftFingerprintElements(members: readonly PerTestOutcome[]): string[] {\n for (let index = members.length - 1; index >= 0; index -= 1) {\n const elements = testFingerprintElements(members[index] as PerTestOutcome)\n if (elements.length > 0) return elements\n }\n return []\n}\n\n/**\n * Evaluate one parsed draft through all four keep-gates and persist the receipt (WTST-02).\n *\n * Returns the receipt AND writes it (D-19), so a caller never has to re-read the store to learn\n * what was just decided.\n */\nexport async function evaluateDraft(\n input: EvaluateDraftInput,\n ports: EvaluateDraftPorts,\n): Promise<DraftReceipt> {\n if (ports.runs === undefined) throw new DraftEvaluationPortNotBoundError('runs')\n if (ports.fingerprints === undefined) throw new DraftEvaluationPortNotBoundError('fingerprints')\n if (ports.receipts === undefined) throw new DraftEvaluationPortNotBoundError('receipts')\n\n const stabilityRunsRequested = input.draftMode === true ? 1 : DRAFT_STABILITY_RUNS_N\n\n // Gates 1 and 2.\n const stability = await runStabilityGates({\n draft: input.draft,\n runPort: ports.runs,\n runsRequested: stabilityRunsRequested,\n })\n\n // D-14'S LIVE ARM, ON THE FLIP PATH AND NOWHERE ELSE. A mixed verdict rejects the draft, and\n // the naive answer — discard it silently — is wrong often enough to matter: a target whose\n // EXISTING tests already flip or sit in quarantine is a target where the APPLICATION is\n // unstable, and an author can only act on that if somebody says it. The read is over records\n // that already exist and starts nothing.\n const suiteStability = await consultSuiteStability(\n input.draft,\n input.targetSuitePath,\n stability.distinctOutcomes,\n ports,\n )\n\n // Gate 3, over the draft's own execution evidence.\n const draftElements = draftFingerprintElements(stability.draftMembers)\n const addsValue = addsValueGate({\n draft: { testName: input.draft.testName, steps: input.draft.steps },\n draftElements,\n index: ports.fingerprints,\n textCorpus: ports.textCorpus,\n })\n\n // Gate 4 — the deterministic static check, whose table lands verbatim on the receipt (D-11).\n const falsifiable = assertionStrengthGate({ steps: input.draft.steps })\n\n const runRefs = stability.gateRuns.map((row) => row.runId)\n const receipt = DraftReceiptSchema.parse({\n schemaVersion: CURRENT_DRAFT_RECEIPT_SCHEMA_VERSION,\n draftRef: {\n filePath: input.draft.filePath,\n testId: input.draft.testId,\n testName: input.draft.testName,\n contentDigest: input.draft.contentDigest,\n },\n gates: {\n executesDefinitive: {\n pass: stability.executesDefinitive,\n runRefs,\n indefinitiveRunRefs: stability.gateRuns\n .filter((row) => !row.definitive)\n .map((row) => row.runId),\n reason: stabilityGateOneReason(stability.executesDefinitive, stability.gateRuns.length),\n },\n stableVerdict: {\n pass: stability.stableVerdict,\n runRefs,\n distinctOutcomes: stability.distinctOutcomes,\n earlyStopped: stability.earlyStopped,\n reason: stabilityGateTwoReason(\n stability.distinctOutcomes,\n stability.earlyStopped,\n suiteStability,\n ),\n },\n addsValue: {\n pass: addsValue.pass,\n novelElementCount: addsValue.finding.novelElements.length,\n comparedTestCount: addsValue.finding.comparedTests.length,\n reason: addsValue.reason,\n },\n falsifiableAssertion: {\n pass: falsifiable.pass,\n assertionStepCount: falsifiable.assertionStepCount,\n falsifiableAssertionCount: falsifiable.falsifiableAssertionCount,\n reason: falsifiable.reason,\n },\n },\n stepTable: falsifiable.table,\n gateRuns: stability.gateRuns,\n addsValueFinding: addsValue.finding,\n stabilityRunsRequested,\n stabilityRunsCompleted: stability.runsCompleted,\n disposition: computeDraftDisposition({\n gates: {\n executesDefinitive: stability.executesDefinitive,\n stableVerdict: stability.stableVerdict,\n addsValue: addsValue.pass,\n falsifiableAssertion: falsifiable.pass,\n },\n stabilityRunsRequested,\n stabilityRunsCompleted: stability.runsCompleted,\n }),\n evaluatedAt: (ports.now ?? Date.now)(),\n ...(input.sessionRef === undefined ? {} : { sessionRef: input.sessionRef }),\n })\n\n await ports.receipts.put(receipt)\n return receipt\n}\n\nfunction stabilityGateOneReason(pass: boolean, runCount: number): string {\n return pass\n ? `all ${runCount} gate-run(s) reached a final verdict about the draft (D-17)`\n : `${runCount} gate-run(s) taken; at least one reached no final verdict — see gateRuns[].reason`\n}\n\n/**\n * Read the target's recorded stability, on a FLIP and only on a flip (D-14, 394-17).\n *\n * THREE WAYS TO GET NOTHING, and all three are the honest answer rather than a degraded guess: the\n * verdict did not flip (there is nothing to explain), the composition bound no consultation, or no\n * product was observed. In the last case the posture is stated by NOTHING — the reason string\n * stays exactly what it has always been — because a fabricated product would read another\n * application's history and say so with names.\n *\n * The gather itself carries no run capability, so \"zero extra runs\" is a property of the port's\n * shape rather than a rule this call site has to keep.\n */\nasync function consultSuiteStability(\n draft: ParsedDraftLike,\n targetSuitePath: string | undefined,\n distinctOutcomes: readonly string[],\n ports: EvaluateDraftPorts,\n): Promise<SuiteStabilityAssessment | undefined> {\n if (distinctOutcomes.length <= 1) return undefined\n const consultation = ports.suiteStability\n if (consultation === undefined) return undefined\n const product = consultation.product()\n if (product === undefined) return undefined\n\n return await gatherSuiteStability(\n {\n product,\n // THE CHOSEN TARGET, falling back to the draft's own file. A standalone verify names no\n // join, and a committed suite file is its own target; a loop-staged draft names the suite\n // it proposes to join, because its own path is a one-test shelf artifact.\n targetFilePath: targetSuitePath ?? draft.filePath,\n // The draft's OWN identity is not evidence about the suite it is trying to join; counting\n // its own flip as a neighbour's would let every mixed verdict explain itself.\n draftTestName: draft.testName,\n },\n consultation.port,\n )\n}\n\n/**\n * Gate 2's reason, composed HERE and nowhere else.\n *\n * The assessment is APPENDED to the draft's own verdict rather than replacing it: \"your test\n * flipped\" and \"your app is unstable here\" are two different sentences and an author needs both —\n * told only the second, they would not know their draft was rejected; told only the first, they\n * would go and debug a test the application broke.\n */\nfunction stabilityGateTwoReason(\n distinctOutcomes: readonly string[],\n earlyStopped: boolean,\n suiteStability?: SuiteStabilityAssessment,\n): string {\n if (distinctOutcomes.length <= 1) {\n return `one verdict across the completed runs: ${distinctOutcomes[0] ?? 'none observed'}`\n }\n return `the verdict flipped across runs (${distinctOutcomes.join(' -> ')})`\n + (earlyStopped ? ' — remaining runs skipped, the flip is already proven (D-17)' : '')\n + (suiteStability === undefined ? '' : ` — ${suiteStability.message}`)\n}\n","// Gate 4 — the static assertion-strength check (393, WTST-02; D-09, D-10, D-11, D-12).\n//\n// ONE classification, THREE views. `classifyDraftSteps` is the only place a step is ever\n// judged; `assertionStrengthGate` folds its rows into the receipt-facing gate result, and\n// `evaluateAssertionStrength` projects the same rows onto the shape plan 01's frozen proving\n// suite pinned before any of this existed. Two of those views exist because two consumers\n// named two shapes first, and the alternative — teaching one of them the other's spelling —\n// would have meant editing an artifact whose whole value is that the implementation did not\n// get to choose it. A projection is cheap; a second judgment would be two answers to\n// \"is this draft's oracle real\", free to disagree.\n//\n// DETERMINISTIC BY CONSTRUCTION (D-06). No I/O, no clock, no config, no model. The hermetic\n// lane runs this per-commit with no LLM by contract, which is only possible if the check\n// cannot reach one.\n//\n// AMBIGUITY TUNES TOWARD REJECT (D-12). Every borderline arm below returns \"not falsifiable\".\n// That is defensible only because the rejection is READABLE: the per-step table lands verbatim\n// in the receipt (D-11), so a rejected author is told which step was called what, which vacuity\n// phrase it matched, and which capture pattern named its expected value. A gate that tunes\n// toward reject without saying why is just a gate that says no.\n\nimport type { StepClassificationRow } from '@vostride/agent-qa-schema'\n\n/**\n * The minimal structural mirror of a parsed draft's step list.\n *\n * Declared HERE rather than imported because the dependency points the other way — this\n * package never names `core`, where `parseTestFile` lives, and acquiring that import would\n * be a `validate:arch` violation with no legal repair (the `TestOutcomeHistoryLike`\n * precedent in `jobs/kinds.ts`). The HOST parses and flattens: `parseTestFile` yields steps\n * as `string | { step: string }`, and the caller narrows to text before handing them down\n * (the parse-at-host precedent in `cli/src/curation/authoring-test-discovery.ts`).\n */\nexport interface ParsedDraftStepsLike {\n readonly steps: readonly string[]\n}\n\n/**\n * The closed assertion-verb set — D-09 clause (i).\n *\n * A PINNED CONSTANT, never config (386 D-15). RETUNE COMMENT: these six are the verbs a person\n * writes when the next sentence is a CLAIM about the app rather than an instruction to it.\n * Every verb added here is a verb that can now open an assertion, which moves the gate's\n * numerator directly — clause (i) is satisfiable by one more shape of step, and every draft\n * that previously failed for having no assertion at all starts failing (or passing) for a\n * different reason. So add one only with a real draft that it rescues, and re-run the frozen\n * corpus afterwards: the expectations table is the denominator that says whether the widening\n * was a fix or a leak.\n *\n * Matching is on the step's LEADING token, exactly and case-insensitively — membership never\n * position, exact never substring. `Verifying` begins with a member and is not one;\n * `Type \"alice\" into the Verify field` contains a member and asserts nothing.\n *\n * Order is alphabetical and NOT load-bearing: the set is read by membership, never scanned.\n */\nexport const ASSERTION_VERBS = [\n 'assert',\n 'check',\n 'confirm',\n 'ensure',\n 'expect',\n 'verify',\n] as const\n\n/**\n * The closed action-verb set — used ONLY to detect a mixed act-and-verify step (D-12).\n *\n * A PINNED CONSTANT, never config. RETUNE COMMENT: these fourteen are the verbs that open an\n * INSTRUCTION to the app. They are read at exactly one place — the leading token of a clause\n * that follows a separator inside an assertion step — and never scanned across a whole step,\n * which is what keeps `Verify the Submit button is disabled` an ordinary assertion about an\n * element that happens to be named after an action. Widening this set makes MORE assertions\n * mixed and therefore non-falsifiable, so it moves the numerator toward reject; narrowing it\n * moves the numerator toward accept, which is the direction that costs a user a bad test.\n * Either way, re-run the frozen corpus.\n */\nexport const ACTION_VERBS = [\n 'click',\n 'drag',\n 'enter',\n 'fill',\n 'hover',\n 'navigate',\n 'open',\n 'press',\n 'scroll',\n 'select',\n 'submit',\n 'type',\n 'upload',\n 'visit',\n] as const\n\n/**\n * The closed vacuity set — D-09 clause (ii).\n *\n * A PINNED CONSTANT, never config. RETUNE COMMENT: a member is a whole assertion remainder\n * that, standing alone, is true of any page the browser managed to render — it names no\n * content, no element and no state that could have come out differently. `page loaded`\n * qualifies; `page shows the text \"Username\"` does not, and neither does anything that names\n * a thing the app could be wrong about. Every phrase added here REJECTS a draft that used to\n * pass, so add one only with the draft it catches, and re-run the frozen corpus.\n *\n * Matched EXACTLY against the normalized remainder — the step with its leading verb, its\n * leading articles and its trailing punctuation removed — and never as a substring of the raw\n * step. `Verify the banner says \"the page loaded\"` contains a member and is a concrete\n * assertion about page content; a substring scan rejects it, which is a real draft lost to a\n * lexicon that reached past its own boundary.\n *\n * ITS TWO JOBS, AND WHICH ONE IS LIVE TODAY. The lexicon NAMES the phrase on the receipt, which\n * is load-bearing now (D-11 — the author has to be told which term was called empty). It also\n * sits as a conjunct in the falsifiability rule, and that conjunct decides nothing on the\n * current membership: no member contains an `EXPECTED_STATE_TERMS` token, so a remainder that\n * equals a member is already non-concrete and refused by the other arm. It is kept as a guard\n * against exactly the widening this comment invites, and 393-15 re-derived WHICH widening that is.\n * `page is visible` is not the candidate: `namesElementInExpectedState` walks left from `visible` and\n * answers on the `PAGE_WHOLE_NOUNS` member `page`, so the concreteness arm refuses it first — in\n * every casing, and under every padding (a padding word the walk may cross reaches `page` anyway,\n * and one it may not stops the walk, which refuses too). The member that would hand this conjunct\n * the whole decision is one carrying an `EXPECTED_STATE_TERMS` token whose nearest content word to\n * the LEFT is an `ELEMENT_NOUNS` member: `banner is visible` is that shape.\n * The guard still has a live trigger rather than a promise — `assertion-strength.test.ts`'s\n * cross-lexicon closure case walks every member and reds if the conjunct goes away under such a\n * widening.\n *\n * Order is alphabetical and NOT load-bearing: the set is read by membership.\n */\nexport const VACUOUS_ASSERTION_PHRASES = [\n 'it works',\n 'no errors',\n 'no errors occurred',\n 'page appears',\n 'page displayed',\n 'page is displayed',\n 'page loaded',\n 'page loads',\n 'page works',\n] as const\n\n/**\n * The closed expected-state set — the second falsifiability arm of D-09 clause (ii).\n *\n * A PINNED CONSTANT, never config. RETUNE COMMENT: a member is a binary, observable state an\n * element is either in or not. It counts as concrete expected content only BESIDE a named\n * element (see `namesElementInExpectedState`), because `is visible` on its own says visible what.\n * Widening this set makes more assertions falsifiable without a quoted literal, which is the arm\n * most likely to accept a weak oracle — re-run the frozen corpus, and prefer a quoted literal.\n *\n * WHAT ONE RETUNE HERE MOVES — RE-DERIVED 2026-08-10 (393-15). This set is the relation's ANCHOR:\n * every member is a position the leftward walk starts from. A member added here therefore widens\n * WHICH STATES count as checkable and nothing else — the element side of the relation still answers\n * by `ELEMENT_NOUNS` membership alone, and the refusal side by everything that is not an element\n * member (a named page-whole noun, or, since 393-17, any token outside the walk's continue set).\n * (Between 393-12 and 393-13 a member added here was ALSO excluded from element-name candidacy, so\n * one retune moved two measurements in opposite directions; that coupling is gone. What replaced it\n * is a READ, not a coupling: the set is consumed as anchor positions, which is why the earlier\n * \"never reads this set at all\" phrasing no longer holds and is corrected here rather than\n * silently dropped — the W-10 record on this lexicon stays continuous.)\n */\nexport const EXPECTED_STATE_TERMS = [\n 'checked',\n 'disabled',\n 'empty',\n 'enabled',\n 'hidden',\n 'selected',\n 'unchecked',\n 'visible',\n] as const\n\n/**\n * The closed element-noun set — the positive lexicon that resolves the relation TRUE (393-13, 393-15).\n *\n * A PINNED CONSTANT, never config. RETUNE COMMENT, AND ITS DIRECTION IS THE INVERSE OF THE THREE\n * EXCLUSION SETS THIS REPLACED: a member is a common name for a CONTROL or a LANDMARK on a page —\n * a thing an author points at, that the app could be wrong about. ADDING a member moves the gate\n * toward ACCEPT: every vacuous-shaped claim naming that noun starts passing, which is the direction\n * that costs a user a bad test. So a member arrives only with a real draft it rescues, plus a\n * re-run of the frozen corpus — the expectations table is the denominator that says whether the\n * widening was a fix or a leak. REMOVING a member refuses drafts: D-12's safe direction, still a\n * real cost.\n *\n * Read by exact membership over a NORMALIZED (lowercased, non-letters stripped) residue token —\n * membership never position, exact never substring.\n *\n * WHAT IS DELIBERATELY ABSENT. The page-whole nouns — app, browser, content, form, page, screen,\n * site — are NOT members, because a claim naming only those says nothing an author could have got\n * wrong about a particular thing. That absence is a NECESSARY condition of refusing `page is visible`\n * and `the form is empty` — the walk tests element membership first, so a page-whole noun listed here\n * would resolve those claims TRUE before any refusal branch is reached — and it is load-bearing in\n * exactly that sense: adding `form` here would re-open the claim D-12 exists to reject. What it is\n * no longer is SUFFICIENT on its own; since 393-17 a non-member is refused by the walk's stop rather\n * than merely failing to be accepted, which is what makes the refusal hold for nouns nobody listed.\n *\n * Order is alphabetical and NOT load-bearing: the set is read by membership.\n */\nexport const ELEMENT_NOUNS = [\n 'alert',\n 'banner',\n 'button',\n 'checkbox',\n 'dialog',\n 'dropdown',\n 'field',\n 'footer',\n 'header',\n 'heading',\n 'icon',\n 'image',\n 'input',\n 'label',\n 'link',\n 'list',\n 'menu',\n 'modal',\n 'option',\n 'panel',\n 'popup',\n 'radio',\n 'row',\n 'sidebar',\n 'slider',\n 'spinner',\n 'tab',\n 'table',\n 'textbox',\n 'toast',\n 'toggle',\n 'toolbar',\n 'tooltip',\n] as const\n\n/**\n * The closed page-whole noun set — the relation's SUBJECT REFUSER (393-15).\n *\n * A PINNED CONSTANT, never config, and it is exactly the seven nouns the `ELEMENT_NOUNS` doc above\n * already names as deliberately absent. It is declared as its own set because the relation needs to\n * ACT on them — a page-whole noun standing between a state term and any element noun to its left is\n * the claim's subject, and it stops the walk — where absence from `ELEMENT_NOUNS` only makes them\n * non-elements.\n *\n * READ IN EXACTLY ONE PLACE: inside `namesElementInExpectedState`'s leftward walk, as the token that\n * resolves an occurrence FALSE. It is never scanned across a whole residue on its own. An\n * independent whole-input scan of a third lexicon is the shape the round-5 verification named as the\n * cause of the defect this set exists to close, and re-introducing it here would reproduce it.\n *\n * RETUNE COMMENT, AND ITS DIRECTION IS THE OPPOSITE OF `ELEMENT_NOUNS`'. ADDING a member moves the\n * gate toward REJECT: every claim whose nearest non-function-word before a state term is that member\n * is refused BY NAME. That is D-12's safe direction and still a real cost, so a member arrives with\n * the vacuous draft it catches plus a frozen-corpus re-run. Since 393-17 REMOVING a member no longer\n * moves the verdict at all — the walk's default stop refuses the same token one branch later — and\n * OMISSION, including omission by inflection or by synonym, behaves the same way and therefore fails\n * toward REJECT. Before that it did not: the walk crossed whatever this set failed to spell, so an\n * omission here was measurably an ACCEPT-direction hole in a tune-toward-reject gate, and a plural\n * was enough to open it. What the set still carries, now that it no longer carries the verdict, is\n * the refusal's NAME — it says which class of subject the gate is refusing, where the default stop\n * can only say \"not an element\" — plus the intent it pins and the disjointness discipline below.\n *\n * A token may not be a member of this set and of `ELEMENT_NOUNS` (or of `EXPECTED_STATE_TERMS`):\n * the walk would have two answers for it. The disjointness is pinned in the lexicon-discipline\n * group of `__tests__/assertion-strength.test.ts`.\n *\n * Order is alphabetical and NOT load-bearing: the set is read by membership.\n */\nexport const PAGE_WHOLE_NOUNS = [\n 'app',\n 'browser',\n 'content',\n 'form',\n 'page',\n 'screen',\n 'site',\n] as const\n\n/**\n * The closed function-word set — the leftward walk's CONTINUE set (393-17).\n *\n * A PINNED CONSTANT, never config. These are the ONLY tokens the walk may cross between an\n * expected-state term and the noun that is its subject. Everything else stops the walk, which is\n * what makes the refuser TOTAL rather than enumerated: a subject head this module has never heard\n * of refuses the claim instead of being walked through in search of a member in another clause.\n *\n * WHY THESE NINE. `is`, `not` and `still` are what the accept controls require — `Verify the submit\n * button is disabled`, `Verify The Submit Button Is Not Visible`, `Verify the username field is\n * still empty` are real drafts that must keep gate 4. The rest is the closed be-copula paradigm\n * (`are`, `be`, `been`, `being`, `was`, `were`), included as a paradigm rather than one tense at a\n * time because a verdict that moved when an author wrote `was` for `is` would be the one-character\n * flip this round exists to remove.\n *\n * WHAT IS DELIBERATELY EXCLUDED, and each exclusion is load-bearing. CONJUNCTIONS: they mark the\n * clause boundary the walk must never cross, so admitting `and` would re-open the cross-clause\n * rescue by construction — the exact defect. PREPOSITIONS: a preposition heads a noun phrase, so a\n * noun always stands between the member and the anchor and that noun decides first; admitting the\n * preposition would only let the walk reach past its own object. ARTICLES: an article always stands\n * to the LEFT of its own noun, so it is never reachable between a member and its state term, and\n * listing it would be a member with no live position. And every open adverb class beyond `still`\n * and `not`, because an open class cannot be closed and a set that tries is a set that leaks.\n *\n * RETUNE COMMENT, and its direction is `ELEMENT_NOUNS`' rather than `PAGE_WHOLE_NOUNS`' (D-12).\n * ADDING a member is an ACCEPT-direction move — one more token the walk may bridge, so claims that\n * were refused start passing — and therefore arrives with the real draft it rescues plus a\n * frozen-corpus re-run. OMISSION fails toward REJECT: an exotic intervening adverb refuses a genuine\n * claim, which is a real cost and the SAFE rot direction, priced beside the other accepted costs on\n * `namesElementInExpectedState`. That asymmetry is the whole point of the set — the pre-fix posture\n * had a lexicon whose omissions failed toward ACCEPT, and this one cannot.\n *\n * Read in exactly one place: inside the walk, as the continue case. Never scanned across a residue.\n * Not exported from the agent barrel (the `PAGE_WHOLE_NOUNS` precedent).\n *\n * Order is alphabetical and NOT load-bearing: the set is read by membership.\n */\nexport const FUNCTION_WORDS = [\n 'are',\n 'be',\n 'been',\n 'being',\n 'is',\n 'not',\n 'still',\n 'was',\n 'were',\n] as const\n\n/**\n * The closed capture-signature set — D-10, the oracle-capture class.\n *\n * A PINNED CONSTANT, never config. RETUNE COMMENT: a member matches a value only a CAPTURE\n * could have produced — a run's own output pasted in as the expectation, which asserts what\n * the app did rather than what it should do. Every pattern is anchored at BOTH ends and is\n * applied to a single whitespace-delimited token of a quoted expected value, never to the\n * step's prose: an unanchored machine-content pattern starts rejecting sentences, which is\n * how a heuristic about ids becomes a heuristic about English.\n *\n * Adding a pattern rejects drafts that used to pass, so add one with the draft it catches and\n * with a human-authored value it must NOT catch — the false-positive control is the half that\n * is easy to skip and expensive to omit.\n *\n * SCOPE, honestly (D-10, the W-09 discipline): this narrows the oracle-capture class, it does\n * not eliminate it. A semantically wrong but syntactically clean expectation — a plausible\n * human-shaped value that simply is not what the app should show — passes every pattern here.\n * 394's authoring provenance is the closure that remains. 2026-09-02 (Phase 412): bug-repro\n * anchoring left with the Issue-slot cleanup.\n *\n * Order is by name, alphabetically, and is NOT load-bearing: every pattern is tried and the\n * hits are reported as a sorted set.\n */\nexport const CAPTURE_SIGNATURE_PATTERNS = [\n { name: 'iso-8601-timestamp', pattern: /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?(?:Z|[+-]\\d{2}:?\\d{2})?$/ },\n { name: 'long-hex', pattern: /^[0-9a-f]{16,}$/i },\n { name: 'opaque-id', pattern: /^(?:sess|session|tok|token|sk|pk|id|ref|txn|ord)[_-][A-Za-z0-9]{8,}$/i },\n { name: 'uuid', pattern: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i },\n] as const\n\n/**\n * The closed separator set for a MIXED act-and-verify step (D-12).\n *\n * A PINNED CONSTANT, never config. RETUNE COMMENT: these are the joins a person types when\n * one step secretly contains two — `Verify the form is submitted and click Continue`. A step\n * like that has no single verdict to report, so it contributes no falsifiable assertion and\n * the author is told to split it.\n *\n * Declared HERE rather than imported from `chat/clause-split.ts`, which pins a near-identical\n * set for the conjunction grammar. That is deliberate and it is the one duplication in this\n * file: the chat separators move the CHAT-03 refusal rate and these move the gate-4 numerator,\n * and a single shared constant would make one retune silently move two unrelated measurements\n * (the W-10 lesson). The sets are allowed to drift because the questions are different.\n *\n * The word tokens carry their own whitespace, which IS the word-boundary rule: ` and ` cannot\n * match inside `command`. A separate boundary check would be a second answer to a question the\n * token spelling already answers, free to disagree with it.\n */\nconst MIXED_STEP_SEPARATORS = [' and ', ' then ', ';', ','] as const\n\n/** Leading determiners stripped before the vacuity lexicon is consulted. */\nconst LEADING_ARTICLES = ['a', 'an', 'that', 'the'] as const\n\nconst TRAILING_PUNCTUATION_RE = /[.!?,;:\\s]+$/\nconst QUOTED_LITERAL_RE = /\"([^\"]*)\"/g\n\n/**\n * An unquoted money amount: a currency symbol with a number (446-11, D-25, the owner's decision).\n *\n * A PINNED PATTERN, never config. It widens D-09 clause (ii) toward ACCEPT, the direction every\n * retune comment in this file warns about, so the case is stated here. `$29.00` names the one value\n * the page must show exactly as `\"$29.00\"` does: the page shows that amount or it does not, so a\n * wrong total fails the step. The currency symbol is what marks a value the page displays rather\n * than a count in the instruction, which is why bare numbers (`1 item`, `29.00`), a symbol with no\n * number, and vague wording (`the total is correct`) stay refused. The five symbols are the ones\n * 440's stated values read, so a price the request states and the draft keeps is one this gate\n * accepts. Read from the unquoted residue only, and compared against earlier actions' quoted spans\n * and money amounts, so restating a typed price, quoted or not, is still a tautology. The frozen\n * corpus verdicts did not move (re-checked in 446-11 and 446-17); re-run it on any change here.\n */\nconst MONEY_AMOUNT_RE = /(?<![\\p{L}\\p{N}])[$€£¥₹]\\d+(?:[.,]\\d+)*(?![\\p{L}\\p{N}])/gu\n\n/** The frozen contract shape plan 01's `corpus-static-gates.test.ts` pinned (D-08). */\nexport interface AssertionStrengthStep {\n readonly text: string\n readonly kind: 'assertion' | 'action'\n readonly falsifiable: boolean\n readonly captureSignatureHits: string[]\n}\n\n/** @see AssertionStrengthStep */\nexport interface AssertionStrengthResult {\n readonly falsifiable: boolean\n readonly steps: AssertionStrengthStep[]\n}\n\n/**\n * The receipt-facing gate result.\n *\n * The counts and the reason are here rather than derived by the receipt assembler because\n * `DraftGateResults.falsifiableAssertion` asks for exactly these three fields beside `pass`,\n * and a consumer recounting the table would be a second answer to a question this function\n * already answered (388 C13, one exported vocabulary).\n */\nexport interface AssertionStrengthGateResult {\n readonly pass: boolean\n readonly assertionStepCount: number\n readonly falsifiableAssertionCount: number\n readonly reason: string\n readonly table: StepClassificationRow[]\n}\n\nfunction normalizeToken(raw: string): string {\n return raw.toLowerCase().replace(/[^a-z]/g, '')\n}\n\nfunction leadingToken(text: string): string {\n return normalizeToken(text.trim().split(/\\s+/)[0] ?? '')\n}\n\nfunction isAssertionVerb(token: string): boolean {\n return (ASSERTION_VERBS as readonly string[]).includes(token)\n}\n\nfunction isActionVerb(token: string): boolean {\n return (ACTION_VERBS as readonly string[]).includes(token)\n}\n\n/**\n * Every double-quoted span of a step, unfiltered — what the author actually typed.\n *\n * TWO VIEWS BECAUSE THERE ARE TWO QUESTIONS (393-15). This RAW view answers the TAUTOLOGY question:\n * an action that typed `\"\"` really did type it, and an assertion restating that same span is still\n * restating a prior action's own content. `quotedLiterals` below answers the CONCRETENESS question:\n * an empty span expects nothing, so it cannot be the expected value that makes an assertion\n * falsifiable. Each consumer reads the view that matches its own question, which is what keeps the\n * two paths from disagreeing about the question each is actually asking.\n *\n * THE COST THE SINGLE FILTERED VIEW CHARGED, recorded rather than absorbed (WR-01, measured by the\n * round-5 verifier). 393-13 introduced the trim filter at the producer, so the prior-action\n * accumulation was starved of empty captures too. Two shapes moved FAIL -> PASS undisclosed:\n * `Type \"\" into the Username field` + `Verify the Username field is empty and shows \"\"`, and the\n * whitespace-literal form of the same pair. Both are tautologies and both are now refused again,\n * pinned in both directions — the two pairs refused, and an accept control (an assertion that\n * quotes nothing after an empty capture) held passing so the restoration cannot over-reject.\n */\nfunction quotedSpans(text: string): string[] {\n return [...text.matchAll(QUOTED_LITERAL_RE)].map((match) => match[1] ?? '')\n}\n\n/**\n * The double-quoted spans that carry expected CONTENT — empty and whitespace-only spans dropped.\n *\n * The filter is a `trim` test rather than a falsiness test because `\" \"` asserts exactly as little\n * as `\"\"` does. Without it, bare `Verify \"\"` satisfied `literals.length > 0` and short-circuited\n * the concreteness arm — a quoted expected value that expects nothing (393-13). Read by the\n * concreteness arm and by the capture-signature scan; never by the tautology comparison.\n */\nfunction quotedLiterals(text: string): string[] {\n return quotedSpans(text).filter((literal) => literal.trim() !== '')\n}\n\n/** The step with every double-quoted span removed, so prose scans cannot read a literal. */\nfunction unquotedResidue(text: string): string {\n return text.replace(QUOTED_LITERAL_RE, ' ')\n}\n\nfunction moneyAmounts(text: string): string[] {\n return unquotedResidue(text).match(MONEY_AMOUNT_RE) ?? []\n}\n\n/** The step after its leading token, byte-for-byte — every caller normalizes for itself. */\nfunction afterLeadingToken(text: string): string {\n const trimmed = text.trim()\n const boundary = trimmed.search(/\\s/)\n\n return boundary === -1 ? '' : trimmed.slice(boundary + 1).trim()\n}\n\n/**\n * The assertion remainder the vacuity lexicon is matched against, EXACTLY.\n *\n * Leading verb, then leading articles one at a time, then trailing punctuation. Articles are\n * stripped iteratively because `that the page is displayed` carries two, and a single pass\n * would leave a remainder that no member can equal — which reads as \"not vacuous\" and is the\n * failure direction that costs a user a bad test.\n */\nfunction vacuityRemainder(text: string): string {\n let remainder = afterLeadingToken(text).toLowerCase().replace(/\\s+/g, ' ').trim()\n\n for (;;) {\n const head = remainder.split(' ')[0] ?? ''\n if (!(LEADING_ARTICLES as readonly string[]).includes(head)) break\n remainder = remainder.slice(head.length).trim()\n }\n return remainder.replace(TRAILING_PUNCTUATION_RE, '')\n}\n\n/**\n * Whether an assertion step secretly contains an instruction (D-12).\n *\n * A separator, and then a clause whose OWN leading token is an action verb. The leading-token\n * rule is the same one role classification uses, and for the same reason: an action verb\n * appearing anywhere in a sentence says nothing, while an action verb opening a clause is an\n * instruction. Quoted spans are removed first — the literal a page must show may itself read\n * `Click here to continue`, and rejecting that draft would be the lexicon reaching past its\n * own boundary again.\n */\nfunction isMixedActAndVerify(text: string): boolean {\n const residue = unquotedResidue(text)\n\n for (const separator of MIXED_STEP_SEPARATORS) {\n const pieces = residue.split(separator)\n if (pieces.length < 2) continue\n if (pieces.slice(1).some((piece) => isActionVerb(leadingToken(piece)))) return true\n }\n return false\n}\n\n/**\n * Whether the assertion names an element that is IN an expected state — D-09 clause (ii)'s second\n * route to concreteness, as ONE relation rather than two unrelated scans.\n *\n * THE RULE ENFORCED, verbatim (393-15, 393-17). The post-verb residue, with double-quoted spans already\n * removed, is tokenized ONCE: split on whitespace, each piece through `normalizeToken` (lowercased,\n * non-letters stripped). For every index whose token is an `EXPECTED_STATE_TERMS` member, walk LEFT\n * from that index one token at a time and answer on the FIRST token that is not a function word: an\n * `ELEMENT_NOUNS` member resolves that occurrence TRUE, a `PAGE_WHOLE_NOUNS` member resolves it\n * FALSE, a `FUNCTION_WORDS` member is crossed and the walk continues, and ANY OTHER token resolves\n * it FALSE and stops. Reaching the start of the residue resolves it FALSE too. CONTINUING is the\n * enumerated case and STOPPING is the default, which is what makes the refuser total: a subject head\n * outside all three sets refuses the claim rather than being walked through until some member turns\n * up. The answer is true iff at least one state-term occurrence resolves TRUE. The `PAGE_WHOLE_NOUNS`\n * branch stands AHEAD of the stop and is redundant with it on today's memberships — the stop would\n * refuse those same seven tokens one branch later — and it is kept because it names the refusal\n * class the gate exists for, which the default stop cannot say. Letter case is never consulted:\n * `normalizeToken` lowercases, so a step and any recasing of it get the identical verdict by\n * construction. There is no distance constant anywhere in the rule: what decides is WHICH token the\n * walk meets first, never how far away it sat — and because everything outside the continue set\n * stops the walk, no verdict can now depend on how many words the sentence put in between.\n *\n * One tokenization consequence, deliberate and in D-12's direction: a state term fused into a\n * hyphenated compound normalizes into a single token that is no longer a member, so the compound\n * anchors nothing and the claim is refused. Punctuation merely attached to a state term\n * (`visible.`) still normalizes clean and anchors as usual.\n *\n * WHY THE RULE IS SHAPED THIS WAY (five regressions, every one of them measured, 2026-08-10 and\n * 2026-08-11, phase 393 verification rounds 2–6). The FIRST rule read any post-verb word beginning with a capital\n * letter as an element name, on the house-style premise that a draft writes `the Submit button`.\n * Title-cased prose defeated it outright: `Verify The Page Is Visible` — the exact vacuous claim\n * D-12 exists to refuse — passed gate 4 while its lowercase twin was refused, and the drafts this\n * filter exists for are LLM-authored and commonly title-cased. The SECOND rule kept the capital and\n * added a neighbour condition — the residue had to carry a capital-initial word beside a\n * lowercase-initial one — which removed only the two degenerate casings and left the whole\n * mixed-case interior open: `Verify the Page is visible` PASSED, one character from the refused\n * form, while `Verify The Submit Button Is Disabled` — a real control in a binary observable state\n * — FAILED. The THIRD rule removed the casing axis entirely and asked instead whether some residue\n * token was a member of NONE of three exclusion lists. That closed the casing axis for good, and\n * the defect simply moved: every ordinary function word nobody had thought to list — a negation, a\n * modal, an adverb, a copula — was outside all three sets and therefore read as an element name, so\n * `Verify the page is not visible` PASSED while `Verify the page is visible` was refused, and seven\n * more paddings of the same vacuous claim with it. The FOURTH rule inverted to one positive element\n * lexicon, which fixed the MEMBERSHIP half and left the POSITIONAL half untouched: element-naming\n * and state-bearing were still two independent membership scans over the whole residue, conjoined\n * with no relation between them, so the gate answered \"a named element in a checkable state\" for any\n * sentence that merely MENTIONED a lexicon member — as a trailing prepositional object, as a verb,\n * or sixty spaces away. All 33 members of the element lexicon were measured carrying the vacuous\n * generic-page claim in one frame, and the round's old-vs-new differential showed that fix had not\n * moved the case in either direction. The common cause: an unrelated conjunction of two whole-input\n * scans is strictly WEAKER than the rule it implements, because it can be satisfied by two facts\n * about different parts of the sentence. Relating the arms — one tokenization, one walk, one\n * decision per state term — is what makes the composed predicate say what D-09 clause (ii) says.\n * The FIFTH rule related the arms correctly and then privileged the claim's subject only when that\n * subject was one of seven exact spellings: every other subject token was crossed rather than\n * answered on, so the walk kept going left, past the subject and across the clause boundary, until\n * some element noun turned up. Inflection alone defeated it — a page-whole subject written in the\n * plural, or with a synonym the seven-member set did not hold, or hyphenated so it normalized into\n * one unrecognized token, handed the verdict to a noun in a different clause with no state asserted\n * of it. A single trailing character flipped the answer, which is the same defect as the SECOND\n * rule's one-character boundary wearing a different lexicon. The common cause with the fourth is\n * that both let an ENUMERATION carry the refusal: a rule that refuses only what it can name is\n * strictly weaker than the rule it implements, because the sentences it has never heard of fall to\n * the accepting side. Making the refusal the DEFAULT and the crossing the enumeration is what\n * removes the spelling dependency, and it is why the continue set may only ever hold a closed class.\n *\n * The removed rules are described in words on purpose. Naming their functions or restating their\n * character classes here would leave a durable, greppable account of a mechanism that no longer\n * exists, which is how a comment starts teaching the shape it was written to retire.\n *\n * RESIDUAL, accepted and named — BOTH of them, and the width claim is RE-DERIVED from the shipped\n * walk rather than carried forward (393-17; the round-6 disclosure asserted the same width over a\n * rule that had a third bypass, which is what made the claim false). The derivation: an occurrence\n * resolves TRUE only when an `ELEMENT_NOUNS` member stands to the left of the anchor with nothing\n * but `FUNCTION_WORDS` members in between, and no clause-boundary token — no conjunction, no\n * separator, no unknown noun — is in that set. So TRUE now requires the member to occupy the\n * anchor's own subject position under a nearest-content-word reading, and the two bypasses below\n * are the two ways that reading can still be wrong. There is no third: a member in another clause,\n * at a distance, in a prepositional object or standing as a verb cannot reach the anchor any more,\n * because reaching it means crossing a token that stops the walk.\n * (a) MEMBERSHIP CANNOT KNOW THE PAGE. `Verify the banner is visible` passes whether or not the\n * page has a banner. Membership decides that a word names a KIND of element; nothing lexical\n * can decide that this page holds one. Pinned by the deliberately-passing test \"leaves the\n * documented residual open on purpose: a lexicon MEMBER reads as an element name\" in\n * `__tests__/assertion-strength.test.ts`. Closing it needs the resolved a11y evidence gate 3\n * works from — it is not reachable by any lexicon retune.\n * (b) NEAREST-PRECEDING IS A SUBJECT PROXY, NOT SYNTAX. The rule reads the nearest content word to\n * the left of a state term as that state's subject, which it usually is and need not be. A\n * member standing between a page-whole subject head and the state term reads as the subject,\n * so `Verify the page with the banner is visible` passes although the claim is about the\n * page. Pinned by the deliberately-passing test \"leaves the SECOND residual open on purpose:\n * nearest-preceding is a subject PROXY, not syntax\". Closing it needs a parse, not a lexicon:\n * the fix is a dependency analysis of the sentence, which is a different class of tool from\n * a deterministic hermetic membership check, so it is accepted here rather than approximated\n * with a heuristic that would ship another axis.\n *\n * ACCEPTED COST, priced in the open, and the retune routes. Every item below is a REAL draft this\n * gate refuses; all are pinned by deliberately-failing cells in the accepted-cost test.\n * - An UNLISTED genuine element noun: `Verify the widget is visible`, `Verify the carousel is\n * visible`, and `Verify the Login form is empty` (whose `form` is a page-whole noun and so stops\n * the walk as well).\n * - PLURALS, as a whole CLASS. Membership is exact and there is no stemming, so `Verify the Submit\n * buttons are disabled` is refused while the singular `Verify the Submit button is disabled`\n * passes. That is the single largest category of loss and it is not a per-word omission.\n * - Six COMMON NOUNS an author reaches for constantly and this lexicon does not hold: `message`,\n * `text`, `title`, `item`, `cell`, `card` — `Verify the error message is visible`, `Verify the\n * text is visible`, `Verify the title is visible`, `Verify the item is selected`, `Verify the\n * cell is empty` and `Verify the card is visible` all lose gate 4.\n * - The ATTACHMENT cost, new with the relation: a genuine element claim written with a page-whole\n * noun nearer the state term is refused, so `Verify the header on the page is visible` fails\n * because `page`, not `header`, is what the walk meets first. This is D-12's direction — the\n * sentence is ambiguous about what is being claimed visible — and it is a cost, not a bonus.\n * - The INTERVENING-TOKEN cost, new with the total refuser: ANY token outside the three sets\n * standing between a member and its state term refuses a genuine claim, because the walk stops\n * on it rather than crossing it. `Verify the submit button is currently visible` loses gate 4 to\n * one ordinary adverb, and `Verify the button badge is visible` loses it to an unknown subject\n * head standing one clause nearer than the member. Both are pinned RED-first. This is the price\n * of a closed continue set, and it is charged in the SAFE direction: what an omission from that\n * set costs is a refused genuine draft, never an accepted vacuous one.\n * The AUTHOR's route out is a singular lexicon noun standing beside its state (`Verify the login\n * field is empty` passes, and is pinned), quoting the literal the page must show, or stating a\n * money amount (see `MONEY_AMOUNT_RE`). The\n * MAINTAINER's routes are an `ELEMENT_NOUNS` membership change or a `FUNCTION_WORDS` membership\n * change (both move the gate toward ACCEPT — one more subject the walk will answer TRUE on, one\n * more token it will cross to get there) or a `PAGE_WHOLE_NOUNS` membership change (which moves the\n * NAMED refusal without moving the verdict, since the stop already refuses whatever that set omits),\n * each with the frozen corpus re-run that says whether the retune was a fix or a leak — never a\n * character-case test, never a fourth exclusion list, never an independent whole-residue scan, and\n * never a refuser that can only refuse what it is able to name: those are the four shapes that\n * shipped the five regressions above.\n */\nfunction namesElementInExpectedState(text: string): boolean {\n const tokens = afterLeadingToken(unquotedResidue(text)).split(/\\s+/).map(normalizeToken)\n\n for (let index = 0; index < tokens.length; index += 1) {\n if (!(EXPECTED_STATE_TERMS as readonly string[]).includes(tokens[index] ?? '')) continue\n\n for (let left = index - 1; left >= 0; left -= 1) {\n const token = tokens[left] ?? ''\n if ((ELEMENT_NOUNS as readonly string[]).includes(token)) return true\n if ((PAGE_WHOLE_NOUNS as readonly string[]).includes(token)) break\n if (!(FUNCTION_WORDS as readonly string[]).includes(token)) break\n }\n }\n return false\n}\n\n/**\n * The capture-signature patterns a quoted expected value hits, by NAME (D-10).\n *\n * Per whitespace-delimited token of each literal, so a value that embeds a machine id inside a\n * sentence is still caught, and reported as a sorted deduplicated set so the receipt reads the\n * same way whichever literal matched first.\n */\nfunction captureSignatureHits(literals: readonly string[]): string[] {\n const hits = new Set<string>()\n\n for (const literal of literals) {\n for (const token of literal.split(/\\s+/)) {\n for (const entry of CAPTURE_SIGNATURE_PATTERNS) {\n if (entry.pattern.test(token)) hits.add(entry.name)\n }\n }\n }\n return [...hits].sort()\n}\n\n/**\n * The per-step classification table (D-11).\n *\n * The ONE judgment in this module. Prior-action captures accumulate as the walk proceeds, which is\n * what makes the tautology rule directional: an assertion cannot restate content that has not been\n * entered yet, and an order-blind comparison would reject a legitimate pre-condition check for\n * restating something that comes later. What accumulates — and what the tautology comparison reads\n * — is the RAW span list; the concreteness arm and the capture-signature scan read the filtered\n * literals instead (see `quotedSpans`). An action's unquoted money amounts join that list beside its\n * spans, and an assertion's money amount is concrete and is compared against it (see\n * `MONEY_AMOUNT_RE`).\n */\nexport function classifyDraftSteps(steps: readonly string[]): StepClassificationRow[] {\n const priorActionLiterals = new Set<string>()\n const rows: StepClassificationRow[] = []\n\n for (const stepText of steps) {\n const spans = quotedSpans(stepText)\n const literals = quotedLiterals(stepText)\n\n if (!isAssertionVerb(leadingToken(stepText))) {\n for (const span of spans) priorActionLiterals.add(span)\n for (const amount of moneyAmounts(stepText)) priorActionLiterals.add(amount)\n rows.push({ stepText, role: 'action', falsifiable: false, captureSignatureHits: [] })\n continue\n }\n\n const vacuityHit = (VACUOUS_ASSERTION_PHRASES as readonly string[])\n .find((phrase) => phrase === vacuityRemainder(stepText))\n const hits = captureSignatureHits(literals)\n const amounts = moneyAmounts(stepText)\n const tautology = [...spans, ...amounts].some((value) => priorActionLiterals.has(value))\n const concrete =\n literals.length > 0 || amounts.length > 0 || namesElementInExpectedState(stepText)\n\n rows.push({\n stepText,\n role: 'assertion',\n falsifiable:\n concrete\n && vacuityHit === undefined\n && hits.length === 0\n && !tautology\n && !isMixedActAndVerify(stepText),\n captureSignatureHits: hits,\n ...(vacuityHit === undefined ? {} : { vacuityHit }),\n ...(tautology ? { tautologyHit: true } : {}),\n })\n }\n return rows\n}\n\nfunction gateReason(rows: readonly StepClassificationRow[]): string {\n const assertions = rows.filter((row) => row.role === 'assertion')\n\n if (assertions.length === 0) {\n return 'no step classifies as an assertion: the draft records what it did, never what should be true (D-09 clause (i))'\n }\n if (assertions.some((row) => row.falsifiable)) {\n return `${assertions.filter((row) => row.falsifiable).length} of ${assertions.length} assertion steps reference concrete expected content`\n }\n\n const causes = new Set<string>()\n for (const row of assertions) {\n if (row.vacuityHit !== undefined) causes.add(`vacuous phrase \"${row.vacuityHit}\"`)\n if (row.tautologyHit === true) causes.add('restates a prior action\\'s own literal')\n for (const hit of row.captureSignatureHits) causes.add(`capture signature ${hit}`)\n // D-12's mixed act-and-verify signal has no receipt ROW field: `StepClassificationRowSchema`\n // is strict and carries no `mixedHit`, and 393-06 declined to add one — a bare boolean would\n // name nothing the step text does not already show, where `vacuityHit` names the exact phrase\n // and `captureSignatureHits` the exact pattern. The cause therefore has to surface HERE, which\n // is where 393-04's own handoff note said it would. Until this line it did not: a mixed step\n // carrying a quoted literal fell through to the fallback below and the receipt read\n // \"no quoted expected value\" about a step that has one — a durable false explanation, which is\n // the one thing D-12's tune-toward-reject posture cannot afford.\n if (isMixedActAndVerify(row.stepText)) {\n causes.add('acts and verifies in one step, so it has no single verdict to report')\n }\n }\n // THE FALLBACK MUST BE TRUE OF EVERY STEP THAT REACHES IT (393-15, re-derived 393-17). Two tails\n // have now been retired here for the same reason, and the reason is worth stating once: a tail\n // that describes the rule's INPUTS goes stale the moment the rule changes, while a tail that\n // states the RELATION the rule decides stays true as long as the rule decides it. The first tail\n // said the step named no element — false about `Verify the Submit buttons are disabled` and every\n // other plural or unlisted noun, a durable receipt denying what the author plainly wrote. The\n // second said no element noun stood as the NEAREST set-noun before a state term, which the total\n // refuser falsified at once: in `Verify the submit button is currently visible` an element noun IS\n // the nearest set-noun before `visible`, and the gate refuses anyway, because an ordinary adverb\n // stands between them. What is true of every step reaching this line is the relation as the walk\n // now decides it — and, as before, it may not deny an element or a literal the author wrote.\n if (causes.size === 0) {\n causes.add(\n 'no quoted expected value, and no element noun this gate knows stands before an expected-state term with only function words between them',\n )\n }\n\n return `${assertions.length} assertion step(s), none falsifiable: ${[...causes].sort().join('; ')} (D-09 clause (ii))`\n}\n\n/**\n * Gate 4 (D-09's two clauses composed) over a parsed draft's steps.\n *\n * Pass requires at least one row that is BOTH an assertion and falsifiable — the two clauses\n * are conjoined on a single row rather than checked independently, because a draft with a\n * vacuous assertion and a falsifiable-looking action would otherwise satisfy them separately.\n */\nexport function assertionStrengthGate(draft: ParsedDraftStepsLike): AssertionStrengthGateResult {\n const table = classifyDraftSteps(draft.steps)\n const assertions = table.filter((row) => row.role === 'assertion')\n const falsifiable = assertions.filter((row) => row.falsifiable)\n\n return {\n pass: falsifiable.length > 0,\n assertionStepCount: assertions.length,\n falsifiableAssertionCount: falsifiable.length,\n reason: gateReason(table),\n table,\n }\n}\n\n/**\n * The frozen proving suite's contract (D-08) — a projection, never a second judgment.\n *\n * `corpus-static-gates.test.ts` was committed RED against this exact signature before any of\n * this module existed, and it names its fields `text`/`kind` where the receipt schema names\n * them `stepText`/`role`. Renaming either side to agree with the other would have meant the\n * implementation editing the artifact that exists to constrain it, so the two spellings both\n * stand and this function carries the mapping. `vacuityHit` and `tautologyHit` are absent from\n * the projection because the frozen shape has no field for them — they survive on the receipt\n * rows, which is where D-11 says the author reads them.\n */\nexport function evaluateAssertionStrength(steps: readonly string[]): AssertionStrengthResult {\n const table = classifyDraftSteps(steps)\n\n return {\n falsifiable: table.some((row) => row.role === 'assertion' && row.falsifiable),\n steps: table.map((row) => ({\n text: row.stepText,\n kind: row.role,\n falsifiable: row.falsifiable,\n captureSignatureHits: row.captureSignatureHits,\n })),\n }\n}\n","// Gates 1 and 2 — the stability driver (Phase 393, D-02/D-17 · WTST-02).\n//\n// Gate 1 asks whether the draft reached a DEFINITIVE verdict; gate 2 asks whether that verdict\n// HELD. Both are answered from execution evidence alone — never from `analyze-run`'s authoring\n// output (the verdict/post-processing split, live-view.md §4) — and both read the DRAFT'S OWN\n// member-test outcome rather than the run's aggregate, because the aggregate carries\n// quarantine-aware rules that are noise for a draft nobody has ever run before.\n//\n// EVERY START INPUT CARRIES BOTH MARKERS (D-02, T-393-03). `gateRun: true` and\n// `excludedFromOutcomes: true` are distinct axes and both are set on every run this module takes.\n// A gate-run that entered the outcome fold would seed the very union gate 3 later compares the\n// draft against, and the corruption accumulates in a derived index rather than announcing itself.\n// The markers are not merely SENT — the acknowledgment is checked, because `runs.start` copies\n// them off the durable record instead of echoing the request, so an acknowledgment without them\n// is the host reporting that the run was not accepted as a gate-run.\n\nimport { DRAFT_STABILITY_RUNS_N } from '@vostride/agent-qa-schema'\nimport type {\n CompletedRunHandoff,\n GateRunRecord,\n MemberTestOutcome,\n PerTestOutcome,\n RunsStartInput,\n} from '@vostride/agent-qa-schema'\n\nimport type { DraftRunPortLike, ParsedDraftLike } from './ports.js'\n\n/**\n * The run was started but the host did not report it back as a gate-run.\n *\n * A refusal rather than a warning, and the reasoning is about blast radius. Every other failure\n * in this module degrades one draft's receipt; this one silently widens the suite union with the\n * draft's own evidence, in a derived index that accumulates across runs, so the next draft\n * evaluated against it reads its own surface as already covered. Nothing downstream can detect\n * that from a receipt. Stopping is the only response that keeps the corruption from compounding.\n */\nexport class GateRunNotFlaggedError extends Error {\n constructor(readonly runId: string, readonly acknowledged: {\n gateRun?: true\n excludedFromOutcomes?: true\n }) {\n super(\n `runs.start accepted ${runId} without both gate-run markers ` +\n `(gateRun=${String(acknowledged.gateRun)}, ` +\n `excludedFromOutcomes=${String(acknowledged.excludedFromOutcomes)}): ` +\n 'an unflagged gate-run pollutes the outcome projection and the suite fingerprint union ' +\n 'the draft is later compared against (WTST-06).',\n )\n this.name = 'GateRunNotFlaggedError'\n }\n}\n\nexport interface RunStabilityGatesInput {\n readonly draft: ParsedDraftLike\n readonly runPort: DraftRunPortLike\n /** How many runs to take. `1` is draft mode; absent means the pinned N. */\n readonly runsRequested?: number\n}\n\nexport interface StabilityGatesResult {\n /** Gate 1. */\n readonly executesDefinitive: boolean\n /** Gate 2. */\n readonly stableVerdict: boolean\n /** One row per run taken, in order — the receipt's `gateRuns`. */\n readonly gateRuns: GateRunRecord[]\n readonly runsCompleted: number\n /** True when D-17's early-stop fired: the reason a completed count may be below N. */\n readonly earlyStopped: boolean\n /**\n * The distinct COMPARISON verdicts observed; `length > 1` is the flip, exactly as\n * `DraftGateResultsSchema.stableVerdict.distinctOutcomes` promises. Raw member-outcome enum\n * values live per run on `gateRuns[].memberOutcome`.\n */\n readonly distinctOutcomes: string[]\n /**\n * The draft's own member outcome from each run that produced one, in order.\n *\n * Gate 3's draft-side elements are computed from these — see `verify-draft.ts`. Carried out of\n * this module rather than re-read because the run documents are already in hand here, and\n * fetching them twice would let the two gates disagree about which run they are describing.\n */\n readonly draftMembers: PerTestOutcome[]\n}\n\n/**\n * Member outcomes that represent a FINAL answer about the draft (D-17).\n *\n * `healed` is here and it is load-bearing rather than lenient: 393-01 measured the accept\n * control's definitive pass arriving as `healed`, not `passed` (F3), on the very draft the corpus\n * exists to accept. A gate 1 that treats a heal as indefinitive fails it.\n */\nconst DEFINITIVE_MEMBER_OUTCOMES: ReadonlySet<string> = new Set<MemberTestOutcome>([\n 'passed',\n 'failed',\n 'healed',\n])\n\n/** The sentinel `memberOutcome` for a run whose document held no member for this draft. */\nexport const ABSENT_MEMBER_OUTCOME = 'absent'\n\n/**\n * The verdict gate 2 COMPARES across runs — `healed` folded into `passed`.\n *\n * A heal is a recovery within one run, not a different answer about the app, and 393-01's F2\n * measured heals arriving on 5 of 8 corpus drafts from seeded procedure replay. Comparing the raw\n * enum would make nearly every draft read unstable for a reason that is about the knowledge store\n * rather than about the draft — a false gate-2 rejection, which is the direction that costs a user\n * a good test. The raw enum survives per run on the receipt, so nothing is hidden by the fold.\n */\nfunction comparisonVerdict(memberOutcome: string): string {\n return memberOutcome === 'healed' ? 'passed' : memberOutcome\n}\n\n/** The draft's own member in a run document, by stable identity (never `testId`). */\nexport function findDraftMember(\n document: CompletedRunHandoff,\n draft: ParsedDraftLike,\n): PerTestOutcome | undefined {\n return document.tests.find(\n (member) => member.filePath === draft.filePath && member.testName === draft.testName,\n )\n}\n\n/** Whether any step recorded a self-heal, beside the member outcome's own `healed` arm. */\nfunction recordedHeal(member: PerTestOutcome): boolean {\n return member.outcome === 'healed'\n || member.steps.some((step) => step.selfHeal !== undefined)\n}\n\n/**\n * Whether this run reached a FINAL answer about the draft, and what was read to decide (D-17).\n *\n * THE ENUM IS NOT ENOUGH, AND NEITHER IS ANY SINGLE TERMINAL FIELD. 393-01 measured both halves.\n * F1: a draft naming controls the target does not have comes back `failed` — a definitive value —\n * while its step evidence carries an infeasible termination, and 19 of 21 failed members in the\n * demo run store carry one, so gate 1 read off the enum alone passes the corpus's own gate-1\n * rejector. F3: the accept control's definitive pass arrives as `healed`, so a gate 1 strict about\n * the enum fails the draft the corpus exists to accept. The answer is therefore a COMPOSITE —\n * the enum admits the run, the step evidence can still disqualify it — which is exactly the shape\n * `GateRunRecordSchema` was minted for: `definitive` is a judgment, not a field copy, and `reason`\n * is where the judgment says what it read.\n *\n * WHERE D-17'S \"error\" WENT. The decision text lists planning failure, infeasible termination,\n * cycle, error, timeout and cancelled. There is no `'error'` member outcome on this build —\n * `RunStatus` is `passed | failed | healed | timeout | cancelled` — and the class it names arrives\n * in one of two shapes that ARE handled: a structural `planningFailure` block (393-01 measured one\n * on page-loaded-only's first run, a guardrail block during planning) or a run whose record cannot\n * be read back at all. Neither is folded into a synthetic enum member, because inventing an\n * outcome value the vocabulary does not have would put a second spelling of `RunStatus` in this\n * file.\n *\n * ORDER IS FOR THE READER, NOT THE VERDICT. Any one cause is disqualifying, so the result does not\n * depend on which is checked first; the order decides which cause the receipt NAMES when a run has\n * more than one, and the enum is checked first because it is the coarsest.\n */\nfunction classifyGateRun(member: PerTestOutcome): { definitive: boolean; reason: string } {\n if (!DEFINITIVE_MEMBER_OUTCOMES.has(member.outcome)) {\n return {\n definitive: false,\n reason: `member outcome '${member.outcome}' is not a final pass or fail (D-17)`,\n }\n }\n\n for (const step of member.steps) {\n if (step.planningFailure !== undefined) {\n return {\n definitive: false,\n reason: `planning failed structurally on step ${step.stepIndex}: the draft was never `\n + 'executed to a verdict, so the enum below describes the attempt, not the app (D-17)',\n }\n }\n if (step.limitStop !== undefined) {\n const { limit, used, configured } = step.limitStop\n return {\n definitive: false,\n reason: `step ${step.stepIndex} stopped at its ${limit} limit (${used} of ${configured} `\n + 'used): the run ran out of limit, not into an answer (D-12)',\n }\n }\n // Historical reader: only pre-436 handoffs carry a cycle block.\n if (step.cycle !== undefined) {\n return {\n definitive: false,\n reason: `a cycle was flagged on step ${step.stepIndex} (${step.cycle.reason}): the run `\n + 'stopped revisiting state rather than reaching an answer (D-17)',\n }\n }\n if (step.termination !== undefined) {\n return {\n definitive: false,\n reason: `step ${step.stepIndex} terminated '${step.termination.kind}' `\n + `(${step.termination.reason}) — indefinitive despite member outcome `\n + `'${member.outcome}', which reads definitive on its own (393-01 F1)`,\n }\n }\n }\n\n return {\n definitive: true,\n reason: `member outcome '${member.outcome}' with no planning failure, limit stop, cycle flag `\n + 'or termination on any step — a final answer about the draft'\n + (member.outcome === 'healed' ? '; a healed pass IS a pass (393-01 F3)' : ''),\n }\n}\n\n/**\n * The `runs.start` input for one gate-run.\n *\n * `patterns` names the draft file and nothing else, so the run admits exactly the member the\n * gates then look for. The draft path is passed through as handed in — boundary validation (is\n * this path inside the workspace at all?) belongs at the op invoke where the resolved config\n * exists, and is plan 07's T-393-01 discharge.\n */\nfunction gateRunStartInput(draft: ParsedDraftLike): RunsStartInput {\n return {\n patterns: [draft.filePath],\n gateRun: true,\n excludedFromOutcomes: true,\n }\n}\n\n/**\n * Take up to `runsRequested` gate-runs and answer gates 1 and 2 (D-17).\n *\n * EARLY-STOP SKIPS RUNS, NEVER A GATE (D-04/D-17). Once two different verdicts have been observed\n * the flip is proven and the remaining runs cannot un-prove it, so they are not taken. Both\n * booleans are still computed and both are still reported — what shrinks is `runsCompleted`, which\n * is why `computeDraftDisposition` reads a short count as `rejected` rather than as `proposal-only`\n * when a gate is false.\n *\n * ONLY OBSERVED VERDICTS PARTICIPATE. A run whose record could not be read, or whose document\n * holds no member for this draft, fails gate 1 and contributes nothing to gate 2. Missing\n * information is not a different answer: counting it as a flip would fail gate 2 for an\n * infrastructure hiccup — the direction that costs a user a good test — and would early-stop the\n * evaluation, throwing away the runs that could still have said something.\n */\nexport async function runStabilityGates(\n input: RunStabilityGatesInput,\n): Promise<StabilityGatesResult> {\n const runsRequested = input.runsRequested ?? DRAFT_STABILITY_RUNS_N\n const gateRuns: GateRunRecord[] = []\n const draftMembers: PerTestOutcome[] = []\n const observedVerdicts: string[] = []\n let earlyStopped = false\n\n for (let taken = 0; taken < runsRequested; taken += 1) {\n const acknowledgement = await input.runPort.start(gateRunStartInput(input.draft))\n if (acknowledgement.gateRun !== true || acknowledgement.excludedFromOutcomes !== true) {\n throw new GateRunNotFlaggedError(acknowledgement.runId, acknowledgement)\n }\n\n const document = await input.runPort.get(acknowledgement.runId)\n const member = document === undefined ? undefined : findDraftMember(document, input.draft)\n\n if (member === undefined) {\n gateRuns.push({\n runId: acknowledgement.runId,\n memberOutcome: ABSENT_MEMBER_OUTCOME,\n definitive: false,\n healed: false,\n reason: document === undefined\n ? 'no completed-run record was readable for this run: nothing is known about it, '\n + 'which is a gate-1 failure and not a verdict'\n : 'the run document holds no member for '\n + `(${input.draft.filePath}, ${input.draft.testName}) — the stable identity, `\n + 'never testId',\n })\n continue\n }\n\n draftMembers.push(member)\n const { definitive, reason } = classifyGateRun(member)\n gateRuns.push({\n runId: acknowledgement.runId,\n memberOutcome: member.outcome,\n definitive,\n healed: recordedHeal(member),\n reason,\n })\n\n observedVerdicts.push(comparisonVerdict(member.outcome))\n if (new Set(observedVerdicts).size > 1) {\n earlyStopped = taken + 1 < runsRequested\n break\n }\n }\n\n const distinctOutcomes = [...new Set(observedVerdicts)]\n\n return {\n executesDefinitive: gateRuns.length > 0 && gateRuns.every((row) => row.definitive),\n // An evaluation that observed no verdict at all has not shown stability; it has shown nothing.\n // D-12's tune-toward-reject applies — a gate with no evidence behind it is not a pass.\n stableVerdict: distinctOutcomes.length === 1,\n gateRuns,\n runsCompleted: gateRuns.length,\n earlyStopped,\n distinctOutcomes,\n draftMembers,\n }\n}\n","// `config.auth.set` — refs only, ratified as law (Phase 395-05, D-11 · CFGM-01/CFGM-02).\n//\n// 2026-09-30, 432-11 D-05/D-07: THIS OP WRITES IN THE CALL. It is constructed, scanned and validated\n// as described below and then published through the direct writer; the answer names the files and\n// fields it changed, a blocked change is answered with its report and nothing is kept, and no git\n// runs. Where the paragraphs below say \"proposal\", read the change this call writes.\n//\n// `config-field-set.ts`'s header carries the arguments for the tier and the one-op-per-action\n// shape; they are not restated. What is different about this one is the law it enforces and where\n// it enforces it. 2026-10-01 (432-27, D-12): this op once declared `config-write`, and that header\n// once argued for the scope. It declares no scope now, because no caller is checked for one; the\n// reference law below, the scan and whole-config validation guard the write, and nothing about the\n// masking or the refusal of a literal credential changed with the scope.\n//\n// A LITERAL CREDENTIAL ARRIVING IN THE INPUT IS ITSELF THE FAILURE. D-11 ratified this action as\n// writing REFERENCES — the name of a plugin package, the name of an environment variable — and\n// never a value. 2026-10-02 (quick 261002-ctr): it also named an auth state, written to\n// `use.authState`; the committed configuration has no such key, so that field is deleted (see\n// `setConfigAuth`). 395-02 enforced the first half in the SHAPE of\n// `ConfigAuthSetInputSchema`: there is no field a credential could be assigned to, which is a\n// property of the type rather than a rule anybody remembers. This op enforces the second half, on\n// the INPUT and before a single byte is mutated, because a law about what the configuration may hold\n// is enforced too late if it is only enforced on the rendered artifact — by then the credential has\n// been through a serialiser, a differ and a digest, and the honest disposition for the proposal that\n// carries one is a refusal rather than a filed record somebody has to go and delete.\n//\n// THE REFUSAL IS ANSWERED, NOT FILED, AND THAT IS THIS OP'S EDGE OVER ITS FOUR SIBLINGS. A secret in\n// a `config.field.set` value is a BLOCKED RECORD: any config path may legitimately hold any value,\n// so the fact worth persisting is \"somebody tried to write a secret into your configuration\". A\n// secret in an auth REFERENCE is a different fact — the caller filled a field with the wrong KIND of\n// thing — and there is no candidate configuration to file because none was ever built. The store\n// delta across a refused call is zero, and a cell measures it.\n//\n// TWO GATES, AND ONLY ONE OF THEM NAMES ANYTHING. The detector engine recognises credential families\n// it knows and values the masker has been seeded with; `isLegalConfigReference` states positively\n// what an auth-state name, a package name and an environment variable name ARE and refuses the\n// complement. The second is the structural one — a rule that names nothing it refuses cannot be\n// walked past by inventing a credential family nobody listed — and the residue where both miss is\n// recorded as a KNOWN BOUND cell rather than described as closed.\n\nimport { ConfigChangeOutputSchema, ConfigAuthSetInputSchema } from '@vostride/agent-qa-schema'\nimport type { ConfigChangeOutput, ConfigAuthSetInput } from '@vostride/agent-qa-schema'\n\nimport { classifyConfigChangeOutput } from './config-propose-verdict.js'\nimport { setConfigAuth } from '../../config-mutation/construct.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { FunctionSpec } from '../spec.js'\n\nexport const CONFIG_AUTH_SET_FUNCTION_ID = 'config.auth.set'\n\nexport const configAuthSetSpec: FunctionSpec<ConfigAuthSetInput, ConfigChangeOutput> = {\n id: CONFIG_AUTH_SET_FUNCTION_ID,\n summary: 'Declare an auth plugin for a configured target by package NAME, written in this call.',\n resultKind: 'unary',\n input: ConfigAuthSetInputSchema,\n output: ConfigChangeOutputSchema,\n boundThrough: 'configWrite',\n risk: {\n name: `fn:${CONFIG_AUTH_SET_FUNCTION_ID}`,\n recognized: true,\n readOnly: false,\n },\n /**\n * This op's own union, folded into a clause verdict (2026-08-20, Phase 399.1 D-01/D-02).\n *\n * THE FOLD IS SHARED BECAUSE THE UNION IS. Six ops answer with `ConfigChangeOutput` (432-11), and a\n * per-op copy of the mapping would be a guardrail refusal that reports `refused` on some doors\n * and `executed` on others the first time one copy is edited. See `config-propose-verdict.ts`\n * for why `blocked` and `refused` are the same status and different words.\n */\n classify: classifyConfigChangeOutput,\n async invoke(input, deps): Promise<ConfigChangeOutput> {\n // The same three-way guard its siblings carry: the files, the validator and the direct writer.\n // The D-11 input check is the reference shape rule, which needs no port (441 D-15).\n const { configFiles, configValidate, configWrite } = deps\n if (\n configFiles === undefined\n || configValidate === undefined\n || configWrite === undefined\n ) {\n throw new FunctionNotBoundError(CONFIG_AUTH_SET_FUNCTION_ID)\n }\n return await setConfigAuth(\n { action: CONFIG_AUTH_SET_FUNCTION_ID, ...input },\n { configFiles, configValidate, configWrite },\n )\n },\n}\n","// The clause verdicts for the config answers — one union, one fold each (399.1-03 · D-01/D-02).\n//\n// 2026-09-30, 432-11 D-05: the config ops answer `ConfigChangeOutput`, what they wrote in the call,\n// and fold through `classifyConfigChangeOutput`. 2026-10-01, 432-17 D-05/D-09: `config.undo.propose`\n// and the `ConfigProposeOutput` union it alone still answered are deleted, and its fold with them.\n//\n// THE CONFIG OPS SHARE ONE FOLD, because six copies of one mapping is the drift this project refuses\n// everywhere else it has a shared vocabulary: a later edit that taught `config.target.create` to\n// report a guardrail block as `refused` and left `config.auth.set` reporting `executed` would be a\n// security control that works on some doors. The arms belong to `ConfigChangeOutputSchema`, so the\n// fold over them belongs beside it too — not inside whichever op happened to need it first.\n//\n// IT READS DISCRIMINANTS AND THE ARM'S OWN NAMED REASON, AND NOTHING ELSE. D-01 rejected chat-side\n// value-pattern matching by name — \"a rule that can only refuse what it can NAME cannot be driven to\n// zero by naming more things\" — and a fold that sniffed strings out of a payload would be that same\n// door-enumeration failure moved one file over. `refusal-classifiers.test.ts` scans this file's\n// executable text for every value-inspecting operator and requires none.\n//\n// IT DECIDES NOTHING. The op has run (no gate and no execution-audit row since 432-13/432-19). This\n// is the REPORT, and its only job is to stop the report saying `executed` over a refusal.\n\nimport type { ConfigChangeOutput } from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict } from '../spec.js'\n\n/**\n * Fold one `ConfigChangeOutput` into the verdict its own arm states (432-11 D-05/D-07).\n *\n * `applied` and `no-change` are `executed`: the file holds the change. `blocked` and `refused` are\n * `refused`, with their own reason, and nothing was written. `interrupted` is `failed`: some files\n * hold the change and one did not, so success is the one thing this report must not say.\n */\nexport function classifyConfigChangeOutput(output: ConfigChangeOutput): ClauseVerdict {\n switch (output.outcome) {\n case 'applied':\n return { status: 'executed', outcome: `applied: ${output.files.join(', ')}` }\n case 'no-change':\n return { status: 'executed', outcome: `no change: ${output.path} already holds that value` }\n case 'blocked':\n return { status: 'refused', outcome: output.blockedReason }\n case 'refused':\n return { status: 'refused', outcome: output.reason }\n case 'interrupted':\n return { status: 'failed', outcome: `interrupted at ${output.failed.path}: ${output.failed.reason}` }\n }\n}\n","// The config change construction pipeline (Phase 395, CFGM-01 / CFGM-02 / CFGM-04 · D-01 / D-03 /\n// D-09 / D-10 / D-11 / D-12 / D-17).\n//\n// 2026-09-30, 432-11 D-05/D-07: THE SIX CONFIG OPERATIONS WRITE IN THE CALL. Step 7 below is now a\n// publication through the direct writer (`configWrite`): field changes through the config\n// transaction, whole files over the digest they were built from. A blocked change is answered as a\n// refusal carrying its report, and nothing is filed or written. Nothing here runs git.\n// 2026-10-01, 432-17 D-05/D-09: `config.undo.propose` and the proposal filing it alone still used\n// are deleted with the proposal inbox; a written change is reverted with git (D-07).\n//\n// SEVEN STEPS IN ONE ORDER, AND THE ORDER IS THE CONTRACT:\n//\n// 1. RE-READ the committed files. CFGM-04's proposal-time law, and it is the first step rather\n// than an optimisation: every digest this proposal records is a claim about what was on disk\n// at the moment the proposal was made, so reading anything cached would make the apply's\n// re-check compare against a file nobody looked at.\n// 2. MUTATE, comment-preservingly, through the host's yaml Document port. A parse→object→stringify\n// round trip destroys every comment in the house-style config and widens the rendered diff past\n// the point a person can review it, which is CFGM-01's whole subject.\n// 3. RENDER the diff and take the digests, through the ONE schema primitive (D-17). Construction\n// and apply call the same export; that is the whole of the CR-02 mitigation.\n// 4. VALIDATE THE WHOLE CANDIDATE SET. CFGM-01 is explicit that validation runs BEFORE the\n// change exists, so a mutation that breaks the config never becomes something a person can\n// accept. It validates the ENTIRE candidate rather than the changed field, because D-03 removed\n// the settable-field whitelist deliberately — the guards here are whole-input by construction\n// or they are door enumeration — and since 395-05 the whole input is the whole FILE SET, not\n// the config yaml alone: `config.hook.add` changes only the hooks file, and a validator that\n// never saw it would have declared valid the one artifact that change wrote.\n// 5. CLASSIFY cross-boundary-ness from the actual VALUES (D-02), through `computeCrossBoundary`.\n// 6. PUBLISH through the direct writer and answer what it wrote (432-11).\n//\n// NO SECRET SCAN (2026-10-14, 441 D-15/D-23). A config change is not scanned for secrets and is\n// never blocked for what a value looks like: a value in a config field is the author's own text.\n// What a change shows — its diff, a validator's words — reaches people and models through the\n// declared-secret mask each door applies to what it shows.\n//\n// SIX OPS, ONE PIPELINE, AND THE SPLIT BETWEEN THEM IS THE POINT (395-05, D-01). Steps 3 to 6 are\n// `checkConfigCandidate` plus `publishConfigChange` and every action reaches them: what a\n// `config.target.create` and a `config.field.set` do differently is which bytes they hand it, never\n// what happens to those bytes afterwards. What the ops DO own is steps 1 and 2 plus their own\n// REQUEST refusals — a create against a name that exists, an edit against one that does not —\n// because those are facts about the ask rather than about the resulting configuration, and the two\n// dispositions are deliberately different answers (see `CONFIG_CHANGE_REFUSAL_REASONS`).\n//\n// A validation failure is answered as a refusal carrying its report, with nothing written or kept.\n//\n// NOTHING HERE COMMITS. The direct writer publishes files and runs no git; a person reviews and\n// reverts the change with their own tools (D-07).\n//\n// PURE OVER PORTS. Every host fact — bytes, the yaml edit, the document's shape, validation, the\n// writer — arrives as a dependency, so the pipeline is drivable end to end with no filesystem and\n// no git, and the composed case in `cli` drives it with the real ones.\n\nimport {\n CONFIG_SET_GITIGNORE,\n UnrenderableConfigDiffError,\n base64Encode,\n isLegalConfigReference,\n renderConfigDiff,\n utf8Decode,\n utf8Encode,\n} from '@vostride/agent-qa-schema'\nimport type {\n ConfigAuthSetInput,\n ConfigChange,\n ConfigChangeOutput,\n ConfigDiffChanged,\n ConfigDiffFileInput,\n ConfigHookAddInput,\n ConfigBlockedReason,\n ConfigChangeFile,\n ConfigProjectScaffoldInput,\n ConfigReferenceKind,\n ConfigTargetCreateInput,\n ConfigTargetEditInput,\n CrossBoundaryReason,\n} from '@vostride/agent-qa-schema'\n\nimport { computeCrossBoundary } from './cross-boundary.js'\nimport type { CrossBoundaryFieldEdit } from './cross-boundary.js'\nimport { HOSTNAME_GATE_REFUSAL_DETAIL, parseHostnameToken } from './hostname-gate.js'\nimport type {\n ConfigFieldValue,\n ConfigFileBytes,\n ConfigFieldWriteOutcome,\n ConfigFilePublishOutcome,\n ConfigFileSet,\n ConfigFilesPortLike,\n ConfigScaffoldContentPortLike,\n ConfigStructuredValue,\n ConfigValidatePortLike,\n ConfigWritePortLike,\n} from './ports.js'\n\n/** The registry map every target op addresses. */\nconst TARGETS_PATH = 'registry.targets'\n\n/** The auth plugin declaration list `config.auth.set` appends a package to. */\nconst AUTH_PLUGINS_PATH = 'plugins.auth'\n\n/** The hooks file's top-level sequence. Read in the HOOKS file, never in the config yaml. */\nconst HOOKS_PATH = 'hooks'\n\nexport interface ConstructConfigFieldSetInput {\n /** The emitting op's bare id — becomes the payload's `action` and the envelope's `emittedBy`. */\n readonly action: string\n readonly path: string\n readonly value: ConfigFieldValue\n}\n\n/**\n * What the six config operations need (432-11 D-05/D-07): the files, the validator and the direct\n * writer that publishes the change in the call.\n */\nexport interface ConstructConfigChangeDeps {\n readonly configFiles: ConfigFilesPortLike\n readonly configValidate: ConfigValidatePortLike\n readonly configWrite: ConfigWritePortLike\n}\n\n/**\n * How a checked change is published (432-11 D-05/D-07).\n *\n * `fields` hands the change to the config transaction as field operations, so it merges onto the\n * file as it stands in its own write turn and keeps an outside edit to another field. `files`\n * publishes each changed file whole, over the digest it was built from.\n */\nexport type ConfigPublication =\n | { readonly kind: 'fields'; readonly changes: readonly ConfigChange[] }\n | { readonly kind: 'files' }\n\n/**\n * Everything steps 3 to 7 are allowed to know about the change one op decided to make.\n *\n * FACTS, NEVER PORTS, on `CrossBoundaryFacts`' own reasoning. An op has already done its reading and\n * its mutating by the time it builds one of these; what it hands over is the candidate set and a\n * per-VALUE account of what it wrote. The pipeline cannot go back and ask for more, which is what\n * keeps \"which bytes are being proposed\" a question with one answer.\n */\nexport interface ConfigMutationPlan {\n /** The emitting op's bare id. */\n readonly action: string\n /** What the change is ABOUT, for the blocked line: a config path, a target name, a hook name. */\n readonly subject: string\n /** The one-line summary an applyable proposal carries. May print values; see below. */\n readonly summaryLine: string\n /**\n * Every SCALAR this change writes, with what it replaced (D-02).\n *\n * FLATTENED TO LEAVES, because the classifier's rules are about values: an origin comparison needs\n * a URL and not the map that contains one. `flattenScalarEdits` does the flattening, so a\n * structured write is classified on everything inside it rather than on the path of its root.\n */\n readonly fieldEdits: readonly CrossBoundaryFieldEdit[]\n /** Whether this proposal ADDS a hook. STATED by the op, never inferred from a path (D-02). */\n readonly addsHook: boolean\n /** The pinned set with this change applied — every member, changed or not. */\n readonly candidate: readonly ConfigFileBytes[]\n}\n\n/**\n * The one-line summary an applied change's receipt carries.\n *\n * REFS AND VALUES, NEVER THE DIFF. The whole envelope vocabulary is map-not-territory about summary\n * lines (391 D-18), and this one keeps to it: what changed and to what, in one clause. The bytes are\n * in the change's own rendered diff.\n */\nexport function configFieldSetSummaryLine(path: string, value: ConfigFieldValue): string {\n return `set ${path} to ${typeof value === 'string' ? value : String(value)}`\n}\n\n/**\n * The BLOCKED record's line: what was attempted and why it was refused, naming the subject only.\n *\n * IT TAKES A SUBJECT RATHER THAN A PATH (395-05), because five ops answer blocked refusals and only\n * one of them addresses a config path. What every subject has in common is that it is a REFERENCE —\n * a path, a target name, a hook name — which is the same class of fact `paths` already carries.\n */\nexport function configBlockedSummaryLine(subject: string, detail: string): string {\n return `${subject} — blocked: ${detail}`\n}\n\n/**\n * Construct, validate and write a `config.field.set` change in the call (432-11).\n *\n * ANSWERS A TYPED RESULT for every ordinary outcome rather than throwing. `blocked` is a refusal\n * carrying the report, with nothing written or kept; `no-change` is a set of a value the config\n * already holds, which is neither an error nor a write.\n */\nexport async function changeConfigField(\n input: ConstructConfigFieldSetInput,\n deps: ConstructConfigChangeDeps,\n): Promise<ConfigChangeOutput> {\n // (1) CFGM-04: re-read at proposal time. Everything below is about these bytes and no others.\n const set = await deps.configFiles.read()\n const target = requireConfigFile(set)\n\n // (2) The comment-preserving edit, over exactly the bytes just read. The previous value comes back\n // from the SAME parse that wrote the new one, because (6) has to compare the two.\n const edit = await deps.configFiles.setField({\n ...(target.bytes === undefined ? {} : { bytes: target.bytes }),\n path: input.path,\n value: input.value,\n })\n\n return await publishConfigChange({\n action: input.action,\n subject: `set ${input.path}`,\n summaryLine: configFieldSetSummaryLine(input.path, input.value),\n fieldEdits: [{\n configPath: input.path,\n ...(edit.previousValue === undefined ? {} : { oldValue: edit.previousValue }),\n newValue: input.value,\n }],\n // A field set writes a config value; it does not add a hook. `config.hook.add` is its own op and\n // supplies this fact itself. Stated rather than inferred, because inferring \"a hook was added\"\n // from a path would be the per-op map D-02 refused.\n addsHook: false,\n candidate: candidateSet(set, [{ path: target.path, bytes: edit.bytes }]),\n }, {\n kind: 'fields',\n changes: [{ op: 'set', path: configSegments(input.path), value: input.value }],\n }, set, deps)\n}\n\n/**\n * Create a target in the call — and refuse a collision rather than merging one.\n *\n * A CREATE IS NEVER AN UPSERT, and this is CFGM-01's adjacency edge. `setIn` at an occupied path\n * REPLACES what is there, silently and comment-destructively: a person who asked to add a target\n * would get a proposal that quietly deleted the `environment` class, the `product` name and the\n * mobile fields of the one they already had, rendered as a diff they would have to read line by line\n * to notice. The refusal names the existing target and points at the op that edits one.\n */\nexport async function createConfigTarget(\n input: ConfigTargetCreateInput & { readonly action: string },\n deps: ConstructConfigChangeDeps,\n): Promise<ConfigChangeOutput> {\n const set = await deps.configFiles.read()\n const target = requireConfigFile(set)\n const entryPath = `${TARGETS_PATH}.${input.name}`\n\n // 2026-10-02 (quick 261002-ctr): no auth-state reference to admit. The input carried\n // `authStateName` and wrote it to `use.authState`, which the committed configuration has no key\n // for, so every such create was blocked by whole-config validation; the field is gone.\n const facts = await deps.configFiles.inspect({\n ...(target.bytes === undefined ? {} : { bytes: target.bytes }),\n paths: [entryPath, TARGETS_PATH],\n })\n if (factsFor(facts, entryPath).present) {\n return {\n outcome: 'refused',\n reason: 'target-exists',\n detail:\n `the target ${input.name} is already configured at ${entryPath}; a create never replaces an `\n + 'existing target, because doing so would silently discard every field it already holds. '\n + 'Use config.target.edit to change it.',\n candidates: [...(factsFor(facts, TARGETS_PATH).keys ?? [])],\n }\n }\n\n // THE HOUSE STYLE, AS ONE BLOCK. `demo/init/agent-qa.config.yaml` writes a web target as\n // `name: { platform, url }`, and writing it as one structured value rather than as two scalar sets\n // means one parse, one rendered block, and a diff a person reads as the addition it is. The class\n // (432 D-19) is written only when declared: undeclared stays visibly undeclared, never defaulted.\n const entry: ConfigStructuredValue = {\n platform: input.platform,\n url: input.url,\n ...(input.environment === undefined ? {} : { environment: input.environment }),\n }\n const bytes = (await deps.configFiles.setField({\n ...(target.bytes === undefined ? {} : { bytes: target.bytes }),\n path: entryPath,\n value: entry,\n })).bytes\n\n const fieldEdits: CrossBoundaryFieldEdit[] = flattenScalarEdits(entryPath, entry, undefined)\n // THE NAME MUST STILL BE FREE WHEN THE WRITE TAKES ITS TURN. The collision check above read the\n // file at the start of the call; the expect makes the transaction refuse, rather than replace, a\n // target somebody created under this name in between.\n const changes: ConfigChange[] = [\n { op: 'expect', path: configSegments(entryPath), value: null },\n { op: 'set', path: configSegments(entryPath), value: entry },\n ]\n\n return await publishConfigChange({\n action: input.action,\n subject: `create target ${input.name}`,\n summaryLine: `create ${input.platform} target ${input.name} at ${input.url}`\n + (input.environment === undefined ? '' : ` (${input.environment})`),\n fieldEdits,\n addsHook: false,\n candidate: candidateSet(set, [{ path: target.path, bytes }]),\n }, { kind: 'fields', changes }, set, deps)\n}\n\n/**\n * Edit a target in the call — and refuse an absent target by NAME.\n *\n * THE REFUSAL LISTS THE CONFIGURED NAMES (387's never-guess posture, D-15's line). An edit of a\n * target nobody configured is almost always a near-miss — `shop` for `shop-web` — and a refusal that\n * says only \"no such target\" makes the next call another guess. The names are already readable\n * through `config.get`, so listing them discloses nothing.\n */\nexport async function editConfigTarget(\n input: ConfigTargetEditInput & { readonly action: string },\n deps: ConstructConfigChangeDeps,\n): Promise<ConfigChangeOutput> {\n const set = await deps.configFiles.read()\n const target = requireConfigFile(set)\n const entryPath = `${TARGETS_PATH}.${input.name}`\n\n // 2026-10-02 (quick 261002-ctr): `changes.authStateName` is gone with the other two ops' field;\n // a url is the only change, and it is not a reference.\n const facts = await deps.configFiles.inspect({\n ...(target.bytes === undefined ? {} : { bytes: target.bytes }),\n paths: [entryPath, TARGETS_PATH],\n })\n if (!factsFor(facts, entryPath).present) {\n return {\n outcome: 'refused',\n reason: 'target-not-found',\n detail:\n `no target named ${input.name} is configured at ${TARGETS_PATH}; an edit changes a target `\n + 'that exists. Use config.target.create to add one.',\n candidates: [...(factsFor(facts, TARGETS_PATH).keys ?? [])],\n }\n }\n\n let bytes = target.bytes\n const fieldEdits: CrossBoundaryFieldEdit[] = []\n const changes: ConfigChange[] = []\n // ORDERED, AND THE ORDER IS FIXED HERE RATHER THAN BY THE INPUT'S KEY ORDER. Two calls asking for\n // the same two changes must produce the same bytes, or the diff a person reads depends on how a\n // model happened to serialise its arguments.\n for (const [path, value] of [\n [`${entryPath}.url`, input.changes.url],\n ] as const) {\n if (value === undefined) continue\n const edited = await deps.configFiles.setField({\n ...(bytes === undefined ? {} : { bytes }),\n path,\n value,\n })\n bytes = edited.bytes\n fieldEdits.push({\n configPath: path,\n ...(edited.previousValue === undefined ? {} : { oldValue: edited.previousValue }),\n newValue: value,\n })\n changes.push({ op: 'set', path: configSegments(path), value })\n }\n\n if (bytes === undefined) throw new TypeError('the config file has no bytes to edit')\n\n return await publishConfigChange({\n action: input.action,\n subject: `edit target ${input.name}`,\n summaryLine: `edit target ${input.name}: ${fieldEdits.map((edit) =>\n `${edit.configPath} to ${String(edit.newValue)}`).join(', ')}`,\n fieldEdits,\n addsHook: false,\n candidate: candidateSet(set, [{ path: target.path, bytes }]),\n }, { kind: 'fields', changes }, set, deps)\n}\n\n/**\n * Declare a target's auth plugin in the call — references only, refused on the INPUT (D-11).\n *\n * WHAT IT WRITES, AND WHERE, IS A FACT ABOUT THIS PRODUCT'S CONFIGURATION SCHEMA RATHER THAN A\n * CHOICE. The committed configuration has exactly one place that declares an auth plugin and it is\n * the `plugins.auth` sequence (`AuthPluginDeclarationSchema`: `{ package }` or `{ path }`,\n * `.strict()`). It has NO place at all for an environment variable's name, which is why\n * `envVarName` is refused rather than written — see the `unsupported-reference` arm below.\n *\n * 2026-10-02 (quick 261002-ctr): IT HAS NO PLACE FOR A STORED AUTH STATE'S BINDING EITHER. This op\n * once wrote `authStateName` to `use.authState`; `core`'s committed `UseSchema` is `.strict()` with\n * no such key (only a test's or a suite's own `use` has one), so whole-config validation answered\n * every such call `blocked / schema-fail`. The input field is deleted rather than written somewhere\n * the schema would also refuse.\n *\n * THE `target` IS RESOLVED, NEVER WRITTEN, and that is deliberate. Naming the target is what lets\n * the op refuse a declaration for a target nobody configured — a typed not-found with the configured\n * names, rather than a change that names nothing.\n */\nexport async function setConfigAuth(\n input: ConfigAuthSetInput & { readonly action: string },\n deps: ConstructConfigChangeDeps,\n): Promise<ConfigChangeOutput> {\n const set = await deps.configFiles.read()\n const target = requireConfigFile(set)\n\n // D-11 FIRST, OVER EVERY SUPPLIED REFERENCE, BEFORE THE DOCUMENT IS TOUCHED. `target` is not in\n // this list because it is never written: a credential arriving there resolves against the registry\n // and produces `target-not-found`, which discloses nothing and says something true.\n const refusal = refuseNonReferences([\n ...(input.pluginPackage === undefined\n ? []\n : [{ field: 'pluginPackage', kind: 'plugin-package' as const, value: input.pluginPackage }]),\n ...(input.envVarName === undefined\n ? []\n : [{ field: 'envVarName', kind: 'env-var-name' as const, value: input.envVarName }]),\n ])\n if (refusal !== undefined) return refusal\n\n const entryPath = `${TARGETS_PATH}.${input.target}`\n const facts = await deps.configFiles.inspect({\n ...(target.bytes === undefined ? {} : { bytes: target.bytes }),\n paths: [entryPath, TARGETS_PATH, AUTH_PLUGINS_PATH],\n })\n if (!factsFor(facts, entryPath).present) {\n return {\n outcome: 'refused',\n reason: 'target-not-found',\n detail:\n `no target named ${input.target} is configured at ${TARGETS_PATH}, so there is nothing to `\n + 'bind an auth state to. Use config.target.create to add one first.',\n candidates: [...(factsFor(facts, TARGETS_PATH).keys ?? [])],\n }\n }\n\n // AFTER THE REFERENCE CHECK, DELIBERATELY. A value that is not shaped like a variable name is\n // answered as refs-only first, because that is the fact the person needs.\n if (input.envVarName !== undefined) {\n return {\n outcome: 'refused',\n reason: 'unsupported-reference',\n detail:\n 'this configuration schema has no field that records an environment variable\\'s name: an '\n + 'auth plugin declaration is a package or a path and nothing else. The plugin reads the '\n + 'variable from the environment it runs in, and no config change is needed to point at it.',\n }\n }\n\n let bytes = target.bytes\n const fieldEdits: CrossBoundaryFieldEdit[] = []\n const changes: ConfigChange[] = []\n\n if (input.pluginPackage !== undefined) {\n // APPENDED PAST THE END, AT A LENGTH THE DOCUMENT ITSELF REPORTED. Writing at a fixed index\n // would overwrite a declaration that is already there; writing the whole sequence back would\n // discard the ones this call did not mention.\n const declaration: ConfigStructuredValue = { package: input.pluginPackage }\n const existing = factsFor(facts, AUTH_PLUGINS_PATH)\n const at = existing.length ?? 0\n const appended = await deps.configFiles.setField({\n ...(bytes === undefined ? {} : { bytes }),\n path: existing.present ? `${AUTH_PLUGINS_PATH}.${at}` : AUTH_PLUGINS_PATH,\n value: existing.present ? declaration : [declaration],\n })\n bytes = appended.bytes\n fieldEdits.push(...flattenScalarEdits(`${AUTH_PLUGINS_PATH}.${at}`, declaration, undefined))\n // AN APPEND IN THE WRITE'S OWN TURN, so a declaration somebody added meanwhile is kept and this\n // one lands after it rather than over it.\n changes.push({ op: 'append', path: configSegments(AUTH_PLUGINS_PATH), value: declaration })\n }\n\n if (bytes === undefined) throw new TypeError('the config file has no bytes to edit')\n\n return await publishConfigChange({\n action: input.action,\n subject: `bind auth for target ${input.target}`,\n summaryLine: `bind auth for target ${input.target}: ${fieldEdits.map((edit) =>\n `${edit.configPath} to ${String(edit.newValue)}`).join(', ')}`,\n fieldEdits,\n addsHook: false,\n candidate: candidateSet(set, [{ path: target.path, bytes }]),\n }, { kind: 'fields', changes }, set, deps)\n}\n\n/**\n * Add a hook in the call — the one action that writes a file other than the config.\n *\n * A HOOK IS CODE THIS PROJECT WILL RUN, which is why `addsHook` is STATED here rather than inferred\n * from a path (D-02) and why every hook addition is cross-boundary regardless of what it contains.\n * The flag raises the `hook-added` cross-boundary reason on the applied receipt. (2026-10-03: the\n * grant machinery that refused on it is deleted.)\n *\n * THE ID IS MINTED BY THE HOST, NEVER FORMATTED HERE. `core`'s `HookDefinitionSchema` refuses any id\n * `isCanonicalHookId` does not accept, and that mint lives in a package this layer may not import\n * and draws randomness this layer may not read. A hand-built `h_`-prefixed string would parse as a\n * string, reach a person's repository, and be refused at the next run rather than at the proposal.\n *\n * THE APPEND IS PAST THE END OF WHAT THE DOCUMENT REPORTS, and a project with no hooks file at all\n * gets one created — which is the whole-new-file case publication already handles, arriving before\n * 395-08's scaffold needs it.\n */\nexport async function addConfigHook(\n input: ConfigHookAddInput & { readonly action: string },\n deps: ConstructConfigChangeDeps,\n): Promise<ConfigChangeOutput> {\n const set = await deps.configFiles.read()\n const hooksMember = set.files.find((file) => file.path === set.hooksFile)\n if (hooksMember === undefined) {\n throw new TypeError(\n `the config file set names ${JSON.stringify(set.hooksFile)} as its hooks file, but the set `\n + 'does not contain it — a set that cannot see its own hooks file cannot declare a hook',\n )\n }\n\n const facts = await deps.configFiles.inspect({\n ...(hooksMember.bytes === undefined ? {} : { bytes: hooksMember.bytes }),\n paths: [HOOKS_PATH],\n })\n const existing = factsFor(facts, HOOKS_PATH)\n const at = existing.length ?? 0\n\n const entry: ConfigStructuredValue = {\n id: deps.configFiles.mintHookId(),\n name: input.name,\n runtime: input.runtime,\n file: input.file,\n timeout: input.timeout ?? DEFAULT_HOOK_TIMEOUT,\n ...(input.network === undefined ? {} : { network: input.network }),\n }\n const written = await deps.configFiles.setField({\n ...(hooksMember.bytes === undefined ? {} : { bytes: hooksMember.bytes }),\n path: existing.present ? `${HOOKS_PATH}.${at}` : HOOKS_PATH,\n value: existing.present ? entry : [entry],\n })\n\n // THE HOOKS FILE IS PUBLISHED WHOLE, over the digest of the bytes it was built from. It is not\n // the config yaml, so the config transaction cannot merge it; a hooks file somebody edited since\n // this call read it refuses the write instead.\n return await publishConfigChange({\n action: input.action,\n subject: `add hook ${input.name}`,\n summaryLine: `add ${input.runtime} hook ${input.name} running ${input.file}`,\n fieldEdits: flattenScalarEdits(`${HOOKS_PATH}.${at}`, entry, undefined),\n // STATED, NOT INFERRED (D-02). This is the op that adds hooks; nothing has to guess.\n addsHook: true,\n candidate: candidateSet(set, [{ path: hooksMember.path, bytes: written.bytes }]),\n }, { kind: 'files' }, set, deps)\n}\n\n/**\n * Everything `config.project.scaffold` needs beyond what every other action needs (395-08, D-04).\n *\n * A SEPARATE TYPE: the scaffold is the only action that renders content it did not compute from\n * the committed file, so widening the shared bundle would make six ops bind a port none of them can\n * reach.\n */\nexport interface ConstructConfigScaffoldDeps extends ConstructConfigChangeDeps {\n readonly scaffoldContent: ConfigScaffoldContentPortLike\n}\n\n/**\n * Configure a project from zero, in ONE call (D-04/D-13/D-15 · CFGM-05; 432-11 D-05/D-07).\n *\n * EVERY FILE IS PUBLISHED WHOLE, AND EVERY ONE IS CHECKED FIRST. The config, the hooks file and the\n * managed `.gitignore` block each carry the digest of the bytes this call read (or the fact that\n * the file was absent), and the direct writer checks all of them before it writes any. A file that\n * changes after that check stops the publication at that file: the answer names the files already\n * written, the one that refused and the ones never reached, and nothing is rolled back.\n *\n * THE GATE RUNS FIRST AND IT IS THE SECURITY PROPERTY (D-15). Nothing below is reached by a token\n * that is not a hostname, and the refusal names both continuations rather than a candidate. The\n * derivation the gate returns is the ONLY source of the target name and the base URL — this\n * function computes neither — so \"the LLM never invents an origin\" is a statement about which\n * function produced the bytes rather than about how the model was asked.\n *\n * A CONFIGURATION THIS SCAFFOLD WOULD OVERWRITE IS A REFUSAL — AND THAT IS DECLARED TARGETS, NEVER\n * A FILE'S EXISTENCE (395-12, narrowed · SC-5's entry point). The refusal protects a person's\n * configuration from being replaced wholesale, and what this op writes is the target registry. A\n * config file that declares NO targets has nothing here to overwrite, so it is MERGED: exactly\n * `registry.targets.<name>` is inserted into the person's own bytes and no other byte of that file\n * moves. The declared-target set arrives as a STRUCTURAL fact from the inspect port — names, never\n * values — for the reason this package parses no yaml at all.\n *\n * WHY THE OLD PREDICATE WAS A PINCER RATHER THAN A GUARD, recorded because the narrowing only reads\n * as safe against it. `resolveCliChatCapabilities` reads the chat model out of `registry.llms`,\n * which lives in the config file — so the only project that can reach this op through a chat turn\n * is a project that HAS a config file, which is precisely the project the file-existence predicate\n * refused. The two conditions closed on each other and CFGM-05's sentence could not complete for\n * any project at all (WINDOWS 132's two jaws, both reproduced live by 395-VERIFICATION). Under the\n * narrowing the serving class is every project that can chat: a model, no targets, one inserted\n * entry. A project with no model anywhere still cannot chat about anything, which is WINDOWS\n * 130/133's parked question about model resolution and not a config-mutation defect.\n *\n * `config.target.create` REMAINS THE OP for adding a target to a project that already declares one,\n * and the refusal still names it — now naming the targets it will not replace, so a person reads\n * WHICH configuration is standing in the way rather than merely that one is.\n *\n * IT IS ALWAYS CROSS-BOUNDARY, AND THAT IS COMPUTED RATHER THAN ASSERTED (D-14/D-02). The scaffold\n * writes a base URL where the committed configuration had none, so `computeCrossBoundary` sees an\n * edit whose old value is absent and whose new value is an origin — and it adds a hooks file and a\n * config file that did not exist. The flag is read off the classifier the same way every other\n * proposal's is; nothing here sets it by hand. 395-07's two-sided enforcement then makes a scaffold\n * unsatisfiable by any standing grant, from either side.\n *\n * `UnrenderableConfigDiffError` IS CAUGHT HERE AND NOWHERE ELSE, and the scope is the argument.\n * 395-02 minted that refusal for the case where two byte sequences decode identically and the diff\n * renders as a blank page; every other op composes bytes it authored from a file it just read, and\n * this is the one that folds a project's EXISTING `.gitignore` — arbitrary bytes, from a file this\n * product does not own — into a file it proposes. Answering it as a typed `refused` rather than\n * letting it escape as a fault is the difference between \"this project's .gitignore is not text I\n * can show you a diff of\" and a stack trace in a chat turn.\n */\nexport async function scaffoldConfigProject(\n input: ConfigProjectScaffoldInput & { readonly action: string },\n deps: ConstructConfigScaffoldDeps,\n): Promise<ConfigChangeOutput> {\n const verdict = parseHostnameToken(input.domain)\n if (verdict.kind === 'not-a-hostname') {\n return { outcome: 'refused', reason: 'not-a-hostname', detail: HOSTNAME_GATE_REFUSAL_DETAIL }\n }\n\n // (1) CFGM-04: the re-read, exactly as every other action does it.\n const set = await deps.configFiles.read()\n const existingConfig = requireConfigFile(set)\n\n // THE PREDICATE, NARROWED (395-12). A config file with no `registry.targets` entries declares\n // nothing this op would replace, so its existence alone is not a refusal. `inspect` answers the\n // MAP's keys — names only, never values — which is the same structural read `config.target.create`\n // already takes to list the names its own refusal offers.\n const declaredTargets = existingConfig.bytes === undefined\n ? []\n : factsFor(\n await deps.configFiles.inspect({ bytes: existingConfig.bytes, paths: [TARGETS_PATH] }),\n TARGETS_PATH,\n ).keys ?? []\n if (declaredTargets.length > 0) {\n return {\n outcome: 'refused',\n reason: 'already-configured',\n detail:\n `this project already configures ${declaredTargets.join(', ')} in ${existingConfig.path}, `\n + 'and scaffolding writes a whole target registry — it would replace what is there. Use '\n + `config.target.create to add ${verdict.targetName} to the configuration you already have.`,\n candidates: [...declaredTargets],\n }\n }\n\n const gitignore = set.files.find((file) => file.path === CONFIG_SET_GITIGNORE)\n // THE ROUND TRIP IS CHECKED BEFORE THE DECODE IS USED. The block is composed as TEXT, so a\n // `.gitignore` carrying bytes utf-8 does not round-trip would come back with every one of them\n // replaced by U+FFFD — a proposal that silently rewrote a file it was only supposed to append to.\n // Refused rather than repaired: this product did not author those bytes.\n if (gitignore?.bytes !== undefined && !bytesEqual(utf8Encode(utf8Decode(gitignore.bytes)), gitignore.bytes)) {\n return {\n outcome: 'refused',\n reason: 'unrenderable-diff',\n detail:\n `${gitignore.path} holds bytes that are not valid UTF-8, so appending the managed block to `\n + 'it would rewrite parts of the file you did not ask to change. Nothing has been written.',\n }\n }\n\n // WHETHER THIS SCAFFOLD ADDS A HOOKS FILE IS A FACT ABOUT THE SET, not a constant. From zero it\n // always does; merging into a project that already has one, it must not — and `addsHook` is\n // STATED by the op (D-02), so it has to stop being stated when no hook is added or the classifier\n // would flag `hook-added` for a file nobody touched.\n const hooksMember = set.files.find((file) => file.path === set.hooksFile)\n const addsHook = hooksMember?.bytes === undefined\n\n const rendered = await deps.scaffoldContent.render({\n targetName: verdict.targetName,\n baseUrl: verdict.baseUrl,\n ...(gitignore?.bytes === undefined ? {} : { existingGitignore: gitignore.bytes }),\n // MERGE MODE, AND ONLY WHEN THERE ARE BYTES TO MERGE INTO. Absent here is the from-zero road,\n // whose rendered bytes are byte-identical to what 395-08 shipped and what the goldens pin.\n ...(existingConfig.bytes === undefined\n ? {}\n : {\n existingConfig: {\n path: existingConfig.path,\n bytes: existingConfig.bytes,\n hooksPath: set.hooksFile,\n hooksPresent: !addsHook,\n },\n }),\n })\n\n try {\n return await publishConfigChange({\n action: input.action,\n subject: `scaffold ${verdict.targetName}`,\n summaryLine: `configure this project for ${verdict.baseUrl} as target ${verdict.targetName}`,\n // THE DERIVED VALUES, AS THE EDITS THEY ARE. The classifier compares each against what the\n // committed configuration held — nothing, because there is no committed configuration — which\n // is what makes `new-origin` a computed verdict here rather than a constant this op asserts.\n fieldEdits: [\n { configPath: `${TARGETS_PATH}.${verdict.targetName}.platform`, newValue: 'web' },\n { configPath: `${TARGETS_PATH}.${verdict.targetName}.url`, newValue: verdict.baseUrl },\n ],\n // The scaffolded hooks file declares one hook, which is code this project would then run.\n // Stated by the op, as D-02 requires, and true exactly when the file did not exist a moment\n // ago — see `addsHook`'s derivation above.\n addsHook,\n candidate: candidateSet(set, [...rendered]),\n }, { kind: 'files' }, set, deps)\n } catch (error) {\n if (!(error instanceof UnrenderableConfigDiffError)) throw error\n return {\n outcome: 'refused',\n reason: 'unrenderable-diff',\n detail:\n `the bytes for ${error.paths.join(', ')} differ from what is on disk, but the diff of them `\n + 'renders as nothing a person could read. Nothing has been written.',\n }\n }\n}\n\n/**\n * What a hook's timeout is when the caller does not say.\n *\n * PINNED, WITH A RETUNE NOTE (386 D-15). `HookDefinitionSchema` makes `timeout` REQUIRED — there is\n * no schema default to inherit — so an op whose DTO marks it optional must supply one, and the\n * alternative to a pinned value is refusing every hook whose duration the caller did not think\n * about. `30s` is what `demo/init/hooks.yaml` writes. RETUNE: owned by whoever owns the hooks\n * vocabulary; a person who wants a different one writes it in the action, and a person who disagrees\n * with the default edits their hooks file, which is one reviewable diff away either way.\n */\nconst DEFAULT_HOOK_TIMEOUT = '30s'\n\n/**\n * D-11's refusal, fired on the INPUT and before anything is mutated (395-05).\n *\n * SCHEMA VALIDATION OF A REFERENCE FIELD, NOT SECRET DETECTION (441 D-15/D-23).\n * `isLegalConfigReference` states what a reference IS and refuses the complement, so the rule names\n * nothing it refuses: no detector, no key-name rule and no credential shape.\n *\n * THE DETAIL DOES NOT QUOTE THE VALUE. The field is named, the law is named, and where a secret\n * belongs is named.\n */\nfunction refuseNonReferences(\n entries: readonly { field: string; kind: ConfigReferenceKind; value: string }[],\n): ConfigChangeOutput | undefined {\n for (const entry of entries) {\n if (isLegalConfigReference(entry.kind, entry.value)) continue\n return {\n outcome: 'refused',\n reason: 'refs-only',\n detail:\n `the value supplied for ${entry.field} is not shaped like a ${entry.kind}. `\n + REFS_ONLY_LAW,\n }\n }\n\n return undefined\n}\n\n/** One sentence, spelled once, so five refusals cannot state the law four different ways. */\nconst REFS_ONLY_LAW =\n 'This configuration records REFERENCES only — the name of an auth state, of a plugin package, of '\n + 'an environment variable — and never a credential, which is what keeps the committed '\n + 'configuration safe to read. Put the secret in '\n + 'the secrets file the configuration names at workspace.secretsFile and pass its NAME here.'\n\n/** What the blocked report says, before it is answered as a refusal. */\ninterface BlockedReport {\n readonly blockedReason: ConfigBlockedReason\n readonly detail: string\n readonly paths: readonly string[]\n readonly validationIssues?: readonly string[]\n}\n\n/** A candidate that passed validation, with everything publication needs. */\ninterface CheckedCandidate {\n readonly rendered: ConfigDiffChanged\n readonly files: readonly (ConfigChangeFile & { readonly bytes: Uint8Array })[]\n readonly crossBoundary: boolean\n readonly crossBoundaryReasons: readonly CrossBoundaryReason[]\n}\n\ntype CandidateCheck =\n | { readonly kind: 'no-change' }\n | { readonly kind: 'blocked'; readonly report: BlockedReport }\n | { readonly kind: 'ready'; readonly checked: CheckedCandidate }\n\n/**\n * Steps 3 to 5, for every action (395-05): render, validate, classify.\n *\n * WHAT ARRIVES IS A CANDIDATE SET, NOT A FILE. `renderConfigDiff` is handed exactly the members\n * whose bytes differ, so a change's `files` list is a statement about what changed rather than\n * about which files were considered — and the digests recorded per file are the ones publication\n * re-checks. Step 6 is the caller's: the six config operations publish (432-11).\n */\nasync function checkConfigCandidate(\n plan: ConfigMutationPlan,\n set: ConfigFileSet,\n deps: { readonly configValidate: ConfigValidatePortLike },\n): Promise<CandidateCheck> {\n const committed = new Map(set.files.map((file) => [file.path, file]))\n const diffInput: ConfigDiffFileInput[] = []\n for (const member of plan.candidate) {\n if (member.bytes === undefined) continue\n const before = committed.get(member.path)?.bytes\n if (before !== undefined && bytesEqual(before, member.bytes)) continue\n diffInput.push({\n path: member.path,\n ...(before === undefined ? {} : { oldBytes: before }),\n newBytes: member.bytes,\n })\n }\n if (diffInput.length === 0) return { kind: 'no-change' }\n\n // (3) THE ONE PRIMITIVE. Publication re-checks the digests it records here (D-17/D-19).\n const rendered = renderConfigDiff(diffInput)\n\n // 395-02: THE PRIMITIVE IS THE AUTHORITY ON WHETHER ANYTHING CHANGED, and this narrowing is where\n // that authority is taken. The byte comparison above answers the same question earlier and more\n // cheaply — which is why it stays: it lets a set of a value the config already holds skip the\n // whole rest of the pipeline — but the answer that reaches a person comes from the same function\n // that renders the diff, so the two halves cannot disagree about what \"no change\" means.\n if (rendered.outcome === 'unchanged') return { kind: 'no-change' }\n\n const digestsByPath = new Map(rendered.perFileDigests.map((digest) => [digest.path, digest]))\n\n // (4) CFGM-01: the WHOLE candidate SET. The validator's own words are answered as they are; each\n // door masks the declared values in what it shows.\n const validation = await deps.configValidate.validate({\n configFile: set.configFile,\n hooksFile: set.hooksFile,\n files: plan.candidate,\n })\n if (!validation.ok) {\n // WR-11: THE REPORT NAMES THE FILE THE ISSUE IS ABOUT, unioned with the files this change\n // diffed. Both halves are kept: the diffed paths say what was being changed, the implicated\n // ones say where to look.\n const implicated = validation.issues.map((issue) => issue.path)\n return {\n kind: 'blocked',\n report: {\n blockedReason: 'schema-fail',\n detail: 'the resulting configuration is not valid',\n paths: [...new Set([...implicated, ...diffInput.map((file) => file.path)])],\n // Non-empty by contract; a validator that refused without saying why would leave a person\n // with nothing to act on, so an empty list is turned into the one honest sentence available.\n validationIssues: validation.issues.length > 0\n ? validation.issues.map((issue) => `${issue.path}: ${issue.message}`)\n : ['the configuration was refused by whole-config validation, which reported no detail'],\n },\n }\n }\n\n const files = rendered.changes.map((change) => {\n const digests = digestsByPath.get(change.path)\n const bytes = plan.candidate.find((member) => member.path === change.path)?.bytes\n if (digests === undefined || bytes === undefined) {\n throw new TypeError('the diff primitive rendered a file the candidate set does not contain')\n }\n return {\n path: change.path,\n changeKind: change.changeKind,\n ...(digests.oldDigest === undefined ? {} : { baseDigest: digests.oldDigest }),\n newContentBase64: base64Encode(bytes),\n bytes,\n }\n })\n\n // (5) D-02, PER VALUE. The classifier compares the value each edit wrote against the one it\n // replaced, and reads the pinned file set from the PORT'S OWN enumeration rather than a second\n // list — `set.files` is what `enumerateConfigFileSet` answered for this workspace, so the\n // out-of-set rule and the writer's scope cannot disagree about which files are config.\n const classified = computeCrossBoundary({\n fieldEdits: plan.fieldEdits,\n addsHook: plan.addsHook,\n filesTouched: files.map((file) => file.path),\n pinnedFileSet: set.files.map((file) => file.path),\n })\n\n return {\n kind: 'ready',\n checked: {\n rendered,\n files,\n crossBoundary: classified.crossBoundary,\n crossBoundaryReasons: [...classified.reasons],\n },\n }\n}\n\n/**\n * Step 6 for the six config operations: publish in the call (432-11 D-05/D-07).\n *\n * A BLOCKED CHANGE IS ANSWERED AND NOTHING IS KEPT. The report carries no diff and no content, and\n * nothing reaches a store or the writer. A clean change goes to the direct writer: field changes\n * through the config transaction, whole files over their digests. The answer is what the writer\n * reports — the files it wrote, a refusal that wrote nothing, or the exact point a multi-file\n * publication stopped at.\n */\nasync function publishConfigChange(\n plan: ConfigMutationPlan,\n publication: ConfigPublication,\n set: ConfigFileSet,\n deps: ConstructConfigChangeDeps,\n): Promise<ConfigChangeOutput> {\n const check = await checkConfigCandidate(plan, set, deps)\n if (check.kind === 'no-change') return { outcome: 'no-change', path: plan.subject }\n if (check.kind === 'blocked') return blockedAnswer(plan, check.report)\n\n const { checked } = check\n const applied = (files: readonly string[]): ConfigChangeOutput => ({\n outcome: 'applied',\n summaryLine: plan.summaryLine,\n files: [...files],\n fields: [...new Set(plan.fieldEdits.map((edit) => edit.configPath))],\n crossBoundary: checked.crossBoundary,\n crossBoundaryReasons: [...checked.crossBoundaryReasons],\n shownDiff: utf8Decode(checked.rendered.diffBytes),\n })\n\n if (publication.kind === 'fields') {\n // FIELD CHANGES REACH ONLY THE CONFIG FILE. A candidate that changed any other member cannot be\n // expressed as config-field operations, and publishing half of it would be a silent drop.\n const stray = checked.files.find((file) => file.path !== set.configFile)\n if (stray !== undefined) {\n throw new TypeError(\n `${plan.action} changed ${stray.path}, which a config field change cannot write`,\n )\n }\n const outcome = await deps.configWrite.applyFields({ changes: publication.changes })\n return outcome.kind === 'applied' ? applied([outcome.file]) : fieldWriteRefusal(outcome)\n }\n\n const outcome = await deps.configWrite.publishFiles({\n files: checked.files.map((file) => ({\n path: file.path,\n ...(file.baseDigest === undefined ? {} : { baseDigest: file.baseDigest }),\n bytes: file.bytes,\n })),\n })\n switch (outcome.kind) {\n case 'published':\n return applied(outcome.written)\n case 'refused':\n return fileWriteRefusal(outcome)\n case 'interrupted':\n return interruptedAnswer(plan, outcome)\n }\n}\n\n/** The blocked report as the direct answer: the report, never the change, and no record. */\nfunction blockedAnswer(plan: ConfigMutationPlan, report: BlockedReport): ConfigChangeOutput {\n return {\n outcome: 'blocked',\n summaryLine: configBlockedSummaryLine(plan.subject, report.detail),\n blockedReason: report.blockedReason,\n paths: [...report.paths],\n ...(report.validationIssues === undefined\n ? {}\n : { validationIssues: [...report.validationIssues] }),\n }\n}\n\n/** Why the config transaction refused, in words that name no value. */\nconst FIELD_WRITE_REFUSAL_WORDS: Readonly<Record<\n Exclude<Extract<ConfigFieldWriteOutcome, { kind: 'refused' }>['error'], 'field_changed'>,\n string\n>> = {\n invalid_write_input: 'the change set is malformed',\n file_invalid: 'the file is not readable as YAML',\n path_not_found: 'a path the change names no longer resolves',\n validation_failed: 'the configuration it would produce is not valid',\n path_not_writable: 'a path the change names cannot be written',\n marker_written_back:\n 'a value or path the change names holds [secret:<name>], the way a declared secret is shown, '\n + 'so it was not written; edit the config file directly instead, without copying the marker',\n}\n\nfunction fieldWriteRefusal(\n outcome: Extract<ConfigFieldWriteOutcome, { kind: 'refused' }>,\n): ConfigChangeOutput {\n if (outcome.error === 'field_changed') {\n const field = (outcome.path ?? [])\n .map((segment) => (typeof segment === 'object' ? segment.name : String(segment)))\n .join('.')\n return {\n outcome: 'refused',\n reason: 'field-changed',\n detail:\n `${field === '' ? 'a field this change depends on' : field} changed in ${outcome.file} after `\n + 'this call read it, so nothing was written. Read the configuration again and ask again.',\n }\n }\n const at = outcome.issues === undefined || outcome.issues.length === 0\n ? ''\n : ` (at ${outcome.issues.map((issue) => issue.path.join('.')).join(', ')})`\n return {\n outcome: 'refused',\n reason: 'write-refused',\n detail:\n `${outcome.file} refused this change as it now stands: ${FIELD_WRITE_REFUSAL_WORDS[outcome.error]}`\n + `${at}, so nothing was written.`,\n }\n}\n\nfunction fileWriteRefusal(\n outcome: Extract<ConfigFilePublishOutcome, { kind: 'refused' }>,\n): ConfigChangeOutput {\n const file = outcome.path ?? 'a file of this change'\n if (outcome.reason === 'file-changed') {\n return {\n outcome: 'refused',\n reason: 'file-changed',\n detail:\n `${file} changed after this call read it, so nothing was written. Read the configuration `\n + 'again and ask again.',\n }\n }\n // 441 GAP3-D5: the fields arm's marker_written_back answer, for a whole file.\n if (outcome.reason === 'marker_written_back') {\n return {\n outcome: 'refused',\n reason: 'write-refused',\n detail:\n `${file} refused this change as it now stands: `\n + `${FIELD_WRITE_REFUSAL_WORDS.marker_written_back}, so nothing was written.`,\n }\n }\n const words = {\n 'no-files': 'there was no file to write',\n 'outside-workspace': `${file} is outside the workspace`,\n 'duplicate-path': `${file} is named twice`,\n }[outcome.reason]\n return {\n outcome: 'refused',\n reason: 'write-refused',\n detail: `${words}, so nothing was written.`,\n }\n}\n\nfunction interruptedAnswer(\n plan: ConfigMutationPlan,\n outcome: Extract<ConfigFilePublishOutcome, { kind: 'interrupted' }>,\n): ConfigChangeOutput {\n const written = outcome.written.length === 0 ? 'nothing' : outcome.written.join(', ')\n const unwritten = outcome.unwritten.length === 0 ? 'no other file' : outcome.unwritten.join(', ')\n const stopped = outcome.failed.reason === 'file-changed'\n ? 'changed after this call read it'\n : 'could not be written'\n return {\n outcome: 'interrupted',\n summaryLine: plan.summaryLine,\n written: [...outcome.written],\n failed: { path: outcome.failed.path, reason: outcome.failed.reason },\n unwritten: [...outcome.unwritten],\n detail:\n `wrote ${written}, then stopped: ${outcome.failed.path} ${stopped}, and ${unwritten} was not `\n + 'reached. Nothing was rolled back; the written files hold the new bytes.',\n }\n}\n\n/** The config yaml, or the one refusal a set that cannot see its own config file deserves. */\nfunction requireConfigFile(set: ConfigFileSet): ConfigFileBytes {\n const target = set.files.find((file) => file.path === set.configFile)\n if (target === undefined) {\n throw new TypeError(\n `the config file set names ${JSON.stringify(set.configFile)} as its config file, but the set `\n + `does not contain it — a set that cannot see its own config file cannot be edited`,\n )\n }\n return target\n}\n\n/** The pinned set with the given members' bytes replaced — every other member carried through. */\nfunction candidateSet(\n set: ConfigFileSet,\n writes: readonly { path: string; bytes: Uint8Array }[],\n): readonly ConfigFileBytes[] {\n const written = new Map(writes.map((write) => [write.path, write.bytes]))\n const merged = set.files.map((file) => {\n const bytes = written.get(file.path)\n return bytes === undefined ? file : { path: file.path, bytes }\n })\n // A write to a path the set does not enumerate stays in the candidate rather than being dropped:\n // the classifier's `out-of-set-path` rule exists to FLAG that case, and a member silently removed\n // here would be a change nobody could flag because nobody could see it.\n for (const write of writes) {\n if (merged.some((file) => file.path === write.path)) continue\n merged.push({ path: write.path, bytes: write.bytes })\n }\n return merged\n}\n\n/**\n * Every scalar leaf a structured write puts into the document, as per-value classifier edits.\n *\n * THE CLASSIFIER'S RULES ARE ABOUT VALUES, so a structured write has to be taken apart before it can\n * be classified: an origin comparison needs the URL string, not the map that contains it, and a\n * secret-adjacency test on the map's root path answers a different question than one on each leaf.\n * Flattening here rather than in each op is what stops four ops from having four ideas about which\n * of their values are worth classifying.\n */\nfunction flattenScalarEdits(\n basePath: string,\n value: ConfigStructuredValue,\n oldValue: ConfigFieldValue | undefined,\n): CrossBoundaryFieldEdit[] {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return [{\n configPath: basePath,\n ...(oldValue === undefined ? {} : { oldValue }),\n newValue: value,\n }]\n }\n if (Array.isArray(value)) {\n return (value as readonly ConfigStructuredValue[]).flatMap((item, index) =>\n flattenScalarEdits(`${basePath}.${index}`, item, undefined))\n }\n return Object.entries(value as { readonly [key: string]: ConfigStructuredValue })\n .flatMap(([key, item]) => flattenScalarEdits(`${basePath}.${key}`, item, undefined))\n}\n\n/**\n * A dotted config path as the config transaction's segments, split exactly as the yaml edit above\n * splits it, so the construction and the publication address the same field.\n */\nfunction configSegments(path: string): string[] {\n return path.split('.')\n}\n\n/** One path's facts out of the port's answer, by NAME — never by the index a caller assumed. */\nfunction factsFor(\n facts: readonly { path: string; present: boolean; keys?: readonly string[]; length?: number }[],\n path: string,\n): { present: boolean; keys?: readonly string[]; length?: number } {\n return facts.find((fact) => fact.path === path) ?? { present: false }\n}\n\nfunction bytesEqual(left: Uint8Array, right: Uint8Array): boolean {\n if (left.length !== right.length) return false\n for (let index = 0; index < left.length; index++) {\n if (left[index] !== right[index]) return false\n }\n return true\n}\n","// The per-VALUE cross-boundary classifier (Phase 395-04, D-02 · CFGM-01).\n//\n// PER VALUE, NOT PER OP, AND THAT IS THE WHOLE DECISION. D-02 put this flag on the PROPOSAL because\n// a static map from op ids to answers cannot see the case that matters: `config.field.set` on\n// `registry.targets.shop.url` is an innocuous edit when the origin stays the same and a change of\n// which machine this product will drive when it does not. The same op, the same path, two different\n// answers — decided by the VALUES, which is the only place the difference exists.\n//\n// CLOSED REASONS, AND NOTHING ELSE MAY BE INVENTED. The output is constrained to\n// `CROSS_BOUNDARY_REASONS`, the closed vocabulary `schema` owns, because the grant machinery refuses\n// on these words and every surface renders them: a fifth class invented here would read fine in an\n// inbox and match nothing on the enforcement side. (2026-10-03, quick 261003-cpv: six reasons now,\n// with the two production members; the vocabulary is still schema's.)\n//\n// WHOLE-INPUT BY CONSTRUCTION (D-03). Nothing here is a whitelist of settable fields, and the two\n// rules that could most easily have become one are deliberately not:\n//\n// - secret-adjacency is `isSecretAdjacentConfigField`, which is SHIPPED BESIDE THE CONSTANT it\n// reads and matches subtree roots in both directions. It is imported rather than re-derived: a\n// second spelling of that rule is a second judgement, and 395-02 already measured that the\n// easy-to-miss direction (an edit ABOVE a root, which replaces the whole subtree) is the one\n// that lets the WIDEST edit through unflagged.\n// - new-origin is decided by PARSING BOTH VALUES, never by matching the path against a list of\n// url-ish names. A config that grows a second URL-valued field next year is covered on the day\n// it is added, which a name list would not be. The cost is stated: a value that parses as an\n// absolute URL and is not one gets an origin comparison it did not need, which can only ever\n// flag MORE, and flagging more asks a person a question they can answer in one word.\n//\n// ABSENT-TO-PRESENT IS A NEW ORIGIN. A target that had no URL and now has one is not \"unchanged\n// origin\"; it is the first origin, which is exactly the fresh ask D-14 says scaffolding a target\n// deserves.\n\nimport {\n CROSS_BOUNDARY_REASONS,\n isSecretAdjacentConfigField,\n} from '@vostride/agent-qa-schema'\nimport type { CrossBoundaryReason } from '@vostride/agent-qa-schema'\n\nimport type { ConfigFieldValue } from './ports.js'\n\n// 2026-10-03 (quick 261003-cpv, 432 review WR-01/WR-10): the production declaration (D-18). Only the\n// loosening direction is named; turning the opt-in off or declaring a target production tightens.\nconst ALLOW_PRODUCTION_PATH = 'allowProduction'\nconst TARGET_ENVIRONMENT_PATH = /^registry\\.targets\\.[^.]+\\.environment$/\n\n/** One field this proposal edits, with the value it replaces — both sides, or the rule is blind. */\nexport interface CrossBoundaryFieldEdit {\n readonly configPath: string\n /** Absent means the path held no scalar before the edit. See `ConfigFieldSetResult`. */\n readonly oldValue?: ConfigFieldValue\n readonly newValue: ConfigFieldValue\n}\n\n/**\n * Everything the classifier is allowed to know. A record of FACTS, never of ports.\n *\n * `pinnedFileSet` ARRIVES AS AN ARGUMENT rather than being enumerated here, and the enumeration it\n * arrives from is `schema`'s `enumerateConfigFileSet` — the same one the host's config-files port\n * reads bytes for and 395-06's porcelain check scopes to. One enumeration, three consumers: a copy\n * here would fail in the permissive direction, silently, the day the set grew a member.\n */\nexport interface CrossBoundaryFacts {\n readonly fieldEdits: readonly CrossBoundaryFieldEdit[]\n /** Whether this proposal ADDS a hook — code this project will execute. Never inferred from a path. */\n readonly addsHook: boolean\n /** Workspace-relative paths this proposal would write. */\n readonly filesTouched: readonly string[]\n /** The pinned config file set, as `enumerateConfigFileSet` answered it for this workspace. */\n readonly pinnedFileSet: readonly string[]\n}\n\nexport interface CrossBoundaryVerdict {\n readonly crossBoundary: boolean\n readonly reasons: readonly CrossBoundaryReason[]\n}\n\n/**\n * The origin of a value, or `undefined` when the value is not an absolute URL.\n *\n * SCHEME, HOST AND PORT — the three facts that decide whether traffic goes somewhere else. A path\n * change under one origin is an ordinary edit; `http` → `https` on one host is NOT, because the two\n * are different origins by every definition that matters and one of them is a downgrade.\n *\n * `URL` normalises the default port away on its own (`https://x:443` and `https://x` are one\n * origin), which is the behaviour wanted here: a person asked to re-approve a redundant port\n * spelling would learn to answer without reading.\n */\nfunction originOf(value: ConfigFieldValue | undefined): string | undefined {\n if (typeof value !== 'string') return undefined\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n return undefined\n }\n if (parsed.host === '') return undefined\n return `${parsed.protocol}//${parsed.host}`\n}\n\n/**\n * Classify one proposal's cross-boundary-ness from its actual values (D-02).\n *\n * REASONS COME BACK IN `CROSS_BOUNDARY_REASONS` ORDER AND WITHOUT DUPLICATES, so two proposals that\n * cross the same boundaries render and compare identically regardless of the order a caller happened\n * to enumerate its edits in. Ordering that follows the input is ordering a caller can perturb.\n */\nexport function computeCrossBoundary(facts: CrossBoundaryFacts): CrossBoundaryVerdict {\n const found = new Set<CrossBoundaryReason>()\n\n for (const edit of facts.fieldEdits) {\n if (isSecretAdjacentConfigField(edit.configPath)) found.add('secret-adjacent-field')\n\n const newOrigin = originOf(edit.newValue)\n // A value that is not a URL cannot change an origin — and a value that IS one is compared\n // against what it replaced, including the case where it replaced nothing.\n if (newOrigin !== undefined && newOrigin !== originOf(edit.oldValue)) found.add('new-origin')\n\n if (edit.configPath === ALLOW_PRODUCTION_PATH && edit.newValue === true\n && edit.oldValue !== true) {\n found.add('production-opt-in')\n }\n if (TARGET_ENVIRONMENT_PATH.test(edit.configPath) && edit.oldValue === 'production'\n && edit.newValue !== 'production') {\n found.add('production-declassified')\n }\n }\n\n if (facts.addsHook) found.add('hook-added')\n\n const pinned = new Set(facts.pinnedFileSet)\n if (facts.filesTouched.some((path) => !pinned.has(path))) found.add('out-of-set-path')\n\n const reasons = CROSS_BOUNDARY_REASONS.filter((reason) => found.has(reason))\n return { crossBoundary: reasons.length > 0, reasons }\n}\n","// The never-guess boundary, as a parse (Phase 395, D-13/D-15 · CFGM-05).\n//\n// A POSITIVE RULE ABOUT WHAT A HOSTNAME IS, NEVER A LIST OF WHAT IT IS NOT. `isLegalConfigReference`\n// (395-05) is this file's in-tree precedent and the reason is the same one D-03 gives for refusing a\n// settable-field whitelist: a rule that can only refuse what it can NAME cannot be driven to zero by\n// naming more things. So there is no deny list of \"words that look like domains\", no lexicon of\n// prepositions to strip, no catalogue of TLDs. There is one predicate — this string IS a hostname —\n// and everything that does not satisfy it is refused by the same sentence.\n//\n// WHY A PARSE AND NOT A PROMPT. The model picks the TOKEN out of the utterance; nothing below asks\n// it whether the token is a site (D-13). `booking.com` against `booking.de` is a coin flip a review\n// should not have to catch, and the whole point of the split is that the derivation a person\n// approves is one deterministic function of bytes they typed.\n//\n// THE DERIVATION IS PINNED, AND ITS TWO DEFERRED HALVES ARE NAMED. A bare token becomes `https://`\n// plus the lowercased host; an explicit `http://` or `https://` and an explicit port are kept exactly\n// as typed (432 D-20, #134). No `www.` prepending, no redirect chasing to a canonical origin, no\n// locale inference. D-13 defers redirect-chasing explicitly — \"a later enhancement if real use shows\n// the bare-domain derivation wrong in practice\" — and the reason to keep it deferred is that a\n// derivation which reaches the network is one whose answer a hermetic cell cannot pin and a person\n// cannot predict from what they typed.\n//\n// LOCAL ORIGINS ARE PARSED, NOT LISTED (432 D-20, #134). `localhost`, an IPv4 loopback literal\n// (127.0.0.0/8) and the bracketed IPv6 loopback `[::1]` are admitted, because a local dev server is\n// a site this product drives. They are admitted only as TYPED: a spelling the URL parser rewrites\n// into loopback (`127.1`, `2130706433`, `0x7f.0.0.1`, `[::ffff:127.0.0.1]`) is refused, since\n// configuring an address the person did not write is the guess this gate exists to refuse. Other\n// IP literals stay refused: an address is not a hostname.\n//\n// THE HONEST BOUND, STATED ONCE. This predicate accepts strings that are syntactically hostnames and\n// are not sites: `readme.md`, `package.json` and `v1.2` all have a dot and legal labels, and the\n// last two are refused only because their final label is not alphabetic or is shorter than two\n// characters. `readme.md` IS accepted, and would scaffold a target at `https://readme.md`. That is\n// the cost of a positive rule with no catalogue, and it is the safe direction: the failure is a\n// proposal a person reads and rejects, rather than an origin nobody was shown. The alternative —\n// a suffix list — is the door enumeration this file exists not to be.\n\n/** The refusal a token that is not a hostname earns, in one sentence naming both continuations. */\nexport const HOSTNAME_GATE_REFUSAL_DETAIL\n = 'that is not a URL and not a target this project configures. Give me the site\\'s address '\n + '(for example https://example.com) or the name of a target from your agent-qa.config.yaml, '\n + 'and I will use exactly what you give me — I will not guess which site you meant.'\n\n/** DNS label syntax: alphanumeric with internal hyphens, 1–63 characters, no leading/trailing `-`. */\nconst LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/\n\n/** The final label. Alphabetic and at least two characters — what a registry TLD is. */\nconst TLD = /^[a-z]{2,}$/\n\n/**\n * A token's routing verdict. `hostname` carries the derivation; `not-a-hostname` carries nothing,\n * because there is nothing honest to carry.\n */\nexport type HostnameGateVerdict =\n | {\n readonly kind: 'hostname'\n /** The lowercased host, with any scheme, credentials, port, path or query removed. */\n readonly domain: string\n /** The kept scheme (default `https`), {@link domain}, and any explicit non-default port. */\n readonly baseUrl: string\n /** The registry key and a test's `target:`: the host's labels and any port, hyphen-joined. */\n readonly targetName: string\n }\n | { readonly kind: 'not-a-hostname' }\n\n/** An explicit scheme. Only http and https name a site this product can drive. */\nconst SCHEME = /^([a-z][a-z0-9+.-]*):\\/\\//i\n\n/** A bare authority: a host or bracketed IPv6 literal and an optional port, nothing else. */\nconst BARE_AUTHORITY = /^(?:[a-z0-9.-]+|\\[[0-9a-f:.]+\\])(?::\\d{1,5})?$/i\n\nconst IPV4 = /^\\d{1,3}(?:\\.\\d{1,3}){3}$/\n\nconst IPV6_LOOPBACK = '[::1]'\n\ninterface ParsedOrigin {\n readonly scheme: 'http' | 'https'\n readonly host: string\n readonly port: string\n}\n\n/**\n * Read a token's scheme, host and port through the platform's URL parser, or refuse it.\n *\n * PARSED, NOT PATTERN-MATCHED. `URL` is the one implementation of this question the platform has,\n * and re-deriving \"where does the authority end\" from a regex is how a token like\n * `https://example.com@evil.example/` gets read as `example.com` by one half of a product and as\n * `evil.example` by the other. `URL.hostname` is the authority's HOST after userinfo and port are\n * removed. A bare token is held to an authority-only shape first, so a path, a sentence or a\n * `javascript:` pseudo-URL never reaches the parser as if it were a host.\n */\nfunction parseOrigin(token: string): ParsedOrigin | undefined {\n const explicit = SCHEME.exec(token)\n let scheme: 'http' | 'https' = 'https'\n let spelled = token\n if (explicit !== null) {\n const named = (explicit[1] as string).toLowerCase()\n if (named !== 'http' && named !== 'https') return undefined\n scheme = named\n } else {\n if (!BARE_AUTHORITY.test(token)) return undefined\n spelled = `https://${token}`\n }\n try {\n const url = new URL(spelled)\n return { scheme, host: url.hostname.toLowerCase(), port: url.port }\n } catch {\n return undefined\n }\n}\n\n/** The host exactly as the token spells it: after any scheme and userinfo, before any port or path. */\nfunction typedHost(token: string): string {\n const authority = token.replace(SCHEME, '').split(/[/?#\\\\]/, 1)[0] ?? ''\n const hostPort = authority.slice(authority.lastIndexOf('@') + 1)\n if (hostPort.startsWith('[')) return hostPort.slice(0, hostPort.indexOf(']') + 1).toLowerCase()\n const colon = hostPort.indexOf(':')\n return (colon === -1 ? hostPort : hostPort.slice(0, colon)).toLowerCase()\n}\n\n/** The registry-key stem for a host, or undefined when the host is not one this gate admits. */\nfunction hostStem(host: string, typed: string): string | undefined {\n if (host === 'localhost') return 'localhost'\n // IP literals are admitted only as typed: the parser also turns `127.1` into `127.0.0.1`.\n if (host === IPV6_LOOPBACK) return typed === host ? 'ipv6-loopback' : undefined\n if (host.startsWith('[')) return undefined\n if (IPV4.test(host)) {\n return host.startsWith('127.') && typed === host ? `ip-${host.split('.').join('-')}` : undefined\n }\n\n // A dot is necessary and nowhere near sufficient. It is stated first because it is the one\n // syntactic fact separating a site from an ordinary word, and every check below is about labels.\n if (!host.includes('.')) return undefined\n if (host.length > 253) return undefined\n const labels = host.split('.')\n if (labels.length < 2) return undefined\n if (!labels.every((label) => LABEL.test(label))) return undefined\n if (!TLD.test(labels[labels.length - 1] as string)) return undefined\n return labels.join('-')\n}\n\n/**\n * Does this token parse as a hostname, and if so what does the scaffold derive from it (D-15)?\n *\n * TRAILING DOT IS NOT STRIPPED, DELIBERATELY. `example.com.` is a legal fully-qualified name in DNS\n * and an empty final label here, so it is refused rather than silently rewritten — the rule is that\n * what a person typed is what gets configured, and a gate that quietly edits the token is a gate\n * that can quietly edit it wrong.\n *\n * A DEFAULT PORT IS NOT A PORT. `https://example.com:443` and `https://example.com` are one origin\n * and the URL standard serialises them identically, so the base URL carries a port only when it is\n * not the scheme's default.\n */\nexport function parseHostnameToken(token: string): HostnameGateVerdict {\n const trimmed = token.trim()\n if (trimmed.length === 0) return { kind: 'not-a-hostname' }\n\n const origin = parseOrigin(trimmed)\n if (origin === undefined) return { kind: 'not-a-hostname' }\n const stem = hostStem(origin.host, typedHost(trimmed))\n if (stem === undefined) return { kind: 'not-a-hostname' }\n\n const port = origin.port === '' ? '' : `:${origin.port}`\n return {\n kind: 'hostname',\n domain: origin.host,\n baseUrl: `${origin.scheme}://${origin.host}${port}`,\n targetName: origin.port === '' ? stem : `${stem}-${origin.port}`,\n }\n}\n","// `config.field.set` — the first of the closed typed action class (Phase 395, D-01/D-03 · CFGM-01).\n//\n// ONE REGISTERED OP PER ACTION (D-01). The closed action class is legible in the registry itself,\n// the planner picks actions by tool name, and 396's MCP projection and 397's parity walk pick this\n// up with no harness change. A union op carrying a mode string would have projected as one tool\n// whose real vocabulary lives inside a string field nothing validates.\n//\n// IT WRITES IN THE CALL AND COMMITS NOTHING (2026-09-30, 432-11 D-05/D-07). The change is\n// constructed, scanned and validated exactly as before, and then published through the direct\n// writer rather than filed as a proposal: the answer names the files and fields it changed. A\n// blocked change is answered with its report and nothing is kept. No git runs; the change is a\n// plain edit a person sees in `git diff` and reverts with `git restore`.\n//\n// NO SCOPE (2026-10-01, 432-24, D-12). This op once declared `config-write`, so 396's safe-mode\n// filter could hide it and a caller holding only `read` could not reach it. Every door can call\n// every operation now; what guards a config write is the construction, scan and whole-config\n// validation below, not who asked.\n//\n// ANY SCHEMA-ADDRESSABLE PATH (D-03). There is no settable-field whitelist, and the absence is the\n// decision: a rule that can only refuse what it can NAME cannot be driven to zero by naming more\n// things. The guards are whole-input by construction — post-mutation validation of the ENTIRE\n// config in the pipeline, and D-02's per-value classifier when 395-04 lands it.\n\nimport { ConfigChangeOutputSchema, ConfigFieldSetInputSchema } from '@vostride/agent-qa-schema'\nimport type { ConfigChangeOutput, ConfigFieldSetInput } from '@vostride/agent-qa-schema'\n\nimport { classifyConfigChangeOutput } from './config-propose-verdict.js'\nimport { changeConfigField } from '../../config-mutation/construct.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { FunctionSpec } from '../spec.js'\n\nexport const CONFIG_FIELD_SET_FUNCTION_ID = 'config.field.set'\n\nexport const configFieldSetSpec: FunctionSpec<ConfigFieldSetInput, ConfigChangeOutput> = {\n id: CONFIG_FIELD_SET_FUNCTION_ID,\n summary: 'Set one configuration field, written in this call.',\n resultKind: 'unary',\n input: ConfigFieldSetInputSchema,\n output: ConfigChangeOutputSchema,\n boundThrough: 'configWrite',\n risk: {\n name: `fn:${CONFIG_FIELD_SET_FUNCTION_ID}`,\n recognized: true,\n readOnly: false,\n },\n /**\n * This op's own union, folded into a clause verdict (2026-08-20, Phase 399.1 D-01/D-02).\n *\n * THE MAPPING MOVED TO `config-propose-verdict.ts` IN 399.1-03, unchanged, when the other six ops\n * answering with this same union got classifiers of their own. It was written here first because\n * this op was the tracer; leaving a private copy behind would have made a guardrail refusal report\n * `refused` on this door and `executed` on the next one the first time somebody edited one copy.\n * The arms, and the reasoning for which of them is `refused`, are documented at the fold.\n */\n classify: classifyConfigChangeOutput,\n async invoke(input, deps): Promise<ConfigChangeOutput> {\n // THREE DEPS, ONE `boundThrough`: the files, the validator and the direct writer (432-11). The\n // declared name is the writer; all three are checked here, by name, so an in-layer caller\n // holding the spec gets the same refusal a pipeline caller would. No scan (441 D-15).\n const { configFiles, configValidate, configWrite } = deps\n if (\n configFiles === undefined\n || configValidate === undefined\n || configWrite === undefined\n ) {\n throw new FunctionNotBoundError(CONFIG_FIELD_SET_FUNCTION_ID)\n }\n return await changeConfigField(\n { action: CONFIG_FIELD_SET_FUNCTION_ID, path: input.path, value: input.value },\n { configFiles, configValidate, configWrite },\n )\n },\n}\n","// `config.hook.add` — the closed typed action class's fifth member (Phase 395-05, D-01/D-02 ·\n// CFGM-01).\n//\n// 2026-09-30, 432-11 D-05/D-07: THIS OP WRITES IN THE CALL. It is constructed, scanned and validated\n// as described below and then published through the direct writer; the answer names the files and\n// fields it changed, a blocked change is answered with its report and nothing is kept, and no git\n// runs. Where the paragraphs below say \"proposal\", read the change this call writes.\n//\n// `config-field-set.ts`'s header carries the arguments for the tier and the one-op-per-action\n// shape; they are not restated. Two things are different about this one.\n//\n// NO SCOPE (2026-10-01, 432-25, D-12). This op once declared `config-write`. Every door can call\n// every operation now; what guards the write is the construction, scan and whole-set validation\n// below, not who asked.\n//\n// IT IS THE ONLY ACTION THAT WRITES A FILE OTHER THAN THE CONFIG YAML. The hooks file is the second\n// member of the pinned config set, and it has its own schema — `core`'s `HooksFileSchema`, with the\n// canonical-id rule and the duplicate-id and duplicate-name refinements. That is why 395-05 widened\n// whole-config validation to the whole candidate SET: a validator that only ever read the config\n// yaml would have declared this proposal valid without looking at the one artifact it wrote, which\n// is D-03's whole-input law satisfied on paper and violated in fact.\n//\n// EVERY HOOK ADDITION IS CROSS-BOUNDARY, UNCONDITIONALLY (D-02). A hook is code this project will\n// EXECUTE, and that is a different kind of change from a setting. The fact is STATED by the\n// construction rather than inferred from the path it wrote, because inferring \"a hook was added\"\n// from a path is the per-op map D-02 refused. (2026-10-01, 432-25, D-12: the standing-approval and\n// grant machinery that once refused on this flag is deleted; the flag stays on the change report.)\n//\n// THE INPUT NAMES A FILE AND NEVER CARRIES A BODY. The script is a thing a person writes and reviews\n// in their editor; a proposal that carried executable text would be asking for approval of two\n// artifacts in one decision. The hook's ID is minted host-side through the same machinery\n// `isCanonicalHookId` accepts, because a hand-formatted id would parse as a string, reach a person's\n// repository, and be refused at the next run rather than at the proposal.\n\nimport { ConfigChangeOutputSchema, ConfigHookAddInputSchema } from '@vostride/agent-qa-schema'\nimport type { ConfigChangeOutput, ConfigHookAddInput } from '@vostride/agent-qa-schema'\n\nimport { classifyConfigChangeOutput } from './config-propose-verdict.js'\nimport { addConfigHook } from '../../config-mutation/construct.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { FunctionSpec } from '../spec.js'\n\nexport const CONFIG_HOOK_ADD_FUNCTION_ID = 'config.hook.add'\n\nexport const configHookAddSpec: FunctionSpec<ConfigHookAddInput, ConfigChangeOutput> = {\n id: CONFIG_HOOK_ADD_FUNCTION_ID,\n summary: 'Declare a hook in the hooks file, written in this call.',\n resultKind: 'unary',\n input: ConfigHookAddInputSchema,\n output: ConfigChangeOutputSchema,\n boundThrough: 'configWrite',\n risk: {\n name: `fn:${CONFIG_HOOK_ADD_FUNCTION_ID}`,\n recognized: true,\n readOnly: false,\n },\n /**\n * This op's own union, folded into a clause verdict (2026-08-20, Phase 399.1 D-01/D-02).\n *\n * THE FOLD IS SHARED BECAUSE THE UNION IS. Six ops answer with `ConfigChangeOutput` (432-11), and a\n * per-op copy of the mapping would be a guardrail refusal that reports `refused` on some doors\n * and `executed` on others the first time one copy is edited. See `config-propose-verdict.ts`\n * for why `blocked` and `refused` are the same status and different words.\n */\n classify: classifyConfigChangeOutput,\n async invoke(input, deps): Promise<ConfigChangeOutput> {\n // The same three-way guard its siblings carry: the files, the validator and the direct writer.\n const { configFiles, configValidate, configWrite } = deps\n if (\n configFiles === undefined\n || configValidate === undefined\n || configWrite === undefined\n ) {\n throw new FunctionNotBoundError(CONFIG_HOOK_ADD_FUNCTION_ID)\n }\n return await addConfigHook(\n { action: CONFIG_HOOK_ADD_FUNCTION_ID, ...input },\n { configFiles, configValidate, configWrite },\n )\n },\n}\n","// `config.get` — the masked resolved-configuration read (Phase 384, D-06).\n//\n// The op is a pass-through by design. Masking happens where the configuration is RESOLVED,\n// inside the composition root, while each entry is constructed. If this op masked instead,\n// an unmasked config would exist inside the layer and the security property would depend on\n// this function never being bypassed — exactly the guarantee the layer refuses to rest on.\n\nimport { ConfigGetInputSchema, MaskedResolvedConfigSchema } from '@vostride/agent-qa-schema'\nimport type { ConfigGetInput, MaskedResolvedConfig } from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport const CONFIG_GET_FUNCTION_ID = 'config.get'\n\nexport const configGetSpec: FunctionSpec<ConfigGetInput, MaskedResolvedConfig> = {\n id: CONFIG_GET_FUNCTION_ID,\n summary: 'Read the resolved project configuration with secret-bearing values masked.',\n resultKind: 'unary',\n input: ConfigGetInputSchema,\n output: MaskedResolvedConfigSchema,\n risk: { name: `fn:${CONFIG_GET_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * A read that answered — the count of what it resolved, and nothing out of it (399.1 D-01).\n *\n * NOT ONE ENTRY'S VALUE, ever. This op's result carries a person's configuration, placeholder-\n * masked; the receipt is a map and the masked payload travels on `results[]` where the surface's\n * own unmasker decides what a human may see (D-04's boundary, not this fold's).\n */\n classify(output): ClauseVerdict {\n const count = output.entries.length\n return {\n status: 'executed',\n outcome: `resolved config — ${count} entr${count === 1 ? 'y' : 'ies'}`,\n }\n },\n invoke(_input, deps) {\n return deps.config.getMasked()\n },\n}\n","// `config.target.create` — the closed typed action class's second member (Phase 395-05, D-01/D-02 ·\n// CFGM-01).\n//\n// 2026-09-30, 432-11 D-05/D-07: THIS OP WRITES IN THE CALL. It is constructed, scanned and validated\n// as described below and then published through the direct writer; the answer names the files and\n// fields it changed, a blocked change is answered with its report and nothing is kept, and no git\n// runs. Where the paragraphs below say \"proposal\", read the change this call writes.\n//\n// EVERY PARAGRAPH `config-field-set.ts` OPENS WITH APPLIES HERE VERBATIM and is not restated: one\n// registered op per action, and no `declaredTier` because a proposal commits nothing. Read that file\n// for the arguments; what follows is what is different about this one. 2026-10-01 (432-26, D-12):\n// this op once declared `config-write` because the scope described what the capability is about.\n// It declares no scope now, because no caller is checked for one; the construction, the scan and\n// whole-config validation below guard the write.\n//\n// A CREATE IS NEVER AN UPSERT, AND THAT IS THIS OP'S WHOLE EDGE. The yaml `setIn` that backs every\n// mutation in this phase REPLACES whatever is at the path it is given, so the natural implementation\n// of \"add a target\" quietly deletes the `product`, `appPackage` and `environment` a target of that\n// name already carried, and renders it as a diff a person would have to read line by line to notice.\n// The pipeline refuses the collision by name and points at `config.target.edit`, which is the op\n// that exists for changing one.\n//\n// IT DOES NOT ADDRESS THE TARGET NAME AS A SETTABLE PATH, and that is not a whitelist. D-03's\n// no-whitelist law is about which config paths a person may set — `config.field.set` still answers\n// any of them. This op exists because \"add a web target\" is a shape the model can fill correctly\n// from an utterance and a raw dotted-path set is not: `platform` and `url` together are what makes a\n// target valid, and a shape that carries both is what stops half a target from being proposed.\n\nimport { ConfigChangeOutputSchema, ConfigTargetCreateInputSchema } from '@vostride/agent-qa-schema'\nimport type { ConfigChangeOutput, ConfigTargetCreateInput } from '@vostride/agent-qa-schema'\n\nimport { classifyConfigChangeOutput } from './config-propose-verdict.js'\nimport { createConfigTarget } from '../../config-mutation/construct.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { FunctionSpec } from '../spec.js'\n\nexport const CONFIG_TARGET_CREATE_FUNCTION_ID = 'config.target.create'\n\nexport const configTargetCreateSpec: FunctionSpec<ConfigTargetCreateInput, ConfigChangeOutput> = {\n id: CONFIG_TARGET_CREATE_FUNCTION_ID,\n summary: 'Add a web target to the registry, written in this call.',\n resultKind: 'unary',\n input: ConfigTargetCreateInputSchema,\n output: ConfigChangeOutputSchema,\n boundThrough: 'configWrite',\n risk: {\n name: `fn:${CONFIG_TARGET_CREATE_FUNCTION_ID}`,\n recognized: true,\n readOnly: false,\n },\n /**\n * This op's own union, folded into a clause verdict (2026-08-20, Phase 399.1 D-01/D-02).\n *\n * THE FOLD IS SHARED BECAUSE THE UNION IS. Six ops answer with `ConfigChangeOutput` (432-11), and a\n * per-op copy of the mapping would be a guardrail refusal that reports `refused` on some doors\n * and `executed` on others the first time one copy is edited. See `config-propose-verdict.ts`\n * for why `blocked` and `refused` are the same status and different words.\n */\n classify: classifyConfigChangeOutput,\n async invoke(input, deps): Promise<ConfigChangeOutput> {\n // The same three-way guard its siblings carry: the files, the validator and the direct writer.\n const { configFiles, configValidate, configWrite } = deps\n if (\n configFiles === undefined\n || configValidate === undefined\n || configWrite === undefined\n ) {\n throw new FunctionNotBoundError(CONFIG_TARGET_CREATE_FUNCTION_ID)\n }\n return await createConfigTarget(\n { action: CONFIG_TARGET_CREATE_FUNCTION_ID, ...input },\n { configFiles, configValidate, configWrite },\n )\n },\n}\n","// `config.project.scaffold` — the from-zero configuration, written as ONE change in the call\n// (Phase 395-08, D-04 / D-13 / D-14 / D-15 · CFGM-05; 2026-10-02, 432-42: re-spelled from the\n// proposal it used to file).\n//\n// 2026-09-30, 432-11 D-05/D-07: THIS OP WRITES IN THE CALL. It is constructed, scanned and validated\n// as described below and then published through the direct writer; the answer names the files and\n// fields it changed, a blocked change is answered with its report and nothing is kept, and no git\n// runs. Where the paragraphs below say \"proposal\", read the change this call writes.\n//\n// THE EIGHTH REGISTERED CONFIG OP, ON D-01's FOOTING. One op per action: the planner picks it by\n// tool name, 396's projection publishes it and 397's parity walk enumerates it, all with no harness\n// change. `config.project.scaffold` — three lowercase dot segments, no underscore, so the chat\n// tool-name mapping (`.` ↔ `_`) has one pre-image and `parity-coverage`'s id pattern accepts it.\n//\n// THE MODEL FILLS ONE FIELD AND DERIVES NOTHING (D-13). `ConfigProjectScaffoldInputSchema` is a\n// strict `{ domain }`, and every field it does not have is a field a model could otherwise invent.\n// The scheme, the target name, the platform, the whole file set: all of it comes from\n// `parseHostnameToken` and the shared content module, which is what makes the proposal a person\n// approves a deterministic function of bytes they typed.\n//\n// THE NEVER-GUESS BOUNDARY IS A REFUSAL, NOT A FALLBACK (D-15). A token that does not parse as a\n// hostname does not become a search, a completion or a best guess — it becomes a typed `refused`\n// naming both continuations. `booking.com` against `booking.de` is a coin flip review should not\n// have to catch, so the product declines to flip it.\n//\n// IT COMMITS NOTHING, WHICH IS WHY IT CARRIES NO `declaredTier`, on `config.field.set`'s stated\n// reasoning. A scaffold is always cross-boundary, and the change report says so.\n//\n// NO SCOPE (2026-10-01, 432-25, D-12). This op once declared `config-write`, and 395-07's two-sided\n// grant enforcement made a scaffold unsatisfiable by any standing grant. Both are deleted: every\n// door can call every operation, and what guards the write is the construction, the whole-new-file\n// scan and the whole-set validation below.\n\nimport { ConfigChangeOutputSchema, ConfigProjectScaffoldInputSchema } from '@vostride/agent-qa-schema'\nimport type { ConfigChangeOutput, ConfigProjectScaffoldInput } from '@vostride/agent-qa-schema'\n\nimport { classifyConfigChangeOutput } from './config-propose-verdict.js'\nimport { scaffoldConfigProject } from '../../config-mutation/construct.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { FunctionSpec } from '../spec.js'\n\nexport const CONFIG_PROJECT_SCAFFOLD_FUNCTION_ID = 'config.project.scaffold'\n\nexport const configProjectScaffoldSpec: FunctionSpec<\n ConfigProjectScaffoldInput,\n ConfigChangeOutput\n> = {\n id: CONFIG_PROJECT_SCAFFOLD_FUNCTION_ID,\n summary:\n 'Configure this project for a site from zero — config, hooks and gitignore, written in this '\n + 'call.',\n resultKind: 'unary',\n input: ConfigProjectScaffoldInputSchema,\n output: ConfigChangeOutputSchema,\n boundThrough: 'scaffoldContent',\n risk: {\n name: `fn:${CONFIG_PROJECT_SCAFFOLD_FUNCTION_ID}`,\n recognized: true,\n readOnly: false,\n },\n /**\n * This op's own union, folded into a clause verdict (2026-08-20, Phase 399.1 D-01/D-02).\n *\n * THE FOLD IS SHARED BECAUSE THE UNION IS. Six ops answer with `ConfigChangeOutput` (432-11), and a\n * per-op copy of the mapping would be a guardrail refusal that reports `refused` on some doors\n * and `executed` on others the first time one copy is edited. See `config-propose-verdict.ts`\n * for why `blocked` and `refused` are the same status and different words.\n */\n classify: classifyConfigChangeOutput,\n async invoke(input, deps): Promise<ConfigChangeOutput> {\n // FOUR DEPS, ONE `boundThrough`, on the arrangement the deleted `config.undo.propose` used\n // (432-17) — with the declared name being this op's OWN one: the files, the validator, the\n // direct writer and `scaffoldContent`, which is what a host that cannot render the shared\n // scaffold substance lacks and the fact that makes this op specifically unavailable.\n const { configFiles, configValidate, configWrite, scaffoldContent } = deps\n if (\n configFiles === undefined\n || configValidate === undefined\n || configWrite === undefined\n || scaffoldContent === undefined\n ) {\n throw new FunctionNotBoundError(CONFIG_PROJECT_SCAFFOLD_FUNCTION_ID)\n }\n return await scaffoldConfigProject(\n { action: CONFIG_PROJECT_SCAFFOLD_FUNCTION_ID, domain: input.domain },\n { configFiles, configValidate, configWrite, scaffoldContent },\n )\n },\n}\n","// `config.target.edit` — the closed typed action class's third member (Phase 395-05, D-01/D-02/D-15\n// · CFGM-01).\n//\n// 2026-09-30, 432-11 D-05/D-07: THIS OP WRITES IN THE CALL. It is constructed, scanned and validated\n// as described below and then published through the direct writer; the answer names the files and\n// fields it changed, a blocked change is answered with its report and nothing is kept, and no git\n// runs. Where the paragraphs below say \"proposal\", read the change this call writes.\n//\n// `config-field-set.ts`'s header carries the arguments for the tier and the one-op-per-action\n// shape; they are not restated. 2026-10-01 (432-23, D-12): the op declares no scope, because no\n// caller is checked for one. What is different about this one is its refusal.\n//\n// AN ABSENT TARGET IS A NAMED REFUSAL THAT LISTS THE CONFIGURED NAMES, which is 387's disambiguation\n// posture and D-15's never-guess line arriving in the write half. The failure this prevents is not\n// an exception — it is a `setIn` at `registry.targets.shpo.url` CREATING a target called `shpo` with\n// a url and no platform, which whole-config validation then refuses for the wrong reason, in a\n// message about a required field rather than about a typo. The names the refusal lists are already\n// readable through `config.get`, so listing them discloses nothing a caller could not already see.\n//\n// THE URL EDIT IS WHERE D-02's PER-VALUE RULE IS SHARPEST. The same op, the same path, two different\n// answers: `registry.targets.shop.url` moved from `https://shop.example.com/cart` to\n// `/basket` is an ordinary edit, and the same field moved to `https://shop.evil.example` is a change\n// of which machine this product will drive. A per-op or per-path risk map cannot tell those apart —\n// which is exactly why D-02 put the flag on the proposal and computed it from the values.\n\nimport { ConfigChangeOutputSchema, ConfigTargetEditInputSchema } from '@vostride/agent-qa-schema'\nimport type { ConfigChangeOutput, ConfigTargetEditInput } from '@vostride/agent-qa-schema'\n\nimport { classifyConfigChangeOutput } from './config-propose-verdict.js'\nimport { editConfigTarget } from '../../config-mutation/construct.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { FunctionSpec } from '../spec.js'\n\nexport const CONFIG_TARGET_EDIT_FUNCTION_ID = 'config.target.edit'\n\nexport const configTargetEditSpec: FunctionSpec<ConfigTargetEditInput, ConfigChangeOutput> = {\n id: CONFIG_TARGET_EDIT_FUNCTION_ID,\n summary: 'Change a configured target\\'s URL, written in this call.',\n resultKind: 'unary',\n input: ConfigTargetEditInputSchema,\n output: ConfigChangeOutputSchema,\n boundThrough: 'configWrite',\n risk: {\n name: `fn:${CONFIG_TARGET_EDIT_FUNCTION_ID}`,\n recognized: true,\n readOnly: false,\n },\n /**\n * This op's own union, folded into a clause verdict (2026-08-20, Phase 399.1 D-01/D-02).\n *\n * THE FOLD IS SHARED BECAUSE THE UNION IS. Six ops answer with `ConfigChangeOutput` (432-11), and a\n * per-op copy of the mapping would be a guardrail refusal that reports `refused` on some doors\n * and `executed` on others the first time one copy is edited. See `config-propose-verdict.ts`\n * for why `blocked` and `refused` are the same status and different words.\n */\n classify: classifyConfigChangeOutput,\n async invoke(input, deps): Promise<ConfigChangeOutput> {\n // The same three-way guard its siblings carry: the files, the validator and the direct writer.\n const { configFiles, configValidate, configWrite } = deps\n if (\n configFiles === undefined\n || configValidate === undefined\n || configWrite === undefined\n ) {\n throw new FunctionNotBoundError(CONFIG_TARGET_EDIT_FUNCTION_ID)\n }\n return await editConfigTarget(\n { action: CONFIG_TARGET_EDIT_FUNCTION_ID, ...input },\n { configFiles, configValidate, configWrite },\n )\n },\n}\n","// `entities.get` — one exact address in, one card out (Phase 387, ENTY-02 / D-09).\n//\n// The simple read path. `entities.resolve` answers the hard question (\"what did the user\n// mean?\"); this one answers the easy one (\"render the thing at this address\"), and keeping\n// them apart is what lets 396 project this op onto an MCP Resource Template — a template\n// needs a total function of an address, not a union that might come back ambiguous.\n//\n// It never mints. `resolve` sights and may therefore assign an address (D-01); `get` is\n// handed an address that already exists, and a `get` that could write would turn every card\n// render on every surface into a potential mutation.\n\nimport { EntitiesGetInputSchema, EntityCardSchema } from '@vostride/agent-qa-schema'\nimport type { EntitiesGetInput, EntityCard } from '@vostride/agent-qa-schema'\n\nimport { readEntityCardContext } from '../entity-cards/card-context.js'\nimport { produceEntityCard } from '../entity-cards/produce-card.js'\nimport { ENTITIES_GET_FUNCTION_ID } from './entities-ids.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport { ENTITIES_GET_FUNCTION_ID }\n\n/**\n * No entity is addressed by this reference.\n *\n * A typed refusal rather than an `undefined` result, on the `RunNotFoundError` precedent: the\n * absence is the ANSWER to a caller who asked for one specific thing, and a surface needs to\n * be able to phrase it. Note what it does not mean — a permanently minted address whose\n * entity has since been tombstoned still RESOLVES (D-04), to a card whose status says so.\n * This error is for an address nothing ever minted.\n */\nexport class EntityNotFoundError extends Error {\n constructor(readonly ref: string) {\n super(`No entity is addressed by ${ref}`)\n this.name = 'EntityNotFoundError'\n }\n}\n\nexport const entitiesGetSpec: FunctionSpec<EntitiesGetInput, EntityCard> = {\n id: ENTITIES_GET_FUNCTION_ID,\n summary: 'Render the entity card for one exact short-ID or agentqa:// URI.',\n resultKind: 'unary',\n input: EntitiesGetInputSchema,\n output: EntityCardSchema as FunctionSpec<EntitiesGetInput, EntityCard>['output'],\n risk: { name: `fn:${ENTITIES_GET_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * A card that came back is a card that was found (399.1 D-01).\n *\n * Absence is a THROW here (`EntityNotFoundError`), not an arm, so the one returning shape is a\n * hit. THE ADDRESS AND NOTHING ELSE: `kind` and `id` are the card's own name, and every fact on\n * it travels on `results[]`.\n */\n classify(output): ClauseVerdict {\n return { status: 'executed', outcome: `found ${output.kind} ${output.id}` }\n },\n async invoke(input, deps) {\n const descriptor = await deps.entities.get(input.ref)\n if (descriptor === undefined) throw new EntityNotFoundError(input.ref)\n // The render context is read HERE, not inside the producer, so the producer stays a pure\n // synchronous function of values (D-10). Read after the lookup: an address that names\n // nothing is refused without touching configuration at all.\n return produceEntityCard(descriptor, await readEntityCardContext(deps, [descriptor]))\n },\n}\n","// Where the card's `url` comes from (Phase 387, ENTY-02 / D-10).\n//\n// D-10: the URL is CONFIG-DERIVED and absent by default. The configuration a function-layer op\n// can see is `ConfigReaderPort.getMasked()` — a flat, dot-path, already-masked list — and that\n// is deliberately the only route. The alternative, a second port that read the raw resolved\n// config, would have made the T-384-07 masking optional at exactly the seam it exists to\n// protect, and \"optional masking is not masking\".\n//\n// Reading through the masker has a consequence worth stating plainly, because it decides this\n// module's central rule. `services.dashboard.baseUrl`'s leaf name is registered in the CLI\n// masker's address set, so a base carrying a path, userinfo, query or fragment is REDUCED to\n// its origin and the entry is flagged `masked: true`. A reduced base is not the operator's\n// base: rendering a link against it would silently drop the path prefix and point every card\n// at a route the dashboard does not serve. So an entry whose value is not verbatim is treated\n// as NO base at all, and the card's `url` is omitted — the same state as an unconfigured\n// dashboard, which is the honest one. The masker's own flag is what makes this decidable; the\n// producer never inspects the value's characters to guess.\n\nimport type {\n EntityDescriptor,\n MaskedResolvedConfig,\n QuarantineEntryState,\n} from '@vostride/agent-qa-schema'\n\nimport type { FunctionDeps } from '../spec.js'\n\n/** The two dot-paths D-10 reads, spelled once. */\nexport const DASHBOARD_BASE_URL_CONFIG_KEY = 'services.dashboard.baseUrl'\nexport const DASHBOARD_WORKSPACE_CONFIG_KEY = 'services.dashboard.workspace'\n\n/** A configured dashboard, as the card producer needs it: both halves, both verbatim. */\nexport interface DashboardUrlBase {\n readonly baseUrl: string\n readonly workspace: string\n}\n\n/**\n * One entry's verbatim value, or `undefined` when there is no such entry or the masker\n * altered it.\n *\n * The `masked` flag is read rather than the value, because `masked: true` means exactly one\n * thing — \"this is not the operator's raw value\" — and that is the only question this module\n * has. A value-shaped test (does it look like a placeholder? does it look like an origin?)\n * would be the producer second-guessing the masker, and would still be wrong for the reduced\n * case, which looks like a perfectly good URL.\n */\nfunction verbatim(masked: MaskedResolvedConfig, key: string): string | undefined {\n const entry = masked.entries.find((candidate) => candidate.key === key)\n if (entry === undefined || entry.masked) return undefined\n return entry.value.trim() === '' ? undefined : entry.value\n}\n\n/**\n * The configured dashboard base, or `undefined` — the v52 default (D-10).\n *\n * BOTH halves are required. A base with no workspace cannot render `:workspace`, and a\n * workspace with no base has nowhere to point; either alone would have to be completed by a\n * guess, and a guessed link is the dead link D-10 forbids.\n */\nexport function readDashboardUrlBase(\n masked: MaskedResolvedConfig,\n): DashboardUrlBase | undefined {\n const baseUrl = verbatim(masked, DASHBOARD_BASE_URL_CONFIG_KEY)\n const workspace = verbatim(masked, DASHBOARD_WORKSPACE_CONFIG_KEY)\n if (baseUrl === undefined || workspace === undefined) return undefined\n return { baseUrl, workspace }\n}\n\n/** Everything the producer needs beyond the descriptor itself. */\nexport interface EntityCardContext {\n readonly urlBase?: DashboardUrlBase\n /**\n * The committed quarantine ledger's folded entries (390 D-12), when this render needs them.\n *\n * Read at the OP boundary and handed to the producer as a value, exactly like `urlBase` — the\n * producer takes no ports, which is what makes ENTY-02's \"two renders of unchanged state are\n * deeply equal\" a fact about the parameter list. Absent means no quarantine port is bound, or\n * no test is being rendered; the producer treats both as `active`.\n */\n readonly quarantine?: readonly QuarantineEntryState[]\n}\n\n/**\n * Build the render context for one op invocation.\n *\n * A configuration read failure is deliberately NOT swallowed into \"no dashboard configured\".\n * The two states are different — one is a deliberate default and the other is a broken\n * project — and a card that quietly dropped its link because the config file could not be\n * parsed would hide the breakage behind D-10's expected absence.\n *\n * The quarantine read is SCOPED to renders that contain a test, and the descriptors are taken as\n * a parameter for exactly that reason. Only a `TST` card's status can depend on the ledger, so a\n * `MEM` or `RUN` render must not be able to fail because a committed file somebody hand-edited\n * no longer parses. When a test IS in the set the read happens once for the whole render — one\n * fold, so two cards in one disambiguation set cannot disagree — and a refusal PROPAGATES:\n * answering `active` there would say \"this test is not quarantined\" about a ledger nobody could\n * open, which is the silent flip this phase exists to prevent.\n */\nexport async function readEntityCardContext(\n deps: FunctionDeps,\n descriptors: readonly EntityDescriptor[],\n): Promise<EntityCardContext> {\n const urlBase = readDashboardUrlBase(await deps.config.getMasked())\n const needsQuarantine = descriptors.some((descriptor) => descriptor.kind === 'TST')\n const quarantine = needsQuarantine ? await deps.quarantine?.list() : undefined\n return {\n ...(urlBase === undefined ? {} : { urlBase }),\n ...(quarantine === undefined ? {} : { quarantine }),\n }\n}\n","// THE entity card producer (Phase 387, ENTY-02 / D-04 / D-10 / D-11 / D-12).\n//\n// One producer, in the function layer, and every surface's card is its output. That is not a\n// tidiness claim — it is what makes the chat card, the MCP `structuredContent` and M5's UI\n// *projections* rather than three renderers that agree until one of them is edited. The\n// claim is testable precisely because the store layer has no vocabulary for a card at all:\n// `knowledge-local` returns descriptors, and the only code in this repo that builds an\n// `EntityCard` is this file.\n//\n// RENDER, never recompute — the discipline `knowledge.bundles.list` established for derived\n// trust fields, applied to entity state. The owning store decided what an entity's status\n// is; this function's job is to carry that decision into the card vocabulary and to REFUSE\n// rather than repair a status the kind does not declare. `EntityCardSchema.parse` is where\n// that refusal happens (D-12), so an unrecognised store state surfaces as a named contract\n// failure at the seam instead of as a card that quietly reads `active`.\n//\n// The function stays SYNCHRONOUS and PURE. Everything it needs beyond the descriptor arrives\n// as an already-read context value (see `card-context.ts`), so the two properties ENTY-02\n// actually claims — two renders of unchanged state are deeply equal, and rendering never\n// writes — are facts about the parameter list rather than promises about the body. An async\n// producer that read configuration itself would have had a handle through which any port\n// could later be reached.\n\nimport { EntityCardSchema, formatEntityUri, formatEntityUrl } from '@vostride/agent-qa-schema'\nimport type {\n EntityCard,\n EntityDescriptor,\n ForgetReceiptV1,\n QuarantineEntryState,\n} from '@vostride/agent-qa-schema'\n\nimport { actionsForKind } from './actions.js'\nimport type { EntityCardContext } from './card-context.js'\nimport { projectKeyFacts } from './key-facts.js'\n\n/** What the producer needs about ONE entity beyond its descriptor. */\nexport interface EntityCardRenderInput extends EntityCardContext {\n /**\n * The forget receipt for a forgotten `MEM` bundle (D-04 + D-19).\n *\n * Supplied by whoever already holds one — the forget verb, which produced it, and later a\n * store lookup for an address whose bundle is gone. It is an INPUT rather than something\n * this module fetches, for the same reason the URL base is: the producer takes no ports.\n */\n readonly forgetReceipt?: ForgetReceiptV1\n}\n\n/**\n * A receipt was supplied for something that is not a knowledge bundle.\n *\n * A refusal rather than a silent drop. `ForgetReceiptV1.resultingBundleStatus` is drawn from\n * the `MEM` card's own status vocabulary (D-19), so a receipt attached to a run or a target\n * is not merely irrelevant, it is a claim about a status that kind does not declare — and\n * dropping it would render a card that omits the very fact the caller asked to show.\n */\nexport class ForgetReceiptKindError extends TypeError {\n constructor(readonly kind: string) {\n super(\n `a forget receipt describes a MEM knowledge bundle (D-19); it cannot render a ${kind} card`,\n )\n this.name = 'ForgetReceiptKindError'\n }\n}\n\n/**\n * The status the card reports (D-04: permanent address, honest status).\n *\n * When a forget receipt is in hand it WINS over the store's reported status, and that is the\n * whole of D-19's second use: the receipt is what the forgotten entity's permanent address\n * resolves to afterwards, so a descriptor still reporting `active` because some projection\n * has not caught up must not be able to contradict it. The receipt's own field is typed to\n * the `MEM` vocabulary, so this substitution can never widen what the card may say.\n */\nfunction statusFor(\n descriptor: EntityDescriptor,\n input: EntityCardRenderInput,\n /**\n * 390 D-12: the SUPPRESSING window this entity sits under, already joined. Passed in rather\n * than recomputed so the status and the key facts are decided by literally one evaluation —\n * a card can never say `quarantined` above facts that describe no window, or the reverse.\n *\n * The two substitutions cannot collide: a receipt describes a `MEM` bundle and a quarantine\n * window a `TST` test, so the receipt keeps its precedence unchanged (D-19's second use).\n */\n quarantineEntry: QuarantineEntryState | undefined,\n): string {\n if (input.forgetReceipt === undefined) {\n return quarantineEntry === undefined ? descriptor.statusSource : 'quarantined'\n }\n if (descriptor.kind !== 'MEM') throw new ForgetReceiptKindError(descriptor.kind)\n return input.forgetReceipt.resultingBundleStatus\n}\n\n/**\n * THE join between an entity and the committed ledger (390 D-11/D-12), spelled once.\n *\n * Three gates, each refusing a different wrong answer:\n *\n * - KIND. Only `TST` has a test identity; every other kind's card is untouched by the ledger.\n * - REPORTED IDENTITY. The join key is `(product, filePath, testName)`, which the store must\n * have REPORTED — never `machineId` (a per-run explicit id) and never the title. A descriptor\n * that carries no identity answers `active`, which is honest: this store cannot say.\n * - STATE. Only `quarantined` counts. An `expired` window has STOPPED suppressing (D-11) and a\n * `released` one is closed, so both\n * are `active` tests whose history lives in `quarantine.list`. A card that showed `expired`\n * as `quarantined` would tell a reader the failing build in front of them is licensed.\n */\nfunction quarantineEntryFor(\n descriptor: EntityDescriptor,\n input: EntityCardRenderInput,\n): QuarantineEntryState | undefined {\n if (descriptor.kind !== 'TST') return undefined\n const identity = descriptor.testIdentity\n if (identity === undefined || input.quarantine === undefined) return undefined\n return input.quarantine.find((entry) =>\n entry.state === 'quarantined'\n && entry.product === identity.product\n && entry.filePath === identity.filePath\n && entry.testName === identity.testName)\n}\n\n/**\n * The dashboard link, or nothing (D-10).\n *\n * ABSENT, not null and not an empty string, whenever no dashboard base is configured — the\n * v52 default — or whenever the configured base cannot render an honest URL. The field is\n * omitted from the object entirely rather than set to `undefined`, so `'url' in card` is\n * false and a surface that iterates the card's own keys never sees it.\n */\nfunction urlFor(\n descriptor: EntityDescriptor,\n input: EntityCardRenderInput,\n): { url: string } | Record<string, never> {\n if (input.urlBase === undefined) return {}\n const url = formatEntityUrl({\n baseUrl: input.urlBase.baseUrl,\n workspace: input.urlBase.workspace,\n kind: descriptor.kind,\n shortId: descriptor.shortId,\n title: descriptor.title,\n })\n return url === undefined ? {} : { url }\n}\n\n/**\n * Render one descriptor as the one card shape.\n *\n * The second parameter defaults to an empty context, which is the v52 production state: no\n * dashboard configured and no receipt in hand. That default is what lets every existing\n * caller keep rendering the card it already rendered.\n */\nexport function produceEntityCard(\n descriptor: EntityDescriptor,\n input: EntityCardRenderInput = {},\n): EntityCard {\n const quarantineEntry = quarantineEntryFor(descriptor, input)\n return EntityCardSchema.parse({\n kind: descriptor.kind,\n id: descriptor.shortId,\n // Recomputed from the address rather than copied off the descriptor: the URI and the\n // short-ID are two spellings of ONE address, and deriving one from the other is what\n // stops a card from ever carrying two that disagree.\n uri: formatEntityUri(descriptor.kind, descriptor.shortId),\n title: descriptor.title,\n status: statusFor(descriptor, input, quarantineEntry),\n ...urlFor(descriptor, input),\n keyFacts: projectKeyFacts({\n descriptor,\n ...(input.forgetReceipt === undefined ? {} : { forgetReceipt: input.forgetReceipt }),\n // The SAME join the status was decided by — computed once, passed as a value, so the\n // projection table stays pure over what it is handed.\n ...(quarantineEntry === undefined ? {} : { quarantineEntry }),\n }),\n actions: actionsForKind(descriptor),\n }) as EntityCard\n}\n","// The `entities.` domain's function ids (Phase 387, D-09).\n//\n// A new domain in the fixed dot-namespaced taxonomy, exactly as `knowledge.` was in 384 —\n// two read-tier verbs over which every surface's entity resolution and rendering flows.\n//\n// The two consts live in their own module for a structural reason rather than a stylistic\n// one: the card producer advertises `entities.get` as a registry action (D-11), and the\n// `entities.get` op renders through the producer. Declaring the ids beside either op would\n// close that loop into an import cycle; declaring them here means the id is one value with\n// one definition, and both files import it in one direction.\n\nexport const ENTITIES_RESOLVE_FUNCTION_ID = 'entities.resolve'\n\nexport const ENTITIES_GET_FUNCTION_ID = 'entities.get'\n","// `knowledge.brief.why` — why did the brief say this (Phase 387, KREV-02 / D-14 / D-15).\n//\n// The verb answers about THEN. It reads the retrieval trace the serving path wrote down at the\n// moment it assembled the brief, and it does not re-run retrieval — not because re-running is\n// discouraged, but because this op is handed nothing it could re-run retrieval WITH.\n//\n// The structure is the argument, so it is worth stating exactly what is structural and what is\n// not. `mapStepEvidenceToWhy` below is a pure function of (lookup, input): it takes no `deps`\n// at all, so the code that decides what the answer IS cannot read a live index by any route —\n// there is no handle in scope. `invoke` has the whole `FunctionDeps` record, as every op does,\n// and makes exactly one call with it: `deps.runs.readStepEvidence`. That the call is the only\n// one is a SOURCE claim, scanned and mutation-probed rather than enforced by a type. Both\n// halves are stated because they are different strengths of guarantee and it would be easy to\n// present the weaker one as the stronger.\n//\n// The substrate is on the RUNS port, not the knowledge port. A step's evidence is a record of\n// what happened during a run; the knowledge index is a record of what is true now. Answering\n// out of the second would answer a different question than the one asked — the exact\n// dishonesty KREV-02 exists to prevent — and no serving capability is reachable from here.\n\nimport { BriefWhyInputSchema, BriefWhyResultSchema, asRunId } from '@vostride/agent-qa-schema'\nimport type {\n BriefWhyInput,\n BriefWhyResult,\n ServedRetrievalTraceV1,\n} from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict, FunctionSpec, StepEvidenceLookup } from '../spec.js'\n\nexport const KNOWLEDGE_BRIEF_WHY_FUNCTION_ID = 'knowledge.brief.why'\n\n/**\n * The address named more than one step, and this verb will not choose one.\n *\n * A caller-facing refusal rather than a `no-trace` arm, and the distinction is the point. Every\n * `no-trace` reason is a statement about a step that WAS addressed and had no trace; this is a\n * statement about the question. Reporting an ambiguous address as an absence would be a wrong\n * answer wearing an honest one's clothes — the reader would conclude the run captured nothing,\n * when in fact two steps answered and neither was asked about.\n *\n * It carries the candidates because that is what the caller needs to ask again. A closed reason\n * enum could have said \"ambiguous\" and could not have said which tests to choose between, which\n * would leave the reader to go and find them by hand.\n */\nexport class AmbiguousStepAddressError extends Error {\n constructor(\n readonly runId: string,\n readonly stepIndex: number,\n readonly testIds: readonly string[],\n ) {\n super(\n `Step ${String(stepIndex)} of run ${runId} is ambiguous: ${testIds.join(', ')}. `\n + 'stepIndex is numbered per member test, so name a testId.',\n )\n this.name = 'AmbiguousStepAddressError'\n }\n}\n\n/**\n * Narrow a trace to one record's attribution, keeping BOTH ledgers.\n *\n * The truncation ledger is filtered too, and that is the whole value of the filter: \"why didn't\n * it mention record X\" is answered by X appearing among the CUT candidates with its rank and\n * score, and a filter that kept only served lines would answer that question with silence.\n *\n * A record that appears in neither ledger yields an answered result with two empty ledgers,\n * which is the honest reading: the trace exists, and that record took no part in the brief.\n * Reporting it as `no-trace` would claim nothing was written down.\n */\nfunction narrowToRecord(\n trace: ServedRetrievalTraceV1,\n recordId: string,\n): ServedRetrievalTraceV1 {\n return {\n schemaVersion: trace.schemaVersion,\n servedLines: trace.servedLines.filter((line) => line.recordId === recordId),\n truncated: trace.truncated.filter((line) => line.recordId === recordId),\n }\n}\n\n/**\n * THE answering logic, as a function of what was read back and nothing else.\n *\n * Exported for its own tests. Deliberately takes no `deps`: an implementation that could\n * consult a live index would need a handle, and there is none in scope to give it one.\n *\n * Throws only for the ambiguous address (see {@link AmbiguousStepAddressError}); every other\n * outcome is an arm of the closed union, because absence is a fact about the evidence and the\n * caller has to be able to read it rather than catch it.\n */\nexport function mapStepEvidenceToWhy(\n lookup: StepEvidenceLookup,\n input: BriefWhyInput,\n): BriefWhyResult {\n switch (lookup.kind) {\n case 'run-not-recorded':\n // `artifact-missing` and not a `RunNotFoundError`: a why-question about a run whose\n // handoff has been pruned is exactly the \"go looking\" case D-15 separated from the\n // permanent one, and the surface's message differs.\n return { kind: 'no-trace', reason: 'artifact-missing' }\n case 'step-not-found':\n return { kind: 'no-trace', reason: 'step-not-found' }\n case 'ambiguous-step-address':\n throw new AmbiguousStepAddressError(input.runId, input.stepIndex, lookup.testIds)\n case 'found': {\n const trace = lookup.evidence.retrievalTrace\n if (trace === undefined) {\n // The run predates trace capture, or captured none. Permanent: retrying changes\n // nothing. The brief itself survived, so it is OFFERED — a reader who cannot learn why\n // a line was chosen can at least read the line.\n return {\n kind: 'no-trace',\n reason: 'pre-trace-run',\n servedBrief: lookup.evidence.servedBrief,\n }\n }\n return {\n kind: 'answered',\n trace: input.recordId === undefined ? trace : narrowToRecord(trace, input.recordId),\n }\n }\n }\n}\n\nexport const knowledgeBriefWhySpec: FunctionSpec<BriefWhyInput, BriefWhyResult> = {\n id: KNOWLEDGE_BRIEF_WHY_FUNCTION_ID,\n summary: 'Explain why a served brief said what it said, from the trace written at serve time.',\n resultKind: 'unary',\n input: BriefWhyInputSchema,\n output: BriefWhyResultSchema,\n risk: { name: `fn:${KNOWLEDGE_BRIEF_WHY_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * `no-trace` IS THE HONEST ABSENCE THIS VERB EXISTS FOR (399.1 D-01).\n *\n * KREV-02's whole posture is that a brief whose trace is gone must be SAID to be gone rather than\n * re-derived; the op that answers it is given no serving capability at all. That is an answer the\n * verb is proud of, not a control declining, so the arm is `executed` with the store's own reason.\n */\n classify(output): ClauseVerdict {\n switch (output.kind) {\n case 'answered':\n return { status: 'executed', outcome: 'answered from the persisted retrieval trace' }\n case 'no-trace':\n return { status: 'executed', outcome: `no-trace: ${output.reason}` }\n default:\n return output satisfies never\n }\n },\n async invoke(input, deps) {\n // The DTO speaks a plain string because it crosses a process boundary as JSON; the port\n // speaks the branded id every other run read uses. Narrowing HERE, once, is what keeps both\n // true, and `asRunId` is the same brand `runs.get`'s own input schema applies.\n const lookup = await deps.runs.readStepEvidence(asRunId(input.runId), {\n stepIndex: input.stepIndex,\n ...(input.testId === undefined ? {} : { testId: input.testId }),\n })\n return mapStepEvidenceToWhy(lookup, input)\n },\n}\n","// `knowledge.record.show` — one record with the provenance that justifies it (Phase 387,\n// KREV-01).\n//\n// WIRING over the reader entry's `showRecord`. The op validates its input, dispatches, and\n// renders the closed union it is handed. It has no list to sort: the answer is one record or a\n// named absence, so the 384 total-order convention has nothing to order here — and inventing a\n// sort for a single value would have been ceremony rather than determinism.\n//\n// ABSENCE IS A RESULT, not a refusal this op throws. `runs.get` turns its port's `undefined`\n// into a typed error because a run id that names nothing is a caller mistake; a record id that\n// names nothing is not, because records are TOMBSTONED and forgotten by design (§7.7) and\n// asking about one that has gone is the ordinary thing a reviewer does. So the miss is an arm\n// of the answer, and a store that could not be read at all still throws — the two stay\n// distinguishable, which is the whole reason the union exists.\n\nimport { KnowledgeRecordShowInputSchema, KnowledgeRecordShowResultSchema } from '@vostride/agent-qa-schema'\nimport type {\n KnowledgeRecordShowInput,\n KnowledgeRecordShowResult,\n} from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport const KNOWLEDGE_RECORD_SHOW_FUNCTION_ID = 'knowledge.record.show'\n\nexport const knowledgeRecordShowSpec: FunctionSpec<\n KnowledgeRecordShowInput,\n KnowledgeRecordShowResult\n> = {\n id: KNOWLEDGE_RECORD_SHOW_FUNCTION_ID,\n summary: 'Show one committed knowledge record with its provenance.',\n resultKind: 'unary',\n input: KnowledgeRecordShowInputSchema,\n output: KnowledgeRecordShowResultSchema,\n risk: { name: `fn:${KNOWLEDGE_RECORD_SHOW_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * \"Absence is a RESULT rather than a refusal\" — the contract's own words (399.1 D-01).\n */\n classify(output): ClauseVerdict {\n switch (output.kind) {\n case 'found':\n return { status: 'executed', outcome: 'found — the record with its provenance' }\n case 'not-found':\n return { status: 'executed', outcome: `not-found: ${output.recordId}` }\n default:\n return output satisfies never\n }\n },\n invoke(input, deps) {\n // The id crosses verbatim, including one shaped like a path. That is safe for a structural\n // reason and not a hopeful one: the reader resolves an id against the records it\n // ENUMERATES and never by joining a caller's string onto a path, which is the same\n // T-384-08 discipline `runs.get` carries. Sanitising here would add a second, weaker\n // spelling of a guarantee the read side already makes.\n return deps.knowledge.showRecord(input)\n },\n}\n","// The knowledge change ops' function ids (Phase 387, KREV-01; 432-12, D-05).\n//\n// In their own module for the same structural reason `entities-ids.ts` exists: the card action\n// table advertises `knowledge.forget` (D-11, the MEM row), and an op file that declared its own id\n// beside its spec would close that into an import cycle the moment a card action pointed at it.\n// Declaring them here means each id is one value with one definition and every importer reaches it\n// in one direction.\n//\n// 2026-09-30, 432-12 (D-02/D-05): the three verbs apply in the call. The `.propose` ids are gone\n// with no alias. 2026-10-01, 432-17 (D-05/D-22): `knowledge.proposal.apply` is deleted with the\n// inbox, and its id with it.\n\nexport const KNOWLEDGE_ACCEPT_FUNCTION_ID = 'knowledge.accept'\n\nexport const KNOWLEDGE_REJECT_FUNCTION_ID = 'knowledge.reject'\n\nexport const KNOWLEDGE_FORGET_FUNCTION_ID = 'knowledge.forget'\n","// `runs.start` — the first unbound→bound transition of 384's binding vocabulary (D-16).\n//\n// Everything declared here in 384 is unchanged: the input contract (including the D-10\n// `gateRun` carrier), the acknowledgment it resolves, and the risk descriptor the classifier\n// reads. What arrived in 385 is the implementation, and with it the one line that says what the\n// implementation NEEDS — `boundThrough: 'runInvocation'`. 2026-10-01 (432-23, D-12): the `run`\n// scope it once cost is gone; every door can start a run, and the run core refuses only a\n// production target the config has not opted into (432-03, D-18).\n//\n// That is the whole of this module's say in whether it is bound. The ANSWER belongs to a\n// composition: a host that supplies a run-invocation port lists this op as `bound` and can\n// run it; a host that does not lists it as `unbound` and refuses it by name. The 384 state\n// is therefore not gone, it is one of the two states, and every registry built without an\n// executor still proves D-09's visible-unbound invariant on this very capability.\n//\n// The implementation joins TWO ports on purpose. The invocation port reports only the id of\n// the run it started; every field of the acknowledgment is then read off that run's own\n// durable record through the same reader `runs.get` answers from. A host that resolved an id\n// without running anything gets `RunNotRecordedError` here rather than a fabricated\n// acknowledgment — which is the difference between \"the call returned\" and \"a run happened\".\n\nimport { RunStartAcknowledgementSchema, RunsStartInputSchema } from '@vostride/agent-qa-schema'\nimport type {\n CompletedRunHandoff,\n RunStartAcknowledgement,\n RunsStartInput,\n} from '@vostride/agent-qa-schema'\n\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport const RUNS_START_FUNCTION_ID = 'runs.start'\n\n/**\n * A run was started but no completed-run record can be read back for it.\n *\n * A caller-facing refusal, and the op's anti-fabrication control: the acknowledgment names\n * facts about a run — its scope, its build ordinal, how many member tests it admitted — and\n * every one of them is read off the record the run itself wrote. If the record is absent the\n * honest answer is that nothing is known about the run, never a plausible-looking object\n * assembled from the request. Distinct from `RunNotFoundError`, which answers a caller who\n * asked about a run that was never started here.\n */\nexport class RunNotRecordedError extends Error {\n constructor(readonly runId: string) {\n super(\n `runs.start started ${runId} but no completed-run record was written for it: ` +\n 'the run did not finish, or the host reported a run it did not execute.',\n )\n this.name = 'RunNotRecordedError'\n }\n}\n\n/**\n * Project the run's own durable record into the acknowledgment.\n *\n * Both durable markers are copied from the RECORD rather than echoed from the request, which\n * is what makes the acknowledgment worth reading: it tells a caller the kind of run that\n * actually started, not the kind it asked for.\n */\nfunction toAcknowledgement(document: CompletedRunHandoff): RunStartAcknowledgement {\n return {\n runId: document.runId,\n scope: document.scope,\n executionContext: document.executionContext,\n buildOrdinal: document.buildOrdinal,\n startedAt: document.startedAt,\n testCount: document.tests.length,\n ...(document.gateRun === undefined ? {} : { gateRun: document.gateRun }),\n ...(document.excludedFromOutcomes === undefined\n ? {}\n : { excludedFromOutcomes: document.excludedFromOutcomes }),\n ...(document.plannerLimits === undefined ? {} : { limits: document.plannerLimits }),\n }\n}\n\nexport const runsStartSpec: FunctionSpec<RunsStartInput, RunStartAcknowledgement> = {\n id: RUNS_START_FUNCTION_ID,\n summary: 'Start a test run and acknowledge the run a caller can then read or stream.',\n resultKind: 'unary',\n boundThrough: 'runInvocation',\n input: RunsStartInputSchema,\n output: RunStartAcknowledgementSchema,\n // Pitfall 10, and every field here is load-bearing:\n // `recognized: true` with NO `readOnly` puts the classifier's floor at mutating-local;\n // `declaredTier` states that tier explicitly rather than relying on the floor alone;\n // the name tokens (fn · runs · start) hit neither destructive lexicon, so nothing\n // raises the tier above what is declared.\n // The tier was chosen when `mutating-shared` would have asked, and an ask in a fail-closed\n // context denied, leaving the authoring loop unable to start a run in CI. 2026-10-01 (432-19/\n // 432-23, D-12/D-15): nothing asks or denies on a tier any more; the tier stays the honest\n // classification. Starting a run really is local: it spends this machine's resources and\n // writes into this project's run directory. It touches nothing another party shares.\n risk: {\n name: `fn:${RUNS_START_FUNCTION_ID}`,\n recognized: true,\n declaredTier: 'mutating-local',\n },\n /**\n * AN ACKNOWLEDGEMENT IS A START, NOT AN OUTCOME (399.1 D-01).\n *\n * This op returns when the run has been ACCEPTED, long before it has a verdict — so the outcome\n * names the run a person can follow and how much it took on, and says nothing about how it went.\n * A refusal to start is a throw and already reaches the engine's `failed` mapping.\n */\n classify(output): ClauseVerdict {\n return {\n status: 'executed',\n outcome: `started ${output.runId} — ${output.testCount} test(s) on ${output.scope}`,\n }\n },\n async invoke(input, deps) {\n // `invokeFunction` already refused this composition on the same fact, so reaching here\n // with no port means an in-layer caller holding the spec directly. The unbound state has\n // no back door: the refusal is the same named error either way (384, D-09).\n const runInvocation = deps.runInvocation\n if (runInvocation === undefined) {\n throw new FunctionNotBoundError(RUNS_START_FUNCTION_ID)\n }\n\n const started = await runInvocation.start(input)\n const document = await deps.runs.get(started.runId)\n if (document === undefined) {\n throw new RunNotRecordedError(started.runId)\n }\n return toAcknowledgement(document)\n },\n}\n","// The card's `actions[]` (Phase 387, ENTY-02 / D-11).\n//\n// A card's actions are REGISTRY OP REFS. A card can therefore only advertise capabilities the\n// registry already contains, which is what makes an advertised action invokable identically\n// over chat, CLI and MCP, subjects it to safe-mode listing filters for free, and lets 397's\n// parity suite assert that every action any card offers actually resolves. A freeform action\n// string would have been a second capability vocabulary — the private-power drift L10 exists\n// to prevent — and there is deliberately no way to construct one here.\n//\n// EVERY id below is IMPORTED from the module that declares it, never written as a literal.\n// That is the drift proof: renaming an op's id is a compile error in this table rather than a\n// card that keeps advertising a capability nothing answers to. The one place a literal would\n// have been convenient — a table keyed by id string — is exactly where it would have been\n// wrong.\n//\n// `inputSeed` carries the entity's OWN references. A seed is a seed and may be partial (the\n// why-verb needs a step index no card knows), but every field it does set is a real field of\n// that op's input contract, filled with a value this entity actually is. What it must never be\n// is a value that ADDRESSES BY COINCIDENCE: `knowledge.record.show` is seeded with a MEM\n// entity's machine id because in this store a bundle directory's name IS the record id\n// (`listBundles` and `showRecord` both read `bundle.manifest.id`), not because the two strings\n// happen to look alike.\n//\n// One decision worth stating rather than leaving to be inferred. `runs.start` is in the\n// default spec list but binds only in a composition that supplies a `runInvocation` port, so a\n// read-only host lists it `unbound`. A TST card advertises it anyway, because D-11 says cards\n// advertise what the REGISTRY contains and `bindingStatus` exists precisely so an unbound\n// capability is VISIBLE rather than silent (D-09). Advertising is not granting: the ref still\n// crosses `invokeFunction`, which refuses an unbound id by name and gates every scope. A card\n// that hid the capability would be making a claim about the host that the card producer — which\n// receives no caller and no composition — is in no position to make.\n\nimport type { ActionRef, EntityDescriptor, EntityKind } from '@vostride/agent-qa-schema'\n\nimport { ENTITIES_GET_FUNCTION_ID } from '../ops/entities-ids.js'\nimport { KNOWLEDGE_BRIEF_WHY_FUNCTION_ID } from '../ops/knowledge-brief-why.js'\nimport { KNOWLEDGE_RECORD_SHOW_FUNCTION_ID } from '../ops/knowledge-record-show.js'\nimport { KNOWLEDGE_FORGET_FUNCTION_ID } from '../ops/knowledge-review-ids.js'\nimport { RUNS_GET_FUNCTION_ID } from '../ops/runs-get.js'\nimport { RUNS_START_FUNCTION_ID } from '../ops/runs-start.js'\n\ntype ActionTable = (descriptor: EntityDescriptor) => ActionRef[]\n\n/** The card itself, addressed by its own short-ID. Useful wherever a card is one of several. */\nfunction openCard(descriptor: EntityDescriptor): ActionRef {\n return {\n functionId: ENTITIES_GET_FUNCTION_ID,\n label: 'Open card',\n inputSeed: { ref: descriptor.shortId },\n }\n}\n\n/**\n * THE per-kind action table.\n *\n * `satisfies Record<EntityKind, …>` for the same reason the fact projections are: a sixth\n * kind must answer what it offers rather than inheriting a fallback. There is no fallback.\n */\nexport const ENTITY_ACTION_TABLES = {\n TST: (descriptor) => [\n openCard(descriptor),\n {\n functionId: RUNS_START_FUNCTION_ID,\n label: 'Run this test',\n // The variadic pattern operand `runs.start` already takes — the test's own identity.\n inputSeed: { patterns: [descriptor.machineId] },\n },\n ],\n RUN: (descriptor) => [\n openCard(descriptor),\n {\n functionId: RUNS_GET_FUNCTION_ID,\n label: 'Open run',\n inputSeed: { runId: descriptor.machineId },\n },\n {\n functionId: KNOWLEDGE_BRIEF_WHY_FUNCTION_ID,\n label: 'Explain a step',\n // DELIBERATELY partial: the why-verb answers about one step, and which step is the\n // caller's question rather than the entity's fact. Seeding a step index would be the\n // card guessing what a human meant, which is the never-guess floor in miniature.\n inputSeed: { runId: descriptor.machineId },\n },\n ],\n MEM: (descriptor) => [\n openCard(descriptor),\n {\n functionId: KNOWLEDGE_RECORD_SHOW_FUNCTION_ID,\n label: 'Show record',\n inputSeed: { recordId: descriptor.machineId },\n },\n {\n // D-11's table completion (387-08). 2026-09-30, 432-12 (D-05/D-09): forget is the explicit\n // removal and it applies in the call, so the action says what it does. The record is\n // tombstoned, never destroyed, and the card at this address then reads `tombstoned`. The\n // seed addresses the RECORD grain because a descriptor carries the machine id it was\n // sighted under, and the bundle grain takes a short-ID whose resolution is the writer's job\n // rather than the card's.\n functionId: KNOWLEDGE_FORGET_FUNCTION_ID,\n label: 'Forget this record',\n inputSeed: { target: { grain: 'record', recordId: descriptor.machineId } },\n },\n ],\n POL: (descriptor) => [openCard(descriptor)],\n TGT: (descriptor) => [openCard(descriptor)],\n} as const satisfies Record<EntityKind, ActionTable>\n\n/** Every id this module can ever advertise — the set the resolvability assertion iterates. */\nexport const ADVERTISED_FUNCTION_IDS: readonly string[] = [\n ENTITIES_GET_FUNCTION_ID,\n RUNS_START_FUNCTION_ID,\n RUNS_GET_FUNCTION_ID,\n KNOWLEDGE_BRIEF_WHY_FUNCTION_ID,\n KNOWLEDGE_RECORD_SHOW_FUNCTION_ID,\n KNOWLEDGE_FORGET_FUNCTION_ID,\n]\n\nexport function actionsForKind(descriptor: EntityDescriptor): ActionRef[] {\n return ENTITY_ACTION_TABLES[descriptor.kind](descriptor)\n}\n","// The per-kind `keyFacts[]` projections (Phase 387, ENTY-02 / D-04 / D-12 / D-19).\n//\n// D-12: a key fact is COMPUTED DETERMINISTICALLY FROM STORE DATA and is never LLM-authored.\n// This module is where that promise is kept, and it is kept structurally rather than by\n// discipline: every function here is a pure function of values it is handed, it imports\n// nothing but the schema vocabulary, and it has no parameter through which a model, a clock,\n// a filesystem or a network could be reached. A companion source scan asserts the absence of\n// a model import with a planted-violation control, because \"no LLM wrote this\" is exactly the\n// kind of claim that is easy to state and easy to stop being true.\n//\n// WHAT A KIND MAY SAY IS A TABLE, not a switch — `KEY_FACT_PROJECTIONS` is written\n// `satisfies Record<EntityKind, …>`, so a sixth kind is a type error here rather than a\n// card that silently renders the generic facts. That table is also the SEAM the phase's\n// stubs land on: today an `EntityDescriptor` carries the identity a store reported, the title,\n// the status and (for a renamed target) the successor, and nothing else, because only the\n// `MEM` sighting source is registered in any composition (387-01, unchanged by 387-03). A run's\n// verdict ordinal and a bundle's record count are facts the store does not yet HAND anybody,\n// and inventing labels for values nothing produces would be exactly the LLM-authored-content\n// failure this module exists to exclude, wearing a deterministic costume. Each kind's richer\n// facts land in its row below on the day its sighting source reports them.\n//\n// The one place richer content exists TODAY is the forget receipt (D-19), which is designed\n// to be both the apply verb's return value and the content a forgotten entity's permanent\n// address resolves to afterwards (D-04). `forgetReceiptKeyFacts` is that second use.\n\nimport { ENTITY_IDENTITY_FACT_LABELS, formatEntityUri } from '@vostride/agent-qa-schema'\nimport type {\n EntityDescriptor,\n EntityKind,\n ForgetReceiptV1,\n KeyFact,\n QuarantineEntryState,\n} from '@vostride/agent-qa-schema'\n\n/**\n * What each kind CALLS the machine id its address maps FROM — RE-EXPORTED, declared in `schema`.\n *\n * The table moved to `schema/src/entity/entity-card.ts` in 400-08 and this line is the re-export\n * every existing importer keeps reading. It moved because it is the only thing that makes the\n * machine id readable OFF a card: the card shape carries no `machineId` field, so the dashboard's\n * entity-card renderer — which routes to pages keyed by machine id — has to be able to NAME the\n * fact that carries it. A second copy in the surface would be a label free to drift from the one\n * the producer writes with; fishing the id out of an `actions[]` seed would be the\n * addressing-by-coincidence `actions.ts` forbids. One declaration, beside the card contract, read\n * by the writer here and by every reader there.\n */\nexport { ENTITY_IDENTITY_FACT_LABELS }\n\n/** The label the D-03 rename fact renders under, named once so a test can pin it. */\nexport const ENTITY_RENAMED_TO_FACT_LABEL = 'renamed to'\n\n/**\n * The labels a quarantined `TST` card projects under, in the order they render (390 D-12/D-17).\n *\n * Three facts, and the third is the only interesting choice. D-17 puts the OCCURRENCE COUNT\n * (\"3rd occurrence in 5 builds\") in the rendered sentence, where a live provider join can compute\n * it; this producer is pure by construction and takes no ports, so it carries the occurrence\n * context the LEDGER ITSELF records — which class of failure recurred, and since when. Reaching\n * for the count here would mean giving the card producer a store handle, which is the one thing\n * ENTY-02's determinism claim rests on it not having.\n *\n * THAT RULE DOES NOT RANGE THE RE-ENTRY HISTORY (390-20). D-17's occurrence count is a count over\n * BUILDS — \"3rd occurrence in 5 builds\" is a join against a live provider, and it is still out of\n * reach here for exactly the reason above. `enteredCount` and `firstEnteredAt` are a different\n * number: the fold DERIVES them from `entered` events already committed to the ledger, and they\n * arrive ON THE ENTRY this module is handed, beside the `owner` and `expiresAt` it has always\n * rendered. Stating them costs this producer no handle, no port and no clock read — it stays a\n * pure function of its argument, which is the whole of what ENTY-02 pins. This distinction is\n * written down because the paragraph above, read alone, looks like it forbids that render, and a\n * reader who found no answer here would be RIGHT to delete a purity violation.\n */\nexport const QUARANTINE_FACT_LABELS = {\n owner: 'quarantine owner',\n expires: 'quarantine expires',\n occurrence: 'quarantine occurrence',\n} as const\n\n/** The labels a forget receipt projects under, in the order they render (D-19). */\nexport const FORGET_RECEIPT_FACT_LABELS = {\n records: 'records forgotten',\n recordIds: 'record ids',\n projections: 'projections scrubbed',\n forgottenAt: 'forgotten at',\n} as const\n\nfunction identityFact(descriptor: EntityDescriptor): KeyFact {\n return {\n label: ENTITY_IDENTITY_FACT_LABELS[descriptor.kind],\n value: descriptor.machineId,\n }\n}\n\n/**\n * D-03's \"with its rename visible\", made literal.\n *\n * The old address keeps resolving to the old name — anything else would make an existing CI\n * log's reference quietly mean a different target — and the card is where a reader learns\n * what it became.\n *\n * It is reachable only from the `TGT` row of the table below, and the successor URI is built\n * for `TGT` unconditionally, which is why there is no `kind === 'TGT'` guard in here. There\n * WAS one, and a mutation probe measured it inert: with it removed every case still passed,\n * because the only thing that decides which kinds show a rename is the table. A second guard\n * that agrees with the table today is a second place the rule could stop being true with\n * nothing comparing them (387-01 D-1, same finding). The table is the one mechanism, and the\n * probe that pins it adds this projection to a kind that must not have it.\n */\nfunction renameFact(descriptor: EntityDescriptor): KeyFact[] {\n if (descriptor.successorMachineId === undefined) return []\n return [{\n label: ENTITY_RENAMED_TO_FACT_LABEL,\n value: descriptor.successorMachineId,\n ref: formatEntityUri('TGT', `TGT-${descriptor.successorMachineId}`),\n }]\n}\n\n/**\n * An open quarantine window rendered as facts (390 D-12).\n *\n * Reached only from the `TST` row of the table below, and only for an entry the join already\n * decided is suppressing — an expired or released window contributes NOTHING here, because the\n * card's status says `active` for both and a fact announcing a quarantine beside it would be the\n * card contradicting itself.\n *\n * WHICH INSTANT THE OCCURRENCE FACT ANSWERS (390-20), and why it is not always the same one. An\n * entry on its FIRST window has one instant to state and states it exactly as it always has. An\n * entry on a LATER lap has two, and since 390-27 it states BOTH, in this order and for these\n * reasons: this test's quarantine history began at `firstEnteredAt`, which LEADS because it is the\n * key `triageOrder` (knowledge-local `quarantine/operations.ts`) sorts the triage queue on; the\n * CURRENT window opened at `enteredAt`, which follows because it is the premise the sibling\n * `expires` fact is DERIVED from. Each half answers a hazard the other cannot. Leading with the\n * current window's instant beside a clause promising RECURRENCE handed a human two different\n * answers to one question: the queue ordering a test by January while the card said April. Stating\n * the history's instant alone printed a computed deadline beside a premise the card had dropped,\n * so a reader could not check `expires` against anything the card showed (IN-02). Stating both, in\n * that order, is what closes each without re-opening the other — see the `occurrenceValue`\n * docstring below, which renders exactly this. `quarantine-ledger.ts`'s own docstring calls these\n * two instants close enough to be exactly the first hazard; naming the sibling here is cheaper\n * than a test asserting the two agree, and it is what keeps the next edit from re-opening the\n * drift.\n */\nfunction quarantineFacts(entry: QuarantineEntryState | undefined): KeyFact[] {\n if (entry === undefined) return []\n return [\n { label: QUARANTINE_FACT_LABELS.owner, value: entry.owner },\n { label: QUARANTINE_FACT_LABELS.expires, value: entry.expiresAt },\n { label: QUARANTINE_FACT_LABELS.occurrence, value: occurrenceValue(entry) },\n ]\n}\n\n/**\n * The occurrence sentence's two arms — ONE fact either way.\n *\n * The history rides in the sentence rather than in a second fact deliberately: the card's bound\n * is on fact COUNT, and a test being quarantined more often must not be able to move a number\n * {@link projectKeyFacts} reasons about below. Both arms are a fixed shape over the entry.\n *\n * The first-window arm is not an optimisation, it is the honest render. \"1 quarantine window\n * since <the same instant the sentence would otherwise have named>\" announces a lap count of one\n * and repeats itself, and every card rendered before the history existed was a first-window card\n * that must stay byte-identical.\n *\n * NO DURATION, NO HUMANISED INTERVAL. The instant is what the ledger holds and what every other\n * quarantine fact renders; \"214 days ago\" would make this fact a function of the wall clock in a\n * producer whose determinism is pinned and which holds no clock to read.\n *\n * THE LATER-LAP ARM CARRIES BOTH INSTANTS (390-27, IN-02). The sibling `expires` fact is DERIVED\n * from `enteredAt`, and an arm stating only `firstEnteredAt` put a computed deadline on the card\n * beside a premise the card had dropped — a human reading \"expires 2026-09-04\" next to \"4 windows\n * since 2026-06-01\" cannot check the one against the other, because the instant the deadline was\n * measured from appears nowhere. The two instants answer DIFFERENT questions, in the fold's own\n * words (`quarantine/ledger.ts`): `firstEnteredAt` is when this test's quarantine history began —\n * what `triageOrder` sorts on, so the history clause still LEADS — and `enteredAt` is when the\n * CURRENT window opened, which is what `expiresAt` and the computed state are about. Stating both\n * is what makes the card self-checkable; dropping either re-opens one of the two defects.\n *\n * A first window has only one instant to state and states it exactly as it always has, so this\n * addition cannot reach the first-window arm: that arm is byte-identical to the render that\n * shipped before any history existed.\n */\nfunction occurrenceValue(entry: QuarantineEntryState): string {\n const history = entry.enteredCount > 1\n ? `${entry.enteredCount} quarantine windows since ${entry.firstEnteredAt}` +\n `; current window since ${entry.enteredAt}`\n : `quarantined since ${entry.enteredAt}`\n return `${entry.verdictClass} failures recurring; ${history}`\n}\n\n/**\n * A forget receipt rendered as facts (D-19 + D-04).\n *\n * The record ids are rendered as ONE fact carrying the whole list rather than as one fact per\n * record, and that is the reconciliation of two rules that would otherwise fight: D-19 says\n * forgetting a bundle lists every member record and nothing is silently partial, while the\n * card contract bounds the number of facts. A per-record fact would have had to be truncated,\n * which is precisely the silent partiality D-19 forbids; a single fact carrying the full list\n * keeps the enumeration complete and the card scannable.\n *\n * Ids are SORTED. A receipt's own array order is whatever the forget verb walked, and a card\n * whose facts reorder between two renders of unchanged state is not deterministic (ENTY-02's\n * ordering edge). Sorting is what makes the projection a function of the receipt's CONTENT\n * rather than of the order it happened to arrive in.\n */\nexport function forgetReceiptKeyFacts(receipt: ForgetReceiptV1): KeyFact[] {\n const recordIds = [...receipt.tombstonedRecords]\n .map((record) => record.recordId)\n .sort((left, right) => (left < right ? -1 : left > right ? 1 : 0))\n const projections = [...receipt.projectionsScrubbed].sort(\n (left, right) => (left < right ? -1 : left > right ? 1 : 0),\n )\n\n return [\n {\n label: FORGET_RECEIPT_FACT_LABELS.records,\n value: String(recordIds.length),\n },\n ...(recordIds.length === 0 ? [] : [{\n label: FORGET_RECEIPT_FACT_LABELS.recordIds,\n value: recordIds.join(', '),\n }]),\n ...(projections.length === 0 ? [] : [{\n label: FORGET_RECEIPT_FACT_LABELS.projections,\n value: projections.join(', '),\n }]),\n {\n label: FORGET_RECEIPT_FACT_LABELS.forgottenAt,\n value: new Date(receipt.forgottenAt).toISOString(),\n },\n ]\n}\n\n/** What a projection is handed: the store's descriptor, plus the receipt when one survives. */\nexport interface KeyFactInput {\n readonly descriptor: EntityDescriptor\n /** The forget receipt for a forgotten `MEM` bundle (D-04/D-19), when the caller holds one. */\n readonly forgetReceipt?: ForgetReceiptV1\n /**\n * The SUPPRESSING quarantine window for a `TST` entity (390), already joined by the producer.\n *\n * Handed in as a value for the same reason the receipt is: this module is pure over what it is\n * given, and a member through which a ledger could be read would be a port in disguise. The\n * join itself is spelled once, beside the status it also decides.\n */\n readonly quarantineEntry?: QuarantineEntryState\n}\n\ntype KeyFactProjection = (input: KeyFactInput) => KeyFact[]\n\n/**\n * THE per-kind projection table.\n *\n * `satisfies Record<EntityKind, …>` is the completeness guarantee: adding a sixth kind and\n * forgetting to say what its card shows is a type error, not a card that renders whatever the\n * fallback happened to be. There is deliberately no fallback.\n */\nexport const KEY_FACT_PROJECTIONS = {\n TST: ({ descriptor, quarantineEntry }) => [\n identityFact(descriptor),\n ...quarantineFacts(quarantineEntry),\n ],\n RUN: ({ descriptor }) => [identityFact(descriptor)],\n MEM: ({ descriptor, forgetReceipt }) => [\n identityFact(descriptor),\n ...(forgetReceipt === undefined ? [] : forgetReceiptKeyFacts(forgetReceipt)),\n ],\n POL: ({ descriptor }) => [identityFact(descriptor)],\n TGT: ({ descriptor }) => [identityFact(descriptor), ...renameFact(descriptor)],\n} as const satisfies Record<EntityKind, KeyFactProjection>\n\n/**\n * Project one entity's key facts (D-12).\n *\n * BOUNDED BY CONSTRUCTION, not by truncation, and the difference is the whole reason the\n * receipt renders as it does. Every row above emits a fixed, small number of facts whatever\n * its input contains — the receipt's record ids are ONE fact carrying the whole list rather\n * than one fact per record — so no store state can push a card past\n * `ENTITY_CARD_MAX_KEY_FACTS` and the schema's `.max()` can never fire.\n *\n * An earlier revision truncated here with a `.slice()`. A mutation probe measured it\n * unreachable: removing it left every case green, because the largest projection any input\n * can produce is five facts. It was a second bound that agreed with the first, and it would\n * have been the WRONG repair anyway — silently dropping the tail of a forget receipt is\n * exactly the silent partiality D-19 forbids. What replaced it is a test that exhausts the\n * projection table and a probe that makes the enumeration per-record, which is the mutation\n * the bound actually protects against.\n */\nexport function projectKeyFacts(input: KeyFactInput): KeyFact[] {\n return KEY_FACT_PROJECTIONS[input.descriptor.kind](input)\n}\n","// `agent.explain` — what this product can do, answered from the catalog (Phase 398 plan 07 —\n// XPLN-02, D-09 / D-10 / D-11 / D-12).\n//\n// THE FIRST OP ADDED SINCE THE PARITY SUITE CLOSED, and registering it is the decision (D-09).\n// \"What can you do\" could have been a private power of whatever surface answered it — a REPL\n// branch, an MCP handler, a paragraph in a prompt. Every one of those is a capability the\n// catalogue does not list, which is the private-power pattern §3's L10 law abolishes and which the\n// 397 census exists to make impossible. So it is a registered op: golden row, scenario row, catalog\n// row, MCP partition entry, all added through their own machinery.\n//\n// THE OP OWNS ORDER AND NOTHING ELSE. Everything load-bearing was proven in plan 04 and is called\n// here, not re-implemented: the renderer quotes every character a person reads out of a catalog row\n// (D-10), the scorer picks the abstention's closest capabilities deterministically (D-11), and the\n// contract's two arms are the whole vocabulary. What this file adds is the SEQUENCE — load, cite,\n// resolve, and on the abstention arm record BEFORE rendering — plus the refusal by name when no\n// host bound the port.\n//\n// WHY `recordAbstained` RUNS BEFORE THE RENDER (398-04's note 2). The abstention text NAMES the\n// docs-gap path, and `docsGap.logged` is an input to the renderer rather than a flag mutated after\n// it: a line claiming a record that was never written is the same class of untrue statement this\n// whole feature is built to prevent. Rendering first and patching the boolean afterwards would\n// leave the TEXT stale while the field read correctly, which is the worst of both.\n//\n// THIS FILE READS NO ENVIRONMENT, OPENS NO FILE, AND COMPOSES NO INVOCATION STRING. `packages/agent`\n// is storageNeutral, so the catalog arrives as data and the coverage append happens behind the port\n// (see `explain/port.ts` for why each of the four methods is a port). And no slash form is spelled\n// here: `invocationForRow` in the renderer is the one place a row's reachable form is composed\n// (D-10), so a second spelling in an op could not drift out of step with it — there is none.\n\nimport { ExplainInputSchema, ExplainOutputSchema } from '@vostride/agent-qa-schema'\nimport type { CatalogRow, ExplainInput, ExplainOutput } from '@vostride/agent-qa-schema'\n\nimport { closestCapabilities, renderExplainOutput } from '../../explain/index.js'\nimport type { CapabilityCatalogPort } from '../../explain/index.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionDeps, FunctionSpec } from '../spec.js'\n\n/**\n * Lowercase dot taxonomy (384 D-15): the `agent` domain, already a pinned member of the conformance\n * suite's `domain-list.ts` because `agent.ask` lives there. No taxonomy widening — an explain is a\n * thing the AGENT does about itself, which is exactly what that domain's charter covers.\n *\n * The literal appears here once; the scenario rows, the composition and every later surface name\n * this constant.\n */\nexport const EXPLAIN_FUNCTION_ID = 'agent.explain'\n\n/**\n * The abstention arm, with the coverage record appended first (D-11).\n *\n * `closestCapabilities` is called HERE as well as inside the renderer, and the duplication is\n * deliberate rather than an oversight: the record must carry the same closest set the person is\n * shown, and the scorer is a total deterministic function of (query, rows) — proven in plan 04\n * against run order, row order and locale — so the two computations cannot disagree. The\n * alternative, threading the set through the renderer's return value, would have made the render a\n * two-phase call for the sake of avoiding one pure function evaluation.\n *\n * AN APPEND FAILURE IS NOT AN ANSWER FAILURE. The coverage log is SURF-FUT-02's demand signal, not\n * part of what the person asked for, so a host whose log cannot be written still gets its honest\n * abstention — and says so, because `docsGapLogged` stays false and the renderer's frozen template\n * set has the sentence for it. Letting the throw out would turn a disk problem into \"explain is\n * broken\", which is a worse answer than the one it would be replacing.\n */\nfunction abstainAndRecord(\n port: CapabilityCatalogPort,\n query: string,\n rows: readonly CatalogRow[],\n): ExplainOutput {\n const closestRowIds = closestCapabilities(query, rows)\n\n let docsGapLogged = false\n try {\n port.recordAbstained({ query, closestRowIds })\n docsGapLogged = true\n } catch {\n // Deliberately swallowed — see the note above. The renderer reports the absence in the text.\n }\n\n // An EMPTY citation is the honest input for every path that reaches here: the empty-catalog arm\n // has nothing to cite, and the ghost-id arm's citation was refused wholesale rather than filtered\n // (the renderer's all-or-nothing control flow). Re-rendering with `citedRowIds: []` therefore\n // states what is true — nothing resolved — instead of carrying a rejected citation forward.\n return renderExplainOutput({ citedRowIds: [] }, rows, { query, docsGapLogged })\n}\n\nexport const explainSpec: FunctionSpec<ExplainInput, ExplainOutput> = {\n id: EXPLAIN_FUNCTION_ID,\n // One line, and it is the line the catalog RENDERS for this row — descriptions live on the spec\n // so one source feeds chat, MCP and the catalogue (396 D-16 / 398 D-08).\n summary:\n 'Answer a question about what this product can do by citing the capability catalog, or say '\n + 'plainly that the catalog does not ground an answer.',\n // 2026-10-01 (432-26, D-12): no scope. This op once declared `read` alone so that it stayed\n // listable in safe mode; safe mode and scopes are deleted, and every caller lists and calls it.\n resultKind: 'unary',\n // D-09: the catalog reaches this op through a port bound at `composeLocalAgent()` (385 D-15). A\n // composition without one lists the capability `unbound` BY NAME rather than degrading to a\n // model-only answer — an explain that silently lost its catalog is precisely an explain that\n // answers from model memory, which is the one behaviour XPLN-02 exists to forbid.\n boundThrough: 'capabilityCatalog',\n input: ExplainInputSchema,\n output: ExplainOutputSchema,\n // Read-only and recognized: it starts nothing, writes nothing a caller can address, and the one\n // byte it appends is a local coverage line about a question it was asked.\n risk: { name: `fn:${EXPLAIN_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * The answer lines this op composed, on their way to the turn's `answer` field (398-13 · D-21).\n *\n * MIGRATED FROM `turn-engine.ts` BY 399.1-03, ARGUMENT INTACT. It lived there as\n * `explainAnswerLines`, an explicit comparison of the running clause's `functionId` against this\n * op's id — a render rule in the engine, which by construction could only ever render what\n * somebody had thought to name there. D-04's promote decision moved it here: this op knows what\n * its own result deserves to have said about it, and the engine no longer knows this op exists.\n *\n * THE RECEIPT CHARTER IS UNTOUCHED, and that is still the whole reason these lines take THIS\n * channel rather than the receipt's. The receipt stays the MAP — the plain `agent.explain\n * completed` line — and the territory travels on the field `renderTurn` already prints and `ask`\n * already shares. A second carrier on the receipt would put the answer inside the map.\n *\n * PARSED, NEVER CAST, and a parse failure renders NOTHING extra: the fold fails OPEN by contract\n * (`foldFunctionResult`), so an unreadable result costs a person legibility and never the record.\n * Every character of `renderedLines` was quoted out of a committed catalog row by the renderer\n * (D-10), so nothing a model wrote can ride this channel — which is why the parse is here and not\n * a cast: a doctored result must not become a door for prose.\n *\n * BOTH ARMS RENDER. An abstention's lines are the honest \"the catalog does not ground an answer\",\n * and XPLN-02's whole claim is that saying so plainly is an ANSWER a person is owed, not a silence.\n */\n renderResult(output): readonly string[] {\n const parsed = ExplainOutputSchema.safeParse(output)\n return parsed.success ? parsed.data.renderedLines : []\n },\n /**\n * AN ABSTENTION IS AN HONEST ANSWER, NOT A CONTROL DECLINING (399.1 D-01/D-02, plan 03's razor).\n *\n * XPLN-02's whole claim is that \"the catalog does not ground an answer\" is a result this op is\n * PROUD of. Folding it to `refused` would tell a person a guardrail stopped their question when\n * what happened is that the question was answered truthfully.\n *\n * COUNTS AND NO TERRITORY, and here that is load-bearing rather than stylistic. The answer text\n * is this op's `renderResult` output and reaches the turn's `answer` field; a receipt outcome\n * carrying a cited row's description would put the territory back inside the map, which is the\n * one thing `explain.test.ts`'s receipt-charter cell exists to red on.\n */\n classify(output): ClauseVerdict {\n switch (output.kind) {\n case 'answer':\n return {\n status: 'executed',\n outcome: `answered — ${output.citations.length} capability citation(s)`,\n }\n case 'abstention':\n return {\n status: 'executed',\n outcome: `abstention — not grounded; `\n + `${output.closestRowIds.length} closest row(s) offered`,\n }\n default:\n return output satisfies never\n }\n },\n async invoke(input, deps: FunctionDeps) {\n const port = deps.capabilityCatalog\n if (port === undefined) {\n throw new FunctionNotBoundError(EXPLAIN_FUNCTION_ID)\n }\n\n const rows = await port.loadCatalog()\n\n // SC-2, at the seam where it is decidable: a catalog with no rows has nothing to ground an\n // answer in, so the model is never asked. Short-circuiting rather than prompting an empty\n // grounding set is what makes \"an empty catalog abstains rather than inventing\" a property of\n // the control flow instead of a hope about what a model does with no data.\n if (rows.length === 0) {\n return abstainAndRecord(port, input.query, rows)\n }\n\n // D-10: the model's WHOLE output contract is `ExplainCitation`, which has no field a command\n // fits in, and the implementation is obliged to pass `rows` as the grounding data. Anything it\n // cites that no row answers to is a ghost, and the renderer answers ghosts by abstaining.\n const citation = await port.citeCapabilities(input.query, rows)\n const output = renderExplainOutput(citation, rows, { query: input.query })\n\n if (output.kind === 'answer') {\n // D-14: a COUNTER and no payload. The query is the one free-text value in this feature and it\n // travels to the local coverage log or nowhere.\n port.recordAnswered()\n return output\n }\n\n // The renderer already decided this is an abstention; it is re-rendered rather than mutated so\n // the docs-gap sentence and the `docsGap.logged` field are composed together, once, from the\n // same fact.\n return abstainAndRecord(port, input.query, rows)\n },\n}\n","// Cite-and-resolve: the deterministic half of `explain` (Phase 398 plan 04 — XPLN-02, D-10 / D-11\n// / D-12; threats T-398-09, T-398-10).\n//\n// THE CANONICAL ROW-ID SCHEME, spelled once and here:\n//\n// op:<registry op id> e.g. op:runs.start\n// alias:<chat alias> e.g. alias:run\n// skill:<skill name> e.g. skill:agent-qa-authoring\n//\n// Kind-prefixed because the three kinds share a namespace of words a person types: `run` is a chat\n// alias AND part of two op ids, and an unprefixed id would make \"which row did you mean\" a\n// question with two answers. The within-kind half is `catalogRowKey` from the schema package, so\n// this file adds the prefix and invents no second notion of a row's identity. Plan 07's catalog\n// feed cites rows by exactly these ids.\n//\n// WHY THIS FILE IS THE MECHANISM AND NOT A PRECAUTION. D-10's claim is that `explain` can never\n// answer from model memory. The way that claim usually fails is the 392 failure class: a\n// structural hole closed by rewriting a prompt. Here the model's whole output contract is\n// `ExplainCitation`, which has no field a command fits in, and this renderer builds every\n// character a person reads out of catalog rows. So the property is not \"the model was told not to\n// invent\" — it is that there is no path from model text to rendered command. Two total properties\n// carry it, and both are cells in `__tests__/renderer.test.ts`:\n//\n// 1. EVERY quoted form in an answer resolves to a cited row. Stated over the whole output, not\n// as a scan for forbidden shapes — a guard that can only refuse what it can NAME is a guard\n// you close by naming more things, forever.\n// 2. Model prose is INERT: the output is a total function of (resolved rows, cited order), so\n// the guarantee is quantified over ARBITRARY prose rather than over the prose we thought of.\n//\n// ALL-OR-NOTHING, DELIBERATELY. One unresolvable id abstains the WHOLE output rather than\n// answering over the ids that did resolve. A partial answer is the shape that reads as grounded\n// while carrying an unexplained absence, and a person cannot tell which half they are holding —\n// the chat resolver table refuses partial matches for the same reason (\"it is not a resolution\n// and it must not be a partial one\").\n\nimport { catalogRowKey } from '@vostride/agent-qa-schema'\nimport type {\n CatalogRow,\n ExplainCitation,\n ExplainCitedCapability,\n ExplainOutput,\n} from '@vostride/agent-qa-schema'\n\nimport { DEFAULT_CLOSEST_COUNT, closestCapabilities } from './scorer.js'\n\n/**\n * Every fixed string an abstention can show a person, frozen and in one place (prohibition P2).\n *\n * A CLOSED SET is what makes the no-blame requirement checkable at all. \"Does the output shame the\n * user\" is not decidable over strings composed ad hoc at three call sites; over a frozen set of\n * five it is a review of five sentences, and the P2 cell scans the complete set rather than a\n * sample of it. Nothing here blames the asker, hedges into false confidence, upsells, or offers a\n * partial answer to soften the refusal.\n */\nexport const EXPLAIN_ABSTENTION_TEMPLATES = Object.freeze({\n uncertain:\n 'I am not certain: I could not ground an answer to that in the capability catalog, so I am not going to guess one.',\n emptyCatalog:\n 'No capability catalog is loaded here, so there is nothing to ground an answer in.',\n closestPrefix: 'The closest capability the catalog carries is',\n noClose: 'Nothing in the catalog reads close to that.',\n gapLogged:\n 'Recorded as a documentation gap in the local coverage log under `.agent-qa/` — the question stays on this machine.',\n gapNotLogged:\n 'No coverage log is bound here, so this gap was not recorded.',\n})\n\n/** The canonical row id — the scheme documented in this file's header. */\nexport function catalogRowId(row: CatalogRow): string {\n return `${row.kind}:${catalogRowKey(row)}`\n}\n\n/**\n * How this row is reached, in the row's OWN form.\n *\n * - op rows get the `/fn <id>` passthrough, which the chat resolver table's one generic branch\n * makes true for every registry op — so this is the form with no per-op maintenance and no\n * chance of naming a door that is not there.\n * - alias rows get `/<alias>`, and the alias comes from the ROW, whose value the catalog producer\n * derived by running the shipped resolver table. Writing an alias literal here would be the\n * second capability vocabulary that table's header forbids.\n * - skill rows get the skill's name: a skill is not invoked with a slash, and inventing a syntax\n * for it would be exactly the fabrication this file exists to prevent.\n */\nexport function invocationForRow(row: CatalogRow): string {\n switch (row.kind) {\n case 'op':\n return `/fn ${row.id}`\n case 'alias':\n return `/${row.alias}`\n case 'skill':\n return row.name\n }\n}\n\n/** The op row's declared required inputs, verbatim. Never guessed, never a synthesised example. */\nfunction requiredParamsOf(row: CatalogRow): readonly string[] {\n if (row.kind !== 'op') return []\n const declared = (row.params as Record<string, unknown>)['required']\n if (!Array.isArray(declared)) return []\n return declared.filter((name): name is string => typeof name === 'string' && name.length > 0)\n}\n\nfunction citedCapabilityOf(row: CatalogRow): ExplainCitedCapability {\n return {\n rowId: catalogRowId(row),\n rowKind: row.kind,\n invocation: invocationForRow(row),\n description: row.description,\n requiredParams: [...requiredParamsOf(row)],\n docPath: row.kind === 'skill' ? row.docPath : row.docPath,\n }\n}\n\n/** One answer line, assembled from a resolved citation and nothing else. */\nfunction answerLineOf(cited: ExplainCitedCapability): string {\n const head = cited.rowKind === 'skill' ? 'skill ' : ''\n const required =\n cited.requiredParams.length > 0\n ? ` (required input: ${cited.requiredParams.join(', ')})`\n : ''\n const docs = cited.docPath === null ? '' : ` (docs: ${cited.docPath})`\n return `${head}\\`${cited.invocation}\\` — ${cited.description}${required}${docs}`\n}\n\nfunction abstain(\n query: string,\n rows: readonly CatalogRow[],\n closestCount: number,\n docsGapLogged: boolean,\n): ExplainOutput {\n const closestRowIds = closestCapabilities(query, rows, closestCount)\n const byRowId = new Map(rows.map((row) => [catalogRowId(row), row]))\n\n const lines: string[] = [\n rows.length === 0\n ? EXPLAIN_ABSTENTION_TEMPLATES.emptyCatalog\n : EXPLAIN_ABSTENTION_TEMPLATES.uncertain,\n ]\n if (rows.length === 0) lines.unshift(EXPLAIN_ABSTENTION_TEMPLATES.uncertain)\n\n if (closestRowIds.length === 0) {\n if (rows.length > 0) lines.push(EXPLAIN_ABSTENTION_TEMPLATES.noClose)\n } else {\n for (const rowId of closestRowIds) {\n const row = byRowId.get(rowId)\n if (row === undefined) continue\n const cited = citedCapabilityOf(row)\n lines.push(\n `${EXPLAIN_ABSTENTION_TEMPLATES.closestPrefix} \\`${cited.invocation}\\` — ${cited.description}`,\n )\n }\n }\n\n lines.push(\n docsGapLogged\n ? EXPLAIN_ABSTENTION_TEMPLATES.gapLogged\n : EXPLAIN_ABSTENTION_TEMPLATES.gapNotLogged,\n )\n\n return {\n kind: 'abstention',\n is_uncertain: true,\n closestRowIds: [...closestRowIds],\n renderedLines: lines,\n docsGap: { logged: docsGapLogged },\n }\n}\n\n/** What the renderer needs beyond the model's citation and the catalog itself. */\nexport interface ExplainRenderContext {\n /**\n * The person's question — used ONLY to rank the abstention's closest capabilities.\n *\n * The renderer is pure: it does not log this, and `packages/agent` could not if it wanted to.\n * The coverage-log append is `recordAbstained` on the host port (D-11).\n */\n readonly query: string\n readonly closestCount?: number\n /**\n * Whether the HOST already appended the coverage record — a report, not a request.\n *\n * It is an input because the abstention text names the docs-gap path, and a line claiming a\n * record that was never written is the same class of untrue statement this whole file is built\n * to prevent. A composition with no coverage log says so.\n */\n readonly docsGapLogged?: boolean\n}\n\n/**\n * Resolve a model's citation against the catalog, or abstain.\n *\n * Answers the `answer` arm only when the citation names at least one row and EVERY id it names\n * resolves. Duplicate ids collapse, first mention wins the position — a row cited twice is one\n * capability, and rendering it twice would be the renderer letting citation COUNT say something\n * the catalog did not.\n */\nexport function renderExplainOutput(\n citation: ExplainCitation,\n rows: readonly CatalogRow[],\n context: ExplainRenderContext,\n): ExplainOutput {\n const closestCount = context.closestCount ?? DEFAULT_CLOSEST_COUNT\n const docsGapLogged = context.docsGapLogged ?? false\n\n if (rows.length === 0) return abstain(context.query, rows, closestCount, docsGapLogged)\n\n const byRowId = new Map(rows.map((row) => [catalogRowId(row), row]))\n const seen = new Set<string>()\n const citations: ExplainCitedCapability[] = []\n\n for (const citedRowId of citation.citedRowIds) {\n const row = byRowId.get(citedRowId)\n // A ghost id is not a bad answer to repair — there is nothing to quote, so the whole output\n // abstains (T-398-10). Returning here rather than collecting is what makes \"no partial answer\"\n // a property of the control flow instead of a later filter someone can relax.\n if (row === undefined) return abstain(context.query, rows, closestCount, docsGapLogged)\n if (seen.has(citedRowId)) continue\n seen.add(citedRowId)\n citations.push(citedCapabilityOf(row))\n }\n\n if (citations.length === 0) return abstain(context.query, rows, closestCount, docsGapLogged)\n\n return {\n kind: 'answer',\n citations,\n renderedLines: citations.map((cited) => answerLineOf(cited)),\n }\n}\n","// The deterministic closest-capability scorer (Phase 398 plan 04 — XPLN-02, D-11).\n//\n// THE MODEL DOES NOT PICK THE SUGGESTION EITHER. D-10 takes the command out of the model's hands;\n// this file takes the consolation prize out of them too, because \"I could not answer that, but you\n// probably want X\" is a claim about the catalog exactly as much as an answer is, and a model that\n// may not name a command may not name a capability by a softer route.\n//\n// HAND-ROLLED ON PURPOSE, AND THAT IS THE EXCEPTION NOT THE RULE. `fuse.js` and\n// `fastest-levenshtein` were both available and both rejected: `packages/agent`'s ownership\n// contract pins its external dependencies at exactly `ai` and `zod`, reconciled against\n// package.json by `validate:arch`, so a similarity library is a boundary change requiring an\n// argument. At thirty lines of pure arithmetic the house dependency discipline wins. If the\n// scorer ever proves inadequate, widening that list is the visible, reviewed step — not a silent\n// import.\n//\n// DETERMINISM IS TWO-SIDED, and the second side is the one that bites. It is not enough that the\n// right row wins; the SAME input must not be able to produce a DIFFERENT answer on another run or\n// another machine. Three things are therefore deliberate and each has a cell:\n// - the total order is score desc then row id asc, so no two rows can be left unordered;\n// - the id comparison is CODE-UNIT, never `localeCompare` — a collation is a machine fact, and a\n// tie broken by the host's locale is the machine-dependent answer this refuses to give;\n// - nothing is read out of a Map or Set in iteration order; the bigram counters exist only to\n// produce numbers, and the ranking is built by an explicit sort over an array.\n\nimport { catalogRowKey } from '@vostride/agent-qa-schema'\nimport type { CatalogRow } from '@vostride/agent-qa-schema'\n\n/** How many suggestions an abstention offers when the caller does not say. */\nexport const DEFAULT_CLOSEST_COUNT = 3\n\n/**\n * The canonical row id — kind-prefixed, so an op and an alias sharing a word are two ids.\n *\n * Spelled here as well as in `renderer.ts` would be two spellings of one identity, so the renderer\n * owns it and this file imports it. `catalogRowKey` (schema) is the within-kind half.\n */\nfunction rowIdOf(row: CatalogRow): string {\n return `${row.kind}:${catalogRowKey(row)}`\n}\n\n/**\n * Code-unit comparison of two canonical row ids.\n *\n * Exported because it IS the determinism claim's choke point: a cell asserts it directly against\n * the pair where a locale collation disagrees, which a test routed only through the ranking could\n * not reach without contriving a tie in every ordering scenario.\n */\nexport function compareRowIds(left: string, right: string): number {\n if (left < right) return -1\n if (left > right) return 1\n return 0\n}\n\n/** Lowercased, whitespace-collapsed — the one normalisation, applied to both sides. */\nfunction normalize(text: string): string {\n return text.toLowerCase().replace(/\\s+/g, ' ').trim()\n}\n\n/**\n * Character bigrams as a multiset, taken WITHIN words and never across a space.\n *\n * The word boundary matters more than it looks. A bigram spanning a space is a gram whose second\n * half is the first letter of an arbitrary next word, so `\"zzzz qqqq wwww\"` shares `\" w\"` with\n * `\"…answer with its run id\"` and scores non-zero against a row it has nothing to do with — which\n * makes \"nothing in the catalog is close\" a state the scorer can never report, and D-11's honest\n * empty answer unreachable. Measured: that one gram scored 0.0247 before this split. Words shorter\n * than two characters contribute no grams, which is correct — `a` and `I` are not evidence.\n */\nfunction bigramCounts(text: string): Map<string, number> {\n const counts = new Map<string, number>()\n for (const word of text.split(' ')) {\n for (let index = 0; index + 1 < word.length; index += 1) {\n const gram = word.slice(index, index + 2)\n counts.set(gram, (counts.get(gram) ?? 0) + 1)\n }\n }\n return counts\n}\n\n/**\n * Sørensen–Dice over character bigrams: `2·|A ∩ B| / (|A| + |B|)`, in [0, 1].\n *\n * Character bigrams rather than word tokens because the queries this serves are typed by a person\n * who does not know the vocabulary yet — \"starting runs\" should reach `runs.start`, and a\n * word-equality tokenizer answers zero to that.\n */\nfunction diceCoefficient(left: string, right: string): number {\n const leftGrams = bigramCounts(left)\n const rightGrams = bigramCounts(right)\n let leftTotal = 0\n for (const count of leftGrams.values()) leftTotal += count\n let rightTotal = 0\n for (const count of rightGrams.values()) rightTotal += count\n if (leftTotal === 0 || rightTotal === 0) return 0\n\n let shared = 0\n for (const [gram, count] of leftGrams) {\n const other = rightGrams.get(gram)\n if (other !== undefined) shared += Math.min(count, other)\n }\n return (2 * shared) / (leftTotal + rightTotal)\n}\n\n/** The row's name-ish text: the word a person would type for it. */\nfunction nameTextOf(row: CatalogRow): string {\n return catalogRowKey(row)\n}\n\n/**\n * A row's score against a query: the better of its NAME alone and its name-plus-description.\n *\n * Two terms and one `max`, not two recipes: Dice normalises by total length, so a row whose name\n * IS the query would otherwise be beaten by a row whose long description happens to mention the\n * word. D-11 names both fields as the similarity's source; this is how both count without either\n * drowning the other.\n */\nfunction scoreRow(normalizedQuery: string, row: CatalogRow): number {\n const name = normalize(nameTextOf(row))\n const withDescription = normalize(`${nameTextOf(row)} ${row.description}`)\n return Math.max(\n diceCoefficient(normalizedQuery, name),\n diceCoefficient(normalizedQuery, withDescription),\n )\n}\n\n/**\n * Up to `k` canonical row ids, closest first — the abstention arm's suggestion (D-11).\n *\n * ZERO-OVERLAP ROWS ARE FILTERED OUT, and that is the honest arm rather than a missing feature: a\n * query sharing no bigram with any row has no closest capability, and returning the\n * alphabetically-first three anyway would be a suggestion drawn from nothing — the same invention\n * by a quieter route. An empty answer is what the abstention text is written to say.\n */\nexport function closestCapabilities(\n query: string,\n rows: readonly CatalogRow[],\n k: number = DEFAULT_CLOSEST_COUNT,\n): readonly string[] {\n if (rows.length === 0 || k <= 0) return []\n const normalizedQuery = normalize(query)\n if (normalizedQuery === '') return []\n\n const ranked = rows\n .map((row) => ({ rowId: rowIdOf(row), score: scoreRow(normalizedQuery, row) }))\n .filter((candidate) => candidate.score > 0)\n .sort((left, right) =>\n left.score === right.score\n ? compareRowIds(left.rowId, right.rowId)\n : right.score - left.score,\n )\n\n return ranked.slice(0, k).map((candidate) => candidate.rowId)\n}\n","// `entities.resolve` — any reference in, a typed resolution out (Phase 387, ENTY-01 / D-09).\n//\n// The reference may be a short-ID, an `agentqa://` URI, or free text a human typed; the\n// answer is one of exactly three arms — a hit, a small disambiguation set, or an honest miss.\n// There is no fourth \"best effort\" arm, and that closed union is the never-guess contract in\n// type form: a surface cannot render a maybe, because it is never handed one.\n//\n// The op does no resolution of its own. The injected directory port decides WHAT the answer\n// is; this file's whole contribution is turning the store layer's descriptors into cards\n// through the one producer, which is what makes the ENTY-02 claim hold at every surface that\n// calls it (chat in 392, MCP in 396, the CLI here and now).\n\nimport {\n EntitiesResolveInputSchema,\n EntityCardResolutionSchema,\n} from '@vostride/agent-qa-schema'\nimport type {\n EntitiesResolveInput,\n EntityCardResolution,\n EntityDescriptor,\n EntityResolution,\n} from '@vostride/agent-qa-schema'\n\nimport { readEntityCardContext } from '../entity-cards/card-context.js'\nimport type { EntityCardContext } from '../entity-cards/card-context.js'\nimport { produceEntityCard } from '../entity-cards/produce-card.js'\nimport { ENTITIES_RESOLVE_FUNCTION_ID } from './entities-ids.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport { ENTITIES_RESOLVE_FUNCTION_ID }\n\n/**\n * Descriptor union → card union, arm for arm.\n *\n * Written as an exhaustive switch rather than a spread-and-patch so a fourth arm added to the\n * resolution vocabulary later is a compile error here instead of a silently unrendered case.\n */\nfunction renderResolution(\n resolution: EntityResolution,\n context: EntityCardContext,\n): EntityCardResolution {\n switch (resolution.kind) {\n case 'resolved':\n return {\n kind: 'resolved',\n card: produceEntityCard(resolution.descriptor, context),\n score: resolution.score,\n }\n case 'ambiguous':\n return {\n kind: 'ambiguous',\n // The SAME context for every candidate — a disambiguation set whose members were\n // rendered under different contexts would put two spellings of one system's state\n // side by side in the one place a human is choosing between them.\n candidates: resolution.candidates.map((candidate) => ({\n card: produceEntityCard(candidate.descriptor, context),\n score: candidate.score,\n })),\n }\n case 'none':\n return resolution\n }\n}\n\n/**\n * Every descriptor a resolution will render a card for — the SAME exhaustive shape as\n * `renderResolution`, so the set the context is built for cannot drift from the set that is\n * rendered. A fourth resolution arm is a compile error here too.\n */\nfunction descriptorsOf(resolution: EntityResolution): readonly EntityDescriptor[] {\n switch (resolution.kind) {\n case 'resolved':\n return [resolution.descriptor]\n case 'ambiguous':\n return resolution.candidates.map((candidate) => candidate.descriptor)\n case 'none':\n return []\n }\n}\n\nexport const entitiesResolveSpec: FunctionSpec<EntitiesResolveInput, EntityCardResolution> = {\n id: ENTITIES_RESOLVE_FUNCTION_ID,\n summary: 'Resolve any entity reference to a card, a disambiguation set, or an honest miss.',\n resultKind: 'unary',\n input: EntitiesResolveInputSchema,\n output: EntityCardResolutionSchema,\n risk: { name: `fn:${ENTITIES_RESOLVE_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * THREE ARMS, ALL ANSWERS (399.1 D-01, plan 03's razor).\n *\n * `ambiguous` and `none` are the resolver refusing to GUESS, which is the never-guess contract\n * doing exactly what it promises — a resolution it will not invent is the answer to the question\n * asked, not a control declining an act. Reporting either as `refused` would send a person\n * looking for a guardrail that never fired.\n */\n classify(output): ClauseVerdict {\n switch (output.kind) {\n case 'resolved':\n return { status: 'executed', outcome: `resolved to ${output.card.id}` }\n case 'ambiguous':\n return {\n status: 'executed',\n outcome: `ambiguous — ${output.candidates.length} candidates, none picked`,\n }\n case 'none':\n return { status: 'executed', outcome: `none: ${output.reason}` }\n default:\n return output satisfies never\n }\n },\n async invoke(input, deps) {\n // Read-tier despite D-01's lazy mint, and the distinction is deliberate: minting records\n // an ADDRESS for something that already existed. It creates no entity, changes no\n // knowledge, and is invisible in every projection except the one that hands out names.\n const resolution = await deps.entities.resolve(input.ref)\n return renderResolution(\n resolution,\n // The descriptors this render is ABOUT to produce cards for — every arm of them, so an\n // ambiguous set containing one test reads the ledger once and every candidate is rendered\n // against the same fold (390). A `none` arm renders nothing and reads nothing.\n await readEntityCardContext(deps, descriptorsOf(resolution)),\n )\n },\n}\n","// `knowledge.accept` — promote a candidate the caller stands behind (Phase 387, KREV-01; 432-12, D-05).\n//\n// 2026-09-30, 432-12 (D-04/D-05/D-09): the change APPLIES IN THE CALL. The op validates its input,\n// hands the review port one direct change and answers what the explicit writer changed: the\n// records it read back, and the commit receipt when a promotion gate was crossed. Nothing is\n// proposed and nothing waits for a second call; the retired `knowledge.accept.propose` id has no\n// alias (D-02). This file keeps its name until the later rename audit, so its consumers move first.\n//\n// `readOnly: false`, at the recognized-mutating floor: an explicit change to this machine's\n// knowledge runs in every execution context (D-01, D-08), and the writer behind the port keeps the\n// lease, delta validation, bundle egress and every promotion gate. 2026-10-01 (432-26, D-12): it\n// declares no `knowledge-write` scope any more; every door can call it. It binds through the\n// OPTIONAL `knowledgeReview` dep and never `deps.knowledge`: the reader port is physically\n// write-free, and a host that supplies no review port lists this verb `unbound` BY NAME.\n\nimport {\n KnowledgeAcceptChangeInputSchema,\n KnowledgeChangeOutputSchema,\n} from '@vostride/agent-qa-schema'\nimport type {\n KnowledgeAcceptChangeInput,\n KnowledgeChangeOutput,\n} from '@vostride/agent-qa-schema'\n\nimport type { FunctionSpec } from '../spec.js'\nimport { classifyKnowledgeChangeOutput } from './knowledge-change-verdict.js'\nimport { KNOWLEDGE_ACCEPT_FUNCTION_ID } from './knowledge-review-ids.js'\n\nexport { KNOWLEDGE_ACCEPT_FUNCTION_ID } from './knowledge-review-ids.js'\n\nexport const knowledgeAcceptSpec: FunctionSpec<KnowledgeAcceptChangeInput, KnowledgeChangeOutput> = {\n id: KNOWLEDGE_ACCEPT_FUNCTION_ID,\n summary: 'Accept a knowledge candidate, applying the change in the call.',\n resultKind: 'unary',\n input: KnowledgeAcceptChangeInputSchema,\n output: KnowledgeChangeOutputSchema,\n boundThrough: 'knowledgeReview',\n risk: { name: `fn:${KNOWLEDGE_ACCEPT_FUNCTION_ID}`, recognized: true, readOnly: false },\n // The fold the three knowledge changes share (2026-10-03, quick 261003-cpv, 432 review IN-04).\n classify: classifyKnowledgeChangeOutput,\n invoke({ operationId, ...input }, deps) {\n // Non-null: `boundThrough` makes an absent review port an `unbound` listing and a binding\n // refusal in `invokeFunction`, so dispatch is only reached in a composition that supplied one. The identity is\n // lifted off the input because it names the change, not the verb: the verb input below is\n // exactly what the explicit writer validates.\n return deps.knowledgeReview!.change({\n verb: 'accept',\n input,\n ...(operationId === undefined ? {} : { operationId }),\n })\n },\n}\n","// The clause verdict for a direct knowledge change — one fold for the three ops (261003-cpv, IN-04).\n//\n// `knowledge.accept`, `knowledge.reject` and `knowledge.forget` answer one union,\n// `KnowledgeChangeOutput`, and each carried a byte-identical copy of this switch. One fold, on the\n// `classifyConfigChangeOutput` precedent: a later edit that taught one door to report a refusal\n// differently would be a report that depends on which door was used.\n\nimport type { KnowledgeChangeOutput } from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict } from '../spec.js'\n\n/**\n * Fold one `KnowledgeChangeOutput` into the verdict its own arm states.\n *\n * `target-not-found` IS ABSENCE, WHICH IS AN ANSWER (399.1 D-01, plan 03's razor): a ref that names\n * nothing is an ordinary mistake and the store is intact. A policy text the writer refused to\n * materialize is a refusal: nothing was changed.\n */\nexport function classifyKnowledgeChangeOutput(output: KnowledgeChangeOutput): ClauseVerdict {\n switch (output.outcome) {\n case 'applied':\n return { status: 'executed', outcome: `${output.verb} applied: ${output.recordIds.length} record(s) changed` }\n case 'target-not-found':\n return { status: 'executed', outcome: 'target-not-found: nothing was changed' }\n case 'refused':\n return { status: 'refused', outcome: `${output.reason}: nothing was changed` }\n default:\n return output satisfies never\n }\n}\n","// `knowledge.bundles.list` — the committed-bundle catalogue (Phase 384, D-06).\n//\n// The seed of the knowledge review surface: 387's five review verbs extend this listing\n// rather than replacing it. Every trust-shaped field on a row is DERIVED by the v51 trust\n// fold behind the port — this op renders what it is handed and never recomputes trust.\n\nimport { KnowledgeBundlesListInputSchema, KnowledgeBundlesListOutputSchema } from '@vostride/agent-qa-schema'\nimport type { KnowledgeBundleSummary, KnowledgeBundlesListInput } from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport const KNOWLEDGE_BUNDLES_LIST_FUNCTION_ID = 'knowledge.bundles.list'\n\nfunction compareText(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0\n}\n\nexport const knowledgeBundlesListSpec: FunctionSpec<\n KnowledgeBundlesListInput,\n KnowledgeBundleSummary[]\n> = {\n id: KNOWLEDGE_BUNDLES_LIST_FUNCTION_ID,\n summary: 'List the committed knowledge bundles with their derived trust state.',\n resultKind: 'unary',\n input: KnowledgeBundlesListInputSchema,\n output: KnowledgeBundlesListOutputSchema,\n risk: { name: `fn:${KNOWLEDGE_BUNDLES_LIST_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * A listing that answered — the count, and nothing out of a bundle (399.1 D-01).\n */\n classify(output): ClauseVerdict {\n return { status: 'executed', outcome: `${output.length} knowledge bundle(s)` }\n },\n async invoke(_input, deps) {\n const rows = await deps.knowledge.listBundles()\n // The op owns its own total order rather than inheriting whatever a composition's\n // directory walk happened to produce: bundle ids are unique only per product, so the\n // pair is the sort key.\n return [...rows].sort((left, right) => (\n compareText(left.product, right.product)\n || compareText(left.bundleId, right.bundleId)\n ))\n },\n}\n","// 416 D-17: one read of committed gate history for every function-layer surface.\nimport { KnowledgeGatesListInputSchema, KnowledgeGatesListResultSchema,\n type KnowledgeGatesListInput, type KnowledgeGatesListResult } from '@vostride/agent-qa-schema'\nimport type { FunctionSpec } from '../spec.js'\n\nexport const KNOWLEDGE_GATES_LIST_FUNCTION_ID = 'knowledge.gates.list'\nexport class KnowledgeGatesUnboundError extends Error {\n constructor() {\n super('knowledge.gates.list: the knowledge reader port binds no gateReceipts')\n this.name = 'KnowledgeGatesUnboundError'\n }\n}\nexport const knowledgeGatesListSpec: FunctionSpec<KnowledgeGatesListInput, KnowledgeGatesListResult> = {\n id: KNOWLEDGE_GATES_LIST_FUNCTION_ID,\n summary: 'Read a knowledge record’s gate history, standing receipts and current promotion verdict.',\n resultKind: 'unary',\n input: KnowledgeGatesListInputSchema,\n output: KnowledgeGatesListResultSchema,\n risk: { name: 'fn:knowledge.gates.list', recognized: true, readOnly: true },\n classify(output) {\n if (output.kind === 'not-found') return { status: 'executed', outcome: 'record not found' }\n return { status: 'executed', outcome: `${output.lines.length} gate line(s); ${output.live.verdict === 'promote'\n ? 'promote via ' + output.live.promotionPath : 'held: ' + output.live.reason}` }\n },\n async invoke(input, deps) {\n if (deps.knowledge.gateReceipts === undefined) throw new KnowledgeGatesUnboundError()\n return deps.knowledge.gateReceipts({ candidateId: input.recordId })\n },\n}\n","// `knowledge.forget` — tombstone a record or an addressed bundle and scrub its projections (Phase 387, KREV-01; 432-12, D-05/D-09).\n//\n// 2026-09-30, 432-12 (D-04/D-05/D-09): the change APPLIES IN THE CALL, and it is the explicit\n// removal D-09 names. The op validates its input, hands the review port one direct change and\n// answers the existing forget receipt: every record tombstoned, with its provenance, and the\n// projections scrubbed. Tombstoned, never destroyed, so the record stays enumerable. The retired\n// `knowledge.forget.propose` id has no alias (D-02). This file keeps its name until the later\n// rename audit, so its consumers move first.\n//\n// `readOnly: false`, at the recognized-mutating floor: an explicit change to this machine's\n// knowledge runs in every execution context (D-01, D-08). 2026-10-01 (432-23, D-12): it declares\n// no `knowledge-write` scope any more; every door can call it. It binds through the OPTIONAL\n// `knowledgeReview` dep, so a host with no review port lists it `unbound` BY NAME.\n\nimport {\n KnowledgeForgetChangeInputSchema,\n KnowledgeChangeOutputSchema,\n} from '@vostride/agent-qa-schema'\nimport type {\n KnowledgeForgetChangeInput,\n KnowledgeChangeOutput,\n} from '@vostride/agent-qa-schema'\n\nimport type { FunctionSpec } from '../spec.js'\nimport { classifyKnowledgeChangeOutput } from './knowledge-change-verdict.js'\nimport { KNOWLEDGE_FORGET_FUNCTION_ID } from './knowledge-review-ids.js'\n\nexport { KNOWLEDGE_FORGET_FUNCTION_ID } from './knowledge-review-ids.js'\n\nexport const knowledgeForgetSpec: FunctionSpec<KnowledgeForgetChangeInput, KnowledgeChangeOutput> = {\n id: KNOWLEDGE_FORGET_FUNCTION_ID,\n summary: 'Forget a knowledge record or bundle, tombstoning it in the call.',\n resultKind: 'unary',\n input: KnowledgeForgetChangeInputSchema,\n output: KnowledgeChangeOutputSchema,\n boundThrough: 'knowledgeReview',\n risk: { name: `fn:${KNOWLEDGE_FORGET_FUNCTION_ID}`, recognized: true, readOnly: false },\n // The fold the three knowledge changes share (2026-10-03, quick 261003-cpv, 432 review IN-04).\n classify: classifyKnowledgeChangeOutput,\n invoke({ operationId, ...input }, deps) {\n // Non-null: `boundThrough` makes an absent review port an `unbound` listing and a refusal at\n // `invokeFunction`'s binding check, so dispatch is only reached in a composition that supplied\n // one. The identity is\n // lifted off the input because it names the change, not the verb: the verb input below is\n // exactly what the explicit writer validates.\n return deps.knowledgeReview!.change({\n verb: 'forget',\n input,\n ...(operationId === undefined ? {} : { operationId }),\n })\n },\n}\n","// `knowledge.records.diff` — what changed since a build ordinal (Phase 387, KREV-01).\n//\n// WIRING over the reader entry's `diffSince`. The change vocabulary, the surviving-event fold\n// and the purge-receipt read all live behind the port; this file projects, echoes the baseline,\n// and sorts. KREV-01's \"four verbs need no new memidex code\" is a claim about exactly this.\n\nimport { KnowledgeRecordsDiffInputSchema, KnowledgeRecordsDiffOutputSchema } from '@vostride/agent-qa-schema'\nimport type {\n KnowledgeRecordsDiffInput,\n KnowledgeRecordsDiffOutput,\n RecordChange,\n} from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport const KNOWLEDGE_RECORDS_DIFF_FUNCTION_ID = 'knowledge.records.diff'\n\nfunction compareText(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0\n}\n\n/**\n * The op's own total order, and it is total all the way down (the 384 convention).\n *\n * One record can change several times at one ordinal — a confirmation and a supersession land\n * in the same build — so the id and the ordinal do not order the list on their own. The trailing\n * legs are what turn \"deterministic enough in practice\" into deterministic: two rows equal on\n * every earlier key still have an order, and it is the same order twice running on any host.\n * A diff that reshuffled between two identical questions would make every pasted answer\n * unverifiable.\n */\nfunction byChangeIdentity(left: RecordChange, right: RecordChange): number {\n return compareText(left.recordId, right.recordId)\n || left.atOrdinal - right.atOrdinal\n || compareText(left.change, right.change)\n || compareText(left.evidenceToken ?? '', right.evidenceToken ?? '')\n || compareText(left.byRecordId ?? '', right.byRecordId ?? '')\n}\n\nexport const knowledgeRecordsDiffSpec: FunctionSpec<\n KnowledgeRecordsDiffInput,\n KnowledgeRecordsDiffOutput\n> = {\n id: KNOWLEDGE_RECORDS_DIFF_FUNCTION_ID,\n summary: 'List every committed knowledge record change since a build ordinal.',\n resultKind: 'unary',\n input: KnowledgeRecordsDiffInputSchema,\n output: KnowledgeRecordsDiffOutputSchema,\n risk: { name: `fn:${KNOWLEDGE_RECORDS_DIFF_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * A diff that answered, WITH ITS BASELINE (399.1 D-01).\n *\n * The ordinal rides the outcome for the contract's own reason: \"a change list with no baseline is\n * a list whose meaning depends on remembering the question\", and a receipt line is exactly the\n * artifact that gets pasted somewhere the question is gone.\n */\n classify(output): ClauseVerdict {\n return {\n status: 'executed',\n outcome: `${output.changes.length} change(s) since ordinal ${output.sinceOrdinal}`,\n }\n },\n async invoke(input, deps) {\n const changes = await deps.knowledge.diffSince(input)\n return {\n schemaVersion: 2,\n // Echoed, not remembered: a change list with no baseline means nothing to a reader who\n // has the answer and not the question, and these answers get pasted into issues and CI\n // logs where the question is gone.\n sinceOrdinal: input.sinceOrdinal,\n changes: [...changes].sort(byChangeIdentity),\n }\n },\n}\n","// `knowledge.records.inspect` — the record-level maintenance view (Phase 387, KREV-01).\n//\n// WIRING over an existing reader export, which is KREV-01's own claim about this verb: the\n// whole of the query lives behind the port, in `inspectRecords`, and this file adds a filter\n// pass-through, a projection and a sort. There is no memidex code here and there must never be\n// — the moment a verb starts deciding which records match, the read-only reader entry stops\n// being the one place that decision is made and the two answers begin to drift.\n//\n// Every trust-shaped field on a row is DERIVED by the v51 trust fold behind the port; this op\n// renders what it is handed and never recomputes trust, exactly as `knowledge.bundles.list`\n// does. The DTO carries the reader's OWN view schema rather than a paraphrase of it, so\n// \"wiring\" stays literally true at the type level too.\n\nimport { KnowledgeRecordsInspectInputSchema, KnowledgeRecordsInspectOutputSchema } from '@vostride/agent-qa-schema'\nimport type {\n InspectRecordView,\n KnowledgeRecordsInspectInput,\n KnowledgeRecordsInspectOutput,\n} from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport const KNOWLEDGE_RECORDS_INSPECT_FUNCTION_ID = 'knowledge.records.inspect'\n\nfunction compareText(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0\n}\n\n/**\n * The op's own total order (the 384 convention).\n *\n * Stated here rather than inherited from whatever the port answered in, and the pair is the\n * key because a record id is unique only within a product — one id in two products is two\n * different records, and a sort on the id alone would leave their relative order to whichever\n * directory walk the composition happened to perform.\n */\nfunction byRecordThenProduct(left: InspectRecordView, right: InspectRecordView): number {\n return compareText(left.recordId, right.recordId)\n || compareText(left.product, right.product)\n}\n\nexport const knowledgeRecordsInspectSpec: FunctionSpec<\n KnowledgeRecordsInspectInput,\n KnowledgeRecordsInspectOutput\n> = {\n id: KNOWLEDGE_RECORDS_INSPECT_FUNCTION_ID,\n summary: 'Inspect committed knowledge records through a closed structural filter.',\n resultKind: 'unary',\n input: KnowledgeRecordsInspectInputSchema,\n output: KnowledgeRecordsInspectOutputSchema,\n risk: { name: `fn:${KNOWLEDGE_RECORDS_INSPECT_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * An inspection that answered — the count, and no record content (399.1 D-01).\n */\n classify(output): ClauseVerdict {\n return { status: 'executed', outcome: `${output.records.length} record(s) inspected` }\n },\n async invoke(input, deps) {\n // The filter crosses UNCHANGED. Narrowing or defaulting it here would be a second query\n // planner sitting above the one that already exists, and the two would answer differently\n // the first time either changed.\n const records = await deps.knowledge.inspectRecords(input)\n return {\n schemaVersion: 2,\n records: [...records].sort(byRecordThenProduct),\n }\n },\n}\n","// `knowledge.reject` — deprecate a candidate the caller does not stand behind (Phase 387, KREV-01; 432-12, D-05).\n//\n// 2026-09-30, 432-12 (D-04/D-05/D-09): the change APPLIES IN THE CALL. The op validates its input,\n// hands the review port one direct change and answers what the explicit writer changed. Nothing is\n// proposed and nothing waits for a second call; the retired `knowledge.reject.propose` id has no\n// alias (D-02). This file keeps its name until the later rename audit, so its consumers move first.\n//\n// `readOnly: false`, at the recognized-mutating floor: an explicit change to this machine's\n// knowledge runs in every execution context (D-01, D-08). 2026-10-01 (432-26, D-12): it declares\n// no `knowledge-write` scope any more; every door can call it. It binds through the OPTIONAL\n// `knowledgeReview` dep, so a host with no review port lists it `unbound` BY NAME.\n//\n// The reason is REQUIRED by the input contract because the `Deprecate` delta this becomes\n// requires one: a verb that admitted an empty reason would be inventing a justification for a\n// decision somebody made.\n\nimport {\n KnowledgeRejectChangeInputSchema,\n KnowledgeChangeOutputSchema,\n} from '@vostride/agent-qa-schema'\nimport type {\n KnowledgeRejectChangeInput,\n KnowledgeChangeOutput,\n} from '@vostride/agent-qa-schema'\n\nimport type { FunctionSpec } from '../spec.js'\nimport { classifyKnowledgeChangeOutput } from './knowledge-change-verdict.js'\nimport { KNOWLEDGE_REJECT_FUNCTION_ID } from './knowledge-review-ids.js'\n\nexport { KNOWLEDGE_REJECT_FUNCTION_ID } from './knowledge-review-ids.js'\n\nexport const knowledgeRejectSpec: FunctionSpec<KnowledgeRejectChangeInput, KnowledgeChangeOutput> = {\n id: KNOWLEDGE_REJECT_FUNCTION_ID,\n summary: 'Reject a knowledge candidate with a reason, applying the change in the call.',\n resultKind: 'unary',\n input: KnowledgeRejectChangeInputSchema,\n output: KnowledgeChangeOutputSchema,\n boundThrough: 'knowledgeReview',\n risk: { name: `fn:${KNOWLEDGE_REJECT_FUNCTION_ID}`, recognized: true, readOnly: false },\n // The fold the three knowledge changes share (2026-10-03, quick 261003-cpv, 432 review IN-04).\n classify: classifyKnowledgeChangeOutput,\n invoke({ operationId, ...input }, deps) {\n // Non-null: `boundThrough` makes an absent review port an `unbound` listing and a binding\n // refusal in `invokeFunction`, so dispatch is only reached in a composition that supplied one. The identity is\n // lifted off the input because it names the change, not the verb: the verb input below is\n // exactly what the explicit writer validates.\n return deps.knowledgeReview!.change({\n verb: 'reject',\n input,\n ...(operationId === undefined ? {} : { operationId }),\n })\n },\n}\n","// `quarantine.add` — manual entry, renewal and the owner claim, in one verb (Phase 390, D-13).\n//\n// The counterpart that makes D-05's narrow auto-gate livable. Automatic quarantine is reserved\n// for the A3-routed classes (flake, environment, timeout) precisely so a real regression is\n// never auto-silenced; a persistent `app_bug` keeps failing the build. This verb is how a human\n// deliberately quarantines a test anyway — a known-broken one, a flake the ladder has not\n// caught up with — which is a different act from the machine deciding to, and it is a different\n// act because a person put their name on it.\n//\n// RE-ADDING RENEWS; IT DOES NOT THROW, AND IT IS NOT A SECOND VERB. In an append-only event log\n// entry and renewal are one gesture with different prior state: an identity with an open window\n// gets a `renewed` event extending the deadline and claiming the owner when one was supplied,\n// and the result says `renewed` so the caller LEARNS which happened. Splitting claim and renew\n// into their own verbs would have forced every caller to read the ledger's current state before\n// it could choose a verb — a read whose answer can change between the two calls.\n//\n// A DIRECT WRITE, NOT A PROPOSE+APPLY PAIR (D-13): see `quarantine-release.ts`. 391 may wrap both\n// verbs in the proposal engine; this plan mints the direct form the engine would wrap.\n//\n// ---- NO SCOPE (2026-10-01, 432-25, D-12) ------------------------------------------------------\n//\n// Both quarantine writes once declared `knowledge-write` rather than a new scope member, on the\n// reasoning that quarantine writes differ from knowledge writes neither in kind nor in\n// recoverability. Every door can call every operation now, so neither verb declares a scope. What\n// keeps the power bounded is unchanged and was never the scope: both verbs append to committed,\n// human-reviewable text under the knowledge root, each REVERSES the other, suppression expires\n// (D-11) and is loud in reporter output (D-15), and the risk descriptor still says the verb writes.\n\nimport {\n QuarantineAddInputSchema,\n QuarantineAddOutputSchema,\n} from '@vostride/agent-qa-schema'\nimport type { QuarantineAddInput, QuarantineAddOutput } from '@vostride/agent-qa-schema'\n\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionDeps, FunctionSpec } from '../spec.js'\n\n/** The literal appears here once; every surface names the constant (384 D-15). */\nexport const QUARANTINE_ADD_FUNCTION_ID = 'quarantine.add'\n\nexport const quarantineAddSpec: FunctionSpec<QuarantineAddInput, QuarantineAddOutput> = {\n id: QUARANTINE_ADD_FUNCTION_ID,\n summary: 'Quarantine one test by hand, renewing and claiming an existing entry.',\n resultKind: 'unary',\n boundThrough: 'quarantine',\n input: QuarantineAddInputSchema,\n output: QuarantineAddOutputSchema,\n risk: { name: `fn:${QUARANTINE_ADD_FUNCTION_ID}`, recognized: true, readOnly: false },\n /**\n * `renewed` IS IDEMPOTENCY, AND THE CONTRACT CALLS IT INFORMATION (399.1 D-01).\n *\n * \"Already quarantined is information an operator acts on, not an error\" — so both arms are\n * `executed` and the outcome says which gesture the ledger recorded.\n */\n classify(output): ClauseVerdict {\n switch (output.kind) {\n case 'entered':\n return { status: 'executed', outcome: 'entered: a new quarantine window was opened' }\n case 'renewed':\n return { status: 'executed', outcome: 'renewed: an open window was extended' }\n default:\n return output satisfies never\n }\n },\n async invoke(input, deps: FunctionDeps) {\n const quarantine = deps.quarantine\n if (quarantine === undefined) {\n // The loudest of the three refusals to get right: an unbound add that no-opped would\n // report a test as quarantined while it kept failing every build, and the operator would\n // read the next red as the quarantine not working rather than as never having existed.\n throw new FunctionNotBoundError(QUARANTINE_ADD_FUNCTION_ID)\n }\n\n // An absent `expiresAt` is left absent on purpose — the implementation stamps the pinned\n // default lifetime at write time. Defaulting it here would put a deadline into the request\n // the caller never asked for, and would be a second place the lifetime constant is spelled.\n return await quarantine.add(input)\n },\n}\n","// `quarantine.list` — the machine-readable enumeration of quarantine state (Phase 390, D-12/D-13).\n//\n// FLAK-03's \"quarantine is enumerable\" in one op: every entry carries the three legs of stable\n// test identity, the fingerprint that keyed the window, the resolved class, the owner, the\n// entry instant, the accumulated re-entry history, the deadline and the computed state. One\n// producer, so a dashboard column, a CLI table and a chat answer are the same rows by\n// construction rather than by review.\n//\n// That enumeration is D-13's, and it is stated in the SCHEMA'S OWN WORDING because it is one\n// contract with two readers, not two paraphrases of one. `QuarantineEntrySchema`'s docstring is\n// the other copy; the re-entry history was added to that copy in 390-18 and to this one in\n// 390-20, and an enumeration contract that under-reports its own contents is precisely the\n// failure the contract exists to prevent (390 IN-01).\n//\n// THE OP RE-SORTS NOTHING. D-12 requires unassigned-owner entries FIRST — they are the triage\n// queue — with the rest ordered deterministically after them. That ordering is the PORT\n// implementation's law and is pinned where it is implemented; a second sort here would be a\n// second declaration of it, free to agree today and disagree after the first tie-break change.\n// The op's whole job is the envelope.\n//\n// THE INPUT CARRIES NO FILTER. Owner and state filtering are reader concerns over rows already\n// in hand. A filter here would make the verb's answer depend on how it was asked, and the one\n// caller that most needs the full picture — a human deciding what to un-quarantine — is exactly\n// the one who would have to know to ask for it.\n\nimport {\n QuarantineListInputSchema,\n QuarantineListOutputSchema,\n} from '@vostride/agent-qa-schema'\nimport type { QuarantineListInput, QuarantineListOutput } from '@vostride/agent-qa-schema'\n\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionDeps, FunctionSpec } from '../spec.js'\n\n/**\n * Lowercase dot taxonomy (384 D-15): a new `quarantine` domain, one noun. Quarantine state is\n * neither a run, a memory nor an analysis — filing these verbs under an existing domain would\n * have made the taxonomy decorative, which is the same call 387 made for `entities`.\n *\n * The literal appears here once; the parity-coverage suite picks the id up off the registry.\n */\nexport const QUARANTINE_LIST_FUNCTION_ID = 'quarantine.list'\n\nexport const quarantineListSpec: FunctionSpec<QuarantineListInput, QuarantineListOutput> = {\n id: QUARANTINE_LIST_FUNCTION_ID,\n summary: 'List every quarantined test with its owner, expiry and lifecycle state.',\n resultKind: 'unary',\n // Bound exactly where a composition supplies the quarantine port. Listing quarantine state\n // is not something a host can approximate: an unbound host answering `[]` would say \"nothing\n // is quarantined\" about a ledger it has never been able to read, which is a wrong answer\n // wearing a correct one's clothes. So it refuses by name instead (D-09).\n boundThrough: 'quarantine',\n input: QuarantineListInputSchema,\n output: QuarantineListOutputSchema,\n risk: { name: `fn:${QUARANTINE_LIST_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * A ledger listing that answered — the count, and no entry's identity legs (399.1 D-01).\n */\n classify(output): ClauseVerdict {\n const count = output.entries.length\n return {\n status: 'executed',\n outcome: `${count} quarantine entr${count === 1 ? 'y' : 'ies'}`,\n }\n },\n async invoke(_input, deps: FunctionDeps) {\n const quarantine = deps.quarantine\n if (quarantine === undefined) {\n throw new FunctionNotBoundError(QUARANTINE_LIST_FUNCTION_ID)\n }\n\n // An EMPTY listing is a result, not an absence: a project with no quarantined tests is the\n // healthy state, and it reads identically to one whose ledger file was never created.\n return { entries: [...await quarantine.list()] }\n },\n}\n","// `quarantine.release` — the human half of the exit path (Phase 390, D-13).\n//\n// Quarantine already exits on its own two ways: M consecutive passing build ordinals\n// (`released-auto`) and the wall-clock expiry that makes suppression stop (D-10/D-11). This is\n// the third — a person deciding the test is fixed and saying so now — and it is what keeps the\n// automatic exits conservative: a rule that has to be the ONLY way out has to be tuned for the\n// impatient case, and this verb is why it does not.\n//\n// A DIRECT WRITE, NOT A PROPOSE+APPLY PAIR (D-13). The two-step KREV idiom exists for\n// LEARNED-knowledge mutations, where the deltas a verb would commit are computed, reviewed and\n// then applied by id. This is operational state: the caller already knows exactly which test it\n// means, the change is one append to an event log, and the counterpart verb reverses it. 391\n// may wrap these in the proposal engine when it lands; wrapping them now would have bought a\n// review step for a gesture whose whole content is already in the request.\n//\n// NOT-QUARANTINED IS AN ARM, NOT A THROW. A release aimed at a test with no open window\n// answers `no-entry`. That is an ordinary situation — a stale note, an auto-exit that beat the\n// human to it, a second click — and a rejected promise would report it as a failure of the\n// system rather than as a fact about the ledger.\n//\n// 2026-10-01 (432-25, D-12): this verb no longer declares a write scope; `quarantine-add.ts` says\n// why both verbs once carried `knowledge-write` and what bounds them now.\n\nimport {\n QuarantineReleaseInputSchema,\n QuarantineReleaseOutputSchema,\n} from '@vostride/agent-qa-schema'\nimport type { QuarantineReleaseInput, QuarantineReleaseOutput } from '@vostride/agent-qa-schema'\n\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionDeps, FunctionSpec } from '../spec.js'\n\n/** The literal appears here once; every surface names the constant (384 D-15). */\nexport const QUARANTINE_RELEASE_FUNCTION_ID = 'quarantine.release'\n\nexport const quarantineReleaseSpec: FunctionSpec<\n QuarantineReleaseInput,\n QuarantineReleaseOutput\n> = {\n id: QUARANTINE_RELEASE_FUNCTION_ID,\n summary: 'Release one test from quarantine — the manual half of the exit path.',\n resultKind: 'unary',\n boundThrough: 'quarantine',\n input: QuarantineReleaseInputSchema,\n output: QuarantineReleaseOutputSchema,\n risk: { name: `fn:${QUARANTINE_RELEASE_FUNCTION_ID}`, recognized: true, readOnly: false },\n /**\n * `no-entry` IS \"an ordinary answer to an ordinary question\" — the contract's words (399.1 D-01).\n */\n classify(output): ClauseVerdict {\n switch (output.kind) {\n case 'released':\n return { status: 'executed', outcome: 'released: the quarantine window was closed' }\n case 'no-entry':\n return {\n status: 'executed',\n outcome: 'no-entry: nothing was quarantined under that identity',\n }\n default:\n return output satisfies never\n }\n },\n async invoke(input, deps: FunctionDeps) {\n const quarantine = deps.quarantine\n if (quarantine === undefined) {\n // An unbound WRITE verb must refuse loudly. A silent no-op would tell an operator their\n // release landed while the ledger stayed exactly as it was, and the next red build would\n // be the first sign otherwise.\n throw new FunctionNotBoundError(QUARANTINE_RELEASE_FUNCTION_ID)\n }\n\n // Forwarded verbatim: the identity legs are DATA the implementation matches entries on —\n // never joined onto a path. The ledger's location is a fixed constant at the knowledge\n // root, so no caller string ever addresses a file (T-390-10).\n return await quarantine.release(input)\n },\n}\n","// `runs.events` — the D-08 stream kind, wired against the recorded event log (FUNC-07).\n//\n// A pure function of (validated input, injected deps). The op owns the resume ARITHMETIC\n// and the refusal vocabulary; the bytes arrive through `FunctionDeps.runs.readEvents`,\n// which the composition root builds over the concrete JSONL event log.\n//\n// The stream this returns is contract-identical to the live attach 386 lands: elements are\n// the same seq-stamped envelopes in the same order, and the resume token is the element's\n// own `seq`. Replay of a completed run is simply the case where the producer has finished.\n\nimport { ReplayIncompleteError } from '@vostride/agent-qa-runner'\nimport { RunEventEnvelopeSchema, RunsEventsInputSchema } from '@vostride/agent-qa-schema'\nimport type { RunEventEnvelope, RunsEventsInput } from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict, FunctionStream, FunctionStreamSpec } from '../spec.js'\n\nexport const RUNS_EVENTS_FUNCTION_ID = 'runs.events'\n\n/**\n * The requested resume point is below the lowest seq the log can still serve.\n *\n * A caller-facing refusal, and the ONE alternative to silently serving a gap: the caller\n * learns the exact seq replay can restart at, so it can decide whether to accept the loss\n * or re-read the run in full. `earliestAvailableSeq` is the documented resume floor the\n * v49 bus reports, carried across the layer boundary unchanged.\n */\nexport class StreamReplayFloorError extends Error {\n constructor(\n readonly runId: string,\n readonly requestedSeq: number,\n readonly earliestAvailableSeq: number,\n ) {\n super(\n `Events before seq ${earliestAvailableSeq} are no longer available for run ${runId} ` +\n `(replay requested at seq ${requestedSeq})`,\n )\n this.name = 'StreamReplayFloorError'\n }\n}\n\n/**\n * Yield the acquired envelopes one at a time.\n *\n * Acquisition happens BEFORE the generator is handed out (see `invoke`), so a floor\n * refusal is an invocation failure rather than a stream that dies mid-delivery. Iteration\n * itself stays lazy, which is the shape a live producer fills in unchanged.\n */\nasync function* replay(\n events: readonly RunEventEnvelope[],\n): FunctionStream<RunEventEnvelope> {\n for (const event of events) {\n yield event\n }\n}\n\nexport const runsEventsSpec: FunctionStreamSpec<RunsEventsInput, RunEventEnvelope> = {\n id: RUNS_EVENTS_FUNCTION_ID,\n summary: \"Stream one run's recorded events in seq order, resuming after lastEventId.\",\n resultKind: 'stream',\n input: RunsEventsInputSchema,\n output: RunEventEnvelopeSchema,\n risk: { name: `fn:${RUNS_EVENTS_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * A STREAM'S VERDICT IS ABOUT THE ACQUISITION, AND IT MUST NOT READ AN ELEMENT (399.1 D-01/D-03).\n *\n * WHAT THIS OP CAN HONESTLY SAY. Every refusal it makes is a THROW before the iterable exists —\n * `StreamReplayFloorError` when the requested resume point is below what the log can still serve,\n * which is the whole reason the spec's header insists the stream is ACQUIRED inside `invoke`\n * rather than lazily on first iteration. So a stream that came back is a replay that opened, and\n * that is the fact this fold reports.\n *\n * IT DELIBERATELY IGNORES ITS ARGUMENT. Reading an element would mean CONSUMING the caller's\n * stream — a side effect, on a member both this file and {@link FunctionSpec.classify} contract as\n * pure, and one that would silently eat the first event of every replay. The argument is named\n * `_stream` so the intent is legible at the signature rather than in a comment somebody may not\n * reach.\n *\n * IT IS DECLARED HERE AND NOT INHERITED. `registry.ts` registers this spec through\n * `runsEventsSpec as FunctionSpec`, and an `as`-cast satisfies `tsc` while shipping an op with no\n * fold — which is precisely the hole the conformance census (`classifier-census.test.ts`) exists\n * to close, and precisely why the required member alone is not the whole enforcement.\n */\n classify(_stream): ClauseVerdict {\n return { status: 'executed', outcome: 'replay opened — the recorded events are streaming' }\n },\n async invoke(input, deps) {\n // The token names the last envelope the caller ALREADY observed, so replay opens at\n // the next one. Absent means the caller has observed nothing, i.e. seq 1 onward.\n const fromSeq = (input.lastEventId ?? 0) + 1\n\n let events: readonly RunEventEnvelope[]\n try {\n events = await deps.runs.readEvents(input.runId, fromSeq)\n } catch (error) {\n if (error instanceof ReplayIncompleteError) {\n throw new StreamReplayFloorError(input.runId, fromSeq, error.earliestAvailableSeq)\n }\n throw error\n }\n\n return replay(events)\n },\n}\n","// `runs.liveurl` — the ONE producer of live-view capability tokens (403 D-03).\n//\n// WHY THIS IS A FUNCTION-LAYER OP AND NOT A DASHBOARD ROUTE. The `liveUrl` is a credential of the\n// v48 family, and the milestone's constraint is that surfaces are thin clients over one typed\n// layer with no private powers. A dashboard that minted its own tokens would be a second auth\n// system with its own expiry rules, its own audit story and its own log discipline — which is\n// exactly the thing this op exists so that nobody has to write.\n\nimport {\n LIVE_URL_SCOPE,\n RunsLiveUrlInputSchema,\n RunsLiveUrlResultSchema,\n} from '@vostride/agent-qa-schema'\nimport type { RunsLiveUrlInput, RunsLiveUrlResult } from '@vostride/agent-qa-schema'\n\nimport { liveUrlOf, mintLiveUrlToken, LIVE_URL_TTL_MS } from '../live-url.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport const RUNS_LIVE_URL_FUNCTION_ID = 'runs.liveurl'\n\n/**\n * This host has no served origin to build a `liveUrl` against, or no live-view composition at all.\n *\n * A GENUINE HOST FACT, refused by name rather than answered with a URL that resolves to nothing:\n * `agent-qa run` in a terminal has no HTTP origin, and inventing one would produce a link that\n * looks live and is not.\n */\nexport class LiveViewUnavailableError extends Error {\n constructor(readonly detail: string) {\n super(`Live view is unavailable on this host: ${detail}`)\n this.name = 'LiveViewUnavailableError'\n }\n}\n\n/**\n * No such run (or no such handle on it). The SAME `unknown_run` word the run-service doors answer\n * with, so a caller that has learned one refusal vocabulary has learned them all.\n */\nexport class UnknownRunError extends Error {\n constructor(readonly runId: string) {\n super(`unknown_run: no live session for run ${runId}`)\n this.name = 'UnknownRunError'\n }\n}\n\nexport const runsLiveUrlSpec: FunctionSpec<RunsLiveUrlInput, RunsLiveUrlResult> = {\n id: RUNS_LIVE_URL_FUNCTION_ID,\n summary: 'Mint a short-lived, view-scoped live-view URL for one handle of a running run.',\n resultKind: 'unary',\n boundThrough: 'liveView',\n input: RunsLiveUrlInputSchema,\n output: RunsLiveUrlResultSchema,\n risk: { name: `fn:${RUNS_LIVE_URL_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * THE OUTCOME SENTENCE NEVER CONTAINS THE TOKEN OR THE URL (LIVE-02, D-04).\n *\n * A clause verdict is a thing surfaces PRINT — into chat transcripts, receipts and the audit\n * sink — so interpolating the result here would put a live credential into every durable record\n * this op touches, from one line of \"helpful\" formatting. What a person needs to know is that a\n * link was minted and for which handle; the link itself is already in the result they asked for.\n *\n * Declared explicitly rather than inherited: `registry.ts` registers this through a\n * `FunctionSpec` cast, and the classifier census is what makes a missing fold red.\n */\n classify(result): ClauseVerdict {\n return { status: 'executed', outcome: `liveUrl minted for handle ${result.handle}` }\n },\n async invoke(input, deps): Promise<RunsLiveUrlResult> {\n const liveView = deps.liveView\n if (!liveView) throw new LiveViewUnavailableError('no live-view port is bound on this host')\n const origin = liveView.origin()\n if (origin === undefined || origin === '') {\n throw new LiveViewUnavailableError('this host is not serving on a known origin')\n }\n\n const handle = input.handle ?? 0\n const stream = liveView.capabilityOf(input.runId, handle)\n if (stream === undefined) throw new UnknownRunError(input.runId)\n\n const now = liveView.now()\n const exp = now + LIVE_URL_TTL_MS\n const token = mintLiveUrlToken(liveView.signer, {\n subject: { kind: 'run', runId: input.runId, handle },\n scope: LIVE_URL_SCOPE,\n iat: now,\n exp,\n })\n // The one observation point for minted tokens, complete because this op is the only minter.\n // 2026-10-14 (441-16, D-01): no shipped host binds it; it never gates producing the link.\n liveView.onMinted?.(token)\n\n return { liveUrl: liveUrlOf(origin, input.runId, token), expiresAt: exp, handle, stream }\n },\n}\n","// The `liveUrl` token PAIR (403 D-01/D-02/D-04) — mint and validate, in one file, both pure.\n//\n// WHY BOTH HALVES LIVE HERE. A token system whose minter and validator are written twice is a\n// token system with two opinions about what a valid token is; the half that drifts is discovered by\n// a user, not by a test. So the dashboard route and the frame proxy call `validateLiveUrlToken` BY\n// REFERENCE through a composed port and hold no parse of their own (LIVE-02's third prohibition).\n//\n// TWO SUBJECT KINDS, ONE PAIR (428 D-07). A token names its subject: a run handle or an editor\n// session. The validator's kind-and-id comparison is the whole cross-kind rule — a run token never\n// opens an editor session and the reverse, even when the two ids are byte-identical.\n//\n// PURE BY CONSTRUCTION. `packages/agent` is providerNeutral + storageNeutral, so no host crypto\n// primitive, no `Buffer` and no host API appears here: the HMAC arrives as an injected\n// {@link LiveUrlSigner}, and base64url is hand-rolled over an ASCII-only claims body.\n\nimport { LIVE_URL_SCOPE } from '@vostride/agent-qa-schema'\nimport type {\n LiveUrlClaims,\n LiveUrlSigner,\n LiveUrlVerdict,\n LiveViewSubject,\n LiveViewSubjectRef,\n} from '@vostride/agent-qa-schema'\n\n/** The token's format marker. A FIXED prefix, deliberately — there is no algorithm negotiation. */\nexport const LIVE_URL_TOKEN_VERSION = 'v2'\n\n/** How long a minted `liveUrl` stays valid (D-02). Short by design; the socket renews in place. */\nexport const LIVE_URL_TTL_MS = 5 * 60 * 1000\n\n/** The served embed page's path prefix (D-06, ratified). Bare — no `/api/` for a host to allowlist. */\nexport const LIVE_EMBED_PATH_PREFIX = '/live/'\n\nconst BASE64URL_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n\n/** base64url-encode an ASCII string. The claims body is JSON of integers + ids, so ASCII holds. */\nexport function encodeBase64Url(text: string): string {\n let out = ''\n for (let i = 0; i < text.length; i += 3) {\n const a = text.charCodeAt(i)\n const b = i + 1 < text.length ? text.charCodeAt(i + 1) : NaN\n const c = i + 2 < text.length ? text.charCodeAt(i + 2) : NaN\n out += BASE64URL_ALPHABET[a >> 2]\n out += BASE64URL_ALPHABET[((a & 3) << 4) | (Number.isNaN(b) ? 0 : b >> 4)]\n if (Number.isNaN(b)) break\n out += BASE64URL_ALPHABET[((b & 15) << 2) | (Number.isNaN(c) ? 0 : c >> 6)]\n if (Number.isNaN(c)) break\n out += BASE64URL_ALPHABET[c & 63]\n }\n return out\n}\n\n/** base64url-decode to an ASCII string, or `undefined` when the input is not base64url at all. */\nexport function decodeBase64Url(text: string): string | undefined {\n let bits = 0\n let acc = 0\n let out = ''\n for (const ch of text) {\n const value = BASE64URL_ALPHABET.indexOf(ch)\n if (value < 0) return undefined\n acc = (acc << 6) | value\n bits += 6\n if (bits >= 8) {\n bits -= 8\n out += String.fromCharCode((acc >> bits) & 0xff)\n }\n }\n return out\n}\n\nfunction subjectBodyOf(subject: LiveViewSubject): LiveViewSubject {\n return subject.kind === 'run'\n ? { kind: 'run', runId: subject.runId, handle: subject.handle }\n : { kind: 'editor', sessionId: subject.sessionId }\n}\n\nfunction claimsBodyOf(claims: LiveUrlClaims): string {\n // Field ORDER is fixed here rather than left to `JSON.stringify` of a caller's object, because\n // the signed bytes are this exact string — a re-ordered body would be a different token.\n return encodeBase64Url(\n JSON.stringify({\n subject: subjectBodyOf(claims.subject),\n scope: claims.scope,\n iat: claims.iat,\n exp: claims.exp,\n }),\n )\n}\n\n/**\n * Mint a token for `claims`. The ONLY producer of `liveUrl` tokens in the system — `runs.liveurl`\n * is its only caller, which is what makes the minted-token secret store complete (D-04, Q4(b)).\n */\nexport function mintLiveUrlToken(signer: LiveUrlSigner, claims: LiveUrlClaims): string {\n const body = claimsBodyOf(claims)\n return `${LIVE_URL_TOKEN_VERSION}.${body}.${signer.sign(body)}`\n}\n\nfunction parseSubject(value: unknown): LiveViewSubject | undefined {\n if (typeof value !== 'object' || value === null) return undefined\n const candidate = value as Record<string, unknown>\n if (candidate.kind === 'run') {\n if (typeof candidate.runId !== 'string' || candidate.runId === '') return undefined\n const handle = candidate.handle\n if (typeof handle !== 'number' || !Number.isInteger(handle)) return undefined\n return { kind: 'run', runId: candidate.runId, handle }\n }\n if (candidate.kind === 'editor') {\n if (typeof candidate.sessionId !== 'string' || candidate.sessionId === '') return undefined\n return { kind: 'editor', sessionId: candidate.sessionId }\n }\n return undefined\n}\n\nfunction parseClaims(decoded: string): LiveUrlClaims | undefined {\n let value: unknown\n try {\n value = JSON.parse(decoded)\n } catch {\n return undefined\n }\n if (typeof value !== 'object' || value === null) return undefined\n const candidate = value as Record<string, unknown>\n const subject = parseSubject(candidate.subject)\n if (subject === undefined) return undefined\n if (typeof candidate.scope !== 'string') return undefined\n if (typeof candidate.iat !== 'number' || typeof candidate.exp !== 'number') return undefined\n return {\n subject,\n scope: candidate.scope as LiveUrlClaims['scope'],\n iat: candidate.iat,\n exp: candidate.exp,\n }\n}\n\nfunction subjectIdOf(subject: LiveViewSubject): string {\n return subject.kind === 'run' ? subject.runId : subject.sessionId\n}\n\n/**\n * Validate a token against the subject it was presented for: a run by its id, or an editor session\n * by its id. A signed subject of another kind, or of the same kind with another id, is\n * `scope_mismatch` (428 D-07).\n *\n * THE SIGNATURE IS CHECKED BEFORE THE BODY IS PARSED (T-403-01). A validator that parses first\n * reports `malformed` for an attacker-authored body and `bad_signature` only for a well-formed\n * forgery — which hands the attacker a free oracle for \"did my claims body parse\". Here, anything\n * that survives the shape check is signature-checked immediately, so an unsigned body is\n * `bad_signature` no matter how it is spelled inside.\n */\nexport function validateLiveUrlToken(\n signer: LiveUrlSigner,\n token: string,\n expect: { subject: LiveViewSubjectRef; now: number },\n): LiveUrlVerdict {\n const parts = token.split('.')\n if (parts.length !== 3) return { kind: 'refused', reason: 'malformed' }\n const [version, body, signature] = parts as [string, string, string]\n if (version !== LIVE_URL_TOKEN_VERSION) return { kind: 'refused', reason: 'malformed' }\n if (body === '' || signature === '') return { kind: 'refused', reason: 'malformed' }\n if (!signer.equals(signature, signer.sign(body))) return { kind: 'refused', reason: 'bad_signature' }\n\n const decoded = decodeBase64Url(body)\n if (decoded === undefined) return { kind: 'refused', reason: 'malformed' }\n const claims = parseClaims(decoded)\n if (claims === undefined) return { kind: 'refused', reason: 'malformed' }\n\n if (claims.exp <= expect.now) return { kind: 'refused', reason: 'expired' }\n const sameSubject =\n claims.subject.kind === expect.subject.kind && subjectIdOf(claims.subject) === expect.subject.id\n if (!sameSubject) return { kind: 'refused', reason: 'scope_mismatch' }\n if (claims.scope !== LIVE_URL_SCOPE) return { kind: 'refused', reason: 'scope_mismatch' }\n return { kind: 'ok', claims }\n}\n\n/**\n * Compose the viewer-facing URL. The token rides the FRAGMENT and nothing else (D-04): a fragment\n * is never sent to the server on any request, never lands in an access log, and never appears in a\n * `Referer` — the three durable channels a query parameter would leak into by default.\n */\nexport function liveUrlOf(origin: string, runId: string, token: string): string {\n return `${origin}${LIVE_EMBED_PATH_PREFIX}${encodeURIComponent(runId)}#${token}`\n}\n","// `editor.liveurl` — the editor subject's view token (428 D-07).\n//\n// The second caller of the one minter (403 D-03): same signer, same TTL, same fragment carriage and\n// the same `onMinted` observation hook as `runs.liveurl`, over a different subject. It reads the\n// editor lookup and nothing else, so an editor session can never become a watchable run through it.\n\nimport {\n EditorLiveUrlInputSchema,\n EditorLiveUrlResultSchema,\n LIVE_URL_SCOPE,\n} from '@vostride/agent-qa-schema'\nimport type { EditorLiveUrlInput, EditorLiveUrlResult } from '@vostride/agent-qa-schema'\n\nimport { liveUrlOf, mintLiveUrlToken, LIVE_URL_TTL_MS } from '../live-url.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\nimport { LiveViewUnavailableError } from './runs-live-url.js'\n\nexport const EDITOR_LIVE_URL_FUNCTION_ID = 'editor.liveurl'\n\n/** No such live editor session on this host. Doors map it by `error.name`. */\nexport class UnknownLiveEditorSessionError extends Error {\n constructor(readonly sessionId: string) {\n super(`unknown_session: no live editor session ${sessionId}`)\n this.name = 'UnknownLiveEditorSessionError'\n }\n}\n\nexport const editorLiveUrlSpec: FunctionSpec<EditorLiveUrlInput, EditorLiveUrlResult> = {\n id: EDITOR_LIVE_URL_FUNCTION_ID,\n summary: 'Mint a short-lived, view-scoped live-view URL for one live editor session.',\n resultKind: 'unary',\n boundThrough: 'liveView',\n input: EditorLiveUrlInputSchema,\n output: EditorLiveUrlResultSchema,\n risk: { name: `fn:${EDITOR_LIVE_URL_FUNCTION_ID}`, recognized: true, readOnly: true },\n // A fixed sentence: the result carries a live credential, and clause verdicts are printed into\n // transcripts, receipts and the audit sink.\n classify(): ClauseVerdict {\n return { status: 'executed', outcome: 'liveUrl minted for a live editor session' }\n },\n async invoke(input, deps): Promise<EditorLiveUrlResult> {\n const liveView = deps.liveView\n if (!liveView) throw new LiveViewUnavailableError('no live-view port is bound on this host')\n const origin = liveView.origin()\n if (origin === undefined || origin === '') {\n throw new LiveViewUnavailableError('this host is not serving on a known origin')\n }\n if (!liveView.editorCapabilityOf) {\n throw new LiveViewUnavailableError('this host serves no live editor')\n }\n\n const stream = liveView.editorCapabilityOf(input.sessionId)\n if (stream === undefined) throw new UnknownLiveEditorSessionError(input.sessionId)\n\n const now = liveView.now()\n const exp = now + LIVE_URL_TTL_MS\n const token = mintLiveUrlToken(liveView.signer, {\n subject: { kind: 'editor', sessionId: input.sessionId },\n scope: LIVE_URL_SCOPE,\n iat: now,\n exp,\n })\n liveView.onMinted?.(token)\n\n return { liveUrl: liveUrlOf(origin, input.sessionId, token), expiresAt: exp, stream }\n },\n}\n","// `runs.digest` — ONE run, one digest, composed live (Phase 391, D-16 / D-17 / D-18).\n//\n// PROP-04's complaint is a product complaint: an approval UX that fires forty times per nightly\n// run is worse than one that fires once. The answer is not a throttle, a debounce or a batching\n// window — every one of those is a timing knob with a wrong setting (386 D-15). The answer is a\n// PROJECTION KEYED BY `runId`. A projection keyed by a run cannot fire per event, so \"exactly\n// one digest per run\" is a property of the shape and not a rule anybody enforces.\n//\n// NOTHING IS PERSISTED HERE. The digest composes from four already-shipped read paths — the\n// analysis op (389 D-11), the chain-state op (388 D-14), the run's own mark ledger (432-09, which\n// replaced the proposals inbox of 391 plan 03) and the quarantine ledger (390 D-13) — every time\n// somebody asks. So there is nothing to drift,\n// nothing to migrate, no second copy of a run's truth to reconcile, and the frozen counts-only\n// notification row is left exactly as it was (D-16, T-391-18).\n//\n// THE TWO SIBLING OPS ARE INVOKED, NOT REIMPLEMENTED. `analysisGetSpec.invoke` and\n// `runsPostProcessingSpec.invoke` are called with THIS call's deps, so the verdict sentences in\n// a digest are the same bytes `analysis.get` serves and the chips are the same five words\n// `runs.postprocessing` serves. That is 389 D-05/D-10 and 388 D-14 honoured by CALLING them\n// rather than by a comment promising not to diverge. The specs are module-internal — nothing\n// outside this package can reach them — so this is composition inside the layer, not a\n// dispatch path around `invokeFunction` (T-384-01): every EXTERNAL caller still arrives through\n// the pipeline, and this op declares its own read-only descriptor. 2026-10-01 (432-24, D-12): the\n// read scope it also declared is gone; no op declares one now.\n//\n// REFS AND COUNTS ONLY (D-18, T-391-17). No delta content, no forget-receipt tombstones, no\n// rationale prose, no masked bytes. A mark change is its mark id, its fix and the record ids or\n// workspace path it changed (432-09, D-04/D-25). Nothing awaits a decision: no proposal store is read.\n\nimport {\n POST_PROCESSING_SKIP_REASON_WORDS,\n RunDigestSchema,\n RunsDigestInputSchema,\n} from '@vostride/agent-qa-schema'\nimport type {\n PostProcessingStatus,\n QuarantineEntryState,\n RunDigest,\n RunDigestMarkChange,\n RunsDigestInput,\n} from '@vostride/agent-qa-schema'\n\nimport { renderAnalysisClusterBlock } from '../../analysis/render-cluster-block.js'\nimport type { ClauseVerdict, FunctionDeps, FunctionSpec } from '../spec.js'\nimport { analysisGetSpec } from './analysis-get.js'\nimport { refuseMissingHandoff } from './runs-get.js'\nimport {\n projectPostProcessingChips,\n projectPostProcessingSkipped,\n runsPostProcessingSpec,\n} from './runs-post-processing.js'\n\n/**\n * Lowercase dot taxonomy (384 D-15): the `runs` domain, one noun.\n *\n * `runs.` rather than a new `digest.` domain, because what this returns is a fact ABOUT A RUN —\n * the same reason `runs.postprocessing` is not `postprocessing.get`. The exported constant is\n * what the CLI's `digest` verb, the tail's fetch pointer, 392's chat and M5 all name; the\n * literal appears here once, and the parity suite picks the id up from the registry.\n */\nexport const RUNS_DIGEST_FUNCTION_ID = 'runs.digest'\n\n/** The line separator 388 pinned for the exit summary, reused so one story reads as one. */\nconst DIGEST_SEPARATOR = ' · '\n\n/**\n * The fixes this run's marks applied, read from the run's own ledger through the read-only feedback\n * port (432-09). ABSENT where this host binds no feedback reads or the ledger cannot be read, so an\n * empty list is only ever a measurement.\n */\nasync function markChangesFor(deps: FunctionDeps, runId: RunsDigestInput['runId']): Promise<RunDigestMarkChange[] | undefined> {\n const read = await deps.feedbackReads?.history(runId)\n if (read === undefined || read.kind !== 'history') return undefined\n return read.entries.flatMap(({ receipt }) => receipt.disposition.kind === 'applied'\n ? [{ markId: receipt.markId, ordinal: receipt.ordinal, fix: receipt.disposition.fix, change: receipt.disposition.change }]\n : [])\n}\n\n/** One line per applied change: refs and counts, never record content. */\nfunction markChangeLine(row: RunDigestMarkChange): string {\n const { change } = row\n const what = change.kind === 'test-file'\n ? `wrote ${change.filePath}`\n : `${change.recordIds.length} record${change.recordIds.length === 1 ? '' : 's'} changed`\n return ` ${row.markId} ${row.fix}: ${what}`\n}\n\n/** The durable identity legs, joined — never `testId`, which is per-run (390 D-13). */\nfunction quarantineRef(entry: QuarantineEntryState): string {\n return `${entry.product}/${entry.filePath}::${entry.testName}`\n}\n\n/**\n * The rendered bytes every surface prints, composed ONCE here.\n *\n * A surface that laid these out for itself would be composing a second story about one run, and\n * the failure mode is not cosmetic: the tail's block, the CLI verb's output and 392's chat\n * would each be free to omit the section that happened to be empty on the day they were\n * written. Sections that have nothing to say still print their zero, because \"no changes\n * applied\" is a fact a person needs and an absent line is indistinguishable from a bug.\n */\nfunction renderDigestLines(digest: Omit<RunDigest, 'lines'>): string[] {\n const lines: string[] = [`digest — ${digest.runId}`]\n\n // The analysis section, through the ONE block renderer. Empty for a run with no failures,\n // which prints nothing at all rather than a header saying there is nothing.\n const clusterBlock = renderAnalysisClusterBlock({\n runId: digest.runId,\n verdicts: [],\n sentences: [],\n clusters: digest.verdictClusters,\n })\n if (clusterBlock !== '') lines.push(clusterBlock)\n\n // 425 D-08 / 444 D-39: a skipped run has no chain to report on, so the two chip words would read\n // `pending` forever. The fact replaces them in the CLI exit line's words; the outcome clause\n // keeps its own behaviour.\n const skipped = digest.chain.skipped\n const skippedWord = skipped === undefined\n ? undefined\n : POST_PROCESSING_SKIP_REASON_WORDS[skipped.reason]\n lines.push(`chain — ${[\n ...(skippedWord === undefined\n ? [`analysis: ${digest.chain.analysis}`, `curation: ${digest.chain.curation}`]\n : [`analysis: skipped (${skippedWord})`, `curation: skipped (${skippedWord})`]),\n ...(digest.chain.outcome === undefined ? [] : [`chain ${digest.chain.outcome}`]),\n ].join(DIGEST_SEPARATOR)}`)\n\n // An absent list and an empty one are not the same statement: \"no changes applied\" is a\n // measurement over a ledger that was read, and an unread ledger is said as such.\n const changes = digest.markChanges\n if (changes === undefined) {\n lines.push('marks — ledger not read here')\n } else if (changes.length === 0) {\n lines.push('marks — no changes applied')\n } else {\n lines.push(`marks — ${changes.length} change${changes.length === 1 ? '' : 's'} applied:`)\n for (const row of changes) lines.push(markChangeLine(row))\n }\n\n lines.push(`candidates — ${digest.candidates.curated} curated${DIGEST_SEPARATOR}${\n digest.candidates.deprecated} deprecated`)\n\n lines.push(`quarantine — ${digest.quarantine.quarantined} quarantined${DIGEST_SEPARATOR}${\n digest.quarantine.expired} expired${\n digest.quarantine.refs.length === 0 ? '' : `: ${digest.quarantine.refs.join(', ')}`}`)\n\n return lines\n}\n\nexport const runsDigestSpec: FunctionSpec<RunsDigestInput, RunDigest> = {\n id: RUNS_DIGEST_FUNCTION_ID,\n summary: \"Compose one run's digest: verdicts, chain, the changes its marks applied, counts.\",\n resultKind: 'unary',\n input: RunsDigestInputSchema,\n output: RunDigestSchema,\n risk: { name: `fn:${RUNS_DIGEST_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * REFS AND COUNTS, which is this op's own law rather than a house style (399.1 D-01 · 391 D-18).\n *\n * The digest's `lines` are its rendered territory and they travel on `results[]`, which D-04\n * prints in full. A receipt line reaching into them would put a run's story inside the map — the\n * exact thing D-18 pinned this op's whole shape around.\n */\n classify(output): ClauseVerdict {\n return {\n status: 'executed',\n outcome: `digest for ${output.runId} — `\n + (output.markChanges === undefined ? 'mark ledger not read'\n : `${output.markChanges.length} mark change(s) applied`),\n }\n },\n async invoke(input, deps: FunctionDeps) {\n const runId = String(input.runId)\n // A digest NAMES a run, so a run this host has never recorded is a refusal rather than a\n // page of zeros — and the check is here, against the REQUIRED runs port, so the refusal is\n // the same on a host with no analysis reader as on one that has it. Delegating it to the\n // analysis composition below would have made a correctness property depend on an optional\n // dep's presence.\n const document = await deps.runs.get(input.runId)\n if (document === undefined) return refuseMissingHandoff(input.runId, deps)\n\n // Each section is composed only where its dep is present. Explicit presence checks rather\n // than a try/catch around the invocations: swallowing would also swallow a real failure\n // inside a bound path, and \"the analysis reader threw\" is not the same fact as \"this host\n // has no analysis reader\".\n const analysis = deps.analysis === undefined\n ? undefined\n : await analysisGetSpec.invoke({ runId: input.runId }, deps)\n const status: PostProcessingStatus | undefined = deps.postProcessing === undefined\n ? undefined\n : await runsPostProcessingSpec.invoke({ runId: input.runId }, deps)\n const quarantine: readonly QuarantineEntryState[] = deps.quarantine === undefined\n ? []\n : await deps.quarantine.list()\n\n const markChanges = await markChangesFor(deps, input.runId)\n\n const curation = status?.notification?.stages.curation\n // ONE FOLD, ONE PRODUCER (law 6). On the bound path the fact is minted once, by the fold\n // inside `runs.postprocessing`, and the digest publishes what that read carried rather than\n // deriving it again — an ordinary run's status carries no skipped key, so a `??` fallback\n // here would re-derive on every ordinary run. The unbound arm is the one composition where no\n // fold ran: there the digest answers from the handoff it already loaded for its own refusal,\n // never from an empty chain, which is also what an in-flight run's chain looks like.\n const skipped = status === undefined\n ? projectPostProcessingSkipped(document)\n : status.skipped\n\n const sections: Omit<RunDigest, 'lines'> = {\n runId,\n // VERBATIM — the same cluster views, carrying the same already-composed representative\n // sentences the one renderer produced inside `analysis.get` (389 D-05/D-15).\n verdictClusters: analysis?.clusters ?? [],\n chain: {\n // `undefined` answers exactly as an empty chain does: nothing was enqueued for this\n // run, which is what a host with no queue database can honestly say (388's own note).\n ...projectPostProcessingChips(undefined),\n ...(status === undefined ? {} : status.chips),\n ...(status?.notification === undefined\n ? {}\n : { outcome: status.notification.outcome }),\n ...(skipped === undefined ? {} : { skipped }),\n },\n ...(markChanges === undefined ? {} : { markChanges }),\n candidates: {\n // Absent counts read as zero HERE and only here: the row omits them when curation never\n // committed a bundle (388 D-11), and a digest section is a place a person reads a\n // number rather than a place a distinction between \"none\" and \"not yet\" survives — the\n // chain chips one line up already carry that distinction.\n curated: curation?.curated ?? 0,\n deprecated: curation?.deprecated ?? 0,\n },\n quarantine: {\n quarantined: quarantine.filter((entry) => entry.state === 'quarantined').length,\n expired: quarantine.filter((entry) => entry.state === 'expired').length,\n // `released` entries are deliberately absent from both the counts and the refs: a\n // released test is one somebody already dealt with, and listing it every run would be\n // the graveyard 390 legislated against, one surface later.\n refs: quarantine\n .filter((entry) => entry.state === 'quarantined')\n .map(quarantineRef),\n },\n }\n\n return { ...sections, lines: renderDigestLines(sections) }\n },\n}\n","// The clustered presentation of a run's analysis — ONE layout, one package (389 D-15).\n//\n// RELOCATED from `cli/src/curation/post-run-tail.ts` by 391-06, unchanged byte-for-byte in what\n// it produces. It moved because it acquired a second caller: the per-run digest (`runs.digest`)\n// carries the clustered verdict sentences as its first section (391 D-18), and the CLI tail\n// prints the digest's rendered lines. Had the layout stayed in the CLI, the digest would have\n// needed its own — and two spellings of one block is how the terminal and the dashboard end up\n// showing the same run's problems in two different shapes with nothing wrong in either. The CLI\n// re-exports this symbol from where it used to live, so the surface that had it still names it.\n//\n// A PURE STRING FOLD over `analysis.get`'s output and nothing else. The sentence bytes are\n// `representative.sentence` VERBATIM — already composed by the one barrel renderer inside the\n// op — so every surface is byte-identical by construction (389 SC3). This function composes no\n// sentence; it decides only what a LIST of them looks like.\n\nimport type { AnalysisGetOutput } from '@vostride/agent-qa-schema'\n\n/**\n * One representative sentence per cluster: a multi-member cluster is annotated with its\n * occurrence count and member refs (`×40: TST-101, TST-102, …`), a singleton reads as one bare\n * sentence.\n *\n * Member refs print the run's own `testId`s; a degenerate member with none falls back to\n * `#testIndex` rather than an empty ref. Empty clusters render the EMPTY STRING and no header:\n * a zero-failure run has no problems to enumerate and gets no line saying so.\n */\nexport function renderAnalysisClusterBlock(analysis: AnalysisGetOutput): string {\n if (analysis.clusters.length === 0) return ''\n const problems = analysis.clusters.length\n const entries = analysis.clusters.map((cluster) => {\n if (cluster.count === 1) return cluster.representative.sentence\n const refs = cluster.members\n .map((member) => (member.testId === '' ? `#${member.testIndex}` : member.testId))\n .join(', ')\n return `×${cluster.count}: ${refs}\\n${cluster.representative.sentence}`\n })\n return `analysis — ${problems} distinct problem${problems === 1 ? '' : 's'}:\\n${\n entries.join('\\n')}`\n}\n","// `runs.postprocessing` — one run's chip truth, read from durable job state (Phase 388, D-14).\n//\n// 2026-08-26 (Phase 404, D-01): the chip set is exactly two — `{analysis, curation}`.\n// 2026-09-02 (Phase 412): the chain now derives exactly the two ids the chips read; the third\n// derived id left with the Issue-slot cleanup.\n//\n// THE single producer of a post-processing chip status. The CLI's exit summary line (plan 04),\n// any later status verb, 392's chat and M5's dashboard all call this op; none of them opens\n// `agent-jobs.db`, and none of them re-derives what a row status means. That is the L10\n// thin-client law applied to the one value in this phase that three surfaces render: three\n// spellings of four words is not a duplication a reviewer catches, it is the state in which the\n// dashboard says one thing and the CLI another about the same row, with nothing wrong in either.\n//\n// Chip truth is DURABLE truth on purpose (ANLZ-05). The bus chips a drain emits are a push\n// convenience for a socket that happens to be open; this is the answer a user who closed their\n// laptop and came back gets, and it has to be the same answer.\n//\n// The projection is exported as a pure function beside the spec, in the `runs-get.ts` idiom:\n// a total mapping with no capability, no port and nothing to await, so the exhaustive table\n// that pins it costs a test file and not a store.\n\nimport {\n CurationSnapshotSchema,\n POST_PROCESSING_DETAIL_STAGES,\n PostProcessingStatusSchema,\n RunsPostProcessingInputSchema,\n toRunNotificationView,\n} from '@vostride/agent-qa-schema'\nimport type {\n CompletedRunHandoff,\n PostProcessingChipStatus,\n PostProcessingChips,\n PostProcessingSkipReason,\n PostProcessingStatus,\n PostProcessingDetailStage,\n PostProcessingStageDetail,\n MaskFn,\n RunsPostProcessingInput,\n CurationSnapshot,\n CurationSnapshotWithheldReason,\n RunId,\n RunNotification,\n} from '@vostride/agent-qa-schema'\n\nimport { chainJobIdsForRun } from '../../jobs/chain-identity.js'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type {\n ClauseVerdict,\n FunctionDeps,\n FunctionSpec,\n PostProcessingChainState,\n PostProcessingJobRow,\n} from '../spec.js'\n\n/**\n * All lowercase, and that is a measurement rather than a taste.\n *\n * D-15's id taxonomy is pinned by `parity-coverage.test.ts` as `/^[a-z]+(?:\\.[a-z]+)+$/`, so a\n * camelCased verb segment is not a spelling this catalogue admits. The shape follows\n * `runs.events` — a domain and a noun — because what this op returns is a STATE and not an\n * action. The exported constant is what plan 04 and every later surface name; the literal\n * appears here once.\n */\nexport const RUNS_POST_PROCESSING_FUNCTION_ID = 'runs.postprocessing'\n\n/**\n * What one job row means as a chip, plus what its ABSENCE means for that particular stage.\n *\n * The absence argument is what keeps this one function rather than one per stage: every stage\n * reads a present row identically, and a stage differs only in what \"no row\" says. For both\n * chips today that is \"not yet\" (`pending`). The parameter stays even though both call sites\n * now pass the same word — a stage whose absence means something else would otherwise have to\n * be written as a second projection, which is the duplication this shape exists to prevent.\n *\n * The claim is read only for a NON-terminal row. A terminal job's claim was released by the\n * transaction that ended it, so consulting it there would be reading a field that says nothing;\n * checking the terminal statuses first also means a row that somehow carried a stale claim\n * still reports what it durably is rather than what somebody was doing to it.\n */\nfunction chipFor(\n row: PostProcessingJobRow | undefined,\n absent: PostProcessingChipStatus,\n): PostProcessingChipStatus {\n if (row === undefined) return absent\n if (row.status === 'done') return 'complete'\n // `cancelled` joins `failed` deliberately: both are terminal states in which the stage's work\n // did not happen, and a chip that told them apart would be reporting queue mechanics at a\n // reader who asked what became of their run.\n if (row.status === 'failed' || row.status === 'cancelled') return 'failed'\n return row.claimed ? 'running' : 'pending'\n}\n\n/**\n * THE projection: durable chain state → the two chips (D-14; narrowed Phase 404, D-01).\n *\n * Closed and total. `undefined` — this project holds no queue database — answers exactly as an\n * empty state does, because both are the same fact about THIS run: nothing was enqueued for it.\n * Distinguishing them here would report on the host rather than on the chain that was asked\n * about, and the caller asked about a chain.\n */\nexport function projectPostProcessingChips(\n state: PostProcessingChainState | undefined,\n): PostProcessingChips {\n return {\n analysis: chipFor(state?.analyzeRun, 'pending'),\n curation: chipFor(state?.curateMemory, 'pending'),\n }\n}\n\n/**\n * THE skipped fold: the run's durable record → why its chain was never enqueued (425 D-08, 444 D-39).\n *\n * Read from the SAME two markers the post-verdict enqueue skip reads, in the same\n * short-circuit order, so the reason a surface renders is the reason the chain was actually\n * skipped for. Never from the absence of job rows: a chain polled a second after its verdict\n * has no rows either, and calling that skipped would tell a user their run was dropped.\n * An absent document is an absent fact, never a refusal.\n */\nexport function projectPostProcessingSkipped(\n document: CompletedRunHandoff | undefined,\n): { reason: PostProcessingSkipReason } | undefined {\n if (document?.gateRun === true) return { reason: 'gate-run' }\n if (document?.excludedFromOutcomes === true) return { reason: 'outcome-excluded' }\n return undefined\n}\n\nconst IN_FLIGHT_ROW_STATUSES: ReadonlySet<string> = new Set(['running', 'pending'])\n\n/**\n * 2026-10-18 (444-12, D-14): a run with no handoff reads `no-verdict` only when its own row is\n * finished and its log holds no `verdict` envelope. The bus logs before it delivers, so a row the\n * ingest finished from a verdict always has that verdict logged. A host without `readRecord`, an\n * absent row, an unreadable log or a failed read derives nothing: absence is not a status.\n */\nasync function readNoVerdictSkipped(\n runId: RunId,\n deps: FunctionDeps,\n): Promise<{ reason: PostProcessingSkipReason } | undefined> {\n const runDetail = deps.runDetail\n if (runDetail?.readRecord === undefined) return undefined\n try {\n const record = await runDetail.readRecord(runId)\n if (record === undefined || IN_FLIGHT_ROW_STATUSES.has(record.status)) return undefined\n const events = await deps.runs.readEvents(runId, 1)\n return events.some(event => event.type === 'verdict') ? undefined : { reason: 'no-verdict' }\n } catch {\n return undefined\n }\n}\n\n/** Copy only recorded DTO facts; queue state and cancellation requests are not detail fields. */\nfunction projectStageDetails(\n state: PostProcessingChainState | undefined,\n mask: MaskFn | undefined,\n): PostProcessingStatus['stageDetails'] {\n const rows = {\n analysis: state?.analyzeRun,\n curation: state?.curateMemory,\n proposals: state?.proposeImprovements,\n } satisfies Record<PostProcessingDetailStage, PostProcessingJobRow | undefined>\n const details: NonNullable<PostProcessingStatus['stageDetails']> = {}\n for (const stage of POST_PROCESSING_DETAIL_STAGES) {\n const row = rows[stage]\n if (row === undefined) continue\n details[stage] = {\n ...(row.attempts === undefined ? {} : { attempts: row.attempts }),\n ...(row.createdAt === undefined ? {} : { createdAt: row.createdAt }),\n ...(row.claimedAt === undefined ? {} : { claimedAt: row.claimedAt }),\n ...(row.startedAt === undefined ? {} : { startedAt: row.startedAt }),\n ...(row.updatedAt === undefined ? {} : { updatedAt: row.updatedAt }),\n ...(row.conclusionKind === undefined ? {} : { conclusionKind: row.conclusionKind }),\n ...(row.lastFailureKind === undefined || mask === undefined\n ? {} : { lastFailureKind: mask(row.lastFailureKind) }),\n ...(row.lastFailureReason === undefined || mask === undefined\n ? {} : { lastFailureReason: mask(row.lastFailureReason) }),\n } satisfies PostProcessingStageDetail\n }\n return Object.keys(details).length === 0 ? undefined : details\n}\n\ntype CurationSnapshotProjection =\n | { kind: 'served'; snapshot: CurationSnapshot }\n | { kind: 'withheld'; reason: 'projection-refused' }\n\nconst refused = (): CurationSnapshotProjection => ({ kind: 'withheld', reason: 'projection-refused' })\n\nfunction projectCurationSnapshot(snapshot: CurationSnapshot, mask: MaskFn): CurationSnapshotProjection {\n const source = CurationSnapshotSchema.safeParse(snapshot)\n if (!source.success) return refused()\n const projected = {\n ...source.data,\n rows: source.data.rows.map(row => ({\n ...row,\n recordId: mask(row.recordId),\n ...(row.byRecordId === undefined ? {} : { byRecordId: mask(row.byRecordId) }),\n changes: row.changes.map(entry => ({\n ...entry,\n change: {\n ...entry.change,\n recordId: mask(entry.change.recordId),\n ...(entry.change.byRecordId === undefined ? {} : { byRecordId: mask(entry.change.byRecordId) }),\n ...(entry.change.evidenceToken === undefined ? {} : { evidenceToken: mask(entry.change.evidenceToken) }),\n ...(entry.change.sourceRunId === undefined ? {} : { sourceRunId: mask(entry.change.sourceRunId) }),\n ...(entry.change.observationId === undefined ? {} : { observationId: mask(entry.change.observationId) }),\n },\n })),\n })),\n }\n // Discriminants and constrained hex digests remain structural facts. If redaction\n // collapses identities, withhold rather than merge rows or fabricate a new breakdown.\n const result = CurationSnapshotSchema.safeParse(projected)\n if (!result.success) return refused()\n return { kind: 'served', snapshot: result.data }\n}\n\ntype RecordedSnapshots =\n | { kind: 'served'; checkpoint?: CurationSnapshot; nested?: CurationSnapshot }\n | { kind: 'withheld'; reason: CurationSnapshotWithheldReason }\n\n/**\n * One verdict for both recorded copies (423 D-15, Gap 2). With no mask projection is not\n * attempted; with one, either copy refusing withholds both, so the checkpoint and the\n * notification can never disagree.\n */\nfunction projectRecordedSnapshots(\n state: PostProcessingChainState | undefined,\n mask: MaskFn | undefined,\n): RecordedSnapshots {\n const recorded = {\n checkpoint: state?.curationSnapshot,\n nested: state?.notification?.stages.curation.curationSnapshot,\n }\n if (recorded.checkpoint === undefined && recorded.nested === undefined) return { kind: 'served' }\n if (mask === undefined) return { kind: 'withheld', reason: 'masking-unavailable' }\n const served: { checkpoint?: CurationSnapshot; nested?: CurationSnapshot } = {}\n for (const key of ['checkpoint', 'nested'] as const) {\n const snapshot = recorded[key]\n if (snapshot === undefined) continue\n const projection = projectCurationSnapshot(snapshot, mask)\n if (projection.kind === 'withheld') return projection\n served[key] = projection.snapshot\n }\n return { kind: 'served', ...served }\n}\n\n// Without a usable mask, failure prose is omitted and recorded snapshots are withheld.\nfunction projectMasked(state: PostProcessingChainState | undefined, mask: MaskFn | undefined) {\n return {\n stageDetails: projectStageDetails(state, mask),\n snapshots: projectRecordedSnapshots(state, mask),\n }\n}\n\nfunction withNestedSnapshot(\n notification: RunNotification,\n snapshot: CurationSnapshot | undefined,\n): RunNotification {\n const { curationSnapshot: _recorded, ...curation } = notification.stages.curation\n return {\n ...notification,\n stages: {\n ...notification.stages,\n curation: { ...curation, ...(snapshot === undefined ? {} : { curationSnapshot: snapshot }) },\n },\n }\n}\n\nexport const runsPostProcessingSpec: FunctionSpec<RunsPostProcessingInput, PostProcessingStatus> = {\n id: RUNS_POST_PROCESSING_FUNCTION_ID,\n summary: \"Read one run's post-processing chip statuses from durable job state.\",\n resultKind: 'unary',\n // Bound exactly where a composition supplies durable queue storage (D-16 idiom). A host that\n // cannot see the queue lists this by name as `unbound` rather than answering all-pending\n // about a chain it has no way to observe.\n boundThrough: 'postProcessing',\n input: RunsPostProcessingInputSchema,\n output: PostProcessingStatusSchema,\n risk: { name: `fn:${RUNS_POST_PROCESSING_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * The two chips drive classification; recorded stage details do not change read success.\n *\n * A chip reading `failed` is this op reporting a CHAIN's state truthfully; the read succeeded.\n * Folding a red chip into the clause's own status would make \"the post-run chain broke\" and \"I\n * could not tell you about the post-run chain\" the same line on a receipt.\n */\n classify(output): ClauseVerdict {\n return {\n status: 'executed',\n outcome: `chain for ${output.runId} — analysis ${output.chips.analysis}, `\n + `curation ${output.chips.curation}`,\n }\n },\n async invoke(input, deps) {\n // `invokeFunction` already refused this composition on the same fact; reaching here with no\n // port means an in-layer caller holding the spec directly, and the refusal is the same\n // named error either way (384, D-09).\n const postProcessing = deps.postProcessing\n if (postProcessing === undefined) {\n throw new FunctionNotBoundError(RUNS_POST_PROCESSING_FUNCTION_ID)\n }\n\n const runId = String(input.runId)\n // The ONE derivation, imported rather than restated (RESEARCH Pattern 2). Derived HERE and\n // handed down, so the rows read are the rows the enqueue addressed through this same host's\n // id source — two copies of the hash input would be two chains that review identically.\n const ids = chainJobIdsForRun(runId, postProcessing.idSource)\n const state = await postProcessing.readChain(ids, runId)\n // Through the REQUIRED runs port, and with no refusal on absence. The not-found throw\n // `runs.get` and `runs.digest` raise is theirs: each NAMES a run, while a chain can\n // legitimately be polled before its handoff lands (the skip runs after the write). An\n // absent document carries no handoff marker; only the run's own record can say no-verdict.\n const handoff = await deps.runs.get(input.runId)\n const skipped = projectPostProcessingSkipped(handoff)\n ?? (handoff === undefined ? await readNoVerdictSkipped(input.runId, deps) : undefined)\n let projected: ReturnType<typeof projectMasked>\n try {\n projected = projectMasked(state, deps.secretMask)\n } catch {\n projected = projectMasked(state, undefined)\n }\n const { stageDetails, snapshots } = projected\n const curationSnapshot = snapshots.kind === 'served' ? snapshots.checkpoint : undefined\n const recordedNotification = state?.notification\n const notification = recordedNotification?.stages.curation.curationSnapshot === undefined\n ? recordedNotification\n : withNestedSnapshot(recordedNotification,\n snapshots.kind === 'served' ? snapshots.nested : undefined)\n\n return {\n runId,\n chips: projectPostProcessingChips(state),\n ...(stageDetails === undefined ? {} : { stageDetails }),\n ...(curationSnapshot === undefined ? {} : { curationSnapshot }),\n ...(snapshots.kind === 'withheld' ? { curationSnapshotWithheld: { reason: snapshots.reason } } : {}),\n ...(skipped === undefined ? {} : { skipped }),\n // Absence is spread away rather than padded (the `runs-get.ts` idiom): a chain in flight\n // has no record yet, and a rendered `null` would be a second spelling of what a missing\n // key already says.\n ...(notification === undefined ? {} : { notification: toRunNotificationView(notification) }),\n }\n },\n}\n","// `runs.artifact` — one content-addressed evidence blob, run-scoped (Phase 405 plan 05, D-12/D-13).\n//\n// THE FOURTH-DOOR LAW APPLIED TO BYTES (404 D-16, D-13). The alternative was a route in\n// `routes.ts` constructing the evidence store and streaming `getBlob` itself — a private store\n// read, which is a capability the function layer cannot see, cannot audit and cannot offer to the\n// CLI, MCP or 408's embed. Routing the bytes through an op is what makes \"resolve this ref\" one\n// question with one answer, asked by every surface that holds a ref.\n//\n// THE PORT IS OPTIONAL AND THE OP REFUSES BY NAME (the `postProcessing` idiom). Widening the\n// REQUIRED `RunsReaderPort` with a blob verb would have made every daemon, MCP and test\n// implementer satisfy a method most of them have no storage for; an optional dep makes \"this host\n// cannot serve artifacts\" a visible `unbound` row rather than a call that fails somewhere far away.\n//\n// ABSENCE IS TWO ANSWERS, NOT ONE (D-15). `unknown_run` and `blob_absent` are different operator\n// situations — a bad link versus a GC'd or never-written artifact — and the page renders the second\n// as a visible \"screenshot unavailable\" state rather than as an error. `getBlob` collapses both\n// into `undefined`, so the SPLIT is made in the port and the two arms are refused by two names.\n//\n// THE CONTENT TYPE IS SNIFFED FROM THE BYTES AND THE SNIFFER CANNOT ANSWER MARKUP (T-405-15). The\n// store keeps no metadata, so the only honest source for \"what is this\" is the head of the blob;\n// and a sniffer with an `image/svg+xml` or `text/html` arm would let whatever wrote the blob choose\n// a type the browser executes. There are three answers and two of them are raster images.\n//\n// THE RESULT DECLARES ITS OWN SIZE. `byteLength` rides beside the base64 so neither the receipt\n// fold below nor the route's `Content-Length` has to read the payload to learn how big it is — a\n// fold that inspected its own payload is exactly what the ops-directory census refuses.\n//\n// NO `Buffer` AND NO HOST API. `packages/agent` is storageNeutral, so base64 is hand-rolled over\n// the `Uint8Array` exactly as `live-url.ts` hand-rolls base64url over an ASCII claims body.\n\nimport { RunsArtifactInputSchema, RunsArtifactResultSchema } from '@vostride/agent-qa-schema'\nimport type { RunsArtifactInput, RunsArtifactResult } from '@vostride/agent-qa-schema'\n\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\nimport { RunNotFoundError } from './runs-get.js'\n\n/**\n * All lowercase and two segments, because the id taxonomy is pinned as `/^[a-z]+(?:\\.[a-z]+)+$/` —\n * `runs.artifactBlob` is not a spelling this catalogue admits. The exported constant is what the\n * dashboard composition hands its server as DATA; `packages/dashboard-server` may not import this\n * package, so the literal appears here once.\n */\nexport const RUNS_ARTIFACT_FUNCTION_ID = 'runs.artifact'\n\n/**\n * The run exists and holds no blob under that sha (D-15).\n *\n * A SEPARATE REFUSAL FROM `RunNotFoundError`, and separate because the two ask different things of\n * whoever reads them: an unknown run is a link that was never valid, while an absent blob is an\n * artifact that was collected, never written, or declared incomplete by its own ref. The dashboard\n * renders the second as a visible unavailable state (406 upgrades that rendering); rendering it as\n * \"no such run\" would tell an operator to go look for a run that is right there.\n *\n * Carries both coordinates so a surface can say WHICH artifact of which run is missing. The route\n * adapter does not echo them — a refusal body that quoted the request's own sha would be a\n * reflection this door has no reason to offer — but a CLI or chat caller holding the error can.\n */\nexport class EvidenceBlobAbsentError extends Error {\n constructor(\n readonly runId: string,\n readonly sha: string,\n ) {\n super(`No evidence blob is recorded for run ${runId} under that content address`)\n this.name = 'EvidenceBlobAbsentError'\n }\n}\n\nconst BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n\n/** The PNG signature, whole. A prefix of it is not a PNG and must not be typed as one. */\nconst PNG_SIGNATURE: readonly number[] = [0x89, 0x50, 0x4e, 0x47]\n/** The JFIF/EXIF start-of-image marker plus its first marker byte. */\nconst JPEG_SIGNATURE: readonly number[] = [0xff, 0xd8, 0xff]\nconst WEBM_SIGNATURE: readonly number[] = [0x1a, 0x45, 0xdf, 0xa3]\nconst MP4_FTYP_SIGNATURE: readonly number[] = [0x66, 0x74, 0x79, 0x70]\n\nexport const ARTIFACT_RANGE_MAX_BYTES = 1048576\nexport const EVIDENCE_SNIFF_HEAD_BYTES = 12\n\nexport class ArtifactRangeNotSatisfiableError extends Error {\n constructor(readonly totalLength: number) {\n super('Artifact range starts beyond the available bytes')\n this.name = 'ArtifactRangeNotSatisfiableError'\n }\n}\n\n/** The type a blob gets when nothing recognises it — opaque, and never rendered as a document. */\nexport const OPAQUE_EVIDENCE_CONTENT_TYPE = 'application/octet-stream'\n\nfunction startsWith(bytes: Uint8Array, signature: readonly number[], offset = 0): boolean {\n if (bytes.length < signature.length + offset) return false\n for (let i = 0; i < signature.length; i += 1) {\n if (bytes[i + offset] !== signature[i]) return false\n }\n return true\n}\n\n/**\n * What these bytes ARE, decided by their own head and by nothing a caller said (D-12, T-405-15).\n *\n * TOTAL, PURE AND DELIBERATELY NARROW. Two raster magics and one opaque default is the whole\n * vocabulary: the blobs this store holds are decision screenshots, and every type outside that set\n * is either something the runner does not write or something a browser would execute. An SVG or an\n * HTML document therefore serves as `application/octet-stream` — which, with the route's\n * `X-Content-Type-Options: nosniff`, is a download and not a script.\n *\n * Exported beside the spec in the `projectRunTokenTotals` idiom: a total mapping with no port and\n * nothing to await can have an exhaustive table written over it for the cost of a test file.\n */\nexport function sniffEvidenceContentType(bytes: Uint8Array): string {\n if (startsWith(bytes, PNG_SIGNATURE)) return 'image/png'\n if (startsWith(bytes, JPEG_SIGNATURE)) return 'image/jpeg'\n if (startsWith(bytes, WEBM_SIGNATURE)) return 'video/webm'\n if (startsWith(bytes, MP4_FTYP_SIGNATURE, 4)) return 'video/mp4'\n return OPAQUE_EVIDENCE_CONTENT_TYPE\n}\n\n/**\n * Standard base64 over raw bytes, hand-rolled.\n *\n * `packages/agent` is storageNeutral and names no host API, so `Buffer.from(bytes).toString(\n * 'base64')` is unavailable here by the same rule that makes `live-url.ts` hand-roll base64url.\n * Padded with `=` because the adapter decodes with the platform's own reader, which expects it.\n */\nfunction encodeBase64(bytes: Uint8Array): string {\n let out = ''\n for (let i = 0; i < bytes.length; i += 3) {\n const a = bytes[i] ?? 0\n const hasB = i + 1 < bytes.length\n const hasC = i + 2 < bytes.length\n const b = hasB ? bytes[i + 1] ?? 0 : 0\n const c = hasC ? bytes[i + 2] ?? 0 : 0\n out += BASE64_ALPHABET[a >> 2]\n out += BASE64_ALPHABET[((a & 0x03) << 4) | (b >> 4)]\n out += hasB ? BASE64_ALPHABET[((b & 0x0f) << 2) | (c >> 6)] : '='\n out += hasC ? BASE64_ALPHABET[c & 0x3f] : '='\n }\n return out\n}\n\nexport const runsArtifactSpec: FunctionSpec<RunsArtifactInput, RunsArtifactResult> = {\n id: RUNS_ARTIFACT_FUNCTION_ID,\n summary: \"Read one run's content-addressed evidence blob by its sha, with a sniffed content type.\",\n resultKind: 'unary',\n // Bound exactly where a composition owns a runtime root (every local host does). A host that\n // holds no run directories lists this by name as `unbound` rather than answering `blob_absent`\n // about every artifact in the product, which would look like a storage failure.\n boundThrough: 'evidenceBlobs',\n input: RunsArtifactInputSchema,\n output: RunsArtifactResultSchema,\n risk: { name: `fn:${RUNS_ARTIFACT_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * The type and the size, which are what a receipt can honestly say about serving bytes.\n *\n * NOT THE BYTES AND NOT THE BASE64. An audit row that quoted the payload would be the blob\n * written a second time, into the one record that is kept forever — and receipts are read by\n * people, in terminals.\n */\n classify(output): ClauseVerdict {\n // TWO DECLARED FIELDS AND NOTHING FROM INSIDE THE PAYLOAD. `byteLength` is on the result\n // precisely so this line does not have to measure `bytesBase64` to write a receipt — a fold\n // that reached into its own payload would be the value matching 399.1 D-01 abolished, and a\n // base64 body has no part of it a receipt may quote in any case.\n return {\n status: 'executed',\n outcome: `${output.contentType}, ${String(output.byteLength)} bytes for ${output.runId}`,\n }\n },\n async invoke(input, deps) {\n // `invokeFunction` already refused this composition on the same fact; reaching here with no\n // port means an in-layer caller holding the spec directly, and the refusal is the same named\n // error either way (384, D-09).\n const port = deps.evidenceBlobs\n if (port === undefined) {\n throw new FunctionNotBoundError(RUNS_ARTIFACT_FUNCTION_ID)\n }\n\n const runId = String(input.runId)\n if (input.range !== undefined) {\n const assertFound = <T extends { status: string }>(lookup: T): void => {\n if (lookup.status === 'unknown_run') throw new RunNotFoundError(runId)\n if (lookup.status === 'blob_absent') throw new EvidenceBlobAbsentError(runId, input.sha)\n }\n let whole: Uint8Array | undefined\n let totalLength: number\n if (port.stat !== undefined && port.readRange !== undefined) {\n const lookup = await port.stat(input.runId, input.sha)\n assertFound(lookup)\n if (lookup.status !== 'found') throw new EvidenceBlobAbsentError(runId, input.sha)\n totalLength = lookup.byteLength\n } else {\n const lookup = await port.read(input.runId, input.sha)\n assertFound(lookup)\n if (lookup.status !== 'found') throw new EvidenceBlobAbsentError(runId, input.sha)\n whole = lookup.bytes\n totalLength = whole.length\n }\n const { start } = input.range\n if (start >= totalLength) throw new ArtifactRangeNotSatisfiableError(totalLength)\n const end = Math.min(input.range.end ?? totalLength - 1, totalLength - 1, start + ARTIFACT_RANGE_MAX_BYTES - 1)\n const readSlice = async (from: number, to: number): Promise<Uint8Array> => {\n if (whole !== undefined) return whole.slice(from, to + 1)\n const lookup = await port.readRange!(input.runId, input.sha, from, to)\n assertFound(lookup)\n if (lookup.status !== 'found') throw new EvidenceBlobAbsentError(runId, input.sha)\n return lookup.bytes\n }\n const head = await readSlice(0, Math.min(EVIDENCE_SNIFF_HEAD_BYTES, totalLength) - 1)\n const bytes = await readSlice(start, end)\n return {\n runId, sha: input.sha, contentType: sniffEvidenceContentType(head),\n byteLength: bytes.length, bytesBase64: encodeBase64(bytes), totalLength, range: { start, end },\n }\n }\n const lookup = await port.read(input.runId, input.sha)\n if (lookup.status === 'unknown_run') {\n // REUSED, NEVER RE-MINTED. `runs.get` already owns \"no run is recorded under that id\", and a\n // second not-found class would give one surface two words for one answer.\n throw new RunNotFoundError(runId)\n }\n if (lookup.status === 'blob_absent') {\n throw new EvidenceBlobAbsentError(runId, input.sha)\n }\n\n return {\n runId,\n sha: input.sha,\n contentType: sniffEvidenceContentType(lookup.bytes),\n byteLength: lookup.bytes.length,\n bytesBase64: encodeBase64(lookup.bytes),\n }\n },\n}\n","// `runs.detail` — one run's durable members, steps and sub-actions (Phase 405 plan 01, D-03).\n//\n// THE FOURTH-DOOR LAW APPLIED TO RUN DETAIL (404 D-16). The dashboard's run-detail page used to\n// read SQLite from inside `routes.ts`; a private store read is a capability the function layer\n// cannot see, cannot audit and cannot offer to the CLI, MCP or chat. So the page reads through\n// this op, the HTTP arm formats nothing, and every surface that wants \"what did that run do\"\n// asks the same question of the same registry.\n//\n// ONE RESULT, NOT PAGED. A run's projection is bounded by the run — members by the suite, steps\n// by the member's instruction count, sub-actions by the loop's own budget — and a cursor would\n// buy a page that renders a whole run all at once nothing except a second way to be wrong about\n// where a step belongs. RESEARCH's alternatives table records the measurement.\n//\n// THE TOKEN SUM IS COMPUTED HERE (D-06) and is exported beside the spec as a pure function, in\n// the `runs-post-processing.ts` idiom: a total mapping with no capability, no port and nothing to\n// await, so the exhaustive table that pins it costs a test file and not a store. Computing it in\n// the port would put the sum in whichever composition happens to hold a database — which is one\n// producer per host of a number the page prints as though there were one.\n\nimport {\n RunDetailProjectionSchema,\n RunsDetailInputSchema,\n} from '@vostride/agent-qa-schema'\nimport type {\n MarkReceipt,\n RunDetailMemberMark,\n RunDetailProjection,\n RunDetailStep,\n RecordingEntry,\n RunId,\n RunTokenTotals,\n RunModelSummary,\n RunsDetailInput,\n} from '@vostride/agent-qa-schema'\n\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, EvidenceBlobReaderPort, FunctionSpec } from '../spec.js'\nimport { annotatePresence } from './evidence-presence.js'\nimport { IN_RUNS_DATABASE, RunNotFoundError } from './runs-get.js'\n\n/**\n * All lowercase and two segments, because D-15's id taxonomy is pinned as\n * `/^[a-z]+(?:\\.[a-z]+)+$/` — a camelCased segment is not a spelling this catalogue admits. The\n * exported constant is what the dashboard composition hands its server as DATA;\n * `packages/dashboard-server` may not import this package, so the literal appears here once.\n */\nexport const RUNS_DETAIL_FUNCTION_ID = 'runs.detail'\n\n/**\n * THE run-level token sum (D-06). Pure, total, and the ONE producer of \"M of K steps unmeasured\".\n *\n * A step counts as MEASURED exactly when it carries a `tokenUsage` — the additive-optional field\n * the runner appends only for a step whose model calls reported usage. A cache hit, a bypass or a\n * provider that reports nothing has no field, and that is a different fact from a step that spent\n * zero tokens.\n *\n * THE THREE SUMS ARE SPREAD IN ONLY WHEN SOMETHING WAS MEASURED, which is the whole of \"absent ≠\n * zero\". With no measured step the answer is `{ measuredSteps: 0, unmeasuredSteps: K }` and no\n * `totalTokens` key at all, so a page cannot render `0 tokens` for a run nobody measured. The v1\n * `prompt_tokens INTEGER DEFAULT 0` column is exactly the lie this shape refuses to be able to\n * tell.\n */\nexport function projectRunTokenTotals(steps: readonly RunDetailStep[]): RunTokenTotals {\n let measuredSteps = 0\n let promptTokens = 0\n let completionTokens = 0\n let totalTokens = 0\n let cachedInputTokens = 0\n let cachedMeasuredSteps = 0\n let cachedInputMeasuredTokens = 0\n\n for (const step of steps) {\n const usage = step.tokenUsage\n if (usage === undefined) continue\n measuredSteps += 1\n promptTokens += usage.promptTokens\n completionTokens += usage.completionTokens\n totalTokens += usage.totalTokens\n if (usage.cachedInputTokens !== undefined) {\n cachedInputTokens += usage.cachedInputTokens\n cachedMeasuredSteps += 1\n cachedInputMeasuredTokens += usage.promptTokens\n }\n }\n\n return {\n measuredSteps,\n unmeasuredSteps: steps.length - measuredSteps,\n ...(measuredSteps === 0 ? {} : { promptTokens, completionTokens, totalTokens }),\n ...(cachedMeasuredSteps === 0 ? {} : {\n cachedInputTokens, cachedMeasuredSteps, cachedInputMeasuredTokens,\n }),\n }\n}\n\n/** Fold already-masked persisted identities; calls and configured roles never multiply steps. */\nexport function projectRunModelSummary(steps: readonly RunDetailStep[]): RunModelSummary | undefined {\n type Identity = { provider?: string; modelId: string }\n const declared = new Map<string, { identity: Identity & { provider: string }; steps: Set<string> }>()\n const responding = new Map<string, { identity: Identity; steps: Set<string> }>()\n function add<T extends Identity>(map: Map<string, { identity: T; steps: Set<string> }>,\n identity: T, step: string) {\n const key = JSON.stringify([identity.provider, identity.modelId])\n const entry = map.get(key) ?? { identity, steps: new Set<string>() }\n entry.steps.add(step)\n map.set(key, entry)\n }\n for (const step of steps) {\n const stepKey = `${step.testIndex}:${step.stepIndex}`\n for (const facts of Object.values(step.modelUsage?.roles ?? {})) {\n if (facts.declared !== undefined) add(declared, facts.declared, stepKey)\n for (const modelId of facts.respondingModelIds ?? []) {\n add(responding, { modelId,\n ...(facts.declared === undefined ? {} : { provider: facts.declared.provider }) }, stepKey)\n }\n }\n }\n if (declared.size === 0 && responding.size === 0) return undefined\n return {\n ...(declared.size === 0 ? {} : { declared: [...declared.values()]\n .map(entry => ({ ...entry.identity, stepCount: entry.steps.size })) }),\n ...(responding.size === 0 ? {} : { responding: [...responding.values()]\n .map(entry => ({ ...entry.identity, stepCount: entry.steps.size })) }),\n }\n}\n\nasync function projectMemberRecording(\n recording: RecordingEntry | undefined,\n port: EvidenceBlobReaderPort | undefined,\n runId: RunId,\n): Promise<RecordingEntry> {\n if (recording === undefined) return { state: 'absent', reason: 'unavailable' }\n if (recording.state !== 'present') return recording\n const [ref] = await annotatePresence(port, runId, [recording.ref])\n return ref?.present === false\n ? { state: 'absent', reason: 'unavailable', evidenceIncomplete: true }\n : recording\n}\n\nexport const runsDetailSpec: FunctionSpec<RunsDetailInput, RunDetailProjection> = {\n id: RUNS_DETAIL_FUNCTION_ID,\n summary: \"Read one run's durable members, steps and sub-actions as the dashboard projected them.\",\n resultKind: 'unary',\n // Bound exactly where a composition owns the dashboard's projection database (the D-16 idiom). A\n // host that holds no such database lists this by name as `unbound` rather than answering an\n // empty run about a projection it has no way to observe.\n boundThrough: 'runDetail',\n input: RunsDetailInputSchema,\n output: RunDetailProjectionSchema,\n risk: { name: `fn:${RUNS_DETAIL_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * The three counts, which are what a receipt can honestly say about a read like this one.\n *\n * NOT THE TOKEN SUM: a receipt line quoting a number the caller is about to render would be a\n * second place that number is stated, and D-06 exists because two producers of one total drift.\n */\n classify(output): ClauseVerdict {\n return {\n status: 'executed',\n outcome: `${String(output.members.length)} member(s), `\n + `${String(output.steps.length)} step(s), `\n + `${String(output.subActions.length)} sub-action(s)`,\n }\n },\n async invoke(input, deps) {\n // `invokeFunction` already refused this composition on the same fact; reaching here with no\n // port means an in-layer caller holding the spec directly, and the refusal is the same named\n // error either way (384, D-09).\n const port = deps.runDetail\n if (port === undefined) {\n throw new FunctionNotBoundError(RUNS_DETAIL_FUNCTION_ID)\n }\n\n const rows = await port.read(input.runId)\n // REUSED, NEVER RE-MINTED. `runs.get` already owns \"no run is recorded under that id\" as a\n // caller-facing refusal, and a second not-found class would give one surface two words for one\n // answer — which is how a page ends up rendering \"unknown run\" and \"run not found\" from the\n // same door depending on which read it tried first.\n if (rows === undefined) {\n throw new RunNotFoundError(String(input.runId), IN_RUNS_DATABASE)\n }\n\n // 419 D-11/D-15: the ledger is append-only; only its latest ordinal per member/step\n // governs. No catch: a bound reader that throws is a broken host, not an absent ledger.\n let members = [...rows.members]\n if (deps.feedback !== undefined) {\n const latest = new Map<string, MarkReceipt>()\n for (const mark of await deps.feedback.marksFor(input.runId)) {\n const address = `${mark.testIndex}:${mark.stepIndex ?? 'run'}`\n const prior = latest.get(address)\n if (prior === undefined || mark.ordinal > prior.ordinal) latest.set(address, mark)\n }\n const byMember = new Map<number, RunDetailMemberMark[]>()\n for (const mark of latest.values()) {\n const marks = byMember.get(mark.testIndex) ?? []\n marks.push({\n markId: mark.markId,\n kind: mark.kind,\n ordinal: mark.ordinal,\n ...(mark.stepIndex === undefined ? {} : { stepIndex: mark.stepIndex }),\n disposition: mark.disposition,\n })\n byMember.set(mark.testIndex, marks)\n }\n members = rows.members.map(member => {\n // Bound-but-unmarked enables the first mark; unbound above still omits the key.\n const marks = byMember.get(member.testIndex) ?? []\n marks.sort((a, b) => (a.stepIndex ?? -1) - (b.stepIndex ?? -1))\n return { ...member, marks }\n })\n }\n\n members = await Promise.all(members.map(async member => ({\n ...member,\n recording: await projectMemberRecording(member.recording, deps.evidenceBlobs, input.runId),\n })))\n\n // READ-TIME PRESENCE, OPPORTUNISTICALLY (406 D-17). The projection recorded which blobs a\n // sub-action produced; only a stat taken now can say whether they survived. `boundThrough`\n // stays `runDetail` because this is not a binding condition: a host with no runtime root\n // serves the whole projection and simply omits the key, which is presence UNKNOWN rather than\n // a claimed absence.\n const subActions = await Promise.all(rows.subActions.map(async (subAction) => {\n const ariaEvidence = subAction.ariaEvidence === undefined ? {\n kind: 'aria' as const, state: 'absent' as const, reason: 'unavailable' as const,\n } : subAction.ariaEvidence\n const refs = subAction.artifactRefs\n if (refs === undefined) return { ...subAction, ariaEvidence }\n const artifactRefs = await annotatePresence(deps.evidenceBlobs, input.runId, refs)\n return { ...subAction, artifactRefs, ariaEvidence }\n }))\n\n // Only absent persisted fields gain a read-time state. Configuration and handoffs cannot\n // establish what was captured. ARIA stays on real children; a childless step gains none.\n const steps: RunDetailStep[] = rows.steps.map(step => ({\n ...step,\n evidence: step.evidence === undefined ? {\n console: { kind: 'console', state: 'absent', reason: 'unavailable' },\n network: { kind: 'network', state: 'absent', reason: 'unavailable' },\n a11y: { kind: 'a11y', state: 'absent', reason: 'unavailable' },\n variables: { kind: 'variables', state: 'absent', reason: 'unavailable' },\n } : step.evidence,\n }))\n\n const models = projectRunModelSummary(rows.steps)\n return {\n runId: rows.runId,\n members,\n steps,\n subActions,\n tokens: projectRunTokenTotals(rows.steps),\n ...(models === undefined ? {} : { models }),\n }\n },\n}\n","import {\n EvidenceDocumentSchema, EvidenceEntrySchema, RunsEvidenceInputSchema, RunsEvidenceOutputContract,\n RunsEvidenceResultSchema, sha256hexBytes, utf8Decode, utf8Encode,\n RUN_EVIDENCE_DOCUMENT_SCHEMA_VERSION,\n} from '@vostride/agent-qa-schema'\nimport type {\n EvidenceDocument, EvidenceEntry, MaskFn, RunDetailRows, RunsEvidenceInput, RunsEvidenceResult,\n} from '@vostride/agent-qa-schema'\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { FunctionSpec } from '../spec.js'\nimport { IN_RUNS_DATABASE, RunNotFoundError } from './runs-get.js'\n\nexport const RUNS_EVIDENCE_FUNCTION_ID = 'runs.evidence'\n\n// Only free-text maps mask keys. Schema keys, kind/source/impact enums and SHA identities\n// remain structural data. Refuse collisions rather than silently losing a recorded value.\nfunction maskMap<T, U>(value: Record<string, T>, mask: MaskFn, project: (item: T) => U): Record<string, U> {\n const entries = Object.entries(value).map(([key, item]) => [mask(key), project(item)] as const)\n if (new Set(entries.map(([key]) => key)).size !== entries.length) throw new Error('Masked key collision')\n return Object.fromEntries(entries)\n}\n\nfunction maskDocument(document: EvidenceDocument, mask: MaskFn): EvidenceDocument {\n switch (document.kind) {\n case 'aria': return { ...document, tree: mask(document.tree) }\n case 'variables': return { ...document, records: maskMap(document.records, mask, item => ({ ...item, value: mask(item.value) })) }\n case 'console': return { ...document, records: document.records.map(item => ({\n ...item, level: mask(item.level), text: mask(item.text),\n ...(item.location === undefined ? {} : { location: { ...item.location, url: mask(item.location.url) } }),\n })) }\n case 'network': return { ...document, records: document.records.map(item => ({\n ...item, url: mask(item.url), method: mask(item.method),\n requestHeaders: maskMap(item.requestHeaders, mask, mask),\n responseHeaders: maskMap(item.responseHeaders, mask, mask),\n ...(item.body === undefined ? {} : { body: mask(item.body) }),\n ...(item.requestBody === undefined ? {} : { requestBody: mask(item.requestBody) }),\n ...(item.timing === undefined ? {} : { timing: maskMap(item.timing, mask, value => value) }),\n })) }\n case 'a11y': return { ...document, records: document.records.map(item => ({\n ...item, ruleId: mask(item.ruleId), description: mask(item.description), help: mask(item.help),\n helpUrl: mask(item.helpUrl), nodes: item.nodes.map(node => ({ html: mask(node.html), target: node.target.map(mask) })),\n })) }\n }\n}\n\nexport const runsEvidenceSpec: FunctionSpec<RunsEvidenceInput, RunsEvidenceResult> = {\n id: RUNS_EVIDENCE_FUNCTION_ID,\n summary: 'Read validated evidence recorded on one run step or ARIA sub-action.',\n resultKind: 'unary',\n boundThrough: 'runDetail',\n input: RunsEvidenceInputSchema,\n output: RunsEvidenceResultSchema,\n // 431-03 (D-03/D-07): the declared output is the canonical document; validation stays `output`.\n outputRepresentation: RunsEvidenceOutputContract,\n risk: { name: `fn:${RUNS_EVIDENCE_FUNCTION_ID}`, recognized: true, readOnly: true },\n classify(output) {\n return { status: output.outcome === 'read-error' ? 'failed' : 'executed', outcome: output.outcome }\n },\n async invoke(input, deps) {\n const address = RunsEvidenceInputSchema.parse(input)\n const detail = deps.runDetail\n const blobs = deps.evidenceBlobs\n if (detail === undefined || blobs === undefined) throw new FunctionNotBoundError(RUNS_EVIDENCE_FUNCTION_ID)\n const error = (code: Extract<RunsEvidenceResult, { outcome: 'read-error' }>['code'], capture?: EvidenceEntry): RunsEvidenceResult => ({\n address, outcome: 'read-error', code, ...(capture === undefined ? {} : { capture }),\n })\n const absent = (reason: 'unavailable' | 'not-captured', incomplete = false): RunsEvidenceResult => ({\n address, outcome: 'absent', evidence: { kind: address.kind, state: 'absent', reason,\n ...(incomplete ? { evidenceIncomplete: true } : {}),\n },\n })\n let rows: RunDetailRows | undefined\n try { rows = await detail.read(address.runId) } catch { return error('storage-read-failed') }\n if (rows === undefined) throw new RunNotFoundError(String(address.runId), IN_RUNS_DATABASE)\n if (rows.runId !== address.runId) return error('ref-not-owned')\n const steps = rows.steps.filter(row => row.testIndex === address.testIndex && row.stepIndex === address.stepIndex)\n if (steps.length === 0) return error('address-not-found')\n if (steps.length !== 1) return error('ambiguous-address')\n const step = steps[0]!\n let rawEntry: unknown\n let child: RunDetailRows['subActions'][number] | undefined\n if (address.kind === 'aria') {\n if (address.subActionIndex === undefined) return absent('not-captured')\n const children = rows.subActions.filter(row => row.testIndex === address.testIndex\n && row.stepIndex === address.stepIndex && row.subActionIndex === address.subActionIndex)\n if (children.length === 0) return error('address-not-found')\n if (children.length !== 1) return error('ambiguous-address')\n child = children[0]!\n if (child.ariaEvidence === undefined) return absent('unavailable')\n rawEntry = child.ariaEvidence\n } else {\n if (step.evidence === undefined) return absent('unavailable')\n rawEntry = step.evidence?.[address.kind]\n }\n const parsedEntry = EvidenceEntrySchema.safeParse(rawEntry)\n if (!parsedEntry.success || parsedEntry.data.kind !== address.kind) return error('invalid-entry')\n const capture = parsedEntry.data\n if (capture.state === 'absent') return { address, outcome: 'absent', evidence: capture }\n\n let rawDocument: unknown\n if (capture.kind === 'variables') {\n if (step.variableSnapshot === undefined) return error('snapshot-missing', capture)\n rawDocument = {\n schemaVersion: RUN_EVIDENCE_DOCUMENT_SCHEMA_VERSION,\n kind: 'variables',\n records: step.variableSnapshot,\n }\n } else {\n if (capture.kind === 'aria' && !child?.artifactRefs?.some(ref => ref.id === capture.ref.id && ref.sha === capture.ref.sha)) {\n return error('ref-not-owned', capture)\n }\n let lookup\n try { lookup = await blobs.read(address.runId, capture.ref.sha) } catch { return error('storage-read-failed', capture) }\n if (lookup.status === 'unknown_run') throw new RunNotFoundError(String(address.runId))\n if (lookup.status === 'blob_absent') return absent('unavailable', true)\n // Integrity is checked over immutable bytes before any text decoding or masking.\n if (sha256hexBytes(lookup.bytes) !== capture.ref.sha) return error('sha-mismatch', capture)\n try {\n const text = utf8Decode(lookup.bytes)\n const roundtrip = utf8Encode(text)\n if (roundtrip.length !== lookup.bytes.length || !roundtrip.every((byte, index) => byte === lookup.bytes[index])) {\n return error('invalid-document', capture)\n }\n rawDocument = JSON.parse(text)\n } catch { return error('invalid-document', capture) }\n }\n const parsed = EvidenceDocumentSchema.safeParse(rawDocument)\n if (!parsed.success || parsed.data.kind !== address.kind) return error('invalid-document', capture)\n // A valid document that cannot be masked is unreadable, never evidence and never invalid.\n const declared = deps.secretMask\n if (declared === undefined) return error('masking-unavailable', capture)\n let maskFailed = false\n const mask: MaskFn = text => {\n try { return declared(text) } catch (cause) { maskFailed = true; throw cause }\n }\n try {\n const document = maskDocument(parsed.data, mask)\n return RunsEvidenceResultSchema.parse({ address, outcome: 'ready', evidence: capture, document })\n } catch { return error(maskFailed ? 'masking-unavailable' : 'invalid-document', capture) }\n },\n}\n","// `runs.knowledge` — what ONE run used and learned (Phase 407, LERN-01 / LERN-02 · D-05 / D-06).\n//\n// THE PANEL'S ONE READ. D-05's posture is that the Knowledge tab is a thin client over a single\n// registry verb, not a page composing N `knowledge.brief.why` calls: the browser, the CLI, MCP\n// and chat all ask this one question and get the same bytes. That is the fourth-door law applied\n// to a surface that would otherwise have been assembled client-side out of per-step reads whose\n// answers could disagree with each other about one run.\n//\n// THE SUBSTRATE IS THE RUN'S HANDOFF, AND NOTHING ELSE (D-06). `deps.runs.get` resolves through\n// the same `enumerate()` / `loadCompletedRunHandoff` version guard `readStepEvidence` uses, so\n// this op and `knowledge.brief.why` can never disagree about what a run recorded. It is NOT the\n// dashboard `run_steps` projection — those rows carry no served brief at all.\n//\n// IT ANSWERS ABOUT THEN. This op is handed no serving capability: there is no index handle in\n// scope, so re-running retrieval to explain a brief is not a temptation it has to resist. A step\n// whose trace was never captured answers `no-trace: pre-trace-run` — the honest absence — rather\n// than a plausible trace computed against today's index (KREV-02's founding argument).\n//\n// A PRUNED HANDOFF IS A RESULT, NOT A THROW (D-06). `runs.digest` next door raises\n// `RunNotFoundError` because a digest NAMES a run and a missing one is a bad question. Here the\n// caller is a PAGE, and a page whose evidence has been garbage-collected has a legible state to\n// render (406 D-17's `EvidenceIncomplete`); a refusal would make that state indistinguishable\n// from a broken read.\n//\n// THE SIBLING OPS ARE INVOKED, NOT REIMPLEMENTED (391's rule). The curation word is the same word\n// `runs.postprocessing` serves and the change list is the same list `knowledge.records.diff`\n// serves — by CALLING them with this call's deps rather than by a comment promising not to diverge.\n// 2026-09-30, 432-09 (D-25): no pending-proposal count is joined; the tab shows what changed. The\n// specs are module-internal, so this is composition inside the layer and not a dispatch path\n// around `invokeFunction`: every external caller still arrives through the pipeline. 2026-10-01\n// (432-26, D-12): the op declares no `read` scope, and no step of that pipeline checks one.\n\nimport {\n maskRecordContent,\n NO_KNOWLEDGE_READER_TRUNCATION,\n projectRecordContent,\n RecordedRetrievalRungSchema,\n RunKnowledgeProjectionSchema,\n RunsKnowledgeInputSchema,\n} from '@vostride/agent-qa-schema'\nimport type {\n BriefLine,\n CautionLine,\n CompletedRunHandoff,\n CurationSnapshot,\n KnowledgeRecordShowResult,\n MaskFn,\n PostProcessingStatus,\n ReadTrace,\n RecordChange,\n RecordedRetrievalRung,\n RunKnowledgeCanaryAttribution,\n RunKnowledgePlanSource,\n RunKnowledgeProjection,\n RunKnowledgeStep,\n RunKnowledgeTrace,\n RunsKnowledgeInput,\n StepEvidence,\n StepPlanSource,\n} from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict, FunctionDeps, FunctionSpec, KnowledgeReaderPort } from '../spec.js'\nimport { knowledgeRecordsDiffSpec } from './knowledge-records-diff.js'\nimport {\n projectPostProcessingChips,\n projectPostProcessingSkipped,\n runsPostProcessingSpec,\n} from './runs-post-processing.js'\nimport { requireSecretMask } from './secret-mask.js'\n\n/**\n * Lowercase dot taxonomy (384 D-15): the `runs` domain, one noun.\n *\n * `runs.knowledge` and not `knowledge.run`, for the reason `runs.postprocessing` is not\n * `postprocessing.get` — what this returns is a fact ABOUT A RUN. The literal appears here once;\n * every surface names the exported constant and the parity suite picks the id up from the\n * registry.\n */\nexport const RUNS_KNOWLEDGE_FUNCTION_ID = 'runs.knowledge'\n\n/**\n * The recorded rung, VALIDATED and never cast, because the handoff is bytes another build wrote.\n */\nfunction recordedRungOf(evidence: StepEvidence): RecordedRetrievalRung | undefined {\n if (evidence.retrievalRung === undefined) return undefined\n const parsed = RecordedRetrievalRungSchema.safeParse(evidence.retrievalRung)\n return parsed.success ? parsed.data : undefined\n}\n\n/**\n * Why this step's brief said what it said — `mapStepEvidenceToWhy`'s `found` arm, per step.\n *\n * The two arms and the `pre-trace-run` reason are the why-verb's own vocabulary rather than a\n * second spelling of it: the panel and `knowledge.brief.why` answer about the same step with the\n * same word. The lookup arms that verb also carries (`run-not-recorded`, `step-not-found`) cannot\n * arise here — a step reached through the loaded document exists by construction — so the panel's\n * evidence-gone state is the projection's own `evidence-incomplete` arm one level up.\n */\nfunction traceArmOf(evidence: StepEvidence): RunKnowledgeTrace {\n const trace = evidence.retrievalTrace\n if (trace === undefined) {\n return { kind: 'no-trace', reason: 'pre-trace-run' }\n }\n return { kind: 'answered', trace }\n}\n\n// The three channel projections PICK named fields rather than spreading the producer's value, so\n// a field added to the serving contract cannot silently reach a page (405's display posture).\nfunction briefLine(line: BriefLine): RunKnowledgeStep['served']['channel1'][number] {\n return {\n id: String(line.id),\n kind: line.kind,\n summary: line.summary,\n trust: line.trust,\n status: line.status,\n servedAsCanary: line.servedAsCanary,\n tier: line.tier,\n }\n}\n\nfunction readTrace(entry: ReadTrace): RunKnowledgeStep['served']['channel2'][number] {\n return {\n id: String(entry.id),\n detailLevel: entry.detailLevel,\n bodyDigest: entry.bodyDigest,\n }\n}\n\n/** Anchors are deliberately dropped: the panel renders a caution's sentence and nothing else. */\nfunction cautionLine(line: CautionLine): RunKnowledgeStep['served']['channel3'][number] {\n return { id: String(line.id), summary: line.summary }\n}\n\n/**\n * The plan source, PICKED member by member for the same reason the channels are (CR-01).\n *\n * This was the one producer value the op spread verbatim, and the wire arm it spread onto is\n * `.strict()` — so the day `StepPlanSource` grew `flow`, every run that had really replayed a\n * procedure started failing `spec.output.parse` with `unrecognized_keys` and the Knowledge tab\n * rendered a read failure for exactly the runs D-07 exists to explain. A field-pick makes that\n * class of break impossible rather than pending: an undeclared member on disk is DROPPED here,\n * and a member this build wants on the wire has to be named in both places on the same commit.\n *\n * Every optional is spread-when-defined, never zero-filled: an absent `miss` is an absent key.\n */\nfunction planSourceOf(source: StepPlanSource): RunKnowledgePlanSource {\n if (source.kind === 'procedure-hint') {\n return {\n kind: 'procedure-hint',\n procedureId: String(source.procedureId),\n ...(source.demotion === undefined ? {} : { demotion: source.demotion }),\n }\n }\n const { checksPassed, total, miss, executionFailure, verifierRejection } = source.guard\n const { flow } = source\n return {\n kind: 'procedure-replay',\n procedureId: String(source.procedureId),\n guard: {\n checksPassed,\n total,\n ...(miss === undefined\n ? {}\n : { miss: { procedureStepIndex: miss.procedureStepIndex, reason: miss.reason } }),\n ...(executionFailure === undefined\n ? {}\n : { executionFailure: { procedureStepIndex: executionFailure.procedureStepIndex } }),\n ...(verifierRejection === undefined\n ? {}\n : { verifierRejection: { procedureStepIndex: verifierRejection.procedureStepIndex } }),\n },\n ...(flow === undefined ? {} : { flow: { cursor: flow.cursor, length: flow.length } }),\n }\n}\n\nfunction projectStep(\n testId: string,\n testIndex: number,\n evidence: StepEvidence,\n): RunKnowledgeStep {\n const rung = recordedRungOf(evidence)\n return {\n testId,\n testIndex,\n stepIndex: evidence.stepIndex,\n stepText: evidence.stepText,\n served: {\n channel1: evidence.servedBrief.channel1.map(briefLine),\n channel2: evidence.servedBrief.channel2.map(readTrace),\n channel3: evidence.servedBrief.channel3.map(cautionLine),\n },\n trace: traceArmOf(evidence),\n // PICKED, not spread (CR-01) — see `planSourceOf`. Spread-away absence, never a `null` and\n // never a zero-fill: a step that replayed no procedure carries NO `planSource` key, which is\n // a different byte from one that carries an empty source (the layer's own idiom).\n ...(evidence.planSource === undefined\n ? {}\n : { planSource: planSourceOf(evidence.planSource) }),\n ...(rung === undefined ? {} : { retrievalRung: rung }),\n }\n}\n\n/**\n * `unbound` means THIS PROJECT HAS NO KNOWLEDGE STORE, derived from durable bytes (D-16).\n *\n * The marker is the `truncation` sentence the runner writes when it serves a step with no reader\n * bound — the one durable fact that distinguishes \"nothing was configured\" from \"retrieval ran\n * and served nothing\", and one that cannot be recovered from an empty channel list. Derived from\n * the evidence rather than from the handoff version on purpose: a version says WHEN a run\n * happened, not what was bound to it.\n *\n * A run with zero steps reads `bound`, which is the conservative answer — it says nothing about\n * a store rather than reporting an absence nothing observed. A step carrying a recorded rung\n * reads `bound` even if its brief was empty, because a rung is only ever resolved when a reader\n * existed to resolve it against.\n */\nfunction knowledgeStoreOf(steps: readonly StepEvidence[]): 'bound' | 'unbound' {\n if (steps.length === 0) return 'bound'\n const everyStepUnserved = steps.every(\n (evidence) => evidence.servedBrief.truncation === NO_KNOWLEDGE_READER_TRUNCATION,\n )\n const noRungRecorded = steps.every((evidence) => recordedRungOf(evidence) === undefined)\n return everyStepUnserved && noRungRecorded ? 'unbound' : 'bound'\n}\n\nfunction stepsOf(document: CompletedRunHandoff): readonly StepEvidence[] {\n return document.tests.flatMap((test) => test.steps)\n}\n\n/**\n * Is this the knowledge store saying \"I could not read all of myself\"? (407-14, CR-03)\n *\n * READ BY NAME, STRUCTURALLY, ON PURPOSE. `KnowledgeMaintenanceScanError` is declared in\n * `packages/knowledge-local`, and this layer is storage-neutral — it holds a PORT, not a store, so\n * it cannot import that class to test with `instanceof` without acquiring a dependency on one\n * particular substrate (403-03 D-4's rule, and the same reason the op's own test file constructs\n * the error rather than importing it). The class pins its own `name` as a readonly literal, which\n * makes the string the stable part of the contract across the boundary.\n *\n * The narrowness is the safety. Only THIS name folds; every other error still leaves this op the\n * way it arrived, so a bound path's real failure is still a failure.\n */\nfunction isScanIncomplete(error: unknown): boolean {\n return error instanceof Error && error.name === 'KnowledgeMaintenanceScanError'\n}\n\ntype ReadyProjection = Extract<RunKnowledgeProjection, { kind: 'ready' }>\ntype LearnedChange = ReadyProjection['learned']['changes'][number]\ntype RecordContent = NonNullable<LearnedChange['recordContent']>\ntype RecordJoin =\n | { recordContent: RecordContent }\n | { contentAbsence: NonNullable<LearnedChange['contentAbsence']> }\n\n/**\n * Current record content, picked field by field and masked string by string (423 D-20/D-21).\n *\n * Trust and status are copied from the maintenance view (`deriveBundleTrust`'s answer), never\n * recomputed, and are named `current*` so no reader mistakes them for what the row recorded.\n * Record identities are not joined strings: the row's own id stays exactly what it was. The pick\n * and the mask are the schema's shared join, which runs.mark.preview's knowledge records use too.\n */\nfunction recordContentOf(\n result: Extract<KnowledgeRecordShowResult, { kind: 'found' }>,\n mask: MaskFn,\n): RecordContent {\n return maskRecordContent(projectRecordContent(result), mask)\n}\n\n/**\n * ONE batch read over the union of every learned and used identity (423 D-20).\n *\n * There is deliberately no per-id fallback to `showRecord`: that read scans every bundle per id.\n * A host without the batch capability gets a named `not-bound` absence on every row instead, and\n * a store that could not finish the scan gets `scan-incomplete` — never a row silently dropped\n * and never an incomplete scan dressed as ordinary misses.\n */\nasync function joinRecords(\n knowledge: KnowledgeReaderPort,\n recordIds: readonly string[],\n mask: MaskFn,\n): Promise<{ joinFor: (recordId: string) => RecordJoin; scanIncomplete: boolean }> {\n const showRecords = knowledge.showRecords\n if (showRecords === undefined) {\n return { joinFor: () => ({ contentAbsence: { reason: 'not-bound' } }), scanIncomplete: false }\n }\n const unique = [...new Set(recordIds)]\n if (unique.length === 0) {\n return { joinFor: () => ({ contentAbsence: { reason: 'not-found' } }), scanIncomplete: false }\n }\n let results: readonly KnowledgeRecordShowResult[]\n try {\n results = await showRecords.call(knowledge, { recordIds: unique })\n } catch (error) {\n if (!isScanIncomplete(error)) throw error\n return {\n joinFor: () => ({ contentAbsence: { reason: 'scan-incomplete' } }),\n scanIncomplete: true,\n }\n }\n const found = new Map<string, RecordContent>()\n for (const result of results) {\n if (result.kind === 'found') found.set(result.record.recordId, recordContentOf(result, mask))\n }\n return {\n joinFor: (recordId) => {\n const content = found.get(recordId)\n return content === undefined\n ? { contentAbsence: { reason: 'not-found' } }\n : { recordContent: content }\n },\n scanIncomplete: false,\n }\n}\n\n/**\n * Is this attributed change one the fixed snapshot recorded? (423 D-15)\n *\n * Compared on the identity both readers retain — record, change, ordinal and replacement — and\n * on the evidence token only where both carry one: `diffSince` reports a record's appearance without\n * the receipt token curation recorded. The snapshot arrives masked, so the change is compared in\n * the same masked form. Record id alone is never enough: a later promotion of a record the\n * snapshot already names is a since-then change.\n */\nfunction recordedBySnapshot(\n change: RecordChange,\n snapshot: CurationSnapshot,\n mask: MaskFn,\n): boolean {\n const recordId = mask(change.recordId)\n const byRecordId = change.byRecordId === undefined ? undefined : mask(change.byRecordId)\n const evidenceToken = change.evidenceToken === undefined ? undefined : mask(change.evidenceToken)\n return snapshot.rows.some((row) => row.changes.some(({ change: recorded }) =>\n recorded.recordId === recordId\n && recorded.change === change.change\n && recorded.atOrdinal === change.atOrdinal\n && recorded.byRecordId === byRecordId\n && (recorded.evidenceToken === undefined || evidenceToken === undefined\n || recorded.evidenceToken === evidenceToken)))\n}\n\nexport const runsKnowledgeSpec: FunctionSpec<RunsKnowledgeInput, RunKnowledgeProjection> = {\n id: RUNS_KNOWLEDGE_FUNCTION_ID,\n summary: \"Project one run's used brief channels, serve-time traces, procedure use, recorded \"\n + 'retrieval rung and curator deltas from its handoff.',\n resultKind: 'unary',\n // NO OPTIONAL-DEP BINDING KEY IS DECLARED ON THIS SPEC AT ALL, and the absence is a claim about\n // the op's substrate rather than an oversight. Its truth is the RUNS port, and that port is\n // REQUIRED — so, exactly like `knowledge.brief.why`, there is no composition that lists this\n // verb and then cannot run it. The optional deps it consults (`postProcessing` and the reader's\n // `canaryAttributions`) only ENRICH the Learned half; binding\n // this op to any of them would leave a host with no queue database unable to see what its own\n // runs used, which is the majority of this projection. Pinned by a cell, and by the grep in the\n // plan's own acceptance criteria — which is why the declaration keyword is not spelled anywhere\n // in this file, including in this comment.\n input: RunsKnowledgeInputSchema,\n output: RunKnowledgeProjectionSchema,\n risk: { name: `fn:${RUNS_KNOWLEDGE_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * COUNTS, NOT CONTENT (399.1 D-01 · 391 D-18's rule applied here).\n *\n * A receipt line names how much a run used and learned; the brief summaries, step text and\n * record ids themselves stay in `results[]` where a reader asked for them. Interpolating a\n * served summary here would put producer prose — possibly masked material — into an audit map.\n *\n * `evidence-incomplete` is `executed` and not a refusal, on `knowledge.brief.why`'s reasoning:\n * a pruned handoff is an answer this verb is proud of, not a control declining.\n */\n classify(output): ClauseVerdict {\n if (output.kind === 'evidence-incomplete') {\n return {\n status: 'executed',\n outcome: `knowledge for ${output.runId} — evidence incomplete`,\n }\n }\n const briefLines = output.steps.reduce(\n (total, step) => total + step.served.channel1.length,\n 0,\n )\n return {\n status: 'executed',\n outcome: `knowledge for ${output.runId} — ${String(output.steps.length)} steps, `\n + `${String(briefLines)} brief lines served, `\n + `${String(output.learned.changes.length)} learned change(s)`\n // T-407-29. A degraded Learned half and a genuinely empty one both read `0 learned\n // change(s)`, and an audit map that could not tell them apart would let an incomplete scan\n // pass as a clean result forever. A clean read's line is byte-identical to what it always\n // was — the suffix appears only where the flag does.\n + (output.learned.scanIncomplete === true ? ', knowledge store scan incomplete' : ''),\n }\n },\n async invoke(input, deps: FunctionDeps) {\n const runId = String(input.runId)\n\n const document = await deps.runs.get(input.runId)\n if (document === undefined) {\n // D-06: a RESULT. The page renders the evidence-gone state; it does not catch anything.\n return { kind: 'evidence-incomplete', runId }\n }\n\n const steps = document.tests.flatMap((test) =>\n test.steps.map((evidence) => projectStep(test.testId, test.testIndex, evidence)))\n const evidence = stepsOf(document)\n\n // Run-constant by construction (D-13): the rung is resolved ONCE at composition and stamped\n // on every step, so the first step carrying one carries the run's. Reading it per step as\n // well is what lets a future producer change stay visible rather than silently averaged.\n const runRung = evidence.map(recordedRungOf).find((rung) => rung !== undefined)\n\n // TWO DIFFERENT QUESTIONS, ANSWERED TWO DIFFERENT WAYS (407-14, CR-03).\n //\n // PRESENCE is still checked rather than caught: \"this host has no queue database\" is not the\n // same fact as \"the queue read threw\" (runs-digest's rule), and a blanket try/catch would\n // erase that difference along with every real failure inside a bound path.\n //\n // What IS caught, and only around the two knowledge-store enrichments, is the store's own\n // named scan error (`isScanIncomplete`). A store that cannot read one bundle is not a store\n // that is absent, and it is not a broken op either — it is a store that can answer PART of\n // this question. Each enrichment folds INDEPENDENTLY to an empty list, and the fold is\n // announced on the wire as `learned.scanIncomplete` rather than hidden inside an emptiness the\n // caller would read as \"nothing was learned\". Anything not carrying that name propagates\n // exactly as it did before.\n //\n // AND THE FLAG IS RAISED BY CONTRACT, NOT BY COINCIDENCE (407-19, REVIEW WR-03). The\n // attribution walk reports `skippedBundles` on its own answer, so a store it could only\n // half-read raises this flag even when it returns rows and even when the records diff read\n // cleanly. Before that count existed, the only thing raising the flag for a half-read store\n // was `diffSince` happening to throw on the same bundle — an inference that fails the moment\n // the two reads see different stores. A degradation marker belongs to the read that degraded;\n // it is never inferred from a sibling.\n let scanIncomplete = false\n const status: PostProcessingStatus | undefined = deps.postProcessing === undefined\n ? undefined\n : await runsPostProcessingSpec.invoke({ runId: input.runId }, deps)\n const curationRow = status?.notification?.stages.curation\n // BOTH counts or neither (D-09/D-12). The frozen notification row omits them when curation\n // never committed a bundle, and a half-present pair rendered as `curated 3, deprecated 0`\n // would report a number nobody measured.\n const countsPresent = curationRow?.curated !== undefined\n && curationRow.deprecated !== undefined\n\n // Channel 1 only — a `ReadTrace` has no `servedAsCanary` authority (the pin\n // `emit-canary-outcomes.ts` already relies on), and the served line's own id IS the curation\n // candidate id.\n const tuples = document.tests.flatMap((test) =>\n test.steps.flatMap((step) =>\n step.servedBrief.channel1\n .filter((line) => line.servedAsCanary)\n .map((line) => ({\n candidateId: String(line.id),\n testId: test.testId,\n testIndex: test.testIndex,\n stepIndex: step.stepIndex,\n }))))\n\n const attribute = deps.knowledge.canaryAttributions\n let attributions: Awaited<ReturnType<NonNullable<typeof attribute>>>['rows'] = []\n if (attribute !== undefined && tuples.length > 0) {\n try {\n const attributed = await attribute.call(deps.knowledge, { runId, tuples })\n attributions = attributed.rows\n // The rows are kept BESIDE the flag rather than dropped by it: a bundle the walk could not\n // load denies nothing to the bundles that read cleanly (407-14's rule), and the flag says\n // the list may be short — not that it is worthless.\n if (attributed.skippedBundles > 0) scanIncomplete = true\n } catch (error) {\n if (!isScanIncomplete(error)) throw error\n scanIncomplete = true\n attributions = []\n }\n }\n // Rows appear ONLY for a tuple with a surviving attributed outcome; one still pending is\n // absent here and the panel reads \"attribution pending\" from the curation word. `flatMap`\n // rather than filter-then-map so the narrowing is PROVED by the control flow instead of\n // re-stated in an assertion the compiler cannot check against a later shape change.\n const canaryAttributions: RunKnowledgeCanaryAttribution[] = attributions.flatMap((row) =>\n row.outcome === undefined\n ? []\n : [{\n testIndex: row.testIndex,\n stepIndex: row.stepIndex,\n recordId: row.candidateId,\n observationId: row.observationId,\n outcome: row.outcome,\n }])\n\n // ATTRIBUTION, NOT A WINDOW (D-10). The since-ordinal only bounds how much the sibling op\n // reads; what makes a row THIS run's is the explicit link — the bundle provenance run id\n // 407-04 stamps, or an observation id recomputed from this run's own served-canary tuples.\n // A row carrying neither is DROPPED rather than guessed at: \"this run deprecated that fact\"\n // is a sentence a person acts on, and a neighbouring run's curation must never wear it.\n const observationIds = new Set(attributions.map((row) => row.observationId))\n let changes: RecordChange[] = []\n let diffChanges: readonly RecordChange[] = []\n try {\n const diff = await knowledgeRecordsDiffSpec.invoke(\n { sinceOrdinal: Math.max(0, document.buildOrdinal - 1) },\n deps,\n )\n diffChanges = diff.changes\n changes = diff.changes.filter((change) =>\n change.sourceRunId === runId\n || (change.observationId !== undefined && observationIds.has(change.observationId)))\n } catch (error) {\n // `diffSince` keeps its MAINTENANCE-grade contract next door: a malformed bundle is an error\n // to a maintainer asking what changed, and this op does not soften it there. The degradation\n // belongs HERE, where the caller is a page (D-06's absence-is-a-result posture applied to the\n // Learned enrichment) — an empty attributed list, and a flag naming why it is empty.\n if (!isScanIncomplete(error)) throw error\n scanIncomplete = true\n changes = []\n }\n\n const mask = requireSecretMask(deps, RUNS_KNOWLEDGE_FUNCTION_ID)\n\n // The fixed checkpoint first; the notification carries a copy of the same snapshot.\n const curationSnapshot = status?.curationSnapshot\n ?? status?.notification?.stages.curation.curationSnapshot\n\n // THE SNAPSHOT'S OWN RECORD IS ALSO AN ATTRIBUTION (427-02, owner decision option-a). A\n // confirmation, deprecation or supersession of a record an earlier run created carries no run\n // link in the store, yet this run's curation recorded it by exact identity. Admitting it here,\n // before the join, is what gives every snapshot row its content; record id alone never admits.\n if (curationSnapshot !== undefined) {\n const linked = new Set(changes)\n changes = diffChanges.filter((change) =>\n linked.has(change) || recordedBySnapshot(change, curationSnapshot, mask))\n }\n\n const join = await joinRecords(deps.knowledge, [\n ...steps.flatMap((row) => [\n ...row.served.channel1.map((line) => line.id),\n ...row.served.channel2.map((line) => line.id),\n ...row.served.channel3.map((line) => line.id),\n ]),\n ...changes.map((row) => row.recordId),\n ], mask)\n if (join.scanIncomplete) scanIncomplete = true\n const joinedSteps = steps.map((row) => ({\n ...row,\n served: {\n channel1: row.served.channel1.map((line) => ({ ...line, ...join.joinFor(line.id) })),\n channel2: row.served.channel2.map((line) => ({ ...line, ...join.joinFor(line.id) })),\n channel3: row.served.channel3.map((line) => ({ ...line, ...join.joinFor(line.id) })),\n },\n }))\n const joinedChanges: LearnedChange[] = changes.map((row) => ({\n ...row,\n ...join.joinFor(row.recordId),\n }))\n\n const skipped = projectPostProcessingSkipped(document)\n\n const sinceThen = curationSnapshot === undefined\n ? undefined\n : joinedChanges.filter((row) => !recordedBySnapshot(row, curationSnapshot, mask))\n\n return {\n kind: 'ready',\n runId,\n buildOrdinal: document.buildOrdinal,\n knowledgeStore: knowledgeStoreOf(evidence),\n ...(runRung === undefined ? {} : { retrievalRung: runRung }),\n steps: joinedSteps,\n curation: {\n // `undefined` answers exactly as an empty chain does — nothing was enqueued for this run\n // — which is what a host with no queue database can honestly say (388's own note).\n status: status?.chips.curation ?? projectPostProcessingChips(undefined).curation,\n ...(countsPresent && curationRow !== undefined\n ? {\n counts: {\n curated: curationRow.curated as number,\n deprecated: curationRow.deprecated as number,\n },\n }\n : {}),\n // 2026-10-18 (444-26, D-61): the run's own handoff says why its chain was never enqueued,\n // by the fold runs.postprocessing calls, so it holds on a host with no queue database too.\n ...(skipped === undefined ? {} : { skipped: { reason: skipped.reason } }),\n },\n learned: {\n changes: joinedChanges,\n canaryAttributions,\n ...(curationSnapshot === undefined ? {} : { curationSnapshot }),\n // Withheld by the nested read: the snapshot and sinceThen stay absent, the rows stay served.\n ...(status?.curationSnapshotWithheld === undefined\n ? {}\n : { curationSnapshotWithheld: status.curationSnapshotWithheld }),\n ...(sinceThen === undefined\n ? {}\n : { sinceThen: { changes: sinceThen, count: sinceThen.length } }),\n // Spread-when-true, never zero-filled: an absent key is the clean read, and `false` is a\n // byte this DTO does not have (the layer's own no-null idiom).\n ...(scanIncomplete ? { scanIncomplete: true as const } : {}),\n },\n }\n },\n}\n","import type { MaskFn } from '@vostride/agent-qa-schema'\n\nimport type { FunctionDeps } from '../spec.js'\n\n// 2026-10-14 (441-16, D-06, E3): a refusing run read masks with the host's declared mask. Unbound,\n// it refuses here; a mask that throws (the secrets file cannot be read) refuses with its own message,\n// probed once so the refusal does not depend on what the run happens to hold.\nexport function requireSecretMask(deps: FunctionDeps, functionId: string): MaskFn {\n const mask = deps.secretMask\n if (mask === undefined) {\n throw new Error(`${functionId} cannot mask run text: this host binds no declared-secret mask.`)\n }\n mask('')\n return mask\n}\n","// `runs.list` — the tracer capability (Phase 384, D-06), widened by 431 D-08.\n//\n// A pure function of (validated input, injected deps): it filters ONE completed-run snapshot,\n// orders it newest-finished first under a total order (endedAt, then runId) so a fixed fixture\n// always renders byte-identically, and caps what it returns only after every filter has run.\n//\n// Test names are stored text, masked with the host's declared mask exactly as runs.overview masks\n// them, and the title filter only ever sees the masked name.\n\nimport {\n RUNS_LIST_DEFAULT_LIMIT,\n RunsListInputSchema,\n RunsListOutputContract,\n RunsListOutputSchema,\n} from '@vostride/agent-qa-schema'\nimport type {\n CompletedRunHandoff,\n MaskFn,\n RecordedTargets,\n RunSummary,\n RunsListInput,\n} from '@vostride/agent-qa-schema'\n\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\nimport { requireSecretMask } from './secret-mask.js'\n\nexport const RUNS_LIST_FUNCTION_ID = 'runs.list'\n\nexport function toRunSummary(\n document: CompletedRunHandoff,\n recordedTargets: RecordedTargets,\n mask: MaskFn,\n): RunSummary {\n return {\n runId: document.runId,\n scope: document.scope,\n buildOrdinal: document.buildOrdinal,\n executionContext: document.executionContext,\n aggregateVerdict: document.aggregateVerdict,\n startedAt: document.startedAt,\n endedAt: document.endedAt,\n testCount: document.tests.length,\n tests: document.tests.map((test) => ({\n testIndex: test.testIndex,\n testId: test.testId,\n testName: mask(test.testName),\n })),\n recordedTargets,\n }\n}\n\n/** Latest finished first: `endedAt` descending, then `runId` descending, so the order is total. */\nexport function compareLatestFinished(\n left: { readonly endedAt: number; readonly runId: string },\n right: { readonly endedAt: number; readonly runId: string },\n): number {\n if (left.endedAt !== right.endedAt) return right.endedAt - left.endedAt\n return left.runId < right.runId ? 1 : left.runId > right.runId ? -1 : 0\n}\n\nfunction namesTest(document: CompletedRunHandoff, filter: string, mask: MaskFn): boolean {\n const needle = filter.toLowerCase()\n return document.tests.some((test) => (\n test.testId === filter || mask(test.testName).toLowerCase().includes(needle)\n ))\n}\n\nfunction recordsTarget(targets: RecordedTargets, target: string): boolean {\n return targets.status === 'recorded' && targets.names.includes(target)\n}\n\nexport const runsListSpec: FunctionSpec<RunsListInput, RunSummary[]> = {\n id: RUNS_LIST_FUNCTION_ID,\n summary:\n 'List completed runs, newest finished first (20 by default, at most 200), each naming its '\n + 'tests; filter by verdict, test id or title, recorded target, or completion time.',\n resultKind: 'unary',\n input: RunsListInputSchema,\n // 2026-08-16 (396-04, D-16): the NAMED array schema, not `z.array(RunSummarySchema)` composed\n // here. The two are the same shape; only one of them is an object a surface can also name, and\n // D-16's whole claim is that the advertised schema and the validated schema are one object.\n output: RunsListOutputSchema,\n // 431-03 (D-03, A1): the canonical companion, tied to `output` above. It changes only what a\n // declaration publishes; `output` is still what `invokeFunction` validates with.\n outputRepresentation: RunsListOutputContract,\n // Read ops declare `readOnly` so the static classifier lands them on the read-only\n // tier — allow in every execution context. The verdict is still computed and audited\n // (D-11): there is no read bypass, only a read classification.\n risk: { name: `fn:${RUNS_LIST_FUNCTION_ID}`, recognized: true, readOnly: true },\n /**\n * A listing that answered — the count, and nothing out of a run (399.1 D-01).\n */\n classify(output): ClauseVerdict {\n return { status: 'executed', outcome: `${output.length} completed run(s)` }\n },\n async invoke(input, deps) {\n const limit = input.limit ?? RUNS_LIST_DEFAULT_LIMIT\n const mask = requireSecretMask(deps, RUNS_LIST_FUNCTION_ID)\n const documents = await deps.runs.list()\n const candidates = documents\n .filter((document) => (\n (input.verdict === undefined || document.aggregateVerdict === input.verdict)\n && (input.since === undefined || document.endedAt >= input.since)\n && (input.test === undefined || namesTest(document, input.test, mask))\n ))\n .sort(compareLatestFinished)\n const summarize = (documents: readonly CompletedRunHandoff[]): Promise<RunSummary[]> =>\n Promise.all(documents.map(async (document) => toRunSummary(\n document,\n deps.runs.getRecordedTargets === undefined\n ? { status: 'unknown' }\n : await deps.runs.getRecordedTargets(document.runId),\n mask,\n )))\n\n const { target } = input\n if (target === undefined) return summarize(candidates.slice(0, limit))\n return (await summarize(candidates))\n .filter((row) => recordsTarget(row.recordedTargets, target))\n .slice(0, limit)\n },\n}\n","// 419 GATE3-01: every mark door invokes this spec through the function pipeline (`invokeFunction`;\n// its permission gate is deleted, 432-19).\nimport { RunsMarkInputSchema, RunsMarkOutcomeSchema } from '@vostride/agent-qa-schema'\nimport type { RunsMarkInput, RunsMarkOutcome } from '@vostride/agent-qa-schema'\n\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\n\nexport const RUNS_MARK_FUNCTION_ID = 'runs.mark'\n\nexport const runsMarkSpec: FunctionSpec<RunsMarkInput, RunsMarkOutcome> = {\n id: RUNS_MARK_FUNCTION_ID,\n summary: 'Mark a run or step false-fail / false-pass / confirmed-bug: freeze the marked decision as gold, triage, and apply the fix (a knowledge change or a test edit) in the call.',\n resultKind: 'unary',\n boundThrough: 'feedback',\n input: RunsMarkInputSchema,\n output: RunsMarkOutcomeSchema,\n // D-13: a mark writes the committed eval root and, since 432-09, applies its fix to knowledge or\n // a test file. mutating-local would understate its risk.\n // No requiresHumanOrigin and, since 432-21 (D-12), no bearer: every caller on every door reaches it.\n // 2026-10-01 (432-24, D-12): the `knowledge-write` scope it declared is gone too.\n risk: {\n name: `fn:${RUNS_MARK_FUNCTION_ID}`,\n recognized: true,\n readOnly: false,\n declaredTier: 'mutating-shared',\n },\n classify(output): ClauseVerdict {\n // T-419-10: receipt text contains only governed kinds, never notes or producer strings.\n switch (output.kind) {\n case 'marked':\n return { status: 'executed', outcome: `marked ${output.receipt.kind} · ${output.receipt.disposition.kind}` }\n case 'already-marked':\n return { status: 'executed', outcome: 'already marked: identical repeat, prior receipt returned' }\n case 'run-not-found':\n return { status: 'refused', outcome: 'run not found at the requested address' }\n case 'member-not-found':\n return { status: 'refused', outcome: 'member not found at the requested run address' }\n case 'step-not-found':\n return { status: 'refused', outcome: `step ${output.stepIndex} not found at member ${output.testIndex}` }\n case 'ambiguous-address':\n return { status: 'refused', outcome: 'ambiguous run address: specify a member' }\n case 'ambiguous-correction':\n return { status: 'refused', outcome: 'executable correction requires exactly one recorded decision' }\n default:\n return output satisfies never\n }\n },\n async invoke(input, deps) {\n const feedback = deps.feedback\n if (feedback === undefined) throw new FunctionNotBoundError(RUNS_MARK_FUNCTION_ID)\n return feedback.mark(input)\n },\n}\n","// 2026-09-15, 423 D-16/D-17: what runs.mark would do for this exact input, through the read-only\n// feedbackReads port. The result is prospective: no intent, lease, model call, id mint or write.\nimport { RunsMarkInputSchema, RunsMarkPreviewResultSchema, maskRecordContent } from '@vostride/agent-qa-schema'\nimport type { MaskFn, RunsMarkInput, RunsMarkPreviewResult } from '@vostride/agent-qa-schema'\n\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\nimport { runsMarkSpec } from './runs-mark.js'\nimport { requireSecretMask } from './secret-mask.js'\n\nexport const RUNS_MARK_PREVIEW_FUNCTION_ID = 'runs.mark.preview'\n\n// Only free text crosses the mask. Ids, kinds, counts, addresses and cassette ids stay structural;\n// joined record content and evidence tokens are masked exactly as runs.knowledge masks them.\nfunction maskResult(result: RunsMarkPreviewResult, mask: MaskFn): RunsMarkPreviewResult {\n if (result.kind !== 'consequences') return result\n return {\n ...result,\n knowledge: {\n ...result.knowledge,\n records: result.knowledge.records.map(record => ({\n ...record,\n ...(record.recordContent === undefined ? {} : { recordContent: maskRecordContent(record.recordContent, mask) }),\n evidence: record.evidence.kind === 'unreadable' ? record.evidence : {\n kind: 'effects' as const,\n effects: record.evidence.effects.map(effect => effect.direction === 'confirm' ? effect\n : { ...effect, overturnsEvidenceToken: mask(effect.overturnsEvidenceToken) }),\n },\n })),\n },\n groundTruth: result.groundTruth.map(item => ({\n ...item,\n recordedVerdict: { ...item.recordedVerdict, reasoning: mask(item.recordedVerdict.reasoning) },\n ...(item.correctedExpectation === undefined ? {} : { correctedExpectation: mask(item.correctedExpectation) }),\n })),\n }\n}\n\nexport const runsMarkPreviewSpec: FunctionSpec<RunsMarkInput, RunsMarkPreviewResult> = {\n id: RUNS_MARK_PREVIEW_FUNCTION_ID,\n summary: 'Preview what runs.mark would do for this exact input: its refusals, resolved step, labels, the knowledge records it reaches with their content and evidence effects, and the fix it would apply, without writing.',\n resultKind: 'unary',\n boundThrough: 'feedbackReads',\n input: RunsMarkInputSchema,\n output: RunsMarkPreviewResultSchema,\n risk: { name: `fn:${RUNS_MARK_PREVIEW_FUNCTION_ID}`, recognized: true, readOnly: true },\n classify(output): ClauseVerdict {\n switch (output.kind) {\n case 'consequences':\n return { status: 'executed', outcome: `preview: ${output.markKind} would apply ${output.draft.kind} over ${output.markedDecisionCount} ${output.markedDecisionCount === 1 ? 'decision' : 'decisions'} (nothing written)` }\n case 'quarantined':\n return { status: 'executed', outcome: `preview: ${output.markKind} would be quarantined as ${output.class} (nothing written)` }\n case 'already-marked':\n return { status: 'executed', outcome: 'preview: identical repeat of an existing mark (nothing written)' }\n case 'run-not-found':\n case 'member-not-found':\n case 'step-not-found':\n case 'ambiguous-address':\n case 'ambiguous-correction':\n // The writer's own refusal wording; classify interpolates only structural fields.\n return runsMarkSpec.classify(output)\n default:\n return output satisfies never\n }\n },\n async invoke(input, deps) {\n const parsed = RunsMarkInputSchema.parse(input)\n const preview = deps.feedbackReads?.preview\n if (preview === undefined) throw new FunctionNotBoundError(RUNS_MARK_PREVIEW_FUNCTION_ID)\n const answer = await preview.call(deps.feedbackReads, parsed)\n if (answer.runId !== parsed.runId) throw new Error('feedbackReads.preview answered for another run')\n const mask = requireSecretMask(deps, RUNS_MARK_PREVIEW_FUNCTION_ID)\n return RunsMarkPreviewResultSchema.parse(maskResult(answer, mask))\n },\n}\n","// 2026-09-15, 423 D-19: every mark on a run in ordinal order, with read-time supersession. Pure\n// observation through the feedbackReads port. 2026-09-30, 432-09 (D-04/D-25): each applied knowledge\n// fix carries the records it changed, read now; nothing is read from a proposal store.\nimport {\n RunsMarksHistoryInputSchema, RunsMarksHistoryResultSchema, markAddressKey, maskRecordContent,\n} from '@vostride/agent-qa-schema'\nimport type {\n MarkHistoryChangedRecord, MarkHistoryEntry, MarkReceipt, MaskFn, RunsMarksHistoryInput, RunsMarksHistoryResult,\n} from '@vostride/agent-qa-schema'\n\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionSpec } from '../spec.js'\nimport { requireSecretMask } from './secret-mask.js'\n\nexport const RUNS_MARKS_HISTORY_FUNCTION_ID = 'runs.marks.history'\n\n// Joined record content is masked exactly as runs.knowledge masks it; ids and absences stay structural.\nfunction maskChangedRecord(record: MarkHistoryChangedRecord, mask: MaskFn): MarkHistoryChangedRecord {\n return record.recordContent === undefined ? record\n : { ...record, recordContent: maskRecordContent(record.recordContent, mask) }\n}\n\n// Only free text crosses the mask. Ids, kinds, counts, paths and addresses stay structural.\nfunction projectEntry(receipt: MarkReceipt, changedRecords: readonly MarkHistoryChangedRecord[] | undefined,\n supersededBy: string | undefined, mask: MaskFn): MarkHistoryEntry {\n return {\n markId: receipt.markId,\n runId: receipt.runId,\n testIndex: receipt.testIndex,\n ...(receipt.testId === undefined ? {} : { testId: receipt.testId }),\n ...(receipt.stepIndex === undefined ? {} : { stepIndex: receipt.stepIndex }),\n kind: receipt.kind,\n origin: receipt.origin,\n ordinal: receipt.ordinal,\n markedAt: receipt.markedAt,\n ...(receipt.note === undefined ? {} : { note: mask(receipt.note) }),\n corrected: {\n expectation: receipt.correctedExpectation !== undefined,\n action: receipt.correctedAction !== undefined,\n },\n ...(receipt.rootCause === undefined ? {} : {\n rootCause: { class: receipt.rootCause.class, producer: mask(receipt.rootCause.producer) },\n }),\n ...(receipt.isRerun === undefined ? {} : { isRerun: receipt.isRerun }),\n disposition: receipt.disposition,\n gold: receipt.gold,\n evidence: receipt.evidence,\n ...(receipt.supersedes === undefined ? {} : { supersedes: receipt.supersedes }),\n active: supersededBy === undefined,\n ...(supersededBy === undefined ? {} : { supersededBy }),\n ...(changedRecords === undefined ? {} : { changedRecords: changedRecords.map(record => maskChangedRecord(record, mask)) }),\n }\n}\n\nexport const runsMarksHistorySpec: FunctionSpec<RunsMarksHistoryInput, RunsMarksHistoryResult> = {\n id: RUNS_MARKS_HISTORY_FUNCTION_ID,\n summary: 'Read every mark on a run in ordinal order with supersession and what each applied fix changed.',\n resultKind: 'unary',\n boundThrough: 'feedbackReads',\n input: RunsMarksHistoryInputSchema,\n output: RunsMarksHistoryResultSchema,\n risk: { name: `fn:${RUNS_MARKS_HISTORY_FUNCTION_ID}`, recognized: true, readOnly: true },\n classify(output): ClauseVerdict {\n switch (output.kind) {\n case 'history':\n return { status: 'executed', outcome: `history: ${output.entries.length} ${output.entries.length === 1 ? 'mark' : 'marks'}` }\n case 'run-not-found':\n return { status: 'refused', outcome: 'run not found at the requested address' }\n case 'ledger-corrupt':\n return { status: 'failed', outcome: `mark ledger is corrupt at line ${output.line}` }\n case 'ledger-unavailable':\n return { status: 'failed', outcome: 'mark ledger is unavailable' }\n default:\n return output satisfies never\n }\n },\n async invoke(input, deps) {\n const { runId } = RunsMarksHistoryInputSchema.parse(input)\n const reads = deps.feedbackReads\n if (reads === undefined) throw new FunctionNotBoundError(RUNS_MARKS_HISTORY_FUNCTION_ID)\n const read = await reads.history(runId)\n if (read.kind !== 'history') return RunsMarksHistoryResultSchema.parse({ ...read, runId })\n\n // The ledger's line order is the ordinal order; a permuted or foreign read is corrupt, never re-sorted.\n const receipts = read.entries.map(entry => entry.receipt)\n const misplaced = receipts.findIndex((receipt, index) => receipt.ordinal !== index + 1 || receipt.runId !== runId)\n if (misplaced !== -1) return { kind: 'ledger-corrupt', runId, line: misplaced + 1 }\n\n // Latest-wins per address (419 D-11): a receipt is superseded by the next mark on its address.\n const supersededBy: (string | undefined)[] = []\n const nextOnAddress = new Map<string, string>()\n for (let index = receipts.length - 1; index >= 0; index -= 1) {\n const key = markAddressKey(receipts[index]!)\n supersededBy[index] = nextOnAddress.get(key)\n nextOnAddress.set(key, receipts[index]!.markId)\n }\n\n const mask = requireSecretMask(deps, RUNS_MARKS_HISTORY_FUNCTION_ID)\n return RunsMarksHistoryResultSchema.parse({\n kind: 'history',\n runId,\n entries: read.entries.map((entry, index) => projectEntry(entry.receipt, entry.changedRecords, supersededBy[index], mask)),\n })\n },\n}\n","// `runs.overview` — one completed run's compact address map (Phase 431, D-06).\n//\n// THE COMPLETED HANDOFF IS THE GATE. A run with no completed handoff is refused before any\n// projection row is read, so an in-progress run can never answer with a partial dashboard tree.\n// The handoff also owns the member list; the run-detail rows add what the projection recorded.\n//\n// COMPOSED, NOT RE-DERIVED. Served records, trace arms and the Learned half come from\n// `runs.knowledge` invoked with this call's deps; presence comes from `annotatePresence`, once per\n// overview; counts are the ones the run stored. Nothing is fetched to be counted.\n//\n// BUILT FIELD BY FIELD. Nothing below spreads a producer, knowledge or dashboard value into the\n// result, so a field added upstream cannot reach this contract without being named here.\n\nimport {\n RUN_OVERVIEW_TEXT_MAX_CODE_POINTS,\n RUN_OVERVIEW_TRUNCATION_INDICATOR,\n RunOverviewProjectionSchema,\n RunsOverviewInputSchema,\n} from '@vostride/agent-qa-schema'\nimport type {\n CompletedRunHandoff,\n EvidenceAbsenceReason,\n EvidenceKind,\n MaskFn,\n RecordedTargets,\n RecordingEntry,\n RunDetailMember,\n RunDetailRows,\n RunDetailStep,\n RunDetailSubAction,\n RunKnowledgeProjection,\n RunKnowledgeStep,\n RunOverviewAria,\n RunOverviewEvidenceAddress,\n RunOverviewLearned,\n RunOverviewProjection,\n RunOverviewRecord,\n RunOverviewRecording,\n RunOverviewScreenshot,\n RunOverviewStep,\n RunOverviewStepEvidence,\n RunOverviewText,\n RunsOverviewInput,\n} from '@vostride/agent-qa-schema'\n\nimport { FunctionNotBoundError } from '../spec.js'\nimport type { ClauseVerdict, FunctionDeps, FunctionSpec } from '../spec.js'\nimport { annotatePresence } from './evidence-presence.js'\nimport { refuseMissingHandoff, RunNotFoundError } from './runs-get.js'\nimport { runsKnowledgeSpec } from './runs-knowledge.js'\nimport { projectPostProcessingSkipped } from './runs-post-processing.js'\nimport { requireSecretMask } from './secret-mask.js'\n\nexport const RUNS_OVERVIEW_FUNCTION_ID = 'runs.overview'\n\nconst SCREENSHOT_REF_PREFIX = 'decision-screenshot:'\n\ntype ReadyKnowledge = Extract<RunKnowledgeProjection, { kind: 'ready' }>\ntype Presence = ReadonlyMap<string, boolean>\ntype NonAriaKind = Exclude<EvidenceKind, 'aria'>\ntype StoredEvidence = NonNullable<RunDetailStep['evidence']>\ntype Captured =\n | { state: 'present' }\n | { state: 'absent'; reason: EvidenceAbsenceReason; evidenceIncomplete?: boolean }\n\n/**\n * Mask first, then fold line breaks and cut: either one before masking could change a declared\n * secret so the mask no longer recognises it. Code points, not UTF-16 units, so a cut never lands\n * inside a pair.\n */\nexport function overviewText(raw: string, mask: MaskFn): RunOverviewText {\n const masked = mask(raw).replace(/\\s*[\\r\\n]+\\s*/g, ' ')\n const points = [...masked]\n if (points.length <= RUN_OVERVIEW_TEXT_MAX_CODE_POINTS) return { text: masked }\n return {\n text: points.slice(0, RUN_OVERVIEW_TEXT_MAX_CODE_POINTS).join('')\n + RUN_OVERVIEW_TRUNCATION_INDICATOR,\n truncated: true,\n }\n}\n\nconst withPresence = (presence: Presence, sha: string) => {\n const answer = presence.get(sha)\n return answer === undefined ? {} : { present: answer }\n}\n\nconst withIncomplete = (flag: boolean | undefined) =>\n flag === true ? { evidenceIncomplete: true as const } : {}\n\n/** Every ref a whole overview may report presence for, stat'd once per distinct sha. */\nasync function readPresence(\n deps: FunctionDeps,\n runId: RunsOverviewInput['runId'],\n rows: RunDetailRows | undefined,\n): Promise<Presence> {\n if (rows === undefined) return new Map()\n const refs: { sha: string }[] = []\n for (const member of rows.members) {\n if (member.recording?.state === 'present') refs.push(member.recording.ref)\n }\n for (const step of rows.steps) {\n for (const entry of Object.values(step.evidence ?? {})) {\n if (entry.state === 'present' && 'ref' in entry) refs.push(entry.ref)\n }\n }\n for (const child of rows.subActions) {\n for (const ref of child.artifactRefs ?? []) {\n if (ref.id.startsWith(SCREENSHOT_REF_PREFIX)) refs.push(ref)\n }\n if (child.ariaEvidence?.state === 'present') refs.push(child.ariaEvidence.ref)\n }\n const distinct = [...new Map(refs.map((ref) => [ref.sha, { sha: ref.sha }])).values()]\n const annotated = await annotatePresence(deps.evidenceBlobs, runId, distinct)\n const presence = new Map<string, boolean>()\n for (const ref of annotated) {\n if (ref.present !== undefined) presence.set(ref.sha, ref.present)\n }\n return presence\n}\n\nfunction projectRecording(member: RunDetailMember | undefined, runId: string,\n presence: Presence): RunOverviewRecording {\n const recording: RecordingEntry | undefined = member?.recording\n if (recording === undefined) return { state: 'absent', reason: 'unavailable' }\n if (recording.state === 'absent') {\n return { state: 'absent', reason: recording.reason, ...withIncomplete(recording.evidenceIncomplete) }\n }\n return {\n state: 'present',\n address: { runId, sha: recording.ref.sha },\n contentType: recording.contentType,\n byteLength: recording.byteLength,\n ...(recording.durationMs === undefined ? {} : { durationMs: recording.durationMs }),\n ...withPresence(presence, recording.ref.sha),\n ...withIncomplete(recording.ref.evidenceIncomplete),\n }\n}\n\nfunction projectEvidence(\n stored: StoredEvidence | undefined,\n base: Omit<RunOverviewEvidenceAddress, 'kind' | 'subActionIndex'>,\n presence: Presence,\n): RunOverviewStepEvidence {\n // A historical row with no persisted entries reads `unavailable`, exactly as runs.detail does.\n const absent = <K extends NonAriaKind>(kind: K, entry: Captured | undefined) => {\n const recorded = entry?.state === 'absent' ? entry : undefined\n return {\n kind,\n state: 'absent' as const,\n reason: recorded?.reason ?? 'unavailable',\n ...withIncomplete(recorded?.evidenceIncomplete),\n address: { ...base, kind },\n }\n }\n const consoleEntry = stored?.console\n const network = stored?.network\n const a11y = stored?.a11y\n const variables = stored?.variables\n return {\n console: consoleEntry?.state === 'present'\n ? { kind: 'console', state: 'present', counts: { ...consoleEntry.counts },\n ...withPresence(presence, consoleEntry.ref.sha), address: { ...base, kind: 'console' } }\n : absent('console', consoleEntry),\n network: network?.state === 'present'\n ? { kind: 'network', state: 'present', counts: { ...network.counts },\n ...withPresence(presence, network.ref.sha), address: { ...base, kind: 'network' } }\n : absent('network', network),\n a11y: a11y?.state === 'present'\n ? { kind: 'a11y', state: 'present', counts: { ...a11y.counts },\n ...withPresence(presence, a11y.ref.sha), address: { ...base, kind: 'a11y' } }\n : absent('a11y', a11y),\n variables: variables?.state === 'present'\n ? { kind: 'variables', state: 'present', counts: { count: variables.counts.count },\n address: { ...base, kind: 'variables' } }\n : absent('variables', variables),\n }\n}\n\nfunction projectAria(child: RunDetailSubAction,\n base: Omit<RunOverviewEvidenceAddress, 'kind' | 'subActionIndex'>,\n presence: Presence): RunOverviewAria {\n const address = { ...base, subActionIndex: child.subActionIndex, kind: 'aria' as const }\n const aria = child.ariaEvidence\n if (aria === undefined || aria.state === 'absent') {\n return {\n subActionIndex: child.subActionIndex,\n state: 'absent',\n reason: aria?.reason ?? 'unavailable',\n ...withIncomplete(aria?.evidenceIncomplete),\n address,\n }\n }\n return {\n subActionIndex: child.subActionIndex,\n state: 'present',\n ...withPresence(presence, aria.ref.sha),\n address,\n }\n}\n\nfunction projectScreenshots(children: readonly RunDetailSubAction[], runId: string,\n presence: Presence): RunOverviewScreenshot[] {\n return children.flatMap((child) => (child.artifactRefs ?? [])\n .filter((ref) => ref.id.startsWith(SCREENSHOT_REF_PREFIX))\n .map((ref) => ({\n subActionIndex: child.subActionIndex,\n sha: ref.sha,\n ...withPresence(presence, ref.sha),\n ...withIncomplete(ref.evidenceIncomplete),\n address: { runId, sha: ref.sha },\n })))\n}\n\ntype JoinedLine = { recordContent?: { kind: string; summary: string }\n contentAbsence?: { reason: NonNullable<RunOverviewRecord['unavailable']>['reason'] } }\n\nfunction projectRecord(\n recordId: string,\n channel: RunOverviewRecord['channel'],\n served: { kind?: string; summary?: string },\n joined: JoinedLine,\n mask: MaskFn,\n): RunOverviewRecord {\n const kind = served.kind ?? joined.recordContent?.kind\n const summary = served.summary ?? joined.recordContent?.summary\n const missing = kind === undefined || summary === undefined\n return {\n recordId,\n channel,\n ...(kind === undefined ? {} : { kind }),\n ...(summary === undefined ? {} : { summary: overviewText(summary, mask) }),\n ...(missing ? { unavailable: { reason: joined.contentAbsence?.reason ?? 'not-found' } } : {}),\n }\n}\n\nfunction projectRecords(step: RunKnowledgeStep, mask: MaskFn): RunOverviewRecord[] {\n return [\n ...step.served.channel1.map((line) =>\n projectRecord(line.id, 'brief', { kind: line.kind, summary: line.summary }, line, mask)),\n ...step.served.channel2.map((line) => projectRecord(line.id, 'read', {}, line, mask)),\n ...step.served.channel3.map((line) =>\n projectRecord(line.id, 'caution', { summary: line.summary }, line, mask)),\n ]\n}\n\nfunction projectSteps(\n test: CompletedRunHandoff['tests'][number],\n runId: string,\n rows: RunDetailRows | undefined,\n knowledge: ReadyKnowledge,\n presence: Presence,\n mask: MaskFn,\n): RunOverviewStep[] {\n const detail = new Map<number, RunDetailStep>()\n for (const step of rows?.steps ?? []) {\n if (step.testIndex === test.testIndex) detail.set(step.stepIndex, step)\n }\n const served = new Map<number, RunKnowledgeStep>()\n for (const step of knowledge.steps) {\n if (step.testIndex === test.testIndex) served.set(step.stepIndex, step)\n }\n const recorded = new Map(test.steps.map((step) => [step.stepIndex, step]))\n const indices = [...new Set([...recorded.keys(), ...detail.keys()])].sort((a, b) => a - b)\n return indices.map((stepIndex): RunOverviewStep => {\n const label = recorded.get(stepIndex)?.stepText ?? detail.get(stepIndex)?.stepText\n const row = detail.get(stepIndex)\n const base = { runId, testIndex: test.testIndex, stepIndex }\n const children = (rows?.subActions ?? [])\n .filter((child) => child.testIndex === test.testIndex && child.stepIndex === stepIndex)\n .sort((left, right) => left.subActionIndex - right.subActionIndex)\n const knowledgeStep = served.get(stepIndex)\n return {\n stepIndex,\n ...(label === undefined ? {} : { label: overviewText(label, mask) }),\n ...(row?.status === undefined ? {} : { status: row.status }),\n capture: row === undefined ? { state: 'unavailable' } : {\n state: 'recorded',\n screenshots: projectScreenshots(children, runId, presence),\n evidence: projectEvidence(row.evidence, base, presence),\n aria: children.map((child) => projectAria(child, base, presence)),\n },\n knowledge: knowledgeStep === undefined ? { state: 'unavailable' } : {\n state: 'recorded',\n records: projectRecords(knowledgeStep, mask),\n brief: {\n address: { runId, testId: test.testId, stepIndex },\n trace: knowledgeStep.trace.kind === 'answered'\n ? { kind: 'answered' }\n : { kind: 'no-trace', reason: knowledgeStep.trace.reason },\n },\n },\n }\n })\n}\n\nfunction projectLearned(knowledge: ReadyKnowledge, document: CompletedRunHandoff): RunOverviewLearned {\n const { learned, curation } = knowledge\n const skipped = projectPostProcessingSkipped(document)\n const snapshot: RunOverviewLearned['snapshot'] = learned.curationSnapshot !== undefined\n ? {\n state: 'recorded',\n breakdown: { ...learned.curationSnapshot.breakdown },\n rows: learned.curationSnapshot.rows.map((row) => ({\n recordId: row.recordId,\n bucket: row.bucket,\n ...(row.byRecordId === undefined ? {} : { byRecordId: row.byRecordId }),\n })),\n }\n : learned.curationSnapshotWithheld !== undefined\n ? { state: 'withheld', reason: learned.curationSnapshotWithheld.reason }\n : { state: 'not-recorded' }\n return {\n knowledgeStore: knowledge.knowledgeStore,\n curation: {\n status: curation.status,\n ...(curation.counts === undefined ? {} : { counts: { ...curation.counts } }),\n // 2026-10-18 (444-26, D-61): the run's own handoff says why its chain was never enqueued, by\n // the fold runs.postprocessing serves; an ordinary run carries no key.\n ...(skipped === undefined ? {} : { skipped: { reason: skipped.reason } }),\n },\n snapshot,\n changes: learned.changes.map((change) => ({\n recordId: change.recordId,\n change: change.change,\n atOrdinal: change.atOrdinal,\n })),\n ...(learned.scanIncomplete === true ? { scanIncomplete: true as const } : {}),\n }\n}\n\nexport const runsOverviewSpec: FunctionSpec<RunsOverviewInput, RunOverviewProjection> = {\n id: RUNS_OVERVIEW_FUNCTION_ID,\n summary: 'Map one completed run: its tests and steps with verdicts, and the address of '\n + 'everything recorded at each, without bodies, traces or bytes.',\n resultKind: 'unary',\n boundThrough: 'runDetail',\n input: RunsOverviewInputSchema,\n output: RunOverviewProjectionSchema,\n risk: { name: `fn:${RUNS_OVERVIEW_FUNCTION_ID}`, recognized: true, readOnly: true },\n classify(output): ClauseVerdict {\n const steps = output.tests.reduce((total, test) => total + test.steps.length, 0)\n return {\n status: 'executed',\n outcome: `overview of ${output.runId} — ${String(output.tests.length)} test(s), `\n + `${String(steps)} step(s)`,\n }\n },\n async invoke(input, deps) {\n const port = deps.runDetail\n if (port === undefined) throw new FunctionNotBoundError(RUNS_OVERVIEW_FUNCTION_ID)\n\n const document = await deps.runs.get(input.runId)\n if (document === undefined) return refuseMissingHandoff(input.runId, deps)\n const runId = String(document.runId)\n\n const read = await port.read(input.runId)\n const rows = read?.runId === runId ? read : undefined\n const knowledge = await runsKnowledgeSpec.invoke({ runId: input.runId }, deps)\n // The handoff vanished between the two reads: the same refusal as never having had one.\n if (knowledge.kind !== 'ready') throw new RunNotFoundError(runId)\n const recordedTargets: RecordedTargets = deps.runs.getRecordedTargets === undefined\n ? { status: 'unknown' }\n : await deps.runs.getRecordedTargets(input.runId)\n const presence = await readPresence(deps, input.runId, rows)\n const mask = requireSecretMask(deps, RUNS_OVERVIEW_FUNCTION_ID)\n\n return {\n runId,\n scope: { tier: document.scope.tier, key: document.scope.key },\n recordedTargets: recordedTargets.status === 'recorded'\n ? { status: 'recorded', names: [...recordedTargets.names] }\n : { status: 'unknown' },\n aggregateVerdict: document.aggregateVerdict,\n buildOrdinal: document.buildOrdinal,\n startedAt: document.startedAt,\n endedAt: document.endedAt,\n tests: [...document.tests]\n .sort((left, right) => left.testIndex - right.testIndex)\n .map((test) => ({\n testIndex: test.testIndex,\n testId: test.testId,\n name: overviewText(test.testName, mask),\n outcome: test.outcome,\n recording: projectRecording(\n rows?.members.find((member) => member.testIndex === test.testIndex), runId, presence),\n steps: projectSteps(test, runId, rows, knowledge, presence, mask),\n })),\n learned: projectLearned(knowledge, document),\n }\n },\n}\n","// The function registry (Phase 384, FUNC-01 / FUNC-03).\n//\n// The registry OWNS the specs and hands out declaration views only. Its internals —\n// the spec map and the injected deps — live in a module-private\n// WeakMap that only `invokeFunction` reads. A surface holding a `FunctionRegistry`\n// therefore has exactly one way to run a capability: `invokeFunction`'s validated dispatch.\n// Since 432-13 that path asks nobody (no gate, confirm port, grant reader or deny overlay).\n\nimport type { FunctionCaller } from '@vostride/agent-qa-schema'\n\nimport { toOutputProjection, toSchemaProjection } from './declaration-projection.js'\nimport type { FunctionBindingStatus } from './spec.js'\nimport { agentAskSpec } from './ops/agent-ask.js'\nimport { analysisGetSpec } from './ops/analysis-get.js'\nimport { authoringDraftEditSpec } from './ops/authoring-draft-edit.js'\nimport { authoringDraftWriteSpec } from './ops/authoring-draft-write.js'\nimport { authoringFunnelGetSpec } from './ops/authoring-funnel-get.js'\nimport { authoringVerifyDraftSpec } from './ops/authoring-verify-draft.js'\nimport { configAuthSetSpec } from './ops/config-auth-set.js'\nimport { configFieldSetSpec } from './ops/config-field-set.js'\nimport { configHookAddSpec } from './ops/config-hook-add.js'\nimport { configGetSpec } from './ops/config-get.js'\nimport { configTargetCreateSpec } from './ops/config-target-create.js'\nimport { configProjectScaffoldSpec } from './ops/config-project-scaffold.js'\nimport { configTargetEditSpec } from './ops/config-target-edit.js'\nimport { entitiesGetSpec } from './ops/entities-get.js'\nimport { explainSpec } from './ops/explain.js'\nimport { entitiesResolveSpec } from './ops/entities-resolve.js'\nimport { knowledgeAcceptSpec } from './ops/knowledge-accept-propose.js'\nimport { knowledgeBriefWhySpec } from './ops/knowledge-brief-why.js'\nimport { knowledgeBundlesListSpec } from './ops/knowledge-bundles-list.js'\nimport { knowledgeGatesListSpec } from './ops/knowledge-gates-list.js'\nimport { knowledgeForgetSpec } from './ops/knowledge-forget-propose.js'\nimport { knowledgeRecordShowSpec } from './ops/knowledge-record-show.js'\nimport { knowledgeRecordsDiffSpec } from './ops/knowledge-records-diff.js'\nimport { knowledgeRecordsInspectSpec } from './ops/knowledge-records-inspect.js'\nimport { knowledgeRejectSpec } from './ops/knowledge-reject-propose.js'\nimport { quarantineAddSpec } from './ops/quarantine-add.js'\nimport { quarantineListSpec } from './ops/quarantine-list.js'\nimport { quarantineReleaseSpec } from './ops/quarantine-release.js'\nimport { runsEventsSpec } from './ops/runs-events.js'\nimport { runsLiveUrlSpec } from './ops/runs-live-url.js'\nimport { editorLiveUrlSpec } from './ops/editor-live-url.js'\nimport { runsDigestSpec } from './ops/runs-digest.js'\nimport { runsArtifactSpec } from './ops/runs-artifact.js'\nimport { runsDetailSpec } from './ops/runs-detail.js'\nimport { RUNS_EVIDENCE_FUNCTION_ID, runsEvidenceSpec } from './ops/runs-evidence.js'\nimport { runsGetSpec } from './ops/runs-get.js'\nimport { runsKnowledgeSpec } from './ops/runs-knowledge.js'\nimport { runsListSpec } from './ops/runs-list.js'\nimport { runsMarkSpec } from './ops/runs-mark.js'\nimport { runsMarkPreviewSpec } from './ops/runs-mark-preview.js'\nimport { runsMarksHistorySpec } from './ops/runs-marks-history.js'\nimport { runsOverviewSpec } from './ops/runs-overview.js'\nimport { runsPostProcessingSpec } from './ops/runs-post-processing.js'\nimport { runsStartSpec } from './ops/runs-start.js'\nimport type { FunctionDeclaration, FunctionDeps, FunctionSpec } from './spec.js'\n\n/** Thrown at construction when two declarations claim the same id — never last-wins. */\nexport class DuplicateFunctionIdError extends Error {\n constructor(readonly functionId: string) {\n super(`Duplicate function id: ${functionId}`)\n this.name = 'DuplicateFunctionIdError'\n }\n}\n\n/**\n * Thrown at construction when a spec's output companion is tied to a schema other than the one\n * `invokeFunction` enforces with (431-03, D-03): the declaration would describe one contract while\n * the gate validated another.\n */\nexport class OutputRepresentationMismatchError extends Error {\n constructor(readonly functionId: string) {\n super(\n `${functionId} declares an outputRepresentation whose runtimeSchema is not its output schema; `\n + 'the companion must describe the exact object invokeFunction validates with',\n )\n this.name = 'OutputRepresentationMismatchError'\n }\n}\n\n/** The capabilities every composition of this layer registers. */\nconst BUILT_IN_FUNCTION_SPECS: readonly FunctionSpec[] = [\n runsListSpec as FunctionSpec,\n runsGetSpec as FunctionSpec,\n runsEventsSpec as FunctionSpec,\n // 403 D-03: the ONE producer of live-view capability tokens. Bound through the OPTIONAL\n // `liveView` dep, so a host with no served origin lists it `unbound` BY NAME rather than\n // handing back a URL that resolves to nothing.\n runsLiveUrlSpec as FunctionSpec,\n // 2026-09-25 (428 D-07): the editor subject's minter, through the same `liveView` dep; a host\n // that serves no live editor refuses it by name. Unprojected from MCP by ruling.\n editorLiveUrlSpec as FunctionSpec,\n // Bound exactly in the compositions that supply a `runInvocation` port (D-16); listed\n // either way, so a host that cannot start a run reports a visible `unbound` rather than a\n // hole in the catalog, and `invokeFunction` refuses it by name. `composeLocalAgent()` in\n // `@vostride/agent-qa-agent-local` is the binding site.\n runsStartSpec as FunctionSpec,\n // 388 D-14: THE chip-truth read. Registered here rather than beside a surface because it is\n // the single producer three surfaces share — the CLI's exit summary line, 392's chat and M5's\n // dashboard are all thin clients of this one op, and the 397 parity suite inherits it by\n // being in the catalogue. Bound through the OPTIONAL `postProcessing` dep, so a host with no\n // durable queue lists it `unbound` BY NAME instead of answering all-pending about a chain it\n // cannot see.\n runsPostProcessingSpec as FunctionSpec,\n // 2026-08-27 (405 D-03): THE durable run-detail read — members, steps, sub-actions and the D-06\n // token sum in ONE result. Registered here rather than beside the dashboard because it is the\n // fourth-door law applied to the page that used to read SQLite from inside a route handler: the\n // browser, the CLI, MCP and chat now ask one registry the same question. Bound through the\n // OPTIONAL `runDetail` dep, so a host that owns no dashboard projection database lists it\n // `unbound` BY NAME instead of answering an empty run about a projection it cannot see.\n runsDetailSpec as FunctionSpec,\n // 423 D-04: parsed evidence uses the existing detail and blob readers together.\n runsEvidenceSpec as FunctionSpec,\n // 419 GATE3-01: the sovereign mark write binds only where the host supplies feedback.\n runsMarkSpec as FunctionSpec,\n // 423 D-19: the mark history read binds through feedbackReads, never through the writer above.\n runsMarksHistorySpec as FunctionSpec,\n // 423 D-16: the consequence preview reads runs.mark's shared plan through feedbackReads, never the writer.\n runsMarkPreviewSpec as FunctionSpec,\n // 2026-08-27 (405-05 D-12/D-13): THE ref-resolving read — one run's content-addressed evidence\n // blob, by sha, with the content type sniffed from the bytes themselves. Registered beside\n // `runs.detail` because the two are the halves of one claim: the projection carries an\n // `artifactRef`, and this is how that ref becomes an image on a page. It is here rather than in\n // a route for `runs.detail`'s reason — a route constructing the evidence store would be a\n // private store read no roster row covers, and 408's embed and MCP would each need their own.\n // Bound through the OPTIONAL `evidenceBlobs` dep, so a host with no runtime root lists it\n // `unbound` BY NAME instead of reporting every artifact in the product as absent.\n runsArtifactSpec as FunctionSpec,\n // 389 D-11: THE analysis read — resolved verdicts, rendered sentences, clusters, one\n // producer for the CLI print, the run page and chat. Bound through the OPTIONAL `analysis`\n // dep (the artifact reader), so a host that cannot see run directories lists it `unbound`\n // BY NAME; the optional `recurrence` dep only enriches the sentence's recurrence clause\n // and never gates the binding.\n analysisGetSpec as FunctionSpec,\n knowledgeBundlesListSpec as FunctionSpec,\n // 416 D-17: gate-and-promotion history, through the required knowledge port's\n // optional member; missing bindings answer with a named refusal.\n knowledgeGatesListSpec as FunctionSpec,\n // 387 KREV-01: the read half of the review-verb family. All three bind through the REQUIRED\n // `knowledge` port, so — unlike the mutating half 387-08 registers through the optional\n // `knowledgeReview` dep — there is no composition that lists these and cannot run them.\n knowledgeRecordsInspectSpec as FunctionSpec,\n knowledgeRecordsDiffSpec as FunctionSpec,\n knowledgeRecordShowSpec as FunctionSpec,\n // KREV-02: the honest verb. Read-tier like its four siblings, and bound everywhere for the\n // same reason — its substrate is the RUNS port, which is required.\n knowledgeBriefWhySpec as FunctionSpec,\n // 2026-08-29 (407 D-05/D-06): the Knowledge panel's ONE read — what a run USED (served brief\n // channels, serve-time trace arms, procedure replay/hint, the recorded retrieval rung) and what\n // it LEARNED (curation counts, the record changes attributable to it, canary outcomes). Placed\n // directly after `knowledge.brief.why` because it is that verb widened from one step to a whole\n // run, and BOUND EVERYWHERE for the identical reason: its substrate is the RUNS port, which is\n // required. The three optional deps it consults only enrich the Learned half, so binding\n // through any of them would leave a host with no queue database unable to see what its own runs\n // used. A pruned handoff answers `evidence-incomplete` — a result the page renders, never a\n // refusal it has to catch (D-06).\n runsKnowledgeSpec as FunctionSpec,\n // 431 D-06: one completed run's address map, composed from the handoff, the run-detail rows and\n // the runs.knowledge projection. Bound through `runDetail`, so a host with no projection lists\n // it `unbound` BY NAME instead of mapping a run it cannot see.\n runsOverviewSpec as FunctionSpec,\n // 387 KREV-01 D-17: the MUTATING half. Registered here and bound only where a composition\n // supplies `knowledgeReview`, so a read-only host lists all three as `unbound` BY NAME rather\n // than omitting them: a capability that is absent from a catalogue is indistinguishable from one\n // that never existed, and D-09 requires the two to look different.\n // 2026-09-30, 432-12 (D-05): the three changes apply in the call; the `.propose` ids are gone\n // with no alias. 2026-10-01, 432-17 (D-05/D-22): `knowledge.proposal.apply` is deleted with the\n // inbox; old proposal files are never read again.\n knowledgeAcceptSpec as FunctionSpec,\n knowledgeRejectSpec as FunctionSpec,\n knowledgeForgetSpec as FunctionSpec,\n configGetSpec as FunctionSpec,\n // 395 D-01/D-03 · CFGM-01: the config editor's first action. Registered as a SIBLING of\n // `config.get` rather than in a family of its own, because it is the write half of a story whose\n // read half already ships here — and registering it is what makes it chat-reachable (392 D-07),\n // projectable over MCP (396) and walkable by the parity suite (397) with no harness change.\n //\n // 2026-09-30, 432-11 (D-05/D-07): the config ops write in the call through the direct writer.\n // 2026-10-01, 432-17 (D-05/D-09): `config.proposal.apply` and `config.undo.propose` are deleted\n // with the inbox; a written change is reverted with git.\n //\n // They bind through OPTIONAL deps, so a host with no config files lists them `unbound` BY NAME\n // rather than answering about a project it cannot read.\n configFieldSetSpec as FunctionSpec,\n // 395-05 D-01: the rest of the closed action class, registered as SIBLINGS on exactly the footing\n // above. One op per action is what makes the class legible in the registry itself — the planner\n // picks an action by tool name, 396 projects each one as its own MCP tool, and 397's parity walk\n // enumerates them — where a single union op carrying a mode string would have projected as one\n // tool whose real vocabulary lives inside a field nothing validates.\n configAuthSetSpec as FunctionSpec,\n configHookAddSpec as FunctionSpec,\n configTargetCreateSpec as FunctionSpec,\n configTargetEditSpec as FunctionSpec,\n // 395-08 D-13/D-15 · CFGM-05: the sixth config op, and the only one that configures a project\n // that has no configuration. Registered rather than folded into `config.target.create` because\n // the two refuse each other's case by name — a create is never an upsert, and a scaffold is\n // never an overwrite — and because the planner picks actions by tool name.\n configProjectScaffoldSpec as FunctionSpec,\n // 390 D-12/D-13: a new `quarantine.` domain — a taxonomy extension exactly as `entities.`\n // was, because quarantine state is neither a run, a memory nor an analysis. All three bind\n // through the OPTIONAL `quarantine` dep, so a host with no knowledge root lists them\n // `unbound` BY NAME rather than answering an empty list about a ledger it cannot read.\n // `list` is read-tier; `release` and `add` are DIRECT gated writes (no propose+apply pair —\n // that idiom is for learned-knowledge mutations, and this is operational state).\n quarantineListSpec as FunctionSpec,\n quarantineReleaseSpec as FunctionSpec,\n quarantineAddSpec as FunctionSpec,\n // 391 PROP-03 / D-15 added a `proposals.` domain (list, show, reject, accept). 2026-10-01, 432-17\n // (D-05/D-22): the domain is deleted with the inbox, with no alias and no hidden follow-up; old\n // proposal files are never read again.\n // 391 PROP-01 / D-03 added a `grants.` domain (list, revoke) over the committed standing-grant\n // ledger. 2026-10-01, 432-18 (D-14/D-15/D-22): the domain is deleted with the ledger; an old\n // `grants.jsonl` is never read again.\n // 391 PROP-04 / D-16: the per-run digest. Filed under `runs.` beside `runs.postprocessing`\n // because what it answers is a fact about a RUN. Read-tier, and it registers NO new dep: the\n // projection composes from capabilities this catalogue already had (since 432-09 its substrate\n // is the required runs port, and since 432-17 there is no proposals inbox to read).\n runsDigestSpec as FunctionSpec,\n // 387 D-09: a new `entities.` domain, a taxonomy extension exactly as `knowledge.` was.\n // Both read-tier, both bound in every composition — the directory is a REQUIRED dep, so\n // there is no host that lists these and cannot run them.\n entitiesResolveSpec as FunctionSpec,\n entitiesGetSpec as FunctionSpec,\n // 392 D-24: a new `agent.` domain, and the taxonomy extension that matters most — the chat turn\n // entry is itself a catalogued, gated capability rather than a power the REPL holds privately\n // (§3's L10 law). It binds through the OPTIONAL `chatTurn` dep, so a host with no engine lists\n // it `unbound` BY NAME rather than answering an empty turn about a request it understood.\n //\n // `agent.chat`, the session-stateful sibling the milestone also names, is deliberately absent\n // until a consumer exists: a registered entry nothing drives would still oblige 397's parity\n // suite to stub it on every surface.\n agentAskSpec as FunctionSpec,\n // 2026-08-17 (398 D-09 · XPLN-02): the SECOND member of the `agent.` domain, and the first op\n // this project has added since the 397 conformance suite closed. Registering it is the decision\n // rather than a filing choice: \"what can you do\" is a question every surface wants to answer, and\n // a surface that answered it privately would be a capability the catalogue does not list — the\n // private-power pattern §3's L10 law abolishes and the census exists to make impossible. As a\n // registered op it is chat-reachable through the 1:1 planner binding and `/fn` with no harness\n // change, adjudicated in `mapping.ts` like every op, and walked by the parity suite for free.\n //\n // Bound through the OPTIONAL `capabilityCatalog` port, whose binding site is `composeLocalAgent()`\n // (385 D-15 — therefore both the CLI and the daemon). A host with no catalog lists it `unbound` BY\n // NAME rather than answering from model memory, which is the exact failure XPLN-02 exists to\n // forbid: an explain that quietly lost its grounding data still SOUNDS like an explain.\n explainSpec as FunctionSpec,\n // 2026-08-10 (393 D-01): a new `authoring.` domain, and the keep-filter's entry point. The four\n // gates that decide whether a generated test is worth keeping are a CATALOGUED capability rather\n // than a private power of whatever writes tests — so 393's corpus proof drives the real gated\n // entry point (the produced-not-literal law), 396's MCP projection and 397's parity suite inherit\n // it from this census with no harness change, and the standalone question (\"is this existing test\n // worth keeping?\") is answerable from every surface.\n //\n // Bound through the OPTIONAL `draftEvaluation` bundle, whose binding site is `composeLocalAgent()`\n // in `@vostride/agent-qa-agent-local` (385 D-15 — one composition root, therefore both the CLI and\n // the daemon). The bundle is supplied only where the host can BOTH parse a test file and start a\n // run, so a host missing either half lists this capability `unbound` BY NAME rather than leaving a\n // hole in the catalogue — and rather than returning a receipt whose four booleans were computed\n // from no runs at all, which is the one answer that could get a draft kept on the strength of\n // nothing.\n //\n // Registering it does NOT flip 392's `write_test` fail-closed scenario: that tool name stays\n // absent from the catalogue until 394 (D-01), and nothing here mints it.\n authoringVerifyDraftSpec as FunctionSpec,\n // 2026-08-11 (394 D-01 · WTST-01): the authoring LOOP's one public entry, beside the evaluator\n // it composes. All six stages — brief, dedup, compile, verify, route, compound — run INSIDE this\n // op, because the stage order is an invariant and registering a stage each would make it a hope\n // about the plan the chat planner happened to make rather than a property of the code. Everything\n // under the surface still crosses the function layer: stage 4 dispatches `authoring.draft.verify`\n // through `invokeFunction` on a caller minted with exactly that op's declared scopes.\n //\n // Bound through the OPTIONAL `draftShelf` bundle — the model and the shelf — whose binding site\n // is `composeLocalAgent()` in `@vostride/agent-qa-agent-local` (385 D-15, therefore both the CLI\n // and the daemon). The read half (`authoringRead`) is supplied with it or not at all and the\n // invoke refuses on either by the same name, so a host that cannot serve an authoring brief says\n // `unbound` BY NAME rather than compiling a test against an empty one — a plausible draft\n // authored against nothing this project knows, which is the failure that looks most like success.\n //\n // Inverting the entry above: registering THIS one DOES flip 392's `write_test` fail-closed chat\n // scenarios, because the tool name they were waiting on now exists in the catalogue the planner\n // binds 1:1. Plan 11 performs the flip and pins planned == executed.\n authoringDraftWriteSpec as FunctionSpec,\n // 2026-08-11 (394-07 D-12/D-13 · WTST-05): the honesty funnel's ONE read, beside the loop it\n // measures. It is registered rather than left a private computation for the same reason the two\n // entries above it are: the number that says whether the keep-filter is filtering must be the\n // SAME number in chat, in the CLI and in the per-run digest, and a projection reachable only\n // from whichever surface owned it would become three answers the moment the second surface\n // wanted one. Read-tier and `readOnly` — it starts nothing and writes nothing, which is D-14\n // expressed as a risk descriptor rather than as a promise.\n //\n // Bound through the OPTIONAL `authoringFunnel` bundle, whose binding site is\n // `composeLocalAgent()` in `@vostride/agent-qa-agent-local` (385 D-15 — therefore both the CLI\n // and the daemon). A host with no runtime root lists it `unbound` BY NAME rather than answering\n // an all-zero funnel: zero built with zero write-eligible does not read as \"nothing happened\", it\n // reads as a loop that filtered everything, which is the one wrong answer that would make the\n // acceptance-failure flag unable to fire on the very hosts that most need it.\n authoringFunnelGetSpec as FunctionSpec,\n // 2026-08-11 (394-09 D-21 · WTST-07): the user-facing edit, and the patch contract's SECOND real\n // consumer. Until this op existed, `applyPatchSetToTestDoc` and the RFC-6902 vocabulary had one\n // caller — the repair loop — and a contract with one consumer is a contract shaped like its one\n // caller. That is not a style objection: this project has twice paid for a one-sided contract\n // that looked correct because only one side ever exercised it (the two-sided contract law).\n //\n // It is NOT a stage of `authoring.draft.write`, which is the argument `loop-ordering.test.ts`\n // requires beside a new `authoring.` id. That pin forbids promoting a loop stage to its own\n // registered op, because a planner holding one could reorder or skip the rest. This verb takes an\n // existing COMMITTED test and a change to make to it; it has no position in the six-stage order,\n // and invoking it before, during or after a loop invocation answers the same question.\n //\n // `mutating-local` and NOT the write op's `mutating-shared`: it takes one model call, starts zero\n // runs, and writes only to the gitignored draft shelf. The consent that matters for an edit is\n // the inbox accept that turns the proposal into a commit, which 391 already owns.\n //\n // Bound through the OPTIONAL `draftShelf` bundle; `draftEvaluation` is checked by the same name\n // inside the invoke, because resolving the target's bytes and applying the patch set are two\n // halves of one capability and a host that had only one of them would list this op `bound` and\n // then fail far from whichever half was missing.\n authoringDraftEditSpec as FunctionSpec,\n]\n\nexport interface CreateFunctionRegistryOptions {\n /** Host-backed implementations the ops read through; built at the composition root. */\n deps: FunctionDeps\n // 2026-10-02 (432-39, D-12): no `resolveExecutionContext` member. No op gate has decided in an\n // execution context since 432-13, nothing here read the option, and the fixtures that passed it\n // stopped by 432-39. A host's live context still reaches a run's record and the knowledge review\n // through their own inputs, never through the registry.\n}\n\nexport interface FunctionRegistry {\n /**\n * Declaration views of every registered op, sorted lexicographically by id.\n *\n * 2026-10-01 (432-20, D-12): the same list for every caller. The safe-mode filter that hid ops\n * whose scopes exceeded `read` is deleted with the scopes themselves, so the caller argument is\n * not read. 2026-10-02 (432-39): the caller contract is narrowed to `surface`/`origin`.\n *\n * KEPT, DATED 2026-10-02 (432-42 census decision): the argument stays and stays unread. Removing\n * it changes no behaviour and touches every listing call site in the workspace (well over a\n * hundred, most of them other plans' fixtures), so the churn buys nothing a reader can observe.\n * It is not a permission seam: C432-TOKENLESS-CATALOG and C432-ALL-OPS-AVAILABLE pin that every\n * caller lists the same set, so a filter returning here reds by name.\n */\n list(caller: FunctionCaller): readonly FunctionDeclaration[]\n}\n\ninterface RegistryInternals {\n specs: ReadonlyMap<string, FunctionSpec>\n deps: FunctionDeps\n}\n\nconst REGISTRY_INTERNALS = new WeakMap<FunctionRegistry, RegistryInternals>()\n\n/**\n * INTERNAL seam for `invokeFunction`. Returns `undefined` for any object that did not\n * come out of `createFunctionRegistry` — such an object registers no specs at all, so\n * every id looks unknown to it.\n */\nexport function registryInternals(registry: FunctionRegistry): RegistryInternals | undefined {\n return REGISTRY_INTERNALS.get(registry)\n}\n\n/**\n * Freeze the parts of a spec enforcement reads (CR-04).\n *\n * The specs are module-level singletons, so a write reached through ONE listing used to\n * change what every registry in the process enforced. Freezing is idempotent and happens\n * at registration, which closes the escalation by whatever route a caller reaches the spec.\n *\n * The live `input`/`output` zod objects are deliberately NOT frozen: freezing a schema's\n * internals would break zod's own lazy caching. That is safe now for a structural reason\n * rather than a hopeful one — a declaration carries an inert projection, so no surface is\n * ever handed the schema object in the first place (BL-01). The earlier rationale here,\n * that freezing the spec made those properties unwritable, was a category error: it sealed\n * the property SLOT while the object it pointed at stayed wide open.\n *\n * WR-03: registration FREEZES the spec objects it is given, permanently and in place. Pass\n * a fresh object if the caller needs a mutable one afterwards.\n */\nfunction freezeSpec(spec: FunctionSpec): FunctionSpec {\n Object.freeze(spec.risk)\n return Object.freeze(spec)\n}\n\n/**\n * Whether THIS composition can run the op (D-09/D-16) — the one place the answer is decided.\n *\n * A spec with no `boundThrough` needs only the required deps, which the type system already\n * guarantees, so it is bound wherever it is registered. A spec that names an optional dep is\n * bound iff this composition supplied one. Nothing is read off a static field, because there\n * is none to read: the alternative — a literal on the spec — is a claim a module-level\n * singleton makes about every composition in the process, and it would report `bound` from\n * the first host that omitted the implementation.\n *\n * Exported for `invokeFunction`, which refuses on the SAME answer a listing renders. Two\n * computations of \"is it bound\" would be two chances to disagree, and the disagreement a\n * caller would see is a capability that lists bound and refuses.\n */\nexport function resolveBindingStatus(\n spec: FunctionSpec,\n deps: FunctionDeps,\n): FunctionBindingStatus {\n // Both readers are required even for addresses whose recorded evidence is absent.\n // Keep listing and invocation on this same answer without hiding runs.detail itself.\n if (spec.id === RUNS_EVIDENCE_FUNCTION_ID) {\n return deps.runDetail === undefined || deps.evidenceBlobs === undefined ? 'unbound' : 'bound'\n }\n if (spec.boundThrough === undefined) return 'bound'\n return deps[spec.boundThrough] === undefined ? 'unbound' : 'bound'\n}\n\n/**\n * Project one spec into the capability-free view a surface receives.\n *\n * Constructed field by field rather than spread-minus-invoke, so a future spec field can\n * never leak the implementation into a listing by accident.\n *\n * COPY or PROJECT, then freeze — the view aliases nothing on the spec. The scalars are\n * copied, the two contracts become inert JSON-Schema projections, and the whole graph is\n * frozen. What a caller holds after this is data: there is no live validator on it to\n * replace, so a permitted listing is no longer a write handle onto the contract vocabulary\n * every firewalled surface shares (T-384-14).\n */\nfunction declarationView(spec: FunctionSpec, deps: FunctionDeps): FunctionDeclaration {\n return Object.freeze({\n id: spec.id,\n summary: spec.summary,\n // 2026-10-01 (432-20, D-10/D-12): no `requiredScopes` and no `requiresHumanOrigin`. Both were\n // projected here so a listing and the dispatch checks read one field; the checks are deleted,\n // and 432-39 deleted both members from the metadata type. The view is built field by field, so\n // an old key smuggled onto a spec object still cannot ride through by accident.\n // 2026-10-02 (432-42, D-14): no `discloses` column; the per-op disclosure is deleted.\n // 399.1 D-01/D-04: the two 399.1 folds, projected as conditional spreads so absent stays\n // absent — the callables stay on the spec, and what crosses to a listing is the\n // boolean fact that this op folds its own result. The golden ledger reads both columns off\n // here, so \"which ops classify their own refusals\" is a census over produced facts rather than\n // over somebody's reading of forty-three op files.\n ...(spec.classify === undefined ? {} : { classifies: true as const }),\n ...(spec.renderResult === undefined ? {} : { rendersResult: true as const }),\n resultKind: spec.resultKind,\n bindingStatus: resolveBindingStatus(spec, deps),\n input: toSchemaProjection(spec.input),\n output: toOutputProjection(spec.output, spec.outputRepresentation),\n risk: Object.freeze({ ...spec.risk }),\n })\n}\n\n/**\n * INTERNAL: registry construction over an explicit spec set. Exported for tests and\n * future in-layer compositions, and deliberately absent from the package barrel — a\n * surface that could supply its own specs could mint capabilities the catalog never\n * declared.\n *\n * WR-03: every spec handed here is FROZEN in place, permanently. Pass a fresh object if\n * the caller needs a mutable one afterwards.\n */\nexport function createRegistryFromSpecs(\n specs: readonly FunctionSpec[],\n options: CreateFunctionRegistryOptions,\n): FunctionRegistry {\n const byId = new Map<string, FunctionSpec>()\n for (const spec of specs) {\n if (byId.has(spec.id)) {\n throw new DuplicateFunctionIdError(spec.id)\n }\n if (\n spec.outputRepresentation !== undefined\n && spec.outputRepresentation.runtimeSchema !== spec.output\n ) {\n throw new OutputRepresentationMismatchError(spec.id)\n }\n byId.set(spec.id, freezeSpec(spec))\n }\n\n const sorted = [...byId.values()].sort((left, right) => (\n left.id < right.id ? -1 : left.id > right.id ? 1 : 0\n ))\n\n const registry: FunctionRegistry = {\n list() {\n return sorted.map((spec) => declarationView(spec, options.deps))\n },\n }\n\n REGISTRY_INTERNALS.set(registry, {\n specs: byId,\n deps: options.deps,\n })\n\n return registry\n}\n\n/** Build the registry of built-in capabilities over composition-supplied dependencies. */\nexport function createFunctionRegistry(\n options: CreateFunctionRegistryOptions,\n): FunctionRegistry {\n return createRegistryFromSpecs(BUILT_IN_FUNCTION_SPECS, options)\n}\n","// The result folds, run at the ONE seam that can reach a spec (Phase 399.1, D-01 / D-03 / D-04).\n//\n// WHY THIS FILE IS HERE AND NOT IN `chat/`. The knowledge of which arm of an op's output union is a\n// refusal lives on that op's {@link FunctionSpec}, and a spec never leaves this directory (BL-01 /\n// 384 FUNC-03) — `ChatInvokeBinding` is deliberately a closure over `invokeFunction` rather than a\n// registry handle, so the chat subtree cannot run a fold even if it wanted to. What CAN reach both\n// is the composition root, which holds the registry and mints that closure; this module is what it\n// calls on the return path, so the fold runs in one place instead of once per composition.\n//\n// FAIL-CLOSED, AND ONLY FOR THE VERDICT (D-03). A classifier that throws, or answers something that\n// is not a verdict, yields `failed` with a named outcome and NEVER `executed`. The asymmetry is the\n// whole decision: an unreadable result might be a refusal, so success is the one claim a receipt\n// must not default to — which is exactly what RC-1b's throw-versus-return derivation got backwards.\n// `summariseOutcome`'s safeParse-with-silent-fallback is the right posture for a DISCLOSURE and the\n// wrong one here, because the field being folded is the verdict itself.\n//\n// THE RENDER FOLD FAILS OPEN, AND THAT IS NOT AN INCONSISTENCY. A fold that throws costs the person\n// a sentence of extra legibility; the complete payload is rendered from `results[]` either way\n// (D-04), so nothing is withheld and there is nothing to fail closed ABOUT. Failing the turn over a\n// decorative line would be the disclosure destroying the record, which is the trade 392's receipt\n// charter already refused.\n\nimport { registryInternals } from './registry.js'\nimport type { FunctionRegistry } from './registry.js'\nimport type { ClauseVerdict } from './spec.js'\n\n/**\n * The verdict a result nobody could read reports.\n *\n * NAMED, so the receipt says which of the two failures happened. A thrown op error already reaches\n * the engine's own `failed` mapping carrying the function layer's refusal name; this outcome means\n * the op RETURNED and its own declared fold could not say what the return meant — a different fact,\n * and one that points at the op's classifier rather than at the op.\n */\nconst UNCLASSIFIABLE: ClauseVerdict = Object.freeze({\n status: 'failed',\n outcome: 'unclassifiable-result',\n})\n\n/** What a fold produced for one result: the verdict, and any extra human lines. */\nexport interface FunctionResultFold {\n readonly verdict: ClauseVerdict\n readonly foldLines: readonly string[]\n}\n\n/**\n * Whether a value is the verdict a classifier is contracted to return.\n *\n * CHECKED RATHER THAN CAST, because a classifier is ordinary op-authored code and a cast here would\n * put an arbitrary object on the receipt — including one whose `status` is a word no surface knows\n * how to render, which would land in a persisted session log and in the goldens. The status set is\n * spelled from the two members a classifier may return; `not-run` is deliberately unreachable from\n * here (see {@link ClauseVerdict}).\n */\nfunction isClauseVerdict(value: unknown): value is ClauseVerdict {\n if (typeof value !== 'object' || value === null) return false\n const candidate = value as { status?: unknown; outcome?: unknown }\n if (typeof candidate.outcome !== 'string') return false\n return candidate.status === 'executed' || candidate.status === 'refused'\n || candidate.status === 'failed'\n}\n\n/** Whether a value is the line list a render fold is contracted to return. */\nfunction isLineList(value: unknown): value is readonly string[] {\n return Array.isArray(value) && value.every((line) => typeof line === 'string')\n}\n\n/**\n * Fold one op's result into the verdict and the extra lines its spec declares.\n *\n * PURE FROM THE CALLER'S SIDE and side-effect-free by contract: both folds are declared pure on the\n * spec, this runs them and nothing else, and it is reached only AFTER the gate has run, the op has\n * run and the audit row is written. It reports; it decides nothing.\n *\n * THE REGISTRY IS AN ARGUMENT rather than a captured handle, so the composition root passes the\n * same registry it dispatched through and the two can never be different objects.\n */\nexport function foldFunctionResult(\n registry: FunctionRegistry,\n functionId: string,\n payload: unknown,\n): FunctionResultFold {\n const spec = registryInternals(registry)?.specs.get(functionId)\n if (spec === undefined) {\n // The op dispatched a moment ago through this same registry, so this is unreachable in a\n // composed host — and it is answered fail-closed rather than optimistically anyway, because the\n // one thing this function must never do is report a success it cannot substantiate.\n return { verdict: UNCLASSIFIABLE, foldLines: [] }\n }\n return { verdict: verdictOf(spec, payload), foldLines: linesOf(spec, payload) }\n}\n\nfunction verdictOf(\n spec: { classify?: (output: never) => unknown },\n payload: unknown,\n): ClauseVerdict {\n // AN ABSENT CLASSIFIER IS FAIL-CLOSED AS OF 399.1-04, AND THE FLIP IS THE WHOLE POINT OF THE\n // PLAN THAT MADE IT. This answered the legacy `{ status: 'executed', outcome: '' }` for one plan,\n // while `FunctionSpec.classify` was optional and an op with no fold was an ordinary, expected,\n // COUNTABLE thing. The member is required now, so an absent one no longer means \"this op has not\n // got round to it\" — it means a cast got past `tsc` AND past the conformance census, and the one\n // claim a receipt must never default to is success (D-03).\n //\n // THE PARAMETER STAYS OPTIONAL ON PURPOSE. Narrowing it to a required member would delete this\n // branch and make the guard unwritable, which is the type system certifying its own coverage:\n // `foldFunctionResult` is exported, the registry stores specs behind an internals seam, and\n // `registry.ts` itself registers a stream spec through an `as`-cast. The branch is reachable in\n // exactly the situation it exists for, and `refusal-classifiers.test.ts` drives it.\n if (typeof spec.classify !== 'function') return UNCLASSIFIABLE\n try {\n const answered: unknown = spec.classify(payload as never)\n return isClauseVerdict(answered) ? answered : UNCLASSIFIABLE\n } catch {\n return UNCLASSIFIABLE\n }\n}\n\nfunction linesOf(\n spec: { renderResult?: (output: never) => unknown },\n payload: unknown,\n): readonly string[] {\n if (spec.renderResult === undefined) return []\n try {\n const rendered: unknown = spec.renderResult(payload as never)\n return isLineList(rendered) ? [...rendered] : []\n } catch {\n return []\n }\n}\n","// `invokeFunction` — the single dispatch path every surface crosses (Phase 384, FUNC-01).\n//\n// 2026-09-30 (432-13, D-01/D-14/D-15): THERE IS NO OP GATE. The surface-capability `evaluate()`\n// call that used to sit here — the ask ladder, its confirm port, the standing-approval reader and the\n// chat session's deny overlay — is gone, and so is its `EVALUATE_PIN` entry. An op a caller may\n// invoke runs once, in every execution context, and no execution-audit row is written for it.\n//\n// What stays is everything that is not an approval: the unknown-id refusal, input validation, the\n// binding check, dispatch, and output validation for unary results.\n//\n// 2026-10-01 (432-20, D-10/D-12): THERE ARE NO PERMISSIONS EITHER. The scope subset check, the\n// human-origin check and their two refusal classes are deleted, and so is the registry's safe-mode\n// listing filter: every door can call every operation. The caller record is not read here at all.\n// Its `surface` and `origin` survive only for the receipts and presentation that already consume\n// them; a branch on either in this path would re-create the per-door powers this layer abolished.\n\nimport type { FunctionCaller } from '@vostride/agent-qa-schema'\n\nimport { registryInternals, resolveBindingStatus } from './registry.js'\nimport type { FunctionRegistry } from './registry.js'\nimport { FunctionNotBoundError } from './spec.js'\n\n// Declared next to `FunctionBindingStatus` (see spec.ts) and surfaced here so every\n// caller-facing refusal this pipeline can raise is importable as one set.\nexport { FunctionNotBoundError }\n\n/** No capability with this id is registered. Thrown before any dependency is touched. */\nexport class UnknownFunctionError extends Error {\n constructor(readonly functionId: string) {\n super(`Unknown function: ${functionId}`)\n this.name = 'UnknownFunctionError'\n }\n}\n\n/** The supplied input failed the op's declared input contract (D-14). */\nexport class FunctionInputError extends Error {\n constructor(\n readonly functionId: string,\n readonly issues: string,\n ) {\n super(`Invalid input for ${functionId}: ${issues}`)\n this.name = 'FunctionInputError'\n }\n}\n\n// 2026-10-01 (432-20, D-12): `FunctionScopeError` and `FunctionOriginError` are deleted with the\n// scope and human-origin checks that raised them. Nothing refuses a caller for who it is.\n\n// 2026-10-01 (432-19, D-15): `FunctionDeniedError` is deleted. It was the execution gate's\n// refusal, carrying the gate's reason and remedies; no gate raises it since 432-13, and the doors\n// that reconstructed or rendered it no longer look for it.\n\nfunction issueSummary(issues: readonly { path: PropertyKey[]; message: string }[]): string {\n return issues\n .map((issue) => {\n const path = issue.path.map(String).join('.')\n return path.length === 0 ? issue.message : `${path}: ${issue.message}`\n })\n .join('; ')\n}\n\n/**\n * Run one registered capability on behalf of one caller.\n *\n * Order is load-bearing and asserted by tests:\n * 1. resolve the spec — unknown id fails before any dependency is touched\n * 2. validate the input — malformed input never reaches an implementation\n * 3. binding check — a declared-but-unbound op refuses by name\n * 4. dispatch — the only place a spec implementation ever runs\n * 5. validate the output — unary results honour their declared contract\n *\n * Stream ops (D-08) run through the SAME steps. Nothing between the refusals and dispatch asks\n * anybody anything (432-13), and nothing reads who is calling (432-20): `caller` is accepted so\n * every door keeps one call shape, and the record it carries is presentation data only.\n */\nexport async function invokeFunction(\n registry: FunctionRegistry,\n functionId: string,\n input: unknown,\n _caller: FunctionCaller,\n): Promise<unknown> {\n const internals = registryInternals(registry)\n const spec = internals?.specs.get(functionId)\n if (internals === undefined || spec === undefined) {\n throw new UnknownFunctionError(functionId)\n }\n\n const parsed = spec.input.safeParse(input)\n if (!parsed.success) {\n throw new FunctionInputError(functionId, issueSummary(parsed.error.issues))\n }\n\n // The DECLARATION is authoritative — an op this composition reports as `unbound` never\n // dispatches, whatever its implementation happens to do — and it is the SAME\n // `resolveBindingStatus` a listing renders, so what a caller was shown and what dispatch\n // enforces cannot disagree (D-16).\n if (resolveBindingStatus(spec, internals.deps) === 'unbound') {\n throw new FunctionNotBoundError(functionId)\n }\n\n const result = await spec.invoke(parsed.data, internals.deps)\n\n // A stream result IS the declared async iterable and passes through untouched: the\n // spec's `output` describes one ELEMENT, so parsing the iterable against it would be a\n // category error. Elements carry their own resume token.\n return spec.resultKind === 'unary' ? spec.output.parse(result) : result\n}\n","// Where a write_test request goes when the project has no target for it (395-08, D-14/D-15 ·\n// CFGM-05).\n//\n// THIS IS THE SEAM, AND FINDING IT WAS THE FIRST THING THIS PLAN HAD TO DO. The plan's design note\n// says \"where the chat turn resolves a write_test request's target against configuredTargetNames\".\n// No such place exists. `AuthoringDraftWriteInputSchema` carries `intent` (free text) and an\n// optional `scope`; the TARGET is decided inside the authoring loop, by a model, from a draft it\n// compiled — `loop.ts:583` reads the vocabulary and `loop.ts:647` checks the emitted name against\n// it, both AFTER an LLM call. So the pre-dispatch question cannot be \"does the request's target\n// match\" (there is no target on the request). It is: given this project's configured vocabulary and\n// the words the person actually typed, is there anything to author against at all?\n//\n// THE AUTHORING LOOP'S OWN BACKSTOP IS UNTOUCHED, WHICH IS RESEARCH PITFALL 6. This resolver runs\n// BEFORE dispatch and answers about the REQUEST; `AuthoringDraftUnconfiguredTargetError` runs after\n// compilation and answers about what the MODEL emitted. They guard different failures — a project\n// with nothing to write for, and a model that named a target this project does not declare — and\n// collapsing either into the other would leave one of them unguarded.\n//\n// THE PASSTHROUGH ARM IS THE COMMON CASE AND IT IS DELIBERATELY WIDE. \"Write a test for the login\n// flow\" in a configured project names no target and no hostname, and it must reach authoring\n// exactly as it does today: `deriveDefaultAuthoringScope` resolves the scope from the project's own\n// targets and committed tests, and the loop's backstop catches an emission that goes wrong. A\n// resolver that refused every intent it could not attribute would break the shipped path for the\n// majority of real requests, in the name of a from-zero case none of them are.\n//\n// THE REFUSAL ARM IS THEREFORE NARROW, AND ITS PRECONDITION IS THE PROJECT RATHER THAN THE WORDING:\n// a project that declares NO targets, and an utterance carrying no hostname. That is exactly D-15's\n// sentence — \"anything else with no configured-target match gets a typed refusal asking for a URL or\n// target name\" — read where it is actually true.\n//\n// THE SCAFFOLD ARM CARRIES THE SAME PRECONDITION SINCE 395-12 (WR-05). Scaffolding is the FROM-ZERO\n// path; a project that already declares targets authors against them. Offering the scaffold there\n// traded a working dispatch for a refusal about a site nobody named — a token like `readme.md` or\n// `index.html` parses as a hostname, and in a configured project that turn used to end in\n// `already-configured` for `readme-md`. The precondition is the project, in both arms.\n//\n// THE ARM TABLE, IN ORDER, BECAUSE THE ORDER IS THE CONTRACT:\n//\n// 1. a token that IS a configured target name -> configured\n// 2. a hostname token whose DERIVED name is configured -> configured\n// 3. a hostname token in a project that declares targets -> passthrough (WR-05, 395-12)\n// 4. a hostname token in a project that declares none -> scaffold\n// 5. no hostname, and the project declares targets -> passthrough\n// 6. no hostname, and the project declares none -> refuse\n//\n// TOKENS, NOT SUBSTRINGS. A configured target named `shop` must not match the word `workshop`, and\n// a hostname must be a whole word rather than a fragment of one. The split is on characters that\n// cannot appear in a hostname or in a target name, so the tokens this sees are the words a person\n// typed.\n\nimport { parseHostnameToken } from './hostname-gate.js'\n\n/**\n * A word: either a bracketed IPv6 origin (432 D-20), whose brackets must survive, or a run of what\n * a hostname and a registry key CAN hold. Everything else separates words.\n */\nconst TOKEN = /(?:[A-Za-z][A-Za-z0-9+.-]*:\\/\\/)?\\[[0-9A-Fa-f:.]+\\][A-Za-z0-9.:/?=&@_-]*|[A-Za-z0-9.:/?=&@_-]+/g\n\nexport type WriteTestRoute =\n | {\n /** A configured target is named in the utterance. Dispatch authoring, unchanged. */\n readonly kind: 'configured'\n readonly name: string\n }\n | {\n /** Nothing to decide here. The authoring loop derives its own scope, as it always has. */\n readonly kind: 'passthrough'\n }\n | {\n /** A hostname this project does not configure. Scaffold it, then author (D-14). */\n readonly kind: 'scaffold'\n readonly domain: string\n readonly targetName: string\n }\n | {\n /** No targets, no hostname. Ask; never guess (D-15). */\n readonly kind: 'refuse'\n }\n\n/**\n * Route one write_test request, deterministically.\n *\n * ORDER IS THE CONTRACT. A configured name wins over a hostname, because a project that already\n * declares `booking-com` and is asked about `booking.com` wants the target it has — and scaffolding\n * would refuse `already-configured` one layer down anyway, which is a worse sentence for a request\n * that had a perfectly good answer.\n */\nexport function resolveWriteTestRoute(input: {\n readonly intent: string\n readonly configuredTargetNames: readonly string[]\n}): WriteTestRoute {\n const tokens = input.intent.match(TOKEN) ?? []\n const configured = new Set(input.configuredTargetNames)\n\n for (const token of tokens) {\n if (configured.has(token)) return { kind: 'configured', name: token }\n }\n\n for (const token of tokens) {\n const verdict = parseHostnameToken(token)\n if (verdict.kind !== 'hostname') continue\n // A hostname whose DERIVED name this project already declares is that target, spelled as a\n // domain. Answering `scaffold` here would send a person to a refusal for a target they have.\n if (configured.has(verdict.targetName)) {\n return { kind: 'configured', name: verdict.targetName }\n }\n // WR-05 (395-12). A project that declares targets authors against them; `readme.md` and\n // `index.html` both parse as hostnames, and offering a scaffold for one of them is how a turn\n // that had a perfectly good authoring dispatch ended in `already-configured` for a site nobody\n // named. The scaffold arm is the from-zero path and this is where it says so.\n if (configured.size > 0) return { kind: 'passthrough' }\n // The scaffold op re-parses what it is handed, so a kept scheme or port travels as the base URL\n // (432 D-20). A plain derivation still travels as the bare domain it always did.\n const domain = verdict.baseUrl === `https://${verdict.domain}` ? verdict.domain : verdict.baseUrl\n return { kind: 'scaffold', domain, targetName: verdict.targetName }\n }\n\n // A project with targets can author against them without being told which; a project with none\n // has nothing at all, and that is the one case where silence is unanswerable.\n return configured.size > 0 ? { kind: 'passthrough' } : { kind: 'refuse' }\n}\n\n/**\n * The refusal a write_test request against an unconfigurable project earns (D-15, 387's posture).\n *\n * 2026-10-03 (quick 261003-cpv, 432 review WR-02): it no longer promises a review. The scaffold\n * writes the configuration in its own call and the test is authored after it (D-05/D-14/D-24).\n */\nexport const WRITE_TEST_UNCONFIGURED_DETAIL\n = 'this project has no agent-qa configuration, so there is no target to write a test against. '\n + 'Name the site\\'s address (for example \"write a test for example.com\") and I will write the '\n + 'configuration for it, then author the test. I will not guess which site you meant.'\n\n/**\n * Why a scaffold the write_test route asked for left nothing to author against, in its own words\n * (261003-cpv, 432 review WR-03). A refused or interrupted answer carries its own `detail`; a\n * blocked one carries its summary line and reason; a no-change one wrote nothing because the\n * configuration already held it. The no-configuration sentence is never the answer here: the\n * person named the site, and the scaffold said why it wrote nothing.\n */\nexport function writeTestScaffoldStopDetail(answer: {\n readonly outcome?: string\n readonly detail?: string\n readonly summaryLine?: string\n readonly blockedReason?: string\n readonly validationIssues?: readonly string[]\n readonly path?: string\n}): string {\n if (answer.detail !== undefined && answer.detail !== '') return answer.detail\n const attempted = answer.summaryLine === undefined ? '' : ` (${answer.summaryLine})`\n if (answer.outcome === 'blocked') {\n const issues = answer.validationIssues === undefined || answer.validationIssues.length === 0\n ? ''\n : ` Validation said: ${answer.validationIssues.join('; ')}.`\n return 'the configuration was not written because the result would not be valid'\n + `${attempted}, so there is no target to write a test against.${issues}`\n }\n if (answer.outcome === 'no-change') {\n return 'the configuration already holds what scaffolding would write'\n + `${answer.path === undefined ? '' : ` (${answer.path})`}, so nothing was written, and it `\n + 'declares no target to write a test against.'\n }\n return 'the configuration change answered without naming a file it wrote'\n + `${attempted}, so there is no target to write a test against.`\n}\n","// D-04 / CHAT-05 — configuration changes are EVENTS, not silent state (Phase 392, plan 07).\n//\n// TWO PURE FUNCTIONS AND NO I/O. One folds what a session last RECORDED about its configuration out\n// of the log it already has; the other diffs that against what the host re-read, and answers in\n// events. Neither reads a file, resolves a profile or walks a registry — the current state arrives\n// as data from the composition root, which is the only place that knows how this host resolves a\n// model and enumerates a toolset. A drift module that re-read the configuration itself would be a\n// second resolution path, free to disagree with the one the turn actually runs under.\n//\n// WHY DRIFT IS AN EVENT AND NOT A HEADER REWRITE. The log is append-only by contract (CHAT-05), so\n// the opening context stays on the header forever and everything after it is a delta a reader folds\n// forward. That is what makes \"what was in force at turn N\" answerable at all; rewriting the header\n// would give the file one truth — the latest — and destroy every earlier one.\n//\n// THE UNKNOWN-PREVIOUS-IDS ARM IS AN HONEST GAP, STATED. A header carries the toolset HASH and not\n// the ids behind it, so a session reopened after a build change can prove the reachable set moved\n// and cannot name what moved. Both facts are kept: the event fires, because the hash is the drift,\n// and its deltas are EMPTY, because nothing in the record knows them. Filling them with the current\n// set would put a fabricated delta into an append-only file, which is worse than an unnamed one —\n// a reader can act on \"changed, contents unknown\" and cannot act on a delta that is wrong.\n\nimport type {\n ChatActiveToolsChangeEvent,\n ChatModelChangeEvent,\n ChatSessionEvent,\n ChatSessionHeader,\n} from '@vostride/agent-qa-schema'\n\n/**\n * What the toolset was, as the record can express it.\n *\n * The hash is the identity and it is REQUIRED; the ids are the explanation and they are optional.\n * The asymmetry mirrors the log's own: a hash survives on the header line, and an id list does not.\n */\nexport interface ChatToolsetFingerprint {\n readonly hash: string\n /** Present only when the caller genuinely observed the set — never reconstructed by guessing. */\n readonly ids?: readonly string[]\n}\n\n/** The configuration facts a chat session is sensitive to (D-04). */\nexport interface ChatConfigState {\n readonly model: string\n readonly toolset: ChatToolsetFingerprint\n}\n\n/**\n * Which turn a drift belongs to, when it happened, and WHY the model moved.\n *\n * `source` distinguishes the two ways a model changes and they are genuinely different facts: a\n * person typed `/model`, or the configuration on disk drifted and the session re-read it (391's\n * human-edits-always-win echo). Collapsing them would leave a reader unable to tell a deliberate\n * switch from one that happened to them. The `verb` arm is what plan 08's directive handler stamps;\n * both arms produce the SAME event through this one function rather than through two emitters.\n */\nexport interface ChatConfigDriftStamp {\n readonly turnId: string\n readonly at: string\n readonly source: ChatModelChangeEvent['source']\n}\n\nexport type ChatConfigDriftEvent = ChatModelChangeEvent | ChatActiveToolsChangeEvent\n\n/** Sorted set difference — the ids in `after` that `before` did not have. */\nfunction added(before: readonly string[], after: readonly string[]): string[] {\n const known = new Set(before)\n return after.filter((id) => !known.has(id)).sort()\n}\n\n/**\n * Diff two configuration states into the events the session log carries (D-04).\n *\n * MODEL FIRST when both drifted, because a reader folding the log rebuilds \"what was in force\" in\n * that order and because the model is the fact a person is far more likely to be looking for. The\n * order is fixed rather than incidental: it is bytes in an append-only file that several surfaces\n * render, and two builds emitting them in different orders would make the file's shape depend on\n * which one wrote it.\n */\nexport function diffChatConfig(\n previous: ChatConfigState,\n current: ChatConfigState,\n stamp: ChatConfigDriftStamp,\n): readonly ChatConfigDriftEvent[] {\n const events: ChatConfigDriftEvent[] = []\n\n if (previous.model !== current.model) {\n events.push({\n kind: 'model_change',\n turnId: stamp.turnId,\n at: stamp.at,\n from: previous.model,\n to: current.model,\n source: stamp.source,\n })\n }\n\n if (previous.toolset.hash !== current.toolset.hash) {\n // The hash is the trigger, and the ids only ever explain it. A comparison keyed on the id\n // ARRAYS would fire on a reordered registry walk — a difference in nothing but iteration order.\n const before = previous.toolset.ids\n const after = current.toolset.ids\n const knowable = before !== undefined && after !== undefined\n events.push({\n kind: 'active_tools_change',\n turnId: stamp.turnId,\n at: stamp.at,\n addedIds: knowable ? added(before, after) : [],\n removedIds: knowable ? added(after, before) : [],\n toolsetHash: current.toolset.hash,\n })\n }\n\n return events\n}\n\n/**\n * Rebuild what the session last recorded, by folding drift events over the header.\n *\n * THE HEADER IS THE BASE AND THE EVENTS ARE THE DELTAS, walked in file order so the LAST one wins.\n * That is the only reading consistent with an append-only log: an earlier `model_change` is not\n * wrong, it is history, and a fold that took the first would answer with the model a session opened\n * three days ago rather than the one its last turn ran under.\n *\n * `toolset.ids` is deliberately never populated here. Nothing in the record carries the set, and the\n * one thing this function must not do is invent one — see the file header.\n */\nexport function foldChatConfigState(\n header: ChatSessionHeader,\n events: readonly ChatSessionEvent[],\n): ChatConfigState {\n let model = header.model\n let hash = header.toolsetHash\n\n for (const event of events) {\n if (event.kind === 'model_change') model = event.to\n else if (event.kind === 'active_tools_change') hash = event.toolsetHash\n }\n\n return { model, toolset: { hash } }\n}\n","// CHAT-04 — chat's compaction TRIGGER POLICY, and nothing else (Phase 392, plan 06, D-20).\n//\n// THIS MODULE IS THREE LINES OF POLICY OVER SHIPPED MECHANISM. The v49 accounting substrate\n// already performs every stage CHAT-04 names: the SDK prune plus the tool-result clearing lane\n// (screenshot stripping, hash-dedup of identical historical results), exchange-atomic eviction of\n// the oldest unpinned tool exchange, and the proportional hard-truncate with its marker — all\n// under one budget, returning one discriminated outcome, never throwing and never violating a pin.\n// What chat owns is WHEN to ask for that pass, WHAT budget to ask under, WHAT extra content to\n// protect, and WHAT to write in the log afterwards. Re-deriving any of the mechanics here would\n// give the repo a second degrade pipeline whose divergence from the first nobody would notice\n// until a conversation came back wrong.\n//\n// ALL SIZE MEASUREMENT CROSSES `accounting.estimate` (edge: CHAT-04/encoding). There is no\n// character count, no byte count and no chars-per-token constant anywhere below, and a test reads\n// this file to keep it that way. The reason is not tidiness: the trigger compares an estimate\n// against a budget, and a second estimator would let the number that decides whether to compact\n// disagree with the number the budget is denominated in — so a conversation could sit permanently\n// just over one measure and just under the other.\n//\n// THE ACCOUNTING INSTANCE ARRIVES AS DATA, on the `AuthorTokenBudget` precedent\n// (`jobs/analyze-run-author.ts:76-79`). `packages/agent` is providerNeutral and storageNeutral and\n// does not depend on `packages/model`; what it declares instead is the SHAPE it needs, which a\n// real `TokenAccounting` satisfies structurally. A host binds the shipped instance; this file\n// cannot construct one, cannot reach a provider, and cannot re-resolve capabilities.\n//\n// ONE EVENT PER PASS, whichever stages fired. The stages of a degrade are FIELDS of one operation\n// (392-01's assumption-delta decision, restated in `session-events.ts:205-215`): they run together\n// under one budget for one turn, so \"what did compaction cost on this turn\" is one row rather than\n// a join. A pass that triggers ALWAYS emits — including the arm where it frees nothing — because a\n// silent pass and no pass are the same bytes for the reader who has to explain a slow turn.\n\nimport type { ModelMessage } from 'ai'\n\nimport type { ChatCompactionEvent } from '@vostride/agent-qa-schema'\n\nimport type { CompactionHook } from './ports.js'\nimport type { SessionReplay } from './session-repair.js'\n\n/**\n * The fraction of the context window at which chat asks for a degrade pass.\n *\n * PINNED, NOT CONFIG (386 D-15, 392 D-20). Spec §4.1 words this as a \"configurable fraction,\n * per-model overridable\"; that reading is deliberately narrowed here, and the narrowing is on the\n * record as a dated reconciliation note under CHAT-04 in `.planning/REQUIREMENTS.md` so an audit\n * does not score the spec-literal phrasing as a gap. Adding a knob later is additive; removing a\n * shipped knob is breaking, and a knob shipped before anybody knows what value to put in it is a\n * question asked of every user in place of an answer given by the tool.\n *\n * Owner: the chat orchestration surface (`packages/agent/src/chat`).\n * Retune trigger: a real session, on a named model, in which 0.5 is demonstrably wrong — a\n * conversation that overflows before this fires, or one degraded so early that answers lose\n * context nobody needed to lose. Per-model behaviour is derived from `getCeilings()` (which\n * composes `resolveCapabilities`) FIRST; a config field is the last resort, not the first.\n */\nexport const COMPACTION_RATIO = 0.5\n\n/**\n * The smallest budget chat will ever ask a conversation to fit under, in tokens.\n *\n * PINNED, NOT CONFIG (386 D-15). This exists for the pathological ceiling, not the ordinary one:\n * on any real chat model half the window is far larger than this, so the floor never binds. It\n * binds when a capability lookup reports a tiny or bogus window, and what it does there is make\n * compaction GIVE UP rather than shred — a budget of a few hundred tokens would evict and truncate\n * a conversation down to a stub that answers nothing, which is a worse outcome than carrying the\n * tokens forward into the overflow handling the model layer already owns. A triggered pass under a\n * binding floor still runs the near-lossless hygiene stage and still reports honestly that it\n * freed little or nothing.\n *\n * Owner: the chat orchestration surface (`packages/agent/src/chat`).\n * Retune trigger: a real session on a small-window model where this floor is observably the reason\n * a conversation degraded badly — raise it if useful context is being cut, lower it only if a\n * genuinely small-window model is overflowing because the floor kept compaction from acting.\n */\nexport const CHAT_MINIMUM_CONTEXT = 8192\n\n/**\n * The substrate's discriminated result, restated as the shape this module consumes.\n *\n * Structurally identical to `DegradeOutcome` in `packages/model/src/accounting/types.ts` so a real\n * instance satisfies it without a cast. Restated rather than imported because `agent` does not\n * depend on `model` and must not start to: the accounting instance is DATA a host supplies, and a\n * package edge added for a type would be an edge a later import could travel.\n */\nexport type ChatDegradeOutcome =\n | { ok: true; messages: ModelMessage[] }\n | { ok: false; reason: 'pinned-content-exceeds-budget'; messages: ModelMessage[] }\n\n/** The caller-supplied degrade controls, as the substrate declares them. */\nexport interface ChatDegradeOptions {\n budget: number\n pin?: (message: ModelMessage, index: number) => boolean\n estimate?: (messages: ModelMessage[]) => number\n}\n\n/**\n * The three methods chat needs off a `TokenAccounting`, and not one more.\n *\n * `recordUsage` is deliberately absent: anchoring the estimate to a provider's reported prompt\n * tokens is the job of whoever made the call, and a compaction pass that could re-anchor would be\n * writing to the very number it is about to read.\n */\nexport interface ChatTokenAccounting {\n estimate(messages: ModelMessage[]): number\n getCeilings(): { contextWindow: number; maxOutput: number }\n degrade(messages: ModelMessage[], options: ChatDegradeOptions): ChatDegradeOutcome\n}\n\nexport interface CompactionPassInput {\n readonly messages: readonly ModelMessage[]\n readonly accounting: ChatTokenAccounting\n /** The turn the engine is running. Compaction never mints one — it is not a turn. */\n readonly turnId: string\n readonly now: () => string\n}\n\n/**\n * What a pass produced: the conversation to carry forward, and the event if one triggered.\n *\n * `messages` is present on BOTH arms, including the cannot-fit one. That is the cannot-wedge\n * clause stated as a type: there is no outcome of this function that leaves a caller without a\n * conversation, and therefore no outcome from which a session cannot continue.\n */\nexport interface CompactionPass {\n readonly messages: readonly ModelMessage[]\n readonly event?: ChatCompactionEvent\n}\n\n/** The plain text of a message, for the pin's identity. Never a size — sizes come from estimate. */\nfunction pinIdentity(message: ModelMessage): string {\n const content = message.content\n if (typeof content === 'string') return `${message.role}\u0000${content}`\n const parts: string[] = []\n for (const part of content as unknown[]) {\n if (typeof part === 'object' && part !== null) {\n const typed = part as { type?: unknown; text?: unknown }\n if (typed.type === 'text' && typeof typed.text === 'string') parts.push(typed.text)\n }\n }\n return `${message.role}\u0000${parts.join('\u0001')}`\n}\n\n/**\n * Protect the last user turn and the last assistant turn, beyond degrade's own system + final.\n *\n * BY CONTENT IDENTITY RATHER THAN BY INDEX, and the difference is a real bug avoided. The pin\n * predicate is called against the array degrade is WORKING on, which is the post-hygiene array —\n * and hygiene may remove an emptied message, after which every index behind it has shifted. A pin\n * closed over positions in the pre-hygiene array would then protect the wrong messages, silently,\n * in exactly the sessions where hygiene did the most work. Text identity survives hygiene, which\n * rewrites tool-result payloads and never the words of a user or an assistant turn.\n *\n * Over-protection is the safe direction: two byte-identical turns both stay, which costs a few\n * tokens and can only ever push toward the cannot-fit arm — an arm that returns a conversation.\n */\nfunction chatPin(messages: readonly ModelMessage[]): (message: ModelMessage) => boolean {\n const protectedIdentities = new Set<string>()\n for (const role of ['user', 'assistant'] as const) {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index]\n if (message.role === role) {\n protectedIdentities.add(pinIdentity(message))\n break\n }\n }\n }\n return (message: ModelMessage): boolean => protectedIdentities.has(pinIdentity(message))\n}\n\n/**\n * The whole of CHAT-04's trigger policy.\n *\n * Below the threshold nothing happens and nothing is logged, because nothing happened. At or above\n * it — the contract is `>=`, so the boundary triggers — the shipped degrade pass runs once under a\n * floored budget, and one event records what it cost whichever way it came out.\n *\n * A HISTORY OF FEWER THAN TWO MESSAGES IS A NO-OP (edge: CHAT-04/empty). Not a guard against a\n * crash — degrade handles both fine — but against a false record: degrade protects the final\n * message unconditionally, so on a one-message history there is nothing it may touch, and a pass\n * that ran would emit an event reporting a cost it did not pay.\n */\nexport function maybeCompact(input: CompactionPassInput): CompactionPass {\n const messages = [...input.messages]\n if (messages.length < 2) return { messages: input.messages }\n\n const { contextWindow } = input.accounting.getCeilings()\n const threshold = COMPACTION_RATIO * contextWindow\n const beforeTokens = input.accounting.estimate(messages)\n if (beforeTokens < threshold) return { messages: input.messages }\n\n const budget = Math.max(CHAT_MINIMUM_CONTEXT, threshold)\n const isPinned = chatPin(messages)\n // The hard-truncate fallback lives INSIDE this call and has already run by the time it returns.\n // `ok: false` is therefore not a failure to act — it is the substrate reporting that even after\n // hygiene, eviction and truncation, the content it may not touch still exceeds the budget. The\n // conversation comes back either way, which is why nothing below has a throwing branch.\n const outcome = input.accounting.degrade(messages, {\n budget,\n pin: (message: ModelMessage): boolean => isPinned(message),\n })\n const afterTokens = input.accounting.estimate(outcome.messages)\n\n return {\n messages: outcome.messages,\n event: {\n kind: 'compaction',\n turnId: input.turnId,\n at: input.now(),\n beforeTokens,\n afterTokens,\n outcome: outcome.ok ? 'degraded' : outcome.reason,\n },\n }\n}\n\n/**\n * The repaired replay as messages the accounting substrate can measure.\n *\n * A straight carry-across: the replay is already refs and one-liners (D-18), and this is not the\n * place to decide what a conversation says. What it IS the place for is the ordering guarantee —\n * the replay handed to the hook has been repaired and has its aborted turns excluded, so the\n * conversation compaction prunes is the one CHAT-05 says it must be.\n */\nexport function replayToModelMessages(replay: SessionReplay): ModelMessage[] {\n return replay.messages.map(\n (message) => ({ role: message.role, content: message.text }) as ModelMessage,\n )\n}\n\nexport interface ChatCompactionHookDeps {\n readonly accounting: ChatTokenAccounting\n readonly now: () => string\n /**\n * Where the conversation to prompt with goes, called on EVERY turn rather than only on a\n * triggered pass. A sink that fired only when compaction ran would leave its consumer holding a\n * stale conversation on every quiet turn, which is the subtle version of the bug this whole\n * ordering exists to prevent.\n */\n readonly onConversation?: (messages: readonly ModelMessage[], sessionId: string) => void\n /**\n * The conversation source, defaulting to the repaired replay the engine hands over.\n *\n * Overridable for the same reason `ClauseSplitter` is a seam: a host that assembles its live\n * turn state through the SDK's `ChatState` rather than by replaying the log has a better answer\n * than the replay, and it must not have to fork the trigger policy to use it.\n */\n readonly conversationFor?: (context: {\n readonly turnId: string\n readonly sessionId: string\n readonly replay: SessionReplay\n }) => readonly ModelMessage[]\n}\n\n/**\n * Bind the trigger policy as the engine's `CompactionHook`.\n *\n * ONE PASS PER TURN, AND NO LOOP AROUND IT. The engine calls this once, immediately after the\n * user message is logged and before stage 1 — so there is no arrangement in which a pass that\n * frees nothing is retried until it does. That is the structural half of \"cannot wedge\"; the other\n * half is that `maybeCompact` returns a conversation on every arm, which its suite pins as a\n * fixpoint over repeated application.\n *\n * THE EVENT GOES WHERE THE CALL SAYS, NOT WHERE THE CONSTRUCTION SAID (392-12, CR-01). The hook\n * carried an `emit` bound once per composition; with one adapter serving many sessions, \"the log\"\n * was not a fact a composition could know. `context.append` is the handle of the turn actually\n * being compacted, so this hook has no way to write into another conversation.\n */\nexport function createChatCompactionHook(deps: ChatCompactionHookDeps): CompactionHook {\n return async (context): Promise<void> => {\n const source = deps.conversationFor?.(context) ?? replayToModelMessages(context.replay)\n const result = maybeCompact({\n messages: source,\n accounting: deps.accounting,\n turnId: context.turnId,\n now: deps.now,\n })\n // THE SESSION TRAVELS WITH THE CONVERSATION (392 plan 13, CR-02). What this publishes is the\n // pruned history of ONE conversation, and the sink it publishes into is now one container per\n // session — so a sink called without the id would have to guess which, and on two interleaved\n // turns the guess is the aliasing this keying removes. The id is the call's own, from the\n // handle the engine opened, never a composition-held value.\n deps.onConversation?.(result.messages, context.sessionId)\n if (result.event !== undefined) await context.append(result.event)\n }\n}\n","// The deterministic stage-1 resolver table (Phase 392, D-05 / D-06 / D-09).\n//\n// One module, hand-authored, CLOSED. Each entry is a pattern and what the pattern resolves to —\n// never a second capability vocabulary. The rule is 387 D-11's and it is absolute: EVERY function\n// id below is IMPORTED from the module that declares it, never written as a literal. An op renamed\n// at its declaration must break this file's compile rather than leave an alias pointing at a string\n// nothing dispatches (`functions/entity-cards/actions.ts:10-14`).\n//\n// THE TABLE IS A CAP, WHICH IS WHY IT IS THIS SMALL. D-06's canon is the verbs the spec names plus\n// the verbs 391 shipped, and then ONE generic `/fn <op> [args]` branch that reaches every registry\n// op without the table growing by one row per op. A table that grew with the registry would be a\n// second listing of the catalogue, drifting from the first; a table that stayed small by hiding\n// ops would be a curated tool set, which the always-send-all law forbids. `/fn` is how both are\n// avoided at once: one tested branch, total reach, zero per-op maintenance.\n//\n// RESOLUTION IS BINARY. `ChatResolution` has exactly two variants and NO CONFIDENCE MEMBER, and\n// the absence is load-bearing (D-09). This path OVERRIDES a model's plan on both the action set and\n// the bound arguments (D-12), so a false positive here does not degrade an answer — it executes a\n// capability nobody asked for. A confidence number would be the first half of a threshold, and a\n// threshold is exactly how an overriding path acquires a false-positive rate. A near-miss — a\n// misspelling, a verb with its required argument missing — therefore resolves to NOTHING and flows\n// on to the planner, which is allowed to be wrong because it is not allowed to override.\n//\n// NO `/tools`, NO `/compact` (D-04). The first fights the always-send-all law; the second is a\n// manual lever over a mechanism 392 keeps automatic.\n\nimport { parseShortId } from '@vostride/agent-qa-schema'\n\nimport { ENTITIES_RESOLVE_FUNCTION_ID } from '../functions/ops/entities-ids.js'\nimport { RUNS_DIGEST_FUNCTION_ID } from '../functions/ops/runs-digest.js'\nimport { RUNS_LIST_FUNCTION_ID } from '../functions/ops/runs-list.js'\nimport { RUNS_START_FUNCTION_ID } from '../functions/ops/runs-start.js'\n\n/**\n * The session-scoped directives: canon that maps to NO registry op.\n *\n * Closed and spelled once. `/model` changes how THIS SESSION behaves (D-04's model override and its\n * `model_change` event); `/help` and `/quit` are REPL chrome. None of them is a capability, which is\n * why none of them has a function id — and they are in the table anyway, because the table is the\n * vocabulary a person types and the meta-test demands a scenario for every row of it.\n *\n * 432-13 (D-14): `/pin` is gone. It was a session deny overlay over the op gate, and there is no op\n * gate; a clause spelled `/pin …` is now an ordinary clause nothing in the table resolves.\n */\nexport const CHAT_DIRECTIVES = ['model', 'help', 'quit'] as const\n\nexport type ChatDirectiveName = (typeof CHAT_DIRECTIVES)[number]\n\n/**\n * What one alias resolves TO.\n *\n * A discriminated union rather than an op shape with optional members, because \"which registry op,\n * with what input\" and \"which session directive, with what argument\" are different questions and a\n * shape that could answer half of each is a shape a caller has to defend against.\n */\nexport type ChatResolverEntry =\n | { readonly kind: 'op'; readonly functionId: string; readonly input: unknown }\n | { readonly kind: 'directive'; readonly directive: ChatDirectiveName; readonly argument?: string }\n\n/**\n * One row: the alias's name, and the single function that decides both whether the clause matches\n * and what it binds.\n *\n * MATCHING AND ARGUMENT BINDING ARE ONE STEP on purpose. Split in two, a clause could pass the\n * pattern and then fail the parse — and there is no honest answer to what that is. It is not a\n * resolution (nothing was bound) and it must not be a partial one (see the header). Folding them\n * means `run` with no test named simply does not match, which is the same answer the table gives\n * `propsals`: nothing, flowed onward.\n */\nexport interface ChatResolverRule {\n /** Human-readable name of the alias — the log's word for it, and the meta-test's scenario key. */\n readonly alias: string\n readonly resolve: (clause: string) => ChatResolverEntry | undefined\n}\n\nexport type ChatResolverTable = readonly ChatResolverRule[]\n\n/**\n * Stage 1's answer for one clause. Two variants, no third, no number.\n *\n * `alias` rides along on the resolved arm because the session log records WHICH canonical form a\n * person used, and reconstructing that from the entry afterwards would mean a second matcher.\n */\nexport type ChatResolution =\n | { readonly kind: 'resolved'; readonly alias: string; readonly entry: ChatResolverEntry }\n | { readonly kind: 'unresolved' }\n\n/**\n * One frozen row, contextually typed.\n *\n * A named helper rather than a bare `Object.freeze({...})` per row: `Object.freeze` is generic and\n * infers from its argument, so a row written inside it loses the contextual type and every `kind`\n * widens to `string`. Going through a parameter of the row type is what makes a misspelled\n * discriminant or a directive name outside the closed set a compile error at the row that has it,\n * which is the whole reason the union is discriminated.\n */\nfunction rule(declaration: ChatResolverRule): ChatResolverRule {\n return Object.freeze(declaration)\n}\n\n/** Case-insensitive, whitespace-trimmed equality — the comparison every bare verb wants. */\nfunction isExactly(word: string): (clause: string) => boolean {\n return (clause) => clause.trim().toLowerCase() === word\n}\n\n/**\n * The remainder after a leading verb, or nothing when the verb stands alone.\n *\n * Returns `undefined` for a bare verb rather than an empty string, so a caller that requires an\n * argument gets its refusal from the same place a caller that forbids one gets its permission.\n */\nfunction argumentAfter(verb: string, clause: string): string | undefined {\n const trimmed = clause.trim()\n const lowered = trimmed.toLowerCase()\n if (!lowered.startsWith(`${verb} `) && !lowered.startsWith(`${verb}\\t`)) return undefined\n const rest = trimmed.slice(verb.length).trim()\n return rest === '' ? undefined : rest\n}\n\n/**\n * `/fn`'s body, following the `fn --input <json>` precedent exactly (`cli/commands/fn.ts`).\n *\n * No body means `{}` — the same default the CLI verb has, because `/fn runs.list` and\n * `agent-qa fn runs.list` are the same request typed at two prompts and a second default would be\n * a second grammar. For `runs.list` that default is the op's own: the 20 newest completed runs.\n * A body that is not a JSON OBJECT (malformed, an array, a bare word) does not resolve: ops take\n * objects, and guessing an object around whatever was typed is exactly the partial match this\n * table does not do.\n */\nfunction parseFnBody(body: string | undefined): Record<string, unknown> | undefined {\n if (body === undefined) return {}\n let parsed: unknown\n try {\n parsed = JSON.parse(body)\n } catch {\n return undefined\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) return undefined\n return parsed as Record<string, unknown>\n}\n\n/**\n * THE CANON. Ordered, and the order is the first-match walk (see `resolveClause`).\n *\n * No two rules overlap today, so the order is documentation rather than semantics — and it is\n * written in D-06's own listing order so it stays readable as one.\n */\nexport const CHAT_RESOLVER_TABLE: ChatResolverTable = Object.freeze([\n rule({\n alias: 'run',\n // The reference is handed to `runs.start` as a PATTERN, verbatim. The op's contract is\n // \"test file paths or glob patterns\", and it resolves the configured default set when the\n // field is absent — so `run` with nothing named is a near-miss here rather than a silent\n // \"run everything\", which is not a request anybody made by typing three letters.\n resolve: (clause) => {\n const reference = argumentAfter('run', clause)\n if (reference === undefined) return undefined\n return { kind: 'op', functionId: RUNS_START_FUNCTION_ID, input: { patterns: [reference] } }\n },\n }),\n rule({\n alias: 'status',\n // ADJUDICATION (the plan asks for it recorded here): the candidates were `runs.list` and\n // `runs.get`. `runs.get` addresses exactly one run BY ID and refuses without one, so it\n // cannot answer a person who typed a bare word — the id is the very thing they did not\n // supply. `runs.list` takes `{}`, answers the 20 most recently finished runs newest first\n // (431 D-08), and is the only read in the registry whose contract answers \"what has happened\n // here lately\" without being told what to look at. `status <run>` is not minted:\n // `digest <run>` already owns \"tell me about that one run\", and two verbs for it would be\n // two answers.\n resolve: (clause) =>\n isExactly('status')(clause)\n ? { kind: 'op', functionId: RUNS_LIST_FUNCTION_ID, input: {} }\n : undefined,\n }),\n rule({\n alias: 'test-ref',\n // 387 D-05's never-guess ladder does the resolving, and the ref it receives is WHAT THE\n // PERSON TYPED, verbatim. `entities.resolve` accepts \"any reference at all — short-ID, URI,\n // or free text\", so pre-chewing `test 42` into `42` here would be this file inventing a\n // second resolution grammar in front of the one that exists to be the only one. Two forms\n // match: the `test <n>` phrase and a bare well-formed short-ID, the latter recognised through\n // the schema's own parser rather than a regex spelled here.\n resolve: (clause) => {\n const trimmed = clause.trim()\n const named = argumentAfter('test', clause)\n const isShortId = parseShortId(trimmed) !== undefined\n if (named === undefined && !isShortId) return undefined\n return { kind: 'op', functionId: ENTITIES_RESOLVE_FUNCTION_ID, input: { ref: trimmed } }\n },\n }),\n rule({\n alias: 'digest',\n // The run reference passes through verbatim for the same reason the acknowledgment in\n // `runs.start` is read off the record rather than echoed: a reference that names no run comes\n // back as `RunNotFoundError`, named, instead of as a plausible-looking digest of nothing.\n // Bare `digest` is a near-miss, not \"the latest\": which run a person meant is a question this\n // table must not answer by guessing.\n resolve: (clause) => {\n const reference = argumentAfter('digest', clause)\n if (reference === undefined) return undefined\n return { kind: 'op', functionId: RUNS_DIGEST_FUNCTION_ID, input: { runId: reference } }\n },\n }),\n // 432-13 (D-05/D-14): the `proposals` inbox alias is gone. Changes apply in the call, so there is\n // no pending-decision inbox to route a bare word to. 432-17 deleted the inbox and its ops too.\n rule({\n alias: 'model',\n resolve: (clause) => {\n const name = argumentAfter('/model', clause)\n return name === undefined ? undefined : { kind: 'directive', directive: 'model', argument: name }\n },\n }),\n rule({\n alias: 'fn',\n // THE PASSTHROUGH (D-06). The op id is NOT validated here — deliberately. `invokeFunction`'s\n // step 1 raises `UnknownFunctionError` naming the id before any dependency is touched, so a\n // typo and a capability that has not shipped yet both come back named, for free, from the one\n // place that knows what is registered. A check here would be a second catalogue.\n resolve: (clause) => {\n const rest = argumentAfter('/fn', clause)\n if (rest === undefined) return undefined\n const separator = rest.search(/\\s/u)\n const functionId = separator === -1 ? rest : rest.slice(0, separator)\n const body = separator === -1 ? undefined : rest.slice(separator).trim()\n const input = parseFnBody(body === '' ? undefined : body)\n if (input === undefined) return undefined\n return { kind: 'op', functionId, input }\n },\n }),\n rule({\n alias: 'help',\n resolve: (clause) =>\n isExactly('/help')(clause) ? { kind: 'directive', directive: 'help' } : undefined,\n }),\n rule({\n alias: 'quit',\n resolve: (clause) =>\n isExactly('/quit')(clause) ? { kind: 'directive', directive: 'quit' } : undefined,\n }),\n] satisfies ChatResolverTable)\n\n/**\n * The refusal a directive gets in a build that binds no handler for it.\n *\n * Stage 1 RESOLVED the clause — the table knows `/model` perfectly well — and this build has\n * nothing to carry it out with. That is a different fact than `no capability handles that`, and it\n * has to read differently in the log. The two are kept apart the same way the headless planner is\n * kept apart from a planner that answered and declined (see `ports.ts`): a person reading a\n * session must be able to tell `this build cannot yet` apart from `nothing can`.\n *\n * (The backticks are not stylistic. `packages/arch`'s dependency lint scans every line of every\n * source file for an import specifier, and its pattern is the word `f`+`rom` followed by a quoted\n * string — so ordinary prose using that word ahead of a quoted phrase reads to it as an import of\n * a package by that name, and the package census reds. Comments here are load-bearing enough to\n * be scanned; they are written to survive the scanner.)\n */\nexport function directiveNotBoundReason(directive: ChatDirectiveName, clause: string): string {\n return (\n `The /${directive} directive is recognised but no handler for it is bound in this build: `\n + `\"${clause}\". The turn was refused before anything ran, so nothing in the request was `\n + 'carried out.'\n )\n}\n\n/**\n * Stage 1 for one clause: the FIRST rule that binds, or `unresolved`.\n *\n * First-match rather than unique-match, and the table is ordered rather than a map, because D-06's\n * canon has forms that could legitimately overlap as it grows, and \"the earlier, more specific rule\n * wins\" is a rule a reader of the table can see. Precision is 1.0 by construction — every rule is\n * an exact predicate over the clause, so a miss is a miss and never a guess (D-09).\n */\nexport function resolveClause(table: ChatResolverTable, clause: string): ChatResolution {\n for (const rule of table) {\n const entry = rule.resolve(clause)\n if (entry !== undefined) return { kind: 'resolved', alias: rule.alias, entry }\n }\n return { kind: 'unresolved' }\n}\n\n/**\n * One line of `/help`, in a shape a census can read (Phase 398 plan 09).\n *\n * WHY THE ENTRIES ARE STRUCTURED AND THE STRING IS DERIVED. `CHAT_HELP_TEXT` used to be ten\n * hand-aligned sentences, and a sentence is not something a test can join to anything: the only\n * assertion available over it was a substring match somebody remembered to write. The fields below\n * are the join keys — `alias` names the row of `CHAT_RESOLVER_TABLE` the line documents, and\n * `syntax` is the FORM A PERSON TYPES, first token and all — so \"the help text agrees with what\n * chat understands\" became a set comparison and \"this line claims an argument is optional\" became a\n * probe of the shipped rule.\n *\n * THE CENSUS-TIE DECISION (398 plan 09, planned 2026-08-16, executed 2026-08-17 · D-01/SC-1).\n * The discretion call was whether help re-derives from the committed capability catalog or stays\n * here with a mechanical tie. It stays HERE. `packages/agent` is storage-neutral — it cannot read a\n * committed artifact off disk without acquiring a filesystem dependency the whole package is built\n * to not have — so re-deriving at runtime would move help out of the package that owns the\n * vocabulary and into the one that ships bytes. The tie gives the same guarantee without the move:\n * `packages/cli/src/__tests__/conformance/help-census.test.ts` set-equals these aliases against the\n * catalog's alias rows plus the shipped directives plus the passthrough, in BOTH directions, so a\n * help line with no capability behind it and a capability with no help line are each a named RED.\n * The header's one-list law is unchanged; what changed is that it is now enforced rather than\n * asked for.\n */\nexport interface ChatHelpEntry {\n /** The `CHAT_RESOLVER_TABLE` row this line documents. The census's join key. */\n readonly alias: string\n /**\n * What a person types, verbatim, including the leading `/` where there is one.\n *\n * `<angle>` marks a REQUIRED argument and `[square]` an optional one, and the distinction is\n * load-bearing rather than typographic: a conformance cell reads it and drives the shipped rule\n * with the bare verb, so a line promising that a verb works alone when the rule refuses it — the\n * exact drift this plan found on `digest` — is a failure rather than a reading.\n */\n readonly syntax: string\n /** What the line says the verb does. */\n readonly summary: string\n}\n\n/**\n * What `/help` prints, one entry per row of the table above (Phase 392 plan 08, D-06).\n *\n * IT LIVES BESIDE THE TABLE, and that is the point rather than the filing: the canon a person can\n * type is `CHAT_RESOLVER_TABLE`, and help text kept anywhere else would be a second list of what\n * chat understands, free to drift from the one that actually routes. `/fn` is named explicitly\n * because it is the reach lever — every registry op is one deterministic branch away, which is why\n * the alias set stays thin (D-06).\n */\nexport const CHAT_HELP_ENTRIES: readonly ChatHelpEntry[] = Object.freeze([\n Object.freeze({ alias: 'run', syntax: 'run <test>', summary: 'start a run for a test' }),\n Object.freeze({ alias: 'status', syntax: 'status', summary: 'the recent runs' }),\n Object.freeze({ alias: 'test-ref', syntax: 'test <n>', summary: 'show a test by reference' }),\n // 2026-08-17 (398 plan 09): this line used to read `digest` / \"the latest run digest\", and both\n // halves were false. The rule fifteen lines up requires a reference and treats a bare `digest` as\n // a near-miss precisely so the table never guesses which run somebody meant — so the help text\n // was advertising a guess the resolver refuses to make. The argument-contract cell in\n // `help-census.test.ts` is what now holds the two together.\n Object.freeze({ alias: 'digest', syntax: 'digest <run>', summary: \"that run's digest\" }),\n Object.freeze({\n alias: 'fn',\n syntax: '/fn <op> [json]',\n summary: 'invoke any registered function by id — every capability, one branch',\n }),\n Object.freeze({\n alias: 'model',\n syntax: '/model <name>',\n summary: 'switch the model for this session',\n }),\n Object.freeze({ alias: 'help', syntax: '/help', summary: 'this list' }),\n Object.freeze({ alias: 'quit', syntax: '/quit', summary: 'end the session' }),\n] as const satisfies readonly ChatHelpEntry[])\n\n/** The column the summaries start in — a reading convenience, pinned once. */\nconst HELP_SYNTAX_COLUMN = 20\n\n/**\n * What `/help` prints, RENDERED from the entries rather than spelled a second time.\n *\n * The string is still the export `composeLocalAgent`'s directive handler returns, because a person\n * types `/help` and reads sentences. What is gone is the possibility of the sentences and the join\n * keys disagreeing: there is one list, and this is a projection of it.\n */\nexport const CHAT_HELP_TEXT = [\n 'What I understand deterministically:',\n ...CHAT_HELP_ENTRIES.map(\n (entry) => ` ${entry.syntax.padEnd(HELP_SYNTAX_COLUMN)}${entry.summary}`,\n ),\n 'Anything else is planned by the model and reconciled against the table before anything runs.',\n].join('\\n')\n","// The chat verbs 432 retired, answered by name (quick 261003-cpv, 432 review IN-05).\n//\n// 432-13 removed `/pin` (a session deny overlay over an op gate that no longer exists) and the\n// bare `proposals` inbox alias (there is no inbox). Neither is a directive or an alias any more:\n// the resolver table does not resolve them, and its deletion census keeps it that way. But a clause\n// stage 1 leaves unresolved flows to the planner, and in a live session a model may plan the op the\n// text of `/pin fn:runs.start` names, which is the opposite of what a person with the old habit\n// meant. So the turn engine asks this module before stage 2 and refuses such a turn by name.\n//\n// EXACT SPELLINGS ONLY: the `/pin` verb with or without an argument, in any case, and the bare word\n// `proposals`. A near-miss such as `/pinned` is not a retired verb and still flows on, as D-09 has\n// every near-miss do.\n\nconst RETIRED_PIN = '/pin'\nconst RETIRED_INBOX = 'proposals'\n\nfunction isRetiredPin(lowered: string): boolean {\n if (lowered === RETIRED_PIN) return true\n if (!lowered.startsWith(RETIRED_PIN)) return false\n const next = lowered.charAt(RETIRED_PIN.length)\n return next === ' ' || next === '\\t'\n}\n\n/** The refusal a retired chat verb gets, or `undefined` for any other clause. */\nexport function retiredChatVerbReason(clause: string): string | undefined {\n const lowered = clause.trim().toLowerCase()\n if (isRetiredPin(lowered)) {\n return '/pin was retired in this version: nothing asks before an operation runs, so there is '\n + 'nothing to pin. Nothing in this request was run.'\n }\n if (lowered === RETIRED_INBOX) {\n return 'the proposals inbox was retired in this version: changes apply when they are made, so '\n + 'nothing waits for a decision. Nothing in this request was run.'\n }\n return undefined\n}\n","// What a damaged session file MEANS, and what a resumed session remembers (Phase 392, CHAT-05 /\n// D-18 / D-19).\n//\n// PURE, AND IN `agent` RATHER THAN IN THE ADAPTER. Deciding what to make of a half-written log is\n// a different kind of work than moving bytes: it has a corpus, it has edge cases that deserve\n// names, and every storage adapter — the JSONL one, the in-memory twin, whatever M5 reads sessions\n// with — has to reach the SAME verdict or two hosts will disagree about whether a conversation\n// happened. A branch inside one adapter's read loop would be that disagreement waiting to be\n// written. Nothing here touches a filesystem; the adapter hands over lines and takes back events.\n//\n// THE TWO CRASH SHAPES D-19 NAMES, AND NO OTHERS.\n//\n// 1. A TORN FINAL LINE. The process died part-way through a write, so the last line is not a\n// whole JSON document. It is skipped and reported by line number. This is the EXPECTED cost\n// of a crash and the fsync discipline bounds it: at most the in-flight turn.\n// 2. A DANGLING TURN. The last event this build can read is neither `turn_complete` nor\n// `aborted`, so a turn was in flight when the process died. Repair APPENDS a synthesized\n// `aborted` naming that turn.\n//\n// Everything else that fails the guard is ordinary DAMAGE, and damage is data: a named refusal\n// beside the events that still fold, on the posture the grant ledger had (391; the ledger was\n// deleted in 432-18).\n// The two are deliberately not collapsed into one word. A tear is what a crash costs; a mid-file\n// line that will not guard was written by another build or damaged in place and will still be\n// broken tomorrow. Telling an operator to go and repair a file whose real problem is that it was\n// killed sends them to fix the wrong thing.\n//\n// NO FURTHER CRASH SHAPE IS CLAIMED COVERED. A torn HEADER is refused by the adapter's own open\n// guard before this function is reached — a session whose header cannot be read is not a session\n// this build may append to, and guessing at its version would be the one mistake an append-only\n// log cannot take back.\n//\n// THE DECLARED VERSION IS AN ARGUMENT (392-01's decision, unchanged here). The file states its\n// version ONCE, on the header, and the open path has already read it; a per-line stamp would be a\n// second answer to a question the header closed, free to disagree with the first.\n\nimport { guardChatSessionEvent } from '@vostride/agent-qa-schema'\nimport type {\n ChatAbortedEvent,\n ChatSessionEvent,\n RefusedChatSessionLine,\n} from '@vostride/agent-qa-schema'\n\n/** One line off a session file, with the number an editor would show the person reading it. */\nexport interface SessionLogLine {\n /** 1-based and counting the header, so a refusal names what the operator will actually see. */\n readonly lineNumber: number\n readonly text: string\n}\n\nexport interface RepairSessionOptions {\n /** Taken off the header the adapter has already validated. Never read off a line. */\n readonly declaredVersion: number\n /** The composition's clock — a synthesized event carries the instant repair happened. */\n readonly now: () => string\n}\n\nexport interface SessionRepair {\n /** Every event the log can still be read as, in file order, with synthesis appended. */\n readonly repaired: readonly ChatSessionEvent[]\n /** What the caller must APPEND to the file to make it match {@link repaired}. */\n readonly synthesized: readonly ChatAbortedEvent[]\n /** Mid-file damage. Present forever; a caller should say so out loud. */\n readonly refusedLines: readonly RefusedChatSessionLine[]\n /** The one line a crash truncated, if there was one. Expected, bounded, not damage. */\n readonly tornTail: RefusedChatSessionLine | undefined\n}\n\n/**\n * The event kinds that CLOSE a turn.\n *\n * A turn whose last event is one of these ended; anything else means the process stopped talking\n * mid-turn. `aborted` counts whichever way it was written, which is what makes repair idempotent:\n * running it twice on the same file cannot produce two abort records for one interrupted turn.\n */\nconst TURN_CLOSING_KINDS: readonly ChatSessionEvent['kind'][] = ['turn_complete', 'aborted']\n\n/**\n * Read a session's event lines, closing any turn the crash left open.\n *\n * Never throws for damaged content. The one thing that can still propagate is an error the guard\n * raises for a reason that is not about a line — and there is none today, because the version is\n * asked per call with the value the header supplied, so a foreign-version log refuses every line\n * with the version named. That path is unreachable through the JSONL adapter, whose open guard\n * refuses a foreign header before this function is called, and it is pinned by a test anyway.\n */\nexport function repairSession(\n lines: readonly SessionLogLine[],\n options: RepairSessionOptions,\n): SessionRepair {\n const events: ChatSessionEvent[] = []\n const refusedLines: RefusedChatSessionLine[] = []\n let tornTail: RefusedChatSessionLine | undefined\n\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index]!\n const isFinal = index === lines.length - 1\n\n let parsed: unknown\n try {\n parsed = JSON.parse(line.text)\n } catch (error) {\n const reason = `unparseable line: ${error instanceof Error ? error.message : String(error)}`\n // The ONLY place the final line is treated differently, and the difference is the whole of\n // D-19's first arm: bytes that stop mid-document at the very end of an append-only file are\n // what a killed process leaves behind.\n if (isFinal) tornTail = { lineNumber: line.lineNumber, reason }\n else refusedLines.push({ lineNumber: line.lineNumber, reason })\n continue\n }\n\n try {\n events.push(guardChatSessionEvent(parsed, options.declaredVersion))\n } catch (error) {\n // It parsed as JSON and still does not describe an event: another build wrote it, or it was\n // edited in place. Truncation does not produce this, so a final line is no different here.\n refusedLines.push({\n lineNumber: line.lineNumber,\n reason: error instanceof Error ? error.message : String(error),\n })\n }\n }\n\n const last = events.at(-1)\n const dangling = last !== undefined && !TURN_CLOSING_KINDS.includes(last.kind)\n const synthesized: ChatAbortedEvent[] = dangling\n ? [{ kind: 'aborted', turnId: last.turnId, at: options.now(), source: 'synthesized' }]\n : []\n\n return {\n repaired: [...events, ...synthesized],\n synthesized,\n refusedLines,\n tornTail,\n }\n}\n\n/** One line of rebuilt conversation. Refs and one-liners only — never a payload body (D-18). */\nexport interface ChatReplayMessage {\n readonly role: 'user' | 'assistant'\n readonly text: string\n readonly turnId: string\n}\n\nexport interface SessionReplay {\n readonly messages: readonly ChatReplayMessage[]\n /** Every turn the log records as interrupted, however it was interrupted. */\n readonly abortedTurnIds: readonly string[]\n}\n\n/**\n * Rebuild the live conversation a resumed session continues from, over REPAIRED events.\n *\n * IT RUNS AFTER REPAIR AND BEFORE ANY PRUNE, and the order is not decoration: replaying the raw\n * events of a crashed session yields a conversation in which the interrupted turn looks answered,\n * so a caller that pruned first would trim a conversation that never happened. CHAT-05 asks for\n * the repair on \"the next turn, before pruning\" for exactly this reason.\n *\n * AN ABORTED TURN IS EXCLUDED WHOLE, not merely truncated. Its user message is a question nobody\n * answered; carrying it forward would put an unanswered request in the model's context and invite\n * the next turn to act on it — which is the silent re-execution CHAT-05's repair exists to\n * prevent. The turn is not lost: it is on the log, with an `aborted` record naming it.\n */\nexport function replaySession(events: readonly ChatSessionEvent[]): SessionReplay {\n const abortedTurnIds = events\n .filter((event) => event.kind === 'aborted')\n .map((event) => event.turnId)\n const aborted = new Set(abortedTurnIds)\n\n const messages: ChatReplayMessage[] = []\n for (const event of events) {\n if (aborted.has(event.turnId)) continue\n switch (event.kind) {\n case 'user_message':\n // The one payload body in this vocabulary, and the exception is principled: the utterance\n // is not a reference to content held elsewhere, it IS the content.\n messages.push({ role: 'user', text: event.text, turnId: event.turnId })\n break\n case 'clause_receipt':\n // Op id plus the one-line outcome. The result itself stayed wherever the op put it, and a\n // replay that reconstituted it would be re-deriving a payload the log declined to carry.\n messages.push({\n role: 'assistant',\n text: `${event.functionId}: ${event.outcome}`,\n turnId: event.turnId,\n })\n break\n case 'mark_unhandled':\n messages.push({ role: 'assistant', text: event.reason, turnId: event.turnId })\n break\n default:\n // Stage outcomes, approvals, config drift and compaction are the record of HOW a turn\n // happened, not of what was said. They belong to the triage report and not to the\n // conversation a resumed session continues.\n break\n }\n }\n\n return { messages, abortedTurnIds }\n}\n","// The session facts this surface owns, as a value two modules read (Phase 394, gap round 3, G-1).\n//\n// A LEAF MODULE rather than a direct planner-tools → turn-engine import. The stamp writes these\n// fields at the invoke; the model-facing projection must withhold the same ones before the model\n// decides. Both sides reading ONE value is the two-sided contract pin; keeping that value here\n// keeps the chat subtree's import graph acyclic by construction rather than by luck.\n\nimport { AUTHORING_DRAFT_WRITE_FUNCTION_ID } from '../functions/ops/authoring-draft-write.js'\nimport { AUTHORING_DRAFT_VERIFY_FUNCTION_ID } from '../functions/ops/authoring-verify-draft.js'\nimport { AUTHORING_FUNNEL_GET_FUNCTION_ID } from '../functions/ops/authoring-funnel-get.js'\n\n/**\n * The ops whose `sessionRef` this surface OWNS (394-17 / 394-19, D-12 · T-394-66 · T-394-74).\n *\n * A SET RATHER THAN AN ID, and that is CR-02's adjudicated fix rather than a generalisation for\n * its own sake. `authoring.draft.verify` carries the same field, spreads it onto the receipt it\n * persists, and is planner-reachable like every registered op — so a guard naming only the write\n * op left the identical forgery open one function id over. Membership makes the guarded vocabulary\n * a value `session-stamp-vocabulary.test.ts` can compare SET-EQUAL against the registry ops that\n * actually carry the field, so a future sibling gaining it reds a cell by the omitted name instead\n * of shipping unguarded. Dropping the field from the verify schema is NOT the alternative fix:\n * `shelf.verifyDraft` needs it to thread the loop's own ref.\n */\nexport const SESSION_STAMPED_FUNCTION_IDS: ReadonlySet<string> = new Set([\n AUTHORING_DRAFT_WRITE_FUNCTION_ID,\n AUTHORING_DRAFT_VERIFY_FUNCTION_ID,\n])\n\n/** The ops whose `window` this surface may scope to the session it knows (394-19, D-12). */\nexport const WINDOW_STAMPED_FUNCTION_IDS: ReadonlySet<string> = new Set([\n AUTHORING_FUNNEL_GET_FUNCTION_ID,\n])\n\n/**\n * The ops whose `scope` the COMPOSITION derives when the caller supplies none (394-26, WINDOWS 110).\n *\n * NOT A STAMP, and the difference is why it is a third set rather than a member of either above.\n * Nothing is written at the invoke here: `authoring.draft.write` declares `scope` OPTIONAL at the\n * registry — the `runs.start` law — and the host resolves it inside the op when it is absent, so a\n * supplied scope reaches the loop untouched and the deriver is never consulted. What membership\n * buys is the model-facing half: an id here gets the one sentence saying who fills the field, and\n * `planner-tools.test.ts` pins the description-bearing ids SET-EQUAL to this set unioned with the\n * window-stamped one. A field the model may omit but is never told it may omit is a field it\n * invents a value for, or refuses the call over — which is the defect this set exists to close.\n *\n * It lives HERE beside the two stamp sets because it answers the same question they do — which\n * fields is the model NOT the source of — and the projection reads all three from one leaf module\n * rather than acquiring a second import graph for the third law.\n */\nexport const HOST_DERIVED_SCOPE_FUNCTION_IDS: ReadonlySet<string> = new Set([\n AUTHORING_DRAFT_WRITE_FUNCTION_ID,\n])\n","// The four-stage turn engine (Phase 392, CHAT-01 / CHAT-05 / D-01 / D-08 / D-10 / D-24).\n//\n// ONE turn engine, two surfaces. The interactive REPL, the one-shot `ask` verb and the scenario\n// harness all drive this same entry — and they reach it through the registered `agent.ask` op, not\n// by holding this object (D-24). Chat therefore has no private powers: every capability a turn\n// exercises crosses `invokeFunction`'s eight-step gate exactly as a typed CLI verb does.\n//\n// THE STAGE ORDER IS A PINNED CONTRACT, in the house style `invoke.ts:123-134` sets:\n//\n// 1. deterministic resolver — the closed table, over the clause split. Precision 1.0 by\n// construction: an exact predicate hit or nothing, never a guess (D-09).\n// 2. planner LLM — via `PlannerStagePort`, and SKIPPED ENTIRELY when stage 1 resolved\n// every clause. Skipping is the tracer's whole point and a permanent property of canonical\n// utterances: they are model-independent, which is what makes their scenarios stable.\n// 3. deterministic reconciliation — the injected strategy. Runs on single-clause turns too, so\n// there is one code path rather than a fast one and a careful one.\n// 4. verdict + sequential execution — in utterance order, stopping on the first runtime failure,\n// one receipt per clause (D-11).\n//\n// STAGE 3 COMPLETES BEFORE STAGE 4 BEGINS, and that ordering IS D-10's strict pre-flight atomicity.\n// An unroutable clause anywhere in the utterance rejects the whole turn with zero executions and a\n// message naming it. There is no arrangement of these four stages in which a side effect precedes\n// the verdict, and that is the property `compound/` scenarios pin as `executed == 0`.\n//\n// EVERY EFFECT, NOT ONLY THE DISPATCHED ONES (392-11, CR-04). A session DIRECTIVE mutates the\n// session rather than the project — `/model` overrides the model — and those effects used to happen\n// above stage 2, so a refused turn could tell a person \"nothing in the request was carried out\"\n// while a directive was already in force. The binding question (\"can this build carry this out at\n// all\") is pure and stays early; the carrying-out sits below the verdict with everything else.\n//\n// NO TURN WRITES AN APPROVAL (432-13, D-14). The `/pin` directive and its `approval_decision` row are\n// gone with the op gate; `approval_decision` stays a readable kind for sessions written before 432.\n//\n// THIS ENGINE NEVER BRANCHES ON `caller.surface`. The anti-pattern is named in `invoke.ts:28-29`\n// and it is the thing the function layer exists to abolish; what varies per stage here is the\n// ORIGIN the composition minted, which is a fact about who is acting, not about where from.\n\nimport type {\n AgentAskInput,\n AgentAskResult,\n ChatSessionEvent,\n ChatSessionHandle,\n ClauseReceipt,\n ClauseResult,\n ChatTurnStatus,\n FunctionCaller,\n SessionLogPort,\n} from '@vostride/agent-qa-schema'\n\nimport { AUTHORING_DRAFT_WRITE_FUNCTION_ID } from '../functions/ops/authoring-draft-write.js'\nimport { CONFIG_PROJECT_SCAFFOLD_FUNCTION_ID } from '../functions/ops/config-project-scaffold.js'\nimport {\n WRITE_TEST_UNCONFIGURED_DETAIL,\n writeTestScaffoldStopDetail,\n resolveWriteTestRoute,\n} from '../config-mutation/write-test-route.js'\n\nimport type {\n CallerMint,\n ChatClause,\n ChatDirectiveHandlers,\n ChatInvokeBinding,\n ChatTurnStateSink,\n ClauseSplitter,\n CompactionHook,\n PlannerStageOutcome,\n PlannerStagePort,\n ReconcileStrategy,\n ResolvedClause,\n} from './ports.js'\nimport { diffChatConfig, foldChatConfigState } from './config-drift.js'\nimport type { ChatConfigState } from './config-drift.js'\nimport { replayToModelMessages } from './compaction.js'\nimport { directiveNotBoundReason, resolveClause } from './resolver-table.js'\nimport { retiredChatVerbReason } from './retired-chat-verbs.js'\nimport { replaySession } from './session-repair.js'\nimport { SESSION_STAMPED_FUNCTION_IDS, WINDOW_STAMPED_FUNCTION_IDS } from './session-stamps.js'\nimport type { ChatDirectiveName, ChatResolverTable } from './resolver-table.js'\n\nexport interface TurnEngineDeps {\n readonly table: ChatResolverTable\n readonly split: ClauseSplitter\n readonly reconcile: ReconcileStrategy\n readonly sessionLog: SessionLogPort\n readonly mint: CallerMint\n readonly invoke: ChatInvokeBinding\n /** Absent ⇒ headless: an unresolved clause fails the turn closed BY NAME (D-08). */\n readonly planner?: PlannerStagePort\n readonly compaction?: CompactionHook\n /**\n * The configuration in force RIGHT NOW for THIS SESSION, re-read per turn (D-04, CR-02).\n *\n * A THUNK rather than a value, and that is the whole of \"config changes are events\": a value\n * captured at construction would be the configuration the host started with, and the drift this\n * seam exists to detect is precisely the case where the file changed underneath a running\n * session. Absent ⇒ this host does not re-read, and nothing is claimed about drift — which is\n * different from claiming there was none, and is why the seam is optional rather than defaulted.\n *\n * IT IS HANDED THE SESSION for the reason `state` below is: the answer includes the model in\n * force, a `/model` override is session-scoped by D-04, and a composition-wide re-read would\n * report one session's override as every session's drift.\n */\n readonly config?: (sessionId: string) => ChatConfigState | Promise<ChatConfigState>\n /**\n * The session directives, where a host binds any, RESOLVED PER SESSION (D-04 / CR-02).\n *\n * Absent, or absent for one directive, means the refusal arm below names it. That is not a\n * degraded mode: a build that recognises `/model` and cannot carry it out should say so, and the\n * `mark_unhandled` row it leaves is what makes the gap countable.\n *\n * A FACTORY, because a directive mutates a session: `/model` moves the model this conversation\n * plans under, `/quit` asks THIS loop to end. Handlers bound once per composition would carry\n * those effects to whoever asked next (W-03).\n */\n readonly directives?: (sessionId: string) => ChatDirectiveHandlers\n /**\n * Where the live turn state a surface renders from is published, PER SESSION (Open Q2, CR-02).\n *\n * The turn id goes out at the START of the turn rather than with the result, and that ordering is\n * the whole reason the seam exists — an interrupted turn never produces a result, so a Ctrl+C\n * handler that waited for one could never name the turn it was interrupting (D-19's graceful arm).\n *\n * A FACTORY OVER THE SESSION ID, resolved once per turn from the header `open()` returned. What\n * this sink carries — the turn in flight, the conversation, the model — are facts about ONE\n * conversation, and a sink held per composition made them facts about whichever turn wrote last.\n * The engine cannot resolve it any earlier than the open, because a turn that names no session is\n * given one BY the adapter and the id is the adapter's answer rather than the caller's input.\n */\n readonly state?: (sessionId: string) => ChatTurnStateSink\n /**\n * This project's configured target vocabulary, for the PRE-DISPATCH write_test route (395-08,\n * D-14/D-15 · CFGM-05).\n *\n * A THUNK for `config`'s reason: a scaffold applied earlier in this very turn changes the answer,\n * and a value captured at composition would send the authoring dispatch that follows it against\n * the vocabulary as it stood before the scaffold wrote anything (2026-10-02, 432-40: re-spelled\n * from \"before the person approved anything\" — the scaffold writes in the call, D-05/D-14).\n *\n * BOUND FROM THE SAME PORT THE AUTHORING LOOP READS (`AuthoringReadPortLike.configuredTargetNames`),\n * so \"which targets does this project declare\" has one answer on both sides of the dispatch. Two\n * readings of that question would let this seam route on a vocabulary the loop then disagrees with,\n * which is the sibling-input failure this project keeps rediscovering.\n *\n * ABSENT ⇒ NO ROUTING. A host that cannot name its targets dispatches authoring exactly as it did\n * before this seam existed, and the loop's own backstop is unchanged. That is deliberately the\n * permissive direction: this seam adds a scaffold offer and a refusal, and a host that cannot\n * answer the question has not lost a guard — the backstop it always had is still there.\n */\n readonly configuredTargets?: () => Promise<readonly string[]>\n /**\n * Where a mid-turn artifact a person should read is written (395-13 · CFGM-05).\n *\n * DISPLAY-ONLY. Nothing handed to this port enters a decision, and nothing waits on it.\n *\n * 2026-09-30, 432-11 D-05/D-14: the `write_test` scaffold route writes the configuration in the\n * scaffold call itself, so what this port shows is a receipt of a change already on disk: the\n * summary, the files written and the diff. It is no longer a precondition of an approval, because\n * there is no approval. An absent port, or one that fails, does not stop the turn; the clause\n * receipt still names the files the scaffold wrote.\n */\n readonly present?: (text: string) => void | Promise<void>\n readonly now: () => string\n readonly mintTurnId: () => string\n}\n\n/** What `agent.ask` is bound to. One method, because a turn is one thing that happens. */\nexport interface TurnEngine {\n runTurn(input: AgentAskInput): Promise<AgentAskResult>\n}\n\n/**\n * A one-line outcome summary, never a payload body (D-18).\n *\n * The log and the receipt are a MAP: they say which op ran and how it went, and the result itself\n * stays wherever the op put it. `JSON.stringify(result)` here would be the single easiest way to\n * put a knowledge record, a config value or a masked secret into a file several surfaces render.\n *\n * THIS IS THE FALLBACK NOW, NOT THE RULE (399.1-03). An op that declares a classifier says how it\n * went in its own words and this line is never reached for it; what remains here is the honest\n * answer for an op that has said nothing about its own result — which is the same line every op\n * printed before folds existed.\n *\n * THE 394-14 EXCEPTION LEFT THIS FILE AND ITS REASONING WENT WITH IT. `summariseOutcome` used to\n * append `authoring.draft.write`'s fan-out report by an explicit id comparison here; that\n * disclosure is now a `renderResult` fold declared on the op's own spec, where the whole argument\n * for it (WTST-08's preview-plus-honest-reporting, and why counts are a map rather than a\n * territory) is recorded. The exception is no longer a named branch in a shared function — it is a\n * member of one spec, which is the same claim enforced by construction rather than by a comparison\n * somebody could widen.\n */\nfunction summarise(functionId: string): string {\n return `${functionId} completed`\n}\n\n// The stamped vocabulary now lives in `session-stamps.ts`, because the model-facing projection in\n// `planner-tools.ts` must withhold exactly what the stamp below writes (394-22, G-1). Re-exported\n// here so the sets stay readable from the module that acts on them.\nexport { SESSION_STAMPED_FUNCTION_IDS, WINDOW_STAMPED_FUNCTION_IDS }\n\n/**\n * Stamp the chat session onto the args of the ops this surface owns the session facts for.\n *\n * TWO LAWS, AND THEY POINT OPPOSITE WAYS ON PURPOSE. The receipt ref is an OVERWRITE AND NEVER A\n * DEFAULT — a `sessionRef` the planner emitted is a value a model wrote, honouring it would let a\n * model attribute its draft to another author's keep rate, and an absent one must stay absent\n * because absence is exclusion on a receipt. The funnel WINDOW is D-12's ratified SURFACE default\n * on the read side: the op cannot construct it (`FunctionSpec.invoke` never sees a caller), so the\n * surface that knows its session supplies it, and only its session ARM's ref is overwritten —\n * all-time and last-n pass through untouched because a model may legitimately ask a wider\n * question.\n *\n * A non-object args value is handed back untouched — the ops' `.strict()` schemas refuse that call\n * anyway, and stamping a key onto a string would invent a shape nobody sent.\n */\nfunction stampSessionFacts(functionId: string, args: unknown, sessionId: string): unknown {\n const stampsRef = SESSION_STAMPED_FUNCTION_IDS.has(functionId)\n const stampsWindow = WINDOW_STAMPED_FUNCTION_IDS.has(functionId)\n if (!stampsRef && !stampsWindow) return args\n if (typeof args !== 'object' || args === null || Array.isArray(args)) return args\n\n const stamped: Record<string, unknown> = { ...(args as Record<string, unknown>) }\n if (stampsRef) stamped.sessionRef = sessionId\n if (stampsWindow) {\n const window = stamped.window\n if (window === undefined) {\n stamped.window = { scope: 'session', sessionRef: sessionId }\n } else if (\n typeof window === 'object'\n && window !== null\n && !Array.isArray(window)\n && (window as { scope?: unknown }).scope === 'session'\n ) {\n stamped.window = { ...(window as Record<string, unknown>), sessionRef: sessionId }\n }\n }\n return stamped\n}\n\n/**\n * What stage 2 produced when it was skipped or when no planner is bound.\n *\n * The EMPTY plan rather than an absent one, so stage 3 reads one shape whatever happened upstream:\n * a reconciliation strategy that had to ask \"was there a planner\" before asking \"what did it say\"\n * would have two paths through the decision that refuses a turn, and only one of them would be\n * exercised by a host that binds a model.\n */\nconst NO_PLAN: PlannerStageOutcome = { toolCalls: [] }\n\n/** The refusal NAME the function layer publishes, which is what a failed receipt carries. */\nfunction refusalName(error: unknown): string {\n if (error instanceof Error) return error.name === '' ? error.message : error.name\n return String(error)\n}\n\n/** The refusal SENTENCE a person reads. See `routeWriteTest`'s catch for why not the name. */\nfunction refusalMessage(error: unknown): string {\n return error instanceof Error && error.message !== '' ? error.message : refusalName(error)\n}\n\n/**\n * A REFUSAL's own user-facing sentence, when the error is one (2026-10-02, 432-42, D-18).\n *\n * A refusal is an error that carries `neutralReason`: the run core's production refusal is the one\n * producer, and its sentence names the target and the one config line to add. The receipt keeps\n * the refusal NAME (the 399.1 charter is unchanged); the sentence is added to the turn's answer so\n * the chat person reads what the MCP door, `agent-qa run` and the dashboard already show. Any other\n * failure adds nothing, so no failing op's message reaches the answer through this path.\n */\nfunction refusalSentenceOf(error: unknown): string | undefined {\n if (typeof error !== 'object' || error === null) return undefined\n const sentence = (error as { neutralReason?: unknown }).neutralReason\n return typeof sentence === 'string' && sentence.trim() !== '' ? sentence : undefined\n}\n\n/**\n * The boundary verdict, ABOVE the change it is a verdict about (399.1, RC-2, criterion 4).\n *\n * WHAT WAS WRONG (history, 399.1). The pre-confirm render answered \"what does this change do\" —\n * summary line, file list, the true diff — and never answered \"does this change cross a trust\n * boundary\". The proposed arm filed that verdict as two required fields, and the one surface where\n * a person was asked to authorise the write showed them neither (`demo/acceptance/399/\n * ACCEPTANCE.md` §9 item 2). 2026-10-02 (432-40, D-05/D-14/D-15): there is no confirm, no proposal\n * and no grant machinery any more; the change is written in the call, and these lines disclose the\n * crossing on the applied answer the person reads.\n *\n * VERBATIM, NEVER A PARAPHRASE. Each reason is one of `CROSS_BOUNDARY_REASONS`' closed words\n * and it is printed as filed. A hand-written sentence per reason would be a SECOND answer to \"why\n * is this crossing\", free to disagree with the record the change answers with — which is the\n * drop-site lesson (D-04) applied to the field a person reads to see what crossed.\n *\n * THE FIELD NAMES ARE IN THE BYTES, deliberately. A person who reads `crossBoundary: true` here can\n * find the same field on the applied answer `agent-qa fn` and the MCP change tool return, and knows\n * they are looking at one fact rather than several surfaces' opinions of it. (432-12: changes apply\n * in the call, so there is no proposal to look it up in and nothing waits for review.)\n *\n * SILENT ON THE COMMON PATH. A change that crosses nothing contributes NO line, because a warning\n * printed over every change is one nobody reads — and an absent or non-boolean verdict is treated\n * as \"no claim of crossing\", never as a crossing, since the notice is a disclosure and inventing one\n * would be this function paraphrasing a producer that said nothing.\n */\nfunction crossBoundaryLines(answer: {\n readonly crossBoundary?: boolean\n readonly crossBoundaryReasons?: readonly string[]\n}): readonly string[] {\n if (answer.crossBoundary !== true) return []\n const reasons = answer.crossBoundaryReasons ?? []\n return [\n 'CROSSES A TRUST BOUNDARY — crossBoundary: true; crossBoundaryReasons: '\n + (reasons.length === 0 ? '(none named)' : reasons.join(', ')),\n ]\n}\n\n/** What one directive did: a line to print back, or the reason the turn is refused. */\ntype DirectiveResult =\n | { readonly kind: 'handled'; readonly text: string }\n | { readonly kind: 'refused'; readonly reason: string }\n\n/** One collected directive: the clause the table matched, and what it matched it as. */\ninterface DirectiveEntry {\n readonly clause: ChatClause\n readonly directive: ChatDirectiveName\n readonly argument?: string\n}\n\n/**\n * Is this directive CARRYABLE by this build — asked without carrying anything out (CR-04).\n *\n * A PURE READ OF `deps.directives`, and that purity is the whole reason this check may sit where\n * the execution loop used to. A build that recognises `/model` and binds no handler should say so\n * early, by name, before a model is ever consulted; but \"say so early\" is a statement about the\n * REFUSAL, not a licence to mutate a session before the verdict that authorises it. Splitting the\n * question from the act is what lets both properties hold at once.\n *\n * The refusal wording is `directiveNotBoundReason`'s, unchanged — `runDirective`'s own not-bound\n * arm reaches for the same function, so the two cannot drift into two answers to one question.\n */\nfunction directiveBindingRefusal(\n handlers: ChatDirectiveHandlers | undefined,\n entry: DirectiveEntry,\n): string | undefined {\n const bound = ((): boolean => {\n switch (entry.directive) {\n case 'model':\n return handlers?.model !== undefined && entry.argument !== undefined\n case 'help':\n return handlers?.help !== undefined\n case 'quit':\n return handlers?.quit !== undefined\n }\n })()\n return bound ? undefined : directiveNotBoundReason(entry.directive, entry.clause.text)\n}\n\n/**\n * Carry out one session directive.\n *\n * ONE EVENT IS BORN HERE and it goes through the vocabulary that already owns it. `/model`\n * produces its `model_change` through `diffChatConfig` — the SAME function the per-turn config\n * re-read calls, with `source: 'verb'` instead of `'config_reread'` — because a person switching\n * models and a file changing underneath a session are different FACTS and not different events\n * (392-07). No directive writes an `approval_decision` (432-13).\n */\nasync function runDirective(\n deps: TurnEngineDeps,\n handlers: ChatDirectiveHandlers | undefined,\n entry: DirectiveEntry,\n context: {\n readonly turnId: string\n readonly sessionId: string\n readonly append: (event: ChatSessionEvent) => Promise<void>\n readonly now: () => string\n },\n): Promise<DirectiveResult> {\n const notBound = (): DirectiveResult => ({\n kind: 'refused',\n reason: directiveNotBoundReason(entry.directive, entry.clause.text),\n })\n\n try {\n switch (entry.directive) {\n case 'model': {\n if (handlers?.model === undefined || entry.argument === undefined) return notBound()\n const outcome = await handlers.model(entry.argument)\n if (outcome.from !== outcome.to && deps.config !== undefined) {\n // Built from the configuration AS IT NOW STANDS, with only the model wound back — so the\n // diff produces exactly one `model_change` and cannot invent a toolset drift the verb did\n // not cause. The handler has already applied the override, which is what makes the\n // current read the `to` side and what stops the next turn's re-read from emitting a\n // `model_change` straight back to the composed model (392-07's trap).\n const current = await deps.config(context.sessionId)\n for (const event of diffChatConfig(\n { ...current, model: outcome.from },\n current,\n { turnId: context.turnId, at: context.now(), source: 'verb' },\n )) {\n await context.append(event)\n }\n }\n return { kind: 'handled', text: outcome.line }\n }\n case 'help': {\n if (handlers?.help === undefined) return notBound()\n return { kind: 'handled', text: handlers.help() }\n }\n case 'quit': {\n if (handlers?.quit === undefined) return notBound()\n return { kind: 'handled', text: handlers.quit() }\n }\n }\n } catch (error) {\n // A handler that REFUSED — a `/model` naming a model this host cannot resolve is the shipped\n // case — is a clause this build could not carry out, so it takes the engine's one refusal path\n // and leaves the same countable row. The message is the refusal's own.\n return { kind: 'refused', reason: error instanceof Error ? error.message : String(error) }\n }\n}\n\nexport function createTurnEngine(deps: TurnEngineDeps): TurnEngine {\n return {\n async runTurn(input: AgentAskInput): Promise<AgentAskResult> {\n // THE HANDLE THIS TURN OWNS (392-12, CR-01). Every write below goes through the object this\n // one `open()` returned, so a second turn running concurrently on the same adapter cannot be\n // written to by this one and cannot write to this one — session identity is a parameter of\n // the write path rather than adapter state. The `try/finally` around the whole body is what\n // makes \"closed on every exit path exactly once\" a property of the shape: a refusal, a\n // completion and a throw between here and `finish` all pass through the same release.\n const handle = await deps.sessionLog.open(input.sessionId)\n try {\n return await runTurnThrough(deps, handle, input)\n } finally {\n await handle.close()\n }\n },\n }\n}\n\n/**\n * The turn itself, written entirely through ONE session's handle.\n *\n * Lifted out of the closure so the open/close pair above can be a plain `try/finally` — the release\n * is then structural rather than a line each return path has to remember, which is the same reason\n * stage 4 is unreachable from a refusal by control flow rather than by a check.\n */\nasync function runTurnThrough(\n deps: TurnEngineDeps,\n opened: ChatSessionHandle,\n input: AgentAskInput,\n): Promise<AgentAskResult> {\n const sessionId = opened.header.sessionId\n // THE PER-SESSION SEAMS, RESOLVED HERE AND NOWHERE EARLIER (392 plan 13, CR-02). The header the\n // adapter just returned is the FIRST moment this session's id is known: `AgentAskInput.sessionId`\n // is optional, and a turn that names none is given one by the adapter rather than by its caller.\n // Resolving above the open would therefore have to guess, and every guess is the aliasing this\n // keying removes. Resolved ONCE per turn rather than per use, so `beginTurn`, `setConversation`\n // and `endTurn` cannot end up addressing two different containers within one turn.\n const state = deps.state?.(sessionId)\n const directiveHandlers = deps.directives?.(sessionId)\n const turnId = deps.mintTurnId()\n // Published BEFORE anything can fail, because the state this names is \"a turn is in flight\"\n // and that becomes true here. A surface interrupted between this line and the boundary below\n // has the id it needs to write the explicit `aborted` event.\n state?.beginTurn(turnId)\n\n // THROUGH THE HANDLE, NEVER THROUGH THE ADAPTER (392-12). There is no adapter-level write verb\n // left to reach for, which is what makes \"this turn's events go to this turn's session\" a\n // property of the type rather than of everybody remembering.\n const append = async (event: ChatSessionEvent): Promise<void> => {\n await opened.append(event)\n }\n // Carried onto EVERY result of this turn, refusal arms included: a person whose session is\n // damaged needs to hear about it on the turn that reopened it, and the refusal arms are the\n // ones a damaged log makes more likely rather than less (392-03's note to this plan).\n const refusedLineCount =\n opened.refusedLines.length === 0\n ? {}\n : { refusedLineCount: opened.refusedLines.length }\n\n const finish = async (\n status: ChatTurnStatus,\n // 399.1 D-05: `results` is REQUIRED on the contract and DEFAULTED here to the empty list,\n // because every arm that reaches this without one is an arm where nothing ran — a refusal, a\n // fail-closed turn, a turn answered in prose. Making each of them spell `results: []` would be\n // making them state the fact twice; making the field optional would have made 'nothing ran' and\n // 'this build does not report results' the same bytes, which is the ambiguity `receipts` was\n // required for in the first place.\n result: Omit<AgentAskResult, 'sessionId' | 'turnId' | 'status' | 'results'>\n & { results?: readonly ClauseResult[] },\n ): Promise<AgentAskResult> => {\n await append({ kind: 'turn_complete', turnId, at: deps.now(), status })\n // The fsync point (D-19). Per TURN, so the loss bound is exactly the in-flight turn —\n // the case the next-turn repair already knows how to handle.\n await opened.turnBoundary()\n state?.endTurn({ turnId, status, receipts: result.receipts, ...(result.answer === undefined ? {} : { answer: result.answer }) })\n return {\n sessionId,\n turnId,\n status,\n ...refusedLineCount,\n ...result,\n results: [...result.results ?? []],\n }\n }\n /**\n * The ONE way this engine refuses a turn (D-08 / D-10 / D-15).\n *\n * Every fail-closed arm goes through here, and that is what makes the `mark_unhandled` event\n * a property of refusing rather than a line somebody remembered to add at three call sites.\n * The event is what CHAT-03's FIELD rate is a projection over — the gated ceiling is computed\n * across the frozen corpus, but the ungated number a live deployment produces is only\n * observable if every refusal in every session left a row. A refusal that returned the right\n * message and logged nothing would be invisible to exactly the measurement D-15 asks for.\n *\n * A DIRECTIVE WITH NO HANDLER GOES THROUGH HERE TOO, and that is a deliberate reading rather\n * than a shortcut: `/model` in a build that binds nothing for it IS a clause this build\n * cannot carry out, so it belongs in the same count as any other. The two facts stay\n * distinguishable in the log through the REASON, which says `recognised but no handler`\n * rather than `no capability handles`, and plan 08 removes the arm entirely by binding them.\n */\n const refuse = async (clause: string, reason: string): Promise<AgentAskResult> => {\n await append({ kind: 'mark_unhandled', turnId, at: deps.now(), clause, reason })\n return finish('fail_closed', { receipts: [], unhandled: { clause, reason } })\n }\n\n // REPAIR, THEN REPLAY, THEN PRUNE (CHAT-05). `open()` has already run the replay-safety\n // repair — that is the adapter's contract, not this engine's option — so the events in hand\n // are the repaired ones and the replay below cannot see an unrepaired conversation. The\n // degrade pass then receives that replay and has nothing else to work on, which is what\n // makes the ordering a property of the code rather than a convention.\n const replay = replaySession(opened.events)\n // The ONE projection, applied once (392-06's mismatch, resolved in `chat-state.ts`): the\n // repaired replay becomes the conversation a surface and a prompt read. A bound degrade pass\n // publishes again over the top with the pruned form.\n state?.setConversation(replayToModelMessages(replay))\n\n // CONFIG DRIFT, BEFORE THE MESSAGE (D-04, CHAT-05). The re-read happens on EVERY turn, which\n // makes the session-start case the first turn's case rather than a second code path — one\n // fold, one diff, one place a `model_change` can be born. The events carry the id of the turn\n // they precede (the base type's own rule for session-scoped facts) and are appended ahead of\n // the user message, so a reader folding the log has the configuration in hand before it sees\n // what was asked under it.\n if (deps.config !== undefined) {\n const current: ChatConfigState = await deps.config(sessionId)\n const previous = foldChatConfigState(opened.header, opened.events)\n for (const event of diffChatConfig(previous, current, {\n turnId,\n at: deps.now(),\n source: 'config_reread',\n })) {\n await append(event)\n }\n }\n\n await append({ kind: 'user_message', turnId, at: deps.now(), text: input.message })\n await deps.compaction?.({ turnId, sessionId, replay, append })\n\n // ---- Stage 1: the deterministic resolver over the clause split.\n const clauses = deps.split(input.message)\n const mapped: ResolvedClause[] = []\n const directives: DirectiveEntry[] = []\n for (const clause of clauses) {\n const resolution = resolveClause(deps.table, clause.text)\n if (resolution.kind === 'unresolved') continue\n if (resolution.entry.kind === 'directive') {\n // Resolved, and NOT executable through the function layer: a directive names no\n // capability (D-04/D-21). It is collected rather than dropped, because a clause the\n // table understood and the engine silently ignored is the exact silent-drop shape D-08\n // and D-10 exist to make impossible.\n directives.push({\n clause,\n directive: resolution.entry.directive,\n ...(resolution.entry.argument === undefined\n ? {}\n : { argument: resolution.entry.argument }),\n })\n continue\n }\n mapped.push({\n clause,\n functionId: resolution.entry.functionId,\n args: resolution.entry.input,\n })\n }\n await append({\n kind: 'stage_outcome',\n turnId,\n at: deps.now(),\n stage: 'resolver',\n // Directives count as RESOLVED here, because they were: the table matched them. Whether\n // anything can carry them out is the next question, and answering it in this field would\n // make \"stage 1 did not recognise this\" and \"this build cannot do it\" the same bytes.\n outcome:\n mapped.length + directives.length === clauses.length ? 'resolved' : 'unresolved',\n })\n\n // ---- Retired verbs, answered by name before any model sees them (261003-cpv, 432 IN-05).\n //\n // A clause stage 1 left unresolved goes to the planner, and in a live session a model may plan\n // the op named in a retired `/pin fn:runs.start`. The retired spellings are refused here, through\n // the same `refuse()` every refusal takes, so the planner is never consulted and nothing runs.\n for (const clause of clauses) {\n if (mapped.some((resolved) => resolved.clause.index === clause.index)) continue\n if (directives.some((entry) => entry.clause.index === clause.index)) continue\n const retired = retiredChatVerbReason(clause.text)\n if (retired !== undefined) return refuse(clause.text, retired)\n }\n\n // ---- Directives, ASKED ABOUT here and carried out below the verdict (D-10, CR-04).\n //\n // A directive names no capability — it changes what this SESSION is, and that is why it does\n // not travel `invokeFunction` and why a model may never reach one (391 D-07: the mechanism\n // deciding what a model may do is the one mechanism it must not touch, even in the\n // tightening direction). A directive with no handler still refuses the whole turn by name,\n // through the same `refuse()` every other refusal takes, so a build that recognises `/model`\n // and cannot carry it out leaves a countable row rather than a silent no-op (D-08 / D-15).\n //\n // WHAT MOVED, AND WHY. This loop USED TO CARRY THE DIRECTIVES OUT here, above stage 2 —\n // which put a directive's effect and its row on the log of a turn that then\n // got refused, under a message reading \"nothing in the request was carried out\"\n // (392-VERIFICATION CR-04). D-10's pre-flight atomicity was applied only to `invokeFunction`\n // dispatches; it is now applied to every effect a turn can have. What stays here is the\n // BINDING question, which mutates nothing.\n for (const entry of directives) {\n const notBound = directiveBindingRefusal(directiveHandlers, entry)\n if (notBound !== undefined) return refuse(entry.clause.text, notBound)\n }\n\n // ---- The directive BATCH, VALIDATED BEFORE THE FIRST ONE IS APPLIED (392-14, E3/E3b).\n //\n // The binding loop above asks \"can this build carry this out at all\"; this one asks \"will THIS\n // argument be accepted\", and both are asked of every entry before any entry is carried out.\n // Without it the execution loop below applied directives one at a time and returned on the first\n // refusal — so a turn whose SECOND directive was refused kept the first one's effect and its row\n // on the log of a turn that then told the person nothing in the request was carried out\n // (392-VERIFICATION round 2; the shipped case was two `/pin`s, retired in 432-13). Moving the loop\n // below the verdict closed the single-directive case and left the BATCH open; a batch is atomic\n // or it is not, and D-10 has no reading under which the second half of a request may undo only\n // the second half.\n //\n // ASKING IS NOT APPLYING, which is what lets this sit above stage 2 beside the binding check:\n // `validate` mutates no session state by its port contract, so a turn refused here has had\n // nothing done to it. `runDirective`'s catch stays as the belt for a host that publishes no\n // validate — such a host is exactly as safe as it was, and no safer.\n //\n // ONE CONSEQUENCE, ACCEPTED: a turn refused here never reaches stage 2, so its log carries the\n // resolver `stage_outcome` row alone rather than three. Every event carries `turnId` and `at`,\n // and the refusal still leaves the same `mark_unhandled` row every other refusal does.\n if (directiveHandlers?.validate !== undefined) {\n for (const entry of directives) {\n try {\n await directiveHandlers.validate(entry.directive, entry.argument)\n } catch (error) {\n // The refusal's own message, for the reason `runDirective`'s catch takes it: the handler\n // knows what it can accept, and re-deriving that here would be a second answer to it.\n return refuse(entry.clause.text, error instanceof Error ? error.message : String(error))\n }\n }\n }\n\n // Everything the directives did not claim. Computed rather than reusing `clauses`, so a turn\n // that is ENTIRELY directives reaches stage 3 with nothing to reconcile and completes through\n // the same four stages as any other — one path, rather than a fast one and a careful one.\n const routable = clauses.filter(\n (clause) => !directives.some((entry) => entry.clause.index === clause.index),\n )\n\n // ---- Stage 2: the planner, consulted ONLY for what stage 1 could not answer.\n const unmapped = routable.filter(\n (clause) => !mapped.some((resolved) => resolved.clause.index === clause.index),\n )\n let planned: PlannerStageOutcome = NO_PLAN\n if (unmapped.length === 0) {\n // The tracer's path, and a permanent one: a fully canonical utterance is model-independent.\n await append({\n kind: 'stage_outcome',\n turnId,\n at: deps.now(),\n stage: 'planner',\n outcome: 'skipped',\n })\n } else if (deps.planner === undefined) {\n // Headless. Not a stub and not an error — a real host posture whose correct behaviour is\n // to refuse by name rather than to guess (D-08).\n await append({\n kind: 'stage_outcome',\n turnId,\n at: deps.now(),\n stage: 'planner',\n outcome: 'unresolved',\n })\n } else {\n planned = await deps.planner.plan({ utterance: input.message, clauses: unmapped, sessionId })\n await append({\n kind: 'stage_outcome',\n turnId,\n at: deps.now(),\n stage: 'planner',\n // The stage RESOLVED when the model produced something to reconcile — a plan, or an\n // answer. It did not when the model was unreachable or said nothing. Whether what it\n // produced survives reconciliation is the next stage's question, and answering it in\n // this field would make \"the model proposed nothing\" and \"the reconciler refused the\n // proposal\" the same bytes for every reader of the log.\n //\n // ONE TERM, NOT TWO: an `answer_only` call IS a tool call, so the disjunction this used to\n // spell (`|| planned.answer !== undefined`) named the same set twice through a projection\n // that no longer exists (392-14).\n outcome:\n planned.failure === undefined && planned.toolCalls.length > 0 ? 'resolved' : 'unresolved',\n })\n }\n\n // ---- Stage 3: deterministic reconciliation, BEFORE any side effect (D-10).\n const verdict = deps.reconcile({ clauses: routable, mapped, planned })\n await append({\n kind: 'stage_outcome',\n turnId,\n at: deps.now(),\n stage: 'reconcile',\n outcome: verdict.kind === 'execute' ? 'resolved' : 'unresolved',\n })\n if (verdict.kind === 'unhandled') {\n return refuse(verdict.clause.text, verdict.reason)\n }\n\n // ---- The directives' side effects, on the execute arm and NOWHERE ELSE (D-10, CR-04).\n //\n // Reachable only from here, by the same control-flow discrimination stage 4 uses: the verdict\n // is a discriminated union, the `unhandled` arm returned above, and this loop lives on the\n // other side of that return. There is no arrangement of these statements in which a model is\n // overridden on a turn that got refused. A handler that THROWS here — a `/model` this host cannot\n // resolve — still routes through `refuse()`, so a refusal at this depth stays as countable as any\n // other.\n //\n // AND THAT SENTENCE IS TRUE OF A BATCH ONLY BECAUSE OF THE PRE-FLIGHT ABOVE (392-14). Read\n // alone, this loop applies entries one at a time and returns on the first refusal — which is\n // precisely the arrangement it claims does not exist, one clause over. What removes it is that\n // every entry's `validate` has already been asked and none of them said no; the catch below is\n // the belt for a host that publishes no validate, and on such a host the batch claim holds only\n // for a single directive.\n //\n // TWO CONSEQUENCES, ACCEPTED. A same-turn `/model` now applies AFTER the verdict, so this\n // turn's planner call ran under the previous model; that is the fail-safe direction, and the\n // alternative is an effect preceding the verdict. And the verb-sourced `model_change` rows now\n // follow this turn's `stage_outcome` rows — every event carries\n // `turnId` and `at`, so no reader's ordering claim rests on which came first within a turn.\n const directiveLines: string[] = []\n for (const entry of directives) {\n const line = await runDirective(deps, directiveHandlers, entry, {\n turnId,\n sessionId,\n append,\n now: deps.now,\n })\n if (line.kind === 'refused') return refuse(entry.clause.text, line.reason)\n directiveLines.push(line.text)\n }\n\n /**\n * The PRE-DISPATCH write_test route (395-08, D-14/D-15 · CFGM-05).\n *\n * IT RUNS BEFORE THE AUTHORING DISPATCH AND NOT INSIDE IT, which is RESEARCH Pitfall 6's whole\n * point: the authoring loop's `AuthoringDraftUnconfiguredTargetError` is a BACKSTOP over what a\n * model emitted, and it fires after an LLM call and a compilation. This asks a different question,\n * about the REQUEST, and it asks it before anything is spent.\n *\n * 2026-09-30, 432-11 D-05/D-14: NO CONFIRM. The scaffold writes the configuration in its own\n * call, the receipt is shown where a surface exists, and control returns to the loop below, which\n * dispatches authoring in the same turn against the target that now exists.\n */\n async function routeWriteTest(\n engine: TurnEngineDeps,\n step: { readonly functionId: string; readonly args: unknown },\n caller: FunctionCaller,\n appendEvent: (event: ChatSessionEvent) => Promise<void>,\n turn: string,\n ): Promise<'proceed' | 'stop'> {\n const intent = (step.args as { intent?: unknown } | undefined)?.intent\n if (typeof intent !== 'string') return 'proceed'\n\n const route = resolveWriteTestRoute({\n intent,\n configuredTargetNames: await (engine.configuredTargets as () => Promise<readonly string[]>)(),\n })\n if (route.kind === 'configured' || route.kind === 'passthrough') return 'proceed'\n if (route.kind === 'refuse') {\n writeTestRefusal = WRITE_TEST_UNCONFIGURED_DETAIL\n return 'stop'\n }\n\n // OP CALLS OP (392 D-24), through the same binding every other dispatch crosses — so the\n // scaffold is audited and receipted exactly as a directly-asked-for one would be.\n //\n // 2026-09-30, 432-11 D-05/D-14: THE SCAFFOLD WRITES IN THIS CALL. There is no proposal to show\n // and no apply to ask about afterwards: the answer is what was written, and the route goes on\n // to author against it.\n let scaffolded: unknown\n try {\n scaffolded = (await engine.invoke(\n CONFIG_PROJECT_SCAFFOLD_FUNCTION_ID, { domain: route.domain }, caller,\n )).payload\n } catch (error) {\n writeTestRefusal = refusalMessage(error)\n return 'stop'\n }\n const answer = scaffolded as {\n outcome?: string\n detail?: string\n summaryLine?: string\n files?: readonly string[]\n shownDiff?: string\n crossBoundary?: boolean\n crossBoundaryReasons?: readonly string[]\n blockedReason?: string\n validationIssues?: readonly string[]\n path?: string\n }\n if (answer.outcome !== 'applied' || answer.files === undefined || answer.files.length === 0) {\n // A refusal, a blocked change, a no-change or an interrupted write: none is a configuration to\n // author a test against. 2026-10-03 (quick 261003-cpv, WR-03): each answers its own reason;\n // the no-configuration sentence was the fallback for the blocked and no-change arms, which\n // carry no `detail`.\n writeTestRefusal = writeTestScaffoldStopDetail(answer)\n return 'stop'\n }\n\n await appendEvent({\n kind: 'clause_receipt',\n turnId: turn,\n at: engine.now(),\n clause: step.functionId,\n functionId: CONFIG_PROJECT_SCAFFOLD_FUNCTION_ID,\n origin: caller.origin,\n status: 'executed',\n outcome: `applied: ${answer.files.join(', ')}`,\n })\n\n // THE RECEIPT, SHOWN WHERE A SURFACE EXISTS. The op's own summary, files and diff, never a\n // re-derivation. Best effort: the change is already on disk and nothing waits on this render,\n // so a surface that is absent or fails leaves the turn to continue.\n const present = engine.present\n if (present !== undefined) {\n try {\n await present(\n [\n ...crossBoundaryLines(answer),\n ...(answer.summaryLine === undefined ? [] : [answer.summaryLine]),\n ...answer.files,\n ...(answer.shownDiff === undefined ? [] : [answer.shownDiff]),\n ].filter((part) => part !== '').join('\\n'),\n )\n } catch {\n // The display is a receipt, not a gate; its failure contributes nothing to the turn.\n }\n }\n return 'proceed'\n }\n\n // ---- Stage 4: sequential execution in utterance order, stopping on failure (D-11).\n //\n // THE LOOP IS UNREACHABLE FROM A REFUSAL BY CONSTRUCTION, which is D-10 expressed as control\n // flow rather than as a check: the verdict is a discriminated union, the `unhandled` arm\n // returns above, and the plan this loop walks exists only on the other arm. There is no\n // ordering of these statements in which a side effect happens before the verdict, because\n // there is no plan to walk until the verdict has produced one.\n const receipts: ClauseReceipt[] = []\n // 399.1 (D-05): what the ops RETURNED, the sibling channel `receipts` was never allowed to be.\n // Appended inside the loop, so its order is the execution order — which is the utterance order\n // this engine preserves everywhere else — and its length is the number of clauses that ran.\n const results: ClauseResult[] = []\n /**\n * Whether some clause of this turn FAILED — the one fact the D-11 stop gate and the aggregate\n * below both read.\n *\n * ITS PRODUCER IS THE RECEIPT VOCABULARY, NOT THE ENDING (399.1-09, D-12). It was set in the\n * dispatch catch, so the only failure it could see was a thrown one — and every arm of a typed\n * refusal RETURNS. That is the same derivation RC-1b got wrong one layer down, and it stayed\n * wrong here after the receipt itself was fixed: a `failed` receipt sat under a `completed`\n * aggregate, the gate never tripped, and `ask` exited 0. It is derived at the push site below\n * now, from `receipt.status`, so a thrown failure and a returned one are one word to this loop.\n */\n let failed = false\n // 398-13 (D-21): what the ops PRODUCED, on its way to the turn's `answer` field. The receipt\n // charter is untouched — see the charter note at the push site below.\n const answerLines: string[] = []\n // The sentence the route wants a refused turn to carry, set by `routeWriteTest` before it answers\n // `stop`. A field rather than a return value so the refusal below reads as the one `refuse()` call\n // it is, and so a route that stopped without a reason still gets D-15's default sentence.\n let writeTestRefusal: string | undefined\n\n for (const step of verdict.plan) {\n // The mint follows the stage that PROVED the binding, which the verdict states (Pitfall 1).\n // Re-deriving it by matching the action back against the mapper set would answer `human`\n // for any planner-produced call to an op the table also knows, and the receipt would then\n // record a model-originated call as a person's (391 D-06, T-392-23). 2026-10-01 (432-20/21,\n // D-12): no op withholds anything by origin any more; the origin is attribution.\n const caller = deps.mint.forStage(step.source)\n let receipt: ClauseReceipt\n if (failed) {\n // `not-run` is a fact, not an absence: a person reading the receipt must be able to tell\n // a clause nobody attempted from one that was attempted and failed (D-11). It is LOGGED\n // like every other receipt, because \"the log is the triage report\" (D-18) is false the\n // moment the log carries only the clauses that got as far as a call.\n receipt = {\n clause: step.clause.text,\n functionId: step.functionId,\n origin: caller.origin,\n status: 'not-run',\n outcome: 'an earlier clause failed, so this one was never attempted',\n }\n } else if (\n step.functionId === AUTHORING_DRAFT_WRITE_FUNCTION_ID\n && deps.configuredTargets !== undefined\n && (await routeWriteTest(deps, step, caller, append, turnId)) === 'stop'\n ) {\n // THE ROUTE REFUSED: the project has no configuration and the scaffold did not write one.\n // Nothing is authored, and the turn says why through the same `refuse()` every other refusal\n // takes, so no draft is written against a project that still has none. (2026-10-03: nothing\n // is offered or declined since 432-13.)\n return refuse(step.clause.text, writeTestRefusal ?? WRITE_TEST_UNCONFIGURED_DETAIL)\n } else {\n try {\n // The result arrives CLASSIFIED (399.1, D-01/D-03/D-05). It used to arrive as `unknown`,\n // read by one id-matching summariser, and the status below was the literal `'executed'` — so\n // the only fact this receipt could report about a returning op was that it had returned.\n // Every arm of a typed refusal returns, which is how a credential-blocked config mutation\n // came to render `executed` in green over a file that was never written (G-399-2).\n const answered = await deps.invoke(\n step.functionId,\n stampSessionFacts(step.functionId, step.args, sessionId),\n caller,\n )\n receipt = {\n clause: step.clause.text,\n functionId: step.functionId,\n origin: caller.origin,\n // THE OP'S OWN VERDICT, not a derivation from how the call ended. Fail-closed upstream:\n // a fold that could not read its result answered `failed`, never `executed`.\n status: answered.verdict.status,\n // An empty outcome means the op's fold had nothing to add, and the line this engine has\n // always printed is the honest answer for it — the same line an op with no fold gets.\n outcome: answered.verdict.outcome === ''\n ? summarise(step.functionId)\n : answered.verdict.outcome,\n }\n // WHAT THE OP PRODUCED, ON THE CHANNEL D-05 GAVE IT. One entry per clause that ran, in\n // execution order, carrying the payload EXACTLY as the function layer returned it —\n // masked. Nothing restores a value here: this value reaches the session log and every\n // `agent.ask` client, and each surface's emit masks with the declared secrets.\n //\n results.push({ functionId: step.functionId, payload: answered.payload })\n // AND INTO THE RECORD, MASKED (399.1-05, D-05's persistence discretion resolved).\n //\n // WHY IT PERSISTS AT ALL. `results[]` is the turn's answer to \"what did the ops actually\n // return\", and 399's UAT rejected a chat surface that could not answer it. A session log\n // that carried only the receipt map would reproduce the same hole one layer down, in the\n // file D-18 calls the triage report — so the territory rides here beside its map.\n //\n // WHY VERBATIM AND NOT A DIGEST. A hash satisfies the disclosure guard trivially and gives\n // a reader nothing; the result is the turn's own territory and it is kept as filed.\n //\n // AND WHY NOTHING UNMASKS ON THE WAY. This is a DURABLE path. `answered.payload` is the\n // function layer's masked value and it is written exactly as it rode `results[]` — each\n // surface's emit masks with the declared secrets, and nothing restores a value into a\n // file. An unmasked entry here would mint a SECOND cleartext sink in\n // `.agent-qa/sessions/chat-*.jsonl`, which is the class\n // `.planning/phases/399.1-chat-render-contract/399.1-ADJUDICATION-transcript-cleartext.md`\n // adjudicates — inherited from 392 for two other fields, and a 399.1 DEFECT if this render\n // phase added a third.\n //\n // `?? null` IS THE JSON BOUNDARY, not a normalisation of the value: the adapter writes\n // JSONL, an `undefined` member serialises to an ABSENT KEY, and an absent key fails\n // `guardChatSessionEvent`'s exact-key check on reopen — so an op that returns nothing would\n // otherwise write a line this build cannot read back.\n await append({\n kind: 'clause_result',\n turnId,\n at: deps.now(),\n functionId: step.functionId,\n payload: answered.payload ?? null,\n })\n // THE RECEIPT CHARTER, WHICH SURVIVED THE MIGRATION THAT DELETED ITS OLD HOME (398-13 D-21,\n // moved here by 399.1-03). `explainAnswerLines` argued this seat at length and the argument\n // is unchanged by the fold arriving: THE RECEIPT STAYS THE MAP — the plain `<op> completed`\n // line, or the op's own one-line verdict — and the TERRITORY travels on this field, which\n // `renderTurn` already prints and `ask` already shares. A second carrier on the receipt\n // would put the answer inside the map, which is the prohibition `summarise` argues for.\n //\n // WHAT CHANGED IS ONLY WHO COMPOSES THE LINES. They used to be composed here, by comparing\n // `step.functionId` against one op's id and parsing that op's output — a render rule living\n // in the engine, which could only ever render what somebody had thought to name here. They\n // are composed now by the op's OWN declared `renderResult`, run at the composition root by\n // `foldFunctionResult`, and this site cannot tell which op produced them. That is the whole\n // of D-04's promote decision: this engine holds ZERO per-op render branches.\n //\n // PARSED, NEVER CAST, AND FAIL-OPEN, unchanged: a fold that throws or answers a non-list\n // renders NOTHING extra rather than anything invented, and the complete masked payload\n // reaches the person through `results[]` either way.\n answerLines.push(...answered.foldLines)\n } catch (error) {\n receipt = {\n clause: step.clause.text,\n functionId: step.functionId,\n origin: caller.origin,\n status: 'failed',\n outcome: refusalName(error),\n }\n const refusal = refusalSentenceOf(error)\n if (refusal !== undefined) answerLines.push(refusal)\n }\n }\n // THE ONE DERIVATION (399.1-09, D-12). Every receipt this loop mints passes here — the\n // catch's, the fold's, and the `not-run` the gate itself writes — so the flag reads the\n // vocabulary rather than the control flow, and the gate above and the aggregate below become\n // honest without either of them changing a line.\n //\n // ONLY `failed` MOVES IT. D-11's rule is stop-on-FAILURE and D-02 ruled a refusal is not one:\n // `clauseReachedCapability` already counts `refused` as an op that reached its capability and\n // came back, so stopping there would abandon the rest of a person's sentence over a control\n // that worked. `executed` and `not-run` are the other two words that must leave it alone.\n if (receipt.status === 'failed') failed = true\n receipts.push(receipt)\n await append({\n kind: 'clause_receipt',\n turnId,\n at: deps.now(),\n clause: receipt.clause,\n functionId: receipt.functionId,\n origin: receipt.origin,\n status: receipt.status,\n outcome: receipt.outcome,\n })\n }\n\n // The answer rides the completed turn (CHAT-01). A turn the model answered in prose reaches\n // here with an empty plan, so the loop above ran zero times and `receipts` is empty — which\n // is the assertion \"answering executes nothing\" is made of, rather than a claim about it.\n // The directive lines lead, because they are what the person asked for FIRST in the\n // utterance order this whole engine preserves, and because a `/model` confirmation printed\n // after the receipts of the clauses that ran under the old model would misreport which model\n // ran them.\n // 398-13 (D-21): directives lead (the existing law), then what the OPS produced, then the\n // planner's prose. An explain answer that reached nobody was XPLN-02's last unwired inch.\n const answer = [...directiveLines, ...answerLines, verdict.answer].filter(\n (line): line is string => line !== undefined && line !== '',\n )\n return finish(failed ? 'failed' : 'completed', {\n receipts,\n results,\n ...(answer.length === 0 ? {} : { answer: answer.join('\\n') }),\n })\n}\n\n/** The clause shape re-exported for composition roots that build a splitter. */\nexport type { ChatClause }\n","// The dotted-id ↔ provider-safe tool-name mapping (Phase 392 plan 04, RESEARCH Pitfall 8).\n//\n// Registry ids are a lowercase dot taxonomy — `runs.start`, `entities.resolve` (384 D-15) — and\n// several providers reject a tool name containing anything outside `[a-zA-Z0-9_-]`. So the planner\n// needs a rename, and the rename needs an INVERSE: what comes back from the model is a tool name,\n// and the only thing the function layer answers to is a function id.\n//\n// SPELLED ONCE, HERE. 396 projects the same registry onto MCP and will need the same rename; if it\n// spells its own, a capability's wire name depends on which surface asked, and the two are free to\n// drift the first time an id grammar changes. One module, both directions, property-tested over the\n// whole registry walk rather than over samples — a collision costs whichever single op happened to\n// collide, which is the one defect shape a sample cannot be relied on to contain (T-392-15).\n//\n// THE MAPPING IS TOTAL ON THE GRAMMAR IT ACCEPTS, AND REFUSES OUTSIDE IT. `.` ↔ `_` is a bijection\n// only while ids carry no underscore and no id maps onto a meta-tool name. Both conditions are\n// CHECKED rather than assumed, in both directions, because the failure they prevent is silent: a\n// tool call misdispatching to a capability nobody asked for.\n\n/** How a registry id separates its domain and verb (384 D-15). */\nconst FUNCTION_ID_SEPARATOR = '.'\n\n/** What a provider-safe tool name carries in its place. */\nconst TOOL_NAME_SEPARATOR = '_'\n\n/** The charset the mapping's output is required to stay inside. */\nconst PROVIDER_SAFE_TOOL_NAME = /^[a-zA-Z0-9_-]+$/\n\n/**\n * The refusal both directions raise. NAMED, because every other refusal this subtree publishes is:\n * a caller that catches it needs to be able to tell \"that name is not mappable\" apart from a\n * transport failure or a contract complaint.\n */\nexport class ChatToolNameError extends Error {\n constructor(readonly subject: string, detail: string) {\n super(`${subject}: ${detail}`)\n this.name = 'ChatToolNameError'\n }\n}\n\n/**\n * The model's answer for a turn it answers in prose (CHAT-01).\n *\n * A first-class action rather than the absence of one: a turn where the person asked a question\n * executes zero ops and returns text, so `the model planned nothing` has to stay distinguishable\n * against `the model answered` — two facts a reader of the log must be able to tell apart.\n *\n * (The backticks are not stylistic. `packages/arch`'s dependency lint reads every source line\n * looking for a specifier, and its pattern is one particular English word ahead of a quoted\n * phrase — so ordinary prose in that shape is reported as an undeclared package import. Two\n * sibling plans have already reddened `validate:arch` this way.)\n */\nexport const ANSWER_ONLY_TOOL_NAME = 'answer_only'\n\n/**\n * The model's answer for a clause no available tool can carry out (D-08).\n *\n * The capability is ABSENT from the registry — 393-395 have not shipped it — so it is absent from\n * the toolset, and this is how the model says so by name instead of improvising with something\n * adjacent. The turn then fails closed naming the clause, with zero executions (D-10).\n */\nexport const MARK_UNHANDLED_TOOL_NAME = 'mark_unhandled'\n\n/** The two orchestration tools, and no others. */\nexport const CHAT_META_TOOL_NAMES = [ANSWER_ONLY_TOOL_NAME, MARK_UNHANDLED_TOOL_NAME] as const\n\nexport type ChatMetaToolName = (typeof CHAT_META_TOOL_NAMES)[number]\n\n/** Whether a tool name belongs to orchestration rather than to a registered capability. */\nexport function isChatMetaToolName(name: string): name is ChatMetaToolName {\n return (CHAT_META_TOOL_NAMES as readonly string[]).includes(name)\n}\n\n/**\n * A registry id, as the provider-facing tool name.\n *\n * Two refusals, and each closes a way the inverse could stop being an inverse:\n *\n * 1. An id already carrying the separator this maps ONTO has two pre-images under the reverse\n * mapping. There is no honest answer to which one it came from, so there is no name for it.\n * 2. An id whose projected name collides with a meta-tool would make an orchestration call and a\n * capability call the same bytes on the wire. `answer.only` is a perfectly plausible future op\n * id, which is exactly why this is a check and not an observation.\n */\nexport function toToolName(functionId: string): string {\n if (functionId.includes(TOOL_NAME_SEPARATOR)) {\n throw new ChatToolNameError(\n functionId,\n `a function id may not contain \"${TOOL_NAME_SEPARATOR}\" — the provider-safe tool name uses `\n + 'it as the separator, so such an id would have two pre-images under the reverse mapping '\n + 'and a tool call could dispatch to a capability nobody asked for',\n )\n }\n const name = functionId.replaceAll(FUNCTION_ID_SEPARATOR, TOOL_NAME_SEPARATOR)\n if (isChatMetaToolName(name)) {\n throw new ChatToolNameError(\n functionId,\n `projects onto the orchestration tool \"${name}\", which would make a capability call and an `\n + 'orchestration call indistinguishable in the model plan',\n )\n }\n if (!PROVIDER_SAFE_TOOL_NAME.test(name)) {\n throw new ChatToolNameError(\n functionId,\n `projects to \"${name}\", which is outside the provider-safe tool-name charset`,\n )\n }\n return name\n}\n\n/**\n * A provider-facing tool name, back as the registry id the function layer answers to.\n *\n * A meta-tool name is REFUSED rather than reversed: `answer_only` would come back as `answer.only`,\n * a well-formed id in a taxonomy that could one day hold it. A caller reading a model plan checks\n * {@link isChatMetaToolName} first; this refusal is what makes forgetting to a failure rather than\n * a silent dispatch.\n *\n * A name that reverses to an id nothing registered is NOT refused here, and that is deliberate:\n * `invokeFunction` raises `UnknownFunctionError` naming it, from the one place that knows what is\n * registered. A check here would be a second catalogue, free to disagree with the real one.\n */\nexport function fromToolName(toolName: string): string {\n if (isChatMetaToolName(toolName)) {\n throw new ChatToolNameError(\n toolName,\n 'is an orchestration tool, not a capability — it names no registry op, and reversing it '\n + 'would manufacture a plausible-looking function id out of a control signal',\n )\n }\n return toolName.replaceAll(TOOL_NAME_SEPARATOR, FUNCTION_ID_SEPARATOR)\n}\n","// Stage 3 — deterministic reconciliation (Phase 392, D-09 / D-10 / D-11 / D-12 / D-16).\n//\n// THE FILE IS A TOTAL FUNCTION FROM TWO PROPOSALS TO ONE VERDICT, and every clause of the utterance\n// leaves it accounted for: bound by the table, bound by the model, answered in prose, or naming the\n// refusal that costs the whole turn. There is no fifth outcome and no path on which a clause simply\n// stops being mentioned — a silently dropped clause is T-392-25, and the only structural defence\n// against it is a merge that walks the CLAUSES rather than either proposal.\n//\n// D-12, PRECISELY. Wherever the table resolved a clause, the mapper's `{ functionId, args }` is the\n// verdict — the model's call for that same clause is discarded whole, target and arguments alike\n// (\"run test 42\" with the model planning TST-999 executes TST-42). That is two claims and they fail\n// independently, so the suite asserts them apart: the ACTION SET (how many, and which) and the\n// BOUND ARGUMENTS. A reconciler that honoured the first and not the second would run the right op\n// against the wrong entity, which is the more dangerous half.\n//\n// D-09'S PRECISION CLAUSE IS WHAT LIMITS THE OVERRIDE. Only EXACT table resolutions participate:\n// `mapped` carries what stage 1 proved at confidence 1.0, and nothing else may ever be added to it,\n// because an overriding path that false-positived would beat a correct model plan with a wrong\n// guess. Everything fuzzy stays on the model's side of the merge, where it is one proposal among\n// others rather than a verdict.\n//\n// WHAT IS ALREADY FINAL HERE IS THE ATOMICITY (D-10). Reconciliation returns before any side effect\n// exists, so an unhandled clause costs the turn everything and executes nothing. That is not an\n// optimisation of the failure path; it is the property `compound/` scenarios assert as\n// `executed == 0`, and a strategy that let earlier clauses run before discovering a later\n// unroutable one would make that assertion unwritable.\n//\n// THE STRATEGY IS PURE: a verdict in, a verdict out, no clock, no filesystem, no model. That purity\n// is what makes D-16's mutation proof meaningful — the differential composes the REAL host twice\n// with two strategies and reads the difference off a named scenario, and it can only do that\n// because swapping this function changes nothing else about the assembled system.\n\nimport type {\n ChatClause,\n ClauseAction,\n PlannerToolCall,\n ReconcileInput,\n ReconcileStrategy,\n ReconcileVerdict,\n ResolvedClause,\n} from './ports.js'\nimport {\n ANSWER_ONLY_TOOL_NAME,\n MARK_UNHANDLED_TOOL_NAME,\n fromToolName,\n isChatMetaToolName,\n} from './tool-names.js'\n\n/**\n * The refusal sentence a fail-closed turn carries.\n *\n * It NAMES the clause (D-08). A message that said only \"I could not do that\" would leave a person\n * unable to tell which half of a compound request was refused, and would make a silent drop and a\n * loud refusal read identically in the log.\n */\nexport function unhandledReason(clause: string): string {\n return (\n `No capability in this build handles: \"${clause}\". The turn was refused before anything ran, `\n + 'so nothing in the request was carried out.'\n )\n}\n\n/**\n * The refusal sentence a turn carries when the MODEL said the clause cannot be done (D-08).\n *\n * D-08's clause-naming law holds, and this adds the ATTRIBUTION law beside it: model prose reaches\n * the person only as the planner's quoted claim, never as a fact this host asserts.\n *\n * The reason is not a defensive one. `reason` is untrusted model output — `modelMarkedUnhandled`\n * reads it off a tool call exactly as it reads the clause — and until this round it was spliced\n * bare after an em-dash, immediately behind a clause the host composed. The two halves then read as\n * one host statement with nothing marking where the host stopped speaking. 394-30 measured what\n * that costs on a real turn: a live planner refused an authoring request with \"it requires a target\n * scope identifier and none was supplied\", a phrase in no source file in this repo, describing a\n * requirement the op's own contract denies (`required: [\"intent\"]`). The person was told a false\n * fact about this build, in this build's voice, and had no way to tell the host had not said it.\n *\n * The host can only assert what it can check. It cannot check the planner's prose; what it CAN\n * check is that the planner said it — so saying so is the whole of the claim it makes about it.\n * The tail is still shown in full rather than dropped, because the planner's stated reason is\n * often the only thing that tells a person what to try next.\n *\n * THE DELIMITERS MUST BE ONES THE PAYLOAD CANNOT SPELL (394-37, WR-03), and the first version of\n * this fix used ones it could. `reason` was spliced between bare `\"` characters — the single most\n * likely character for a planner's prose to contain — and followed by a fixed sentence the model\n * can read in its own tool description. A planner emitting\n * `X\". The turn was refused before anything ran, so nothing in the request was carried out. This\n * build requires …` closed the attribution after `X` and left its own claim standing after the\n * host's atomicity sentence, in the host's voice: 394-30's defect, restored through the fix meant\n * to close it. `JSON.stringify` escapes the quote AND the newline a multi-line payload would use\n * to leave the quoted span, so there is no byte sequence the model can emit that ends the\n * quotation early — while the tail is still shown whole.\n *\n * AND THE HOST FINISHES SPEAKING BEFORE THE QUOTATION OPENS. The attribution moved to the END for\n * the same reason the escaping was needed: with the host's own two claims — which clause, and that\n * nothing ran — both made before any model byte appears, there is no host sentence AFTER the\n * quotation for a crafted payload to impersonate by running on into it.\n */\nexport function modelUnhandledReason(clause: string, reason: string): string {\n return (\n `No capability in this build handles: \"${clause}\". The turn was refused before anything ran, `\n + 'so nothing in the request was carried out.\\n'\n + `The planner's stated reason, unverified by this build: ${JSON.stringify(reason)}`\n )\n}\n\n/**\n * The refusal sentence a turn carries when the model's plan cannot be attributed to its clauses.\n *\n * AN ACTION CALL CARRIES NO CLAUSE. The model emits `runs_start {…}`, not \"runs_start, for the\n * second half of what you asked\" — so when it makes more action calls than there are clauses\n * needing one, NOTHING in the output says which clause each call was about. Binding them by\n * position is a guess, and the guess is wrong exactly when the model made a call about a clause the\n * TABLE already resolved (392-VERIFICATION round 3, CR-01): the surplus call shifted every later\n * binding, so a clause that asked for a digest ran a test with the model's own arguments and its\n * real intent left no row at all, on a turn the person was told completed.\n *\n * So the sentence states the DISAGREEMENT rather than inventing a cause. It names a clause (D-08)\n * and it says what could not be done with the plan, because \"no capability handles this\" would be\n * false here — a capability does handle it, and the reason nothing ran is that nobody can tell\n * which call was for it.\n */\nexport function unattributablePlanReason(\n clause: string,\n proposed: number,\n needed: number,\n): string {\n return (\n `The plan proposed ${String(proposed)} actions for ${String(needed)} clauses that needed one, `\n + `so no call could be attributed to \"${clause}\". The turn was refused before anything ran, `\n + 'so nothing in the request was carried out.'\n )\n}\n\n/** The refusal sentence a turn carries when stage 2 could not reach the model at all. */\nexport function plannerFailedReason(clause: string, failure: { name: string }): string {\n return (\n `The planner could not be reached (${failure.name}), so \"${clause}\" was never routed. `\n + 'The turn was refused before anything ran.'\n )\n}\n\n/**\n * Read the model's own fail-closed signal off its plan (D-08).\n *\n * `mark_unhandled` is a tool call like any other, so this is a read of untrusted output: the clause\n * text it names is used to CHOOSE which clause the refusal is about, by matching what the splitter\n * produced, and never as the refusal's subject directly. A model that names a clause nobody typed\n * still refuses the turn — the first unmapped clause is the honest subject then — because a plan\n * containing this call is a plan whose author said it could not be completed.\n */\nfunction modelMarkedUnhandled(\n input: ReconcileInput,\n): { clause: string; reason: string } | undefined {\n for (const call of input.planned.toolCalls) {\n if (call.toolName !== MARK_UNHANDLED_TOOL_NAME) continue\n const body = (typeof call.input === 'object' && call.input !== null ? call.input : {}) as {\n clause?: unknown\n reason?: unknown\n }\n return {\n clause: typeof body.clause === 'string' ? body.clause : '',\n reason: typeof body.reason === 'string' ? body.reason : 'no capability for it has shipped.',\n }\n }\n return undefined\n}\n\n/** One `answer_only` call that survived the coverage predicate: the clause it names, and its prose. */\ninterface AnsweredClaim {\n readonly clause: string\n readonly text: string\n}\n\n/**\n * The model's `answer_only` calls that actually ANSWER something (CR-03, and 392-14's tightening).\n *\n * A CLAIM COVERS THE CLAUSE IT NAMES AND NO OTHER, matched against what the splitter produced —\n * which is the same read `modelMarkedUnhandled` performs on `mark_unhandled`, with one deliberate\n * difference: THERE IS NO FALLBACK HERE. `mark_unhandled`'s fallback to \"the first unmapped clause\"\n * is fail-SAFE, because a model whose claim matches nothing still refuses more than it otherwise\n * would. An answer-coverage fallback would be fail-DANGEROUS in exactly the mirror direction: it\n * completes more, and what it completes is a clause nobody bound and nobody answered. That\n * asymmetry is why a claim naming text no one typed covers nothing at all, and why a call with no\n * `clause` field — the shape this tool had before the field was required — covers nothing either.\n *\n * AND IT MUST ALSO SAY SOMETHING. Naming a clause was made necessary and left sufficient, so\n * `{clause: \"delete the knowledge root\", text: \"\"}` — schema-valid until this round, naming a\n * clause the person really typed — consumed that clause and returned a `completed` turn with no\n * receipt, no refusal and no mention of it anywhere in the result (392-VERIFICATION round 2, E1).\n * A claim is coverage only when it names a clause AND carries prose, and the predicate here is one\n * notch stricter than the schema's `min(1)`: whitespace-only prose fails, because a space is not\n * an answer and the fail-safe direction is to refuse.\n *\n * AN ORDERED MULTISET, NOT A SET. `mapped` is keyed by clause INDEX; a set of clause TEXT let one\n * claim speak for every occurrence of a repeated clause (\"run test 42 and run test 42\", answered\n * once, both covered). The list below is consumed one entry per clause during the merge walk, so a\n * claim covers exactly one occurrence and the two halves of the merge agree about what identifies\n * a clause.\n */\nfunction answeredClauseClaims(input: ReconcileInput): AnsweredClaim[] {\n const claims: AnsweredClaim[] = []\n for (const call of input.planned.toolCalls) {\n if (call.toolName !== ANSWER_ONLY_TOOL_NAME) continue\n const body = (typeof call.input === 'object' && call.input !== null ? call.input : {}) as {\n clause?: unknown\n text?: unknown\n }\n if (typeof body.clause !== 'string' || body.clause === '') continue\n if (typeof body.text !== 'string' || body.text.trim() === '') continue\n claims.push({ clause: body.clause, text: body.text })\n }\n return claims\n}\n\n/**\n * The model's ACTION proposals, in the order it made them.\n *\n * The two orchestration calls are removed here and nowhere else. They are not proposals about what\n * to run — one answers the turn and the other refuses it — and {@link fromToolName} THROWS on both\n * by design, so a merge that reversed every call without checking would crash on precisely the two\n * calls that matter most. Filtering by the published predicate rather than by a local name test is\n * what keeps that check from being re-derived a third time.\n */\nfunction actionCalls(input: ReconcileInput): readonly PlannerToolCall[] {\n return input.planned.toolCalls.filter((call) => !isChatMetaToolName(call.toolName))\n}\n\n/** What one clause turned out to be, decided once and read by everything below. */\ntype ClauseDisposition =\n | { readonly kind: 'mapped'; readonly clause: ChatClause; readonly resolved: ResolvedClause }\n | { readonly kind: 'answered'; readonly clause: ChatClause; readonly text: string }\n | { readonly kind: 'needs'; readonly clause: ChatClause }\n\n/**\n * The deterministic override: what the table proved beats what anything else proposed.\n *\n * The mapped set is indexed by CLAUSE INDEX rather than by matching text, and that is the D-12\n * mechanism in miniature: the clause's position is its identity, so a planner entry for a clause\n * the table already resolved cannot displace the mapper's binding no matter how the model spelled\n * it.\n *\n * THE COUNTS MUST AGREE BEFORE ANYTHING BINDS. Every clause gets exactly one disposition —\n * mapped, answered, or needing a proposal — and the number of action calls the model made is\n * compared against the number of clauses in that third group. That comparison is the ONE place a\n * count disagreement is decided, and it happens between the passes, before a single binding exists:\n * a disagreement refuses the turn BY NAME (D-08) rather than shifting the alignment by one, so the\n * materialize walk below has no refusal arm at all. The count and the set it is compared against\n * come from the same pass, because a second predicate computing \"which clauses need a proposal\"\n * would be free to drift from the one the binder walks.\n *\n * WHEN NO CLAUSE NEEDS A PROPOSAL nothing can be mis-bound — no call is popped by anybody — and\n * the calls are discarded whole. This is a CHOICE, not an absence of alternatives: through the\n * engine there is always a clause a refusal could name here, because stage 2 is skipped entirely\n * when every clause is mapped (`turn-engine.ts`), so a non-empty proposal list beside an empty\n * needy list means at least one clause was ANSWERED. Naming it is available and is not taken. The\n * asymmetry this file has always had is what decides it: the model may lose a proposal, and the\n * person may never lose a request. A clause that was answered did not lose its request — its prose\n * reaches the person — so the discarded call costs the model, not the person. Ratified 2026-08-10\n * against the alternative of refusing by name, which would move this case and cost every such turn\n * a refusal instead of an answer.\n */\nexport const deterministicOverrideStrategy: ReconcileStrategy = (\n input: ReconcileInput,\n): ReconcileVerdict => {\n const mappedByIndex = new Map(input.mapped.map((resolved) => [resolved.clause.index, resolved]))\n\n // The model's own refusal is checked BEFORE the plan is assembled, because a turn one of whose\n // clauses cannot be done is refused whole (D-10) — including the clauses the table did resolve.\n // Assembling first and discarding after would put a plan and a refusal in the same code path,\n // which is how a partially-executed compound turn eventually gets written.\n const marked = modelMarkedUnhandled(input)\n if (marked !== undefined) {\n const named =\n input.clauses.find((clause) => clause.text === marked.clause)\n ?? input.clauses.find((clause) => !mappedByIndex.has(clause.index))\n ?? input.clauses[0]\n if (named !== undefined) {\n return {\n kind: 'unhandled',\n clause: named,\n reason: modelUnhandledReason(named.text, marked.reason),\n }\n }\n }\n\n const proposed = actionCalls(input)\n // Consumed by `takeClaimFor` as the disposition pass goes: what is left at the end are the claims\n // that named nothing the person typed, and they cover nothing.\n const claims = answeredClauseClaims(input)\n\n /** Pop the FIRST unconsumed claim naming this clause text, or nothing. One claim, one clause. */\n const takeClaimFor = (text: string): string | undefined => {\n const index = claims.findIndex((claim) => claim.clause === text)\n if (index === -1) return undefined\n return claims.splice(index, 1)[0]?.text\n }\n\n // ---- PASS 1: DISPOSITION. Every clause becomes exactly one of three things, and no proposal is\n // spent and no refusal is issued here.\n //\n // THE ORDER OF THE THREE QUESTIONS IS THE MECHANISM: mapped → answered → needs a proposal.\n //\n // The coverage question used to sit BELOW the proposal consumption, and that one statement's\n // position produced two opposite user-visible defects from the same input shape (392-VERIFICATION\n // round 2). \"What is a flake and summarise the last failure\" with the plan the prompt itself asks\n // for — one `answer_only` for clause 1, one action call for clause 2 — bound the action to the\n // ANSWERED clause, so with two action calls a tool ran against a clause the model had marked\n // answer-only and every receipt named the wrong clause; and with one action call the second\n // clause found no proposal left and the WHOLE TURN was refused by name, naming the clause the\n // model had actually bound. Asking coverage first costs nothing and removes both.\n //\n // MAPPED STILL TAKES PRECEDENCE OVER A CLAIM, so a claim naming a clause the table bound is not\n // consumed and does not reduce the count below. A claim that could shrink the needy set for a\n // clause it was never going to answer would let the model turn an equality into a whole-discard\n // and silently unbook the clause it did plan for.\n const dispositions: ClauseDisposition[] = []\n const needy: ChatClause[] = []\n for (const clause of input.clauses) {\n const resolved = mappedByIndex.get(clause.index)\n if (resolved !== undefined) {\n dispositions.push({ kind: 'mapped', clause, resolved })\n continue\n }\n // An unresolved clause is answered by prose or it is not answered at all — and \"answered\" is a\n // claim about THIS clause, quoted and non-empty, rather than about the turn (CHAT-01, CR-03).\n // The line this replaced read `if (input.planned.answer !== undefined) continue`, which let one\n // model-emitted answer consume every clause the merge had no binding for: \"run test 42 and\n // delete the knowledge root\", answered once, completed with the second clause erased.\n const answered = takeClaimFor(clause.text)\n if (answered !== undefined) {\n dispositions.push({ kind: 'answered', clause, text: answered })\n continue\n }\n dispositions.push({ kind: 'needs', clause })\n needy.push(clause)\n }\n\n // ---- THE ACCOUNTING: the ONE site where a count disagreement is decided, between the passes and\n // before any binding exists. Both numbers come from the same pass above (D-10, CR-01).\n //\n // DEFICIT — fewer calls than clauses needing one. Byte-for-byte what it always did: it names the\n // clause the supply exhausts at, with the sentence the posture chooses (an unreachable planner\n // says so; anything else says no capability handles it). A person may never lose a request.\n const exhaustedAt = proposed.length < needy.length ? needy[proposed.length] : undefined\n if (exhaustedAt !== undefined) {\n return input.planned.failure !== undefined\n ? {\n kind: 'unhandled',\n clause: exhaustedAt,\n reason: plannerFailedReason(exhaustedAt.text, input.planned.failure),\n }\n : { kind: 'unhandled', clause: exhaustedAt, reason: unhandledReason(exhaustedAt.text) }\n }\n // SURPLUS — more calls than clauses needing one, with at least one clause needing one. `needy[0]`\n // is undefined exactly when nothing needs a proposal, which is the whole-discard case: no call\n // can be popped by anybody, so nothing is mis-bound. A subject to refuse about does exist there\n // (an ANSWERED clause — see the header); discarding rather than refusing is the ratified choice,\n // not a consequence of having nobody to name.\n const unattributable = proposed.length > needy.length ? needy[0] : undefined\n if (unattributable !== undefined) {\n return {\n kind: 'unhandled',\n clause: unattributable,\n reason: unattributablePlanReason(unattributable.text, proposed.length, needy.length),\n }\n }\n\n // ---- PASS 2: MATERIALIZE. The counts agree by construction now — either they were equal or\n // nothing needs a proposal — so this contains NO refusal arm and cannot.\n //\n // The pairing is by position and it is spelled once: the i-th proposal belongs to the i-th clause\n // that needs one. A proposal past the end of `needy` has no clause to belong to and is discarded\n // here, which is the only place in this file a call is ever dropped.\n const plannerBound = new Map<number, ClauseAction>()\n proposed.forEach((proposal, position) => {\n const clause = needy[position]\n if (clause === undefined) return\n plannerBound.set(clause.index, {\n clause,\n // The id the function layer answers to. An id nothing registered is NOT checked here —\n // `invokeFunction` raises `UnknownFunctionError` naming it, from the one place that knows\n // what is registered, and a check here would be a second catalogue free to disagree.\n functionId: fromToolName(proposal.toolName),\n // Carried across UNVALIDATED and unshaped. What validates a tool call's arguments is the\n // op's own live schema inside `invokeFunction`; a shape enforced here would be a second\n // validator standing in front of the real one.\n args: proposal.input,\n source: 'planner',\n })\n })\n\n const plan: ClauseAction[] = dispositions.flatMap((disposition) =>\n disposition.kind === 'mapped'\n // The override, in one line: the table's binding, tagged with the stage that proved it so the\n // engine mints a human caller for it. Nothing the model proposed is consulted for this clause.\n ? [{ ...disposition.resolved, source: 'resolver' as const }]\n : disposition.kind === 'needs'\n ? (plannerBound.get(disposition.clause.index) ?? [])\n // An answered clause contributes prose rather than an action; it is accounted for below.\n : [],\n )\n const answers: string[] = dispositions.flatMap((disposition) =>\n disposition.kind === 'answered' ? [disposition.text] : [],\n )\n // Utterance order, preserved (D-11): order is meaning, and later clauses routinely depend on\n // earlier ones. Both walks above go over `dispositions`, which pass 1 built by walking `clauses`\n // rather than either resolution set, precisely so a planner that answered out of order cannot\n // reorder what runs.\n //\n // THE PROSE IS THE CONSUMED CLAIMS', AND ONLY THEIRS. It used to be `input.planned.answer` — the\n // FIRST `answer_only` call's text, projected by `readBackPlan` — while the prompt and the tool\n // description had already been moved to \"ONE CALL PER CLAUSE you are answering\". So a turn\n // answering two questions accounted for both clauses and handed the person one answer, with the\n // other silently dropped (392-VERIFICATION round 2, path (4)). Building it here from what the\n // merge actually consumed is what makes the accounting checkable: the answers a person reads are\n // exactly the claims that covered a clause, in the order they typed them. That producer-side\n // projection is now gone entirely, so there is one prose path rather than two that can disagree.\n return answers.length === 0\n ? { kind: 'execute', plan }\n : { kind: 'execute', plan, answer: answers.join('\\n') }\n}\n\n// The tracer's whole-utterance splitter USED TO LIVE HERE and is gone as of plan 02, because the\n// seam it was holding open is now filled: `chat/clause-split.ts` is the real conjunction grammar\n// and the composition root binds it. Keeping the one-clause version around as a published symbol\n// would leave two answers to \"how is an utterance split\" in the barrel, with only one of them\n// bound — which is precisely the second-vocabulary failure this subtree is written to avoid. A\n// differential that wants a null splitter can spell one inline; that is a test's need, not a\n// production surface.\n","// The deterministic conjunction grammar (Phase 392, D-09 / RESEARCH Pitfall 5).\n//\n// One utterance in, the clauses a person meant out. This is stage 1's other half: the closed\n// resolver table decides what a clause MEANS, and this file decides what a clause IS. Both are\n// deterministic and both are capped, because the mapper they feed OVERRIDES a model's plan (D-12)\n// and an overriding path with a false-positive rate is worse than no overriding path at all.\n//\n// IT IS A CHARACTER SCAN, NOT A REGEX SPLIT, and that is the whole reason the module exists rather\n// than one line at the call site. `utterance.split(/ and |;|,/)` passes every simple case and then\n// tears `write a test for \"add and remove items\"` into two clauses, the second of which no\n// capability handles — so the turn fails closed, loudly, on a request that was never compound.\n// That is not a cosmetic bug: CHAT-03 measures the `mark_unhandled` rate over the frozen corpus,\n// and a splitter that manufactures phantom clauses inflates the very number the ceiling exists to\n// hold down (RESEARCH Pitfall 5). Quote state is therefore explicit and the scan is character-wise.\n//\n// RECONCILIATION RUNS UNIFORMLY ON SINGLE-CLAUSE TURNS. A one-clause utterance is a compound of\n// one, and it takes the identical path through stages 2-4. There is no fast lane, because a fast\n// lane is a second implementation of the turn contract that nothing keeps in step with the first.\n//\n// A STYLE MODIFIER IS NOT A REQUEST, AND SPLITTING ONE OFF MANUFACTURES A PHANTOM CLAUSE (392-16,\n// G-392-1). `in one sentence, what does it mean to call a test flaky?` is one question with an\n// instruction about the FORM of the answer, and the separator between them is a real one. Split\n// into two clauses, `in one sentence` is a clause no capability handles and the model has to claim\n// back byte-for-byte through `answer_only`; miss that claim and, with zero action calls, the\n// deficit arm refuses the WHOLE turn with a sentence asserting nothing handles a clause the model\n// in fact addressed. It is the same failure Pitfall 5 above names, arriving through the separator\n// set instead of through a regex: a phantom clause inflates the very CHAT-03 `mark_unhandled`\n// number the ceiling exists to hold down (measured: 2 of 5 live runs at 1/3 against a 1/5 ceiling).\n// So a piece that is EXACTLY one of the pinned {@link STYLE_MODIFIER_PHRASES} is elided, on the\n// same terms as an empty piece — and never to zero clauses.\n\nimport type { ChatClause } from './ports.js'\n\n/**\n * The closed separator set.\n *\n * A PINNED CONSTANT, never config (386 D-15). RETUNE COMMENT: these four are the separators a\n * person actually types between two requests in one breath. Widening the set is a real decision\n * with a real cost — every token added is a token that can now split a clause that meant one\n * thing, and the failure is silent in the direction that matters (a phantom clause reads as a\n * refusal of something the person never asked for). Add a token only with a scenario that shows\n * the utterance it rescues, and re-run the ceiling measurement afterwards.\n *\n * The word tokens carry their own whitespace, which IS the word-boundary rule: ` and ` cannot\n * match inside `sandbox` or `android` because neither has a space where the token needs one. A\n * separate boundary check would be a second answer to a question the token spelling already\n * answers, free to disagree with it.\n *\n * Order is the order the scanner tries them. It is not load-bearing today — no token is a prefix\n * of another — and it is written longest-first anyway so that it stays not load-bearing.\n */\nexport const CONJUNCTION_TOKENS = [' and ', ' then ', ';', ','] as const\n\n/**\n * The closed style-modifier set (392-16, G-392-1).\n *\n * THE INCLUSION CRITERION: a phrase that, STANDING ALONE AS A WHOLE PIECE, instructs the FORM of\n * the answer and names no capability, no entity and no action this build has or could ever have.\n * `in one sentence` qualifies; `summarise the last failure` does not, and neither does anything\n * that could one day become an op.\n *\n * A PINNED CONSTANT, never config (386 D-15). RETUNE COMMENT: every phrase added here is a phrase\n * that can now be DROPPED from a request, and a dropped request is the silent failure this file's\n * header decides against everywhere else. So add one only with a case that shows the utterance it\n * rescues, re-run the ceiling measurement afterwards, and never write a pattern or a regex in place\n * of a member — a pattern would reach into `briefly explain the flake`, which is a real request\n * that merely begins with a member.\n *\n * Order is alphabetical and is NOT load-bearing: the set is read by exact membership, never\n * scanned in sequence.\n */\nexport const STYLE_MODIFIER_PHRASES = [\n 'briefly',\n 'concisely',\n 'in a sentence',\n 'in brief',\n 'in one sentence',\n 'in short',\n 'in two sentences',\n] as const\n\n/**\n * Whether a surviving piece is a style modifier and nothing else.\n *\n * EXACT on the whole trimmed piece, case-insensitively — the same case discipline `separatorAt`\n * applies, for the same reason. Not a prefix test and not a substring test: `briefly explain the\n * flake` begins with a member and is a request. Quote characters are part of a piece's text, so a\n * quoted `\"briefly\"` is not a member either, which is the behaviour the quote-protection rule\n * above already promises.\n */\nfunction isStyleModifier(text: string): boolean {\n return (STYLE_MODIFIER_PHRASES as readonly string[]).includes(text.toLowerCase())\n}\n\n/** The quote characters that protect a span. Both, because people type both. */\nconst QUOTE_CHARACTERS = ['\"', \"'\"] as const\n\ntype QuoteCharacter = (typeof QUOTE_CHARACTERS)[number]\n\nfunction isQuoteCharacter(character: string): character is QuoteCharacter {\n return (QUOTE_CHARACTERS as readonly string[]).includes(character)\n}\n\n/**\n * The bracket pairs that protect a span, the way a quote pair does (2026-08-16, Phase 397 plan 04).\n *\n * WHY A SECOND KIND OF PROTECTED SPAN EXISTS. `/help` advertises `/fn <op> [json]` as \"invoke any\n * registered function by id — every capability, one branch\", and D-06 rests the thin table's whole\n * argument on that claim. A JSON object with more than one member carries a STRUCTURAL comma, and\n * that comma is outside every quoted span by construction — it sits between one value's closing\n * quote and the next key's opening one. `,` is a pinned separator, so\n * `/fn config.target.create {\"name\":\"shop\",\"platform\":\"web\",\"url\":\"…\"}` was torn into three pieces,\n * none of which parses as `/fn`'s body, and a person who typed exactly what the help text told them\n * to type was answered \"No capability in this build handles …\". Measured over Phase 397's scenario\n * table: 14 of the 41 registered capabilities have an input whose smallest valid JSON encoding\n * carries a structural comma, so for a third of the catalogue the reach lever did not reach.\n *\n * IT ADDS NO TOKEN AND REMOVES NONE. {@link CONJUNCTION_TOKENS} is untouched; what changes is where\n * a token is looked for, which is the same change quote protection already makes. The asymmetry is\n * the file head's: an unquoted bracket in English prose is rare and costs at most a clause that\n * could have been split, while the alternative manufactures a phantom clause and a spurious refusal\n * on a documented, deterministic route. Pitfall 5 says which way to be wrong.\n *\n * QUOTE STATE WINS. A bracket INSIDE a quoted span is a character in a sentence, not the start of a\n * document, so it never opens a depth — otherwise `write a test for \"the { key\" and status` would\n * swallow its own conjunction.\n */\nconst BRACKET_PAIRS: Readonly<Record<string, string>> = Object.freeze({ '{': '}', '[': ']' })\n\nconst CLOSING_BRACKETS: readonly string[] = Object.freeze(Object.values(BRACKET_PAIRS))\n\n/**\n * The separator starting at `at`, or nothing.\n *\n * Case-insensitive on the word tokens, because `run X AND status` is the same request as its\n * lowercase twin and a person typing at a prompt is not thinking about case.\n */\nfunction separatorAt(utterance: string, at: number): string | undefined {\n const lowered = utterance.toLowerCase()\n for (const token of CONJUNCTION_TOKENS) {\n if (lowered.startsWith(token, at)) return token\n }\n return undefined\n}\n\n/**\n * Split one utterance into the clauses stage 1 routes.\n *\n * Pure, total and host-free: no clock, no config, no I/O, and no input throws. An unterminated\n * quote is not an error a person should have to hear about — it protects to end-of-utterance,\n * which over-protects (one clause where two were meant) rather than under-protects (a phantom\n * clause and a spurious refusal). Pitfall 5 says which way to be wrong. An unterminated BRACKET\n * gets the identical answer for the identical reason (see {@link BRACKET_PAIRS}).\n *\n * Empty pieces are elided rather than preserved, so `status,,proposals` and `status, proposals`\n * are the same request. A clause whose text is empty could name nothing in a refusal, and D-08\n * requires that a fail-closed turn name what it could not do.\n */\nexport function splitClauses(utterance: string): readonly ChatClause[] {\n const pieces: string[] = []\n let current = ''\n let openQuote: QuoteCharacter | undefined\n let bracketDepth = 0\n let at = 0\n\n while (at < utterance.length) {\n const character = utterance[at]!\n\n if (openQuote !== undefined) {\n // Inside a quoted span nothing separates. The closing quote is kept in the clause text\n // because the text is what a refusal quotes back and what an arg parser reads.\n current += character\n if (character === openQuote) openQuote = undefined\n at += 1\n continue\n }\n\n if (isQuoteCharacter(character)) {\n openQuote = character\n current += character\n at += 1\n continue\n }\n\n // The bracket depth is maintained HERE — after the quote arm above has already `continue`d —\n // which is what makes \"quote state wins\" a property of the control flow rather than a rule.\n if (BRACKET_PAIRS[character] !== undefined) {\n bracketDepth += 1\n current += character\n at += 1\n continue\n }\n\n if (CLOSING_BRACKETS.includes(character)) {\n // FLOORED AT ZERO. A stray `}` must not drive the counter negative, or a later `{` would\n // leave it at zero and the protection would silently stop working for the rest of the scan —\n // a guard defeated by a character a person typed by accident is not a guard.\n bracketDepth = Math.max(0, bracketDepth - 1)\n current += character\n at += 1\n continue\n }\n\n if (bracketDepth > 0) {\n // Inside a bracketed span nothing separates, exactly as inside a quoted one.\n current += character\n at += 1\n continue\n }\n\n const separator = separatorAt(utterance, at)\n if (separator !== undefined) {\n pieces.push(current)\n current = ''\n at += separator.length\n continue\n }\n\n current += character\n at += 1\n }\n pieces.push(current)\n\n const survivors: string[] = []\n for (const piece of pieces) {\n const text = piece.trim()\n if (text === '') continue\n survivors.push(text)\n }\n\n // THE STYLE-MODIFIER ELISION, and the reason it is its own pass rather than another `continue`\n // above: \"is there a real request beside this one\" is not a question a piece can answer about\n // itself. The whole survivor set has to exist first. Modifiers go only when a non-member\n // survives; an utterance made ONLY of modifiers keeps them all, because refusing something a\n // person typed is recoverable and dropping it silently is not — the same asymmetry Pitfall 5\n // already decides in this file, and the reason zero clauses is not an outcome this can produce.\n const kept = survivors.some((text) => !isStyleModifier(text))\n ? survivors.filter((text) => !isStyleModifier(text))\n : survivors\n\n const clauses: ChatClause[] = []\n for (const text of kept) {\n // The index is the clause's position among the clauses that SURVIVED elision, which is what\n // the engine and the reconciler key on. It is a clause's identity within one turn, not an\n // offset into the utterance, and D-12's override depends on exactly that: a planner entry for\n // a clause the table already resolved cannot displace it, whatever the model called it.\n clauses.push({ text, index: clauses.length })\n }\n return clauses\n}\n","// The live turn state a chat surface renders from (Phase 392 plan 08, RESEARCH Open Q2).\n//\n// THE DECISION THIS FILE IS, stated in code because it is a decision and not drift: chat's live\n// turn state is a PLAIN IN-MEMORY CONTAINER the engine mutates and the surface reads. CONTEXT\n// pre-ratified \"AI SDK v6 `AbstractChat`/`ChatState` owns live turn state\" (spec §4.2), and full\n// adoption of `AbstractChat` with its `DirectChatTransport` is DEFERRED to M5 rather than taken\n// here. The reason is a conflict, not a preference: the SDK's chat machinery AUTO-EXECUTES tool\n// calls as they stream, and D-10's pre-flight atomicity says reconciliation completes before the\n// first side effect. A transport that ran a tool the moment the model named it would execute the\n// first clause of a turn the reconciler was about to refuse whole. M5's streaming and HTTP\n// machinery is where that transport earns the work of reconciling the two; until then the state\n// this file holds is the same shape a surface would read off `ChatState`, minus the auto-run.\n//\n// WHAT IS IN IT IS WHAT A SURFACE CANNOT ANSWER FOR ITSELF. The active turn id (minted inside the\n// engine, and the only thing a Ctrl+C handler can name), the conversation as compaction left it,\n// the model in force after any `/model`, and whether `/quit` asked the loop to end. (The\n// classes `/pin` denied left with the pin overlay, 432-18.) Everything else a REPL renders —\n// receipts, the answer — rides the turn result.\n//\n// THE CONVERSATION IS `ModelMessage[]`, AND THE DIRECTION IS SPELLED ONCE (392-06's flagged\n// mismatch, resolved here because this is the file that holds it). The one projection is\n// `replayToModelMessages`: log events become `ChatReplayMessage[]` through `replaySession`, that\n// becomes `ModelMessage[]` through the projection, compaction prunes IN THAT FORM, and the prompt\n// renders from it. There is no inverse, because there could not be an honest one — pruning drops\n// and truncates messages, so re-keying the result back onto turn-stamped replay messages would\n// have to invent the turn ids it lost, and a fabricated ref in state several surfaces render is\n// the same wrong the `active_tools_change` deltas refuse to commit.\n\nimport type { ModelMessage } from 'ai'\n\nimport type { ChatTurnStatus, ClauseReceipt } from '@vostride/agent-qa-schema'\n\n/** What the last turn did, as a surface renders it. Absent before the first turn of a session. */\nexport interface ChatLastTurn {\n readonly turnId: string\n readonly status: ChatTurnStatus\n readonly receipts: readonly ClauseReceipt[]\n readonly answer?: string\n}\n\n/** A frozen view of the session's live state. Handed out per read, never the live object. */\nexport interface ChatStateSnapshot {\n /**\n * The model in force RIGHT NOW, after any `/model` this session ran.\n *\n * This is the value the config re-read compares against, and that is why the override lives here\n * rather than in a variable beside it: a thunk that kept answering the composed model would emit\n * a `model_change` straight back on the next turn, undoing the verb it just recorded (392-07).\n */\n readonly activeModel: string\n /**\n * The turn currently in flight, or absent between turns.\n *\n * The ONLY thing that can name an interrupted turn. A SIGINT handler has no other way to write\n * the explicit `aborted` event D-19's graceful arm asks for — the id is minted inside the engine\n * and a surface never sees it until the turn result comes back, which for an interrupted turn is\n * never.\n */\n readonly activeTurnId?: string\n /** The conversation as compaction left it, oldest first (see the module head for the direction). */\n readonly conversation: readonly ModelMessage[]\n readonly lastTurn?: ChatLastTurn\n /** `/quit` asked the loop to end. The REPL reads it; nothing in the engine acts on it. */\n readonly closing: boolean\n}\n\n/**\n * The mutable container. The engine writes; the surface reads.\n *\n * Deliberately NOT an event emitter. A REPL renders after each turn returns, and a subscription\n * would be the seam through which a surface started reacting to a turn mid-flight — which is the\n * streaming design M5 owns, not a thing to half-build here.\n */\nexport interface ChatStateContainer {\n read(): ChatStateSnapshot\n beginTurn(turnId: string): void\n endTurn(turn: ChatLastTurn): void\n setConversation(messages: readonly ModelMessage[]): void\n setActiveModel(model: string): void\n requestClose(): void\n}\n\nexport interface CreateChatStateInput {\n /** The model the session opened under — `unbound` on a host that composed none. */\n readonly activeModel: string\n}\n\nexport function createChatState(input: CreateChatStateInput): ChatStateContainer {\n let activeModel = input.activeModel\n let activeTurnId: string | undefined\n let conversation: readonly ModelMessage[] = []\n let lastTurn: ChatLastTurn | undefined\n let closing = false\n\n return {\n read() {\n // A fresh object per read, with frozen arrays: a surface handed the live members could\n // change what the engine believes is in force, and the one member that would matter is the\n // model — which is exactly the value the drift check compares against.\n return {\n activeModel,\n ...(activeTurnId === undefined ? {} : { activeTurnId }),\n conversation: Object.freeze([...conversation]),\n ...(lastTurn === undefined ? {} : { lastTurn }),\n closing,\n }\n },\n beginTurn(turnId) {\n activeTurnId = turnId\n },\n endTurn(turn) {\n // Cleared on the SAME call that records the result, so \"a turn is in flight\" and \"the last\n // turn finished\" can never both be true — an abort handler firing between them would write\n // an `aborted` event for a turn that already carries its `turn_complete`.\n activeTurnId = undefined\n lastTurn = turn\n },\n setConversation(messages) {\n conversation = [...messages]\n },\n setActiveModel(model) {\n activeModel = model\n },\n requestClose() {\n closing = true\n },\n }\n}\n","// The chat-open banner (Phase 392 plan 08, D-23 / 388 D-14).\n//\n// ONE READ, ONCE, WHEN A PERSON OPENS A CONVERSATION. There is no timer in this file, no watcher,\n// and no second pass — 388 D-14's one-read law is the whole design, and the reason is that the\n// alternative is not \"a fresher banner\" but a background process that keeps a project's stores\n// warm for a person who may have walked away. Live push is M5's, where a transport earns it.\n//\n// AT MOST ONE LINE, AND USUALLY NONE. A REPL that greeted every open with a status report trains a\n// person to skip the greeting, and then the one open that had something to say goes unread. So the\n// idle case is SILENCE rather than a reassuring sentence.\n//\n// EVERY READ DEGRADES TO SILENCE. A banner may never block chat open, and it may never turn an\n// unbound or refused op into a failure the person has to deal with before they can type.\n//\n// 2026-10-01 (432-17, D-05/D-22): the pending-proposals half is deleted with the inbox. Nothing is\n// filed for a person to decide, and old proposal files are never read, so the banner is the latest\n// run's digest headline or silence.\n//\n// IT COMPOSES REGISTERED OPS AND NOTHING ELSE. Every fact here is read through the same\n// `invokeFunction` binding a turn dispatches through, with the session's own caller — the read is\n// user-initiated, so it is read exactly as the person typing `digest` would read it. This file\n// reaches no store, holds no reader, and widens no DTO: `RunDigest.lines` is carried across\n// verbatim, which is the one-renderer law applied to a greeting.\n\nimport type { FunctionCaller } from '@vostride/agent-qa-schema'\n\nimport { RUNS_DIGEST_FUNCTION_ID } from '../functions/ops/runs-digest.js'\nimport { RUNS_LIST_FUNCTION_ID } from '../functions/ops/runs-list.js'\nimport type { ChatInvokeBinding } from './ports.js'\n\n/**\n * One read, or nothing.\n *\n * Swallowed HERE and nowhere else, and the swallow is narrow by construction: it wraps exactly one\n * invocation, so a failure inside the banner's own composition cannot be mistaken for a refused op.\n */\nasync function readOrNothing(\n invoke: ChatInvokeBinding,\n functionId: string,\n input: unknown,\n caller: FunctionCaller,\n): Promise<unknown> {\n try {\n // THE PAYLOAD ONLY (399.1). The seam answers a classified envelope now, and the banner is the\n // one consumer that legitimately wants none of it: it composes a greeting out of two reads, it\n // reports no receipt, and a verdict has nowhere on a banner to go. The fragments below parse\n // what they read, so a payload that is not what they expect renders nothing — the posture this\n // function already had for a read that threw.\n return (await invoke(functionId, input, caller)).payload\n } catch {\n return undefined\n }\n}\n\n/**\n * The latest run this project produced, or nothing.\n *\n * `runs.list` owns the chronology (431 D-08): newest finished first, `runId` breaking a tie, so the\n * banner asks for one row and takes it. Choosing again here would be a second ordering free to\n * disagree with `agent-qa digest`, which reads the same first row.\n */\nfunction latestRunId(answer: unknown): string | undefined {\n if (!Array.isArray(answer)) return undefined\n return (answer as readonly { runId?: string }[])[0]?.runId\n}\n\n/**\n * The digest half: the digest's OWN first rendered line.\n *\n * Carried across rather than composed here. `RunDigest.lines` is what `agent-qa digest` prints and\n * what the post-run tail emits, so re-deriving a headline would put a second sentence about one\n * run in front of a person — the failure the one-renderer law names.\n */\nfunction digestFragment(answer: unknown): string | undefined {\n const lines = (answer as { lines?: readonly string[] } | undefined)?.lines\n const headline = lines?.[0]\n return headline === undefined || headline.trim() === '' ? undefined : headline\n}\n\n/**\n * Compose the banner for one chat open.\n *\n * Sequential rather than concurrent, deliberately: the digest read is CONDITIONAL on the run list\n * having produced a run, and a project with no runs must not issue a `runs.digest` call against an\n * id it invented. Two reads at open is the ceiling; a third would need a decision.\n */\nexport async function composeBanner(\n invoke: ChatInvokeBinding,\n caller: FunctionCaller,\n): Promise<string | undefined> {\n const runId = latestRunId(\n await readOrNothing(invoke, RUNS_LIST_FUNCTION_ID, { limit: 1 }, caller),\n )\n const digest =\n runId === undefined\n ? undefined\n : digestFragment(await readOrNothing(invoke, RUNS_DIGEST_FUNCTION_ID, { runId }, caller))\n\n return digest\n}\n","// Reading one scenario back (Phase 392 plan 09, CHAT-02).\n//\n// A scenario file is committed DATA that decides whether a gate passes, so the step between the\n// bytes on disk and the assertion has to be a validation rather than a cast. This module is that\n// step, spelled once for both lanes and for the manifest walk.\n//\n// IT TAKES A PARSED DOCUMENT, NEVER A PATH, and the shape of that decision is architectural rather\n// than stylistic. `packages/agent` is `storageNeutral`: the class rules forbid `node:fs` by name,\n// and they are right to — a package whose whole claim is \"storage access through ports only\" must\n// not grow a file reader for its own test corpus. The eight lines of `readFileSync` + YAML decode\n// therefore live in the runners, which are test files in packages that may touch a disk, and\n// everything that could be got WRONG about a scenario — the schema, the cross-checks, the refusal\n// wording — lives here where one spelling serves every caller. (The plan named a `loadScenario`\n// that resolves and reads a path; the split is the deviation, and it is recorded as one.)\n//\n// THE REFUSAL NAMES THE SCENARIO. A zod error alone reports a field path against an anonymous\n// object, and the reader of a red gate needs to know WHICH of twenty files is malformed before\n// anything else is useful.\n\nimport { ChatScenarioSchema } from '@vostride/agent-qa-schema'\nimport type { ChatScenario, ScenarioClass } from '@vostride/agent-qa-schema'\n\n/**\n * How a scenario is addressed: `<class>/<id>.yml`, relative to `src/chat/scenarios`.\n *\n * The directory name IS the class name, so there is no second mapping table to keep in step with\n * `SCENARIO_CLASSES`. A class added to the vocabulary needs a directory and nothing else.\n */\nexport function scenarioRelativePath(reference: {\n readonly class: ScenarioClass\n readonly id: string\n}): string {\n return `${reference.class}/${reference.id}.yml`\n}\n\n/**\n * Validate a decoded scenario document against the schema AND against the line that found it.\n *\n * The second half is the one worth stating. The manifest addresses a scenario by class and id, and\n * the file states its own class and id — two facts that a loader trusting the filename would let\n * drift, leaving a corpus entry whose contents belong to a different scenario than the one the\n * denominator counted.\n */\nexport function parseScenario(\n document: unknown,\n expected: { readonly class: ScenarioClass; readonly id: string },\n): ChatScenario {\n const reference = `${expected.class}/${expected.id}`\n const parsed = ChatScenarioSchema.safeParse(document)\n if (!parsed.success) {\n const detail = parsed.error.issues\n .map((issue) => `${issue.path.join('.') || '<root>'}: ${issue.message}`)\n .join('; ')\n throw new Error(`scenario ${reference} is not a valid ChatScenario — ${detail}`)\n }\n const scenario = parsed.data\n if (scenario.id !== expected.id || scenario.class !== expected.class) {\n throw new Error(\n `scenario ${reference} declares itself as ${scenario.class}/${scenario.id} — the file and `\n + 'the manifest line that addressed it must name the same scenario',\n )\n }\n return scenario\n}\n","// THE mark_unhandled CEILING (Phase 392 plan 09, CHAT-03 / D-15).\n//\n// `mark_unhandled` is the FAIL-CLOSED PATH, not an error path. It is supposed to fire: a build that\n// cannot author a test must refuse to author a test, by name, rather than reaching for the nearest\n// op it does have. So the thing worth measuring is not whether it fires — it is whether it starts\n// firing on requests this build CAN serve, because that is how a fail-closed path decays. It goes\n// noisy, a person learns to distrust it, and the pressure lands on disabling it rather than on\n// fixing the routing underneath. The ceiling is what turns that decay into a red build.\n//\n// TWO PROPERTIES, AND BOTH ARE STRUCTURAL RATHER THAN CAREFUL:\n//\n// 1. THE DENOMINATOR IS THE FROZEN MANIFEST. `SCENARIO_CORPUS`, never a directory listing and\n// never a glob. A scoring set that grows as scenarios are written lets the ratio drift without\n// anyone deciding it should, which is this project's most expensive recorded failure mode\n// (D-15, RESEARCH Pitfall 2). Nothing in this module can discover a scenario; a caller must\n// hand it a count, and the only honest source of that count is the manifest.\n//\n// 2. THE COMPARISON IS EXACT INTEGER ARITHMETIC. The ceiling is a rational `{ num, den }`\n// compared by cross-multiplication, never a percentage compared after rounding. A rate\n// rounded to whole percent reports 20.1% as 20% and passes a breached ceiling — a threshold\n// that rounds in the implementer's favour is not a threshold.\n//\n// ONE FUNCTION SERVES BOTH READINGS (D-15). The harness measures the rate over the corpus; a live\n// deployment's FIELD rate is a projection over `mark_unhandled` rows in session logs. Both are\n// `computeMarkUnhandledRate` over a list of events. There is no metric store, no field gate, and no\n// second counter that could disagree with this one about what a refusal is.\n\nimport type { ChatSessionEvent } from '@vostride/agent-qa-schema'\n\n/**\n * The pinned ceiling: at most one refusal per five `should_execute` scenarios.\n *\n * A PINNED CONSTANT WITH A RETUNE COMMENT, NEVER CONFIG (386 D-15). A configurable ceiling is a\n * ceiling that gets raised the first time it is inconvenient, at which point it measures the\n * patience of whoever raised it.\n *\n * OWNER: the chat orchestration subsystem (Phase 392, CHAT-03).\n *\n * RETUNE WHEN, and only when:\n * - the corpus GROWS through a deliberate `SCENARIO_CORPUS` bump, and the new members change what\n * a representative request looks like. At the corpus size this pin ships against, 1/5 leaves no\n * slack at all on the live lane — three `should_execute` live scenarios means the first refusal\n * exceeds it. That is deliberate for a young corpus: with three cells, one miss IS a routing\n * regression, and a tolerance that hid it would be a tolerance for nothing observable.\n * - a MEASURED live rate sits consistently far from the pin in either direction across several\n * gate runs. Consistently far below means the pin has stopped being a gate; consistently just\n * above on requests that genuinely cannot be served means the corpus admitted cells the build\n * was never going to route, and the fix is the corpus, not the number.\n *\n * A retune moves this constant AND `SCENARIO_CORPUS_VERSION`, so a rate recorded in any SUMMARY\n * stays attributable to the pair it was measured against.\n */\nexport const MARK_UNHANDLED_CEILING = { num: 1, den: 5 } as const\n\n/**\n * The measurement: two counts, and deliberately NOT their quotient.\n *\n * A stored rate would be a third number that could disagree with the two it came from, and the\n * comparison below never needs it — cross-multiplication reads the counts directly.\n */\nexport interface MarkUnhandledCounts {\n readonly unhandledCount: number\n readonly denominator: number\n}\n\n/**\n * Count the refusals in a session-event stream against a caller-supplied denominator.\n *\n * The denominator is a PARAMETER rather than something this module derives, and that is the D-15\n * discipline expressed as a signature: a function that could count scenarios for itself would be\n * one refactor away from counting files on a disk.\n */\nexport function computeMarkUnhandledRate(\n events: readonly ChatSessionEvent[],\n denominator: number,\n): MarkUnhandledCounts {\n let unhandledCount = 0\n for (const event of events) {\n if (event.kind === 'mark_unhandled') unhandledCount += 1\n }\n return { unhandledCount, denominator }\n}\n\n/**\n * Has the corpus exceeded the pinned ceiling?\n *\n * STRICT GREATER-THAN over cross-multiplied integers: a count sitting exactly ON the pin passes,\n * and one more fails. Both sides of that boundary are unit-tested, because a gate whose passing\n * side was never checked is a gate nobody can satisfy, and a gate whose failing side was never\n * checked is not a gate at all.\n *\n * An empty denominator with any refusal in it EXCEEDS, by the same arithmetic and for the right\n * reason: refusals counted against a corpus with nothing in it is not a rate, and reporting it as\n * within the ceiling would be exactly the vacuous pass this measurement exists to refuse.\n */\nexport function ceilingExceeded(counts: MarkUnhandledCounts): boolean {\n return (\n counts.unhandledCount * MARK_UNHANDLED_CEILING.den\n > counts.denominator * MARK_UNHANDLED_CEILING.num\n )\n}\n","// THE FROZEN CORPUS MANIFEST (Phase 392 plan 09, D-15 / CHAT-03).\n//\n// This list IS the ceiling denominator. Not the contents of the `scenarios/` directory, not a glob,\n// not \"whatever the runner found\" — this list. The distinction is the single most expensive lesson\n// this project has recorded: a scoring set that grows as work is added lets the measured ratio\n// drift without anyone deciding to move it, and every round of the arc then reports progress that\n// nobody chose (RESEARCH Pitfall 2, the treadmill law).\n//\n// So membership is a DELIBERATE EDIT. `scenario-manifest.test.ts` walks both directions — a listed\n// scenario with no file and a file with no line both fail the build — which means a scenario cannot\n// join the denominator by being written, only by being admitted. When it is admitted, `CORPUS_VERSION`\n// moves and the number reported afterwards is a number about a different corpus, stated as such.\n//\n// THE EXPECTATION KIND IS PART OF THE LINE. The ceiling is computed over `should_execute` entries,\n// so a scenario flipping arm changes the denominator as surely as one being added. D-08's flip law\n// already makes a flip a phase's arrival proof; carrying the kind here makes it a two-file edit.\n//\n// PURE DATA, NO IMPORTS BEYOND THE VOCABULARY. Nothing here reads a file or parses a byte, because\n// `packages/agent` is storageNeutral and because a manifest that could DERIVE itself from a disk\n// would be the glob it exists to refuse.\n\nimport type { ScenarioClass, ScenarioExpectationKind, ScenarioLane } from '@vostride/agent-qa-schema'\n\n/**\n * The corpus this build measures against.\n *\n * BUMPED WHENEVER THE CORPUS STOPS BEING THE SAME CORPUS — a member added or removed, an\n * expectation kind flipped, or an utterance re-authored. A recorded rate can then always be\n * attributed to a known set, and a rate quoted without one is a number whose meaning cannot be\n * reconstructed after the next scenario lands.\n *\n * v1 — 392 plan 02 seeded 13 deterministic + the canon compound pair; 392 plan 08 flipped the four\n * directive scenarios to `should_execute` before this manifest existed.\n * v2 — 392 plan 09 admits the `planner/` seeds (the live lane's natural-language arm).\n * v3 — 392 plan 09, after the FIRST live execution: `run-42-and-digest`'s digest clause names its\n * run (the original was unsatisfiable under D-10's pre-flight atomicity — see that file), and\n * `list-recent-runs` is re-authored as a request to DO something rather than a question about\n * the project.\n * v4 — 392 plan 11, the gap round for 392-VERIFICATION's CR-03 and CR-04: two `compound/` cells\n * admitted, both `fail_closed`, so the ceiling's `should_execute` denominators are unmoved\n * (11 hermetic, 3 live) and the two defects the corpus could not see now have permanent\n * cells. `pin-and-write-test` is the corpus's first HERMETIC compound cell — both halves are\n * deterministic, and its lane is named as an exception in `scenario-manifest.test.ts` rather\n * than derived from its class. The verifier's third probe (two overlapping sessions on one\n * composition, CR-01/CR-02) is deliberately NOT a cell here: the scenario runner is\n * single-turn by design, so it lands as a composition-level concurrency test in plan 392-12.\n * v5 — 392 plan 14, the SECOND gap round for 392-VERIFICATION's round-2 gap: two more `compound/`\n * cells, both `fail_closed` and both HERMETIC, so the denominators stay 11 hermetic / 3 live.\n * `pin-and-pin-nonsense` is the multi-directive arm the runner's fail_closed side-effect\n * assertion could not reach while `pin-and-write-test` was the only directive cell;\n * `run-42-and-delete-root-empty-answer` is the hermetic sibling of the live CR-03 cell,\n * carrying the empty-prose `answer_only` shape through a scripted planner so the class is\n * proved per commit rather than only behind the announced-skipped live gate (W-08).\n * v6 — 392 plan 15, the THIRD gap round, for 392-VERIFICATION round 3's CR-01: one more `compound/`\n * cell, `fail_closed` and HERMETIC, so the denominators stay 11 hermetic / 3 live.\n * `run-42-and-summarise-extra-call` is the configuration the corpus had in NEITHER lane — a\n * table-mapped clause beside a planner-bound one on a turn that completed — with a scripted\n * planner emitting an extra action call about the MAPPED clause. Pre-fix that call shifted the\n * binding of every later clause and executed with the model's own arguments; the cell is what\n * makes the arity accounting's refusal observable per commit rather than only in a unit.\n * v7 — 394 plan 11, THE ARRIVAL FLIP, and the first version whose size does not move. 392 plan 08\n * wrote D-08's flip law and committed three cells asserting that no capability could author a\n * test; 394 registered the six-stage loop as `authoring.draft.write`, so two of those three\n * change arm: `planner/write-test-for-checkout` and `compound/write-test-2fa-and-run`, both\n * LIVE, taking the live denominator to 5. Both now pin planned == executed, because a cell\n * that merely completed would be satisfied by a turn that planned the capability and never\n * reached it — and reachability is the whole claim a flip makes.\n *\n * TWO CELLS DELIBERATELY DO NOT FLIP, and each refusal is load-bearing for something 394\n * does not ship. `deterministic/fn-unknown-op` addresses `write_test`, which was the SPEC's\n * noun for the loop and is NOT a registered function id in this build (the id is\n * `authoring.draft.write`); its `/fn` utterance therefore still reaches `invokeFunction` with\n * an id nothing registers, which is the exact backstop that cell exists to prove, and flipping\n * it would have made an unknown-op test pass for the wrong reason. So the HERMETIC denominator\n * is unmoved at 11. `compound/pin-and-write-test` measures the CR-04 directive/pin probe — a\n * refused turn that had already recorded a pin and an `approval_decision` row — and its\n * write-test half is only the vehicle; flipping it would delete the corpus's one cell that\n * names a directive on a turn that fails.\n *\n * v8 — 395 plan 09, THE CONFIG ARRIVAL, AND IT IS AN ADMISSION RATHER THAN A FLIP. 392 D-08 named\n * the handoff as a flip — \"the config `fail_closed` scenario moves to `should_execute`\" — and\n * 395's research went looking for that cell across all 23 files and every line below. THERE IS\n * NO CONFIG CELL IN v7. Nothing was ever admitted to flip, so executing the handoff faithfully\n * means admitting one: `planner/config-edit-timeout`, LIVE and `should_execute`, taking the\n * corpus to 24 and the live denominator to 6.\n *\n * THE SIZE MOVING IS THE WHOLE DIFFERENCE, and it is why the size and the denominator are\n * pinned side by side in `scenario-manifest.test.ts`. v7 was the first version whose size did\n * not move: two cells changed arm and the live denominator rose by two, which is what a flip\n * looks like from here. This version's size rises by one AND the denominator rises by one,\n * which is what an admission looks like, and the pair is the only thing that tells them apart.\n *\n * AN ADMISSION GROWS THE DENOMINATOR, WHICH IS THE MOVEMENT THE TREADMILL LAW EXISTS TO WATCH.\n * Stated rather than slipped through: every gap-round cell since v4 was authored `fail_closed`\n * precisely so the denominators did not move for work being done. This one is not a gap-round\n * cell — it is a capability that did not exist in v7's build and does in this one, and the\n * denominator it enters is the population the `mark_unhandled` ceiling is computed over. The\n * rate reported after this commit is a rate about a DIFFERENT corpus, which is the sentence\n * this version number exists to let a reader say.\n *\n * v9 — 398 plan 07, THE EXPLAIN ARRIVAL, and it is an ADMISSION on v8's shape rather than a flip.\n * `agent.explain` did not exist in v8's build: \"what can you do\" had no reachable op, so the\n * only honest outcomes were prose out of model memory or `mark_unhandled`, and no cell was\n * ever admitted that could flip. Two `planner/` cells join — `what-can-you-do` and\n * `how-do-i-explain` — taking the corpus to 26 and the live denominator to 8.\n *\n * TWO CELLS AND NOT ONE, because XPLN-02 names two SHAPES of question rather than two\n * wordings: an enumeration and a request for one capability's command. A planner that routed\n * the first and answered the second from model memory is a real, reachable half-failure, and a\n * corpus carrying only the enumeration form could not see it.\n *\n * THE DENOMINATOR MOVES BY TWO, WHICH IS THE MOVEMENT THE TREADMILL LAW WATCHES. Stated rather\n * than slipped through, on v8's own terms: these are not gap-round cells authored `fail_closed`\n * to leave the ratio alone — they are a capability that did not exist in v8's build and does in\n * this one. Every rate reported after this commit is a rate about a DIFFERENT corpus, which is\n * the sentence this version number exists to let a reader say.\n *\n * BOTH WERE UNRUN AT THE COMMIT THAT ADMITTED THEM. `AGENT_QA_LIVE_CHAT_CONFIG` was unset in\n * that session, so the live gate announced its skip and neither utterance has met a model. The\n * rows are corpus-pinned, not yet measured; the first live execution is the measurement, and\n * if it routes to prose the UTTERANCE is what gets re-authored (392-09's precedent), never the\n * assertion.\n *\n * v10 — 432 plan 13, TWO RETIREMENTS, and the size does not move. `/pin` and the bare `proposals`\n * inbox alias left chat resolution with the op gate and the proposal inbox (D-05/D-14), so\n * `deterministic/pin` and `deterministic/proposals` no longer name a table row. Each is KEPT and\n * re-authored as a `fail_closed` absence cell (\"re-spelled, never deleted\"): the retired verb is\n * an unroutable clause that refuses by name with zero executions. Both leave the hermetic\n * `should_execute` denominator, taking it from 11 to 9; the live denominator is unmoved.\n *\n * DENOMINATORS AT THIS VERSION: 9 hermetic, 8 live. One canonical line, parsed by\n * `scenario-manifest.test.ts` and compared against the counts the list below actually has, so this\n * header cannot go on claiming numbers the corpus stopped having. Every other assertion in that\n * file reads the LIST, which is exactly why the header needed its own.\n */\nexport const SCENARIO_CORPUS_VERSION = 10\n\n/**\n * One admitted scenario.\n *\n * Every field is a CLAIM the closure test checks against the file, rather than a convenience copy:\n * class and id address it, lane decides which gate runs it, and kind decides whether it counts\n * toward the `mark_unhandled` denominator.\n */\nexport interface ScenarioCorpusEntry {\n readonly id: string\n readonly class: ScenarioClass\n readonly lane: ScenarioLane\n readonly kind: ScenarioExpectationKind\n}\n\nconst entry = (value: ScenarioCorpusEntry): ScenarioCorpusEntry => value\n\n/**\n * The admitted set, in class order and then in the order each arrived.\n *\n * Deterministic scenarios run hermetic per commit; `planner` and `compound` run in the live-model\n * lane as a release gate (D-13). There is no third lane and no scenario outside this list.\n */\nexport const SCENARIO_CORPUS: readonly ScenarioCorpusEntry[] = Object.freeze([\n // --- deterministic: the ten canon aliases (392-02) -------------------------------------------\n entry({ id: 'run', class: 'deterministic', lane: 'hermetic', kind: 'should_execute' }),\n entry({ id: 'status', class: 'deterministic', lane: 'hermetic', kind: 'should_execute' }),\n entry({ id: 'test-ref', class: 'deterministic', lane: 'hermetic', kind: 'should_execute' }),\n entry({ id: 'digest', class: 'deterministic', lane: 'hermetic', kind: 'should_execute' }),\n // 432-13: the inbox alias is retired; the cell is its measured absence (v10).\n entry({ id: 'proposals', class: 'deterministic', lane: 'hermetic', kind: 'fail_closed' }),\n entry({ id: 'fn', class: 'deterministic', lane: 'hermetic', kind: 'should_execute' }),\n // The directives. `executed: 0` on a `should_execute` arm is the SHAPE, not a compromise: a\n // directive names no capability, so it crosses the function layer zero times on a turn that did\n // exactly what was asked (392-08's flip). 432-13 retired `/pin`; its cell is its absence (v10).\n entry({ id: 'model', class: 'deterministic', lane: 'hermetic', kind: 'should_execute' }),\n entry({ id: 'pin', class: 'deterministic', lane: 'hermetic', kind: 'fail_closed' }),\n entry({ id: 'help', class: 'deterministic', lane: 'hermetic', kind: 'should_execute' }),\n entry({ id: 'quit', class: 'deterministic', lane: 'hermetic', kind: 'should_execute' }),\n // --- deterministic: the three stage-1 edge scenarios (392-02) ---------------------------------\n entry({ id: 'quoted-conjunction', class: 'deterministic', lane: 'hermetic', kind: 'should_execute' }),\n entry({ id: 'near-miss-alias', class: 'deterministic', lane: 'hermetic', kind: 'fail_closed' }),\n // DID NOT FLIP, and the reason is a measurement rather than an oversight (394-11). This line was\n // written to flip when the authoring loop registered `write_test`. 394 registered the loop as\n // `authoring.draft.write` — `write_test` is the spec's noun for the capability and is not a\n // function id anywhere in the registry — so the utterance still carries an id nothing registers,\n // and the cell still proves the one thing it was admitted for: `/fn` validates no op id, and\n // `invokeFunction` names an unknown one before any dependency is touched. A phase that registers\n // ops can make an unknown-op test pass for the wrong reason; this one did not.\n entry({ id: 'fn-unknown-op', class: 'deterministic', lane: 'hermetic', kind: 'fail_closed' }),\n // --- planner: natural language, live lane (392-09) --------------------------------------------\n entry({ id: 'list-recent-runs', class: 'planner', lane: 'live', kind: 'should_execute' }),\n entry({ id: 'explain-flaky', class: 'planner', lane: 'live', kind: 'should_execute' }),\n // D-08's LIVE arm, FLIPPED (394-11). It was admitted as the cell proving the planner could not\n // invent an authoring capability out of prose; the loop shipping makes the same prose routable,\n // and the flip is what says so. Its file pins planned == executed, so a turn that planned the\n // capability without reaching it reds here rather than reading as arrival.\n entry({ id: 'write-test-for-checkout', class: 'planner', lane: 'live', kind: 'should_execute' }),\n // --- planner: 395's config arrival, ADMITTED (395-09) ------------------------------------------\n // The first member this corpus has ever gained for a capability rather than for a defect. 392\n // D-08 designed this as a flip and there was nothing to flip: no config cell was ever admitted,\n // which 395's research established by enumerating every file above. So the handoff is executed as\n // an ADMISSION — the size moves as well as the denominator, and the pair of pins in\n // `scenario-manifest.test.ts` is what makes the two movements distinguishable after the fact.\n // The cell pins planned == executed == 1 on `config.field.set`, the propose op D-03 gave any\n // schema-addressable path; it deliberately stops short of `config.proposal.apply`, which is the\n // verb that changes a person's git history and the only one in the family that is gated.\n entry({ id: 'config-edit-timeout', class: 'planner', lane: 'live', kind: 'should_execute' }),\n // --- planner: 398's explain arrival, ADMITTED (398-07) -----------------------------------------\n // The corpus's second admission for a capability rather than for a defect, and the first pair.\n // `agent.explain` answers a question about what this product can do BY CITING the committed\n // capability catalog, so these two cells are what make \"never from model memory\" checkable at the\n // routing level: a turn that answered either utterance in prose completes without executing\n // anything, and `planned == executed == 1` on the op id is what tells the two apart.\n entry({ id: 'what-can-you-do', class: 'planner', lane: 'live', kind: 'should_execute' }),\n entry({ id: 'how-do-i-explain', class: 'planner', lane: 'live', kind: 'should_execute' }),\n // --- compound: the canon pair, live lane (392-02) ---------------------------------------------\n entry({ id: 'run-42-and-digest', class: 'compound', lane: 'live', kind: 'should_execute' }),\n // The spec's own example, FLIPPED (394-11). Both clauses are routable now, so D-10's pre-flight\n // atomicity has a plan it can admit instead of a whole turn it must refuse.\n entry({ id: 'write-test-2fa-and-run', class: 'compound', lane: 'live', kind: 'should_execute' }),\n // --- compound: the two gap-round regression cells (392-11) -------------------------------------\n // The verifier's own probes, admitted so neither defect can return silently. Both are\n // `fail_closed`, so neither enters the ceiling denominator: what they add is the ability to SEE a\n // refused turn that carried something out, which `executed == 0` alone never could.\n entry({ id: 'run-42-and-delete-root', class: 'compound', lane: 'live', kind: 'fail_closed' }),\n // STAYS REFUSING THROUGH 394's FLIP (394-11). Its second clause is a write-test request, so a\n // reader who found the other two write-test cells flipped could reasonably take this one for an\n // oversight. It is not. What this cell measures is CR-04 — a refused turn that had ALREADY\n // recorded a pin and an `approval_decision` row — and its refusal comes from the hermetic lane's\n // tripwire model, not from the authoring capability being absent. Flipping it would remove the\n // corpus's only cell naming a directive on a turn that fails, to prove something two live cells\n // already prove.\n entry({ id: 'pin-and-write-test', class: 'compound', lane: 'hermetic', kind: 'fail_closed' }),\n // --- compound: the second gap round's two cells (392-14) ---------------------------------------\n // What the round-2 verification found the corpus still could not see: a directive BATCH whose\n // later entry refuses (the earlier one's pin and its `approval_decision` row survived), and the\n // empty-prose `answer_only` that erased a clause on a `completed` turn. Both `fail_closed`, both\n // HERMETIC — the lanes are named exceptions in `scenario-manifest.test.ts`, and the denominators\n // are unmoved at 11 hermetic / 3 live.\n entry({\n id: 'run-42-and-delete-root-empty-answer',\n class: 'compound',\n lane: 'hermetic',\n kind: 'fail_closed',\n }),\n entry({ id: 'pin-and-pin-nonsense', class: 'compound', lane: 'hermetic', kind: 'fail_closed' }),\n // --- compound: the third gap round's cell (392-15) ---------------------------------------------\n // The mixed-mapping configuration NO cell in either lane had: a table-mapped clause beside a\n // planner-bound one on a turn that completed, with the model making an extra call about the\n // mapped clause (CR-01). `fail_closed` and hermetic, so the denominators are unmoved again.\n entry({\n id: 'run-42-and-summarise-extra-call',\n class: 'compound',\n lane: 'hermetic',\n kind: 'fail_closed',\n }),\n])\n","// Stage 2 — the tool-bound planner (Phase 392 plan 04, CHAT-01 / CHAT-06 / D-10).\n//\n// THE MODEL ARRIVES BUILT. This module takes a `LanguageModel` as a constructor argument and does\n// not construct one: it names no provider package, and it does not name `createModel` either. That\n// is CHAT-06 stated structurally rather than as a convention — every chat model call rides the one\n// entry the host composes, which is where the masking middleware and the profile resolution live,\n// so there is no arrangement of this file in which a chat turn reaches a provider that skipped\n// them. The `packages/arch` chat-model rollcall reds the build if that ever stops being true.\n//\n// THE STAGE PRODUCES A PLAN AND NOTHING ELSE. `generateText` executes a tool exactly when the tool\n// carries a function to run, and `projectPlannerTools` gives none of them one — so what comes back\n// is the model's proposal, in `result.toolCalls`, with zero side effects behind it. Reconciliation\n// then decides what that proposal means (D-10). This is the strongest available form of \"nothing\n// runs before the verdict\": not an ordering somebody maintains, but an absent callback.\n//\n// A TRANSPORT FAILURE IS DATA, NOT A CRASH. An auth refusal, a rate limit or an outage is a fact\n// about this turn. It comes back as `failure` on the outcome, the engine folds it into a failed\n// turn with a named receipt, and the session survives. A thrown error here would surface as a stack\n// trace over a REPL and leave the session log with a turn that neither completed nor failed.\n//\n// A NOTE ON THE STRING FORM OF `LanguageModel`. The SDK's own type also admits a bare model id,\n// which it resolves through a global provider registry — i.e. it constructs a client. That variant\n// is excluded from {@link ChatLanguageModel} on purpose: it is a second door to the thing CHAT-06\n// closes, and it is closed here at the type rather than by asking hosts not to walk through it.\n\nimport { generateText } from 'ai'\nimport type { LanguageModel, ToolSet } from 'ai'\n\nimport { buildChatPrompt } from './chat-prompt.js'\nimport type { ChatPromptInput } from './chat-prompt.js'\nimport type {\n PlannerStageFailure,\n PlannerStageOutcome,\n PlannerStagePort,\n PlannerStageRequest,\n PlannerToolCall,\n} from './ports.js'\n\n/** A model OBJECT, never a model id: an id would be resolved by constructing a client. */\nexport type ChatLanguageModel = Exclude<LanguageModel, string>\n\n/** What the prompt's context and volatile tiers state about the session, read per turn. */\nexport type ChatSessionPromptContext = Omit<ChatPromptInput, 'utterance' | 'clauses'>\n\nexport interface PlannerStageDeps {\n /** Built by the host through `createModel` and handed over — CHAT-06. */\n readonly model: ChatLanguageModel\n /** The registry projection from `planner-tools.ts`. Execute-less, by that module's contract. */\n readonly tools: ToolSet\n /**\n * Read once per REQUEST rather than captured at construction, because the model in force, the\n * pending-count facts and the conversation all change WITHIN a session — a `/model` directive\n * mid-session is the obvious case (D-04), and a stage holding a snapshot would prompt against a\n * session that no longer exists.\n *\n * IT IS TOLD WHICH SESSION IS ASKING (392 plan 13, CR-02). A composition caches one stage per\n * model NAME, so the same stage serves every session planning under that model; a thunk taking\n * no argument therefore had exactly one conversation available to answer with, and on two\n * interleaved turns that was whichever session published last. The request is the only thing\n * here that knows whose turn this is.\n */\n readonly context: (request: PlannerStageRequest) => ChatSessionPromptContext\n}\n\n/** The refusal NAME a provider published, or the closest honest thing to it. */\nfunction toStageFailure(error: unknown): PlannerStageFailure {\n if (error instanceof Error) {\n return { name: error.name === '' ? 'PlannerStageError' : error.name, message: error.message }\n }\n return { name: 'PlannerStageError', message: String(error) }\n}\n\n/**\n * Shape the SDK's tool calls into the plan stage 3 reads.\n *\n * NOTHING IS DROPPED AND NOTHING IS PROJECTED. Every call survives into `toolCalls` in the order\n * the model made them, meta-tools included: `mark_unhandled` is a proposal about the turn that only\n * reconciliation can act on, and filtering it here would put the fail-closed decision in the\n * component whose input is the untrusted one.\n *\n * THE `answer` PROJECTION IS GONE (392-14). This function used to lift the FIRST `answer_only`\n * call's text onto the outcome as a convenience — and once the tool contract asked for one call per\n * answered clause, that convenience became a SECOND prose channel carrying strictly less than the\n * calls it was derived from: reconciliation counted every claimed clause as answered while the\n * person read the first answer only (392-VERIFICATION round 2, path (4)). The calls are the whole\n * of what the model said; whoever needs the prose reads the claims it belongs to.\n */\nexport function readBackPlan(\n toolCalls: readonly { readonly toolName: string; readonly input: unknown }[],\n): PlannerStageOutcome {\n const plan: PlannerToolCall[] = toolCalls.map((call) => ({\n toolName: call.toolName,\n input: call.input,\n }))\n\n return { toolCalls: plan }\n}\n\n/**\n * Build stage 2 over an already-constructed model and an already-projected toolset.\n *\n * Both arrive from the composition root, and neither is reachable from here: this module cannot\n * build a model and cannot widen a toolset. What it can do is ask, and read the answer back.\n */\nexport function createPlannerStage(deps: PlannerStageDeps): PlannerStagePort {\n return {\n async plan(request): Promise<PlannerStageOutcome> {\n const { system, prompt } = buildChatPrompt({\n utterance: request.utterance,\n clauses: request.clauses,\n ...deps.context(request),\n })\n\n try {\n const result = await generateText({\n model: deps.model,\n tools: deps.tools,\n system,\n prompt,\n })\n return readBackPlan(result.toolCalls)\n } catch (error) {\n return { toolCalls: [], failure: toStageFailure(error) }\n }\n },\n }\n}\n","// Chat's tier blocks for the ONE prompt builder (Phase 392 plan 04 — 389 D-04, 392-EXTENDS).\n//\n// THIS MODULE AUTHORS CONTENT, NEVER ASSEMBLY. `tiered-prompt-builder.ts` owns the tier law and\n// the render order; chat passes its own `agent_context` and its own blocks, exactly as\n// analyze-run does, and touches nothing about how the three tiers are joined. That parameter is\n// the whole mechanism by which six job types share one prompt idiom (spec §1.4: \"parameterized,\n// not separate personas\"), and the way it usually gets lost is not a decision — it is a caller\n// who needed one more section and wrote its own assembly instead of one more block.\n//\n// TIER PLACEMENT IS A CACHE DECISION AS WELL AS A STRUCTURAL ONE. The stable tier is chat's role\n// and the invariant planning discipline: identical bytes on every turn of every session, so a\n// provider prompt cache sees the same prefix each call. Session facts move per session and lead\n// the prompt leg; the conversation and the current utterance move every turn and trail it. Put\n// the utterance in the stable tier and the cached prefix is novel on every keystroke — a defect\n// that never fails a test and only ever shows up as a bill.\n//\n// THE INSTRUCTIONS BELOW ARE WHAT CHAT-03's CEILING MEASURES. One action tool call per clause in\n// utterance order is what makes the reconciler's order alignment meaningful; `mark_unhandled`\n// naming the clause is what makes the fail-closed arm a NAMED refusal rather than an improvisation\n// with an adjacent capability (D-08); `answer_only` is what keeps an informational turn from\n// looking like a planning failure. Loosening any of the three moves the measured unhandled rate\n// without moving any mechanism, which is the one way that number can lie.\n//\n// `answer_only` IS LAST-RESORT, AND 392 PLAN 10's LIVE RUN IS WHY. As first written, the\n// instruction said to use it \"when the turn asks for information rather than for something to\n// happen\" — and a real model, asked to route `show me the digest for RUN-1`, read that as its case\n// and answered in prose while `runs.digest` sat unused in its tool set. Until 398 grounds this tool\n// in the capability catalogue, its text is ungrounded model memory: the person asked for a run's\n// digest and would have been handed an invention that looks exactly like the real one. So the\n// instruction now names the precondition it always meant — no offered tool can produce what was\n// asked — and says plainly that the model knows nothing about this project the tools did not tell\n// it. This is a correctness fix about fabrication, not a routing preference.\n//\n// NO PAYLOAD BODIES. Session facts are one-liners and the replayed conversation is refs plus\n// outcomes (D-18) — the same map-not-territory rule the session log follows, applied to the one\n// place where the whole conversation is about to cross a network boundary (T-392-14).\n\nimport type { ModelMessage } from 'ai'\n\nimport { buildTieredPrompt } from '../prompt/tiered-prompt-builder.js'\nimport type { PromptTierBlock } from '../prompt/tiered-prompt-builder.js'\nimport type { JobModelRequest } from '../jobs/record-llm-authorship.js'\n\nimport type { ChatClause } from './ports.js'\n\n/** Who is asking and why — chat's stable-tier provenance (§1.4's `agent_context` parameter). */\nexport const CHAT_AGENT_CONTEXT =\n 'agent-qa chat orchestrator. A person is talking to the QA agent through a terminal session. '\n + 'Your job on this turn is to PROPOSE a plan, not to carry one out: nothing you name here runs '\n + 'until a deterministic reconciliation step has checked it.'\n\nconst ROLE_BLOCK: PromptTierBlock = {\n title: 'Role',\n body:\n 'You route what a person asked for onto the capabilities this host actually has. Every '\n + 'capability available to you is offered as a tool; there are no others, and there is no way '\n + 'to ask for one. A capability that is missing is missing because it has not shipped yet.',\n}\n\nconst PLANNING_BLOCK: PromptTierBlock = {\n title: 'How to answer',\n body:\n // \"OF THE LIST BELOW\", not \"of the request\". The `Request` block carries the WHOLE utterance\n // while `Clauses to answer` carries only what stage 1 could not bind, so a count scoped to the\n // request asks for calls about clauses that are already resolved — and every one of those is a\n // call reconciliation cannot attribute to anything (392-VERIFICATION round 3).\n 'Call one action tool per clause of the list below, in utterance order. Order is meaning: later '\n + 'clauses routinely depend on earlier ones, so the sequence you emit is the sequence that '\n + 'will be considered.\\n'\n + '\\n'\n + 'Use `answer_only` ONLY when no tool you were offered can produce what was asked for. You '\n + 'have no knowledge of this project beyond what the tools return, so a question a tool can '\n + 'answer must be routed to that tool: answering it yourself would put a plausible-looking '\n + 'invention where the project data belongs. A turn answered this way performs zero actions '\n + 'and returns your text. Name the clause you are answering in `clause`, copied verbatim from '\n + 'the list above: the call covers that clause and no other, so a request with two clauses '\n + 'needs one call per clause you answer.\\n'\n + '\\n'\n + 'Use `mark_unhandled` when no available tool can carry out a clause, naming that clause and '\n + 'saying which capability would be needed. This refuses the whole turn without performing any '\n + 'of it, and that is the correct outcome. Never substitute a tool that looks close: a request '\n + 'nobody can satisfy and a request satisfied by the wrong action are not the same event, and '\n + 'the person can only recover from the first one.\\n'\n + '\\n'\n // THE BOUND ON THE PARAGRAPH ABOVE, AND THE DEFINITION THE ONE BELOW LEANS ON (WINDOWS 110).\n //\n // It sits between them on purpose. The refusal instruction preceded it and \"needs an\n // identifier\" follows it, and until this sentence existed nothing in the prompt said WHICH\n // inputs a tool demands — so a model deciding whether a clause \"needs\" something was deciding\n // it from its own reading rather than from the contract it was handed. 394-30 measured what\n // that costs: on a dist serving `authoring.draft.write` with `required: [\"intent\"]`, a live\n // planner refused the turn by name over \"a target scope identifier\", a requirement its own\n // tool contract denies and a phrase no source file in this repo contains. D-10 then spent the\n // whole turn on it.\n //\n // Stated in the SCHEMA's vocabulary rather than in prose about capabilities, because that is\n // the one form of the rule the model can check against what it was actually sent.\n + \"A tool's required inputs are exactly the `required` list in its schema. Never mark a clause \"\n + 'unhandled because a field outside that list is missing: omit the field, or fill it from the '\n + \"person's own words when they name it.\\n\"\n + '\\n'\n + 'Bind arguments only from what the person actually supplied. If a clause needs an identifier '\n + 'and none was given, that clause is unhandled — do not invent one.',\n}\n\nexport interface ChatPromptInput {\n /** The current message, verbatim — the one payload body this vocabulary carries. */\n readonly utterance: string\n /** The clauses the planner is being asked about, as the splitter produced them. */\n readonly clauses: readonly ChatClause[]\n /** The model in force for this turn, as the session states it. */\n readonly activeModel: string\n /** Session facts as one-liners — refs and counts, never a serialized result (D-18). */\n readonly facts?: readonly string[]\n /**\n * The conversation this turn continues, oldest first, already repaired and PRUNED.\n *\n * `ModelMessage`, and the direction is spelled once (392-06's flagged mismatch, resolved by plan\n * 08's `chat-state.ts`). Log events become `ChatReplayMessage[]` through `replaySession`, that\n * becomes `ModelMessage[]` through `replayToModelMessages`, compaction prunes in THAT form, and\n * this block renders what compaction left. Taking the replay shape here would have needed an\n * inverse projection that could only invent the turn ids pruning discarded.\n */\n readonly conversation?: readonly ModelMessage[]\n}\n\n/**\n * The clauses stage 2 is asked about, numbered BY LIST POSITION rather than by clause index.\n *\n * The engine asks the planner only about the clauses stage 1 could not bind, so this list is a\n * SUBSET of the utterance's clauses — and numbering it by `clause.index + 1` rendered that subset\n * with holes: a two-clause request whose first clause the table resolved arrived as a list starting\n * at \"2.\", under an instruction to make one call per clause of the request. A model reading that\n * plans for the item it cannot see, which is the surplus call the reconciler then cannot attribute\n * (392-VERIFICATION round 3, CR-01's reachability half, WR-02). Contiguous numbering costs nothing\n * and makes the set the model is asked to count the same set the accounting counts.\n */\nfunction renderClauses(clauses: readonly ChatClause[]): string {\n return clauses.map((clause, position) => `${String(position + 1)}. ${clause.text}`).join('\\n')\n}\n\nfunction renderConversation(messages: readonly ModelMessage[]): string {\n return messages\n .map((message) => {\n // Chat only ever produces text content — `replayToModelMessages` carries a one-liner across\n // and compaction truncates strings — so the non-string arm is unreachable through the chat\n // path today. It is handled rather than cast because `ModelMessage` genuinely admits parts,\n // and a cast would put an object's default rendering into a prompt the day it stopped being\n // unreachable.\n const text =\n typeof message.content === 'string' ? message.content : JSON.stringify(message.content)\n return `${message.role}: ${text}`\n })\n .join('\\n')\n}\n\n/**\n * Chat's three tiers, rendered by the one builder.\n *\n * A block is added only when it has content: an empty tier contributes zero bytes by the builder's\n * own contract, and a header over nothing would be a section a reader has to interpret as \"there\n * were none\" rather than \"this host did not say\".\n */\nexport function buildChatPrompt(input: ChatPromptInput): JobModelRequest {\n const context: PromptTierBlock[] = [\n { title: 'Session', body: `Model in force: ${input.activeModel}` },\n ]\n if (input.facts !== undefined && input.facts.length > 0) {\n context.push({ title: 'Session facts', body: input.facts.join('\\n') })\n }\n\n const volatile: PromptTierBlock[] = []\n if (input.conversation !== undefined && input.conversation.length > 0) {\n volatile.push({ title: 'Conversation so far', body: renderConversation(input.conversation) })\n }\n volatile.push({ title: 'Request', body: input.utterance })\n if (input.clauses.length > 0) {\n volatile.push({ title: 'Clauses to answer', body: renderClauses(input.clauses) })\n }\n\n return buildTieredPrompt({\n agent_context: CHAT_AGENT_CONTEXT,\n stable: [ROLE_BLOCK, PLANNING_BLOCK],\n context,\n volatile,\n })\n}\n","// The planner's action vocabulary (Phase 392 plan 04, D-07 / D-08 / D-10).\n//\n// THE TOOLSET IS THE REGISTRY WALK. Every registered op projects 1:1 to a tool, plus exactly two\n// orchestration meta-tools, and nothing else exists. That is the always-send-all law expressed as\n// code rather than as a policy: the model is shown everything this host can do, so a curated subset\n// — the shape that quietly decides on a person's behalf which capabilities are worth mentioning —\n// has nowhere to live. It is also what makes 393-395's arrival free: an op registered there appears\n// here without anyone editing this file, and 397's chat-equals-registry conformance becomes a walk\n// rather than a hand-maintained list.\n//\n// NO TOOL CARRIES AN EXECUTE CALLBACK, and that omission is the load-bearing line in this file.\n// `generateText` runs a tool exactly when the tool has a function to run; with none present it\n// returns the model's plan in `result.toolCalls` and enacts nothing. D-10 requires reconciliation\n// to complete BEFORE the first side effect, and this is the version of that requirement the SDK\n// cannot get wrong — there is no callback to invoke, so there is no ordering to remember.\n//\n// THE WALK CONSUMES DECLARATIONS, NEVER SPECS. A declaration is capability-free by construction\n// (384 BL-01): scalars plus inert JSON-Schema projections, with no live validator and no\n// implementation anywhere on it. So this module holds no dispatch path, and the chat subtree still\n// has exactly one way to run anything — the `ChatInvokeBinding` its composition supplies. The\n// projections it reads are the same views 396's MCP tool listing will consume, which is the point:\n// one description of a capability, rendered by every surface that describes capabilities.\n\nimport { jsonSchema, tool } from 'ai'\nimport type { Tool, ToolSet } from 'ai'\nimport { z } from 'zod'\n\nimport type { FunctionCaller } from '@vostride/agent-qa-schema'\n\nimport type { FunctionDeclaration, FunctionSchemaProjection } from '../functions/spec.js'\nimport {\n HOST_DERIVED_SCOPE_FUNCTION_IDS,\n SESSION_STAMPED_FUNCTION_IDS,\n WINDOW_STAMPED_FUNCTION_IDS,\n} from './session-stamps.js'\nimport {\n ANSWER_ONLY_TOOL_NAME,\n ChatToolNameError,\n MARK_UNHANDLED_TOOL_NAME,\n toToolName,\n} from './tool-names.js'\n\n/**\n * What the projection needs of a registry: the listing, and nothing else.\n *\n * `FunctionRegistry` satisfies this structurally, and the composition root hands one over. Naming\n * the narrower shape here is what keeps the chat subtree's reach honest — this module cannot\n * acquire the registry's internals seam even by accident, because the type it holds does not have\n * one. The claim \"chat can propose only what the registry declares\" is then a fact about what this\n * function was given rather than a rule about what it chose to do with it.\n */\nexport interface PlannerToolSource {\n list(caller: FunctionCaller): readonly FunctionDeclaration[]\n}\n\n/**\n * `answer_only`'s contract: WHICH clause is being answered, and the prose (CHAT-01, CR-03).\n *\n * THE `clause` FIELD IS REQUIRED, and it mirrors `mark_unhandled`'s for the same reason: a turn is\n * made of clauses, so a claim about a turn cannot stand in for a claim about one of them. Without\n * it, one call answering one question consumed every OTHER clause the merge had no binding for —\n * an unroutable action erased with no receipt and no refusal (392-VERIFICATION CR-03).\n */\nexport const ANSWER_ONLY_INPUT_SCHEMA = z.object({\n // NON-EMPTY for the same reason `text` is, one field over (392-15, WR-01). `reconcile.ts` has\n // rejected `clause: \"\"` since the field was required — a claim that names nothing covers nothing\n // — while the contract the model was SHOWN still admitted it. The two halves of one field cannot\n // be allowed to disagree in the direction that lets the model emit a call the reader will refuse.\n clause: z\n .string()\n .min(1)\n .describe(\n 'The part of the request, quoted verbatim from the clauses you were given, that this '\n + 'answer is about.',\n ),\n // NON-EMPTY, and that is the model-facing half of the coverage predicate (392-14). `z.string()`\n // admitted `\"\"`, so the one call that erases a clause — naming it, answering nothing — was\n // inside the contract the model was shown. The reader in `reconcile.ts` moved in the SAME commit\n // and is deliberately one notch stricter (it also rejects whitespace-only prose): the two halves\n // of a claim's meaning cannot be allowed to disagree in the direction that completes more.\n text: z\n .string()\n .min(1)\n .describe('The answer, in prose, for a turn that asks for information.'),\n})\n\n/** `mark_unhandled`'s contract: WHICH clause, and WHY nothing here can carry it out (D-08). */\nexport const MARK_UNHANDLED_INPUT_SCHEMA = z.object({\n clause: z\n .string()\n .describe('The part of the request, quoted from what the person typed, that cannot be done.'),\n reason: z.string().describe('Which capability would be needed, in one sentence.'),\n})\n\nconst ANSWER_ONLY_DESCRIPTION =\n 'Answer the person in prose and perform no action. Use this when the request asks for '\n + 'information rather than for something to happen. ONE CALL PER CLAUSE you are answering, '\n + 'naming that clause in `clause` copied verbatim from the list you were given: this call '\n + 'covers the clause it names and no other, and any clause left neither named here nor bound '\n + 'to a tool refuses the whole turn.'\n\n// THE SECOND SENTENCE IS 394-30's LIVE REFUSAL, ANSWERED AT THE CALL THAT MADE IT. A live planner\n// refused an authoring turn whose only obstacle was an OMITTED OPTIONAL FIELD — one its own tool\n// contract lists outside `required` — so the refusal was never \"no tool here can do this\" but \"I\n// decided a tool I have needs something it says it does not\". That decision is made at the moment\n// this call is emitted, which makes this description the nearest surface to it: the prompt states\n// the general law (chat-prompt.ts) and this states it where the misuse happens.\nconst MARK_UNHANDLED_DESCRIPTION =\n 'Declare that a part of the request cannot be carried out with the tools available. Naming it '\n + 'here refuses the whole turn without performing any of it, which is the correct outcome — '\n + 'never substitute a different tool that looks close. Do not use this because an optional field '\n + 'is missing — optional fields never make a request unhandleable.'\n\nconst HOST_SUPPLIES_WINDOW =\n 'The host supplies a session-scoped `window` when this field is omitted — omit it to ask about '\n + 'the current session; pass `window` only to widen to all-time or last-n.'\n\n// TWO FACTS, AND THE SENTENCE THAT PRECEDED IT GOT BOTH WRONG (394-30, WINDOWS 110).\n//\n// It closed with \"pass `scope` only to author for a DIFFERENT target\" — which reads to a planner as\n// an instruction to WITHHOLD a scope the person has already named, exactly the field the surface is\n// positioned to fill from their own words. And its opening promised a host derivation flatly, while\n// `deriveDefaultAuthoringScope` binds only where the project has ONE candidate product and returns\n// `AuthoringScopeUnresolvableError` otherwise (six candidates on the demo workspace). A model told\n// the host will handle something the host refuses has been handed a false premise to plan against.\n//\n// So this says who fills the field and when, and states the refusal as a refusal. Guessing belongs\n// to NOBODY: the host must not guess among candidates (D-19) and the planner must not invent a\n// requirement its contract denies, which leaves the person's own utterance as the one legitimate\n// source of a scope — and the planner as the only surface positioned to read it. The absent-scope\n// path is thereby a single-product-project affordance, and the sentence says so out loud rather\n// than letting a multi-product project discover it as a refusal.\nconst HOST_DERIVES_SCOPE =\n \"When the person's request names the page, product or target it is for, pass `scope` with that \"\n + \"target's key. When `scope` is omitted the host derives it only when this project has exactly \"\n + 'one candidate product; otherwise the call returns a typed refusal naming every candidate — '\n // The dist-gate sentinel 394-35 greps before it spends, kept whole on ONE source line: a string\n // concatenation folds at build time, so a phrase split across two lines is greppable in the built\n // bytes and invisible in the source the acceptance check reads.\n + 'it never guesses.'\n\n/** A projected JSON-Schema node, as the shape this transform edits it through. */\ntype SchemaNode = Record<string, unknown>\n\nfunction objectNode(value: unknown): SchemaNode | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as SchemaNode)\n : undefined\n}\n\n/** Drop `key` from a node's `required`, and the empty list with it. */\nfunction dropRequired(node: SchemaNode, key: string): void {\n const required = node.required\n if (!Array.isArray(required)) return\n const kept = required.filter((entry) => entry !== key)\n if (kept.length === 0) delete node.required\n else node.required = kept\n}\n\n/**\n * The arms of a projected union, under whichever keyword zod emitted for it.\n *\n * Discriminated unions project as `oneOf` and plain ones as `anyOf`; which keyword carries the\n * arms is a library detail rather than a contract this file may pin.\n */\nfunction unionArms(node: unknown): SchemaNode[] {\n const union = objectNode(node)\n const arms = Array.isArray(union?.oneOf) ? union.oneOf : union?.anyOf\n if (!Array.isArray(arms)) return []\n return arms.map(objectNode).filter((arm): arm is SchemaNode => arm !== undefined)\n}\n\n/**\n * The model-facing view of a declaration's input: the contract, minus what the host stamps.\n *\n * THE SET IS THE STAMP'S OWN. Both sides read `session-stamps.ts`, so the fields withheld here and\n * the fields `stampSessionFacts` writes at the invoke cannot drift; `planner-tools.test.ts` pins\n * the transformed ids SET-EQUAL to the union of the two sets. Showing the model a field the host\n * overwrites unconditionally is what talked a live planner into refusing the call instead of\n * emitting the field-absent step the stamp exists to complete (394-22, G-1).\n *\n * EVERY EDIT IS ON A CLONE. `declaration.input` is the registry's shared inert projection — the\n * same view 396's MCP listing consumes — so an in-place edit here would rewrite what every other\n * surface publishes (T-394-85).\n */\nfunction modelFacingInput(declaration: FunctionDeclaration): FunctionSchemaProjection {\n const withholdsRef = SESSION_STAMPED_FUNCTION_IDS.has(declaration.id)\n const optionalisesWindow = WINDOW_STAMPED_FUNCTION_IDS.has(declaration.id)\n if (!withholdsRef && !optionalisesWindow) return declaration.input\n\n const projected = structuredClone(declaration.input) as SchemaNode\n const properties = objectNode(projected.properties)\n if (properties === undefined) return projected\n\n if (withholdsRef) {\n // Host-owned end to end: the stamp is an overwrite and never a default, so the model is not\n // shown the field at all rather than shown one its value would be discarded from.\n delete properties.sessionRef\n dropRequired(projected, 'sessionRef')\n }\n\n if (optionalisesWindow) {\n // THE `window` PROPERTY STAYS — a model may legitimately widen to all-time or last-n (D-12);\n // only its requiredness goes. THE SESSION ARM'S `sessionRef` DOES NOT: it is host-owned end to\n // end exactly as the top-level field is, so it is removed from the arm rather than merely made\n // optional there (WR-02). The wider arms carry no ref and pass through untouched.\n dropRequired(projected, 'window')\n for (const arm of unionArms(properties.window)) {\n const armProperties = objectNode(arm.properties)\n if (armProperties === undefined || !Object.hasOwn(armProperties, 'sessionRef')) continue\n delete armProperties.sessionRef\n dropRequired(arm, 'sessionRef')\n }\n }\n\n return projected\n}\n\n/**\n * The catalogue's own summary, plus each sentence a host-filled field has to say out loud.\n *\n * APPENDED IN SET ORDER, never a rewrite: `declaration.summary` is what 396's MCP listing renders,\n * so a description built by replacing it would publish two catalogues. An id in both sets would\n * carry both sentences — no id is in both today, and the arrangement is deliberate rather than\n * lucky: nothing forbids it, and the day one arrives it needs both facts told rather than one.\n */\nfunction modelFacingDescription(declaration: FunctionDeclaration): string {\n const sentences = [\n ...(WINDOW_STAMPED_FUNCTION_IDS.has(declaration.id) ? [HOST_SUPPLIES_WINDOW] : []),\n ...(HOST_DERIVED_SCOPE_FUNCTION_IDS.has(declaration.id) ? [HOST_DERIVES_SCOPE] : []),\n ]\n return [declaration.summary, ...sentences].join(' ')\n}\n\n/**\n * Build the model's entire action vocabulary from the capabilities this host declares.\n *\n * The caller is the PLANNER's caller, minted at the composition root with agent origin (Pitfall 1).\n * It matters here only through the registry's own safe-mode listing filter; the equivalence between\n * this set and the walk holds for whichever caller a host supplies, because both sides read the\n * same listing.\n */\nexport function projectPlannerTools(source: PlannerToolSource, caller: FunctionCaller): ToolSet {\n const tools: Record<string, Tool> = {}\n\n for (const declaration of source.list(caller)) {\n const name = toToolName(declaration.id)\n if (Object.hasOwn(tools, name)) {\n // Unreachable while `toToolName` stays injective over the id grammar, and asserted anyway:\n // a silent last-wins here would drop a capability from the model's vocabulary and leave the\n // walk-equivalence test comparing two sets that both lost the same member.\n throw new ChatToolNameError(\n declaration.id,\n `projects onto \"${name}\", which another registered capability already occupies`,\n )\n }\n tools[name] = tool({\n // `dynamic` is the literal truth about these tools rather than a convenience: their input\n // shapes are known at runtime, off the registry this host composed, and not at the time this\n // module is written. It also makes the read-back uniform — every action call comes back with\n // an unknown input the reconciler validates through the function layer's real contract.\n type: 'dynamic',\n description: modelFacingDescription(declaration),\n // The declaration's own inert projection, minus the fields the host stamps at the invoke.\n // Deriving a second schema here would be a second description of a contract the layer\n // already publishes, free to disagree with the validator `invokeFunction` enforces with —\n // so the transform SUBTRACTS from that projection and never restates it.\n inputSchema: jsonSchema(modelFacingInput(declaration) as never),\n // NO `execute`. See the file header — this absence is the mechanism, not an oversight.\n })\n }\n\n tools[ANSWER_ONLY_TOOL_NAME] = tool({\n description: ANSWER_ONLY_DESCRIPTION,\n inputSchema: ANSWER_ONLY_INPUT_SCHEMA,\n })\n tools[MARK_UNHANDLED_TOOL_NAME] = tool({\n description: MARK_UNHANDLED_DESCRIPTION,\n inputSchema: MARK_UNHANDLED_INPUT_SCHEMA,\n })\n\n return tools\n}\n","import type { GateReceipt, RecordId } from '@vostride/agent-qa-schema'\n\n/**\n * 2026-09-06, 416 D-10: replayGateAvailable is true iff a host composition bound this port.\n * Phase 416 binds nothing; Phase 417 binds runReplayGate.\n *\n * 2026-09-11, 422 D-14 — THE ACKNOWLEDGEMENT CONTRACT, stated on the port rather than in the\n * adapter that happens to implement it today.\n *\n * A resolved `runReplayGate` means the returned receipt is DURABLE: the writer capability\n * acknowledged persisting it. It does not mean \"a receipt was generated\". The distinction is\n * the whole point — a Gate-1 run costs replay work no later run can recover, and a caller that\n * read a generated-but-unwritten receipt as a screening result would report a candidate as\n * screened whose evidence nothing can find afterwards, then refuse to screen it again because\n * its own memory says it already did.\n *\n * So the contract is one-sided on purpose: persistence refusal, a stale writer fence, a lease\n * held by somebody else and a dry run are all REFUSALS, surfaced through this port's existing\n * error path as {@link Gate1ReceiptNotPersistedError}. There is no acknowledgement member on\n * the returned receipt, because a receipt that reached this caller at all is already the\n * acknowledged one and a flag saying so would be a second answer to the same question.\n */\nexport interface ReplayGatePort {\n runReplayGate(candidateId: RecordId): Promise<GateReceipt>\n}\n\n/**\n * The Gate-1 call produced a receipt that the writer did not acknowledge persisting (422 D-14).\n *\n * PROVIDER-NEUTRAL, and it lives here rather than in the CLI adapter for the reason every other\n * port refusal does: the caller that has to tell \"screened\" from \"spent but unrecorded\" is the\n * job handler, two packages away from whichever host bound the port, and an adapter-private\n * class would make that distinction reachable only by matching on message text.\n *\n * `recorded` carries the writer's own word for what happened — `dry-run`, `lease-held`,\n * `lease-refused`, or whatever a future writer adds — because a caller deciding whether to\n * retry wants to know WHICH refusal it met, and a boolean would flatten a transient lease\n * contention into the same fact as a deliberate dry run.\n *\n * What this error does NOT carry is the receipt. Handing back the bytes of a receipt nothing\n * stored is exactly the affordance that lets a caller record a screening result the store will\n * never agree with.\n */\nexport class Gate1ReceiptNotPersistedError extends Error {\n override readonly name = 'Gate1ReceiptNotPersistedError'\n\n constructor(\n readonly candidateId: string,\n readonly recorded: string,\n ) {\n super(\n `Gate 1 for candidate ${candidateId} produced a receipt the writer did not acknowledge ` +\n `(${recorded}). The replay work was spent and nothing was persisted, so this call ` +\n 'establishes no screening result for that candidate.',\n )\n }\n}\n","// The agent job queue's store port (Phase 385, D-05 / D-06 / D-07).\n//\n// This port is deliberately NOT generic CRUD. `PersistencePort`'s `saveJob`/`getJob` shape\n// let a caller express any interleaving it liked and left atomicity to review; here every\n// verb is ONE store transaction with a name for what it means, so a wrong interleaving is\n// not a bug the reviewer has to catch — it is a sentence the type surface cannot form\n// (D-05). The engine keeps policy (what may chain, how many attempts); the store keeps\n// atomicity. Every verb is promise-returning so a store may be asynchronous, even though\n// the phase-385 implementation happens to be synchronous underneath.\n//\n// FENCING (D-07). Every DRAIN-side verb — the ones only the process currently entitled to\n// drain the queue may call — takes a `JobStoreFence` and the store re-reads the recorded\n// epoch INSIDE the same transaction before mutating. The fence is present from birth rather\n// than added when the second writer arrives in 386, because retrofitting it onto a live\n// unfenced port means redesigning the commit boundary while split-brain is already possible.\n//\n// `enqueue` is fence-FREE, and that is the resolution of the D-02/D-07 tension rather than\n// an oversight: D-02 says any process may enqueue directly against the database, so an\n// enqueue fence would be a token no enqueuer could hold. Enqueue needs no authority because\n// it arbitrates on data instead — the `(kind, idempotencyKey)` unique index makes a losing\n// concurrent enqueue a dedupe, not a conflict (D-08). Authority is only ever needed to\n// CLAIM or ADVANCE work, which is exactly the set of verbs that carries the fence.\n\nimport type {\n Job,\n JobConclusionKind,\n JobEnqueueRequest,\n JobId,\n JobKind,\n JobStatus,\n} from '@vostride/agent-qa-schema'\n\n/**\n * The authority token a drain-side verb must present.\n *\n * Deliberately a plain epoch record, not an opaque handle: 386 binds the v51 writer lease\n * as its source, and that lease's authority already IS an integer epoch on disk.\n */\nexport interface JobStoreFence {\n readonly epoch: number\n}\n\n/**\n * The semantic unit accepted by the checkpoint persistence boundary.\n *\n * The engine constructs this record and the store owns its durable bytes. Keeping the\n * envelope beside the port makes a foreign raw payload unrepresentable without making the\n * storage-neutral port depend on the engine that consumes it.\n */\nexport interface JobCheckpointRecord {\n readonly checkpointId: string\n readonly jobId: JobId\n readonly attempt: number\n readonly recordedAt: string\n readonly value: unknown\n}\n\n/**\n * Refusal at the mutation boundary, mirroring v51's `WriterAuthorityLostError` shape: a\n * named class carrying both the epoch the caller held and the epoch the store observed, so\n * a log line says which writer was behind and by how much.\n */\nexport class StaleJobStoreEpochError extends Error {\n override readonly name = 'StaleJobStoreEpochError'\n\n constructor(\n readonly heldEpoch: number,\n readonly observedEpoch: number,\n ) {\n super(\n `agent job store authority lost; held epoch ${heldEpoch}, observed ${observedEpoch}`,\n )\n }\n}\n\n/**\n * One job row to insert: a caller's `JobEnqueueRequest` plus what the engine resolved for it.\n *\n * 385 plan 02 split this from the request DTO rather than duplicating it. The request is the\n * three facts a CALLER knows; the two fields added here are derived at the engine boundary\n * and belong to nobody else. The id is derived from `(kind, idempotencyKey)` through an\n * injected id source, so the same logical job carries the same id in every process and in\n * every replay (D-03 corollary) — a store that minted its own would break that, and a caller\n * that supplied its own could break it twice. Timestamps are absent on purpose: the store\n * stamps them from ITS injected clock, so no SQL-side default can leak host time into a dump.\n *\n * There is no separate \"chained enqueue\" type. A successor differs from a root job in who\n * asked for it, not in what it is, and the difference that does matter — a successor is\n * inserted inside its predecessor's transaction — is expressed by the verb it arrives at.\n */\nexport interface JobInsert extends JobEnqueueRequest {\n readonly id: JobId\n readonly summary: string\n}\n\n/**\n * Refusal when an operator tries to requeue a row this build cannot read (422 D-16).\n *\n * A requeue is the one operator verb that DESTROYS history — it resets the attempt count, deletes\n * every checkpoint row and file the last attempt recorded, and disowns the run's chain-terminal\n * notification. For an ordinary terminal row that is the whole point: the row goes back so a fixed\n * handler can run it again. For a quarantined row there is no handler to run it again — no kind\n * registry contains its kind — so the reset would spend the remedy and buy nothing: the very next\n * claim would quarantine the row a second time, and the spent attempt and the fixed reason that\n * recorded WHY it was quarantined would be gone.\n *\n * Raised INSIDE the requeue's transaction and before any of those three media is touched, so a\n * refused requeue leaves the store byte-identical.\n *\n * THE MESSAGE DOES NOT NAME THE KIND, and that is the same rule\n * `QUARANTINED_UNREADABLE_KIND_REASON` states for `last_failure_reason`: the unreadable kind is\n * a string an EARLIER build -- or anything with write access to that database -- put in a\n * column, and this message is rendered on operator terminals and copied into logs.\n * Interpolating it here took the one field of the row this build refuses to trust and pasted it\n * into the one place an operator is most likely to read without thinking. The value stays on\n * `unreadableKind`, where a caller has to ask for it and knows what it is when they do --\n * exactly where the `kind` column keeps it.\n */\nexport class QuarantinedJobRequeueError extends Error {\n override readonly name = 'QuarantinedJobRequeueError'\n\n constructor(\n readonly jobId: string,\n readonly unreadableKind: string,\n ) {\n super(\n `Agent job ${jobId} cannot be requeued: it was recorded under a kind this build does ` +\n 'not read, so it was quarantined at claim rather than handled. No registered kind can ' +\n 'run it, and a requeue would reset its spent attempt and delete the record of why it ' +\n 'was quarantined without making it runnable. The original kind, id and payload are ' +\n 'preserved in the row for inspection. Clear the row deliberately if it is no longer ' +\n 'wanted.',\n )\n }\n}\n\n/**\n * The result of an enqueue.\n *\n * `deduped` reports that the unique index already held this `(kind, idempotencyKey)` pair\n * and `job` is the pre-existing row. A duplicate enqueue is a SUCCESS, never an error —\n * that is what makes \"run the tail twice, get one job\" a store guarantee rather than a\n * convention every caller has to remember (D-08).\n */\nexport interface JobEnqueueOutcome {\n readonly job: Job\n readonly deduped: boolean\n}\n\n/**\n * An empty queue is an ordinary outcome, not an exception.\n *\n * The claim carries the `payload` beside the job because the `Job` DTO does not hold it and\n * should not: the payload is opaque input only the claiming kind's handler knows how to read,\n * while `Job` is the row every observer of the queue sees. Without it on the claim a handler\n * would be a function of its own id and no kind could do real work at all.\n */\nexport type JobClaimOutcome =\n | { readonly claimed: false }\n | { readonly claimed: true; readonly job: Job; readonly payload: unknown }\n\n/**\n * What a claim may be told is not its to take (Phase 388-09, G-388-2 substrate).\n *\n * The exclusion is an OWNERSHIP declaration: a host names the kinds it may not claim, fixed\n * when its queue is composed. A kind on this list must be left exactly as the claim found it\n * — never claimed and released — because per D-18 the attempt is spent AT the claim, and\n * (388-09 Task 1, M-2) a released row is re-offered ahead of every younger row, so a\n * claim-then-release \"refusal\" either burns the row's bound or starves every other kind\n * behind it for as long as the row exists. The only refusal that writes no receipt and\n * costs nothing is one where the excluded row is never offered at all.\n */\nexport interface ClaimNextOptions {\n readonly excludeKinds?: readonly JobKind[]\n}\n\nexport interface JobCompleteOutcome {\n readonly job: Job\n readonly chained: readonly JobEnqueueOutcome[]\n}\n\n/** The terminal parent and continuation rows committed by one permanent-failure transaction. */\nexport interface JobFailAndChainOutcome {\n readonly job: Job\n readonly chained: readonly JobEnqueueOutcome[]\n}\n\n/**\n * How a failed attempt should be disposed of. Behaviour lands with the retry plan.\n *\n * This is NOT a second spelling of the handler's `JobHandlerOutcome`, and the two are kept\n * apart deliberately (385 plan 02). The handler REPORTS whether the thing that went wrong\n * could go right next time; the engine DECIDES what to record, and only the engine knows how\n * many attempts remain. A retryable report on the last permitted attempt becomes a permanent\n * disposition here — which is exactly the bound D-18 puts on retries, and it would have\n * nowhere to live if the report and the decision were one type.\n */\nexport type JobFailureDisposition =\n | { readonly kind: 'retry'; readonly reason: string; readonly retryAfterMs?: number }\n | { readonly kind: 'permanent'; readonly reason: string }\n\nexport type JobCheckpointReadOutcome =\n | { readonly found: false }\n | { readonly found: true; readonly payload: unknown }\n\n/**\n * What asking to cancel a job actually did (D-19).\n *\n * Three outcomes, because cancellation genuinely has three cases and collapsing any two of\n * them loses a guarantee. A job nobody is running stops at once — there is nothing to be\n * cooperative about. A job in flight only records the REQUEST: terminating its row out from\n * under a running handler would abandon a half-finished step and leave whatever it was part\n * way through with no owner, so the driver honours the request at its next checkpoint boundary\n * instead. A job that has already finished, failed or been cancelled reports what it is and\n * nothing moves — a cancel is not an eraser.\n */\nexport type JobCancelOutcome =\n | { readonly outcome: 'cancelled' }\n | { readonly outcome: 'cancel-requested' }\n | { readonly outcome: 'already-terminal'; readonly status: JobStatus }\n\n/**\n * What returning a finished job to the queue actually did (413 D-04/D-06 gap closure).\n *\n * A requeue is an OPERATOR's explicit act under the fence, not a lifecycle transition any\n * handler can reach. It exists because Phase 413's pump composed without the post-run\n * capabilities, the kind registry selected the STAND-IN analyze-run handler, and nineteen\n * rows reached `done` with a checkpoint recorded and nothing authored — a completion the\n * queue has no vocabulary to disown.\n *\n * `requeued` returns the row to `queued` with its attempts reset AND everything its last\n * attempt recorded FORGOTTEN in all three durable media, because they are one remedy rather\n * than three tidy-ups. The checkpoint rows and the checkpoint files go because `readCheckpoint`\n * resolves the LATEST recorded value across attempts, so a reset that kept the stand-in's\n * `verdicts-authored` row would hand the real handler the stand-in's value on the next attempt\n * and it would report completion having written nothing — the very substitution the requeue\n * exists to undo, performed a second time by the recovery path. The chain-terminal notification\n * the attempt minted for the run this job's payload names goes for a stronger reason: the\n * store's insert dedupes on the run (`ON CONFLICT (run_id) DO NOTHING`), so a receipt that\n * survives a requeue can never be replaced by the re-run — it would keep publishing an outcome\n * for an attempt whose every other trace the same transaction just deleted.\n *\n * What the requeue does NOT touch is the row's identity: the id and the\n * `(kind, idempotencyKey)` pair survive, so the chain identity `chainJobIdsForRun` derives\n * from the run id still addresses this row and a re-chained successor dedupes onto the\n * existing slot instead of doubling it. Enqueueing a fresh job under a new key would have\n * been the easier remedy and the wrong one.\n *\n * `not-terminal` is a refusal, and it carries the status it found. A queued or claimed job\n * belongs to a drainer: requeueing one would reset the attempt count out from under a\n * handler that is running, which is the two-writers-under-one-fence tampering the fence\n * exists to exclude.\n */\nexport type JobRequeueOutcome =\n | { readonly outcome: 'requeued' }\n | { readonly outcome: 'not-terminal'; readonly status: JobStatus }\n\n/**\n * Refusal when a driver tries to land a job cancelled that nobody asked to cancel.\n *\n * `cancelled` is reachable through exactly one path — a request, then either an immediate\n * transition or a boundary the driver honoured — and this refusal is what makes that a store\n * invariant instead of a property of the current driver. A future host that decided to\n * \"clean up\" a stuck job by cancelling it directly gets told which step it skipped.\n */\nexport class JobCancellationNotRequestedError extends Error {\n override readonly name = 'JobCancellationNotRequestedError'\n\n constructor(readonly jobId: JobId) {\n super(\n `agent job ${String(jobId)} cannot be recorded as cancelled: no cancellation was ever ` +\n 'requested for it. A job reaches the cancelled state only by being asked to, so a ' +\n 'driver landing one here has skipped the request the operator never made.',\n )\n }\n}\n\n/**\n * What a chain-terminal transition asks the store to record, if it really is terminal\n * (Phase 388, D-09 / D-10 / D-12).\n *\n * The 385 D-05 split, applied to a new decision. POLICY is already resolved by the time this\n * record exists: the engine decided which run this job belongs to, which ids the chain could\n * have enqueued, and what the notification should say. What the STORE decides is the only\n * part that cannot be decided outside a transaction — whether every candidate that exists is\n * terminal at the instant of the write, and whether this run has been notified already.\n *\n * `payloadJson` arrives serialized rather than as a value, and that is deliberate: the record\n * crosses a storageNeutral port into a store whose column is text, and canonical\n * serialization is a shipped primitive. A store that serialized it would be a second place\n * the bytes are decided, and the two would differ on the first key-order question.\n *\n * The parameter is OPTIONAL on both terminal verbs and defaults absent, so every existing\n * caller — the store-contract suite, the kill matrix, every kind that is not a chain member —\n * compiles and behaves exactly as before. A record that arrives for a chain that turns out\n * NOT to be terminal is not an error: the store simply writes nothing.\n */\nexport interface ChainTerminalRecord {\n /** The UNIQUE key one notification per run rests on. `runId` alone (D-10). */\n readonly dedupeKey: string\n /**\n * Every job the chain COULD have enqueued, whether or not it did.\n *\n * Candidates rather than members, because a derived chain id is not a promise that a row\n * exists. `chainJobIdsForRun` derives EVERY one of the chain's ids from the run id alone, up\n * front, while the rows appear one at a time: each successor is enqueued only once its\n * predecessor chains, and a deduped or halted chain leaves a derived id no row will ever\n * carry. The store's rule is therefore stated over the candidates that EXIST — a successor\n * that has not been written yet cannot be read as a finished one, so the terminal cannot fire\n * a job early. The head is the one exception and is checked by name: a chain whose analyze-run\n * row was never written is not a run's chain at all.\n *\n * 2026-09-01 (Phase 409): the chain narrowed to two ids.\n * 2026-09-11 (Phase 422, D-13): three again, the third being the proposal stage the fold now\n * chains to. The candidate/member distinction is what carries that widening for free — a\n * chain halted at a permanently failed fold has no proposal row, and the rule reads it as the\n * absence it is rather than as an unfinished stage that blocks the record forever.\n */\n readonly candidateJobIds: readonly JobId[]\n /** Canonical JSON of the `RunNotification` this terminal would record. */\n readonly payloadJson: string\n}\n\n/** One row of the deterministic logical dump (D-03). Column names, not the DTO shape. */\nexport interface JobStoreDumpRow {\n readonly id: string\n readonly kind: string\n readonly idempotencyKey: string\n readonly status: string\n readonly summary: string\n readonly payload: unknown\n readonly attempts: number\n readonly claimed: boolean\n /**\n * Someone has asked for this job to stop (D-19).\n *\n * Store-owned state, exactly like `claimed`, and for the same reason: `JobStatus` is a\n * shipped kernel vocabulary whose C6 break added the two TERMINAL members the queue needed,\n * and \"a running job that has been asked to stop\" is not a terminal state — it is a fact\n * about what has been asked of a job that is still queued. Adding a status member for it\n * would be a second contract break to describe something no observer of the row needs to\n * treat as a lifecycle stage.\n */\n readonly cancelRequested: boolean\n /**\n * What this row CONCLUDED, when the store can say it from the row alone (422 D-16).\n *\n * Present today for exactly one conclusion, `unreadable_kind`: a row written under a kind this\n * build has since retired, landed permanently at claim without ever being parsed. It belongs on\n * the DIAGNOSTIC projection rather than on `Job` because that is the only projection such a row\n * can travel through at all — `Job.kind` is the strict five-kind enum, so a quarantined row is\n * precisely the row the typed DTO cannot carry. Naming the column-shaped facts here is what lets\n * a listing describe it instead of throwing on it.\n *\n * ABSENT means \"this row concluded nothing the store can name\", which includes an ordinary\n * `done` row and a retired-kind row still sitting queued. It is not a summary of the status.\n */\n readonly conclusionKind?: JobConclusionKind\n readonly createdAt: string\n readonly updatedAt: string\n}\n\n/**\n * A deterministic, ordered, canonical-JSON-comparable projection of everything the store\n * holds. The kill matrix compares THIS across an interrupted and an uninterrupted history —\n * never raw database bytes, whose page layout is not deterministic (D-03).\n */\nexport interface JobStoreDump {\n readonly schemaVersion: number\n readonly epoch: number\n readonly jobs: readonly JobStoreDumpRow[]\n}\n\nexport interface JobStorePort {\n /**\n * Record `epoch` as the authority that may now drain, and hand back the fence proving it.\n * Adopting an epoch BELOW the recorded one is refused: authority only moves forward.\n */\n adoptEpoch(epoch: number): Promise<JobStoreFence>\n\n /** Fence-free by design — see the D-02/D-07 note at the top of this module. */\n enqueue(request: JobInsert): Promise<JobEnqueueOutcome>\n\n /**\n * Offer the next claimable row, honouring an optional kind exclusion in the SELECTION\n * itself — an excluded row is never claimed, so its status, claim and attempt count are\n * untouched (see `ClaimNextOptions`).\n *\n * `options` is OPTIONAL for a reason worth keeping: TypeScript accepts an implementation\n * that declares fewer parameters, so every existing store and every fake in the repo keeps\n * compiling untouched, and the corpus of things that must change is exactly the things\n * that must BEHAVE differently.\n */\n claimNext(fence: JobStoreFence, options?: ClaimNextOptions): Promise<JobClaimOutcome>\n\n /**\n * Terminate one job and enqueue its declared successors in the SAME transaction. Two\n * verbs would leave a window where a crash loses the chain; one verb has no window.\n *\n * `chainTerminal`, when supplied, joins that same transaction (388 D-09): the notification\n * a replayed terminal re-attempts dedupes on a unique index rather than on a caller's\n * memory of having written it.\n */\n completeAndChain(\n jobId: JobId,\n next: readonly JobInsert[],\n fence: JobStoreFence,\n chainTerminal?: ChainTerminalRecord,\n ): Promise<JobCompleteOutcome>\n\n /**\n * Land one permanent failure and enqueue every declared continuation in the SAME fenced\n * transaction. A stale or crashing host therefore exposes neither half or both halves,\n * never a terminal parent with a partial chain (or an orphaned chain with a live parent).\n *\n * Carries the same optional chain-terminal record as its sibling, and that symmetry is\n * D-12: a failure is exactly when the user most needs to hear from the chain, so the\n * notification cannot live on the success path alone.\n */\n failAndChain(\n jobId: JobId,\n disposition: Extract<JobFailureDisposition, { readonly kind: 'permanent' }>,\n next: readonly JobInsert[],\n fence: JobStoreFence,\n chainTerminal?: ChainTerminalRecord,\n ): Promise<JobFailAndChainOutcome>\n\n recordFailure(\n jobId: JobId,\n disposition: JobFailureDisposition,\n fence: JobStoreFence,\n ): Promise<void>\n\n // Refund an aborted attempt and free its claim, keeping last failure, not-before and started_at.\n releaseInterrupted(jobId: JobId, fence: JobStoreFence): Promise<void>\n\n /**\n * Durably publish one checkpoint. The store records the canonical payload and digest in\n * the same fenced transaction that touches the job. A file may be written afterward as a\n * cross-process projection, but that projection never becomes the source of authority.\n */\n publishCheckpoint(\n jobId: JobId,\n checkpointId: string,\n payload: JobCheckpointRecord,\n fence: JobStoreFence,\n ): Promise<void>\n\n /**\n * Ask for a job to stop, and report what that meant for the job it found (D-19).\n *\n * Fenced like every other verb that moves a job, and for the sharper reason: a writer that\n * has lost its lease could otherwise cancel work the current writer is actively running.\n * One transaction, so the decision between \"stop it now\" and \"ask it to stop\" is made\n * against the same row state it is then written to.\n */\n requestCancel(jobId: JobId, fence: JobStoreFence): Promise<JobCancelOutcome>\n\n /**\n * Land a job that was asked to stop, releasing its claim. THE DRIVER'S verb, not a caller's.\n *\n * Separate from `requestCancel` because they are opposite ends of the protocol: one records\n * an intention against a job somebody else is running, the other completes it from inside\n * the run. Refuses with `JobCancellationNotRequestedError` when no request exists, which is\n * what keeps `cancelled` unreachable except through the two-step path.\n */\n recordCancellation(jobId: JobId, fence: JobStoreFence): Promise<void>\n\n /**\n * Return a FINISHED job to the queue, forgetting what its last attempt recorded.\n *\n * Terminal is exactly `done | failed | cancelled` — the store's own `TERMINAL_JOB_STATUSES`\n * — and anything else answers `not-terminal` having moved nothing. The lifecycle reset and\n * the checkpoint forget are ONE fenced transaction, because a row that reads `queued` while\n * its checkpoints still exist is precisely the state that replays a stand-in's recorded\n * authorship as though a handler had produced it.\n *\n * An id no row answers to raises the store's existing not-found error rather than gaining a\n * third outcome arm (413-02 D-4): the outcome union describes what the store found a JOB\n * to be, and a mismatched id is a caller bug, not data.\n */\n requeueTerminal(jobId: JobId, fence: JobStoreFence): Promise<JobRequeueOutcome>\n\n /**\n * Read-side: no fence, because reading claims no authority.\n *\n * Returns the authoritative payload recorded under the fence. A concrete store may serve\n * a file projection only after validating its digest against that record; a missing or\n * mismatched projection falls back to the authoritative record, never to bare file bytes.\n */\n readCheckpoint(jobId: JobId, checkpointId: string): Promise<JobCheckpointReadOutcome>\n\n dumpState(): Promise<JobStoreDump>\n}\n","// The agent job queue engine (Phase 385, D-05 / D-08 / D-17 / D-18 / D-20).\n//\n// Pure semantics. This package is storageNeutral, so nothing here touches a host API: every\n// byte the engine causes to exist crosses `JobStorePort`. The driver is a PUMPABLE function\n// — `runNextJob` does one job and returns — never a loop with timers. Phase 385 ships no\n// production dispatcher at all; the first real host arrives with the daemon, and a driver\n// that owned its own scheduling would have to be taken apart again to let that host own it.\n//\n// All engine-visible time comes from the injected clock. A single ambient timestamp here\n// would make the deterministic dump the crash matrix compares differ for reasons that have\n// nothing to do with correctness (D-03), and the usual repair for a flaky equality\n// assertion is to loosen it — which would quietly retire the proof.\n\nimport type {\n ChainedJobRequest,\n Job,\n JobHandlerOutcome,\n JobId,\n JobKind,\n} from '@vostride/agent-qa-schema'\nimport { canonicalJson } from '@vostride/agent-qa-schema'\n\nimport type { ClockPort } from '../ports/clock.js'\nimport type {\n ChainTerminalRecord,\n ClaimNextOptions,\n JobCancelOutcome,\n JobCheckpointRecord,\n JobEnqueueOutcome,\n JobInsert,\n JobStoreFence,\n JobStorePort,\n} from '../ports/job-store.js'\nimport {\n buildChainTerminalNotification,\n chainJobIdsForRun,\n POST_RUN_CHAIN_TERMINAL_KINDS,\n} from './chain-identity.js'\nimport type {\n JobBackoffPolicy,\n JobKindDeclaration,\n JobKindRegistry,\n} from './kind-registry.js'\nimport { recordLlmAuthorship } from './record-llm-authorship.js'\nimport type {\n JobAuthorCallback,\n JobCheckpointContext,\n JobModelCapability,\n} from './record-llm-authorship.js'\n\n/**\n * Where job ids come from.\n *\n * Injected rather than generated, and derived from `(kind, idempotencyKey)` rather than\n * random, so the same logical job carries the same id in every process and across a replay.\n * A random id would make two dumps of the same history unequal by construction.\n */\nexport interface JobIdSource {\n jobIdFor(kind: JobKind, idempotencyKey: string): JobId\n}\n\n/**\n * Thrown when an enqueue arrives without a usable idempotency key (D-08).\n *\n * The type already requires the argument; this covers the empty string, which types cannot\n * exclude and which would silently collapse every keyless caller onto one queue slot.\n */\nexport class MissingIdempotencyKeyError extends Error {\n override readonly name = 'MissingIdempotencyKeyError'\n\n constructor(readonly jobKind: JobKind) {\n super(\n `An agent job of kind ${jobKind} was enqueued without an idempotency key. Every ` +\n 'enqueue needs one: dedupe is a store guarantee resting on the (kind, key) unique ' +\n 'index, and an empty key would collapse unrelated jobs onto a single slot.',\n )\n }\n}\n\n/** Thrown when a handler asks to chain to a successor its kind never declared (D-17). */\nexport class UndeclaredJobSuccessorError extends Error {\n override readonly name = 'UndeclaredJobSuccessorError'\n\n constructor(\n readonly jobKind: JobKind,\n readonly successorKind: JobKind,\n ) {\n super(\n `Agent job kind ${jobKind} may not chain to ${successorKind}: the successor is not ` +\n 'in its declared topology. The declared set is the auditable one, so a chain that ' +\n 'only exists inside a handler body must not be reachable.',\n )\n }\n}\n\n/** Thrown when a handler publishes a checkpoint its kind never declared. */\nexport class UndeclaredJobCheckpointError extends Error {\n override readonly name = 'UndeclaredJobCheckpointError'\n\n constructor(\n readonly jobKind: JobKind,\n readonly checkpointId: string,\n ) {\n super(\n `Agent job kind ${jobKind} may not publish checkpoint ${checkpointId}: it is not on ` +\n \"the kind's declared checkpoint schedule. Recovery is planned from the declared \" +\n 'schedule, so a checkpoint outside it is state nothing would ever resume from.',\n )\n }\n}\n\n/**\n * Raised at a checkpoint boundary when the job being run has been asked to stop (D-19).\n *\n * A thrown sentinel rather than a return value, because the boundary is inside a capability\n * the handler awaits and there is no other way to unwind a handler from underneath. A handler\n * MAY catch it — cooperative cancellation is cooperative — but catching it buys nothing: the\n * next boundary raises it again, and a kind whose handler swallowed every one of them would\n * simply run to the end, which is the same thing that happens to a kind with no boundary at\n * all. The driver catches it, records the cancellation and reports the boundary it stopped at.\n */\nexport class JobCancelledError extends Error {\n override readonly name = 'JobCancelledError'\n\n constructor(\n readonly jobId: JobId,\n readonly checkpointId: string,\n ) {\n super(\n `agent job ${String(jobId)} was asked to stop and is being cancelled at checkpoint ` +\n `${checkpointId}; work already checkpointed stays recorded and this step never ran`,\n )\n }\n}\n\nexport interface CreateAgentJobQueueOptions {\n readonly store: JobStorePort\n readonly registry: JobKindRegistry\n readonly clock: ClockPort\n readonly idSource: JobIdSource\n /**\n * The model a job may author with, bound by the composition root (D-10).\n *\n * REQUIRED, and deliberately not defaultable. An optional capability would mean a queue\n * could be built with none, and the only sensible behaviour for an author callback that\n * cannot reach a model is to fail somewhere far from the composition that forgot it. Making\n * it an argument of construction puts that decision where the binding is made. The engine\n * never calls it: the only thing that happens to this value is that the authorship\n * primitive hands it to an author callback, carrying the job's signal when a host passed one.\n */\n readonly model: JobModelCapability\n /**\n * The kinds this host may never claim, fixed when its queue is composed (388-09).\n *\n * A CONSTRUCTION option, deliberately not a member of `RunNextJobInput`: whether a host\n * may claim a kind is a fact about the HOST — which capabilities its composition can bind\n * — and putting it on the per-call input would make it a decision every pump site\n * re-makes, with every pump site a place the answers could diverge. Absent means what it\n * means today: every declared kind is this host's to take.\n */\n readonly unclaimableKinds?: readonly JobKind[]\n}\n\nexport interface RunNextJobInput {\n readonly fence: JobStoreFence\n // 2026-10-19 (444.1-13, D-01): reaches every model request of the claimed job; an attempt\n // that fails while it is aborted is released with its attempt refunded.\n readonly signal?: AbortSignal\n}\n\n/** Facts every ran outcome carries, whatever the job's disposition turned out to be. */\nexport interface RanJobOutcomeBase {\n readonly ran: true\n /** The job AS CLAIMED. The store owns what its row says afterwards. */\n readonly job: Job\n readonly checkpointsPublished: readonly string[]\n /**\n * `false` in exactly one case: the attempt bound was already spent when the job was\n * claimed, so the driver failed it without handing it to its handler (D-18).\n */\n readonly handlerInvoked: boolean\n /**\n * The payload of the job AS CLAIMED, so a host can attribute this outcome to whatever the\n * payload names — a run, above all — without going back to the store for a row the job has\n * already moved past (406 D-16). Optional because the outcome is the engine's fact and the\n * payload is the caller's: nothing here reads it, and no fabricated outcome must grow a\n * field to keep compiling.\n */\n readonly payload?: unknown\n}\n\nexport type RunNextJobOutcome =\n | { readonly ran: false; readonly reason: 'no-job' }\n | (RanJobOutcomeBase & {\n readonly disposition: 'completed'\n readonly chained: readonly JobEnqueueOutcome[]\n })\n | (RanJobOutcomeBase & {\n readonly disposition: 'retry-scheduled'\n readonly reason: string\n /**\n * How long a host should wait before pumping this job again, computed from the kind's\n * declared backoff policy and the attempt just spent.\n *\n * Returned rather than applied: 385 ships no dispatcher, and a driver that slept on its\n * own would be the timer loop this engine deliberately is not. The same value goes to the\n * store as the disposition's `retryAfterMs`, which stores the row's not-before time from\n * its own clock and keeps the row out of every claim until then (444.1 D-23).\n */\n readonly retryDelayMs: number\n readonly attemptsRemaining: number\n })\n | (RanJobOutcomeBase & {\n readonly disposition: 'cancelled'\n /**\n * The checkpoint the driver refused to publish, i.e. WHERE the request was honoured.\n *\n * Named rather than implied, because \"cancelled\" alone cannot say how much of the job\n * had already happened, and `checkpointsPublished` beside it says exactly that: the\n * steps in that list are done and durable, this one never started.\n */\n readonly honoredAtCheckpoint: string\n })\n | (RanJobOutcomeBase & {\n readonly disposition: 'failed'\n readonly reason: string\n /** What the kind's declared disposition enqueued — empty for a halt-chain kind. */\n readonly continuation: readonly JobEnqueueOutcome[]\n })\n | (RanJobOutcomeBase & {\n readonly disposition: 'interrupted'\n // `handler-threw: …` or the aborted attempt's retryable reason.\n readonly reason: string\n })\n\nexport interface CancelJobInput {\n readonly jobId: JobId\n readonly fence: JobStoreFence\n}\n\nexport interface RecoverAbandonedClaimsInput {\n readonly fence: JobStoreFence\n}\n\nexport interface RecoverAbandonedClaimsOutcome {\n readonly released: readonly JobId[]\n}\n\nexport interface AgentJobQueue {\n /**\n * Enqueue one job. The key is MANDATORY and there is no keyless overload — dedupe has to\n * be impossible to opt out of, or \"running the tail twice produces one job\" degrades from\n * a guarantee into a habit.\n */\n enqueue(kind: JobKind, payload: unknown, idempotencyKey: string): Promise<JobEnqueueOutcome>\n\n /** Claim, run, checkpoint and dispose of exactly one job. Returns when that job is done. */\n runNextJob(input: RunNextJobInput): Promise<RunNextJobOutcome>\n\n /**\n * Ask for one job to stop (D-19).\n *\n * Built with the driver rather than after it. The place a cooperative cancel is honoured is\n * the seam between declared checkpoints, and that seam only exists inside `runNextJob` —\n * adding the check later would mean reopening engine core with handlers already written\n * against it. 385 exposes this on no surface at all; the phases that own job UX do that.\n */\n cancel(input: CancelJobInput): Promise<JobCancelOutcome>\n\n /**\n * Return every outstanding claim to the queue, keeping the attempt each one spent.\n *\n * A host that dies while holding a job leaves its row claimed and nothing reaps it, so\n * without this the bound above is unreachable for exactly the job it exists to stop: a\n * poison job would sit claimed forever instead of exhausting its attempts and failing. The\n * attempt is deliberately NOT refunded — that is what makes the bound survive a crash.\n *\n * Call it after adopting authority and BEFORE pumping. Only one process may drain under a\n * given fence, so at that moment every outstanding claim belongs to a host that is gone;\n * calling it beside a live pump would take a job away from the handler still running it.\n */\n recoverAbandonedClaims(\n input: RecoverAbandonedClaimsInput,\n ): Promise<RecoverAbandonedClaimsOutcome>\n}\n\n/**\n * The delay a host should wait after spending `attempt`, per the kind's declared policy.\n *\n * A pure function of the policy and the attempt number — no clock is read here and none can\n * be, which is what keeps a kind's retry behaviour describable without running it.\n */\nfunction retryDelayMs(policy: JobBackoffPolicy, attempt: number): number {\n if (policy.kind === 'none') return 0\n if (policy.kind === 'fixed') return policy.delayMs\n const grown = policy.initialDelayMs * policy.factor ** Math.max(0, attempt - 1)\n return Math.min(grown, policy.maxDelayMs)\n}\n\n/** The summary a job carries when its caller supplied none. Deterministic on purpose. */\nfunction defaultSummary(kind: JobKind, idempotencyKey: string): string {\n return `agent job ${kind} (${idempotencyKey})`\n}\n\nexport function createAgentJobQueue(options: CreateAgentJobQueueOptions): AgentJobQueue {\n const { store, registry, clock, idSource, model, unclaimableKinds } = options\n // Resolved once at construction, so every pump passes the same exclusion or none at all;\n // a queue built without the option calls `claimNext(fence)` exactly as it did before.\n // Copied and frozen at construction, never captured by reference (WR-11): the caller keeps a\n // handle on the array it passed, and a queue that claimed against that live array would let\n // a post-construction write to it re-arm the exclusion this guard exists to hold.\n const claimOptions: ClaimNextOptions | undefined =\n unclaimableKinds === undefined\n ? undefined\n : Object.freeze({ excludeKinds: Object.freeze([...unclaimableKinds]) })\n\n function requestFor(kind: JobKind, payload: unknown, idempotencyKey: string): JobInsert {\n // An undeclared kind is refused before anything is written: the store would happily\n // hold a row no handler can ever pick up, and that row is indistinguishable from a\n // stuck job forever after.\n registry.require(kind)\n if (idempotencyKey.trim() === '') {\n throw new MissingIdempotencyKeyError(kind)\n }\n return {\n id: idSource.jobIdFor(kind, idempotencyKey),\n kind,\n idempotencyKey,\n summary: defaultSummary(kind, idempotencyKey),\n payload,\n }\n }\n\n function successorRequests(\n declaration: JobKindDeclaration,\n next: readonly ChainedJobRequest[],\n ): JobInsert[] {\n return next.map((successor) => {\n if (!declaration.allowedSuccessors.includes(successor.kind)) {\n throw new UndeclaredJobSuccessorError(declaration.kind, successor.kind)\n }\n return requestFor(successor.kind, successor.payload, successor.idempotencyKey)\n })\n }\n\n /**\n * The notification a finishing job should carry INTO its terminal transaction, if it is one\n * (388 D-09 / D-10 / D-12).\n *\n * Three conditions, and each excludes a different wrong record. The kind must be one whose\n * finish can end a post-run chain — an unrelated kind has no run and no stages to report.\n * The payload must name a run — a chain-member job enqueued by a harness with a scripted\n * payload is not a run's chain, and inventing a dedupe key for it would collide with a real\n * one. And the job must be chaining NOTHING: enqueuing a successor in this very transaction\n * is the definition of a chain that has not finished, which is also why this is decided from\n * the inserts rather than from the kind's declared topology.\n *\n * What is NOT decided here is whether the chain's other members are terminal. That is a\n * question about rows at the instant of the write, and only the store can ask it inside the\n * transaction that answers it (385 D-05).\n */\n function chainTerminalFor(input: {\n readonly job: Job\n readonly payload: unknown\n readonly next: readonly JobInsert[]\n readonly finished: 'done' | 'failed'\n readonly publishedValues: ReadonlyMap<string, unknown>\n }): ChainTerminalRecord | undefined {\n if (!POST_RUN_CHAIN_TERMINAL_KINDS.includes(input.job.kind)) return undefined\n if (input.next.length > 0) return undefined\n const record =\n input.payload !== null && typeof input.payload === 'object' && !Array.isArray(input.payload)\n ? (input.payload as Record<string, unknown>)\n : {}\n const runId = record.runId\n if (typeof runId !== 'string' || runId === '') return undefined\n\n const ids = chainJobIdsForRun(runId, idSource)\n return {\n dedupeKey: runId,\n // All THREE derived ids since 422 D-13. The store's rule is stated over the candidates that\n // EXIST, so a chain halted at the fold — whose proposal row was never written — still\n // terminates, while a chain that enqueued the proposal job cannot notify before it lands.\n candidateJobIds: [ids.analyzeRun, ids.curateMemory, ids.proposeImprovements],\n payloadJson: canonicalJson(\n buildChainTerminalNotification({\n runId,\n finishingKind: input.job.kind,\n finished: input.finished,\n payload: input.payload,\n publishedValues: input.publishedValues,\n }),\n ),\n }\n }\n\n /**\n * Land one job permanently, running whatever continuation its kind declared (D-20).\n *\n * Validation and deterministic request construction happen before durability. The store then\n * receives the terminal parent and the complete continuation set in one fenced call, so there\n * is no ordering choice here and no crash window for the engine to repair on replay.\n */\n async function failPermanently(input: {\n readonly job: Job\n readonly payload: unknown\n readonly declaration: JobKindDeclaration\n readonly reason: string\n readonly handlerInvoked: boolean\n readonly published: readonly string[]\n readonly publishedValues: ReadonlyMap<string, unknown>\n readonly fence: JobStoreFence\n }): Promise<RunNextJobOutcome> {\n const { job, declaration, reason, fence } = input\n const requests =\n declaration.onPermanentFailure === 'halt-chain'\n ? []\n : declaration.onPermanentFailure({ job, payload: input.payload, reason })\n\n // Validated before a single store call: an undeclared continuation is a wrong\n // declaration, and half of one already enqueued is worse than none.\n const inserts = successorRequests(declaration, requests)\n\n // D-12: a permanent failure is a chain terminal too. Wiring notify into the completion\n // path alone would leave the runs a user most needs to hear about silent — a curation that\n // exhausted its attempts lands HERE and nowhere else.\n const failed = await store.failAndChain(\n job.id,\n { kind: 'permanent', reason },\n inserts,\n fence,\n chainTerminalFor({\n job,\n payload: input.payload,\n next: inserts,\n finished: 'failed',\n publishedValues: input.publishedValues,\n }),\n )\n\n return {\n ran: true,\n disposition: 'failed',\n job: failed.job,\n payload: input.payload,\n checkpointsPublished: input.published,\n handlerInvoked: input.handlerInvoked,\n reason,\n continuation: failed.chained,\n }\n }\n\n return {\n async enqueue(kind, payload, idempotencyKey) {\n return store.enqueue(requestFor(kind, payload, idempotencyKey))\n },\n\n async cancel({ jobId, fence }) {\n // Pure delegation on purpose: which of the three things a cancel means depends on the\n // row's state at the instant of the write, and only the store can read and write that\n // in one transaction. An engine that decided here would be deciding from a read it had\n // already let go of.\n return store.requestCancel(jobId, fence)\n },\n\n async recoverAbandonedClaims({ fence }) {\n const dump = await store.dumpState()\n const released: JobId[] = []\n for (const row of dump.jobs) {\n if (!row.claimed) continue\n const jobId = row.id as JobId\n await store.recordFailure(\n jobId,\n { kind: 'retry', reason: 'the claim was abandoned by a host that did not finish it' },\n fence,\n )\n released.push(jobId)\n }\n return { released }\n },\n\n async runNextJob({ fence, signal }) {\n const claim =\n claimOptions === undefined\n ? await store.claimNext(fence)\n : await store.claimNext(fence, claimOptions)\n if (!claim.claimed) {\n return { ran: false, reason: 'no-job' }\n }\n\n const job = claim.job\n const declaration = registry.require(job.kind)\n const published: string[] = []\n /**\n * What each checkpoint this attempt published actually said.\n *\n * Kept beside the id list rather than read back from the store, because the one consumer\n * — the chain-terminal notification's curation counts — is assembled microseconds before\n * the transaction that ends the job, and a read there would be querying rows that\n * transaction is about to change. It is per-ATTEMPT state on purpose: a resumed job that\n * did not re-publish a step carries no value for it, and reporting the previous attempt's\n * numbers as this one's is exactly the kind of quiet wrongness a checkpoint exists to\n * prevent.\n */\n const publishedValues = new Map<string, unknown>()\n\n // D-18's bound, enforced HERE — on the claim, which is the one point a job that kills\n // its host cannot skip. Checked only when recording a failure it would never fire for a\n // handler that never returns, and that handler is exactly the one the bound is for. The\n // attempt was already spent by the claim, so a job arriving with more attempts than its\n // kind permits has had every attempt it was owed.\n if (job.attempts > declaration.maxAttempts) {\n return failPermanently({\n job,\n payload: claim.payload,\n declaration,\n reason:\n `the attempt bound of ${declaration.maxAttempts} is spent (this claim is attempt ` +\n `${job.attempts}), so this agent job is given up on without being run again`,\n handlerInvoked: false,\n published,\n publishedValues,\n fence,\n })\n }\n\n // One gate for both directions. Recovery is planned from the declared schedule, so an\n // id outside it is state nothing would ever resume from — whether a handler is writing\n // it or an authorship primitive is looking for it.\n const requireDeclaredCheckpoint = (checkpointId: string): void => {\n if (!declaration.checkpointed || !declaration.checkpointSchedule.includes(checkpointId)) {\n throw new UndeclaredJobCheckpointError(job.kind, checkpointId)\n }\n }\n\n /**\n * THE checkpoint boundary (D-19). Both ways into a checkpoint pass through here.\n *\n * The cancellation state is re-read every time rather than read once at the claim: a\n * cancel that arrived while the job was running is precisely the case this exists for,\n * and a value cached before the handler started could never see it. Reading it at the\n * boundary is also what makes the boundary the boundary — the step in flight completes\n * and is published, and the NEXT one never begins.\n *\n * A declaration error is decided first: a handler naming a checkpoint its kind never\n * declared is wrong whether or not anyone asked the job to stop.\n */\n let honoredAtCheckpoint: string | undefined\n const enterCheckpointBoundary = async (checkpointId: string): Promise<void> => {\n requireDeclaredCheckpoint(checkpointId)\n const dump = await store.dumpState()\n const row = dump.jobs.find((candidate) => candidate.id === String(job.id))\n if (row?.cancelRequested === true) {\n // Remembered as well as thrown, and the FIRST boundary wins. A refusal at a boundary\n // IS the cancellation being honoured, so a handler that catches the sentinel and\n // carries on cannot take that back — its later boundaries refuse too, and the job\n // lands cancelled whatever it eventually reports.\n honoredAtCheckpoint ??= checkpointId\n throw new JobCancelledError(job.id, checkpointId)\n }\n }\n\n const landCancelled = async (boundary: string): Promise<RunNextJobOutcome> => {\n await store.recordCancellation(job.id, fence)\n return {\n ran: true,\n disposition: 'cancelled',\n job,\n payload: claim.payload,\n checkpointsPublished: published,\n handlerInvoked: true,\n honoredAtCheckpoint: boundary,\n }\n }\n\n const publish = async (checkpointId: string, value: unknown): Promise<void> => {\n await enterCheckpointBoundary(checkpointId)\n const record: JobCheckpointRecord = {\n checkpointId,\n jobId: job.id,\n attempt: job.attempts,\n recordedAt: clock.now(),\n value,\n }\n await store.publishCheckpoint(job.id, checkpointId, record, fence)\n published.push(checkpointId)\n publishedValues.set(checkpointId, value)\n }\n\n const jobModel: JobModelCapability =\n signal === undefined\n ? model\n : {\n modelId: model.modelId,\n ...(model.vision === undefined ? {} : { vision: model.vision }),\n generate: (request) => model.generate({ ...request, signal }),\n }\n\n const landInterrupted = async (reason: string): Promise<RunNextJobOutcome> => {\n await store.releaseInterrupted(job.id, fence)\n return {\n ran: true,\n disposition: 'interrupted',\n job,\n payload: claim.payload,\n checkpointsPublished: published,\n handlerInvoked: true,\n reason,\n }\n }\n\n // The context that carries the model. It is built here and handed to the authorship\n // primitive; it is NOT part of what the handler receives, which is the structural half\n // of \"a job has no ambient model accessor\" (D-11 layer 2).\n const checkpointContext: JobCheckpointContext = {\n jobId: job.id,\n model: jobModel,\n async readRecordedValue(checkpointId) {\n // The same boundary. An authorship that is about to consult a model is exactly where\n // a pending cancel is worth the most, so the request is honoured BEFORE the call\n // rather than after it, and the answer nobody will use is never paid for.\n await enterCheckpointBoundary(checkpointId)\n const recorded = await store.readCheckpoint(job.id, checkpointId)\n // The envelope is peeled UNCONDITIONALLY, and that is a fact about the writer rather\n // than a guess about the bytes: `publish` just above is the only thing that ever\n // writes a checkpoint payload, and it always wraps the authored value in a\n // `JobCheckpointRecord`. Testing the payload's shape first would be re-deriving from\n // the bytes something the engine already knows — and it cannot even do that\n // faithfully, because canonical JSON has no member for a `value` of `undefined`, so\n // the envelope of an authored `undefined` reads back one key short of the one that\n // was written and is indistinguishable from a payload nothing wrapped. The primitive\n // would then answer a bare value on the first pass and an envelope on the resume:\n // two functions wearing one name, which is the failure its own contract forswears.\n //\n // Exactly one level is peeled, so an authored object carrying a `value` key of its\n // own comes back whole. `recorded` remains the discriminant — `{recorded: true,\n // value: undefined}` is a checkpoint that holds `undefined`, never an absent one.\n return recorded.found\n ? { recorded: true, value: (recorded.payload as JobCheckpointRecord).value }\n : { recorded: false }\n },\n publishCheckpoint: publish,\n }\n\n let outcome: JobHandlerOutcome\n try {\n outcome = await declaration.handler({\n job,\n payload: claim.payload,\n publishCheckpoint: publish,\n recordLlmAuthorship: async <T>(\n checkpointId: string,\n author: JobAuthorCallback<T>,\n ): Promise<T> => recordLlmAuthorship(checkpointContext, checkpointId, author),\n })\n } catch (error) {\n // Only THIS job's sentinel is a cancellation. A handler that ran a nested job and let\n // its refusal escape would otherwise land the wrong row cancelled.\n if (error instanceof JobCancelledError && String(error.jobId) === String(job.id)) {\n return landCancelled(honoredAtCheckpoint ?? error.checkpointId)\n }\n // Declaration refusals are engine invariants, not handler failures. Turning one into\n // a retry would hide a programming error behind backoff and make an impossible\n // checkpoint look transient.\n if (error instanceof UndeclaredJobCheckpointError) throw error\n\n const reason = `handler-threw: ${error instanceof Error ? error.message : String(error)}`\n // Before the bound: an aborted attempt did not fail, so even the last one is not spent.\n if (signal?.aborted === true) return landInterrupted(reason)\n if (job.attempts < declaration.maxAttempts) {\n const delayMs = retryDelayMs(declaration.backoff, job.attempts)\n await store.recordFailure(job.id, { kind: 'retry', reason, retryAfterMs: delayMs }, fence)\n return {\n ran: true,\n disposition: 'retry-scheduled',\n job,\n payload: claim.payload,\n checkpointsPublished: published,\n handlerInvoked: true,\n reason,\n retryDelayMs: delayMs,\n attemptsRemaining: declaration.maxAttempts - job.attempts,\n }\n }\n\n return failPermanently({\n job,\n payload: claim.payload,\n declaration,\n reason,\n handlerInvoked: true,\n published,\n publishedValues,\n fence,\n })\n }\n\n // The handler returned normally — but if a boundary refused along the way it swallowed\n // the refusal, and a swallowed cancel is still a cancel. Reached only in that case: a\n // job whose boundaries all passed leaves this undefined, which is what keeps a cancel\n // arriving after the last checkpoint from retroactively discarding finished work.\n if (honoredAtCheckpoint !== undefined) {\n return landCancelled(honoredAtCheckpoint)\n }\n\n // The discriminant is READ, not merely accepted. A driver that ignored it and reached\n // for `next` would complete a job whose handler had just said it failed, and the row\n // would read `done` forever after with nothing recording that anything went wrong.\n if (outcome.status === 'complete') {\n const inserts = successorRequests(declaration, outcome.next)\n const completed = await store.completeAndChain(\n job.id,\n inserts,\n fence,\n chainTerminalFor({\n job,\n payload: claim.payload,\n next: inserts,\n finished: 'done',\n publishedValues,\n }),\n )\n return {\n ran: true,\n disposition: 'completed',\n job: completed.job,\n payload: claim.payload,\n checkpointsPublished: published,\n handlerInvoked: true,\n chained: completed.chained,\n }\n }\n\n if (outcome.status === 'retryable' && signal?.aborted === true) {\n return landInterrupted(outcome.reason)\n }\n\n // A retryable REPORT on the last permitted attempt becomes a permanent DECISION: the\n // handler says the thing that went wrong could go right next time, and only the engine\n // knows there is no next time. That asymmetry is why the report and the decision are\n // two types rather than one.\n if (outcome.status === 'retryable' && job.attempts < declaration.maxAttempts) {\n const delayMs = retryDelayMs(declaration.backoff, job.attempts)\n await store.recordFailure(\n job.id,\n { kind: 'retry', reason: outcome.reason, retryAfterMs: delayMs },\n fence,\n )\n return {\n ran: true,\n disposition: 'retry-scheduled',\n job,\n payload: claim.payload,\n checkpointsPublished: published,\n handlerInvoked: true,\n reason: outcome.reason,\n retryDelayMs: delayMs,\n attemptsRemaining: declaration.maxAttempts - job.attempts,\n }\n }\n\n // Either the handler said the failure is permanent — which skips every remaining\n // attempt, because retrying something that cannot succeed only spends the bound — or it\n // said retryable on the attempt that used the bound up.\n return failPermanently({\n job,\n payload: claim.payload,\n declaration,\n reason: outcome.reason,\n handlerInvoked: true,\n published,\n publishedValues,\n fence,\n })\n },\n }\n}\n","// The one memoizing checkpointed effect (Phase 385, D-10 / D-11 layer 2).\n//\n// Every job's access to a model goes through this function and there is no second route. The\n// capability arrives as the author callback's ARGUMENT, so a handler cannot obtain one on its\n// own however it is written: the context that carries the model is built by the engine and is\n// never handed to a handler, and the handler-facing surface has no member of that kind and\n// nowhere to grow one (pinned by exact `keyof` equality in the tests). That is why this\n// package can stay provider-neutral while jobs still author with a model — the model is a\n// value the composition binds at the edge, never a name this package resolves.\n//\n// The control flow is the guarantee, not an optimization:\n//\n// 1. read the recorded value for this checkpoint\n// 2. HIT -> return the recorded bytes; `author` is never reached at all\n// 3. MISS -> invoke `author` exactly once, publish what it produced, THEN return\n//\n// Step 3's order is the whole of JOBQ-03. A resume can only be re-invocation-free if the bytes\n// were durable before the caller ever saw them, so publishing after the return — or without\n// awaiting it — would leave a window in which a host dies holding an answer no store accepted,\n// and the next host has no choice but to ask the model again. The publish is awaited and its\n// failure propagates; this function never hands back a value the store has not taken.\n//\n// The memoization lives HERE and nowhere else. A conditional re-author written into a handler\n// (`if (!checkpoint) …`) is still a re-author, and five kinds each carrying their own copy of\n// that conditional is five chances to get it wrong — which is exactly the anti-pattern the\n// research names.\n//\n// 2026-09-01 (Phase 409): five rather than six — the reserved sixth job kind left with the\n// Issue-slot cleanup.\n\nimport type { JobId } from '@vostride/agent-qa-schema'\n\n/**\n * What an author asks a model for.\n *\n * Minimal on purpose. This package cannot name a provider SDK, so the capability is described\n * structurally and the composition root adapts the real thing onto it. A wider shape here\n * would be a second, drifting copy of a vocabulary that already has an owner.\n */\nexport interface JobModelRequest {\n readonly system?: string\n readonly prompt: string\n /**\n * Optional image parts riding the SAME request (389 D-02). Screenshots are\n * capability-gated per the v46 negotiation the host binding surfaces as `vision` below:\n * an author attaches evidence bytes here only when the capability advertises vision AND\n * a blob reader is bound. Absent means a text-only request — the L9 graceful-degradation\n * posture — and every pre-widening caller and stub stays assignable unchanged.\n */\n readonly images?: readonly Uint8Array[]\n // 2026-10-19 (444.1-13, D-01): set by the engine from the host's per-run signal.\n readonly signal?: AbortSignal\n}\n\n/** What a model answered. Text, because a caller that needs structure parses it. */\nexport interface JobModelOutput {\n readonly text: string\n}\n\n/**\n * The model, as a job may see it (D-11 layer 2).\n *\n * A TYPE, never an import: a job handler receives a value shaped like this from exactly one\n * place — the author callback's parameter — and the barrel publishes no accessor that could\n * produce one. `modelId` is here so a checkpoint's provenance is recordable without the engine\n * having to know anything else about the binding.\n */\nexport interface JobModelCapability {\n readonly modelId: string\n /**\n * Whether the bound model accepts image parts (389 D-02) — the v46 capability\n * negotiation surfaced as one flag by the host binding. OPTIONAL and absent means\n * text-only: a text-only BYOM binding and every existing stub keep compiling and keep\n * their L9 posture without declaring anything. Nothing else in the memoization\n * contract moves with this flag.\n */\n readonly vision?: boolean\n generate(request: JobModelRequest): Promise<JobModelOutput>\n}\n\n/**\n * What a checkpoint already holds, with the engine's envelope already peeled.\n *\n * The engine owns the envelope (attempt, recorded-at, the job it belongs to) and the store\n * owns the bytes; this primitive is handed the VALUE, so the same call returns the same thing\n * whether it authored it a moment ago or is reading it back after a crash. A primitive that\n * returned an envelope on resume and a bare value on the first pass would be two functions\n * wearing one name.\n */\nexport type JobRecordedValueOutcome =\n | { readonly recorded: false }\n | { readonly recorded: true; readonly value: unknown }\n\n/**\n * The narrow context the engine builds for one claimed job.\n *\n * It carries the model and no handler ever receives it. Everything a handler can reach is on\n * `JobHandlerContext`, whose member set is pinned for exact equality — so \"there is no ambient\n * model accessor\" is a fact about the type surface rather than a habit of the code.\n */\nexport interface JobCheckpointContext {\n readonly jobId: JobId\n readonly model: JobModelCapability\n readRecordedValue(checkpointId: string): Promise<JobRecordedValueOutcome>\n publishCheckpoint(checkpointId: string, value: unknown): Promise<void>\n}\n\n/** The only signature that ever receives a model inside a job. */\nexport type JobAuthorCallback<T> = (model: JobModelCapability) => Promise<T>\n\n/**\n * The primitive, partially applied to one job. This is what a handler is handed.\n *\n * Present on every kind's handler context, including uncheckpointed ones: calling it there is\n * refused by name rather than being unavailable, because an optional member would push a\n * `?.()` into every handler and make \"this kind cannot author\" a runtime shrug instead of a\n * refusal that says which declaration is wrong.\n */\nexport type BoundRecordLlmAuthorship = <T>(\n checkpointId: string,\n author: JobAuthorCallback<T>,\n) => Promise<T>\n\nexport async function recordLlmAuthorship<T>(\n context: JobCheckpointContext,\n checkpointId: string,\n author: JobAuthorCallback<T>,\n): Promise<T> {\n const recorded = await context.readRecordedValue(checkpointId)\n if (recorded.recorded) {\n // The resume path. `author` is not merely skipped — control never reaches it, so there is\n // no flag, no option and no argument that could make a resumed job invoke a model.\n return recorded.value as T\n }\n\n const authored = await author(context.model)\n // Awaited BEFORE the return, so what the caller receives is what the store already holds.\n await context.publishCheckpoint(checkpointId, authored)\n return authored\n}\n"],"mappings":"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","names":["refused","errorTextOf","exercisedAnchors","failingStepOf","failureFingerprint","resolveRunVerdicts","slugBranch","canonicalJson","CURRENT_ANALYSIS_SCHEMA_VERSION","CurationSnapshotSchema","errorTextOf","failingStepOf","RunNotificationSchemaError","validateAnalysisAgainstHandoff","canonicalJson","failingStepOf","z","entry","failingStepOf","z","entry","canonicalJson","asRecord","CurationSnapshotSchema","RunNotificationSchemaError","isCount","failingStepOf","errorTextOf","refused","parts","CURRENT_ANALYSIS_SCHEMA_VERSION","validateAnalysisAgainstHandoff","canonicalJson","verdicts","allowance","failingStepOf","failureFingerprint","exercisedAnchors","errorTextOf","resolveRunVerdicts","slugBranch","entry","TestEditPatchSetSchema","suiteTestRef","entry","suiteTestRef","entry","entry","TestEditPatchSetSchema","parsePatchSet","TestEditPatchSetSchema","stepOutcomeUnproven","stepOutcomeUnproven","identityOf","TestEditPatchSetSchema","named","entry","DraftReceiptSchema","DRAFT_STABILITY_RUNS_N","tokens","entry","gateReason","DRAFT_STABILITY_RUNS_N","DRAFT_STABILITY_RUNS_N","DraftReceiptSchema","entry","outcome","ConfigChangeOutputSchema","ConfigChangeOutputSchema","ConfigChangeOutputSchema","ConfigChangeOutputSchema","ConfigChangeOutputSchema","ConfigChangeOutputSchema","ConfigChangeOutputSchema","ConfigChangeOutputSchema","ConfigChangeOutputSchema","ConfigChangeOutputSchema","EntityCardSchema","entry","formatEntityUri","entry","entry","formatEntityUri","EntityCardSchema","catalogRowKey","catalogRowKey","KnowledgeChangeOutputSchema","KnowledgeChangeOutputSchema","compareText","compareText","KnowledgeChangeOutputSchema","KnowledgeChangeOutputSchema","LIVE_URL_SCOPE","LIVE_URL_SCOPE","LIVE_URL_SCOPE","LIVE_URL_SCOPE","CurationSnapshotSchema","IN_FLIGHT_ROW_STATUSES","CurationSnapshotSchema","entry","entry","lookup","entry","utf8Decode","utf8Encode","capture","utf8Decode","utf8Encode","entry","evidence","documents","RunsMarkInputSchema","maskRecordContent","maskRecordContent","RunsMarkInputSchema","maskRecordContent","maskRecordContent","entry","entry","tokens","replay","rule","entry","entry","replay","answer","z","z","entry","canonicalJson","canonicalJson"]}
|