@vostride/agent-qa-agent-local 0.2.2 → 0.2.4

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/composition/run-composition.ts","../src/composition/knowledge-budgets.ts","../src/composition/knowledge-reader.ts","../src/composition/run-invocation-core.ts","../src/composition/run-risk.ts","../src/composition/run-drive-vocabulary.ts","../src/composition/evidence-blob-reader.ts","../src/composition/quarantine-snapshot.ts","../src/composition/quarantine-vocabulary.ts","../src/composition/compose-local-agent.ts","../src/composition/knowledge-review-reader.ts","../src/analysis/persist-analysis.ts","../src/session/jsonl-session-log.ts","../src/store/job-checkpoint-store.ts","../src/store/store-errors.ts","../src/store/post-processing-reader.ts","../src/store/sqlite-job-store.ts","../src/store/logical-dump.ts","../src/composition/build-ordinals.ts","../src/composition/compose-job-recovery.ts","../src/session/memory-session-log.ts"],"sourcesContent":["// The host-neutral run composition (Phase 385 plan 08 — D-13).\n//\n// This is the dissected majority of what used to be a 1035-line composition helper inside the CLI.\n// Nothing here was rewritten: the digest mint, the persistence-port construction, the suite\n// lifecycle and the member run-config assembly are the same code, moved.\n// What changed is WHERE it lives and what it is allowed to assume, and only one thing was actually\n// taken away — the readline default on the confirm seam, which became a presentation port (see\n// presentation-ports.ts for the rule that decided every symbol's side of the line). Since 432-13\n// nothing reads that port: a run asks nobody, and 432-14 deleted the port with its last producer.\n//\n// Why it moved: 386's daemon has to build a real RunConfig without importing a CLI. A composition\n// that lives inside one surface is a composition every other host has to re-derive, and two hosts\n// deriving the same RunConfig differently is the class of bug the dual-host proof exists to\n// exclude. So the composition root moves down to where the local host implementations already\n// live, and the surface keeps only the parts a terminal is required to run.\n//\n// Heavy first-party dependencies are legal in this subtree and nowhere else in this package; the\n// arch rule named composition-carveout enforces that, so the job store proper stays lean.\n\nimport { createHash } from 'node:crypto'\nimport { dirname, isAbsolute, resolve } from 'node:path'\nimport { detectExecutionContext } from '@vostride/agent-qa-safety-local'\nimport { guardToolOutput } from '@vostride/agent-qa-model'\nimport type { TokenAccounting } from '@vostride/agent-qa-model'\nimport type {\n ModelCapabilities,\n RecordedRetrievalRung,\n RecordId,\n ReadTrace,\n ScopeKey,\n} from '@vostride/agent-qa-schema'\nimport {\n FsEventLog,\n FsEvidenceArtifactStore,\n FsHandoffStore,\n FsRunArtifactStore,\n nextBuildOrdinal,\n recordBuildTag,\n RUNS_SUBDIR,\n slugBranch,\n SharpScreenshotCompressor,\n} from '@vostride/agent-qa-runner-local'\nimport type { ScreenshotCompressorLogger } from '@vostride/agent-qa-runner-local'\nimport {\n coerceRunJSResult,\n createMemoryTools,\n createRecordLedger,\n liveStreamFor,\n resolveSecretEnv,\n resolveSecretTemplatesInValue,\n} from '@vostride/agent-qa-runner'\nimport type {\n Action,\n AccessibilityCheckHandler,\n ActionPlanCache,\n AppiumScriptHandler,\n ConfigDigests,\n EventLogPort,\n EvidenceArtifactStorePort,\n FailureScreenshotWriter,\n HandoffStorePort,\n HookDefinition,\n HookExecutorPort,\n LoopLogger,\n MemberEventSink,\n MemberRunConfig,\n MemberStepSpec,\n MemberTest,\n MemberTestExecutor,\n MemberTestRunContext,\n NonActionToolMap,\n PlannerConfig,\n Planner,\n PlatformAdapter,\n KnowledgeHintReader,\n PostVerdictPort,\n RecordLedger,\n RunArtifactStorePort,\n RunJsHandler,\n RunMemberDescriptor,\n SandboxRunnerOptions,\n ScreenshotCompressor,\n SecretRedactorPort,\n SecretStore,\n StorageStatePort,\n TestResult,\n Verifier,\n WorkingMemoryPort,\n} from '@vostride/agent-qa-runner'\nimport {\n computeKnowledgeBudgets,\n memoryToolGate,\n scaledRecordCap,\n type KnowledgeBudgets,\n} from './knowledge-budgets.js'\nimport { constructKnowledgeReader } from './knowledge-reader.js'\nimport type { ConstructKnowledgeReaderInput } from './knowledge-reader.js'\n\n// ---- Local structural types -----------------------------------------------------------------\n\n/** Mirror of schema's ExecutionContext union (safety-local's detectExecutionContext returns it). */\nexport type RunExecutionContext = 'local-interactive' | 'local-headless' | 'ci' | 'cloud'\n\n/**\n * The provider-substrate model handle, named through the runner's own config rather than through\n * the substrate package. It is the identical type — the runner types both model slots with it —\n * and taking it this way keeps a provider-substrate edge off a package whose declared external\n * dependency set is empty and whose whole point is that it installs nothing (JOBQ-02).\n */\ntype RunLanguageModel = MemberRunConfig['plannerModel']\n\n/** The message shape the token accountant estimates, taken from the accountant's own signature. */\ntype AccountedMessage = Parameters<TokenAccounting['estimate']>[0][number]\n\n// ---- (0) run-scoped knowledge serving composition (D-01/D-02/D-09/D-15/D-17/D-23) ----------\n\ntype KnowledgeAccounting = Pick<TokenAccounting, 'estimate' | 'getCeilings'>\n\n/**\n * 407 D-13/D-17 — the shape of THE retrieval-rung resolver, declared structurally here and\n * INJECTED rather than imported.\n *\n * knowledge-local's main entry has exactly ONE importer in this workspace by ratified rule\n * (385 D-14/SC5, enforced at file granularity by `findKnowledgeWriterSingletonOffenders`), and\n * that importer is `compose-local-agent.ts` — the local composition root. `resolveRetrievalRung`\n * lives on the main entry deliberately (407-03: it opens an index probe and may load a model, so\n * it is not `./reader` material), so naming it from this file would have made a second importer\n * and quietly retired the invariant. The seam keeps the singleton intact while leaving exactly\n * one implementation in the tree: `compose-local-agent.ts` re-exports the real resolver as\n * `resolveHostRetrievalRung`, and both CLI doors pass THAT.\n *\n * It is REQUIRED, not optional-with-a-default. A default would be a second place the production\n * resolver could be chosen from, and an omission at a new door would show up as a run with no\n * rung — a banner that silently says nothing — rather than as a compile error.\n */\nexport type RetrievalRungResolver = (\n options: { knowledgeRoot: string; agentQaRoot?: string },\n) => Promise<RecordedRetrievalRung>\n\nexport interface RunKnowledgeComposition {\n reader: KnowledgeHintReader\n budgets: KnowledgeBudgets\n /**\n * 407 D-13 — the HOST's retrieval ladder at THIS run's serve time, started here and awaited\n * exactly once by the first step's evidence recorder. It is a promise rather than a value\n * because the resolver's embedder probe can cost a model load, and overlapping that with run\n * start keeps it off the critical path (T-407-16). Never re-probed per step: a run's rung is a\n * fact about when it was served, not a live indicator of the machine.\n */\n retrievalRung: Promise<RecordedRetrievalRung>\n recordLedger: RecordLedger\n nonActionTools?: NonActionToolMap\n beginMemoryTurn?: (scope?: ScopeKey, exposedIds?: readonly RecordId[]) => void\n drainMemoryReadTraces?: () => ReadTrace[]\n}\n\nexport interface OpenRunKnowledgeCompositionInput {\n resolveTrustPriors?: ConstructKnowledgeReaderInput['resolveTrustPriors']\n knowledgeRoot: string\n product?: string\n scope: ScopeKey\n /** Known containing scopes for a member (the suite scope on prepared-suite runs). */\n parentScopes?: readonly ScopeKey[]\n asOfBuild: number\n capabilities: ModelCapabilities\n accounting: KnowledgeAccounting\n qaRulesText: string\n workingContextText: string\n /**\n * 407 D-13 — the hosted runtime root (`<configDir>/.agent-qa`) the embedder probe discovers its\n * worker under. Absent falls back to the acquirer's own rule, so a caller that does not know the\n * root still gets an honest answer rather than an error.\n */\n agentQaRoot?: string\n /**\n * 407 D-17 — the injected rung resolver. Production callers pass `resolveHostRetrievalRung`\n * (the composition root's binding of THE one knowledge-local resolver); tests pass a fake and\n * never touch the host. See {@link RetrievalRungResolver} for why it is injected and required.\n */\n resolveRetrievalRung: RetrievalRungResolver\n}\n\n/**\n * Open and bind the complete serving stack once per run/planner scope. The composition root can\n * estimate only prompt material it owns, so `qaRulesText` is the run-start capability/rules appendix\n * and `workingContextText` is the resolved suite/test context plus steps. Both ride the same model\n * accounting estimator as planning calls; static runner rules remain covered by the reserved\n * output and conservative fractional allocation rather than a second character heuristic.\n */\nexport function openRunKnowledgeComposition(\n input: OpenRunKnowledgeCompositionInput,\n): RunKnowledgeComposition {\n const ceilings = input.accounting.getCeilings()\n const qaRulesTokens = input.accounting.estimate([\n { role: 'system', content: input.qaRulesText } as AccountedMessage,\n ])\n const workingContextTokens = input.accounting.estimate([\n { role: 'user', content: input.workingContextText } as AccountedMessage,\n ])\n const computed = computeKnowledgeBudgets({\n contextWindow: ceilings.contextWindow,\n reservedOutput: ceilings.maxOutput,\n qaRulesTokens,\n workingContextTokens,\n })\n const budgets: KnowledgeBudgets = {\n ...computed,\n recordCap: scaledRecordCap(input.capabilities),\n }\n const reader = constructKnowledgeReader({\n ...(input.resolveTrustPriors === undefined ? {} : { resolveTrustPriors: input.resolveTrustPriors }),\n knowledgeRoot: input.knowledgeRoot,\n ...(input.product === undefined ? {} : { product: input.product }),\n ...(input.parentScopes === undefined ? {} : { parentScopes: input.parentScopes }),\n asOfBuild: input.asOfBuild,\n recordCap: budgets.recordCap,\n })\n // D-13: started HERE, beside the reader that will serve this run, because this is the only place\n // that knows both roots. Nobody awaits it until the first step's recorder does, so a no-op catch\n // is attached now — an unhandled rejection from a probe that merely asks what the host can do\n // must not become a process-level warning (or, under a stricter host, a crash).\n const retrievalRung = input.resolveRetrievalRung({\n knowledgeRoot: input.knowledgeRoot,\n ...(input.agentQaRoot === undefined ? {} : { agentQaRoot: input.agentQaRoot }),\n })\n retrievalRung.catch(() => undefined)\n const channel2Enabled = memoryToolGate(input.capabilities)\n const recordLedger = createRecordLedger({\n cap: budgets.recordCap,\n budget: budgets.brief + budgets.caution + (channel2Enabled ? budgets.searchResults : 0),\n seedRecords: [],\n })\n\n // D-09/T-380-29: the planner's action slice remains whole under the always-send-all law. The\n // optional non-action slice is composed only for capable models, so non-registration itself is\n // the gate and no model-visible flag can elevate a weak profile into Channel 2.\n const memory = channel2Enabled\n ? createMemoryTools({\n reader,\n scope: input.scope,\n asOfBuild: input.asOfBuild,\n searchResultBudget: budgets.searchResults,\n readBodyBudget: budgets.readBody,\n recordLedger,\n estimateTokens: (text) => input.accounting.estimate([\n { role: 'user', content: text } as AccountedMessage,\n ]),\n })\n : undefined\n\n return {\n reader,\n budgets,\n retrievalRung,\n recordLedger,\n nonActionTools: memory?.tools,\n beginMemoryTurn: memory?.beginTurn,\n drainMemoryReadTraces: memory?.drainReadTraces,\n }\n}\n\n// ---- (1) computeRunConfigDigests — the ONE digest mint (D-20) --------------------------------\n\n/** One member's file inputs to the digest mint. `suiteFileContent` is absent on the single-test path. */\nexport interface RunDigestMemberInput {\n testFileContent: string\n suiteFileContent?: string\n}\n\n/**\n * The per-member cache pair AND the run-level handoff pair, both produced by the SINGLE call\n * below (D-20). The cache-key threading consumes `perMember[i]`; the handoff header carries\n * `runLevel`. Because both draw from one mint, run identity and handoff identity cannot fork.\n */\nexport interface RunConfigDigests {\n runLevel: ConfigDigests\n perMember: ConfigDigests[]\n}\n\n/** 16-hex SHA-256 digest of a UTF-8 string (the 356 A5 `sha256hex16` value; node:crypto here). */\nfunction digest16(input: string): string {\n return createHash('sha256').update(input, 'utf8').digest('hex').slice(0, 16)\n}\n\n/**\n * Mint the run's config digests ONCE (D-20; RESEARCH A1 pinning).\n *\n * - Per-member cache pair:\n * suiteConfigDigest = sha256hex16(configContent + '\\n' + (suiteFileContent ?? ''))\n * testConfigDigest = sha256hex16(testFileContent)\n * - Run-level handoff pair:\n * suiteConfigDigest = sha256hex16(ordered DISTINCT per-member suite digests joined by '\\n')\n * testConfigDigest = sha256hex16(ordered per-member test digests joined by '\\n')\n * A single-member run collapses the run-level pair to the member's values.\n *\n * Both consumers (per-member cache, run-level handoff) draw from this one call — identities\n * cannot fork. This is the ONLY digest computation in the composition layer.\n */\nexport function computeRunConfigDigests(input: {\n configContent: string\n members: readonly RunDigestMemberInput[]\n}): RunConfigDigests {\n const perMember: ConfigDigests[] = input.members.map((m) => ({\n suiteConfigDigest: digest16(input.configContent + '\\n' + (m.suiteFileContent ?? '')),\n testConfigDigest: digest16(m.testFileContent),\n }))\n\n if (perMember.length === 1) {\n // Single-member runs collapse the run-level pair to the member values.\n return { runLevel: { ...perMember[0] }, perMember }\n }\n\n const distinctSuiteDigests: string[] = []\n const seen = new Set<string>()\n for (const pair of perMember) {\n if (!seen.has(pair.suiteConfigDigest)) {\n seen.add(pair.suiteConfigDigest)\n distinctSuiteDigests.push(pair.suiteConfigDigest)\n }\n }\n\n const runLevel: ConfigDigests = {\n suiteConfigDigest: digest16(distinctSuiteDigests.join('\\n')),\n testConfigDigest: digest16(perMember.map((p) => p.testConfigDigest).join('\\n')),\n }\n\n return { runLevel, perMember }\n}\n\n// ---- (2) resolveRunExecutionContext — canonical resolver (D-04) ------------------------------\n\n/**\n * Resolve the run's execution context via safety-local's canonical `detectExecutionContext`\n * (RESEARCH Q1.4 recommendation (a) — already tested; an explicit override wins). Carried into\n * `RunConfig.executionContext` and the handoff header.\n */\nexport function resolveRunExecutionContext(override?: RunExecutionContext): RunExecutionContext {\n return detectExecutionContext(override) as RunExecutionContext\n}\n\n// ---- (3) buildRunPorts + buildOrdinal — runner-local persistence tier (D-06/D-17/D-18) -------\n\n/** The durable run ports the shell wires behind `RunConfig.ports` (event log + handoff + artifact). */\nexport interface RunPersistencePorts {\n eventLog: EventLogPort\n handoffStore: HandoffStorePort\n runArtifactStore: RunArtifactStorePort\n /**\n * CASS-02 run-scoped decision-screenshot store (Plan 13). Constructed once here from the SAME\n * persistence root + runId as the other adapters; the shell hands this exact instance to every\n * member so Plan 12's live-decision producer persists into one durable, run-addressable namespace.\n */\n evidenceArtifacts: EvidenceArtifactStorePort\n /**\n * 403-13 (WR-06, LIVE-03): where a live-frame VIEWER's fault is reported. Declared here as well\n * as on the runner's `RunPorts`, because `assembleCliRun` spreads THIS interface into\n * `RunConfig.ports` — a member declared on only one side is invisible in the type across that\n * hop. Non-durable and off the bus by construction; the run's transcript never records a viewer.\n */\n onSubscriberFault?: (code: string, message: string) => void\n /**\n * 404-01 (D-05/D-10): the host-composed post-verdict step the shell awaits between `verdict` and\n * `runFinished`. Declared here for the SAME reason `onSubscriberFault` is — `assembleCliRun`\n * spreads THIS interface into `RunConfig.ports`, so a member declared on only one side of that\n * hop is invisible in the type and would silently never reach `startRun`.\n *\n * It is NOT built by `buildRunPorts`: this package's runner seam names no queue and no writer\n * lease, and inventing a second spelling of either here is what D-05 exists to prevent. The core\n * threads whatever the HOST handed it (`RunInvocationCoreOptions.postVerdict`) and nothing else.\n */\n postVerdict?: PostVerdictPort\n}\n\n/**\n * Construct the runner-local persistence ports rooted at the run's `.agent-qa` runtime dir (the\n * FsActionCache rooting idiom). `FsEventLog`/`FsHandoffStore`/`FsRunArtifactStore`/\n * `FsEvidenceArtifactStore` all write under the SAME `<configDir>/.agent-qa/runs/<slug(runId)>/…`\n * family (D-08 — one self-contained run dir).\n */\nexport function buildRunPorts(input: { configDir: string; runId: string }): RunPersistencePorts {\n const root = resolve(input.configDir, '.agent-qa')\n return {\n eventLog: new FsEventLog({ root, runId: input.runId }),\n handoffStore: new FsHandoffStore({ root, runId: input.runId }),\n runArtifactStore: new FsRunArtifactStore({ root, runId: input.runId }),\n evidenceArtifacts: new FsEvidenceArtifactStore({ root, runId: input.runId }),\n // A NAMED, observable, non-durable destination: greppable by code, visible to a test through\n // `process.once('warning', …)`, and no `console.` call in a package that makes none.\n onSubscriberFault: (code, message) => {\n process.emitWarning(message, { code })\n },\n }\n}\n\n/**\n * Construct the D-08/Q10 screenshot compressor at the composition root (sharp's host-adapter home).\n * The runner-local `SharpScreenshotCompressor` is injected into every member's runner loop via\n * `RunSuiteConfig.compressor` / `RunTestConfig.compressor` — core no longer constructs one.\n */\nexport function buildScreenshotCompressor(logger?: ScreenshotCompressorLogger): ScreenshotCompressor {\n return new SharpScreenshotCompressor(logger)\n}\n\n/** Resolve D-16 build-tag precedence without reading ambient process state. */\nexport function resolveBuildTagSetting(input: {\n flag?: string\n env?: string\n use?: { buildTag?: string }\n}): string | undefined {\n for (const value of [input.flag, input.env, input.use?.buildTag]) {\n const trimmed = value?.trim()\n if (trimmed) return trimmed\n }\n return undefined\n}\n\n/**\n * Advance the per-product buildOrdinal counter under the same `.agent-qa` root (D-18), then\n * record D-14/D-16's first-seen tag mapping beside it when supplied. Both files are lock-free,\n * best-effort runtime truth; the resolved ordinal rides `RunConfig.buildOrdinal` into the handoff.\n */\nexport async function resolveRunBuildOrdinal(input: {\n configDir: string\n product: string\n buildTag?: string\n}): Promise<number> {\n const root = resolve(input.configDir, '.agent-qa')\n const ordinal = await nextBuildOrdinal({ root, product: input.product })\n if (input.buildTag !== undefined) {\n await recordBuildTag({\n root,\n product: input.product,\n tag: input.buildTag,\n ordinal,\n })\n }\n return ordinal\n}\n\n// ---- (4) createSuiteLifecycle — lazy per-suite setup/teardown --------------------------------\n\n/**\n * The ONE exclusive lane every suite member declares (402-02, D-09). The runner's bounded member\n * pool never runs two members of the same lane concurrently, and the suite path needs that for two\n * independent reasons, either of which alone would be sufficient:\n *\n * 1. Every member of a suite drives the ONE `PlatformAdapter` its suite set up — one browser, one\n * page. Two members on it at once would interleave navigations and clicks on a shared surface.\n * D-09 requires each concurrent member its own browser/CDP handle; the suite path does not\n * supply that today, so it does not get concurrency today.\n * 2. `createSuiteLifecycle` admits ONE ACTIVE SUITE at a time. Two suites live at once is a\n * lifecycle violation, not a scheduling preference.\n *\n * A single lane string (rather than one lane per suite) is what encodes BOTH: it serializes within\n * a suite and across suites. When a producer starts handing each member its own session AND the\n * lifecycle admits concurrent suites, this becomes a per-suite key — or disappears — and the shell\n * needs no argument re-litigated for that to be safe.\n *\n * STATUS 2026-08-24 (402-02): reason (2) is CLOSED — `createSuiteLifecycle` below is now a\n * once-latch with member reference counting, so two members of one suite merge into one setup and\n * a boundary crossed while members are live is a named error rather than a mid-flight teardown.\n * Reason (1) is OPEN and is what still holds the lane: `suiteConfig.adapter` is per-SUITE, so\n * within-suite concurrency would still put two tests on one browser page. Giving each suite member\n * its own session is a change to what a suite MEANS (suite setup navigates once and members\n * inherit that page state, per-test hooks run against it, auth state is captured from it) and is\n * not this plan's to make. Do not drop this lane until that is decided.\n */\nexport const SUITE_LIFECYCLE_LANE = 'suite-lifecycle'\n\n/** The setup/teardown pair a suite runs when it first becomes active / when it is torn down. */\nexport interface SuiteLifecycleHooks {\n /** Suite-level setup: setup hooks + adapter.setup + suite-URL navigation. */\n setup(): Promise<void>\n /** Suite-level teardown: teardown hooks + auth-state capture (when all passed) + adapter.cleanup. */\n teardown(): Promise<void>\n}\n\n/**\n * One member's hold on the active suite (402-02). Held from the moment `ensureReady` admits the\n * member until the member settles; the suite cannot be torn down while any hold is outstanding.\n */\nexport interface SuiteMemberLease {\n /** Drop this member's hold. Idempotent — a double release never double-decrements. */\n release(): void\n}\n\n/**\n * Thrown when `ensureReady` is asked for a suite while a DIFFERENT suite still has live members\n * (402-02). This is the one-active-suite invariant made loud. The alternative — tearing the live\n * suite down to make room — closes the browser out from under a test that is still running in it,\n * and does so silently. The shell's exclusive lane (`SUITE_LIFECYCLE_LANE`) means no shipped\n * composition can reach this, so it reads as an assertion rather than a runtime condition; that is\n * exactly the point of naming it instead of assuming it.\n */\nexport class SuiteBoundaryWhileLiveError extends Error {\n constructor(\n readonly activeSuiteKey: string,\n readonly requestedSuiteKey: string,\n readonly liveMembers: number,\n ) {\n super(\n `Cannot enter suite \"${requestedSuiteKey}\": suite \"${activeSuiteKey}\" still has ` +\n `${liveMembers} live member(s). Suite boundaries are serialized.`,\n )\n this.name = 'SuiteBoundaryWhileLiveError'\n }\n}\n\nexport interface SuiteLifecycle {\n /**\n * Admit a member to `suiteKey` and resolve once the suite is ready. The FIRST member to arrive\n * starts the suite's setup; every other member of that suite awaits the SAME setup promise\n * rather than starting a second one. Crossing a suite boundary tears down the previous suite —\n * but only once its last member has released; a boundary crossed while members are live is a\n * {@link SuiteBoundaryWhileLiveError}, never a silent teardown.\n *\n * The returned {@link SuiteMemberLease} MUST be released when the member settles (pass or fail);\n * `buildSuiteMemberExecutor` does it in a `finally`.\n */\n ensureReady(suiteKey: string, hooks: SuiteLifecycleHooks): Promise<SuiteMemberLease>\n /** Tear down the last active suite (if any). Called once at run end after `session.done`. */\n finalize(): Promise<void>\n}\n\n/**\n * A lazy, CONCURRENCY-SAFE suite-lifecycle manager (the Q1.2 \"pre/post-run composition\" rows,\n * redesigned for the 402-02 member pool). A wholly SKIPPED suite never sets up — the shell only\n * invokes the executor (hence `ensureReady`) for non-skipped members, so a suite whose members are\n * all fail-fast/cancel skips is never touched.\n *\n * WHAT CHANGED AND WHY. The pre-402 version read the active key, awaited `hooks.setup()`, and THEN\n * assigned the key — three steps with awaits between them. Under a `for` loop that is fine because\n * only one member is ever inside it. Under a pool, two members of one suite both observe \"no active\n * suite\" and both run setup: two browsers for one suite, and the second teardown handle silently\n * overwriting the first, so the first suite's browser is never closed. The fix is not a lock; it is\n * to make the state transition SYNCHRONOUS and let the promise be the shared thing:\n *\n * - the once-latch: `activeKey`, `activeTeardown` and `activeSetup` are all assigned in the same\n * synchronous region, BEFORE any await, so there is no window in which a second member can\n * observe the pre-setup state. Every later member of the suite awaits `activeSetup` itself.\n * - member reference counting: the count is incremented before awaiting setup, so a concurrent\n * boundary crossing sees the hold. Teardown fires at a BOUNDARY (or at `finalize`) and only\n * when the count is zero — never merely because it hit zero, which would tear the suite down\n * and set it back up between every pair of members.\n * - a failed setup poisons the suite: the rejected latch is kept and re-thrown to every later\n * member, so setup is attempted exactly once and no member half-starts against a suite that\n * never came up. Such a suite is never torn down — nothing came up to take down.\n */\nexport function createSuiteLifecycle(): SuiteLifecycle {\n let activeKey: string | undefined\n let activeSetup: Promise<void> | undefined\n let activeTeardown: (() => Promise<void>) | undefined\n let liveMembers = 0\n\n const tearDownActive = async (): Promise<void> => {\n const teardown = activeTeardown\n activeKey = undefined\n activeSetup = undefined\n activeTeardown = undefined\n liveMembers = 0\n if (teardown) await teardown()\n }\n\n return {\n async ensureReady(suiteKey, hooks) {\n if (activeKey !== undefined && activeKey !== suiteKey) {\n if (liveMembers > 0) {\n throw new SuiteBoundaryWhileLiveError(activeKey, suiteKey, liveMembers)\n }\n await tearDownActive()\n }\n\n if (activeKey !== suiteKey) {\n // THE ONCE-LATCH. All three assignments are synchronous and happen before the setup body\n // can suspend, so the check above and the state below can never be split by an await.\n activeKey = suiteKey\n activeTeardown = hooks.teardown\n activeSetup = (async () => {\n try {\n await hooks.setup()\n } catch (error) {\n // A suite that never came up has nothing to take down, and the latch stays rejected so\n // every later member of this suite inherits the same failure instead of retrying.\n activeTeardown = undefined\n throw error\n }\n })()\n }\n\n const setup = activeSetup\n // Counted BEFORE the await: a boundary crossing that races this member must see the hold.\n liveMembers += 1\n let released = false\n const lease: SuiteMemberLease = {\n release() {\n if (released) return\n released = true\n liveMembers -= 1\n },\n }\n try {\n await setup\n } catch (error) {\n lease.release()\n throw error\n }\n return lease\n },\n async finalize() {\n await tearDownActive()\n },\n }\n}\n\n// ---- (5) buildSuiteMemberExecutor — the MemberTestExecutor closure (D-01) ---------------------\n\n/**\n * One prepared suite member: its suite key + lifecycle hooks (setup runs on the first member of\n * that suite) and a `run(ctx)` that builds the member's bound `SuiteMemberInput` around core's\n * per-test machinery and returns `executeSuiteMember(...)` with the shell-provided ctx seams\n * (abortSignal, events, per-member configDigests) threaded in.\n */\nexport interface SuiteMemberBinding {\n suiteKey: string\n hooks: SuiteLifecycleHooks\n /**\n * 403 D-05: the suite's ONE adapter, read only for its live-stream declaration. Present so the\n * executor can register the capability AFTER `ensureReady` has resolved the suite's `setup()`\n * (which is where `adapter.setup()` runs, so `this.page` exists) and BEFORE the first step.\n */\n adapter?: PlatformAdapter\n run(ctx: MemberTestRunContext): Promise<TestResult>\n}\n\n/**\n * Declare (or withdraw) a member's live stream on the shell-provided context (403 D-05), by the one\n * selection rule `liveStreamFor` (428 D-11/D-12). A continuous stream is registered with the\n * labelled 1s snapshot producer over `screenshot()` as its fallback, which the hub starts when the\n * stream fails to start. An adapter with no continuous stream but a `screenshot()` registers the\n * snapshot producer itself; an adapter whose own stream is already a snapshot registers that alone;\n * an adapter with neither registers `undefined` and its handle reads `{ kind: 'none' }`.\n * The `ctx.registerLiveStream?.()` call is itself optional so a composition that predates the port\n * is a no-op rather than a crash.\n */\nexport function registerAdapterLiveStream(\n ctx: MemberTestRunContext,\n adapter: PlatformAdapter | undefined,\n): void {\n const registration = liveStreamFor(adapter)\n ctx.registerLiveStream?.(registration?.capability, registration?.fallback)\n}\n\n/**\n * Build the injected `MemberTestExecutor` (D-01). Per member the closure looks up the prepared\n * binding by the shell-derived `testIndex` (array position — authoritative), calls\n * `lifecycle.ensureReady(...)` to lazily set up / cross-boundary tear down the member's suite,\n * then runs the member behind `executeSuiteMember`. Wrapping ONE audited function instead of\n * replicating the loop body.\n */\nexport function buildSuiteMemberExecutor(input: {\n lifecycle: SuiteLifecycle\n bindings: readonly SuiteMemberBinding[]\n}): MemberTestExecutor {\n return async (member: RunMemberDescriptor, ctx: MemberTestRunContext): Promise<TestResult> => {\n const binding = input.bindings[ctx.testIndex]\n if (!binding) {\n throw new Error(`No suite-member binding for testIndex ${ctx.testIndex} (testId ${member.testId})`)\n }\n const lease = await input.lifecycle.ensureReady(binding.suiteKey, binding.hooks)\n try {\n // 403 D-05: the suite is up (adapter.setup() resolved inside `ensureReady`), so the member's\n // live stream is declarable now and before its first step.\n registerAdapterLiveStream(ctx, binding.adapter)\n return await binding.run(ctx)\n } finally {\n // The hold is dropped on EVERY exit, throw included — a leaked hold would block the next\n // suite's boundary forever with a SuiteBoundaryWhileLiveError.\n lease.release()\n }\n }\n}\n\n// ---- (6) masking seed pipeline: deleted 441-19 (D-12). A run masks only through its producer's\n// `SecretRedactor`, built from the declared secrets; nothing seeds from the environment or auth state.\n\n// ---- (7) per-run stamped audit sink: deleted 441-43 (D-15). Neither a run nor a curation fold\n// writes a guardrail audit row, so a run directory holds no audit file beside its events.\n\n/**\n * The one composition of a run's own directory (401-20, CR-04).\n *\n * EXTRACTED RATHER THAN COPIED, and that is the whole point of it existing. The core's collision\n * refusal has to ask \"does this id already name a run\", and the only honest way to ask is against\n * the SAME path the run's artifacts are written to. A second spelling of\n * `runs/<slugBranch(runId)>/` would be free to drift from this one, and a refusal that looked in\n * the wrong place would be green while a colliding id walked past it — path forking is the failure\n * mode this function's own caller already warns about.\n */\nexport function runDirFor(input: { configDir: string; runId: string }): string {\n return resolve(input.configDir, '.agent-qa', RUNS_SUBDIR, slugBranch(input.runId))\n}\n\n// ---- (9) member-run-config builder — the D-05 cutover onto runMemberTest (363-11) ------------\n//\n// Both startRun sites (suite + single-test) execute each member through the runner-owned\n// `runMemberTest` (Plan 10). The executor closure at each site composes core-owned memory\n// init/curator/destroy AROUND this member run and returns the member `TestResult` to the shell.\n// `buildMemberRunConfig` is the ONE place (Pitfall 8 — no per-site drift) that maps the resolved\n// host impls into a `MemberRunConfig`, constructing the adapter-backed injected handlers the runner\n// stays neutral about: runJS (web `page.evaluate` + `coerceRunJSResult`), appium (adapter execute\n// with secret resolution), the accessibility check (dynamic web-package load), the failure\n// screenshot writer, and the store-neutral secret resolver. Adapter internals are legal HERE — this\n// is the composition root (D-05). Core's `runTest`/`runTestWithRetry` per-test wrapper is gone;\n// its responsibilities live in `runMemberTest` (runner) and in the memory/curator composition here.\n\n/** Capture a best-effort failure screenshot from the adapter (re-homed from the deleted core\n * reporter/screenshot.ts). Returns undefined when the adapter exposes no screenshot capability or\n * capture throws — never fails the step. */\nasync function captureFailureScreenshotFromAdapter(adapter: PlatformAdapter): Promise<Buffer | undefined> {\n try {\n const shot = (adapter as { screenshot?: () => Promise<Buffer> }).screenshot\n if (typeof shot !== 'function') return undefined\n return await shot.call(adapter)\n } catch {\n return undefined\n }\n}\n\n/** Build the injected runJS handler (Q-2). Web-only, mirroring the deleted core runjs-inline\n * execution half: resolve the page from the adapter, `page.evaluate`, coerce the result. Non-web /\n * page-less returns a `[runJS error: …]` value the runner splices in (the same self-describing text\n * core produced). */\nfunction buildRunJsHandler(adapter: PlatformAdapter): RunJsHandler {\n return async (code, ctx) => {\n if (adapter.platform !== 'web') {\n return { value: '[runJS error: runJS is only supported on web platform]', error: 'runJS is only supported on web platform' }\n }\n const page = 'getPage' in adapter\n ? (adapter as { getPage: () => { evaluate: (c: string) => Promise<unknown> } | undefined }).getPage()\n : undefined\n if (!page) {\n return { value: '[runJS error: no browser page available]', error: 'no browser page available' }\n }\n void ctx\n const raw = await page.evaluate(code)\n return { value: coerceRunJSResult(raw) }\n }\n}\n\n/** Build the injected appium handler (Q-2). Resolves secret templates in the action, then executes\n * it on the adapter (the core appium-inline execution half). */\nfunction buildAppiumScriptHandler(adapter: PlatformAdapter, secretStore?: SecretStore): AppiumScriptHandler {\n return async (action) => adapter.execute(resolveSecretTemplatesInValue(action as Action, secretStore) as Action)\n}\n\n/** Build the injected accessibility-check handler (Q-4). Web-only; resolves the page and runs the\n * dynamically-loaded `@vostride/agent-qa-web` `runAccessibilityCheck` (the composition root is the\n * dynamic-load host — resolves Open Q-4 as move-now). A lost page is a capture failure,\n * never a successful zero-violation check. */\nfunction buildAccessibilityCheckHandler(adapter: PlatformAdapter): AccessibilityCheckHandler {\n return async (opts) => {\n const page = 'getPage' in adapter ? (adapter as { getPage: () => unknown }).getPage() : undefined\n if (!page) throw new Error('Accessibility capture requires an active browser page')\n const web = await import('@vostride/agent-qa-web')\n return web.runAccessibilityCheck(page as any, opts)\n }\n}\n\n/** Build the injected failure-screenshot writer. Captures from the adapter into the member's\n * `result.screenshot` (in-run buffer, the same artifact the reporter subscribers persist beside the\n * run dir). */\nfunction buildFailureScreenshotWriter(adapter: PlatformAdapter): FailureScreenshotWriter {\n return async () => captureFailureScreenshotFromAdapter(adapter)\n}\n\n/** The runner-owned `MemberTest` shape derived from a resolved (already suite-patched) TestDefinition.\n * `filePath` is the member's own file. A suite-patched test carries no `url` (the suite owns nav), so\n * `runMemberTest` skips the per-test navigate for suite members. */\nexport function toMemberTest(test: any, filePath: string): MemberTest {\n return {\n testId: (test['test-id'] as string | undefined) ?? test.name,\n name: test.name,\n filePath,\n url: test.url as string | undefined,\n context: test.context as string | undefined,\n steps: test.steps as Array<string | MemberStepSpec>,\n meta: test.meta as MemberTest['meta'],\n }\n}\n\n/** Everything both executor closures resolve at the composition root and hand to\n * {@link buildMemberRunConfig}. The adapter-backed injected handlers are constructed here from\n * `adapter` + `secretStore` so the two sites never drift (Pitfall 8). */\nexport interface BuildMemberRunConfigInput {\n // loop host impls\n adapter: PlatformAdapter\n planner: Planner\n verifier: Verifier\n cache?: ActionPlanCache\n workingMemory?: WorkingMemoryPort\n storageState?: StorageStatePort\n compressor?: ScreenshotCompressor\n knowledgeReader?: KnowledgeHintReader\n /** 407 D-13 — the composed rung, carried through untouched to the loop's evidence recorder. */\n knowledgeRetrievalRung?: Promise<RecordedRetrievalRung>\n knowledgeBudgets?: KnowledgeBudgets\n knowledgeAsOfBuild?: number\n recordLedger?: RecordLedger\n beginMemoryTurn?: (scope?: ScopeKey, exposedIds?: readonly RecordId[]) => void\n drainMemoryReadTraces?: () => ReadTrace[]\n configDigests?: ConfigDigests\n // models\n plannerModel: RunLanguageModel\n verifierModel: RunLanguageModel\n stepModelScope?: MemberRunConfig['stepModelScope']\n // variable seeds\n envFileVars?: Record<string, string>\n inlineVars?: Record<string, string>\n suiteVars?: Record<string, string>\n cliVars?: Record<string, string>\n hookSetupVars?: Record<string, string>\n // inline hooks\n inlineHookDefs?: Map<string, HookDefinition>\n sandboxOptions?: SandboxRunnerOptions\n // secrets — the concrete SecretStore (superset of SecretResolver); resolveSecretEnv needs forEachSecret.\n secretStore?: SecretStore\n secretRedactor?: SecretRedactorPort\n // per-member ctx (bound by the run shell)\n sink: MemberEventSink\n testIndex: number\n abortSignal: AbortSignal\n /** CASS-02 run-scoped evidence store the shell threads onto the member ctx (Plan 13). */\n evidenceArtifacts?: EvidenceArtifactStorePort\n // run config\n captureScreenshots?: boolean\n accessibility?: MemberRunConfig['accessibility']\n timeouts?: MemberRunConfig['timeouts']\n plannerConfig?: PlannerConfig\n logger?: LoopLogger\n logCapture?: { console?: boolean; network?: boolean }\n vision?: { screenshotSize?: number; effectiveResolution?: number }\n visionGate?: { attachImage: boolean; captureMode: 'full' | 'textOnly'; promptNote: string }\n contextWindow?: number\n suiteContext?: string\n /** The member's own file, for the core-parity fileUpload path resolver. */\n filePath: string\n}\n\n/**\n * Assemble the {@link MemberRunConfig} `runMemberTest` slots behind, wiring the adapter-backed\n * injected handlers (runJS/appium/a11y/failure-shot), the store-neutral secret resolver, and the\n * fileUpload path resolver — reproducing core's `runTest` per-test behavior on runner soil (D-05).\n */\nexport function buildMemberRunConfig(input: BuildMemberRunConfigInput): MemberRunConfig {\n const sandbox = input.sandboxOptions\n return {\n adapter: input.adapter,\n planner: input.planner,\n verifier: input.verifier,\n cache: input.cache,\n workingMemory: input.workingMemory,\n storageState: input.storageState,\n // CTXB-06: model's canonical compaction (compactLogs for log bursts, guardBlob\n // otherwise) replaces the runner-local ceiling fallback on every tool-output value.\n guardBlob: guardToolOutput,\n compressor: input.compressor,\n knowledgeReader: input.knowledgeReader,\n knowledgeRetrievalRung: input.knowledgeRetrievalRung,\n knowledgeBudgets: input.knowledgeBudgets,\n knowledgeAsOfBuild: input.knowledgeAsOfBuild,\n recordLedger: input.recordLedger,\n beginMemoryTurn: input.beginMemoryTurn,\n drainMemoryReadTraces: input.drainMemoryReadTraces,\n configDigests: input.configDigests,\n\n plannerModel: input.plannerModel,\n verifierModel: input.verifierModel,\n stepModelScope: input.stepModelScope,\n\n envFileVars: input.envFileVars,\n inlineVars: input.inlineVars,\n suiteVars: input.suiteVars,\n cliVars: input.cliVars,\n hookSetupVars: input.hookSetupVars,\n\n // Inline hooks: the runner-local DockerHookExecutor + sandbox env/authState come off the resolved\n // sandbox options; the per-run secret env is resolved store-side (never crosses into the runner).\n hookExecutor: sandbox?.executor as HookExecutorPort | undefined,\n inlineHookDefs: input.inlineHookDefs,\n hookEnvVars: sandbox?.envVars,\n hookSecretEnv: resolveSecretEnv(input.secretStore),\n hookAuthState: sandbox?.authState,\n\n runJs: buildRunJsHandler(input.adapter),\n appiumScript: buildAppiumScriptHandler(input.adapter, input.secretStore),\n accessibilityCheck: 'getPage' in input.adapter && typeof input.adapter.getPage === 'function'\n ? buildAccessibilityCheckHandler(input.adapter)\n : undefined,\n persistFailureScreenshot: buildFailureScreenshotWriter(input.adapter),\n\n resolveSecrets: (text: string) => resolveSecretTemplatesInValue(text, input.secretStore),\n secretStore: input.secretStore,\n secretRedactor: input.secretRedactor,\n\n sink: input.sink,\n testIndex: input.testIndex,\n abortSignal: input.abortSignal,\n evidenceArtifacts: input.evidenceArtifacts,\n\n captureScreenshots: input.captureScreenshots,\n accessibility: input.accessibility,\n timeouts: input.timeouts,\n plannerConfig: input.plannerConfig,\n logger: input.logger,\n logCapture: input.logCapture,\n vision: input.vision,\n visionGate: input.visionGate,\n contextWindow: input.contextWindow,\n suiteContext: input.suiteContext,\n resolveUploadPath: (rawPath: string) =>\n isAbsolute(rawPath) ? rawPath : resolve(dirname(input.filePath), rawPath),\n }\n}\n","// Relocated out of the CLI by Phase 385 plan 08 (D-13) unchanged. The budget arithmetic never\n// touched a terminal, so it is host-neutral by the dissection rule and belongs beside the reader\n// binding it sizes rather than in whichever surface happened to call it first.\n\nimport type { ModelCapabilities } from '@vostride/agent-qa-schema'\n\n/** Provisional share of usable model context reserved for the frozen Channel-1 brief. */\nexport const BRIEF_FRACTION = 0.05\n\n/** Provisional share of usable model context reserved for one-shot Channel-3 cautions. */\nexport const CAUTION_FRACTION = 0.01\n\n/** Provisional non-zero Channel-1 floor; field evidence may tune it in a later milestone. */\nexport const MIN_BRIEF = 256\n\n/** Provisional non-zero Channel-3 floor sized to preserve at least one concise caution line. */\nexport const MIN_CAUTION = 64\n\n/** Provisional upper bound for learned Channel-1 brief tokens, independent of model size. */\nexport const BRIEF_CEILING = 2_048\n\n/** Provisional share of usable context available to cumulative Channel-2 record bodies per turn. */\nexport const READ_BODY_FRACTION = 0.1\n\n/** Provisional hard cap on distinct records admitted across all three channels in one turn. */\nexport const GLOBAL_RECORD_CAP = 24\n\n/** Provisional multiplier applied to the distinct-record cap for gate-failing weak models. */\nexport const WEAK_MODEL_CAP_SCALE = 0.5\n\n/** Provisional minimum context window required before the optional Channel-2 tool surface is useful. */\nexport const MIN_MEMORY_TOOL_CONTEXT_WINDOW = 16_384\n\nexport interface KnowledgeBudgets {\n brief: number\n /** Wrapper-fixed Channel-2 search-result budget; never exposed in the tool schema. */\n searchResults: number\n caution: number\n readBody: number\n recordCap: number\n}\n\nexport interface ComputeKnowledgeBudgetsInput {\n contextWindow: number\n reservedOutput: number\n qaRulesTokens: number\n workingContextTokens: number\n}\n\nfunction floorFinite(value: number): number {\n if (Number.isNaN(value)) return 0\n if (value === Number.POSITIVE_INFINITY) return Number.MAX_SAFE_INTEGER\n if (value === Number.NEGATIVE_INFINITY) return Number.MIN_SAFE_INTEGER\n return Math.floor(value)\n}\n\nfunction clamp(value: number, minimum: number, maximum: number): number {\n return Math.min(maximum, Math.max(minimum, value))\n}\n\n/**\n * Derive every learned-knowledge budget beside model token accounting. The raw fraction is\n * floored before any floor/ceiling clamp, preserving D-02's exact boundary behavior. The reader\n * and provider-neutral loop receive only the resulting plain numbers.\n */\nexport function computeKnowledgeBudgets(input: ComputeKnowledgeBudgetsInput): KnowledgeBudgets {\n const usableContext = input.contextWindow\n - input.reservedOutput\n - input.qaRulesTokens\n - input.workingContextTokens\n\n const brief = clamp(\n floorFinite(usableContext * BRIEF_FRACTION),\n MIN_BRIEF,\n BRIEF_CEILING,\n )\n const caution = Math.max(MIN_CAUTION, floorFinite(usableContext * CAUTION_FRACTION))\n const readBody = Math.max(MIN_BRIEF, floorFinite(usableContext * READ_BODY_FRACTION))\n\n // Search entries and Channel-1 learned lines are both summary-sized projections. Reuse the\n // same bounded allocation rather than inventing a model-controlled or unbounded search knob.\n const searchResults = brief\n return { brief, searchResults, caution, readBody, recordCap: GLOBAL_RECORD_CAP }\n}\n\n/**\n * Provisional D-09 predicate pinned by Phase 380 research. Channel 2 is absent when the model\n * cannot call tools, is text-only, or has too little context; Channels 1 and 3 remain available.\n */\nexport function memoryToolGate(capabilities: ModelCapabilities): boolean {\n return capabilities.toolCalling\n && capabilities.vision\n && capabilities.contextWindow >= MIN_MEMORY_TOOL_CONTEXT_WINDOW\n}\n\n/** Apply D-17's weak-model cap reduction through the exact D-09 gate predicate. */\nexport function scaledRecordCap(capabilities: ModelCapabilities): number {\n if (memoryToolGate(capabilities)) return GLOBAL_RECORD_CAP\n return Math.max(1, Math.floor(GLOBAL_RECORD_CAP * WEAK_MODEL_CAP_SCALE))\n}\n","import { openKnowledgeReader } from '@vostride/agent-qa-knowledge-local/reader'\nimport type { KnowledgeHintReader, ServedRunBrief } from '@vostride/agent-qa-runner'\nimport type { ScopeKey, TrustPriorTable } from '@vostride/agent-qa-schema'\n\n/** Inputs the composition root resolves when opening the run-scoped knowledge reader. */\nexport interface ConstructKnowledgeReaderInput {\n resolveTrustPriors?: () => TrustPriorTable | undefined\n knowledgeRoot: string\n product?: string\n /** Known containing scopes for a member (the suite scope on prepared-suite runs). */\n parentScopes?: readonly ScopeKey[]\n asOfBuild: number\n recordCap: number\n}\n\n/**\n * Freeze Channel 1 at the composition root. The budget is deliberately absent from the key:\n * budgets are run-fixed, while canonical `[tier,key]` material gives one immutable memo entry per\n * scope. All other reader methods remain live pass-throughs for Channels 2, 3, and canary output.\n *\n * KREV-02 · D-13: the memo holds the WHOLE composite, so a repeat serve returns the trace captured\n * at the moment the brief was actually assembled — not a fresh trace describing the cache hit.\n * That is the deliberate choice and it is what makes the why-verb answer about *then*: a step that\n * replans four times against one frozen brief was served that brief once, and the attribution that\n * explains its lines is the one from that single serve. A \"hit\"-flavoured trace would describe the\n * memo rather than the retrieval, and there would be no honest rank or score to put in it. The\n * value type is written out rather than inferred so this stays a decision instead of a side effect\n * of `ReturnType`; `knowledge-budgets.test.ts` pins that a repeat carries the original trace.\n */\nexport function createFrozenKnowledgeReader(reader: KnowledgeHintReader): KnowledgeHintReader {\n const briefs = new Map<string, ServedRunBrief>()\n const scopeKey = (scope: ScopeKey): string => JSON.stringify([scope.tier, scope.key])\n\n return {\n getRunBrief(scope, budget) {\n const key = scopeKey(scope)\n const existing = briefs.get(key)\n if (existing !== undefined) return existing\n const brief = reader.getRunBrief(scope, budget)\n briefs.set(key, brief)\n return brief\n },\n search: (query, options) => reader.search(query, options),\n read: (id, options) => reader.read(id, options),\n getCautions: (anchors, budget) => reader.getCautions(anchors, budget),\n getProcedure: (intent, screenState, availability) =>\n reader.getProcedure(intent, screenState, availability),\n emitCanaryOutcome: (payload) => reader.emitCanaryOutcome(payload),\n }\n}\n\n/**\n * Construct the run-scoped reader through the physically read-only package subpath, then freeze\n * its Channel-1 brief for the lifetime of the run.\n */\nexport function constructKnowledgeReader(\n input: ConstructKnowledgeReaderInput,\n): KnowledgeHintReader {\n return createFrozenKnowledgeReader(openKnowledgeReader({\n ...(input.resolveTrustPriors === undefined ? {} : { priors: input.resolveTrustPriors() }),\n knowledgeRoot: input.knowledgeRoot,\n ...(input.product === undefined ? {} : { product: input.product }),\n scopeDefaults: {\n asOfBuild: input.asOfBuild,\n ...(input.parentScopes === undefined ? {} : { parentScopes: input.parentScopes }),\n },\n budgets: { recordCap: input.recordCap },\n }))\n}\n","// The one in-process run invocation core (Phase 401, D-02; approval removed 432-13).\n//\n// WHAT THIS FILE IS. Every local run trigger — `agent-qa run`, the chat/MCP `runs.start` op, the\n// daemon drainer, the dashboard's run button — resolves to ONE function here. It owns the ORDER a\n// run is started in:\n//\n// refuse unhonourable request fields\n// → resolve the run id (refuse an unminted or colliding one)\n// → resolve the target's declared class (a config read; no network)\n// → refuse a production target the config has not opted into (432-03, D-18)\n// → persistence ports → assemble → startRun → onSession → await the run\n//\n// NOTHING ASKS (432-13, D-01/D-14/D-15). There is no approval ladder, no confirm port and no session\n// trust here any more: a non-production run starts in every execution context, and production is\n// refused in plain words unless the same config says `allowProduction: true`. Every refusal still\n// lands BEFORE assembly — assembly is where the run-start baseline probe fetches the target and\n// where the build-ordinal counter is advanced — so a refused run leaves no probe, no ordinal bump, no\n// run directory and no browser. `assembleRun` is a port this file calls once, below every refusal.\n//\n// THE ONE `startRun` OWNER. `packages/arch/src/lint/startrun-pin.ts` pins this file as the only\n// production file that starts a run in-process.\n//\n// IT NEVER READS AMBIENT CONTEXT (D-07). There is no `resolveRunExecutionContext()` call here, no\n// `getActiveExecutionContext`, no ALS read, no `process.env` sniff for who is asking. The door\n// that knows supplies `executionContext`, and the run records it: a daemon serving a browser and a\n// terminal on the same machine carries two different answers.\n\nimport { existsSync } from 'node:fs'\nimport { dirname } from 'node:path'\n\nimport type {\n RunId,\n RunSession,\n RunsStartInput,\n} from '@vostride/agent-qa-schema'\nimport { startRun } from '@vostride/agent-qa-runner'\nimport type { PostVerdictPort, RunConfig } from '@vostride/agent-qa-runner'\n\nimport { buildRunPorts, runDirFor } from './run-composition.js'\nimport type { RunExecutionContext, RunPersistencePorts } from './run-composition.js'\nimport { buildProductionRefusal } from './run-risk.js'\nimport type { RunTargetClass } from './run-risk.js'\n\n/**\n * The assembler port's own vocabulary, re-exported from the module that DECLARES the port.\n *\n * IT PASSES THROUGH HERE RATHER THAN THROUGH THE BARREL because the composition carveout admits\n * `@vostride/agent-qa-runner` only under `composition/` — the rule that keeps the job store proper\n * lean. A host writing a `RunAssembler` needs the types a `RunConfig` is made of; naming the runner\n * package itself would put a surface through the firewall (FUNC-02) for the vocabulary of a port\n * this file defined. Types only: erased before anything runs, granting no reach.\n */\nexport type {\n BaselineProbeResult,\n ConfigDigests,\n MemberTestExecutor,\n // 404-01 (D-10): the post-verdict step's vocabulary, on the same terms as the rest of this\n // block — a host writing the factory below needs the shape it must return.\n PostVerdictOutcome,\n PostVerdictPort,\n PostVerdictStepInput,\n RunConfig,\n RunMemberDescriptor,\n} from '@vostride/agent-qa-runner'\n\n/**\n * The request fields this seam refuses, and the reason is not the one the CLI host had.\n *\n * `createCliRunExecution` refused these because the `run` COMMAND had no argv to express them\n * (`local-agent-host.ts`). This core can express both — and honouring either would be the defect\n * RESEARCH Pitfall 7 names:\n *\n * `executionContext` — the context a run records comes from the composition that owns the door\n * (D-07) and from nowhere else. The FIELD survives on the contract as the label a run RECORDS,\n * and it is refused here until some door has a use for recording a label that differs from the\n * context it was started in.\n *\n * `scope` — resolves from the config's own target/product resolution. Accepting an override\n * would let a caller address one product's run ledger while running another's.\n *\n * Read OFF the request rather than enumerated positively, so a field added to `RunsStartInput`\n * with no plan for carrying it shows up here as a refusal instead of as a silent drop.\n */\nexport const REFUSED_RUN_REQUEST_FIELDS = [\n 'scope',\n 'executionContext',\n] as const satisfies readonly (keyof RunsStartInput)[]\n\n/**\n * The request named a field this seam refuses, so the request is refused rather than reshaped.\n *\n * The successor to `UnsupportedRunRequestError` (cli `local-agent-host.ts`), which dies with the\n * spawn port in 401-05. Same class of refusal, different rationale: that one could not express the\n * fields, this one declines to.\n */\nexport class RunRequestFieldRefusedError extends Error {\n constructor(readonly refusedFields: readonly string[]) {\n super(\n `agent-qa cannot start a run with: ${refusedFields.join(', ')}. ` +\n 'scope resolves from the config the run is started against, and executionContext is ' +\n 'supplied by the composition that owns the door — a caller-named execution context ' +\n 'would be a caller relabelling where its run came from.',\n )\n this.name = 'RunRequestFieldRefusedError'\n }\n}\n\n/**\n * The request named a run id this system would not have minted (2026-08-23, 401-20 · CR-04).\n *\n * A DECISION, NOT A FAULT, and it joins `RunRequestFieldRefusedError` under the same rule: the\n * caller asked for something this seam declines, and says so by name before anything happens.\n *\n * WHY IT IS ASKED HERE AND NOT IN THE SCHEMA. `packages/schema` owns PATH-SAFETY on the id — the\n * id becomes a directory name and that is judgeable with no dependencies — but it may not name\n * `@vostride/agent-qa-ids` and must not re-spell the canonical id shape. So \"is this an id this\n * system would have minted\" is asked here, through a predicate supplied beside `mintRunId` and for\n * `mintRunId`'s stated reason: a locally invented answer would be a second spelling of a run's\n * identity. Measured pre-fix: `runId: 'not-a-minted-id'` was acknowledged, and `runId: ''` ran a\n * whole run into a shared `runs/default/` directory before the op reported `RunNotRecordedError`.\n */\nexport class RunIdNotMintedError extends Error {\n constructor(readonly runId: string) {\n super(\n `agent-qa cannot start a run under ${JSON.stringify(runId)}: a caller-named run id must be `\n + 'one this system minted. Start the run without naming an id and read the id back off the '\n + 'acknowledgment, or name an id `agent-qa` handed you.',\n )\n this.name = 'RunIdNotMintedError'\n }\n}\n\n/**\n * The request named a run id that already belongs to a run (2026-08-23, 401-20 · CR-04).\n *\n * WHAT A COLLISION COSTS, measured rather than reasoned about. Pre-fix, a second `runs.start`\n * naming a completed run's id APPENDED seven more envelopes to that run's `events.jsonl`\n * (2111 → 4221 bytes), OVERWROTE its `handoff.json`, and added a second row to its\n * `execution_audit.jsonl` — and then acknowledged the caller with the victim's own id. The\n * acknowledgment law makes that worse rather than better: `runs.start` reads every ack field back\n * off the run's durable record specifically so a host cannot fabricate one, and a colliding id\n * satisfies that read with a PRIOR run's record. So the refusal has to land before the record is\n * touched at all — which is why it sits in the identity step, above assembly.\n *\n * THE TEST IS THE RUN'S OWN DIRECTORY, derived through `runDirFor` — the same composition the\n * run's ports use — because every artifact a collision could tamper with lives inside it.\n * Asking after `handoff.json` alone would let a run that crashed before writing one be silently\n * appended to.\n */\nexport class RunIdAlreadyInUseError extends Error {\n constructor(readonly runId: string) {\n super(\n `agent-qa cannot start a run under ${JSON.stringify(runId)}: that id already names a run in `\n + 'this project. Starting a second run under it would append to the first run\\'s event log '\n + 'and overwrite its handoff. Start the run without naming an id.',\n )\n this.name = 'RunIdAlreadyInUseError'\n }\n}\n\n/**\n * This run was refused before it started.\n *\n * Since 432-13 the one producer is the production refusal (`refuseProductionWithoutOptIn`): its\n * reason is the plain sentence naming the target and the config line. 2026-10-01 (432-19, D-15):\n * it carries no remedy list, because the remedy vocabulary left with the execution gate.\n * `neutralReason` is the same sentence; the dashboard and run-service doors read that member to\n * tell a run denial from any other rejection, and a door renders it and never composes its own.\n */\nexport class RunDeniedError extends Error {\n readonly neutralReason: string\n\n constructor(\n readonly runId: string,\n readonly reason: string,\n ) {\n super(reason)\n this.name = 'RunDeniedError'\n this.neutralReason = reason\n }\n}\n\n/**\n * What one resolution of this request's targets answers (401-14).\n *\n * THE CLASS AND THE NAMES COME BACK TOGETHER because they are two renderings of ONE pass over the\n * run's members: `targetClass` is the most-restrictive fold over them, `targetNames` the declared\n * names of the members it folded over. A door that answered them from two passes could refuse on\n * one reading of the config while the run it describes came from another.\n */\nexport interface RunTargetDeclaration {\n /** The DECLARED class of the run's members — a config read, never a probe (D-06). */\n readonly targetClass: RunTargetClass\n /**\n * The distinct declared target names, in first-appearance member order.\n *\n * DISPLAY-ONLY (T-401-G3b). Members that declare no target contribute nothing, which is how an\n * all-undeclared run arrives here as an empty list rather than as a list of invented names.\n */\n readonly targetNames: readonly string[]\n /**\n * The members' targets DECLARED `environment: production`, in first-appearance member order\n * (432-03, D-18). Repeats are allowed; the refusal names each target once.\n *\n * REQUIRED, so a door that forgets it does not compile. It comes from the SAME resolution as\n * `targetClass` and `targetNames`, which is what keeps a mixed run from hiding a production member\n * behind its siblings.\n */\n readonly productionTargetNames: readonly string[]\n /**\n * The config's top-level `allowProduction`, read from the same config the targets resolved\n * against. Only the literal `true` opts in; absence and `false` do not. No request field and no\n * CLI flag reaches this.\n */\n readonly allowProduction?: boolean\n}\n\n/**\n * Refuse a run that drives a production target the config has not opted into (432-03, D-18).\n *\n * A production CLASS with no names still refuses, so a producer that folded the class but lost the\n * names fails closed. The refusal is a plain `RunDeniedError` carrying the sentence from\n * `buildProductionRefusal`.\n *\n * EXPORTED because a producer that must acquire a device or an adapter before the core runs (the\n * suite half) calls it first, so production is refused before that acquisition too.\n */\nexport function refuseProductionWithoutOptIn(\n runId: string,\n declaration: Pick<RunTargetDeclaration, 'productionTargetNames' | 'allowProduction'> & {\n readonly targetClass?: RunTargetClass\n },\n): void {\n const production =\n declaration.productionTargetNames.length > 0 || declaration.targetClass === 'production'\n if (!production || declaration.allowProduction === true) return\n const reason = buildProductionRefusal(declaration.productionTargetNames)\n throw new RunDeniedError(runId, reason)\n}\n\n/**\n * The identity refusals, asked against the run's own directory (401-20, CR-04).\n *\n * EXPORTED for the same producers `refuseProductionWithoutOptIn` is: a door that refuses production\n * ahead of the core asks these first, so a duplicate or unminted id keeps its own refusal on every\n * path.\n */\nexport function refuseUnavailableRunId(input: {\n readonly configDir: string\n readonly runId: string\n readonly isMintedRunId: (value: string) => boolean\n}): void {\n if (!input.isMintedRunId(input.runId)) throw new RunIdNotMintedError(input.runId)\n if (existsSync(runDirFor({ configDir: input.configDir, runId: input.runId }))) {\n throw new RunIdAlreadyInUseError(input.runId)\n }\n}\n\n/** What the assembler is handed: everything the core resolved, and nothing it did not. */\nexport interface RunAssemblyContext {\n /** The run's identity, already resolved. The core starts the run under THIS id and no other. */\n readonly runId: string\n /** The caller's request, refused fields already rejected. */\n readonly request: RunsStartInput\n /** The context the door carried — the same value, so a run cannot record a different one. */\n readonly executionContext: RunExecutionContext\n /** The durable ports, rooted at `<configDir>/.agent-qa` (Pitfall 5 — the evidence check's root). */\n readonly ports: RunPersistencePorts\n /** `dirname(agentQaRoot)` — the project directory the config sits in. */\n readonly configDir: string\n /** The config file this run resolves against (request override honoured). */\n readonly configPath: string\n /** The declared class the door resolved. Handed over so an assembler need not re-resolve it. */\n readonly targetClass: RunTargetClass\n}\n\n/**\n * Build the `RunConfig` the runner shell starts.\n *\n * A PORT rather than shared code, on `RunExecutionPort`'s own argument: members, executor,\n * reporters and masking are decisions a host answers differently. What crosses into the core is\n * the type; what stays with the door is the assembly. The core supplies the identity fields\n * (`runId` and the markers) over whatever the assembler returns, so a door cannot start a run\n * under an id the caller was not acknowledged with.\n *\n * EVERYTHING WITH A SIDE EFFECT BELONGS HERE, not in the door's pre-flight: the baseline probe\n * (network), the build-ordinal advance (a durable write), the quarantine fold. This function is\n * called below every refusal, so a refused run costs the target nothing.\n */\nexport type RunAssembler = (context: RunAssemblyContext) => Promise<RunConfig> | RunConfig\n\nexport interface RunInvocationCoreOptions {\n /** The config file runs resolve against unless the request names another. */\n readonly configPath: string\n /** The project's runtime root, i.e. `<configDir>/.agent-qa`. */\n readonly agentQaRoot: string\n /**\n * The context this door's runs are started in and record (D-07).\n *\n * CALLER-RESOLVED, NEVER SNIFFED. The CLI resolves its TTY posture, the daemon carries\n * `local-headless`, CI passes its own. A core that detected this itself would be answering a\n * question about the machine when the question is about the door.\n */\n readonly executionContext: RunExecutionContext\n /**\n * Resolve what this request's targets DECLARE (D-06; names added 401-14).\n *\n * INJECTED BECAUSE THE CONFIG LIVES BEHIND THE DOOR, not because any of it is negotiable. Target\n * resolution needs the CLI's `resolveTarget`/`AgentQaConfig` vocabulary, which this package may\n * not name. `undefined` is undeclared, which is not production.\n *\n * ONE RESOLUTION, ALL FIELDS, AND THAT IS THE POINT OF THE SHAPE. The class, the names, the\n * production members and the opt-in come back from one pass, so the production refusal is asked\n * about the members the run will actually drive.\n *\n * Must not touch the target, and must not probe. A resolver that read a URL would put a network\n * call before the production refusal, which is the one ordering this file exists to hold.\n */\n readonly resolveTargetDeclaration: (\n request: RunsStartInput,\n ) => RunTargetDeclaration | Promise<RunTargetDeclaration>\n /** Build the `RunConfig`. Called ONLY once every refusal has passed. */\n readonly assembleRun: RunAssembler\n /**\n * Mint a run id when the request carries none.\n *\n * REQUIRED rather than defaulted: the id generator lives in `@vostride/agent-qa-ids` (via core),\n * which this package does not depend on, and a locally invented id shape would be a second\n * spelling of a run's identity. Every shipped door already holds `generateRunId`.\n */\n readonly mintRunId: () => string\n /**\n * Is this a run id this system would have minted? (2026-08-23, 401-20 · CR-04)\n *\n * REQUIRED, WITH NO DEFAULT AND NO FALLBACK, for exactly `mintRunId`'s reason and one more. The\n * canonical predicate lives in `@vostride/agent-qa-ids`, which this package does not depend on,\n * and a locally invented shape check would be a second spelling of a run's identity — the same\n * argument that made minting an option. The extra reason is that an OPTIONAL predicate with a\n * permissive fallback is this defect wearing a type: every composition that forgot it would be\n * back to accepting any string, and the build would say nothing. A composition that omits this\n * does not compile.\n *\n * It answers about the SHAPE only. Whether the id is free is this file's own question, asked\n * against the run's own directory.\n */\n readonly isMintedRunId: (value: string) => boolean\n /**\n * Notified with the started session, synchronously, before the core awaits it (D-09's bridge\n * hook). Subscribers attach here; the bus replays from seq 1, so nothing is missed.\n */\n readonly onSession?: (session: RunSession) => void\n /**\n * Build this run's post-verdict step (404 D-05/D-10) — the durable `analyze-run` enqueue plus\n * ONE writer-lease consult, awaited by the shell between `verdict` and `runFinished`, whose\n * answer becomes `runFinished.disposition`.\n *\n * HOST-COMPOSED, CORE-THREADED, and both halves are load-bearing. It is host-composed because\n * the step speaks queue and writer-lease vocabulary this package's runner seam may not name —\n * the same argument that made `mintRunId` an option rather than a local. It is threaded HERE\n * rather than left to each door because the enqueue is precisely what the `runs.start` door and\n * the daemon door forgot: a door that supplies no factory gets a run whose wire honestly reads\n * `detached`, and a door that supplies one cannot then forget to wire it in.\n *\n * Called ONCE per run, after every refusal has passed and the persistence ports exist, so a\n * refused run never composes one. Absent ⇒ no `postVerdict` member reaches `RunConfig.ports` at all\n * (conditional spread, never an `undefined` field), and the shell reports `detached` with no\n * warning — which is the truth about a host from which nothing will be drained.\n */\n readonly postVerdict?: (input: {\n readonly runId: string\n readonly configDir: string\n }) => PostVerdictPort\n /** The door's first third-party code, awaited once the request is allowed and before any port. */\n readonly afterRefusal?: () => Promise<void>\n}\n\n/**\n * The one in-process run execution core.\n *\n * Returns a `RunExecutionPort` (the shape `createLocalRunInvocation` binds `runs.start` over), so\n * the op's evidence check — read the run's own event log back, refuse an empty one — applies to\n * this seam unchanged.\n *\n * NO DEFENSIVE CATCH ANYWHERE (D-03). A run that crashes hard takes its host with it, on purpose:\n * crash-through surfaces bugs instead of absorbing them, and the runner's budget/abort machinery\n * is the orderly containment. The only `throw`s this file introduces are the two refusals above,\n * which are decisions rather than faults.\n */\nexport function createRunInvocationCore(\n options: RunInvocationCoreOptions,\n): { execute(request: RunsStartInput): Promise<{ runId: RunId }> } {\n const configDir = dirname(options.agentQaRoot)\n\n return {\n async execute(request: RunsStartInput): Promise<{ runId: RunId }> {\n // (1) The refusal, first — before an id is minted or a config is read. A refused request\n // must not leave a run id behind that a caller could later ask about.\n const refused = REFUSED_RUN_REQUEST_FIELDS.filter((field) => request[field] !== undefined)\n if (refused.length > 0) throw new RunRequestFieldRefusedError(refused)\n\n // (2) Identity, and it REFUSES before it resolves (401-20, CR-04).\n //\n // A caller-supplied id carries exactly the trust the old `AGENT_QA_RUN_ID` child environment\n // variable carried — the door minting it is the door running it. What it does NOT carry, and\n // used to be described here as if it did, is a guarantee about the id itself: 394-11 removed\n // host-side id minting from the CLI precisely because a run's identity is not a caller's to\n // invent, and `RunsStartInputSchema` now refuses a path-shaped one but cannot ask the other\n // two questions. Both land here, and both land BEFORE anything is minted, read or written:\n //\n // SHAPE — is this an id this system would have minted? The predicate is injected, because\n // the canonical shape lives in a package this one does not depend on.\n // FREEDOM — does it already name a run? Asked against the run's OWN directory, through the\n // same `runDirFor` the run's ports are rooted at.\n //\n // ORDER IS THE CONTROL. Both refusals sit above the declaration resolve and above assembly —\n // so a refused request leaves no run directory, no build-ordinal bump and, above all, not one\n // byte changed in the run it named. A refusal that half-wrote into somebody else's run\n // directory would be the defect performing itself.\n if (request.runId !== undefined) {\n refuseUnavailableRunId({\n configDir,\n runId: request.runId,\n isMintedRunId: options.isMintedRunId,\n })\n }\n const runId = request.runId ?? options.mintRunId()\n\n // (3) The declaration, from the config itself. Cheap, and it must stay cheap: this is the\n // last thing that happens before a run may be refused.\n const declaration = await options.resolveTargetDeclaration(request)\n const targetClass = declaration.targetClass\n\n // (3a) PRODUCTION, BEFORE ANY EFFECT (432-03, D-18). Above the persistence ports and\n // assembly, so a refused production run leaves no run directory, no probe, no build ordinal\n // and no adapter. It asks nothing and offers nothing: the config opts in, or the run does not\n // start. Since 432-13 it is the only refusal of a well-formed request.\n refuseProductionWithoutOptIn(runId, declaration)\n\n // (3b) 2026-10-16 (442-08, D-10): the door's own code runs only for an allowed request, and a\n // failure here still leaves no run directory.\n await options.afterRefusal?.()\n\n // (4) Assembly — the first line that may touch the target, and it is below every refusal.\n const ports = buildRunPorts({ configDir, runId })\n // 404 D-05/D-10: the post-verdict step, built ONCE per run and spread into the ports the\n // assembler receives — so it rides the same hop `handoffStore` does and reaches\n // `RunConfig.ports` through the door's own assembler without the door remembering to add it.\n const postVerdict = options.postVerdict?.({ runId, configDir })\n const assembled = await options.assembleRun({\n runId,\n request,\n executionContext: options.executionContext,\n ports: {\n ...ports,\n ...(postVerdict === undefined ? {} : { postVerdict }),\n },\n configDir,\n configPath: request.configPath ?? options.configPath,\n targetClass,\n })\n\n // (5) Start. The markers ride straight from the request onto the RunConfig — the chain that\n // used to be request → port → argv → command flag → RunConfig is now request → RunConfig,\n // and only the literal `true` carries (a `false` is a refusal, not a synonym for absence).\n // `runId` is stamped over whatever the assembler returned so the id this call acknowledges\n // is provably the id the run was started under.\n const session = startRun({\n ...assembled,\n runId: runId as RunId,\n ...(request.gateRun === true ? { gateRun: true as const } : {}),\n ...(request.excludedFromOutcomes === true\n ? { excludedFromOutcomes: true as const }\n : {}),\n })\n\n options.onSession?.(session)\n\n // The handoff is assembled and persisted before `done` resolves (runner shell's terminal\n // sequence), so awaiting it is awaiting the run AND its durable record.\n await session.done\n\n return { runId: runId as RunId }\n },\n }\n}\n","// The run's target-class vocabulary and the production refusal's re-export (Phase 401 D-05/D-06,\n// 432-03 D-18).\n//\n// 2026-10-01 (432-19, D-14/D-15): THE RUN GATE'S RECIPES ARE DELETED. `buildRunRiskDescriptor`\n// (the `run:start` descriptor the gate classified), `RUN_START_RISK_ACTION_NAME` and\n// `buildRunDisclosure` (the sentence a person was asked to approve a run on) had no consumer after\n// 432-13 removed the gate's call-site and nothing asks a person any more. What stays is the\n// declaration vocabulary the production refusal folds over, and the refusal sentence itself.\n//\n// WHY IT LIVES IN agent-local/composition RATHER THAN IN cli. The CLI, the daemon and the\n// dashboard all start runs, and a vocabulary that lives inside one surface is a vocabulary the\n// other two re-derive. This module takes a PLAIN target-class value, never a `ResolvedTarget` and\n// never anything else shaped like a CLI type — agent-local must not import the CLI.\n\n/**\n * A target's declared environment, as the config carries it (`TargetSchema.environment`).\n *\n * `undefined` is a first-class member and means UNDECLARED — not \"unknown, assume harmless\".\n *\n * `production` (432-03, D-18) outranks every other class in a fold. A production run is refused\n * before any effect unless the config opts in (`refuseProductionWithoutOptIn`); one that is opted\n * in starts like any other run (432-13).\n */\nexport type RunTargetClass = 'local' | 'shared' | 'production' | undefined\n\n// 432-04: the production refusal moved to schema, so the dashboard live editor (which may not\n// import this package) shows the same sentence. Re-exported here so every existing consumer of\n// this module keeps its import.\nexport {\n ALLOW_PRODUCTION_OPT_IN,\n buildProductionRefusal,\n distinctInFirstOccurrenceOrder,\n} from '@vostride/agent-qa-schema'\n","// The two symbols a CLI in-process run DRIVE needs and had no legal route to (Phase 401 plan 11).\n//\n// WHAT THEY ARE. `runSafetyScope` is `@vostride/agent-qa-safety-local`'s AsyncLocalStorage scope —\n// the run's masking context, audit sink and execution context installed for the duration of the\n// run, so every model egress masks and every tool call is gated and audited. `mapVerdictToExitCode`\n// is the runner's own verdict→code table. A drive that RUNS the run has to do both.\n//\n// WHY THEY NEEDED A ROUTE AT ALL. FUNC-02's surface firewall admits only `@vostride/agent-qa-agent`,\n// `-agent-local`, `-analytics` and `-schema` to a file under `packages/cli` without an exact\n// `(file, specifier)` ledger entry; that ledger only ever SHRINKS and a file written after\n// 2026-07-28 can never join it. `commands/run.ts` is the one cli file already ledgered for\n// `safety-local` and `runner`. So the composition module that becomes the ONE in-process drive\n// could not name either package, and re-exporting them from the composition root is the sanctioned\n// hop — the same one 401-03 used for the assembler port's runner types.\n//\n// WHY NOT FROM `run-invocation-core.ts`, WHICH THE PLAN'S ROUTE TABLE NAMED. Measured: the core's\n// own D-07 hygiene census (`run-invocation-core.test.ts`) asserts that no member of the ambient\n// context family — `runSafetyScope` among them — appears in the core's COMMENT-STRIPPED source. A\n// re-export is not a call, but the census cannot tell one from the other, and restating it to make\n// an exception for re-export lines would weaken a live anchor to accommodate a convenience. The\n// anchor is right and the placement was wrong: the core answers \"may this run happen and in what\n// order\", and the drive's scope-and-exit-code vocabulary is not part of that answer. A sibling\n// module keeps the census byte-exact.\n//\n// NEITHER IS A NEW POWER. Both already reach the CLI door today — `run.ts` imports `runSafetyScope`\n// statically and pulls `mapVerdictToExitCode` out of a dynamic runner import on both of its paths.\n// What changes is that the one drive both paths become callers of can name them too.\n//\n// PUBLISHED ON THE BARREL, NOT REACHABLE PAST IT. Re-exporting these two from `src/index.ts`\n// directly would name the two packages from OUTSIDE `packages/agent-local/src/composition/`, which\n// the composition carve-out refuses (401-03 measured that refusal on the runner types). The port\n// and its vocabulary travel together.\n\nexport { runSafetyScope } from '@vostride/agent-qa-safety-local'\nexport type { SafetyScopeBundle } from '@vostride/agent-qa-safety-local'\nexport { mapVerdictToExitCode } from '@vostride/agent-qa-runner'\n\n// 441-48 (D-14): the masking digest sidecar this hop also carried (405-02) is deleted. It existed\n// only so a restarted dashboard could restore placeholders, and nothing restores any more.\n","// The evidence-blob read port, bound over the SAME store the runner wrote through (405-05, D-13).\n//\n// ONE BINDING, TWO CONSUMERS. Before this file the analysis job's `readEvidenceBlob` was an inline\n// lambda at the composition root, and `runs.artifact` would have needed a second one. Two lambdas\n// over one store is two answers to \"where do this run's blobs live\" — they agree on the day the\n// second is written, and the first time either side changes a root or a subdirectory they stop.\n// So the lambda moved here and both consumers call it.\n//\n// WHY THIS IS A COMPOSITION FILE AND NOT AN OP. `packages/agent` is storageNeutral: `node:fs` and\n// the concrete store are unreachable there by architecture, which is exactly why the op declares a\n// PORT and this package fills it. What crosses the boundary is bytes and a three-arm verdict.\n//\n// THE TWO ABSENCES ARE SEPARATED HERE, AND HERE IS THE ONLY PLACE THEY CAN BE (D-15).\n// `FsEvidenceArtifactStore.getBlob` answers `undefined` for a malformed sha AND for an ENOENT,\n// and the layer above needs to tell an unknown RUN apart from a run holding no such BLOB\n// — a bad link from a screenshot the diet collected. The run's own directory is what distinguishes\n// them: a run that has started has `runs/<slug(runId)>/` whether or not it has written a handoff\n// (RESEARCH Pattern 3), so directory presence is the run-existence question and the store's own\n// answer is the blob question.\n//\n// THIS FILE ASSEMBLES NO PATH FROM CALLER INPUT (T-405-14). The runId becomes a path segment\n// exactly once, inside `slugBranch`, which is the shared traversal guard the store's own\n// constructor uses — and the sha is regex-checked before it is ever handed on. Containment is the\n// store's rule; a second rule here would be a second rule free to be the weaker one.\n\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { EvidenceBlobReaderPort } from '@vostride/agent-qa-agent'\nimport type { EvidenceBlobLookup, EvidenceBlobPresence, RunId } from '@vostride/agent-qa-schema'\nimport { FsEvidenceArtifactStore, RUNS_SUBDIR, slugBranch } from '@vostride/agent-qa-runner-local'\n\n/** The lowercase 64-hex shape a content address has. The store's own rule, checked before it. */\nconst SHA256_HEX_RE = /^[0-9a-f]{64}$/\n\nexport interface CreateEvidenceBlobReaderInput {\n /** The runtime root, i.e. `<configDir>/.agent-qa` — the parent of `runs/`. */\n readonly agentQaRoot: string\n}\n\n/**\n * THE LOOKUP — one run, one sha, three answers. Synchronous, because the store is.\n *\n * THIS IS THE SHARED RULE, and both consumers below are shapings of it. The analysis job wants\n * bytes-or-nothing and the op wants the three-arm split; writing the rule once and adapting it\n * twice is what keeps \"where does a blob live\" a single sentence in this repository.\n *\n * The regex guard is deliberately redundant with `RunsArtifactInputSchema`: the schema already\n * refused every malformed sha before the op ran, so that branch is unreachable through the shipped\n * path. It stays because an in-layer caller has no schema in front of it, and the alternative to\n * guarding here is handing an unchecked string on toward a `join` — which is the one thing a port\n * implementation may never do, reachable or not.\n */\nfunction runDirectoryExists(input: CreateEvidenceBlobReaderInput, runId: string): boolean {\n // THE RUN-EXISTENCE QUESTION, asked of the directory rather than of a handoff: a run that is\n // mid-flight has a directory and no `handoff.json`, and answering `unknown_run` for it would\n // make a live run's screenshots read as a broken link.\n //\n // ONE FUNCTION RATHER THAN TWO SPELLINGS, because the read and the stat below are the same rule\n // at two costs: a second `existsSync` here is a second definition of what a known run IS, and\n // the day one of them learns about a new layout the other reports a live run as unknown.\n return existsSync(join(input.agentQaRoot, RUNS_SUBDIR, slugBranch(runId)))\n}\n\nexport function lookupEvidenceBlob(\n input: CreateEvidenceBlobReaderInput,\n runId: string,\n sha: string,\n): EvidenceBlobLookup {\n if (!SHA256_HEX_RE.test(sha)) return { status: 'blob_absent' }\n if (!runDirectoryExists(input, runId)) return { status: 'unknown_run' }\n const bytes = new FsEvidenceArtifactStore({ root: input.agentQaRoot, runId }).getBlob(sha)\n return bytes === undefined ? { status: 'blob_absent' } : { status: 'found', bytes }\n}\n\n/**\n * THE SAME RULE, MINUS THE BYTES (Phase 406, D-17) — presence for a whole run's artifact refs.\n *\n * WHY NOT `lookupEvidenceBlob(...).status`: a run page annotates every ref it is about to render,\n * and the read arm loads a screenshot into memory to reach the status it then discards. This\n * shaping walks the identical three-way split — malformed sha, unknown run, then the store's own\n * answer — and asks the store to STAT instead of read. The two arms above `runDirectoryExists`\n * are shared code, not a copy, so `found` here and `found` there are the same claim.\n */\nexport function statEvidenceBlob(\n input: CreateEvidenceBlobReaderInput,\n runId: string,\n sha: string,\n): EvidenceBlobPresence {\n if (!SHA256_HEX_RE.test(sha)) return 'blob_absent'\n if (!runDirectoryExists(input, runId)) return 'unknown_run'\n return new FsEvidenceArtifactStore({ root: input.agentQaRoot, runId }).hasBlob(sha)\n ? 'found'\n : 'blob_absent'\n}\n\nexport function statEvidenceBlobSize(\n input: CreateEvidenceBlobReaderInput,\n runId: string,\n sha: string,\n): Awaited<ReturnType<NonNullable<EvidenceBlobReaderPort['stat']>>> {\n if (!SHA256_HEX_RE.test(sha)) return { status: 'blob_absent' }\n if (!runDirectoryExists(input, runId)) return { status: 'unknown_run' }\n const byteLength = new FsEvidenceArtifactStore({ root: input.agentQaRoot, runId }).blobSize(sha)\n return byteLength === undefined ? { status: 'blob_absent' } : { status: 'found', byteLength }\n}\n\nexport function readEvidenceBlobRange(\n input: CreateEvidenceBlobReaderInput,\n runId: string,\n sha: string,\n start: number,\n end: number,\n): EvidenceBlobLookup {\n if (!SHA256_HEX_RE.test(sha)) return { status: 'blob_absent' }\n if (!runDirectoryExists(input, runId)) return { status: 'unknown_run' }\n const bytes = new FsEvidenceArtifactStore({ root: input.agentQaRoot, runId }).readBlobRange(sha, start, end)\n return bytes === undefined ? { status: 'blob_absent' } : { status: 'found', bytes }\n}\n\n/**\n * The op's PORT over {@link lookupEvidenceBlob}.\n *\n * BOTH MEMBERS ARE BOUND HERE (406, D-17): this host holds run directories, so it can honestly\n * answer the optional presence member, and an op reading it gets `present` for every ref rather\n * than the omitted key a host without local storage would leave.\n *\n * ASYNC EVEN THOUGH THE STORE IS NOT, because the port is the shape a host that does not hold its\n * blobs on a local disk would also have to satisfy — and a synchronous contract is one such a host\n * could never implement without lying about it. The local answer is simply already resolved.\n */\nexport function createEvidenceBlobReader(\n input: CreateEvidenceBlobReaderInput,\n): EvidenceBlobReaderPort {\n return {\n read: (runId: RunId, sha: string): Promise<EvidenceBlobLookup> =>\n Promise.resolve(lookupEvidenceBlob(input, String(runId), sha)),\n has: (runId: RunId, sha: string): Promise<EvidenceBlobPresence> =>\n Promise.resolve(statEvidenceBlob(input, String(runId), sha)),\n stat: (runId, sha) => Promise.resolve(statEvidenceBlobSize(input, String(runId), sha)),\n readRange: (runId, sha, start, end) =>\n Promise.resolve(readEvidenceBlobRange(input, String(runId), sha, start, end)),\n }\n}\n\n/**\n * The analysis job's shaping: the bytes, or nothing, with the two absences collapsed.\n *\n * THE COLLAPSE IS THIS CALLER'S, not the rule's. An evidence-diet pass has the same work to do\n * whether a run is unknown or its blob was already collected — there is no screenshot either way —\n * so it takes the narrower answer rather than making the shared rule narrower for everyone.\n */\nexport function readEvidenceBlobBytes(\n input: CreateEvidenceBlobReaderInput,\n runId: string,\n sha: string,\n): Uint8Array | undefined {\n const lookup = lookupEvidenceBlob(input, runId, sha)\n return lookup.status === 'found' ? lookup.bytes : undefined\n}\n","// The run-start quarantine snapshot (Phase 390, D-16).\n//\n// THIS is where the committed ledger becomes run input: fold it ONCE before `startRun`, hand the\n// resolved set to the run as plain data on RunConfig. The runner gains zero ports and stays\n// storageNeutral, and the disposition is deterministic for the whole run — a mid-run ledger edit\n// can never retroactively change a running build. It mirrors how `executionContext` is resolved\n// once at run start.\n//\n// WHY IT LIVES HERE rather than beside the run command that calls it: the CLI's shipped source no\n// longer names the knowledge package at all (2026-08-02, Phase 387 plan 09 D-20 removed it from\n// that contract), and the surface firewall ledger only shrinks — a new leak is fixed, not waived.\n// The local composition root is the sanctioned home for knowledge access, and this file takes the\n// READER entry, beside `knowledge-reader.ts`: the snapshot opens nothing, writes nothing and holds\n// no lease. The writer entry keeps its single importer.\n//\n// One helper serves BOTH `startRun` composition sites (the multi-suite path and the direct\n// single-test path) so neither can drift into a second spelling of the rule.\n//\n// DEGRADATION (T-390-04): a ledger read failure answers an EMPTY set with a printed warning, never\n// an abort. A broken or hand-mangled quarantine file must never be able to stop a run — the worst\n// it can do is withhold suppression, which fails builds loudly rather than passing them silently.\n\nimport { slugBranch } from '@vostride/agent-qa-schema'\nimport type { QuarantineAppliedEntry } from '@vostride/agent-qa-schema'\nimport {\n QUARANTINE_LEDGER_FILENAME,\n foldQuarantineLedgerState,\n readQuarantineLedger,\n} from '@vostride/agent-qa-knowledge-local/reader'\n\nexport interface RunQuarantineSnapshotInput {\n /** The committed knowledge root, already resolved (`resolveKnowledgeRoot`). */\n knowledgeRoot: string\n /** The run's RAW product / scope key; slugged here to match the projection partition law. */\n product: string\n /** Run-start instant as an ISO-8601 string — the ONE clock read, made by the caller. */\n now: string\n warn?: (message: string) => void\n}\n\n/**\n * Resolve the entries this run will apply: active (`'quarantined'`) and belonging to this run's\n * product. Expired entries are deliberately EXCLUDED — a lapsed entry's test fails builds again\n * (D-11) — and released entries are gone.\n *\n * Measured consequence worth knowing at THIS seam, because this is where the exclusion is decided:\n * for a test still crossing the threshold that is exactly ONE red build. The snapshot below is\n * taken at run start (entry lapsed ⇒ not applied ⇒ red), and that same run's post-run fold\n * re-enters it with a fresh full-lifetime deadline before the next run takes its own snapshot. No\n * human is scheduled into that loop at any point, and nothing bounds the repetition\n * (measured 2026-08-06).\n */\nexport function resolveRunQuarantineSnapshot(\n input: RunQuarantineSnapshotInput,\n): readonly QuarantineAppliedEntry[] {\n const warn = input.warn ?? ((): void => {})\n const product = slugBranch(input.product)\n\n let read: ReturnType<typeof readQuarantineLedger>\n try {\n read = readQuarantineLedger(input.knowledgeRoot)\n } catch (error) {\n // Includes the typed version refusal: a ledger this build cannot read is surfaced loudly and\n // then treated as absent for THIS run. Suppressing nothing is the safe direction.\n warn(\n `${QUARANTINE_LEDGER_FILENAME} could not be read (${\n error instanceof Error ? error.message : String(error)\n }); no test is quarantined for this run`,\n )\n return []\n }\n\n if (read.refusedLines.length > 0) {\n // Refusal-as-data reaching a human: the healthy entries still apply, and the damaged lines are\n // named by line number so they can be fixed in the file they live in.\n warn(\n `${QUARANTINE_LEDGER_FILENAME} has ${read.refusedLines.length} unreadable line(s) — ${read.refusedLines\n .map((refused) => `line ${refused.lineNumber}: ${refused.reason}`)\n .join('; ')}`,\n )\n }\n\n return foldQuarantineLedgerState(read.events, input.now)\n .filter((entry) => entry.state === 'quarantined' && entry.product === product)\n .map((entry) => ({\n product: entry.product,\n filePath: entry.filePath,\n testName: entry.testName,\n expiresAt: entry.expiresAt,\n }))\n}\n","/**\n * The quarantine gate's vocabulary, published to the hosts that RENDER its decisions (390-30).\n *\n * WHY THIS FILE EXISTS AT ALL. The curation tail's withheld line must branch its remedy on the\n * crossing's ADMISSIBILITY, not on the producer alone: an `escalate-only` class is refused at the\n * gate's FIRST conjunct and no later run admits it; an `authored-required` class needs an analyst\n * rather than another run; only the floor-eligible classes are honestly told that the next applied\n * run's fold re-evaluates the crossing. The shipped line branched on the producer, so every\n * deterministic sighting was promised a re-evaluation — false for `environment` and false for\n * `unknown`, which is `classifyRootCause`'s terminal arm and so the dominant shape on a project\n * with no analysis budget. An operator line that promises admission a fold will never grant sends a\n * human to wait for relief that cannot come.\n *\n * The fix is only durable if the line's promise and the gate's refusal are read out of ONE\n * vocabulary. So the render consumes the very tables `autoQuarantines` refuses on, rather than\n * restating them — a restatement is a second rule that can disagree with the first.\n *\n * WHY THE HOP, measured rather than assumed (390-30). A surface naming knowledge-local directly\n * fails `validate:arch` three separate ways: 387 D-20 removed it from the CLI's dependency\n * contract, the reader carve-out admits only the `/reader` subpath without a writer allowance, and\n * the FUNC-02 surface firewall ledger only ever SHRINKS — new surface code is fixed, never waived.\n * The composition root is the sanctioned way a host acquires what a private package holds.\n *\n * WHY `/reader` AND NOT THE MAIN ENTRY. SC5 pins the main entry to EXACTLY ONE importer\n * (`compose-local-agent.ts`); a second would red the singleton rule. Nothing is lost by holding to\n * the read entry, because these are frozen constant maps: they open nothing, write nothing and hold\n * no lease. No power crosses here — only the vocabulary needed to describe a decision already made.\n */\nexport {\n QUARANTINE_CLASS_DISPOSITIONS,\n QUARANTINE_FLOOR_ELIGIBILITY,\n} from '@vostride/agent-qa-knowledge-local/reader'\nexport type {\n QuarantineDisposition,\n QuarantineFloorEligibility,\n} from '@vostride/agent-qa-knowledge-local/reader'\n","// The one local composition root (Phase 385 plan 09 — D-15).\n//\n// `packages/agent` is storageNeutral — it may not touch `node:*`. Every host capability the\n// function ops and the job queue need is built HERE over the concrete local storage and handed in\n// as an injected port. This is the file `packages/cli/src/composition/function-registry.ts` named\n// as its own successor in its header, moved down to where the local implementations already live.\n//\n// Why it is here and not in a surface: 386's daemon composes the same host. A composition that\n// lives inside one surface is a composition every other host re-derives, and two hosts deriving the\n// same registry differently is the host-divergence bug class the dual-host proof exists to exclude.\n// So there is one function, and both hosts call it.\n//\n// Heavy first-party dependencies are legal in this subtree and nowhere else in this package; the\n// arch rule named composition-carveout enforces that, so the job store proper stays lean.\n\nimport { randomUUID } from 'node:crypto'\nimport { existsSync, readdirSync, readFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dirname, join } from 'node:path'\nimport { DatabaseSync } from 'node:sqlite'\n\nimport { canaryOutcomeObservationId, planMarkEvidence, projectMarkEvidenceOutcome } from '@vostride/agent-qa-knowledge-local/reader'\nimport {\n AUTHORING_DRAFT_VERIFY_FUNCTION_ID,\n CHAT_HELP_TEXT,\n CHAT_RESOLVER_TABLE,\n createAgentJobQueue,\n createChatCompactionHook,\n createChatState,\n createFunctionRegistry,\n createPlannerStage,\n createRealJobKindRegistry,\n createTurnEngine,\n deterministicOverrideStrategy,\n foldFunctionResult,\n invokeFunction,\n parseProposeGate1Allowance,\n projectPlannerTools,\n PROPOSE_GATE1_ALLOWANCE_CHECKPOINT,\n RUNS_START_FUNCTION_ID,\n replayToModelMessages,\n splitClauses,\n} from '@vostride/agent-qa-agent'\nimport type {\n AgentJobQueue,\n AuthoringFunnelPortLike,\n CapabilityCatalogPort,\n ChatConfigState,\n ChatDirectiveHandlers,\n ChatLanguageModel,\n ChatStateContainer,\n ChatStateSnapshot,\n ChatTokenAccounting,\n CompactionHook,\n LiveViewPort,\n PlannerStagePort,\n RunDetailReaderPort,\n ReconcileStrategy,\n AnalysisArtifactReaderPort,\n ClockPort,\n ConfigFilesPortLike,\n ConfigReaderPort,\n ConfigScaffoldContentPortLike,\n ConfigValidatePortLike,\n EntityDirectoryPort,\n FunctionDeps,\n FunctionRegistry,\n JobIdSource,\n JobKindRegistry,\n JobModelCapability,\n JobStorePort,\n KnowledgeReaderPort,\n PostRunJobCapabilities,\n RecurrenceLadder,\n RecurrenceProvider,\n RunInvocationPort,\n RunsReaderPort,\n StartedRun,\n StepEvidenceAddress,\n StepEvidenceLookup,\n} from '@vostride/agent-qa-agent'\nimport {\n ADDRESSING_LEDGER_DB_FILE,\n acquireEmbedder,\n acquireWriterLease,\n classifyIndexFace,\n countPendingCurationJobs,\n createMemorySightingSource,\n createLocalKnowledgeStore,\n createQuarantineOperations,\n QUARANTINE_FLAG_FLOOR,\n describeAllEntities,\n embedPendingEntities,\n countRemainingCurationWork,\n deriveWriterLeaseFreshness,\n drainQueue,\n DRAIN_BUDGET_MS,\n EMBEDDER_WORKER_REGISTRATION_FILE,\n EMBEDDER_WORKER_START_TIMEOUT_MS,\n EMBEDDER_WORKER_TERM_GRACE_MS,\n EmbedderWorkerTimeoutError,\n embedderWorkerProcessIsAlive,\n embedderWorkerSocketPath,\n enqueueCurationCandidateProjection,\n failureRecurrence,\n fingerprintRecurrence,\n listTestsInFile,\n foldQuarantineLedgerState,\n foldRetrievalRung,\n foldRunOutcomes,\n createDraftReceiptsStore,\n createSuiteFingerprintIndex,\n indexDbPath,\n readQuarantineLedger,\n readTestOutcomeHistory,\n getEntityDescriptor,\n heartbeatLease,\n inspectDrainableCurationWork,\n isLeaseStale,\n listQueuedCandidates,\n openAddressingLedger,\n openEntityIndex,\n openKnowledgeReader,\n purgeAffectedSetFingerprint,\n probeEmbedderWorkerSocket,\n purgeRecord,\n readCanonicalBundleAnchors,\n readCanonicalBundleStateDigests,\n canaryPostureFactsFor,\n standingReceiptDigestsFor,\n lowerTrustSharesFor,\n readEmbedderWorkerRegistration,\n readWriterLease,\n rebuildIndex,\n reconcileRunOutcomesProjection,\n entityIndexDbPath,\n resolveEntityRef,\n sightEntity,\n refreshWriterLeaseAuthority,\n releaseLease,\n removeEmbedderWorkerRegistration,\n resetEmbedderCapability,\n resolveEmbedderCapability,\n resolveProcessIncarnation,\n verifyEmbedderWorkerIncarnation,\n resolvePurgeAffectedSet,\n resolveRollbackAffectedSet,\n rollbackAffectedSetFingerprint,\n rollbackCampaign,\n rollbackCurationJob,\n runMaintenanceTail,\n sweepEntityIndex,\n RUN_OUTCOMES_PROJECTION_VERSION,\n ENTITY_INDEX_SWEEP_INTERVAL_MS,\n type EmbedderWorkerRegistration,\n type EntityIndexSweepReport,\n type ResolveEntityRefDeps,\n applyExplicitReview,\n appendMarkEvidence,\n triageMark,\n servedIdsOn,\n procedureReadOn,\n applyFeedback,\n enumerateBundleDirs,\n loadBundle,\n verifyBundleIntegrity,\n createAuthoringReader,\n openAddressingLedger as openAddressingLedgerForReview,\n resolveRetrievalRung,\n} from '@vostride/agent-qa-knowledge-local'\nimport type {\n ExplicitReviewDelegate,\n ExplicitReviewRequest,\n ExplicitReviewResult,\n CreateLocalKnowledgeStoreConfig,\n} from '@vostride/agent-qa-knowledge-local'\nimport type { KnowledgeReviewPort } from '@vostride/agent-qa-agent'\nimport type { FeedbackPort, FeedbackReadsPort } from '@vostride/agent-qa-schema'\nimport type { ArtifactRef } from '@vostride/agent-qa-schema'\nimport type { ServedRecordFacts } from '@vostride/agent-qa-knowledge-local'\nexport type { ServedRecordFacts, MarkTriage, ApplyFeedbackInput } from '@vostride/agent-qa-knowledge-local'\nimport { ReplayIncompleteError } from '@vostride/agent-qa-runner'\nimport {\n getActiveExecutionContext,\n setActiveExecutionContextResolver,\n} from '@vostride/agent-qa-safety'\nimport {\n ARTIFACT_FILE,\n FsEventLog,\n FsEvidenceArtifactStore,\n HANDOFF_FILE,\n RUNS_SUBDIR,\n loadCompletedRunHandoff,\n slugBranch,\n} from '@vostride/agent-qa-runner-local'\nimport {\n admitAnalysisArtifactForRun,\n ANALYSIS_FILE,\n asJobId,\n DEFAULT_EMBEDDING_PROFILE,\n guardRunAnalysisArtifact,\n maskPayloadTree,\n sha256hex16,\n} from '@vostride/agent-qa-schema'\nimport type {\n AuthoringBrief,\n AuthoringVerifyDraftInput,\n ChatSessionEvent,\n ChatSessionHandle,\n CompletedRunHandoff,\n DraftReceipt,\n ExecutionContext,\n GateReceipt,\n GateReceiptRecordOutcome,\n KnowledgeChangeOutput,\n KnowledgeChangeVerb,\n MaskFn,\n PromotionOutcome,\n RecordId,\n ResolvePromotionPosture,\n FunctionCaller,\n JobKind,\n QuarantineEntryStateName,\n QuarantineLadderState,\n RecordedTargets,\n RunEventEnvelope,\n RunId,\n RunStartAcknowledgement,\n TestEditPatchSet,\n TestFileWrite,\n RunsStartInput,\n ScopeKey,\n SessionLogPort,\n} from '@vostride/agent-qa-schema'\n\nimport { createKnowledgeReaderPort } from './knowledge-review-reader.js'\nimport type { SightMemoryEntities } from './knowledge-review-reader.js'\nimport { createEvidenceBlobReader, readEvidenceBlobBytes } from './evidence-blob-reader.js'\nimport { buildRunPorts } from './run-composition.js'\nimport type { RetrievalRungResolver } from './run-composition.js'\nimport { writeAnalysisArtifact } from '../analysis/persist-analysis.js'\nimport { createJsonlSessionLog } from '../session/jsonl-session-log.js'\nimport { createJobCheckpointStore } from '../store/job-checkpoint-store.js'\nimport { createPostProcessingReader } from '../store/post-processing-reader.js'\nimport { AGENT_JOB_STORE_DB_FILE, createSqliteJobStore } from '../store/sqlite-job-store.js'\nimport type { SqliteJobStore } from '../store/sqlite-job-store.js'\n\n// ---- the knowledge-writer capabilities (D-14, SC5) --------------------------------------------\n//\n// This file is the ONE place the knowledge package's writer-gated main entry is named, and the arch\n// rule named reader-carveout enforces both halves of that: a second file naming it fails, and zero\n// files naming it fails too — an allowance nothing uses is a rule that passes forever while\n// checking nothing.\n//\n// What this is NOT: a per-host binding. Every function below takes the roots and options it works\n// against as arguments, so there is nothing for a composition to close over and every host would\n// bind the identical object. Saying that plainly matters, because the value of gathering them here\n// is not parameterisation — it is that \"which writer powers does the local host grant?\" has one\n// answer, in one type, reachable through one edge, instead of being the union of whatever six\n// surface files happened to import.\n//\n// Consequence for a caller: a module that needs one of these at MODULE scope takes it from\n// `LOCAL_CURATION_CAPABILITIES` directly; a host that has a handle takes it from `host.curation`,\n// which is the same frozen object. Threading a handle through the curation tail's call graph would\n// have been a signature change to code D-14 requires this phase to leave semantically untouched.\n\n/**\n * 407 D-13/D-17 — THE retrieval-rung resolver, bound at the one edge that may name the writer\n * entry (385 D-14/SC5) and handed to `openRunKnowledgeComposition` by every run door.\n *\n * The binding exists so there is exactly ONE resolver in the tree with exactly ONE importer of\n * the package that owns it. `run-composition.ts` declares the seam's shape structurally and takes\n * the function as a required input rather than importing it — naming knowledge-local's main entry\n * from a second file would retire the singleton the arch gate enforces, and the fix would look\n * like relaxing the gate.\n *\n * Typed as {@link RetrievalRungResolver} rather than by its own signature, so the pass-through\n * that reaches the CLI is the narrow two-root contract the doors actually use — the embedder\n * `probes` seam and the preferred profile stay knowledge-local's business.\n */\nexport const resolveHostRetrievalRung: RetrievalRungResolver = resolveRetrievalRung\n\n/**\n * 407 D-18/D-20 — the READ-ONLY knowledge probes a diagnostic grades a host with.\n *\n * `doctor` needs the two axes SEPARATELY, not just the folded word: its `Knowledge store` row is\n * about the index face, its `Embedder` row is about the capability outcome, and only its third row\n * is the fold. {@link resolveHostRetrievalRung} above hands back the fold alone, so a surface that\n * had only that would have to re-derive the other two — which is a second fold in everything but\n * name, and exactly what D-17's one-resolver rule exists to prevent.\n *\n * Published as its own frozen table rather than folded into {@link LOCAL_DAEMON_CAPABILITIES}\n * because every member here is a READ. Nothing in it acquires a lease, spawns a worker, downloads\n * an artifact or writes to the knowledge root, and a caller that holds this object cannot mutate\n * the thing it is reporting on. That is the whole mitigation for T-407-19: the boundary is the\n * shape of the capability, not a promise in a doc comment at the call site.\n *\n * `foldRetrievalRung` rides along for the same reason the resolver does — one fold table in one\n * package, reached through the one edge that may name the writer entry (385 D-14/SC5).\n */\nexport interface LocalKnowledgeProbeCapabilities {\n readonly classifyIndexFace: typeof classifyIndexFace\n readonly foldRetrievalRung: typeof foldRetrievalRung\n readonly indexDbPath: typeof indexDbPath\n readonly readEmbedderWorkerRegistration: typeof readEmbedderWorkerRegistration\n readonly readWriterLease: typeof readWriterLease\n readonly resolveEmbedderCapability: typeof resolveEmbedderCapability\n}\n\nexport const LOCAL_KNOWLEDGE_PROBES: LocalKnowledgeProbeCapabilities = Object.freeze({\n classifyIndexFace,\n foldRetrievalRung,\n indexDbPath,\n readEmbedderWorkerRegistration,\n readWriterLease,\n resolveEmbedderCapability,\n})\n\n// The probe vocabulary the three doctor rows are typed against, re-exported through the same one\n// edge. Types are erased, so this hands a caller no power the frozen table above does not.\nexport type {\n AcquireEmbedderOutcome,\n IndexFace,\n ReadEmbedderWorkerRegistrationOutcome,\n ResolveEmbedderCapabilityOptions,\n} from '@vostride/agent-qa-knowledge-local'\n\n// 387-08 D-18: the delegate transport's own vocabulary, re-exported through the one edge that\n// names the writer entry. 2026-10-01 (432-17): the proposal door's `ApplyDelegate` and\n// `ApplyReviewResult` are deleted with it; a delegate receives the validated request and its stable\n// identity (432-09), never a proposal id to reload.\nexport type {\n ExplicitReviewDelegate,\n ExplicitReviewDelegation,\n ExplicitReviewRequest,\n ExplicitReviewResult,\n} from '@vostride/agent-qa-knowledge-local'\n\nexport type {\n AcquireWriterLeaseOutcome,\n AuthorOutcome,\n AuthoringTestRef,\n CurationCandidateProjection,\n CurationJobView,\n CurationProjectionArtifactSource,\n CuratorAuthor,\n EnqueueCurationCandidateProjectionOutcome,\n HeartbeatLeaseOutcome,\n LeaseOperationOptions,\n NeighborRecord,\n OpenServingKnowledgeReaderConfig,\n PurgeAffectedSet,\n PurgeReceipt,\n RebuildReport,\n ReadWriterLeaseOutcome,\n ReleaseLeaseOutcome,\n RollbackAffectedSet,\n RollbackCampaignInput,\n RollbackCurationJobInput,\n RollbackReport,\n WriterLease,\n WriterLeaseAuthority,\n WriterLeaseFreshness,\n} from '@vostride/agent-qa-knowledge-local'\n\n// Surface hosts reach worker lifecycle vocabulary through this one legal composition edge.\nexport {\n /**\n * THE one-shot post-run budget (388-02 D-03), reached through the same edge.\n *\n * Re-exported rather than restated: the CLI's post-run tail runs the agent-job chain under\n * the identical bound the curation drain has always used, and a surface that spelled `60_000`\n * of its own would be the second knob the user explicitly refused.\n */\n DRAIN_BUDGET_MS,\n EMBEDDER_WORKER_REGISTRATION_FILE,\n EMBEDDER_WORKER_START_TIMEOUT_MS,\n EMBEDDER_WORKER_TERM_GRACE_MS,\n EmbedderWorkerTimeoutError,\n // The projection's maintenance cadence reaches the daemon host through the same one edge.\n ENTITY_INDEX_SWEEP_INTERVAL_MS,\n}\n\n/**\n * The standing daemon's writer-authority substrate, published through the same one composition\n * edge as every other local writer capability. Surface packages may import agent-local, but the\n * architecture firewall deliberately forbids them from naming knowledge-local or safety\n * directly; keeping this frozen table here preserves that boundary without duplicating lease\n * behavior in the CLI host.\n */\nexport interface LocalDaemonCapabilities {\n readonly acquireWriterLease: typeof acquireWriterLease\n readonly heartbeatLease: typeof heartbeatLease\n readonly releaseLease: typeof releaseLease\n readonly readWriterLease: typeof readWriterLease\n readonly isLeaseStale: typeof isLeaseStale\n /**\n * CR-01/CR-08: the one three-valued freshness verdict — fresh, reclaimable, or unknown.\n *\n * Any surface that classifies a holder as recoverable must read this and not the lease file\n * alone, and must name what it does with `unknown` rather than inheriting a boolean it never\n * chose. An authority state that cannot be read is not evidence that nobody holds it.\n */\n readonly deriveWriterLeaseFreshness: typeof deriveWriterLeaseFreshness\n readonly countPendingCurationJobs: typeof countPendingCurationJobs\n readonly countRemainingCurationWork: typeof countRemainingCurationWork\n readonly inspectDrainableCurationWork: typeof inspectDrainableCurationWork\n readonly listQueuedCandidates: typeof listQueuedCandidates\n readonly acquireEmbedder: typeof acquireEmbedder\n readonly drainQueue: typeof drainQueue\n readonly runMaintenanceTail: typeof runMaintenanceTail\n readonly resolveEmbedderWorkerEntryPath: () => string\n readonly readEmbedderWorkerRegistration: typeof readEmbedderWorkerRegistration\n readonly embedderWorkerProcessIsAlive: typeof embedderWorkerProcessIsAlive\n readonly embedderWorkerSocketPath: typeof embedderWorkerSocketPath\n readonly probeEmbedderWorkerSocket: typeof probeEmbedderWorkerSocket\n /** CR-05: no surface may signal a registered worker pid without this verdict returning 'match'. */\n readonly verifyEmbedderWorkerIncarnation: typeof verifyEmbedderWorkerIncarnation\n // 2026-10-16 (442-02, D-20): a run owner's start time, read for the CLI's runs.db ownership.\n readonly resolveProcessIncarnation: typeof resolveProcessIncarnation\n readonly removeEmbedderWorkerRegistration: (\n agentQaRoot: string,\n expected: EmbedderWorkerRegistration,\n ) => ReturnType<typeof removeEmbedderWorkerRegistration>\n readonly resetEmbedderCapability: () => void\n readonly pinLocalHeadlessExecutionContext: () => void\n}\n\nfunction resolveEmbedderWorkerEntryPath(): string {\n const requireBase = typeof __filename === 'string'\n ? __filename\n : import.meta.url\n const knowledgeEntry = createRequire(requireBase).resolve('@vostride/agent-qa-knowledge-local')\n return join(dirname(knowledgeEntry), 'embedder-worker', 'worker-entry.js')\n}\n\nexport const LOCAL_DAEMON_CAPABILITIES: LocalDaemonCapabilities = Object.freeze({\n acquireWriterLease,\n heartbeatLease,\n releaseLease,\n readWriterLease,\n deriveWriterLeaseFreshness,\n isLeaseStale,\n countPendingCurationJobs,\n countRemainingCurationWork,\n inspectDrainableCurationWork,\n listQueuedCandidates,\n acquireEmbedder,\n drainQueue,\n runMaintenanceTail,\n resolveEmbedderWorkerEntryPath,\n readEmbedderWorkerRegistration,\n embedderWorkerProcessIsAlive,\n embedderWorkerSocketPath,\n probeEmbedderWorkerSocket,\n verifyEmbedderWorkerIncarnation,\n resolveProcessIncarnation,\n removeEmbedderWorkerRegistration,\n resetEmbedderCapability: () => resetEmbedderCapability(DEFAULT_EMBEDDING_PROFILE),\n pinLocalHeadlessExecutionContext: () => {\n setActiveExecutionContextResolver(() => 'local-headless')\n },\n})\n\n/**\n * Index maintenance and the campaign/job rollback verbs, plus the lease every one of them is only\n * legal to hold under. Grouped rather than flattened because they share that precondition: a host\n * reaching for `purgeRecord` without a lease is the mistake the grouping makes visible.\n */\nexport interface LocalKnowledgeMaintenanceCapabilities {\n readonly acquireWriterLease: typeof acquireWriterLease\n readonly refreshWriterLeaseAuthority: typeof refreshWriterLeaseAuthority\n readonly releaseLease: typeof releaseLease\n readonly rebuildIndex: typeof rebuildIndex\n readonly purgeRecord: typeof purgeRecord\n readonly resolvePurgeAffectedSet: typeof resolvePurgeAffectedSet\n readonly purgeAffectedSetFingerprint: typeof purgeAffectedSetFingerprint\n readonly rollbackCampaign: typeof rollbackCampaign\n readonly rollbackCurationJob: typeof rollbackCurationJob\n readonly resolveRollbackAffectedSet: typeof resolveRollbackAffectedSet\n readonly rollbackAffectedSetFingerprint: typeof rollbackAffectedSetFingerprint\n}\n\ninterface ReceiptWriterInput extends Pick<CreateLocalKnowledgeStoreConfig,\n 'knowledgeRoot' | 'executionContext' | 'resolvePromotionPosture' | 'resolveTrustPriors' | 'sourceBuildOrdinal' | 'sourceRunId'> {\n /** The caller already holds this authority; these capabilities never acquire a lease. */\n lease: { leaseId: string; epoch: number }\n}\n\nexport interface RecordGateReceiptInput extends ReceiptWriterInput {\n receipt: GateReceipt\n}\n\nexport interface PromoteWithReceiptsInput extends ReceiptWriterInput {\n candidateId: RecordId\n receipts?: readonly GateReceipt[]\n}\n\nfunction receiptWriter(input: ReceiptWriterInput) {\n return createLocalKnowledgeStore({\n knowledgeRoot: input.knowledgeRoot,\n executionContext: input.executionContext,\n writerLeaseId: input.lease.leaseId,\n epoch: input.lease.epoch,\n ...(input.resolveTrustPriors === undefined ? {} : { resolveTrustPriors: input.resolveTrustPriors }),\n ...(input.resolvePromotionPosture === undefined ? {} : { resolvePromotionPosture: input.resolvePromotionPosture }),\n ...(input.sourceBuildOrdinal === undefined ? {} : { sourceBuildOrdinal: input.sourceBuildOrdinal }),\n ...(input.sourceRunId === undefined ? {} : { sourceRunId: input.sourceRunId }),\n })\n}\n\nfunction recordGateReceipt(input: RecordGateReceiptInput): Promise<GateReceiptRecordOutcome> {\n return receiptWriter(input).recordGateReceipt(input.receipt)\n}\n\nfunction promoteWithReceipts(input: PromoteWithReceiptsInput): Promise<PromotionOutcome> {\n return receiptWriter(input).promote(input.candidateId, input.receipts)\n}\n\n/** Internal facts only: public showRecord deliberately omits bundle construction fields. */\nfunction readFeedbackRecord(input: { knowledgeRoot: string; recordId: string; evidenceRef?: ArtifactRef }): ServedRecordFacts | undefined {\n const matches = enumerateBundleDirs(input.knowledgeRoot).flatMap(entry => {\n const result = loadBundle(entry.dir)\n return result.kind === 'loaded' && result.bundle.manifest.id === input.recordId\n && verifyBundleIntegrity(entry.dir).ok ? [result.bundle] : []\n })\n if (matches.length !== 1) return undefined\n const bundle = matches[0]!\n const artifact = input.evidenceRef ?? bundle.artifactsIndex.artifacts[0]\n if (artifact === undefined) return undefined\n return { recordId: input.recordId, kind: bundle.frontmatter.kind,\n ...(bundle.frontmatter.subtype === undefined ? {} : { subtype: bundle.frontmatter.subtype }),\n anchors: bundle.frontmatter.anchors.map(anchor => anchor.raw), scope: bundle.frontmatter.scope,\n summary: bundle.summary, distilledEvidenceRef: { id: artifact.id, sha: artifact.sha },\n // This is the only admitted draft construction stage; user origin belongs on the delta.\n originStage: 'run-curation' }\n}\n\nexport interface LocalCurationCapabilities {\n readonly readFeedbackRecord: typeof readFeedbackRecord\n readonly appendMarkEvidence: typeof appendMarkEvidence\n /**\n * 2026-09-15, 423 D-16/D-17: the lease-free planning half appendMarkEvidence executes, so a\n * consequence preview names every confirm/overturn effect without the writer. Reads only.\n */\n readonly planMarkEvidence: typeof planMarkEvidence\n readonly projectMarkEvidenceOutcome: typeof projectMarkEvidenceOutcome\n readonly triageMark: typeof triageMark\n readonly servedIdsOn: typeof servedIdsOn\n readonly procedureReadOn: typeof procedureReadOn\n readonly applyFeedback: typeof applyFeedback\n readonly recordGateReceipt: typeof recordGateReceipt\n readonly promoteWithReceipts: typeof promoteWithReceipts\n /** Serving-side reader the tail folds against; read-only despite arriving on the writer edge. */\n readonly openKnowledgeReader: typeof openKnowledgeReader\n readonly drainQueue: typeof drainQueue\n readonly foldRunOutcomes: typeof foldRunOutcomes\n /**\n * THE mechanism a version bump rides (393 CR-02). The per-run receipt below carries the\n * version, but invalidating receipts only re-runs folds that answer 'already-applied' on the\n * durable marker — so the refold a bump promises happens through THIS capability, as a rebuild\n * of the derived family, and nowhere else.\n *\n * It is invoked at exactly two sites, one per supported host (393 round 6, CR-02-daemon): once\n * per CLI curation-tail sweep, and once per daemon lease acquisition. Both, because the CLI\n * tail is unreachable whenever a standing daemon takes the hand-off — a promise true of one\n * host is, on the other host, a projection that never converges.\n */\n readonly reconcileRunOutcomesProjection: typeof reconcileRunOutcomesProjection\n readonly enqueueCurationCandidateProjection: typeof enqueueCurationCandidateProjection\n readonly readCanonicalBundleAnchors: typeof readCanonicalBundleAnchors\n readonly readCanonicalBundleStateDigests: typeof readCanonicalBundleStateDigests\n readonly readCanaryPostureFacts: typeof canaryPostureFactsFor\n readonly readStandingGateReceipts: typeof standingReceiptDigestsFor\n readonly readLowerTrustShares: typeof lowerTrustSharesFor\n /** 418 D-07: reuse the writer's observation identity through the existing CLI bridge. */\n readonly canaryOutcomeObservationId: typeof canaryOutcomeObservationId\n /**\n * Component of the tail's receipt: a bump refolds runs already receipted at the old version.\n * The receipt is the per-run half of that promise; `reconcileRunOutcomesProjection` above is\n * the half that actually re-derives the rows.\n */\n readonly runOutcomesProjectionVersion: typeof RUN_OUTCOMES_PROJECTION_VERSION\n readonly maintenance: LocalKnowledgeMaintenanceCapabilities\n}\n\nexport const LOCAL_CURATION_CAPABILITIES: LocalCurationCapabilities = Object.freeze({\n readFeedbackRecord,\n appendMarkEvidence,\n planMarkEvidence,\n projectMarkEvidenceOutcome,\n triageMark,\n servedIdsOn,\n procedureReadOn,\n applyFeedback,\n recordGateReceipt,\n promoteWithReceipts,\n openKnowledgeReader,\n drainQueue,\n foldRunOutcomes,\n reconcileRunOutcomesProjection,\n enqueueCurationCandidateProjection,\n readCanonicalBundleAnchors,\n readCanonicalBundleStateDigests,\n readCanaryPostureFacts: canaryPostureFactsFor,\n readStandingGateReceipts: standingReceiptDigestsFor,\n readLowerTrustShares: lowerTrustSharesFor,\n runOutcomesProjectionVersion: RUN_OUTCOMES_PROJECTION_VERSION,\n canaryOutcomeObservationId,\n maintenance: Object.freeze({\n acquireWriterLease,\n refreshWriterLeaseAuthority,\n releaseLease,\n rebuildIndex,\n purgeRecord,\n resolvePurgeAffectedSet,\n purgeAffectedSetFingerprint,\n rollbackCampaign,\n rollbackCurationJob,\n resolveRollbackAffectedSet,\n rollbackAffectedSetFingerprint,\n }),\n})\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction isTargetName(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0\n}\n\n/**\n * The target names an artifact snapshot recorded (431 D-08), read out of an UNTRUSTED document:\n * a single test's resolved definition, or every suite member that recorded one. Any shape it does\n * not recognise answers `unknown`, so malformed metadata can never read as \"recorded no targets\".\n * Only the names cross this seam; no other part of the snapshot does.\n */\nfunction recordedTargetsOf(artifact: unknown): RecordedTargets {\n const source = isRecord(artifact) ? artifact.source : undefined\n if (!isRecord(source)) return { status: 'unknown' }\n\n if (source.kind === 'test') {\n const target = isRecord(source.resolvedDefinition) ? source.resolvedDefinition.target : undefined\n return isTargetName(target) ? { status: 'recorded', names: [target] } : { status: 'unknown' }\n }\n if (source.kind !== 'suite' || !Array.isArray(source.members)) return { status: 'unknown' }\n\n const names = new Set<string>()\n for (const member of source.members) {\n if (!isRecord(member)) return { status: 'unknown' }\n if (member.target === undefined || member.target === null) continue\n if (!isTargetName(member.target)) return { status: 'unknown' }\n names.add(member.target)\n }\n return names.size === 0 ? { status: 'unknown' } : { status: 'recorded', names: [...names].sort() }\n}\n\n/**\n * Enumerate `<agentQaRoot>/runs/<slug>/handoff.json`. A project with no runs directory is an\n * ordinary empty result, not an error; an individual unreadable or version-rejected document is\n * skipped so one bad run never hides every other run.\n */\nexport function createRunsReader(agentQaRoot: string): RunsReaderPort {\n function enumerate(): CompletedRunHandoff[] {\n const runsDir = join(agentQaRoot, RUNS_SUBDIR)\n if (!existsSync(runsDir)) return []\n\n const documents: CompletedRunHandoff[] = []\n for (const entry of readdirSync(runsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const handoffPath = join(runsDir, entry.name, HANDOFF_FILE)\n if (!existsSync(handoffPath)) continue\n try {\n documents.push(loadCompletedRunHandoff(handoffPath))\n } catch {\n continue\n }\n }\n return documents\n }\n\n return {\n list(): Promise<readonly CompletedRunHandoff[]> {\n return Promise.resolve(enumerate())\n },\n /**\n * Resolution runs over the ENUMERATED run documents and matches on the recorded `runId`,\n * never by joining the caller's string onto a path (T-384-08): a `runId` of `../../etc` can\n * therefore address nothing outside the runs directory, because it is never used to build a\n * path at all.\n */\n get(runId: RunId): Promise<CompletedRunHandoff | undefined> {\n return Promise.resolve(enumerate().find((document) => document.runId === runId))\n },\n /**\n * Deep replay of one run's `events.jsonl` through the SAME concrete store the v49 bus appends\n * with, so a replayed stream is byte-for-byte what the run emitted.\n *\n * Two cases are deliberately distinct. An absent or empty log is an ordinary empty replay —\n * nothing was recorded, so nothing was lost. A log whose earliest surviving seq is ABOVE the\n * requested resume point means events the caller asked for existed and are gone; that is\n * reported with the bus's own `ReplayIncompleteError` carrying the floor, never papered over\n * by returning the surviving suffix (D-07/D-08).\n */\n readEvents(runId: RunId, fromSeq: number): Promise<readonly RunEventEnvelope[]> {\n const recorded = [...new FsEventLog({ root: agentQaRoot, runId }).read(0)]\n .sort((left, right) => left.seq - right.seq)\n if (recorded.length === 0) return Promise.resolve([])\n\n const earliestAvailableSeq = recorded[0]!.seq\n if (fromSeq < earliestAvailableSeq) {\n return Promise.reject(new ReplayIncompleteError(fromSeq, earliestAvailableSeq))\n }\n return Promise.resolve(recorded.filter((event) => event.seq >= fromSeq))\n },\n /**\n * One step's persisted evidence, read back out of the run's own handoff document\n * (387 KREV-02 / D-15).\n *\n * Through `loadCompletedRunHandoff` — the version guard — and NOT through a raw JSON read,\n * which is the load-bearing half. 387-02 gave the guard a present-implies-valid clause for\n * the retrieval trace, so a document whose trace is present but malformed is refused here\n * rather than reaching the why-verb looking well-formed.\n *\n * The ambiguity check is the never-guess law at this seam. `stepIndex` numbers steps per\n * MEMBER TEST, so a run with two tests has two step 0s; when the address does not name a\n * test and more than one candidate answers to it, this reports the candidates rather than\n * picking whichever test the document happened to list first. Picking would have produced a\n * confident, wrong answer to a question that was never asked — and a why-verb that does\n * that is worse than one that refuses, because its answer looks exactly like a right one.\n */\n readStepEvidence(runId: RunId, address: StepEvidenceAddress): Promise<StepEvidenceLookup> {\n const document = enumerate().find((candidate) => candidate.runId === runId)\n if (document === undefined) return Promise.resolve({ kind: 'run-not-recorded' })\n\n const candidates = document.tests.filter((test) => (\n (address.testId === undefined || test.testId === address.testId)\n && test.steps.some((step) => step.stepIndex === address.stepIndex)\n ))\n if (candidates.length === 0) return Promise.resolve({ kind: 'step-not-found' })\n if (candidates.length > 1) {\n return Promise.resolve({\n kind: 'ambiguous-step-address',\n // Sorted, so the refusal a surface prints is the same list twice running.\n testIds: candidates.map((test) => test.testId).sort(),\n })\n }\n\n const evidence = candidates[0]!.steps.find((step) => step.stepIndex === address.stepIndex)\n return Promise.resolve(\n evidence === undefined\n ? { kind: 'step-not-found' }\n : { kind: 'found', evidence },\n )\n },\n /**\n * Resolved over the ENUMERATED run directories (T-384-08, T-431-01): the caller's id is only\n * ever compared, never joined onto a path, and the directory must hold a completed handoff\n * recording that same id, so one run's snapshot can never answer for another. A snapshot that\n * is absent, unreadable or gone since `list()` answered is `unknown`, never an error.\n */\n getRecordedTargets(runId: RunId): Promise<RecordedTargets> {\n const runsDir = join(agentQaRoot, RUNS_SUBDIR)\n if (!existsSync(runsDir)) return Promise.resolve({ status: 'unknown' })\n\n const entry = readdirSync(runsDir, { withFileTypes: true })\n .find((candidate) => candidate.isDirectory() && candidate.name === runId)\n if (entry === undefined) return Promise.resolve({ status: 'unknown' })\n\n try {\n const runDir = join(runsDir, entry.name)\n if (loadCompletedRunHandoff(join(runDir, HANDOFF_FILE)).runId !== runId) {\n return Promise.resolve({ status: 'unknown' })\n }\n return Promise.resolve(\n recordedTargetsOf(JSON.parse(readFileSync(join(runDir, ARTIFACT_FILE), 'utf8'))),\n )\n } catch {\n return Promise.resolve({ status: 'unknown' })\n }\n },\n }\n}\n\n/**\n * The knowledge READ port, served through the PHYSICALLY read-only `/reader` package entry.\n *\n * The five read verbs live in `knowledge-review-reader.ts`, which is registered in the arch\n * reader carve-out's pinned file list and therefore CANNOT name the writer-gated entry. This\n * file can (it also binds the curator), so keeping the verbs here would have put them in the\n * one place in the workspace where a write import is legal — separation by discipline instead\n * of by rule. What stays here is the half that genuinely belongs to a composition root: the\n * D-01 sighting site, which mints into the durable addressing ledger and so must live where\n * the writer entry may be named.\n *\n * The knowledge ROOT arrives as a host-supplied resolver rather than being derived here: deciding\n * which configuration file is in force, layering an environment over it and choosing whether to\n * load and execute auth plugins are three decisions a daemon makes differently from a terminal,\n * and by the plan-08 dissection rule a thing a headless host would substitute is a port.\n */\nexport function createKnowledgeReader(\n resolveKnowledgeRoot: () => Promise<string> | string,\n sightMemoryEntities?: SightMemoryEntities,\n resolvePromotionPosture?: () => Promise<ResolvePromotionPosture | undefined>,\n resolveTrustPriors?: CreateLocalKnowledgeStoreConfig['resolveTrustPriors'],\n): KnowledgeReaderPort {\n return createKnowledgeReaderPort({\n resolveKnowledgeRoot,\n ...(resolveTrustPriors === undefined ? {} : { resolveTrustPriors }),\n ...(resolvePromotionPosture === undefined ? {} : { resolvePromotionPosture }),\n ...(sightMemoryEntities === undefined ? {} : { sightMemoryEntities }),\n })\n}\n\n// ---- knowledge review: the WRITE half of the verb family (387 KREV-01 / D-17 · D-18) --------\n\nexport interface CreateKnowledgeReviewInput {\n readonly resolveTrustPriors?: CreateLocalKnowledgeStoreConfig['resolveTrustPriors']\n readonly resolvePromotionPosture?: () => Promise<ResolvePromotionPosture | undefined>\n readonly agentQaRoot: string\n readonly resolveKnowledgeRoot: () => Promise<string> | string\n /**\n * The writer lease this host ALREADY holds, when it is the holder (D-18).\n *\n * The daemon's half of the routing rule. A holder cannot acquire its own lease a second time, so\n * it hands the authority it owns to the change; supplying this is mutually exclusive with\n * supplying a delegate, and a host that supplies both is a host claiming to be two places.\n */\n readonly resolveWriterAuthority?: () => { readonly leaseId: string; readonly epoch: number } | undefined\n /**\n * 432-12 (D-05): how a direct change reaches a live writer-lease holder. The holder receives the\n * validated request and the change's stable identity, bounded; the lease is never taken. Absent,\n * a held lease refuses the change by name. Exclusive with {@link resolveWriterAuthority}: a holder\n * never delegates. The daemon supplies none, which is why its own changes cannot recurse.\n */\n readonly knowledgeChangeDelegate?: ExplicitReviewDelegate\n /**\n * 432-12: the context a direct change is recorded under. Absent means the process resolver, the\n * default every registry in this composition already reads. The context is recorded as-is; an\n * explicit change applies in every context (D-04/D-08).\n */\n readonly resolveExecutionContext?: () => ExecutionContext\n}\n\n/** The public answer to one direct change, from the explicit writer's own result (432-12). */\nfunction knowledgeChangeOutput(\n verb: KnowledgeChangeVerb,\n operationId: string,\n result: ExplicitReviewResult,\n): KnowledgeChangeOutput {\n switch (result.outcome) {\n case 'applied':\n return {\n outcome: 'applied',\n verb,\n operationId,\n recordIds: [...result.recordIds],\n ...(result.forgetReceipt === undefined ? {} : { forgetReceipt: result.forgetReceipt }),\n ...(result.commitReceipt === undefined ? {} : { commitReceipt: result.commitReceipt }),\n }\n case 'target-not-found':\n return { outcome: 'target-not-found', verb, operationId, target: result.target }\n case 'policy-materialize-refused':\n return { outcome: 'refused', verb, operationId, reason: 'policy-materialize-refused' }\n default:\n return result satisfies never\n }\n}\n\n/**\n * Bind the mutating review verbs over the review modules and the Curator's one commit path.\n *\n * A SEPARATE factory from `createKnowledgeReader`, mirroring the port split it implements: this\n * is the object whose presence makes accept/reject/forget report `bound`, and a host that wants\n * only the read verbs simply does not build one. The `MEM-` short-ID leg resolves through the\n * addressing ledger, opened per call and closed again on exactly the reasoning the entity\n * directory uses — a durable file the composition root owns, never a handle a review module holds.\n */\nexport function createKnowledgeReview(input: CreateKnowledgeReviewInput): KnowledgeReviewPort {\n async function roots(): Promise<{ knowledgeRoot: string }> {\n return { knowledgeRoot: await input.resolveKnowledgeRoot() }\n }\n\n // 432-12: this host's direct changes take the writer lease one at a time. Two changes racing in\n // one process would otherwise find the lease held by each other and the second would refuse as if\n // another writer held it. The queue releases on success and failure alike (the config\n // transaction's pattern); it does not claim to serialize across processes, which the lease does.\n let changeChain: Promise<unknown> = Promise.resolve()\n function serialized<T>(work: () => Promise<T>): Promise<T> {\n const next = changeChain.then(work, work)\n changeChain = next.then(() => undefined, () => undefined)\n return next\n }\n\n return {\n // 432-12 (D-04/D-05/D-09): one explicit change, applied in the call through the direct writer\n // (432-06). Nothing is filed: the change is committed under the lease, handed to a live\n // holder, or refused by type. A missing identity is minted here, once per call, and returned on\n // the receipt so the caller can retry the same change.\n change: (request) => serialized(async () => {\n const { knowledgeRoot } = await roots()\n const operationId = request.operationId ?? randomUUID()\n const authority = input.resolveWriterAuthority?.()\n const result = await applyKnowledgeChange({\n agentQaRoot: input.agentQaRoot,\n knowledgeRoot,\n request: { verb: request.verb, input: request.input } as ExplicitReviewRequest,\n operationId,\n // The op that made the change, stamped on Gate-3 receipts: `knowledge.accept`,\n // `knowledge.reject` or `knowledge.forget`, which is the verb's own op id.\n opId: `knowledge.${request.verb}`,\n executionContext: (input.resolveExecutionContext ?? getActiveExecutionContext)(),\n ...(input.resolveTrustPriors === undefined ? {} : { resolveTrustPriors: input.resolveTrustPriors }),\n ...(input.resolvePromotionPosture === undefined\n ? {}\n : { resolvePromotionPosture: input.resolvePromotionPosture }),\n ...(input.knowledgeChangeDelegate === undefined ? {} : { delegate: input.knowledgeChangeDelegate }),\n ...(authority === undefined ? {} : { writerAuthority: authority }),\n })\n return knowledgeChangeOutput(request.verb, operationId, result)\n }),\n // 2026-10-01 (432-17, D-05/D-22): `propose` and `apply` are deleted with the proposal inbox.\n }\n}\n\n\n\n// ---- 432-09: an explicit knowledge change, applied in the call (D-04/D-11) ------------------------\n\nexport interface ApplyKnowledgeChangeInput {\n readonly agentQaRoot: string\n readonly knowledgeRoot: string\n readonly request: ExplicitReviewRequest\n /** The caller's stable identity for this change: a retry with the same identity lands nothing twice. */\n readonly operationId: string\n /** The op making the change, stamped on its Gate-3 receipts. */\n readonly opId: string\n /** The caller's actual context, recorded as-is. An explicit change applies in every context. */\n readonly executionContext: ExecutionContext\n readonly resolveTrustPriors?: CreateLocalKnowledgeStoreConfig['resolveTrustPriors']\n readonly resolvePromotionPosture?: () => Promise<ResolvePromotionPosture | undefined>\n /**\n * How this host reaches a live writer-lease holder. The holder receives exactly the validated\n * request and identity, bounded; the lease is never taken. Absent, a held lease refuses by name.\n */\n readonly delegate?: ExplicitReviewDelegate\n /** The lease this host already holds, when it is the holder. Exclusive with {@link delegate}. */\n readonly writerAuthority?: { readonly leaseId: string; readonly epoch: number }\n}\n\n/**\n * Apply one explicit knowledge change through the direct writer (432-06), with this host's short-id\n * resolver. Nothing is filed: the change is committed, or it is refused by type.\n */\nexport async function applyKnowledgeChange(input: ApplyKnowledgeChangeInput): Promise<ExplicitReviewResult> {\n const posture = await input.resolvePromotionPosture?.()\n const ledger = openAddressingLedgerForReview({\n path: join(input.agentQaRoot, ADDRESSING_LEDGER_DB_FILE),\n })\n try {\n return await applyExplicitReview({\n agentQaRoot: input.agentQaRoot,\n knowledgeRoot: input.knowledgeRoot,\n request: input.request,\n operationId: input.operationId,\n opId: input.opId,\n executionContext: input.executionContext,\n resolveBundleShortId: (shortId) => ledger.lookupByShortId(shortId)?.machineId,\n ...(input.resolveTrustPriors === undefined ? {} : { resolveTrustPriors: input.resolveTrustPriors }),\n ...(posture === undefined ? {} : { resolvePromotionPosture: posture }),\n ...(input.delegate === undefined ? {} : { delegate: input.delegate }),\n ...(input.writerAuthority === undefined ? {} : { writerAuthority: input.writerAuthority }),\n })\n } finally {\n ledger.close()\n }\n}\n\n// ---- entities: the addressing ledger and the tier-(a) resolver (387 D-01/D-02/D-09) ----------\n\nexport interface CreateEntityDirectoryInput {\n readonly agentQaRoot: string\n readonly resolveKnowledgeRoot: () => Promise<string> | string\n}\n\n/**\n * Bind the entity directory over this host's durable addressing ledger.\n *\n * The ledger file is opened PER CALL and closed again, and both halves of that are deliberate.\n *\n * Opened per call, because the ledger is a durable file under the agent-qa root: opening it\n * eagerly at composition time would bring an `entity-addresses.db` into existence in a project\n * that has never resolved anything, and `agent-qa fn --list` is exactly such a caller. This is\n * the same law the job store's deferred `jobs()` handle carries, expressed for a port that has\n * no handle to defer.\n *\n * Closed again, because minting is LEASE-FREE by design (D-02) — the CLI must mint with no\n * daemon running, so several processes hold this file at once and sqlite arbitrates through\n * WAL and the busy timeout. A connection kept open for the life of a composition would hold a\n * reader open across a caller's whole session for no gain; the transactions here are single\n * statements at a human-paced grain.\n *\n * The path is resolved HERE rather than inside `knowledge-local`, beside `agent-jobs.db`, so\n * the package that owns the runtime root is the package that names its files.\n */\nexport function createEntityDirectory(input: CreateEntityDirectoryInput): EntityDirectoryPort {\n return {\n resolve(ref) {\n return withEntityResolutionDeps(input, (deps) => resolveEntityRef(ref, deps))\n },\n get(ref) {\n return withEntityResolutionDeps(input, (deps) => getEntityDescriptor(ref, deps))\n },\n }\n}\n\n/**\n * The D-01 LIST-VERB sighting site (387 plan 06).\n *\n * Lives beside the entity directory rather than inside the read port, because minting reaches\n * the durable addressing ledger through the writer-gated package entry, and the file that\n * binds the read verbs is held to the reader subpath by the arch carve-out. So the read port\n * is handed this callback and never a ledger.\n *\n * It goes through `sightEntity` — the resolver's OWN sighting leg — and not through a local\n * mint. D-01 names four sighting sites and a second minting path written for the fourth is a\n * second place where \"first sighting mints, idempotently, and projects into the entity index\"\n * could stop being true with nothing comparing the two. `resolveEntityRef` is deliberately NOT\n * what is called here: it would fall through to the hybrid tiers on an id no source recognises\n * (a purged record's id, say), running a retrieval to answer a question nobody asked.\n *\n * One ledger span for the whole batch. A listing surfaces every bundle at once, and opening the\n * two databases per row would turn a human-paced review verb into N open/close cycles.\n */\nexport function createMemorySightingHook(\n input: CreateEntityDirectoryInput,\n): SightMemoryEntities {\n return (bundleIds) => withEntityResolutionDeps(input, (deps) => {\n for (const bundleId of bundleIds) sightEntity(bundleId, deps)\n })\n}\n\n/**\n * Open the addressing ledger and the entity-index projection for ONE span, run `body`, close.\n *\n * Shared by the directory port and the list-verb sighting hook so both obey the same open/close\n * law rather than two copies of it.\n */\nasync function withEntityResolutionDeps<T>(\n input: CreateEntityDirectoryInput,\n body: (deps: ResolveEntityRefDeps) => T | Promise<T>,\n): Promise<T> {\n const knowledgeRoot = await input.resolveKnowledgeRoot()\n const ledger = openAddressingLedger({\n path: join(input.agentQaRoot, ADDRESSING_LEDGER_DB_FILE),\n })\n // The D-06 projection is opened beside the ledger and for the same span. It lives under\n // the KNOWLEDGE root rather than the agent-qa root because it is derived from knowledge\n // the same way the memidex index is, and it is disposable in exactly that sense — while\n // the ledger, one directory tree away, is the thing that must never be rebuilt.\n const entityIndex = openEntityIndex({ path: entityIndexDbPath(knowledgeRoot), knowledgeRoot })\n try {\n // AWAITED inside the try, not returned from it: tier (b)'s dense leg is asynchronous, so\n // returning the promise would close both databases while the resolution was still using\n // them. The bug is invisible while every caller is synchronous, which is exactly why it\n // is worth the word.\n return await body({\n ledger,\n entityIndex,\n // One kind is wired by the tracer. 387-03 registers the remaining sources here and\n // neither the resolver nor the ops change — which is the property the tracer exists\n // to establish before anything expands.\n sources: [createMemorySightingSource(() => knowledgeRoot)],\n })\n } finally {\n entityIndex.close()\n ledger.close()\n }\n}\n\nexport interface SweepEntityIndexInput extends CreateEntityDirectoryInput {\n /**\n * Test seam ONLY. Production omission runs the real acquisition ladder, which is what makes\n * the dense rung appear on hosts that have a model and stay absent on hosts that do not.\n */\n readonly acquireEmbedderCapability?: typeof acquireEmbedder\n}\n\nexport interface SweepEntityIndexOutcome extends EntityIndexSweepReport {\n /** How many renderings gained a vector this sweep. Zero on a floor host, by design. */\n readonly embedded: number\n}\n\n/**\n * The daemon's maintenance-cadence sweep over the D-06 projection.\n *\n * Three properties, and each is a deliberate refusal rather than an omission:\n *\n * - it takes NO writer lease. Everything it writes lives in the entity index's own file, and\n * a projection that needed the lease could not be maintained by a host that does not hold\n * one — which is every one-shot CLI process.\n * - it never writes the addressing ledger. It READS the ledger to know what exists (D-02: the\n * ledger is the durable truth, not a projection) and writes only the rendering of it.\n * - it embeds only what a host can already embed. `acquireEmbedder` with no download is the\n * same ladder the retrieval legs ride: ready means the dense rung joins the resolver on this\n * host, and anything else leaves the projection lexical-only rather than blocking the sweep.\n */\nexport async function sweepEntityIndexProjection(\n input: SweepEntityIndexInput,\n): Promise<SweepEntityIndexOutcome> {\n const knowledgeRoot = await input.resolveKnowledgeRoot()\n const ledger = openAddressingLedger({\n path: join(input.agentQaRoot, ADDRESSING_LEDGER_DB_FILE),\n })\n const entityIndex = openEntityIndex({ path: entityIndexDbPath(knowledgeRoot), knowledgeRoot })\n try {\n const report = sweepEntityIndex(entityIndex, describeAllEntities({\n ledger,\n sources: [createMemorySightingSource(() => knowledgeRoot)],\n }))\n\n let embedded = 0\n const acquire = input.acquireEmbedderCapability ?? acquireEmbedder\n const capability = await acquire({\n preferredProfile: DEFAULT_EMBEDDING_PROFILE,\n allowDownload: false,\n agentQaRoot: input.agentQaRoot,\n })\n if (capability.kind === 'ready') {\n embedded = await embedPendingEntities(\n entityIndex,\n capability.embedder,\n capability.profile,\n )\n }\n return { ...report, embedded }\n } finally {\n entityIndex.close()\n ledger.close()\n }\n}\n\n// ---- runs.start: the composition's binding (D-16) ---------------------------------------------\n\n/**\n * The host's run-execution capability: run this request to completion, and say which run it was.\n *\n * A PORT rather than shared code, by the plan-08 dissection rule. Would a headless drainer\n * execute a suite the way a terminal host does? It would substitute — the process model\n * (in-process, a child, a worker pool), the signal handling, the reporters and the exit\n * discipline are all decisions the host owns and answers differently. What crosses into the\n * composition is the type; what stays with the host is the orchestration.\n *\n * The verb resolves the IDENTITY of the run and nothing else. Anything richer would be the\n * host telling the composition what happened, and the whole point of the binding below is\n * that the composition does not take the host's word for it.\n */\nexport interface RunExecutionPort {\n /**\n * 2026-10-01 (432-18, D-15): the optional `gate` argument (401-08, D-08) carried the standing\n * approvals in force — the durable ledger's answer unioned with any dispatch-scoped grant — to a\n * run gate behind the port. The run gate went in 432-13 and the ledger and the dispatch overlay\n * go in 432-18, so a host is handed the request and nothing else.\n */\n execute(request: RunsStartInput): Promise<StartedRun>\n}\n\n/**\n * The run this host reported did not leave a durable event log behind.\n *\n * The composition's evidence check, and the reason `runs.start` cannot be satisfied by a host\n * that returns a plausible run id without running anything. The v49 bus writes `runStarted`\n * before anything else can happen, so a run that began at all has a non-empty log; an empty\n * one means no run took place under that id. Read through {@link buildRunPorts} — the same\n * `FsEventLog` family the runner appends with — so what is inspected is the run's own record\n * rather than a path this file re-derives.\n */\nexport class RunProducedNoEventsError extends Error {\n constructor(readonly runId: string) {\n super(\n `The host reported run ${runId}, but no run events were recorded for it. ` +\n 'A run that started at all writes runStarted before anything else, so an empty ' +\n 'event log means no run took place under that id.',\n )\n this.name = 'RunProducedNoEventsError'\n }\n}\n\n/**\n * Bind `runs.start` over a host's run execution.\n *\n * The composition contributes the half a host must not be trusted with: after the host says a\n * run happened, the run's own durable event log is read back and an empty one is refused. The\n * op then builds its acknowledgment from the completed-run record through the SAME reader\n * `runs.get` answers from, so \"the run is real\" and \"the run is addressable\" are one fact.\n */\nexport function createLocalRunInvocation(input: {\n readonly agentQaRoot: string\n readonly execution: RunExecutionPort\n}): RunInvocationPort {\n return {\n async start(request: RunsStartInput): Promise<StartedRun> {\n const started = await input.execution.execute(request)\n const { eventLog } = buildRunPorts({\n configDir: dirname(input.agentQaRoot),\n runId: String(started.runId),\n })\n if (eventLog.read(0).length === 0) {\n throw new RunProducedNoEventsError(String(started.runId))\n }\n return started\n },\n }\n}\n\n// ---- authoring.draft.verify: the keep-gate evaluator's binding (393 D-01 / D-15) --------------\n\n/** The stable test identity, spelled once for this binding. */\ninterface DraftIdentity {\n readonly filePath: string\n readonly testName: string\n}\n\n/**\n * A parsed draft, as the HOST hands it over.\n *\n * Structurally identical to `packages/agent`'s `ParsedDraftLike`, and mirrored here rather than\n * imported for the reason every mirror in this graph exists: that type lives inside `agent`'s\n * `authoring/` and is not on its barrel, and publishing it to give a composition a name would put\n * a gate-orchestration type on the surface that publishes exactly one dispatch.\n *\n * `filePath` MUST be the workspace-relative identity the runner records on\n * `PerTestOutcome.filePath` — `workspaceRelativeIdentityPath`, the one spelling of that recipe.\n * Gates 1-2 find the draft's own member inside each run document by comparing against those bytes,\n * so a path spelled any other way makes every gate-run report `absent` for its own draft and gate\n * 1 fail for a join reason wearing a draft reason's clothes.\n */\nexport interface ParsedDraftDescriptor {\n readonly testId: string\n readonly filePath: string\n readonly testName: string\n /**\n * The parsed test's `target`. REQUIRED, exactly as `ParsedDraftLike.target` and\n * `TestDefinitionSchema` require it (394-37, WR-04).\n *\n * A mirror that dropped it would hand `packages/agent` a draft whose target the compile stage\n * cannot check against the vocabulary it just served — and the cost of not checking is paid as\n * real child gate runs on a name `resolveTarget` throws on, against a key no repair patch may\n * edit.\n */\n readonly target: string\n readonly steps: readonly string[]\n /**\n * The parsed test's `context` block — an EDITABLE root, and therefore one the credential gate\n * scans. Structurally identical to `ParsedDraftLike.context`; a mirror that dropped it would\n * hand `packages/agent` a draft whose context can no longer be screened.\n */\n readonly context?: string\n readonly contentDigest: string\n}\n\n/**\n * What a host can say about a caller-supplied draft path.\n *\n * Four refusal arms and one success, because `packages/agent` is `storageNeutral` and genuinely\n * cannot answer any of them: it can neither stat a path nor know where the workspace ends. The op\n * turns each arm into its own NAMED error, so the refusal a caller catches is declared beside the\n * capability while the syscall stays with the host that owns a filesystem (T-393-01).\n */\nexport type DraftParseOutcome =\n | { readonly kind: 'parsed'; readonly draft: ParsedDraftDescriptor }\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/** One authored suite test as TEXT, for gate 3's degraded lane (D-16). */\nexport interface SuiteTextEntry {\n readonly filePath: string\n readonly testName: string\n readonly stepsText: readonly string[]\n}\n\n/**\n * The host's authoring capability: parse ONE draft, and enumerate the authored-test universe.\n *\n * BOTH VERBS OR NEITHER, and the bundling is a report rather than a convenience. A host that\n * supplied only the parse would bind a capability whose gate-3 text lane is permanently empty —\n * evidence-less suite tests would silently stop joining the comparison, and a draft would look\n * novel purely because whatever it duplicates has never been run. That is D-16's unsafe direction\n * arrived at by omission, and the only way to make it un-omittable is to make the two arrive\n * together.\n *\n * Both verbs live at the HOST because both need `parseTestFile` from `@vostride/agent-qa-core`,\n * which neither this package nor `agent` may import (the FUNC-02 firewall) — the parse-at-host\n * precedent `cli/src/curation/authoring-test-discovery.ts` established.\n */\nexport interface DraftAuthoringPort {\n parseDraft(filePath: string): Promise<DraftParseOutcome>\n suiteTextCorpus(): Promise<readonly SuiteTextEntry[]>\n /**\n * 394-33 · WR-07: the names a `target` may legally take in this project.\n *\n * ON THIS PORT for the reason `deriveDefaultScope` is: both hosts build their authoring\n * capability from ONE factory, so a verb that lives here is reached by the CLI `fn` surface and\n * the chat/daemon host without a second binding either could forget. A vocabulary served by only\n * one of the two hosts would make \"does stage 3 guess at `target`\" depend on which surface a\n * person happened to author from.\n *\n * IT ENUMERATES AND NEVER REFUSES — the opposite posture to `deriveDefaultScope` right below it,\n * which throws when the answer is not unique. There is no such thing as an ambiguous list, and a\n * project declaring no targets has an honest empty answer rather than a failure.\n */\n configuredTargetNames(): Promise<readonly string[]>\n /**\n * 394-26 · WINDOWS 110: which scope this project authors for, when the caller named none.\n *\n * ON THIS PORT rather than beside it, and that placement is the guarantee. Both hosts build\n * their authoring capability from one factory, so a verb that lives here is reached by the CLI\n * `fn` surface and the chat/daemon host without a second binding either could forget — which is\n * what makes \"there is ONE derivation\" a fact about the wiring rather than a convention.\n *\n * IT THROWS RATHER THAN ANSWERING `undefined` when the project has no unique product: the host\n * is the only side that knows which candidates it saw, and a refusal that cannot name them\n * leaves an author with no way to write the `scope` that would have worked.\n */\n deriveDefaultScope(): Promise<ScopeKey>\n /**\n * 394 D-01 · WTST-01: PARSE the compiled draft, then WRITE it to the shelf — in that order, as\n * one verb, joining for exactly the reason the two above bundle.\n *\n * ONE VERB AND NOT TWO, because the order is the mitigation (T-394-06). Model-authored YAML is\n * the one input on the authoring path that no schema at the op boundary can vet, and separate\n * verbs would let a caller write first and discover the parse failure afterwards — with bytes\n * already on this workspace's disk. Here an unparsable draft answers `unparsable` having\n * created nothing at all.\n *\n * THE DIGEST IS THE HOST'S, over the bytes it is writing, and it is the caller's only\n * addressing: the shelf path is minted from it, so nothing the model emitted reaches the\n * filesystem as a path component. `DraftRef.contentDigest`'s whole promise — a later edit\n * cannot inherit an earlier receipt — is only true while the digest is over what was stored.\n */\n stageDraft(contents: string): Promise<DraftStageOutcome>\n /**\n * 394-06 D-09/D-20: apply an RFC-6902 patch set to a staged draft and stage the result.\n *\n * AT THE HOST for the same reason its two neighbours are: `applyPatchSetToTestDoc` needs the\n * yaml CST from `@vostride/agent-qa-core`, which neither this package nor `agent` may import.\n * It answers the same `DraftStageOutcome`, so a patch that renders an unrunnable document is\n * refused with the shelf untouched rather than written and discovered later.\n */\n applyPatchesToDraft(\n draft: ParsedDraftDescriptor,\n patchSet: TestEditPatchSet,\n ): Promise<DraftStageOutcome>\n /**\n * 432 D-06/D-07: write a staged draft's bytes to its test path — the direct final-test writer.\n *\n * AT THE HOST for its neighbours' reason: the workspace identity mint lives in\n * `@vostride/agent-qa-core`. The host checks the boundary and that the target still holds the\n * bytes the caller read (absent for a new test), writes through a sibling temp and a rename, runs\n * no git, and answers `not-written` with its reason whenever the bytes did not land.\n */\n publishDraft(request: DraftPublishRequest): Promise<TestFileWrite>\n}\n\n/** One draft to write: its shelf path, its target, and what the target held when it was read. */\nexport interface DraftPublishRequest {\n readonly draftPath: string\n readonly targetPath: string\n readonly sourceDigest?: string\n}\n\n/**\n * What staging produced: a parsed draft that IS on the shelf, or a refusal that wrote nothing.\n *\n * Structurally the mirror of `agent`'s `DraftStageOutcome`, on this file's own mirror discipline\n * — that type lives inside `agent`'s `authoring/` and the value crossing this seam is assignable\n * to it unchanged.\n */\nexport type DraftStageOutcome =\n | { readonly kind: 'staged'; readonly draft: ParsedDraftDescriptor }\n | { readonly kind: 'unparsable'; readonly reason: string }\n\n/** The suite comparison, materialized once per evaluation. */\ninterface FingerprintSnapshot {\n readonly union: ReadonlySet<string>\n readonly covered: readonly DraftIdentity[]\n readonly elements: ReadonlyMap<string, readonly string[]>\n}\n\nconst EMPTY_FINGERPRINT_SNAPSHOT: FingerprintSnapshot = {\n union: new Set<string>(),\n covered: [],\n elements: new Map<string, readonly string[]>(),\n}\n\n/**\n * The 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 and 393-06 each shipped a module carrying a literal control byte and `file(1)` classified\n * both `data`, so every `grep` over them reported nothing — a false CLEAN verdict from the exact\n * instrument this phase's posture checks are made of. A separator is still needed, because\n * concatenation alone lets (\"ab\", \"c\") and (\"a\", \"bc\") collide.\n */\nfunction draftIdentityKey(identity: DraftIdentity): string {\n return `${identity.filePath}\\u0000${identity.testName}`\n}\n\n/**\n * Read the suite's fingerprints for one product, EXCLUDING the draft's own identity.\n *\n * THE UNION IS FOLDED FROM THE PER-TEST VERBS rather than read from `elementUnion()`, and that is\n * the whole reason this function exists. A draft is very often an EXISTING test — \"is this one\n * still worth keeping?\" is D-01's standalone value — so its own rows are in the table, and\n * `elementUnion()` would hand back a set already containing everything the draft exercises. Gate 3\n * would then find nothing novel and reject every test that has ever run, which is the mirror of\n * the defect 393-06 found on the other side: a gate that cannot say yes is as useless as one that\n * cannot say no. The exclusion is applied to `coveredTests()` and the union is folded from what\n * survives, so both of gate 3's lanes see the same suite and neither compares the draft to itself.\n *\n * A missing database, a store predating the projection, and a product with no rows all answer the\n * EMPTY snapshot, which gate 3 reads as an uncovered suite. Any other read failure propagates: a\n * corrupt index is not an empty suite.\n */\nfunction readSuiteFingerprints(\n knowledgeRoot: string,\n product: string,\n draft: DraftIdentity,\n): FingerprintSnapshot {\n const path = indexDbPath(knowledgeRoot)\n if (!existsSync(path)) return EMPTY_FINGERPRINT_SNAPSHOT\n const db = new DatabaseSync(path, { readOnly: true })\n try {\n const index = createSuiteFingerprintIndex(db, { product })\n const draftKey = draftIdentityKey(draft)\n const covered = index\n .coveredTests()\n .filter((identity) => draftIdentityKey(identity) !== draftKey)\n const elements = new Map<string, readonly string[]>()\n const union = new Set<string>()\n for (const identity of covered) {\n const own = index.elementsForTest(identity.filePath, identity.testName)\n elements.set(draftIdentityKey(identity), own)\n for (const element of own) union.add(element)\n }\n return { union, covered, elements }\n } catch (error) {\n if (error instanceof Error && error.message.includes('no such table')) {\n return EMPTY_FINGERPRINT_SNAPSHOT\n }\n throw error\n } finally {\n db.close()\n }\n}\n\ninterface DraftEvaluationBindingInput {\n readonly authoring: DraftAuthoringPort\n readonly agentQaRoot: string\n readonly knowledgeRoot: () => Promise<string> | string\n /** The SAME reader `runs.get` answers from — see below. */\n readonly readRun: (runId: string) => Promise<CompletedRunHandoff | undefined>\n /** Dispatch one gate-run through the REAL `runs.start` op (D-02, op-calls-op). */\n readonly startGateRun: (request: RunsStartInput) => Promise<RunStartAcknowledgement>\n /**\n * The funnel's read bundle, handed straight through for D-14's gate-2 consultation (394-17).\n *\n * THE SAME OBJECT the `authoring.funnel.get` op binds. This evaluation does not read a second\n * projection: it asks the one this composition already answers \"what does this project know\n * about this suite\" with.\n */\n readonly authoringFunnel: AuthoringFunnelPortLike\n}\n\n/**\n * Bind `authoring.draft.verify` over this host's capabilities (385 D-15).\n *\n * WHAT IS ASSEMBLED HERE, and why each piece is where it is:\n *\n * `runs.start` is reached as an OP, not as a port (D-02). The evaluator confirms a gate-run by\n * reading both markers off the ACKNOWLEDGMENT, and `runs.start` is the one function that copies\n * them from the run's own durable record instead of echoing the request. Binding the raw\n * invocation port instead would have meant re-deriving an acknowledgment here — a second\n * spelling of a contract that op already owns, free to disagree with it about exactly the fact\n * the confirmation turns on. It also means every gate-run crosses the policy gate and lands in\n * the execution audit, which is T-393-09's stated mitigation rather than a side effect.\n *\n * `runs.get` is reached as the READER and not as the op, because that op projects a `RunDetail`\n * and gates 1-2 need the completed-run HANDOFF: the per-step sub-action evidence gate 3's\n * fingerprint is minted from does not survive the projection. This is `runs-start.ts`'s own\n * posture verbatim — its acknowledgment is built \"through the SAME reader `runs.get` answers\n * from\" — applied one layer out.\n *\n * THE PRODUCT IS OBSERVED, NEVER DERIVED. `createSuiteFingerprintIndex` requires the partition\n * the fold wrote under, which is `slugBranch(scope.key)` of the run's own scope. Deriving it\n * here from configuration would be a SECOND rule for a fact the write side already decides, and\n * the first time the two disagreed a draft would be measured against an empty suite and pass\n * gate 3 for free. So it is read off the first acknowledgment this evaluation receives — and\n * since D-04 forbids short-circuiting, gates 1-2 have always taken at least one run by the time\n * gate 3 asks the index anything. The index is opened LAZILY for exactly that reason, and once:\n * three verbs against one snapshot, one connection, closed before gate 3 reads a byte of it.\n */\nfunction createDraftEvaluation(input: DraftEvaluationBindingInput) {\n return {\n resolveDraft(draftPath: string): Promise<DraftParseOutcome> {\n return input.authoring.parseDraft(draftPath)\n },\n async openEvaluation(draft: ParsedDraftDescriptor) {\n const knowledgeRoot = await input.knowledgeRoot()\n const draftIdentity: DraftIdentity = {\n filePath: draft.filePath,\n testName: draft.testName,\n }\n const draftKey = draftIdentityKey(draftIdentity)\n // The authored universe MINUS the draft itself. Handed its own bytes to compare against,\n // the text lane scores 1.0 and reads the draft as already covered — by itself.\n const textCorpus = (await input.authoring.suiteTextCorpus()).filter(\n (entry) => draftIdentityKey(entry) !== draftKey,\n )\n\n let observedProduct: string | undefined\n let snapshot: FingerprintSnapshot | undefined\n const fingerprints = (): FingerprintSnapshot => {\n if (snapshot !== undefined) return snapshot\n snapshot = observedProduct === undefined\n ? EMPTY_FINGERPRINT_SNAPSHOT\n : readSuiteFingerprints(knowledgeRoot, observedProduct, draftIdentity)\n return snapshot\n }\n\n return {\n runs: {\n async start(request: RunsStartInput): Promise<RunStartAcknowledgement> {\n const acknowledgement = await input.startGateRun(request)\n observedProduct ??= slugBranch(acknowledgement.scope.key)\n return acknowledgement\n },\n get: (runId: string) => input.readRun(runId),\n },\n fingerprints: {\n elementUnion: () => fingerprints().union,\n coveredTests: () => fingerprints().covered,\n elementsForTest: (filePath: string, testName: string) =>\n fingerprints().elements.get(draftIdentityKey({ filePath, testName })) ?? [],\n },\n textCorpus,\n // D-19: the gitignored per-draft receipt store, bound over `agentQaRoot` beside the\n // proposals inbox and for its reason — a receipt is machine-local working state under the\n // runtime root, not a committed artifact a pull request has any business showing.\n receipts: createDraftReceiptsStore({ resolveAgentQaRoot: () => input.agentQaRoot }),\n // D-14's live arm (394-17, step c). `product` is the SAME `observedProduct` gate 3's index\n // is opened against — read off the first gate-run acknowledgment, never derived from\n // configuration — so the stability read and the suite index can never be asking about two\n // different applications. Before any run is acknowledged it is `undefined` and the\n // consultation is skipped; D-04 forbids short-circuiting, so a flip cannot be observed\n // until at least one run has been.\n suiteStability: {\n port: input.authoringFunnel,\n product: () => observedProduct,\n },\n }\n },\n }\n}\n\n/**\n * The caller every gate-run is dispatched as (D-02, op-calls-op).\n *\n * MINTED HERE, on the rule every caller in this file is under: the composition says who a call is\n * on behalf of. `origin: agent` because nobody typed this run: a person asked for a draft to be\n * verified, and the runs that answer that are the system's own doing.\n *\n * 2026-10-01 (432-20/432-21, D-12): no scope set and no safe-mode flag. The two scopes this caller\n * held were exactly `authoring.draft.verify`'s declared ones, so a nested call could not widen what\n * the outer caller was granted; with no scope checked anywhere there is nothing to widen.\n */\nconst AUTHORING_GATE_RUN_CALLER: FunctionCaller = Object.freeze({\n surface: 'authoring',\n origin: 'agent',\n})\n\n/**\n * The caller the authoring loop's stage 4 dispatches `authoring.draft.verify` as (394 D-01,\n * op-calls-op · T-394-05).\n *\n * There is no second minted caller for `runs.start` / `runs.get`, and its absence is the design\n * rather than an omission. The loop takes no run of its own: every gate-run is started INSIDE\n * `authoring.draft.verify`, which already dispatches it on {@link AUTHORING_GATE_RUN_CALLER}\n * above.\n *\n * `origin: agent` for the reason the gate-run caller is: a person asked for a test to be written,\n * and the verification that answers it is the system's own doing. 2026-10-01 (432-20/432-21,\n * D-12): the narrowed scope pair this caller carried — the callee's own `requiredScopes`, asserted\n * against the spec — is deleted with the scope check it was narrowing for.\n */\nconst AUTHORING_LOOP_VERIFY_CALLER: FunctionCaller = Object.freeze({\n surface: 'authoring',\n origin: 'agent',\n})\n\n/** Wall-clock in the one format every store column and dump row is written in. */\nexport const SYSTEM_CLOCK: ClockPort = Object.freeze({\n now: (): string => new Date().toISOString(),\n})\n\n/**\n * Job ids are derived from `(kind, idempotencyKey)` rather than minted at random, so two hosts\n * enqueuing the same logical work address the same row and the store's unique index has something\n * stable to deduplicate on.\n */\nconst digestJobIdSource: JobIdSource = {\n jobIdFor: (kind, idempotencyKey) =>\n asJobId(`job_${sha256hex16(`${kind} ${idempotencyKey}`)}`),\n}\nexport const DIGEST_JOB_ID_SOURCE: JobIdSource = Object.freeze(digestJobIdSource)\n\n/**\n * The durable half of the host, opened on demand.\n *\n * `store` is the concrete sqlite store rather than the neutral port: the host that opened the\n * database is the one entitled to close it and to take the D-03 logical dump, and both verbs live\n * on the implementation. Nothing else in the package publishes it.\n */\nexport interface LocalAgentJobs {\n readonly queue: AgentJobQueue\n readonly store: SqliteJobStore\n readonly kinds: JobKindRegistry\n /** The capability the queue was constructed with, exposed so a host can assert what it bound. */\n readonly model: JobModelCapability\n /**\n * The id source the queue was constructed with.\n *\n * Exposed because a caller that watches this queue's outcomes must be able to derive the same\n * ids the enqueue addressed — the push half of a run's chip trail and the pull half of its\n * status have to agree about which rows belong to which run. Publishing the SOURCE makes that\n * agreement structural; re-deriving a default at the call site would make it a convention, and\n * a convention is exactly what breaks the first time a host is composed with a different one.\n */\n readonly idSource: JobIdSource\n /**\n * The kind exclusion the queue was constructed with, resolved from\n * `UNCLAIMABLE_BY_PROSE_POSTURE` and published for the same stated reason `idSource` is:\n * a caller that must assert what its queue was constructed with should read the value\n * rather than re-derive a default. Empty when the host declared `'masker-active'` or was\n * composed with no `postRun` at all.\n */\n readonly unclaimableKinds: readonly JobKind[]\n}\n\n/** Refusal returned when durable capabilities are requested after their composition was closed. */\nexport class LocalAgentClosedError extends Error {\n override readonly name = 'LocalAgentClosedError'\n\n constructor(readonly agentQaRoot: string) {\n super(\n `The local agent composition for ${agentQaRoot} is closed. A closed composition cannot `\n + 'reopen its job store; create a new composition with fresh lifecycle ownership instead.',\n )\n }\n}\n\nexport interface LocalAgentHost {\n /** The 384 function registry with every seed capability bound over local storage. */\n readonly registry: FunctionRegistry\n /**\n * The live chat session composed beside the registry (392 plan 08).\n *\n * Present on EVERY host, because the turn engine is (D-24) — a host whose chat session were\n * optional would make `agent.ask` bound and its state absent, which is two answers to whether\n * this host can hold a conversation.\n */\n readonly chat: LocalAgentChatSession\n /** The knowledge-writer powers this host grants — the same frozen object for every host. */\n readonly curation: LocalCurationCapabilities\n /** The clock every store column, dump row and audit stamp in this host is written against. */\n readonly clock: ClockPort\n /**\n * Open (once) the durable job queue and its sqlite store over this host's runtime root.\n *\n * A method rather than an eager member, and the reason is a behaviour rather than a taste:\n * constructing the store CREATES `<agentQaRoot>/agent-jobs.db` and the checkpoint directory. A\n * host that only lists the registry — `agent-qa fn --list` is exactly that — would otherwise\n * bring a queue database into existence in a project that has never enqueued anything. Repeated\n * calls return the same instance, so \"opened once\" is a property of the handle and not of the\n * caller's discipline.\n */\n jobs(): Promise<LocalAgentJobs>\n /** Close whatever was opened and join an open already in flight. Idempotent. */\n close(): Promise<void>\n}\n\n/**\n * What a host's curation binding does with candidate prose (388-10, UF-388-01 / D-11).\n *\n * A closed union, REQUIRED wherever `postRun` is supplied: a host that cannot say what its\n * fold does with candidate prose has not been reviewed for UF-388-01, and the typechecker is\n * what makes that review mandatory rather than customary.\n *\n * - `'masker-active'` — the fold has the declared-secret mask bound (441-01 decision 10), or the\n * binding never reaches candidate emission at all.\n * - `'no-masker'` — the binding folds with NO declared mask. A statement about DISCLOSURE, not\n * about capability: the fold would run, but its prose masking would degrade to a pass-through,\n * so a host declaring this may not claim the kind that runs it.\n */\nexport type CandidateProsePosture = 'masker-active' | 'no-masker'\n\n/**\n * The chain kinds a host of each posture MAY NOT CLAIM — one table, no second spelling.\n *\n * A `Record` over the union rather than a condition, deliberately: this phase's named defect\n * class is a guard whose input domain is written in prose while the code ranges over a\n * subset, and a total `Record` stops compiling the day a third posture is added. The queue's\n * `unclaimableKinds` is derived from this table and from nothing else.\n */\nexport const UNCLAIMABLE_BY_PROSE_POSTURE: Record<CandidateProsePosture, readonly JobKind[]>\n = Object.freeze({\n // Frozen to the same depth it is read at (WR-11). The shallow freeze every sibling table\n // here uses is not enough for this one: the VALUES are the arrays the queue claims\n // against, so an unfrozen inner array is a writable disclosure guard reachable from any\n // module that can import the table.\n 'masker-active': Object.freeze([]),\n 'no-masker': Object.freeze(['curate-memory'] as const),\n })\n\nexport interface ComposeLocalAgentInput {\n // 2026-10-14 (441-55, 441-16, D-06): the declared-secret mask for chat projections and run reads.\n readonly mask: MaskFn\n /** Immutable neutral data resolved by the host, reused until recomposition. */\n readonly resolveTrustPriors?: CreateLocalKnowledgeStoreConfig['resolveTrustPriors']\n readonly feedback?: FeedbackPort\n /**\n * 423 D-19/D-16: read-only mark history and consequence preview; absent leaves runs.marks.history\n * and runs.mark.preview unbound by name, and a port without `preview` leaves only the preview unbound.\n */\n readonly feedbackReads?: FeedbackReadsPort\n /** DATA across the wall: host preparation may await; candidate evaluation is synchronous. */\n readonly resolvePromotionPosture?: () => Promise<ResolvePromotionPosture | undefined>\n /** The project's runtime root, i.e. `<configDir>/.agent-qa`. Absolute. */\n readonly agentQaRoot: string\n /**\n * Masked configuration reads. Injected because flattening and masking a resolved configuration\n * needs the host's own loader — its file layering, its environment, its plugin policy — and the\n * masking decision is a disclosure boundary the host owns (T-384-07 / T-384-17).\n */\n readonly config: ConfigReaderPort\n /** Resolves the knowledge root this invocation serves from. See `createKnowledgeReader`. */\n readonly knowledgeRoot: () => Promise<string> | string\n /**\n * The model a job may author with (D-10, plan 05).\n *\n * A required factory. REQUIRED because the queue's own `model` option is required and not\n * defaultable — an optional capability means a queue can be built with none, and the only place\n * to discover that is inside an author callback far from the composition that forgot it. A\n * FACTORY because `jobs()` is deferred, and resolving a provider handle costs a configuration\n * read and an auth resolution that a host listing the registry must not pay.\n *\n * It is called at most once, when the queue is opened. `agent-local` never constructs a model:\n * its ownership contract forbids provider invocation, so the handle arrives already built and no\n * provider name is named here.\n */\n readonly model: () => JobModelCapability | Promise<JobModelCapability>\n /**\n * How this host executes a run (D-16). OPTIONAL, and the optionality is the reporting\n * mechanism rather than a convenience: a host that supplies it lists `runs.start` as\n * `bound` and can run it; a host that does not lists the same capability as `unbound` and\n * refuses it by name. Not every composition can start a run — a listing, a read-only\n * surface, 386's daemon before it wires an executor — and D-09 requires that to be a\n * visible state rather than a call that fails somewhere far from the composition.\n */\n readonly runExecution?: RunExecutionPort\n /**\n * How this host parses a draft and enumerates its authored suite (393 D-01), on the exact\n * optional-operation idiom `runExecution` above uses.\n *\n * OPTIONAL, and — like its neighbour — the optionality is the reporting mechanism rather than a\n * convenience. `authoring.draft.verify` is bound only where this AND `runExecution` are both\n * present, because a host that cannot parse a test file and a host that cannot start a run are\n * both hosts that cannot verify a draft. Either one missing lists the capability `unbound` BY\n * NAME, which is the honest answer; the alternative is a receipt whose four booleans were\n * computed from no runs at all, and a refusal wearing a verdict's clothes is the one answer that\n * could get a draft kept on the strength of nothing.\n *\n * Host-supplied for the reason `mintQuarantineIdentityPath` is: it needs `parseTestFile` and the\n * CHECKOUT ROOT, and neither this package nor `agent` may name `@vostride/agent-qa-core`.\n */\n readonly draftAuthoring?: DraftAuthoringPort\n // 432-16 (D-07): `draftApply`, `configApply` and `configUndoSource` are gone from this input. They\n // were the one-commit test-draft apply, the one-commit config apply and the git-history read the\n // config undo proposed from; agent-qa makes no git commits, so no host supplies them and the\n // pre-432 verbs that named them answer unbound until 432-17 deletes the verbs.\n /**\n * 395-01 D-03/D-17 · CFGM-01/04: the committed config file SET as RAW BYTES, plus the\n * comment-preserving field edit over them.\n *\n * Host-supplied because the edit is `yaml`'s Document API, and neither this package nor `agent`\n * may name that dependency under their ownership contracts. The CLI host already depends on it and already owns the file format.\n */\n readonly configFiles?: ConfigFilesPortLike\n /**\n * 395-01 CFGM-01: whole-config validation, run BEFORE a proposal surfaces.\n *\n * Host-supplied because `AgentQaConfigSchema` lives in `@vostride/agent-qa-core`, which neither\n * this package nor `agent` may name — the `mintQuarantineIdentityPath` arrangement exactly.\n */\n readonly configValidate?: ConfigValidatePortLike\n /**\n * 395-08 D-04 · CFGM-05: the shared scaffold CONTENT, rendered by the host that owns it.\n *\n * A SEPARATE OPTIONAL BINDING. The substance lives beside\n * `init`'s own write path in `packages/cli`, which neither this package nor `packages/agent` may\n * import; its absence leaves `config.project.scaffold` — and only that op — unbound, which is the\n * honest catalogue answer for a host that can edit a configuration but cannot create one.\n */\n readonly scaffoldContent?: ConfigScaffoldContentPortLike\n /**\n * 2026-09-30, 432-07 D-05/D-07: the direct config writer. Host-supplied because its transaction\n * is the dashboard's config file transaction, shared per path with the dashboard's own writes.\n */\n readonly configWrite?: FunctionDeps['configWrite']\n /**\n * 2026-08-17 (398 D-09 / D-11 · XPLN-02): the four host halves `agent.explain` needs — the\n * committed capability catalog as data, the model's citation over it, and the two coverage hooks.\n *\n * Host-supplied for the reason `scaffoldContent` is, and the boundary is harder here rather than\n * softer: the artifact is read by `loadCapabilityCatalog` in `packages/cli`, which walks the\n * package root and touches `fs`, and this package is host-neutral. The citation call needs the\n * model the chat host already composed through `createModel`, which is a resolution neither this\n * package nor `packages/agent` may perform. The coverage append is a file write.\n *\n * OPTIONAL, and the absence is the report. A composition that omits it lists `agent.explain`\n * `unbound` BY NAME rather than degrading to a model-only answer — which is the one behaviour\n * XPLN-02 exists to forbid, and the one that would be hardest to notice, because an explain\n * answering from model memory still sounds exactly like an explain.\n */\n readonly capabilityCatalog?: CapabilityCatalogPort\n /**\n * 403 D-03: the live-view mint seam `runs.liveurl` binds through, handed straight through from\n * the host — this composition decides nothing about it.\n *\n * OPTIONAL because the absence is a genuine host fact and not a degradation: a host serving no\n * HTTP origin has no URL it could honestly mint, so the op lists `unbound` BY NAME rather than\n * returning a link that resolves to nothing.\n */\n readonly liveView?: LiveViewPort\n /**\n * 405 D-03: the durable run-detail projection read `runs.detail` binds through, handed straight\n * through from the host — this composition decides nothing about it and constructs no database.\n *\n * OPTIONAL because a host may have no projection to read, and then `runs.detail` lists `unbound`\n * BY NAME. The CLI host binds a reader over the configured or default runs database path whenever\n * its config parses (a read before that file exists answers not recorded in the runs database);\n * the dashboard passes its own handle.\n */\n readonly runDetail?: RunDetailReaderPort\n /**\n * 432-12 (D-05): how a direct knowledge change reaches the writer-lease holder when one is alive,\n * as an OPTIONAL operation on the input bag rather than a new production seam (the 386-41 D-2\n * idiom): `agent-local` cannot name a socket and does not. The CLI host injects a closure\n * over `invokeViaDaemon` that invokes the change op there with the same identity; the daemon's\n * own composition injects nothing, because it holds the lease.\n */\n readonly knowledgeChangeDelegate?: ExplicitReviewDelegate\n /** The writer lease a leaseholding host already owns (387-08 D-18). See `createKnowledgeReview`. */\n readonly resolveWriterAuthority?: () => { readonly leaseId: string; readonly epoch: number } | undefined\n /**\n * Mints the durable workspace-relative identity the quarantine ledger keys `filePath` on\n * (390-12 / D-01). Core's `workspaceRelativeIdentityPath`, pre-bound by the host to its own\n * config directory.\n *\n * Host-supplied for the same reason `resolveWriterAuthority` one field up is: the CHECKOUT ROOT is\n * a fact only a host knows. Neither this composition nor the verbs beneath it can discover it, and\n * a layer that guessed would mint identities against the wrong root.\n *\n * REQUIRED, and — unlike its neighbour — not conditionally spread. The optionality of the writer\n * authority is a real report about a real difference between hosts: one holds the lease, one does\n * not. There is no host that can legitimately lack a checkout root, so an absent mint is not a\n * posture, it is exactly the unvalidated pass-through that let the write verbs author permanently\n * unreadable lines into a committed artifact. It belongs at compile time, at the composition that\n * forgot it.\n */\n readonly mintQuarantineIdentityPath: (filePath: string) => string\n readonly clock?: ClockPort\n readonly idSource?: JobIdSource\n /** The kind registry the queue dispatches through. Defaults to the six real declarations. */\n readonly jobKinds?: JobKindRegistry\n /**\n * What the post-run chain's real handlers may do (388 D-01), on the optional-operation\n * idiom `runExecution` and `applyDelegate` already use.\n *\n * OPTIONAL, and the optionality is the report rather than a convenience: a host that\n * supplies it dispatches the REAL analyze-run and curate-memory bodies, and a host that\n * does not keeps the scripted stand-ins. Only `curateRun` is asked for — the handoff read\n * is built here, from `agentQaRoot`, because it is a path derivation this package already\n * owns and a caller-supplied one would be a second layout to keep in step with the writer's.\n *\n * `curateRun` is the caller's because it is not a local concern at all: it needs the writer\n * lease, a knowledge root and the v51 drain, and the CLI's run tail is where all three\n * already meet (plan 02 binds it).\n */\n readonly postRun?: {\n readonly curateRun: PostRunJobCapabilities['curateRun']\n /**\n * REQUIRED beside the binding it describes: a `postRun` that omits it must stop\n * typechecking, because the posture is the UF-388-01 review of this binding and an\n * unreviewed binding is exactly what let the daemon fold unmasked. See\n * `CandidateProsePosture` for what each member does and does not certify.\n */\n readonly candidateProse: CandidateProsePosture\n /**\n * The 422 D-13 proposal stage's staging port, passed straight through.\n *\n * OPTIONAL beside a REQUIRED `curateRun`, and the asymmetry is the contract: without\n * `curateRun` there is no real fold and therefore no real chain, whereas a host that binds\n * no staging port still runs the third stage — it stages nothing, records no counts, and\n * the terminal says exactly that. Passed through rather than built here for the same reason\n * `curateRun` is: the adversarial staging is not a local concern, and this package may not\n * name the seam it lives behind.\n */\n readonly stageAdversarialProposal?: PostRunJobCapabilities['stageAdversarialProposal']\n /**\n * The 422 D-14 Gate-1 leg's four ports, passed straight through (422-09).\n *\n * NEUTRAL FORWARDING, and the neutrality is the contract rather than a style note: every one\n * of these needs a committed corpus, a screening run and a writer this package may not name,\n * and a version of this file that could construct them could not be this file. What crosses\n * here is four closures and a number; what stays on the other side is every fact about where\n * they read from.\n *\n * Each is OPTIONAL and each is spread on presence, because a host that binds none is the\n * shipped posture — the stage runs, screens nothing, and says so by omitting the member.\n */\n readonly runReplayGate?: PostRunJobCapabilities['runReplayGate']\n readonly listBundles?: PostRunJobCapabilities['listBundles']\n readonly gateReceiptsFor?: PostRunJobCapabilities['gateReceiptsFor']\n readonly readProposeCorpusPosture?: PostRunJobCapabilities['readProposeCorpusPosture']\n /**\n * 2026-09-13, 422 D-19, gap plan 422-27: the host's durable per-run evaluation-root\n * posture, forwarded as a neutral closure. Absence leaves the handler's fail-closed\n * default in force; this composition neither resolves nor interprets the posture.\n */\n readonly readMisdirectionRootPosture?: PostRunJobCapabilities['readMisdirectionRootPosture']\n /**\n * The operator's per-job Gate-1 bound, as a FACTORY resolved once at queue open.\n *\n * A factory on the exact `model` / `analysisTokenBudget` idiom, for the same reason those are:\n * reading it needs a configuration read, and paying for one at composition would charge every\n * host that only lists the registry. The capability itself is plain data — a number the\n * handler reads and never a reader it calls.\n */\n readonly proposeGate1MaxPerJob?: () =>\n | Promise<number | undefined>\n | number\n | undefined\n }\n /**\n * D-01's TokenAccounting substrate for the analyze-run author (389 plan 06). OPTIONAL\n * and host-resolved: both production hosts derive it from the SAME model-profile\n * resolution as the job model itself (one source of truth, no second config surface —\n * 386 D-15), and `composeLocalAgent` only passes the resolved value through. A FACTORY\n * on the exact `model` idiom — resolution may need a configuration read, and it is paid\n * once, at queue open, never by a host that only lists the registry. A factory that\n * answers `undefined` composes the plan-04 no-ladder posture: packs travel whole.\n */\n readonly analysisTokenBudget?: () =>\n | Promise<PostRunJobCapabilities['analysisTokenBudget']>\n | PostRunJobCapabilities['analysisTokenBudget']\n /**\n * The host's execution context for this composition (400-01, D-05).\n *\n * 2026-10-02 (432-39, D-12): it reaches the knowledge review, which records a direct change under\n * it, and nothing else here; the registry option it was also forwarded to is deleted, because no\n * op decides in a context. The history below explains why it is injected per composition.\n *\n * INJECTED RATHER THAN PINNED ON THE PROCESS, and that is the whole reason this field exists.\n * The registry accepted a `resolveExecutionContext` from 384 until 432-39; what it did NOT have\n * was a way for a host to supply one, so the only lever a host had was\n * `setActiveExecutionContextResolver` — a PROCESS GLOBAL. Reaching for it changes the answer\n * for everything composed in that process, including compositions the host does not own, and a\n * host that forgot to restore it leaks its posture into every later caller. The dashboard door\n * is the first host that has to state a posture per composition rather than per process\n * (D-01/D-05: the browser confirm channel is what makes the context interactive, and it is a\n * property of a server, not of the machine), so the injected form is what it binds.\n *\n * ABSENT MEANS THE SHIPPED AMBIENT RESOLVER, unchanged: the knowledge review's own default reads\n * safety's process resolver, so every existing host composes exactly as it did before. This is\n * a passthrough and nothing here decides what a context MEANS. (432-19: `requiresFailClosed`, the\n * gate's reading of a context, is deleted; the four-member vocabulary stays.)\n */\n readonly resolveExecutionContext?: () => ExecutionContext\n /**\n * Notified AFTER one session event has been appended to its log (400-01, D-03).\n *\n * AN OBSERVER, AND EVERY WORD OF THAT IS THE CONTRACT. It is called with an event that is\n * ALREADY ON THE FILE — after `append` resolves, never before and never instead — so a host\n * pushing these somewhere cannot show a person an event the durable log does not carry. It\n * cannot append, cannot rewrite and cannot refuse: the return value is discarded and a throw is\n * swallowed at the notify site, because a surface's push channel failing must not fail the turn\n * that produced the event.\n *\n * WHY THIS AND NOT A HOST-SUPPLIED `SessionLogPort`. The obvious alternative — let a host wrap\n * or replace the log — is exactly what D-04 forbids: sessions belong to the agent, not to a\n * surface, and a replaceable log is a second store one conversation at a time. This seam widens\n * nothing. The log stays the single producer and the single writer; what a host gets is a\n * carbon copy of what was written.\n *\n * The SESSION ID travels with the event because the event itself carries only a `turnId` — the\n * grammar's exact-key guard means it never will carry more (Pitfall 4), so the fact a subscriber\n * needs is supplied beside the record rather than smuggled into it.\n */\n readonly observeSessionEvent?: (sessionId: string, event: ChatSessionEvent) => void\n // 2026-10-01 (432-17, D-05): `mintingSurface` — which door a composition minted proposals as\n // (400-05) — is deleted with the proposal records it stamped. A direct change records no door.\n /**\n * The turn engine's reconciliation strategy (392 D-16).\n *\n * AN INTERNAL COMPOSITION OPTION, and every word of that is load-bearing. It is here so the\n * mutation proof can assemble the REAL host twice — override on, override off — and read the\n * difference off a named compound scenario, which is the only differential that measures what\n * production actually wires (Pitfall 3, the produced-not-literal law).\n *\n * IT IS NOT, AND MUST NEVER BECOME, CONFIG-REACHABLE. No field of `AgentQaConfig` names it and\n * none may: the deterministic override is the mechanism that stops a model's plan from beating\n * a proven mapping, so a production knob that switched it off would be a supported way to\n * disable a safety property. Absent, the shipped strategy is used — which is what makes the\n * absence the safe default rather than an unconfigured state.\n */\n readonly chatReconcile?: ReconcileStrategy\n /**\n * The model stage 2 plans with, ALREADY BUILT by the host through `createModel` (CHAT-06).\n *\n * A model OBJECT and never a model id: the SDK's own type also admits an id it resolves by\n * constructing a client, which would put a provider client behind chat without the masking\n * middleware and the profile resolution `createModel` owns. The type closes that door here.\n *\n * ABSENT IS A REAL POSTURE, NOT AN UNCONFIGURED ONE. A host with no model bound is HEADLESS: any\n * clause the deterministic table cannot resolve fails the turn closed by name (D-08), which is\n * the correct behaviour rather than a degraded one. That is also why no planner is stubbed in —\n * a stub answering \"I could not plan that\" would say the same words about an entirely different\n * fact, that a model was asked and declined.\n */\n readonly chatModel?: ChatLanguageModel\n /**\n * The accounting instance chat's degrade pass measures against (CHAT-04, plan 06).\n *\n * HOST-RESOLVED and passed through untouched, on `analysisTokenBudget`'s precedent and for its\n * reason: the ceilings must come from the SAME capability resolution as the chat model itself,\n * or a session would compact against a window the model does not have. This composition adds no\n * knob of its own and cannot construct one — `agent-local` reaches no provider.\n *\n * Absent ⇒ no degrade pass runs and the `compaction` seat stays empty, which is the posture\n * every host had before a model was bound.\n */\n readonly chatAccounting?: ChatTokenAccounting\n /**\n * How this host resolves a model NAMED by `/model <name>` (D-04, plan 08).\n *\n * Supplied by the host for the same reason `chatModel` is, and enforced by the same rule: the\n * chat subtree may not construct a model, so a session-scoped switch has to arrive as a\n * capability the composition was handed. Absent ⇒ `/model` still records the session's declared\n * model and emits its `model_change` (the header, the prompt and the drift check all follow it),\n * and no new client is resolved — the honest behaviour for a host that composed one model.\n */\n readonly chatModelFor?: (name: string) => ChatLanguageModel | Promise<ChatLanguageModel>\n /**\n * Where a chat session PRINTS a mid-turn artifact a person reads (395-13, D-14).\n *\n * A PLAIN FUNCTION: printing needs nothing from this composition. The surface is handed text and\n * writes it. (432-16 deleted the `chatConfirm` factory that used to sit beside it.)\n *\n * PASSED THROUGH UNTOUCHED to the turn engine's `present`. Absent ⇒ the engine renders nothing\n * mid-turn, which is every host that is not a REPL — and no gate, receipt or session row moves.\n */\n readonly chatPresent?: (text: string) => void | Promise<void>\n}\n\n// 432-16 (D-14/D-15): `ChatConfirmBindings` and `ChatApprovalDecisionRecord` are deleted with the\n// chat confirm they served. Nothing asks, so no grant is minted from chat and no `approval_decision`\n// row is written; sessions written before 432 still carry such rows and the session guard in\n// `schema/src/chat/session-events.ts` still reads them.\n\n/**\n * The live chat session a host holds beside the registry (plan 08, RESEARCH Open Q2).\n *\n * Exposed because two of its facts have no other route to a surface: the state a REPL renders\n * from, and the ability to close an interrupted turn honestly. Everything else a conversation does\n * goes through `agent.ask` like every other capability (D-24).\n */\nexport interface LocalAgentChatSession {\n /**\n * The live state of ONE conversation, or `undefined` for a session this host has not opened\n * (392 plan 13, CR-02).\n *\n * A LOOKUP RATHER THAN A CONTAINER, because the facts inside it — the turn in flight, the\n * conversation, the model in force, what `/pin` denies, whether `/quit` was typed — are facts\n * about a session and never about a host. A composition serving two conversations that handed\n * out one container was answering both of them with whichever turn wrote last, which is what\n * let a planner read the wrong history (CR-02) and a pin outlive its session (W-03).\n *\n * `undefined` is the honest answer for an id nobody here is holding, and reading NEVER creates\n * a scope: a surface asking about a session cannot bring one into being by asking.\n */\n stateFor(sessionId: string): ChatStateSnapshot | undefined\n /**\n * Write the explicit `aborted` event for the turn in flight, and fsync (D-19's graceful arm).\n *\n * A no-op between turns, deliberately: an `aborted` row for a turn that already carries its\n * `turn_complete` would make the repair on the next open trim a turn that finished.\n */\n abortActiveTurn(): Promise<void>\n}\n\n/**\n * One test's recorded outcome history, read per query from the derived run-outcome\n * projection (389 plan 02's read side) at `<knowledgeRoot>/memory/index/knowledge.db`.\n *\n * Absence discipline: a database that was never created, a store predating the projection\n * tables, and an identity the projection never counted ALL answer `undefined` — the author\n * and the renderer both carry a typed no-history posture, and faking an empty row would\n * erase the distinction plan 02 pinned. Any OTHER read failure propagates: a corrupt store\n * is not \"no history\".\n */\nfunction readProjectedTestHistory(\n knowledgeRoot: string,\n query: { readonly product: string; readonly filePath: string; readonly testName: string },\n): ReturnType<typeof readTestOutcomeHistory> {\n const path = indexDbPath(knowledgeRoot)\n if (!existsSync(path)) return undefined\n const db = new DatabaseSync(path, { readOnly: true })\n try {\n return readTestOutcomeHistory(db, {\n product: query.product,\n filePath: query.filePath,\n testName: query.testName,\n })\n } catch (error) {\n if (error instanceof Error && error.message.includes('no such table')) return undefined\n throw error\n } finally {\n db.close()\n }\n}\n\n/**\n * The recurrence pair the clause renders, from whichever window the query keyed (390 D-07).\n *\n * `kth` / `windowBuilds` keep 389's names because they are the renderer's vocabulary; what\n * changed underneath is which window answers them.\n */\ninterface ProjectedRecurrence {\n readonly kth: number\n readonly windowBuilds: number\n}\n\n/**\n * One recurrence read, over ONE connection (390 D-07).\n *\n * A query CARRYING a fingerprint is answered by the fingerprint-keyed window — the same failure\n * recurring, which is what the ladder triggers on — and a query without one falls back to the\n * per-test window 389 bound this seam to. The fallback is not a degradation: a member with no\n * failing step to key from has no fingerprint to count, and its per-test history is the honest\n * answer rather than a stand-in key's.\n *\n * The read-time \"current build\" is the row's own `lastBuildOrdinal` (falling back to the greatest\n * windowed ordinal) for BOTH legs: at render time the latest recorded build IS current, and using\n * one ordinal for both keeps the numerator and the denominator on the same window.\n */\nfunction readProjectedRecurrence(\n knowledgeRoot: string,\n query: { readonly product: string; readonly filePath: string; readonly testName: string\n readonly fingerprint?: string },\n): ProjectedRecurrence | undefined {\n const path = indexDbPath(knowledgeRoot)\n if (!existsSync(path)) return undefined\n const db = new DatabaseSync(path, { readOnly: true })\n try {\n const history = readTestOutcomeHistory(db, {\n product: query.product,\n filePath: query.filePath,\n testName: query.testName,\n })\n if (history === undefined) return undefined\n const currentBuildOrdinal =\n history.lastBuildOrdinal\n ?? history.lastOutcomes.reduce((max, entry) => Math.max(max, entry.buildOrdinal), 0)\n if (query.fingerprint === undefined) return failureRecurrence(history, currentBuildOrdinal)\n const windowed = fingerprintRecurrence(\n db,\n { product: query.product, fingerprint: query.fingerprint },\n currentBuildOrdinal,\n )\n return { kth: windowed.occurrenceOrdinals, windowBuilds: windowed.windowOrdinals }\n } catch (error) {\n if (error instanceof Error && error.message.includes('no such table')) return undefined\n throw error\n } finally {\n db.close()\n }\n}\n\n/**\n * What a folded ledger entry renders as on the sentence's ladder — a TOTAL table (390 D-17).\n *\n * `satisfies Record<QuarantineEntryStateName, …>` is load-bearing: a fourth ledger state cannot\n * compile until someone decides how it reads to a human. `released` maps to NO rung because a\n * closed window is history, not a state of the test today — the clause would otherwise announce a\n * quarantine that ended.\n */\nconst LADDER_STATE_FOR_ENTRY = {\n quarantined: 'quarantined',\n expired: 'expired',\n released: undefined,\n} as const satisfies Record<QuarantineEntryStateName, QuarantineLadderState | undefined>\n\n/**\n * The ladder rung this identity sits on, joined LIVE from the committed ledger (390 D-06/D-17).\n *\n * Keyed on IDENTITY, not on the fingerprint: the ledger records which TEST is suppressed, and a\n * test whose failure mode changed is still suppressed. `now` arrives as an argument (one read per\n * query — two reads could land either side of one deadline).\n *\n * An unreadable ledger PROPAGATES its typed error rather than answering \"no rung\". Healing here\n * would render a suppressed test's sentence as an ordinary one, which is the silent flip this\n * phase exists to prevent (the same posture 390-03 pinned for the authoring reader).\n *\n * Below the ledger, the FLAG floor: a fingerprint at D-06's floor with no open window is\n * `flagged` — one build of warning before anything changes — and that covers both halves of\n * D-05's class gate, since a class that never auto-quarantines still recurs loudly here.\n */\nfunction readQuarantineLadder(\n knowledgeRoot: string,\n identity: { readonly product: string; readonly filePath: string; readonly testName: string },\n now: string,\n recurrence: ProjectedRecurrence,\n): RecurrenceLadder | undefined {\n const entries = foldQuarantineLedgerState(readQuarantineLedger(knowledgeRoot).events, now)\n const entry = entries.find((candidate) =>\n candidate.product === identity.product\n && candidate.filePath === identity.filePath\n && candidate.testName === identity.testName)\n const state = entry === undefined ? undefined : LADDER_STATE_FOR_ENTRY[entry.state]\n if (entry !== undefined && state !== undefined) return { state, expiresAt: entry.expiresAt }\n if (recurrence.kth >= QUARANTINE_FLAG_FLOOR) return { state: 'flagged' }\n return undefined\n}\n\ninterface ProjectionRecurrence {\n readonly provider: RecurrenceProvider\n /**\n * Resolve (and cache) the knowledge root the SYNC provider reads under. See the\n * `runs.get` wrapper in `composeLocalAgent` for why this exists and where it is awaited.\n */\n prime(): Promise<void>\n}\n\n/**\n * The D-08 recurrence seam, bound at ONE composition root.\n *\n * 389 bound it to v51's per-test run-outcome window; 390-06 REBOUND the COMPUTATION to the\n * fingerprint-keyed window plus a per-call fold of the committed quarantine ledger (D-07/D-17).\n * The priming machinery below is unchanged and deliberately so — G-389-2's fused\n * mint-and-attach is a shipped fix, and only what the provider computes moved.\n *\n * The join is LIVE per call: both reads run on every query and nothing about the ANSWER is\n * cached, so a store update OR a ledger append between two renders changes the clause (D-08,\n * SC4). Only the knowledge ROOT — a composition-lifetime fact, not an answer — is resolved\n * once and remembered.\n *\n * A host may supply an ASYNC root resolver (the CLI layers configuration). A query that\n * arrives before the root resolves answers `undefined` — rendered as the explicit\n * no-history clause — which is why every `analysis.get` invocation primes the root through\n * the awaited `runs.get` hop before the sync join can run. A synchronously-throwing\n * resolver is swallowed to the SAME degrade (a read that needs no knowledge root never\n * fails on one), and minting + handler attachment are fused in `beginResolve` — the one\n * place a root-resolution promise is created — so no promise can be orphaned (G-389-2).\n */\nfunction createProjectionRecurrenceProvider(\n resolveKnowledgeRoot: () => Promise<string> | string,\n /** The host clock, read ONCE per query — the ladder's expiry comparison needs an instant. */\n now: () => string,\n): ProjectionRecurrence {\n let root: string | undefined\n let resolving: Promise<void> | undefined\n\n function beginResolve(): Promise<void> | undefined {\n if (resolving !== undefined) return resolving // reuse the in-flight resolution; never mint a second promise\n let answer: Promise<string> | string\n try {\n answer = resolveKnowledgeRoot()\n } catch {\n return undefined // sync throw: swallowed here, retried on the next query\n }\n if (typeof answer === 'string') {\n root = answer\n return undefined\n }\n // A failed resolution clears the marker so the next query retries rather than\n // pinning the provider to permanent no-history over a transient host error.\n resolving = answer.then(\n (value) => {\n root = value\n },\n () => {\n resolving = undefined\n },\n )\n return resolving\n }\n\n function rootNow(): string | undefined {\n if (root !== undefined) return root\n beginResolve()\n return root\n }\n\n return {\n prime(): Promise<void> {\n if (root !== undefined) return Promise.resolve()\n // Both stored handlers swallow, so prime never rejects — the awaited runs.get hop\n // cannot fail on a knowledge-root problem.\n return beginResolve() ?? Promise.resolve()\n },\n provider: {\n failureRecurrence(query) {\n const knowledgeRoot = rootNow()\n if (knowledgeRoot === undefined) return undefined\n const recurrence = readProjectedRecurrence(knowledgeRoot, query)\n // No recorded history is the honest no-history clause, ladder or not: 389's absence\n // discipline is a prohibition this plan inherits, and a reader who needs the owner or\n // the deadline of an entry with no history has `quarantine.list` and the entity card.\n if (recurrence === undefined) return undefined\n const ladder = readQuarantineLadder(knowledgeRoot, query, now(), recurrence)\n return ladder === undefined ? recurrence : { ...recurrence, ladder }\n },\n },\n }\n}\n\n/**\n * The `analysis.json` read side (389 D-10/D-11), path-derived from the artifact's own\n * `runId` through the SAME `runs/<slug>/` law as the handoff read and the persist binding\n * — `slugBranch` is the traversal guard (T-389-01), and no caller ever supplies a path.\n *\n * An absent file is `undefined` — \"the analysis never ran\" is a true state of a run, which\n * `analysis.get` serves as the floor. Everything else propagates: a schemaVersion newer\n * than this build reads is `guardRunAnalysisArtifact`'s typed hard failure (never swallowed\n * into a silent floor), and malformed bytes are corruption, not absence. A PRESENT file\n * recording ANOTHER run's id is refused by identity (`admitAnalysisArtifactForRun`,\n * G-389-3A) and served as the floor — a refusal, not an absence, distinguishable by the\n * two-leg differential: the same bytes with the id corrected are adopted.\n */\nfunction createAnalysisArtifactReader(agentQaRoot: string): AnalysisArtifactReaderPort {\n return {\n getArtifact(runId) {\n const path = join(agentQaRoot, RUNS_SUBDIR, slugBranch(runId), ANALYSIS_FILE)\n let bytes: string\n try {\n bytes = readFileSync(path, 'utf8')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined\n throw error\n }\n const admission = admitAnalysisArtifactForRun(\n guardRunAnalysisArtifact(JSON.parse(bytes)),\n runId,\n )\n return admission.kind === 'admitted' ? admission.artifact : undefined\n },\n }\n}\n\n/**\n * The post-run handlers' capabilities, or nothing at all (388 D-01 / D-06).\n *\n * The handoff read is DERIVED from `runId` through the same `runs/<slug>/handoff.json` layout\n * `FsHandoffStore` writes and `createRunsReader` enumerates — never a path carried on the job\n * payload, which would be a stored fact free to go stale between the enqueue and the claim,\n * and a caller-controlled string on the way to `join`. `slugBranch` is what makes a runId of\n * `../../etc` address nothing outside the runs directory (T-361-01 precedent).\n *\n * `loadCompletedRunHandoff` already hard-fails typed on a missing file or an unreadable\n * schema version, which is exactly the posture the handler wants: both are permanent\n * conditions of that run, not transient ones worth a retry.\n */\nexport function postRunCapabilities(\n input: ComposeLocalAgentInput,\n /**\n * The RESOLVED knowledge root. `openJobs` awaits the host's resolver once at queue open\n * — the same once-at-open idiom the model factory follows — so the SYNC capability\n * members below never race an async resolution mid-job.\n */\n knowledgeRoot: string,\n /** The RESOLVED budget, awaited from the input factory at the same open (see above). */\n analysisTokenBudget?: PostRunJobCapabilities['analysisTokenBudget'],\n /**\n * The job store this queue was opened over (422 D-14).\n *\n * Handed in rather than constructed here, because it is the SAME store the queue drains: the\n * charge a proposal job reads back has to be the one its own `publishCheckpoint` wrote, and a\n * second reader over a second handle would be a second opinion about what this job spent.\n * OPTIONAL so every existing caller of this builder keeps compiling; absent, the proposal\n * stage's Gate-1 leg is the typed no-op it already is on a host that binds no replay gate.\n */\n jobStore?: Pick<JobStorePort, 'readCheckpoint'>,\n /** The RESOLVED per-job Gate-1 bound, awaited from the input factory at the same open (422-09). */\n proposeGate1MaxPerJob?: number,\n): PostRunJobCapabilities | undefined {\n const postRun = input.postRun\n if (postRun === undefined) return undefined\n return {\n // 422 D-14: ONE narrow read — this job's own durable Gate-1 charge, addressed by its own id,\n // through the authoritative `readCheckpoint` the store already publishes. The handler is\n // handed no store, no checkpoint reader and no path; the shape check is `agent`'s, beside\n // the shape it checks, so two hosts cannot disagree about what a readable charge is.\n ...(jobStore === undefined\n ? {}\n : {\n readProposeGate1Allowance: async (jobId: string) =>\n parseProposeGate1Allowance(\n await jobStore.readCheckpoint(asJobId(jobId), PROPOSE_GATE1_ALLOWANCE_CHECKPOINT),\n ),\n }),\n loadCompletedRunHandoff: (runId: string) =>\n loadCompletedRunHandoff(\n join(input.agentQaRoot, RUNS_SUBDIR, slugBranch(runId), HANDOFF_FILE),\n ),\n curateRun: postRun.curateRun,\n // 422 D-13: spread on the conditional idiom this file uses throughout, so an unbound port\n // is an ABSENT member rather than a present `undefined` — the handler decides on presence,\n // in one place, and a host that declined to bind cannot be mistaken for one that bound a\n // hole.\n ...(postRun.stageAdversarialProposal === undefined\n ? {}\n : { stageAdversarialProposal: postRun.stageAdversarialProposal }),\n // 422-09 (D-14): the Gate-1 leg's four ports and its bound, forwarded on the same\n // presence-spread idiom one line up. The handler's own `screenGate1` requires ALL FOUR before\n // it screens anything, so a host that binds three of them is a host that screens nothing —\n // which is why they are forwarded one by one rather than as a bundle a caller could\n // half-populate without noticing.\n ...(postRun.runReplayGate === undefined ? {} : { runReplayGate: postRun.runReplayGate }),\n ...(postRun.listBundles === undefined ? {} : { listBundles: postRun.listBundles }),\n ...(postRun.gateReceiptsFor === undefined ? {} : { gateReceiptsFor: postRun.gateReceiptsFor }),\n ...(postRun.readProposeCorpusPosture === undefined\n ? {}\n : { readProposeCorpusPosture: postRun.readProposeCorpusPosture }),\n ...(postRun.readMisdirectionRootPosture === undefined\n ? {}\n : { readMisdirectionRootPosture: postRun.readMisdirectionRootPosture }),\n ...(proposeGate1MaxPerJob === undefined ? {} : { proposeGate1MaxPerJob }),\n // 389 D-09: the artifact's path is DERIVED from the artifact's own runId through the\n // same `runs/<slug>/` law as the handoff read above — `slugBranch` is the traversal\n // guard (T-389-01), and a job payload never carries a path.\n persistAnalysis: (artifact) =>\n writeAnalysisArtifact(\n join(input.agentQaRoot, RUNS_SUBDIR, slugBranch(artifact.runId), ANALYSIS_FILE),\n artifact,\n ),\n // Plan 02's read side over the derived projection, keyed the projection's way —\n // (product, filePath, testName), the stable identity, NEVER a per-run explicit id.\n // The query arrives already keyed by the author callback; this binding only reads.\n readTestHistory: (query) => readProjectedTestHistory(knowledgeRoot, query),\n // D-02's sha-addressed screenshot bytes: the SAME CASS-02 store the runner writes.\n // `FsEvidenceArtifactStore.getBlob` validates the lowercase 64-hex shape BEFORE any\n // path use (T-389-14) and answers ENOENT as honest absence; the runId becomes a path\n // segment only through `slugBranch` inside the store's own constructor.\n //\n // 405-05: THROUGH THE SHARED RULE, not a lambda of its own. `runs.artifact` binds a port over\n // the same `lookupEvidenceBlob` below, and two lambdas over one store would be two answers to\n // where a run's blobs live — agreeing on the day the second is written and diverging the first\n // time either side changes a root. This job wants only the found bytes, so the three-arm\n // lookup collapses here; the SPLIT is what the op needs and what this caller does not.\n readEvidenceBlob: (runId, sha) =>\n readEvidenceBlobBytes({ agentQaRoot: input.agentQaRoot }, runId, sha),\n // Host-resolved and passed through untouched (386 D-15): the budget derives from the\n // same profile resolution as the job model, and this composition adds no knob of its own.\n ...(analysisTokenBudget === undefined ? {} : { analysisTokenBudget }),\n }\n}\n\n/** Compose the local agent host. */\n/**\n * The two callers chat mints, one per stage (392, RESEARCH Pitfall 1 / 391 D-06).\n *\n * IDENTICAL BUT FOR `origin`. `FunctionCaller.origin` answers \"did a person decide this\", and inside\n * ONE turn both answers occur: a person typing a canonical alias decided that call, and a model\n * planning one did not. The receipts a turn logs record that origin per clause.\n *\n * `surface` is `'chat'` on both and is ATTRIBUTION ONLY. Nothing in the function layer may branch\n * on it (`invoke.ts:28-29`).\n *\n * 2026-10-01 (432-20/432-21, D-12): no scope set and no safe-mode flag. `CHAT_STAGE_SCOPES`, the\n * whole closed scope union both stages held, is deleted: every caller can call every operation, and\n * the human-origin restriction the origin split once protected is deleted with `requiresHumanOrigin`.\n */\nexport const CHAT_RESOLVER_CALLER: FunctionCaller = Object.freeze({\n surface: 'chat',\n origin: 'human',\n})\n\nexport const CHAT_PLANNER_CALLER: FunctionCaller = Object.freeze({\n surface: 'chat',\n origin: 'agent',\n})\n\n/**\n * A fingerprint of what the turn engine could reach when a session opened.\n *\n * Derived from the REGISTRY rather than from a hand-kept list, which is D-07's projection law\n * applied to the log: the toolset a turn is measured against is whatever the catalogue declares,\n * so a build that gains an op gains it here without anybody remembering to say so. A registry not\n * yet composed answers `'unbound'` — the same honest word the model field uses.\n */\nfunction chatToolsetIds(registry: FunctionRegistry | undefined): readonly string[] {\n if (registry === undefined) return []\n return registry\n .list(CHAT_RESOLVER_CALLER)\n .map((declaration) => declaration.id)\n .sort()\n}\n\nfunction chatToolsetHash(registry: FunctionRegistry | undefined): string {\n if (registry === undefined) return 'unbound'\n // Sorted before hashing, which is what makes the hash an identity of the SET rather than of the\n // walk: a registry that enumerated in a different order must not read as a toolset change.\n // The workspace's own digest helper, not a second hashing call site (388 C13 in miniature).\n return sha256hex16(chatToolsetIds(registry).join('\\n'))\n}\n\n// 2026-10-15 (441-68, GAP2-D3): chat projections mask the text a person, an op or config wrote and\n// keep the closed vocabulary the code writes and reads back (`guardChatSessionEvent` checks keys,\n// `kind`, `turnId` and `at` exactly). Keys are never renamed outside an op's payload. A member no\n// table names is masked as a tree, which fails closed.\ntype ChatMemberRule = 'as-written' | 'text' | 'tree' | ((value: unknown, mask: MaskFn) => unknown)\ntype ChatMemberRules = Readonly<Record<string, ChatMemberRule>>\n\nfunction projectChatMembers<T extends object>(value: T, rules: ChatMemberRules, mask: MaskFn): T {\n return Object.fromEntries(Object.entries(value).map(([key, member]) => {\n const rule = Object.hasOwn(rules, key) ? rules[key]! : 'tree'\n if (rule === 'as-written') return [key, member]\n if (typeof rule === 'function') return [key, rule(member, mask)]\n if (rule === 'text' && typeof member === 'string') return [key, mask(member)]\n return [key, maskPayloadTree(member, mask)]\n })) as T\n}\n\nconst eachChatRecord = (rules: ChatMemberRules): ChatMemberRule => (value, mask) => {\n const project = (entry: unknown) =>\n isRecord(entry) ? projectChatMembers(entry, rules, mask) : maskPayloadTree(entry, mask)\n return Array.isArray(value) ? value.map(project) : project(value)\n}\n\nconst CHAT_EVENT_BASE: ChatMemberRules = {\n kind: 'as-written', turnId: 'as-written', at: 'as-written',\n}\nconst CHAT_CLAUSE_RECEIPT_RULES: ChatMemberRules = {\n clause: 'text', functionId: 'as-written', origin: 'as-written', status: 'as-written', outcome: 'text',\n}\nconst CHAT_EVENT_RULES: Readonly<Record<ChatSessionEvent['kind'], ChatMemberRules>> = {\n user_message: { ...CHAT_EVENT_BASE, text: 'text' },\n stage_outcome: { ...CHAT_EVENT_BASE, stage: 'as-written', outcome: 'as-written' },\n clause_receipt: { ...CHAT_EVENT_BASE, ...CHAT_CLAUSE_RECEIPT_RULES },\n clause_result: { ...CHAT_EVENT_BASE, functionId: 'as-written', payload: 'tree' },\n approval_decision: {\n ...CHAT_EVENT_BASE, actionClass: 'as-written', decision: 'as-written', source: 'as-written',\n },\n mark_unhandled: { ...CHAT_EVENT_BASE, clause: 'text', reason: 'text' },\n model_change: { ...CHAT_EVENT_BASE, from: 'text', to: 'text', source: 'as-written' },\n active_tools_change: {\n ...CHAT_EVENT_BASE, addedIds: 'as-written', removedIds: 'as-written', toolsetHash: 'as-written',\n },\n compaction: {\n ...CHAT_EVENT_BASE, beforeTokens: 'as-written', afterTokens: 'as-written', outcome: 'as-written',\n },\n aborted: { ...CHAT_EVENT_BASE, source: 'as-written' },\n turn_complete: { ...CHAT_EVENT_BASE, status: 'as-written' },\n}\n\nconst CHAT_INVOKE_ANSWER_RULES: ChatMemberRules = {\n payload: 'tree',\n verdict: eachChatRecord({ status: 'as-written', outcome: 'text' }),\n foldLines: 'tree',\n}\n\nconst CHAT_TURN_RESULT_RULES: ChatMemberRules = {\n sessionId: 'as-written',\n turnId: 'as-written',\n status: 'as-written',\n answer: 'text',\n receipts: eachChatRecord(CHAT_CLAUSE_RECEIPT_RULES),\n results: eachChatRecord({ functionId: 'as-written', payload: 'tree' }),\n unhandled: eachChatRecord({ clause: 'text', reason: 'text' }),\n refusedLineCount: 'as-written',\n}\n\nfunction projectChatSessionEvent(event: ChatSessionEvent, mask: MaskFn): ChatSessionEvent {\n const rules = Object.hasOwn(CHAT_EVENT_RULES, event.kind)\n ? CHAT_EVENT_RULES[event.kind]\n : CHAT_EVENT_BASE\n return projectChatMembers(event, rules, mask)\n}\n\nexport function composeLocalAgent(input: ComposeLocalAgentInput): LocalAgentHost {\n const clock = input.clock ?? SYSTEM_CLOCK\n\n const entityResolutionInput = {\n agentQaRoot: input.agentQaRoot,\n resolveKnowledgeRoot: input.knowledgeRoot,\n }\n\n // 389 plan 06: the recurrence seam and its root priming. `analysis.get` awaits\n // `deps.runs.get` before any recurrence join runs (analysis-get.ts invoke order), so\n // priming the root inside that awaited hop is what makes the SYNC provider correct on a\n // host whose knowledge-root resolver is async (the CLI): by the time the join runs, the\n // root string is cached. A resolution failure is swallowed HERE only — the provider then\n // answers the honest no-history clause, and the knowledge verbs report their own errors\n // through their own awaited resolutions.\n const recurrence = createProjectionRecurrenceProvider(input.knowledgeRoot, () => clock.now())\n const runsReader = createRunsReader(input.agentQaRoot)\n\n // 392 D-02 / D-14 / D-24: the chat turn engine, assembled at THE composition root.\n //\n // Assembled HERE and nowhere else for 385 D-15's reason, which bites harder for chat than for\n // anything before it: two hosts assembling a turn engine differently would be two answers to\n // \"what can a conversation do\", and one of the two would be the one a user is talking to.\n //\n // The dispatch binding closes over `composedRegistry`, which this very call is about to\n // produce. That is deliberate rather than awkward: the engine invokes ops through\n // `invokeFunction` on the SAME registry `agent.ask` is registered in, so a clause a turn runs\n // crosses the identical eight-step gate a typed CLI verb does (D-24 / 384 FUNC-03). Reading the\n // reference at call time rather than at construction is what lets that cycle exist without a\n // second registry, and it is safe because a turn cannot run before the registry it is bound\n // into has been built.\n let composedRegistry: FunctionRegistry | undefined\n // `unbound` when this host binds no model — the honest word rather than a placeholder, and the\n // same vocabulary the registry uses for a declared capability with no implementation behind it.\n // A headless host's session header says so, and the day one is bound the drift from here is a\n // `model_change` event rather than a header rewrite (D-04; the log is append-only).\n const composedChatModelName = input.chatModel === undefined ? 'unbound' : input.chatModel.modelId\n\n // 392 plan 08/13 (RESEARCH Open Q2, CR-02 / W-03): the live turn state and the pin set, KEYED BY\n // SESSION.\n //\n // Both used to be one object per composition, and the verifier's finding is what that costs on a\n // host serving more than one conversation: `activeTurnId` / `conversation` / `activeModel` are\n // facts about ONE session, so a single container published whichever turn wrote last — and the\n // planner, which reads the conversation at plan time across an `await`, could therefore put one\n // person's history into another person's outbound provider request. The pin holder is the same\n // shape with a sharper edge: a `/pin` typed in one conversation denied that action class for\n // every later caller until the process restarted, while `pin-overlay.ts`'s own header said the\n // pin dies with the session. It now does.\n //\n // CREATED ON FIRST RESOLUTION and held for the composition's life. That is bounded by the number\n // of sessions this host serves and reaped with the composition, which is the same lifetime the\n // single container had; what changed is that it is one per conversation instead of one per host.\n interface ChatSessionScope {\n readonly state: ChatStateContainer\n }\n const chatScopes = new Map<string, ChatSessionScope>()\n const chatScopeFor = (sessionId: string): ChatSessionScope => {\n const existing = chatScopes.get(sessionId)\n if (existing !== undefined) return existing\n if (composedRegistry === undefined) {\n throw new TypeError('a chat session opened before its registry finished composing')\n }\n const scope: ChatSessionScope = {\n // An UNBORN session has run no `/model`, so it opens under the model this host composed —\n // which is also what its header will say. A container seeded from another session's override\n // would make one conversation's verb the next conversation's opening posture.\n state: createChatState({ activeModel: composedChatModelName }),\n // 432-13 (D-14): no pin holder. `/pin` left chat resolution with the op gate it tightened.\n }\n chatScopes.set(sessionId, scope)\n return scope\n }\n\n // THE MODEL IN FORCE IS READ, NEVER CAPTURED, and this one line is the whole of 392-07's warning.\n // `/model` writes the override into the session's own state; every consumer below — the planner's\n // prompt and the per-turn config re-read — reads it through here. A thunk that kept answering the\n // COMPOSED model would emit a `model_change` straight back on the next turn, silently undoing the\n // verb that had just been recorded.\n const chatModelNameFor = (sessionId: string): string =>\n chatScopeFor(sessionId).state.read().activeModel\n\n // The live model OBJECT for a model name. Keyed by name rather than by session, because\n // `chatModelFor` is a resolution of a name and two sessions naming the same model mean the same\n // model — the same reason the planner stage cache below is keyed that way. Which name a session\n // is under is the per-session fact, and it lives in that session's state.\n const chatModelsByName = new Map<string, ChatLanguageModel>()\n if (input.chatModel !== undefined) chatModelsByName.set(composedChatModelName, input.chatModel)\n\n const chatSessionLog = createJsonlSessionLog({\n root: input.agentQaRoot,\n now: () => clock.now(),\n // THE COMPOSED MODEL, not a session's override, and the difference is a leak this keying closes.\n // This thunk is read when a header is WRITTEN, which happens exactly once per session and only\n // for a session that has not existed until now — so no `/model` can have run in it. Answering\n // with a live override would stamp one conversation's switch onto the opening header of every\n // conversation opened after it. 441 GAP3-D4: written and listed through the declared mask.\n model: () => input.mask(composedChatModelName),\n toolsetHash: () => chatToolsetHash(composedRegistry),\n })\n\n // 392-12 / CR-01: WHICH SESSIONS ARE OPEN RIGHT NOW, and which turns each of them has recorded.\n //\n // The engine owns a session for the length of a turn, but a writer here is OUTSIDE a turn's\n // call stack and still belongs to one: `chat.abortActiveTurn`, reached from a signal handler\n // (the confirm port's `onDecision` was the other until 432-16 deleted it). Both used to\n // append through the adapter, which — while the adapter had one descriptor — meant \"whichever\n // session opened last\". They now write through the handle of the session whose file already\n // carries the turn in question, and the ATTRIBUTION IS THE LOG'S OWN: every event carries a\n // `turnId`, so the wrapper records the ids it has written per handle and a later writer names a\n // turn rather than guessing a session. A turn nobody here is holding gets no row, which is the\n // fail-safe direction — the alternative is a row in the wrong conversation, and that is CR-01.\n const liveChatSessions = new Map<string, { handle: ChatSessionHandle; turnIds: Set<string> }>()\n\n const trackedChatSessionLog: SessionLogPort = {\n async open(sessionId?: string): Promise<ChatSessionHandle> {\n const opened = await chatSessionLog.open(sessionId)\n const id = opened.header.sessionId\n const turnIds = new Set<string>()\n const tracked: ChatSessionHandle = {\n header: opened.header,\n events: opened.events,\n refusedLines: opened.refusedLines,\n append: async (event) => {\n // 2026-10-14 (441-06, D-06): every event carries the declared mask (441-68: per member).\n const projected = projectChatSessionEvent(event, input.mask)\n turnIds.add(projected.turnId)\n await opened.append(projected)\n // 400-01 (D-03): the host's carbon copy, taken AFTER the write and never instead of it.\n // Swallowed by name: a surface's push channel is downstream of the durable log, and a\n // failing SSE write must not fail the turn whose event it was trying to announce.\n try {\n input.observeSessionEvent?.(id, projected)\n } catch { /* a push channel's failure is not the turn's */ }\n },\n turnBoundary: () => opened.turnBoundary(),\n close: async () => {\n // Unregistered BEFORE the descriptor goes, so nothing can pick this handle up in the\n // window between the two and write through a closed one.\n liveChatSessions.delete(id)\n await opened.close()\n },\n }\n liveChatSessions.set(id, { handle: tracked, turnIds })\n return tracked\n },\n }\n\n /** The open session whose file already carries this turn, or none if nobody here holds it. */\n const chatSessionHoldingTurn = (turnId: string): ChatSessionHandle | undefined => {\n for (const entry of liveChatSessions.values()) {\n if (entry.turnIds.has(turnId)) return entry.handle\n }\n return undefined\n }\n\n // 392 plan 04/07: stage 2, assembled LAZILY over the registry this call is about to produce.\n //\n // The laziness is the same cycle the dispatch binding below resolves, for the same reason: the\n // toolset is a walk of the registry `agent.ask` is registered in, and D-07's projection law says\n // the planner's vocabulary IS that catalogue — so an eagerly-built toolset would either need a\n // second registry or would have to be a curated list, which is exactly what 397's conformance\n // and 396's MCP parity are built against not being. Built once on first use and reused after,\n // because a walk per turn would re-project ~30 JSON schemas for no new information.\n //\n // KEYED BY THE MODEL IN FORCE (plan 08). `createPlannerStage` binds its model at construction, so\n // a single cached stage would keep planning through the model a `/model` verb had just replaced —\n // the override would move the prompt's `activeModel` line and change nothing about who answered.\n // One stage per model, built on first use of each.\n const plannerStages = new Map<string, PlannerStagePort>()\n const chatPlanner: PlannerStagePort | undefined =\n input.chatModel === undefined\n ? undefined\n : {\n plan: (request) => {\n if (composedRegistry === undefined) {\n throw new TypeError('a chat turn ran before its registry finished composing')\n }\n const activeName = chatModelNameFor(request.sessionId)\n let stage = plannerStages.get(activeName)\n if (stage === undefined) {\n stage = createPlannerStage({\n model: (chatModelsByName.get(activeName) ?? input.chatModel) as ChatLanguageModel,\n tools: projectPlannerTools(composedRegistry, CHAT_PLANNER_CALLER),\n // Read PER REQUEST — not per turn and not per stage (392 plan 13, CR-02). A stage\n // is shared by every session planning under the same model name, so a context\n // thunk taking no argument had exactly one conversation to answer with, and on\n // two interleaved turns it answered with whichever one published last. Taking the\n // requesting session's id makes \"the conversation this request replays\" a fact\n // about the call. The read is still LIVE, so a `/model` override still moves what\n // the prompt states without the stage being rebuilt, and the conversation block\n // still carries what compaction left rather than a second replay of the log.\n context: (contextRequest) => {\n const scope = chatScopeFor(contextRequest.sessionId).state.read()\n return { activeModel: scope.activeModel, conversation: scope.conversation }\n },\n })\n plannerStages.set(activeName, stage)\n }\n return stage.plan(request)\n },\n }\n\n // CHAT-04's degrade pass, bound when the host supplied the accounting instance (plan 06).\n // Its one event goes through the HANDLE the engine hands it per turn (392-12) — the hook holds\n // no log of its own and no longer holds a binding to one, so there is exactly one writer per\n // session and it is that session's own.\n const chatCompaction: CompactionHook | undefined =\n input.chatAccounting === undefined\n ? undefined\n : createChatCompactionHook({\n accounting: input.chatAccounting,\n now: () => clock.now(),\n // 392-06's flagged consumer, wired: what compaction leaves IS the conversation the\n // prompt renders, and it lands in the live state on EVERY turn rather than only on a\n // triggered pass — a sink that fired only when a pass ran would leave the prompt holding\n // a stale conversation on every quiet turn. Into the SESSION'S OWN container (plan 13):\n // the id is the compacted turn's, so a pruned history cannot land in another\n // conversation however many turns are in flight.\n onConversation: (messages, sessionId) => {\n chatScopeFor(sessionId).state.setConversation(messages)\n },\n })\n\n const chatTurn = createTurnEngine({\n table: CHAT_RESOLVER_TABLE,\n // 392 plan 02, D-09: the real conjunction grammar, quote-aware. The tracer's\n // whole-utterance placeholder is gone; this is the seam filled, not widened.\n split: splitClauses,\n reconcile: input.chatReconcile ?? deterministicOverrideStrategy,\n sessionLog: trackedChatSessionLog,\n // RESEARCH Pitfall 1: per-STAGE minting, because origin is a per-call fact. A deterministic\n // table hit is a person typing and mints `human`; a planner-planned call mints `agent`, and the\n // turn's receipts record which.\n // 2026-10-01 (432-21, D-12): NOT STAMPED WITH THE SESSION ANY MORE. The session id rode the\n // caller for the gate's deny overlay (plan 13, W-03) and the overlay is deleted (432-13/18/19);\n // nothing reads `FunctionCaller.sessionId`. The session still reaches the ops that record it\n // through the turn's own session facts, not through the caller.\n mint: {\n forStage: (stage) => (stage === 'resolver' ? CHAT_RESOLVER_CALLER : CHAT_PLANNER_CALLER),\n },\n // 399.1 D-01/D-03/D-05: the classified envelope, built HERE because this closure is the one\n // place in the system holding both the registry and the invoke call. The chat subtree cannot\n // reach a spec by construction (384 FUNC-03), so the verdict and the render fold have to arrive\n // as data on this return — which is what `ChatInvokeAnswer` is. `foldFunctionResult` owns the\n // fail-closed rule so both composition roots get the same one rather than a copy each.\n //\n // invokeFunction validates canonical output; it does not promise masking. Classify those\n // original bytes before projecting the answer into results[] and the durable clause_result.\n invoke: async (functionId, invokeInput, caller) => {\n if (composedRegistry === undefined) {\n throw new TypeError('a chat turn ran before its registry finished composing')\n }\n const payload = await invokeFunction(composedRegistry, functionId, invokeInput, caller)\n const fold = foldFunctionResult(composedRegistry, functionId, payload)\n return projectChatMembers({ payload, ...fold }, CHAT_INVOKE_ANSWER_RULES, input.mask)\n },\n ...(chatPlanner === undefined ? {} : { planner: chatPlanner }),\n ...(chatCompaction === undefined ? {} : { compaction: chatCompaction }),\n // 392 plan 08: the directive handlers, which is what turns the engine's\n // `directive recognised but no handler` refusal from the shipped behaviour into an\n // unreachable arm on this host. `/help` and `/quit` are REPL chrome and answer in prose;\n // `/model` changes what the session is and returns the EFFECT it had. (432-13: `/pin` is gone.)\n //\n // RESOLVED PER SESSION (plan 13, CR-02 / W-03). Each one acts on a conversation rather than the\n // project, so the handler set is built over the scope of the session running the turn:\n // `/model` moves that conversation's model and `/quit` asks that loop to end.\n directives: (sessionId) => ({\n // THE BATCH PRE-FLIGHT (392-14, E3/E3b). The engine asks this of EVERY directive of a turn\n // before it applies the first one, so a refused later directive leaves an earlier one\n // unapplied.\n //\n // IT APPLIES NOTHING. `/model` RESOLVES the model and caches it under its name — a cache is\n // not the session's state, and the session's own `activeModel` is left exactly where it was.\n // The resolution is also the only part of `/model` that can fail, so caching it here is what\n // makes the later apply unable to throw after an earlier directive has already been carried\n // out.\n validate: async (directive, argument) => {\n if (directive === 'model' && argument !== undefined && input.chatModelFor !== undefined) {\n chatModelsByName.set(argument, await input.chatModelFor(argument))\n }\n },\n model: async (name) => {\n const scope = chatScopeFor(sessionId)\n const from = scope.state.read().activeModel\n // Resolved ALREADY, when this host publishes `validate` — the pre-flight cached it under\n // this name and the apply reuses it rather than resolving a second time. Two resolutions\n // of one name on one turn would be two chances to disagree, and the second of them would\n // be running after the batch had been declared safe.\n if (input.chatModelFor !== undefined && !chatModelsByName.has(name)) {\n // Resolved by the HOST (CHAT-06): the chat subtree may not construct a model, so a\n // session-scoped switch is a capability this composition was handed. A resolution\n // failure throws, and the engine turns it into the same named refusal every other\n // unroutable clause gets — a `/model` that silently kept the old model would be the\n // worst answer available, since every later turn would report the new name.\n //\n // Recorded under the NAME, which is the key the planner cache and every other session\n // naming that model read it back by. The resolution is a fact about the name; which\n // session is under it is the fact that stays in the session's own state.\n chatModelsByName.set(name, await input.chatModelFor(name))\n }\n scope.state.setActiveModel(name)\n return { from, to: name, line: `model: ${from} → ${name}` }\n },\n help: () => CHAT_HELP_TEXT,\n quit: () => {\n chatScopeFor(sessionId).state.requestClose()\n return 'closing this session'\n },\n }),\n state: (sessionId) => chatScopeFor(sessionId).state,\n // D-04: the configuration RE-READ, per turn and PER SESSION. A thunk rather than a captured\n // value, because the drift worth detecting is precisely the one that happens underneath a\n // running session — a model resolved differently by the host, or a build whose registry\n // reaches further than the one this session opened against. The engine folds the log for what\n // was last recorded and emits `model_change` / `active_tools_change` on the difference.\n //\n // THE MODEL IT REPORTS IS THE ASKING SESSION'S (plan 13). A composition-wide read would answer\n // one conversation's `/model` override for every conversation, and the per-turn diff would\n // then write a `model_change` into sessions nobody had switched.\n //\n // 441 GAP3-D4: masked, because the log it is compared with is masked on append.\n config: (sessionId): ChatConfigState => {\n const ids = chatToolsetIds(composedRegistry)\n return {\n model: input.mask(chatModelNameFor(sessionId)),\n toolset: { hash: chatToolsetHash(composedRegistry), ids },\n }\n },\n // 395-08 D-14/D-15 · CFGM-05: the target vocabulary the PRE-DISPATCH write_test route reads.\n // Bound off the SAME host verb `authoringRead.configuredTargetNames` uses, so the seam that\n // decides whether to offer a scaffold and the loop that later checks what a model emitted are\n // reading one answer rather than two. A host that cannot name its targets binds nothing and the\n // route never runs, which leaves the shipped dispatch and the loop's own backstop exactly as\n // they were.\n // BOUND ONLY WHERE THE LOOP IS. A host that cannot author has nothing for this route to route,\n // and binding it anyway would answer an empty vocabulary — which the route reads as the\n // from-zero case and refuses, reporting the wrong cause for a host whose real problem is that\n // `authoring.draft.write` is unbound. Absent leaves the shipped dispatch untouched.\n ...(input.draftAuthoring !== undefined && input.runExecution !== undefined\n ? { configuredTargets: () => (input.draftAuthoring as DraftAuthoringPort).configuredTargetNames() }\n : {}),\n // 395-13 D-14: where the scaffold proposal is rendered before the in-turn apply is invoked.\n // Conditionally spread on the exact idiom above, so a host that binds no surface leaves the\n // field ABSENT and the engine's own \"renders nothing\" posture is what answers — in one place.\n ...(input.chatPresent === undefined ? {} : { present: input.chatPresent }),\n now: () => clock.now(),\n mintTurnId: () => `turn-${randomUUID()}`,\n })\n\n // 2026-10-01 (432-18, D-14/D-15/D-22): no grants port, standing-approval read or dispatch-scoped\n // grant overlay is composed. The grant ops, the ledger and the overlay are deleted, and an old\n // `grants.jsonl` under the knowledge root is never opened.\n\n // 394 D-01: the authoring loop's host half, narrowed ONCE so the loop's closures capture a value\n // rather than an optional property — and so \"can this host author a draft\" is decided in one\n // place. `runExecution` is part of the condition even though nothing here calls it: stage 4\n // dispatches `authoring.draft.verify`, which is itself unbound without it, so a host bound to\n // author but not to verify would produce a draft and then refuse to say whether it is any good.\n const authoringLoopHost = input.draftAuthoring !== undefined && input.runExecution !== undefined\n ? input.draftAuthoring\n : undefined\n\n // 394-07 D-12/D-14 · WTST-05: the honesty funnel's reads, assembled ONCE and handed to both\n // consumers — the `authoring.funnel.get` op below, and the gate-2 flip consultation the draft\n // evaluator makes (394-17). Two bindings would be two answers to what this project knows about\n // one suite, which is the 385 D-15 rule this whole file is under.\n const authoringFunnel: AuthoringFunnelPortLike = {\n receipts: createDraftReceiptsStore({ resolveAgentQaRoot: () => input.agentQaRoot }),\n quarantine: {\n list: async () => (await createQuarantineOperations({\n resolveKnowledgeRoot: input.knowledgeRoot,\n now: () => clock.now(),\n mintIdentityPath: input.mintQuarantineIdentityPath,\n ...(input.resolveWriterAuthority === undefined\n ? {}\n : { resolveWriterAuthority: input.resolveWriterAuthority }),\n }).list()),\n },\n // D-14's history half, over the run-outcome projection's own read side (394-17, step b).\n //\n // ONE CONNECTION PER VERB, opened read-only and closed in `finally`, on the shape\n // `readProjectedTestHistory` above already takes. An absent database, a store predating the\n // projection tables and an identity nothing has counted all answer EMPTY — which\n // `assessSuiteStability` turns into the honest `no-history` posture rather than into a clean\n // bill of health. Any other read failure propagates: a corrupt store is not \"no history\".\n //\n // THE OUTCOME WORDS. The durable window keeps one boolean per build (`last_outcomes_json`),\n // which is what the fold reduced each member's outcome to, so this spells it back with the two\n // words it was reduced FROM. Nothing downstream compares those strings against a member list —\n // `assessSuiteStability` counts DISTINCT values — so a flip in the window is a flip here, and\n // no vocabulary is invented beyond what the projection actually kept.\n outcomes: {\n testsIn: async (product: string, filePath: string) => {\n const knowledgeRoot = await input.knowledgeRoot()\n const path = indexDbPath(knowledgeRoot)\n if (!existsSync(path)) return []\n const db = new DatabaseSync(path, { readOnly: true })\n try {\n return listTestsInFile(db, { product, filePath })\n .map((testName) => ({ filePath, testName }))\n } catch (error) {\n if (error instanceof Error && error.message.includes('no such table')) return []\n throw error\n } finally {\n db.close()\n }\n },\n outcomesFor: async (product: string, filePath: string, testName: string) => {\n const knowledgeRoot = await input.knowledgeRoot()\n const history = readProjectedTestHistory(knowledgeRoot, { product, filePath, testName })\n if (history === undefined) return []\n return history.lastOutcomes.map((entry) => (entry.passed ? 'passed' : 'failed'))\n },\n },\n }\n\n const registry = createFunctionRegistry({\n deps: {\n secretMask: input.mask,\n runs: {\n ...runsReader,\n get: async (runId) => {\n await recurrence.prime()\n return runsReader.get(runId)\n },\n },\n // 387 D-01: this host's list verbs are live sighting sites. Every entity a listing,\n // an inspect, a diff or a show surfaces gets its permanent address the first time it\n // is surfaced — which is what \"pre-existing entities get IDs the day they are first\n // referenced\" means in practice, and it costs the creation paths nothing.\n knowledge: createKnowledgeReader(\n input.knowledgeRoot,\n createMemorySightingHook(entityResolutionInput),\n input.resolvePromotionPosture,\n input.resolveTrustPriors,\n ),\n config: input.config,\n entities: createEntityDirectory(entityResolutionInput),\n // 387-08 KREV-01: the WRITE half, and it is present in every local composition because a\n // local host owns the knowledge root it serves from. It stays an OPTIONAL dep so a host\n // that is genuinely read-only — a listing, a remote surface — reports the four mutating\n // verbs as `unbound` BY NAME rather than as a hole in the catalogue.\n knowledgeReview: createKnowledgeReview({\n ...(input.resolveTrustPriors === undefined ? {} : { resolveTrustPriors: input.resolveTrustPriors }),\n ...(input.resolvePromotionPosture === undefined ? {} : { resolvePromotionPosture: input.resolvePromotionPosture }),\n agentQaRoot: input.agentQaRoot,\n resolveKnowledgeRoot: input.knowledgeRoot,\n ...(input.knowledgeChangeDelegate === undefined\n ? {}\n : { knowledgeChangeDelegate: input.knowledgeChangeDelegate }),\n ...(input.resolveWriterAuthority === undefined\n ? {}\n : { resolveWriterAuthority: input.resolveWriterAuthority }),\n // 432-12: the host's own context, so a direct change is recorded under the context it was\n // actually made in. (432-39: the registry no longer receives it; this is its one reader.)\n ...(input.resolveExecutionContext === undefined\n ? {}\n : { resolveExecutionContext: input.resolveExecutionContext }),\n }),\n // 388 D-14: chip truth, on EVERY local host and not gated on `postRun`. The two are\n // different questions and conflating them would be the bug: `postRun` says whether this\n // host can DO the chain's work, while this says whether it can SEE what the chain did —\n // and a host that never drains anything (a status query, a listing, the CLI after a\n // handed-off tail) is exactly the caller that most needs to read durable state.\n //\n // Given the SAME id source the queue below is built with, so the rows projected are the\n // rows enqueued. It opens nothing here: the reader constructs no handle until it is asked\n // a question, and never one that could create the database (Pitfall 4).\n postProcessing: createPostProcessingReader({\n agentQaRoot: input.agentQaRoot,\n idSource: input.idSource ?? DIGEST_JOB_ID_SOURCE,\n }),\n // 405 D-03: the run-detail projection read, conditionally spread on the house rule — an\n // absent port must be an ABSENT field and not a present `undefined` one, because the\n // registry reads exactly this record to decide what the capability LISTS as. Unlike\n // `postProcessing` above it is NOT present on every local host: chip truth is readable from\n // `agentQaRoot` alone, but a run's projected step tree lives in a dashboard database that\n // only the dashboard process holds.\n // 423 D-04: runs.evidence shares this reader with runs.detail and the blob reader\n // below. The registry requires both for evidence without narrowing detail availability.\n ...(input.runDetail === undefined ? {} : { runDetail: input.runDetail }),\n // 405-05 D-12/D-13: the run-scoped evidence-blob read, on EVERY local host and NOT\n // conditionally spread — unlike `runDetail` one line up, which needs a dashboard database\n // this host may not hold, every local composition has a runtime root and therefore has the\n // run directories these blobs live in. It is the SAME reader the analysis job's\n // `readEvidenceBlob` is built over, so \"resolve this ref\" and \"diet this evidence\" cannot\n // disagree about where a blob is.\n evidenceBlobs: createEvidenceBlobReader({ agentQaRoot: input.agentQaRoot }),\n // Present iff this host can execute a run. The registry reads the SAME record to\n // decide what `runs.start` lists as, so the declaration and the dispatch cannot\n // disagree about whether this composition can run it (D-16).\n ...(input.runExecution === undefined ? {} : {\n runInvocation: createLocalRunInvocation({\n agentQaRoot: input.agentQaRoot,\n execution: input.runExecution,\n }),\n }),\n // 389 D-10/D-11: the artifact read `analysis.get` binds through, and the D-08\n // recurrence join the one renderer consults. Both are bindable from `agentQaRoot`\n // and the knowledge root alone, so every local composition carries them — a host\n // with no artifact on disk serves the floor, and a host with no recorded history\n // renders the explicit no-history clause; neither is a refusal (plan 05's law).\n analysis: createAnalysisArtifactReader(input.agentQaRoot),\n recurrence: recurrence.provider,\n // 398 D-09 (dated 2026-08-17): the catalog port `agent.explain` binds through, handed\n // straight through from the host. Conditionally spread rather than assigned, on the\n // `runInvocation` precedent: an absent port must be an ABSENT field and not a present\n // `undefined` one, because the registry reads exactly this record to decide what the\n // capability LISTS as — so the declaration and the dispatch cannot disagree about whether\n // this composition can explain itself (D-16).\n ...(input.capabilityCatalog === undefined\n ? {}\n : { capabilityCatalog: input.capabilityCatalog }),\n // 403 D-03: the live-view mint seam, conditionally spread on the same rule — an absent port\n // must be an ABSENT field, so `runs.liveurl` declares `unbound` where no origin is served.\n ...(input.liveView === undefined ? {} : { liveView: input.liveView }),\n // 390 D-12/D-13: the three quarantine verbs, bound HERE and therefore on BOTH hosts —\n // the CLI tail and 386's daemon compose the same root, which is the whole point of\n // 385 D-15 (a second binding site is a second answer to \"what is quarantined\").\n //\n // Present in every local composition for the same reason the knowledge WRITE half is: a\n // local host owns the committed knowledge root the ledger lives at. It stays an OPTIONAL\n // dep so a genuinely read-only or remote composition reports all three `unbound` BY NAME\n // rather than answering an empty list about a ledger it has never been able to open.\n //\n // The port takes the root as a FACTORY (the CLI resolves it asynchronously) and the clock\n // as an argument, so this composition supplies both and the implementation reads neither\n // of its own accord. Nothing opens here: the first byte is read when a verb is invoked.\n //\n // 390-09 / CR-03: the SAME `resolveWriterAuthority` the apply path consumes three bindings\n // above, and it is what lands each host on the correct lease arm with zero daemon changes.\n // The daemon supplies it (`cli/src/daemon/host.ts:1839`) because it acquired the lease at\n // startup and holds it for its lifetime, so the verbs ride that authority instead of asking\n // for a lease the process cannot be granted twice; the CLI in-process host supplies nothing,\n // so the verbs acquire and release per call. Conditionally spread like its neighbour rather\n // than assigned through: an absent authority must be an ABSENT field, not a present\n // `undefined` one, so the implementation's `?.()` arm distinguishes the two hosts.\n //\n // 390-12 / D-01: the identity mint is handed straight through, REQUIRED and unspread. The\n // verbs key the committed ledger on `filePath` and every reader compares those bytes with\n // `===`, so a host that supplied nothing would be back to storing whatever a human typed —\n // the round-2 regression. Unlike the authority above there is no host without a checkout\n // root, so the absent case is a compile error rather than a second posture.\n // 394-07 D-12 / WTST-05: the honesty funnel's reads, bound HERE and therefore on BOTH hosts,\n // which is the whole point of 385 D-15 — a second binding site would be a second answer to\n // \"how many drafts did this session keep\", and that number is the one WTST-05 exists to keep\n // honest.\n //\n // UNCONDITIONAL, unlike the loop's two halves above it, and the asymmetry is the point: the\n // funnel is a READ over records this host owns by owning `agentQaRoot`, so every local\n // composition can answer it whether or not it can author anything. An empty receipts\n // directory and an absent one are the same answer, and nothing opens here — the first byte\n // is read when the verb is invoked.\n //\n // THE RECEIPTS PORT IS THE READ HALF ONLY. The evaluator one binding below is handed the\n // same store's `put`; this bundle names `list` and nothing else, so the projection is\n // structurally unable to write the records it reports on. Two narrow mirrors over one store\n // rather than one wide port.\n //\n // 2026-10-01 (432-17, D-06): the bundle no longer reads the proposals inbox. 2026-10-02\n // (quick 261002-ctr): the terminal stage is `writeEligible`, read off the receipts this\n // bundle lists (see `projectAuthoringFunnel`).\n //\n // `outcomes` IS BOUND (394-17, step b): the port's two verbs now LEAD with `product`, so the\n // binding reads the run-outcome projection on its own primary key instead of guessing a\n // partition or serving every product's history under one file path.\n //\n // ASSEMBLED ABOVE rather than inline, because the gate-2 flip path is handed the SAME\n // bundle: one composition-level answer to \"what does this project know about this suite\",\n // reached by the funnel read op and by the evaluator's consultation alike.\n authoringFunnel,\n // 2026-10-01 (432-17, D-05/D-22): the proposals inbox (391 PROP-03) is not bound — it is deleted\n // with its ops. Old files under `<agentQaRoot>/proposals/` are never opened again.\n ...(input.feedback === undefined ? {} : { feedback: input.feedback }),\n ...(input.feedbackReads === undefined ? {} : { feedbackReads: input.feedbackReads }),\n quarantine: createQuarantineOperations({\n resolveKnowledgeRoot: input.knowledgeRoot,\n now: () => clock.now(),\n mintIdentityPath: input.mintQuarantineIdentityPath,\n ...(input.resolveWriterAuthority === undefined\n ? {}\n : { resolveWriterAuthority: input.resolveWriterAuthority }),\n }),\n // 392 D-24: the turn engine assembled above. Bound HERE and therefore on BOTH hosts, so\n // `agent.ask` is a real capability wherever the composition root runs — and unbound nowhere,\n // which is what lets 397's parity suite read it off the registry with no chat-specific case.\n chatTurn: {\n // The engine also echoes authored clause text on receipts and refusal answers. Mask\n // the complete outward projection after execution, never the message it dispatches.\n runTurn: async turnInput =>\n projectChatMembers(await chatTurn.runTurn(turnInput), CHAT_TURN_RESULT_RULES, input.mask),\n },\n // 393 D-01 / D-15: the keep-gate evaluator's two host halves, bound HERE and therefore on\n // BOTH hosts — the CLI and 386's daemon compose this same root, which is the whole point of\n // 385 D-15 (a second binding site would be a second answer to \"is this draft worth keeping\",\n // and the two would disagree about a decision that gets written into a durable receipt).\n //\n // Conditionally spread on BOTH halves, because a capability that can parse but cannot run is\n // not a degraded evaluator — it is a host that must say `unbound` by name. `runs.start` is\n // dispatched through the registry this very call is about to produce, which is the same\n // deferred reference the chat engine takes and is safe for the same reason: no op can run\n // before the registry it is registered in has been built.\n ...(input.draftAuthoring === undefined || input.runExecution === undefined ? {} : {\n draftEvaluation: createDraftEvaluation({\n authoring: input.draftAuthoring,\n agentQaRoot: input.agentQaRoot,\n knowledgeRoot: input.knowledgeRoot,\n authoringFunnel,\n readRun: (runId) => runsReader.get(runId as RunId),\n startGateRun: async (request) => {\n if (composedRegistry === undefined) {\n throw new TypeError('a gate-run started before its registry finished composing')\n }\n return await invokeFunction(\n composedRegistry,\n RUNS_START_FUNCTION_ID,\n request,\n AUTHORING_GATE_RUN_CALLER,\n ) as RunStartAcknowledgement\n },\n }),\n }),\n // 394 D-01 / WTST-01: the authoring LOOP's two halves, bound HERE and therefore on BOTH\n // hosts, under the SAME condition the evaluator above is bound under — the loop's stage 4\n // dispatches `authoring.draft.verify`, so a host that cannot verify a draft cannot author\n // one either, and a third answer to \"can this host author\" would be a third thing to keep\n // in step.\n //\n // THE READ HALF IS `getAuthoringBrief`'S FIRST PRODUCTION CALLER. The port has been\n // implemented and unbound since v51 (`knowledge-local/src/serving/authoring-reader.ts`),\n // which means every field of its contract is crossing a real seam for the first time here;\n // a mismatch surfaces at this binding rather than in a surface. The reader is built PER\n // CALL over a freshly resolved knowledge root, on the standing-approval reader's stated\n // reasoning — the CLI resolves its root asynchronously and per call, and a root captured\n // once would serve a brief out of a knowledge tree the invocation is not serving from. No\n // `product` is bound: the composition does not own one, and the SCOPE arrives on the op's\n // input, which is the honest half of the pair the reader filters on.\n //\n // `suiteTextCorpus` is the SAME host walk gate 3's degraded lane already consumes, reached\n // here for stage 2's pre-authoring screen. One walk, one notion of what a suite test's text\n // is; a second enumeration would let the screen and the gate disagree about the same pair.\n //\n // THE WRITE HALF bundles the model, the shelf and the verify dispatch, because none of the\n // three is independently bindable: a host with a model and no shelf cannot author, one with\n // a shelf and no model has nothing to author with, and one that can do both but cannot\n // verify would produce a test and have nothing to say about whether it is worth keeping.\n // The model is a FACTORY, resolved at most once and only when a draft is actually compiled,\n // the same idiom `openJobs` uses — binding this capability must not construct a client for a\n // host that never authors.\n //\n // WHY THE ROUTER (plan 05) WILL READ `DraftRunPortLike.get`'s `CompletedRunHandoff` AND NOT\n // `runs.get`'s PROJECTION. D-08 routes on run EVIDENCE — step terminations, planning\n // failure, cycle flags, the per-step sub-action record — and `runs.get` projects a\n // `RunDetail` in which none of that survives (`stepCount` is its only step-shaped field).\n // This is `createDraftEvaluation`'s own posture, stated one layer out: the op is reached for\n // what an op owns, and the reader is read for evidence no projection carries. A router built\n // on the projection would have to infer a mechanics failure from a member verdict, and\n // inferring an app defect out of a bare member verdict is precisely the cardinal error D-08\n // exists to make unreachable.\n //\n // A NOTE FOR WHOEVER EDITS THIS PARAGRAPH. The arch dependency scan reads import specifiers\n // out of this file's RAW BYTES, comments included, so any prose shaped like an import's\n // trailing clause — the keyword, then a quoted phrase — is reported as an undeclared\n // external dependency of this package. Two drafts of this comment tripped it, once on a\n // sentence about verdicts and once on the sentence explaining the first. Keep quoted phrases\n // away from that keyword here.\n ...(authoringLoopHost === undefined ? {} : {\n authoringRead: {\n async getAuthoringBrief(intent: string, scope: ScopeKey): Promise<AuthoringBrief> {\n const knowledgeRoot = await input.knowledgeRoot()\n return createAuthoringReader({ knowledgeRoot }).getAuthoringBrief(intent, scope)\n },\n suiteTextCorpus: () => authoringLoopHost.suiteTextCorpus(),\n // 394-33 · WR-07: the `target` vocabulary stage 3's compile prompt serves. Bound off the\n // SAME port the brief and the corpus come from, so a host that can run the loop's read\n // stages can name its own targets by construction — see the port's own doc.\n configuredTargetNames: () => authoringLoopHost.configuredTargetNames(),\n },\n // 394-26 · WINDOWS 110: the scope an intent-only call is authored at, bound HERE and so on\n // BOTH hosts, off the same port the read and compile halves come from. Its own deps key\n // rather than a third verb on `authoringRead`, because deriving a scope needs the resolved\n // config and the workspace while the brief needs a knowledge index — a host can have one\n // without the other, and the op refuses on THIS key by name when a scope-less call arrives\n // at a composition that never bound it.\n authoringScope: {\n deriveDefault: () => authoringLoopHost.deriveDefaultScope(),\n },\n draftShelf: {\n model: async () => await input.model(),\n write: (contents: string) => authoringLoopHost.stageDraft(contents),\n // 394-06 D-09/D-20: the ONE RFC-6902 applier, reached at the host because it needs the\n // yaml CST and neither `agent` nor this package may depend on `core`. Same seam,\n // same reason and same shape as `stageDraft` right above it.\n applyPatches: (draft, patchSet) => authoringLoopHost.applyPatchesToDraft(draft, patchSet),\n // 432 D-06/D-07: the direct writer the loop's final write and the edit op reach. Same seam\n // and same reason as the two verbs above: the boundary check needs `core`.\n publish: (request) => authoringLoopHost.publishDraft(request),\n // 394-06: stage 5's evidence reader and the repair arm's probe runner. The reader is\n // the same `runsReader` the gate evaluator is bound to — a second reader would be a\n // second answer to what one run recorded — and the starter dispatches the REGISTERED\n // `runs.start` on the gate-run caller, so a probe is marker-stamped exactly as a gate\n // run is and is excluded from outcomes for the same reason.\n runs: {\n start: async (request): Promise<RunStartAcknowledgement> => {\n if (composedRegistry === undefined) {\n throw new TypeError('a repair probe started before its registry finished composing')\n }\n return await invokeFunction(\n composedRegistry,\n RUNS_START_FUNCTION_ID,\n request,\n AUTHORING_GATE_RUN_CALLER,\n ) as RunStartAcknowledgement\n },\n get: (runId: string) => runsReader.get(runId as RunId),\n },\n // 2026-10-01 (432-18/432-19, D-15): no dispatch-scoped grant exists. The authoring loop\n // runs its dispatch directly, and no gate run it starts consults any approval.\n verifyDraft: async (verifyInput: AuthoringVerifyDraftInput): Promise<DraftReceipt> => {\n if (composedRegistry === undefined) {\n throw new TypeError('a draft was verified before its registry finished composing')\n }\n return await invokeFunction(\n composedRegistry,\n AUTHORING_DRAFT_VERIFY_FUNCTION_ID,\n verifyInput,\n AUTHORING_LOOP_VERIFY_CALLER,\n ) as DraftReceipt\n },\n },\n // 2026-10-01 (432-17, D-06): no authoring proposal writer is bound; an authored test is\n // written in its own call through the shelf's direct writer.\n }),\n // 432-16 (D-07): no test-draft or config commit port and no undo source is bound — agent-qa\n // makes no git commits. The final authored test is written through `draftShelf.publish`.\n //\n // 395-01 D-01/D-03/D-17 · CFGM-01/03/04: the config editor's host half, each spread on its\n // OWN condition rather than as one bundle, so a host missing one reports that one `unbound`.\n ...(input.configFiles === undefined ? {} : { configFiles: input.configFiles }),\n ...(input.configValidate === undefined ? {} : { configValidate: input.configValidate }),\n ...(input.scaffoldContent === undefined\n ? {}\n : { scaffoldContent: input.scaffoldContent }),\n ...(input.configWrite === undefined ? {} : { configWrite: input.configWrite }),\n // 2026-10-14 (441-39, D-15): a config change is not scanned for secrets, so no scan is bound.\n // 2026-10-01 (432-17, D-05): no config proposal filer is bound; the six config ops write in\n // the call through `configWrite`.\n },\n // 2026-10-15 (441-28, D-15): no audit sink; the guardrail audit went with the guardrails.\n // 432-13 (D-14/D-15): no standing-approval reader, confirm port or session deny overlay reaches\n // the registry — `invokeFunction` asks nobody. 432-18 deleted the grant reader with the ledger.\n // 2026-10-02 (432-39, D-12): the host's execution-context answer is no longer forwarded here.\n // The registry's option was retired and unread since 432-13 and is deleted; the same answer\n // still reaches the knowledge review above, which records a direct change under it.\n })\n // Closes the cycle the turn engine's dispatch binding was built against. It happens exactly\n // here, on the line after the registry exists, so there is no window in which a turn could run\n // against an unset reference — and the engine's own guard names that state if one ever appears.\n composedRegistry = registry\n\n let opened: LocalAgentJobs | undefined\n let opening: Promise<LocalAgentJobs> | undefined\n let closing: Promise<void> | undefined\n let lifecycleGeneration = 0\n let closed = false\n\n async function openJobs(openGeneration: number): Promise<LocalAgentJobs> {\n const model = await input.model()\n // Resolved ONCE at queue open, the same idiom as the model above: the post-run\n // capability members read synchronously, and the knowledge root is a process fact.\n const knowledgeRoot = await input.knowledgeRoot()\n const analysisTokenBudget = input.analysisTokenBudget === undefined\n ? undefined\n : await input.analysisTokenBudget()\n // 422-09: resolved at the SAME open, for the same reason — the capability member is a number\n // the handler reads synchronously, and resolving it per job would read configuration inside a\n // claim that must not depend on a file the operator can edit mid-drain.\n const proposeGate1MaxPerJob = input.postRun?.proposeGate1MaxPerJob === undefined\n ? undefined\n : await input.postRun.proposeGate1MaxPerJob()\n const store = createSqliteJobStore({\n path: join(input.agentQaRoot, AGENT_JOB_STORE_DB_FILE),\n clock,\n checkpoints: createJobCheckpointStore({ root: input.agentQaRoot }),\n })\n let jobs: LocalAgentJobs\n try {\n const kinds = input.jobKinds\n ?? createRealJobKindRegistry(\n postRunCapabilities(input, knowledgeRoot, analysisTokenBudget, store, proposeGate1MaxPerJob),\n )\n // Resolved ONCE and used for both the queue and the published field: the value a watcher\n // derives ids from has to be the value the queue mints them with, and two spellings of the\n // same default is how those two drift.\n const idSource = input.idSource ?? DIGEST_JOB_ID_SOURCE\n // Resolved ONCE from the one table, for the queue and the published field alike (388-10).\n //\n // A host with NO `postRun` folds to `'no-masker'` rather than to no exclusion (WR-12).\n // Silence is not a review: a host that never declared what its fold does with candidate\n // prose cannot have reviewed it, and the fail-safe reading of an undeclared posture is\n // the constrained one. 388-09's M-3 measured what the permissive reading costs — a\n // stand-in registry composed without `postRun` runs a `curate-memory` row to `done` and\n // publishes `bundle-committed`, a receipt no fold earned. Read through the same total\n // table as every other posture, so there is no fall-through here to drift from it.\n const unclaimableKinds: readonly JobKind[]\n = UNCLAIMABLE_BY_PROSE_POSTURE[input.postRun?.candidateProse ?? 'no-masker']\n jobs = {\n queue: createAgentJobQueue({\n store,\n registry: kinds,\n clock,\n idSource,\n model,\n ...(unclaimableKinds.length === 0 ? {} : { unclaimableKinds }),\n }),\n store,\n kinds,\n model,\n idSource,\n unclaimableKinds,\n }\n } catch (error) {\n store.close()\n throw error\n }\n if (closed || openGeneration !== lifecycleGeneration) {\n // The model can resolve after close. Constructing then invalidating here keeps the open\n // transactional: the late store proves it can initialize, but it never becomes reachable.\n store.close()\n throw new LocalAgentClosedError(input.agentQaRoot)\n }\n opened = jobs\n return jobs\n }\n\n return {\n registry,\n chat: {\n stateFor: (sessionId) => chatScopes.get(sessionId)?.state.read(),\n async abortActiveTurn(): Promise<void> {\n // D-19's GRACEFUL arm. The hard-kill arm needs nothing here — a torn tail is detected and\n // an `aborted` synthesized on the next open — but a Ctrl+C that got as far as running this\n // handler can say so explicitly, which is a better record than one reconstructed later.\n //\n // EVERY LIVE SESSION IS ASKED, AND EACH ANSWERS WITH ITS OWN TURN (392-12 shape, plan 13\n // state). Plan 12 could iterate the handles but had only ONE turn id to look for, because\n // `chatState` was per-composition — so on a host with two turns genuinely in flight, one\n // was nameable and the other was not. Each session now holds the id of the turn IT is\n // running, so graceful shutdown closes every conversation rather than the last one to\n // start. Between turns a session names nothing, and writing an `aborted` anyway would put\n // a row on a turn that already carries its `turn_complete` — which the next open's repair\n // would read as an interrupted turn and prune from the conversation.\n for (const [sessionId, entry] of liveChatSessions) {\n const turnId = chatScopes.get(sessionId)?.state.read().activeTurnId\n if (turnId === undefined) continue\n if (!entry.turnIds.has(turnId)) continue\n await entry.handle.append({\n kind: 'aborted',\n turnId,\n at: clock.now(),\n source: 'explicit',\n })\n // Fsynced immediately rather than at a turn boundary that is not coming: this is the\n // last thing this process writes, and an unflushed `aborted` is exactly the event the\n // repair it exists to make unnecessary would have to reconstruct.\n await entry.handle.turnBoundary()\n }\n },\n },\n curation: LOCAL_CURATION_CAPABILITIES,\n clock,\n jobs(): Promise<LocalAgentJobs> {\n if (closed) return Promise.reject(new LocalAgentClosedError(input.agentQaRoot))\n // Memoized on the PROMISE, not on the resolved value: two concurrent callers awaiting a\n // value-memoized opener would each run the factory and each open the database.\n opening ??= openJobs(lifecycleGeneration)\n return opening\n },\n close(): Promise<void> {\n if (closing !== undefined) return closing\n closed = true\n lifecycleGeneration += 1\n const pending = opening\n const current = opened\n opened = undefined\n // Preserve the existing synchronous-close property for a fully opened composition. Callers\n // that historically did not await close still release the handle before returning.\n current?.store.close()\n closing = (async () => {\n if (pending !== undefined) {\n try {\n const late = await pending\n if (late !== current) late.store.close()\n } catch {\n // A superseded opener closes its own store; a model/open failure owns no live handle.\n }\n }\n opening = undefined\n })()\n return closing\n },\n }\n}\n","// The function layer's knowledge READ port, bound over the physically read-only entry\n// (Phase 387, KREV-01 / FUNC-04 / D-01).\n//\n// This file exists so the read half of the review-verb family has a home that CANNOT name the\n// writer-gated entry. It is registered in the arch reader carve-out's pinned file list, which\n// means the lint fails this file for naming anything but the `/reader` subpath — the same rule\n// that already binds `knowledge-read.ts` and the run-scoped serving reader. The alternative,\n// leaving the binding inside the composition root (which legitimately names the writer entry,\n// because it also binds the curator), would have put five read verbs inside the one file in\n// the workspace where a write import is legal. The rule would still have passed and the\n// separation would have been discipline rather than structure.\n//\n// D-01 LIST-VERB SIGHTING. Entity ids discovered by listing and single-record verbs go to the\n// injected `sightMemoryEntities` callback. The callback is INJECTED rather than constructed\n// here for the reason above: minting reaches the durable addressing ledger, whose module lives\n// on the writer-gated entry, so a version of this file that could mint could not be a reader\n// file. The composition root — which may name that entry — supplies it. The callback is a side\n// effect on the ledger and never on the answer: every projection below is byte-identical\n// whether or not one is supplied, which is what keeps the wiring-parity claim true.\n\nimport {\n canaryAttributionsFor,\n candidateInjectionFor,\n gateReceiptsFor,\n diffSince,\n inspectRecords,\n listBundles,\n showRecord,\n showRecords,\n} from '@vostride/agent-qa-knowledge-local/reader'\nimport type { KnowledgeReaderPort } from '@vostride/agent-qa-agent'\nimport type { ResolvePromotionPosture, TrustPriorTable } from '@vostride/agent-qa-schema'\n\n/**\n * Hand every entity id an output surfaced to the addressing ledger's sighting seam.\n *\n * Fire-and-forget by contract: it resolves when the sighting is recorded, and a rejection is\n * not the read's problem. An address is a permanent fact about an entity and a listing is a\n * question about the store; failing the question because the bookkeeping failed would let the\n * ledger take down the answer it exists to annotate.\n */\nexport type SightMemoryEntities = (bundleIds: readonly string[]) => Promise<void>\n\nexport interface ConstructKnowledgeReaderPortInput {\n resolveTrustPriors?: () => TrustPriorTable | undefined\n /**\n * Which knowledge root this invocation serves from, resolved per call.\n *\n * A host-supplied resolver rather than a string, on the same reasoning the bundle listing\n * already carried: deciding which configuration file is in force is a decision a daemon\n * makes differently from a terminal.\n */\n resolveKnowledgeRoot: () => Promise<string> | string\n /** Host preparation may await; the returned per-candidate resolver is synchronous. */\n resolvePromotionPosture?: () => Promise<ResolvePromotionPosture | undefined> | ResolvePromotionPosture | undefined\n /** The D-01 sighting site. Absent in hosts that bind no addressing ledger. */\n sightMemoryEntities?: SightMemoryEntities\n}\n\nexport function createKnowledgeReaderPort(\n input: ConstructKnowledgeReaderPortInput,\n): KnowledgeReaderPort {\n async function sight(bundleIds: readonly string[]): Promise<void> {\n if (input.sightMemoryEntities === undefined || bundleIds.length === 0) return\n try {\n await input.sightMemoryEntities(bundleIds)\n } catch {\n // See `SightMemoryEntities`: the read already answered.\n }\n }\n\n return {\n // 2026-09-07, 417 D-01: forward the candidate DATA verbatim. Since 441-41 (D-06) nothing here\n // scans it; the chat and MCP doors mask declared values in every op result.\n async candidateInjection({ candidateId }) {\n return candidateInjectionFor({\n ...(input.resolveTrustPriors === undefined ? {} : { priors: input.resolveTrustPriors() }),\n knowledgeRoot: await input.resolveKnowledgeRoot(), candidateId,\n })\n },\n // 416 D-17: the caller supplied the identity; forward the reader's answer verbatim.\n async gateReceipts({ candidateId }) {\n return gateReceiptsFor({\n knowledgeRoot: await input.resolveKnowledgeRoot(),\n candidateId,\n resolvePromotionPosture: await input.resolvePromotionPosture?.(),\n })\n },\n async listBundles() {\n const rows = listBundles(await input.resolveKnowledgeRoot(), input.resolveTrustPriors?.())\n await sight(rows.map((row) => row.bundleId))\n return rows\n },\n async inspectRecords({ filter }) {\n const records = inspectRecords({\n ...(input.resolveTrustPriors === undefined ? {} : { priors: input.resolveTrustPriors() }),\n knowledgeRoot: await input.resolveKnowledgeRoot(),\n filter,\n })\n await sight(records.map((record) => record.recordId))\n return records\n },\n async diffSince({ sinceOrdinal }) {\n const changes = diffSince({\n knowledgeRoot: await input.resolveKnowledgeRoot(),\n sinceOrdinal,\n })\n // A change list names records by id including ones whose bundle is gone (a purge\n // change). Those simply are not sighted: the sighting seam requires a source to\n // RECOGNISE the id, so a purged record mints nothing and the ledger stays a record of\n // entities that were actually seen rather than of ids that were mentioned.\n await sight(changes.map((change) => change.recordId))\n return changes\n },\n async showRecord({ recordId }) {\n const result = showRecord({\n ...(input.resolveTrustPriors === undefined ? {} : { priors: input.resolveTrustPriors() }),\n knowledgeRoot: await input.resolveKnowledgeRoot(),\n recordId,\n })\n await sight(result.kind === 'found' ? [result.record.recordId] : [])\n return result\n },\n // Caller-supplied union IDs are already known, like canary tuples below. Forward\n // the maintenance batch without address-ledger sightings or per-record scans.\n async showRecords({ recordIds }) {\n return showRecords({ knowledgeRoot: await input.resolveKnowledgeRoot(), recordIds })\n },\n /**\n * 407 D-08: what became of the canary lines one run served.\n *\n * Resolved per call like its four siblings, and NOT sighted. The caller already holds every\n * candidate id in the tuples it passes — it read them off its own run's evidence — so a\n * sighting here would record that the reader was handed ids rather than that an entity was\n * surfaced to anyone, which is the distinction the ledger exists to keep.\n *\n * The reader entry's answer is forwarded VERBATIM, `skippedBundles` included (407-19, REVIEW\n * WR-03). This binding neither counts nor interprets: how much of the store went unread is a\n * fact only the walk knows, and a composition that dropped it here would hand the op a\n * clean-looking answer over a half-read store.\n */\n async canaryAttributions({ runId, tuples }) {\n return canaryAttributionsFor({\n knowledgeRoot: await input.resolveKnowledgeRoot(),\n runId,\n tuples,\n })\n },\n }\n}\n","// The analysis artifact's host write adapter (Phase 389, D-09 / T-389-03).\n//\n// The durability idiom is the curation-tail receipt writer's, copied deliberately and NOT\n// handoff.json's plain write: stage under a random `.tmp` name, write at 0o600, fsync the\n// staged file, rename into place, fsync the directory, remove the staged file in a finally.\n// The artifact is what a chip's `done` promises is fetchable — the verdicts-authored value\n// is recorded only AFTER this returns — so a torn or unsynced write here would be the one\n// place `authored` could overstate. Idempotent per path by construction: rename replaces\n// atomically, so re-persisting the same run leaves one file and last write wins.\n\nimport { closeSync, fsyncSync, openSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport { randomUUID } from 'node:crypto'\nimport { dirname, join } from 'node:path'\n\nimport { canonicalJson } from '@vostride/agent-qa-schema'\nimport type { RunAnalysisArtifact } from '@vostride/agent-qa-schema'\n\n/** The staged-file marker, kept distinct from the receipt writer's so residue is attributable. */\nconst ANALYSIS_STAGE_PREFIX = 'analysis.json'\n\nfunction fsyncFile(file: string): void {\n const fd = openSync(file, 'r')\n try {\n fsyncSync(fd)\n } finally {\n closeSync(fd)\n }\n}\n\n/**\n * Durably write one run's analysis artifact at `path` (D-09).\n *\n * The caller owns the path law — the composition root derives it from `runId` alone via\n * `slugBranch`, mirroring the handoff read binding (T-389-01). This helper owns only the\n * bytes and their durability.\n */\nexport function writeAnalysisArtifact(path: string, artifact: RunAnalysisArtifact): void {\n const dir = dirname(path)\n const staged = join(dir, `.${ANALYSIS_STAGE_PREFIX}.${randomUUID()}.tmp`)\n try {\n writeFileSync(staged, `${canonicalJson(artifact)}\\n`, { encoding: 'utf8', mode: 0o600 })\n fsyncFile(staged)\n renameSync(staged, path)\n fsyncFile(dir)\n } finally {\n rmSync(staged, { force: true })\n }\n}\n","// The chat session log's JSONL disk adapter (Phase 392, CHAT-05 / D-17 / D-18 / D-19).\n//\n// APPEND-ONLY, AND THE FILE IS NEVER REWRITTEN. That is the requirement CHAT-05 states literally,\n// and it is also what makes the log usable as the triage report D-18 describes: a reader can trust\n// that line N means the same thing it meant when it was written, and a crash can only ever cost the\n// tail. Every verb below is either an append or a read; there is no update path to misuse. REPAIR\n// obeys the same law — it APPENDS a synthesized `aborted` event and touches not one existing byte.\n//\n// THE DURABILITY POSTURE IS COPIED FROM `job-checkpoint-store.ts`, not re-derived. Five things come\n// across verbatim, each of them a platform quirk already debugged once in this repo:\n//\n// 1. The narrow injectable fs facade — exactly the calls this module makes and nothing else. A\n// wide facade invites a test to answer on its own behalf.\n// 2. The two-factory seam — production options have NO fs member, so \"append without the fsync\"\n// is not a one-argument change a composition root can make by accident. The seam is a second\n// exported function a test names explicitly, and it is deliberately NOT on this package's\n// barrel: the checkpoint store publishes neither of its factories, for the reason that a seam\n// reachable by every surface is no longer a seam.\n// 3. Exclusive create (`'wx'`) for a new session, so a torn file from an earlier crash can never\n// be mistaken for this one's.\n// 4. The parent-directory fsync after a create, with the `DIRECTORY_FSYNC_SWALLOWED_CODES`\n// allowlist IMPORTED rather than re-derived — a directory entry is not durable until its\n// parent is synced, and a hand-copied allowlist is how best-effort silently becomes no-effort.\n// 5. `SAFE_PATH_SEGMENT` and its named refusal — a session id is a caller-supplied string that\n// becomes a path, which is the T-392-01 spoofing surface exactly.\n//\n// WHERE THE FSYNCS ARE, AND WHY THERE. Two, and only two, on the life of a session: one on the\n// header at create (a session file that exists at all is a session file whose header is on the\n// device, and whose directory entry is too), and one per TURN at `turnBoundary()`. Per turn rather\n// than per event is what makes the loss bound exactly the in-flight turn — which is exactly what\n// the repair below knows how to handle. Syncing per event would buy a guarantee finer than any\n// reader can use, and syncing at close would leave a killed process with a turn nobody landed.\n//\n// ONE DESCRIPTOR PER SESSION, HELD BY THAT SESSION'S HANDLE (392-12, CR-01). This adapter used to\n// keep ONE mutable `fd` and repoint it on every `open()`, which made session identity adapter state\n// rather than a parameter of the write path: two turns whose awaits interleaved both wrote into\n// whichever file opened last, and the loser was left with a turn that never closed — synthesized as\n// `aborted` and pruned out of the conversation, the user's own message with it, on the next open.\n// Descriptors are now keyed by session id and reachable only through the handle `open()` returned,\n// so there is no expression in this file that can write to a session the caller did not open. A\n// second open of a session already held is `ChatSessionBusyError`, not a second descriptor.\n//\n// WHAT REPAIR DECIDES LIVES ELSEWHERE. `repairSession` is a pure function in `packages/agent`\n// beside the turn engine, because deciding what a DAMAGED file means is a different kind of work\n// than moving bytes, and it deserves its own corpus rather than a branch in a read loop. This\n// adapter does the raw-line half (a torn FINAL line is skipped; a damaged mid-file line is a named\n// refusal) and hands guarded events onward. The header, by contrast, is refused outright: a session\n// whose header this build cannot read is not a session it can safely append to.\n\nimport {\n closeSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readSync,\n readFileSync,\n readdirSync,\n writeFileSync,\n} from 'node:fs'\nimport { isAbsolute, join } from 'node:path'\n\nimport { repairSession } from '@vostride/agent-qa-agent'\nimport { CURRENT_CHAT_SESSION_SCHEMA_VERSION } from '@vostride/agent-qa-schema'\nimport type {\n ChatSessionEvent,\n ChatSessionHandle,\n ChatSessionHeader,\n OpenedChatSession,\n SessionLogPort,\n} from '@vostride/agent-qa-schema'\n\nimport { DIRECTORY_FSYNC_SWALLOWED_CODES } from '../store/job-checkpoint-store.js'\n\n/** Directory segment under the agent-qa runtime root. Gitignored, per D-17. */\nexport const CHAT_SESSIONS_SUBDIR = 'sessions'\n\n/** The file extension every session log carries. A listing filters on it, nothing else. */\nconst SESSION_FILE_SUFFIX = '.jsonl'\n\n/**\n * How many bytes a listing reads at a time.\n *\n * RETUNE if session headers ever grow past a line or listings become the hot path: the only\n * property this number has to have is that it is a CONSTANT, so listing a thousand sessions costs\n * a thousand small buffers rather than a thousand whole files in memory. 64 KiB is one filesystem\n * read on every platform this ships to and comfortably holds a header line many times over.\n */\nexport const CHAT_SESSION_READ_CHUNK_BYTES = 64 * 1024\n\n/**\n * Ids that are safe as a single path segment.\n *\n * The same class `job-checkpoint-store.ts` uses, and the same reasoning: leading dots are excluded\n * so `..` cannot be an id at all, and the class admits no separator on any platform.\n */\nconst SAFE_PATH_SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/\n\n/** A caller-supplied session id that could not be a path segment (T-392-01). */\nexport class InvalidChatSessionIdError extends Error {\n override readonly name = 'InvalidChatSessionIdError'\n\n constructor(readonly sessionId: string) {\n super(\n `${JSON.stringify(sessionId)} is not a usable chat session id. Ids are minted by this `\n + 'adapter and are limited to letters, digits, dot, dash and underscore.',\n )\n }\n}\n\n/**\n * A session id that names no session.\n *\n * A REFUSAL and never a create (D-17, RESEARCH Open Q4). Creating a fresh session for a mistyped\n * `--session` would tell a person their history was lost when in fact it was never looked at, and\n * would do so in the one direction no later read can undo.\n */\nexport class UnknownChatSessionError extends Error {\n override readonly name = 'UnknownChatSessionError'\n\n constructor(readonly sessionId: string) {\n super(`No chat session ${sessionId} exists under this project's runtime root.`)\n }\n}\n\n/**\n * A session somebody is already holding open (Phase 392 plan 12, T-392-BUSY).\n *\n * A REFUSAL BY NAME rather than a second descriptor. Two handles on one file would interleave two\n * turns inside a single conversation — the same damage the cross-session aliasing did, one level\n * down — and it is exactly what a double-submit of one `sessionId` over the daemon socket asks for.\n * The remedy is to wait for the holder, which is why the id is on the error rather than only in\n * the message.\n */\nexport class ChatSessionBusyError extends Error {\n override readonly name = 'ChatSessionBusyError'\n\n constructor(readonly sessionId: string) {\n super(\n `Chat session ${sessionId} is already open in this process. One writer at a time: a second `\n + 'handle would interleave two turns in one conversation.',\n )\n }\n}\n\n/** Bytes that do not describe a session this build can append to. */\nexport class ChatSessionHeaderError extends Error {\n override readonly name = 'ChatSessionHeaderError'\n\n constructor(\n readonly sessionId: string,\n readonly detail: string,\n ) {\n super(`The session file for ${sessionId} cannot be read: ${detail}.`)\n }\n}\n\n/**\n * Exactly the filesystem calls this module makes, and nothing else.\n *\n * `'a'` is the append-mode open the whole design rests on: the kernel places every write at the\n * current end of file, so two writers cannot interleave a partial line, and no offset bookkeeping\n * exists here to get wrong. `'r'` appears twice for two unrelated reasons — the parent-directory\n * fsync needs a descriptor on the directory, and the listing needs a bounded read on a file.\n *\n * `writeFileSync` on a descriptor rather than `writeSync` is deliberate. `writeSync` may report a\n * SHORT write and leave the caller to loop; a loop is exactly the offset bookkeeping the append\n * mode was chosen to abolish, and a forgotten one is a half-written line — the damage shape this\n * file is otherwise built to survive. `writeFileSync` writes the whole buffer or throws, which is\n * also what the checkpoint store's facade takes.\n */\nexport interface ChatSessionFs {\n mkdirSync(path: string, options: { readonly recursive: true }): void\n openSync(path: string, flags: 'a' | 'wx' | 'r'): number\n writeFileSync(fd: number, data: string, encoding: 'utf8'): void\n fsyncSync(fd: number): void\n closeSync(fd: number): void\n readSync(\n fd: number,\n buffer: Buffer,\n offset: number,\n length: number,\n position: number | null,\n ): number\n readFileSync(path: string, encoding: 'utf8'): string\n readdirSync(path: string): string[]\n}\n\n/** The production implementation, frozen so it cannot be patched from a distance. */\nexport const REAL_CHAT_SESSION_FS: ChatSessionFs = Object.freeze({\n mkdirSync,\n openSync,\n writeFileSync,\n fsyncSync,\n closeSync,\n readSync,\n readFileSync,\n readdirSync,\n})\n\n/**\n * What a production caller supplies: a root and the session's opening context.\n *\n * The absence of an fs member is the guarantee, exactly as it is on `CreateJobCheckpointStoreOptions`.\n */\nexport interface CreateJsonlSessionLogOptions {\n /** Absolute path to the agent-qa runtime root, typically `<project>/.agent-qa`. */\n readonly root: string\n /** ISO instant source — the composition's clock, never `Date.now()` reached for here. */\n readonly now: () => string\n /**\n * The model in force when the session opens. Drift is `model_change` events, never a rewrite.\n *\n * A THUNK rather than a string, because a composition root resolves its model lazily — a host\n * that only lists the registry must not pay a provider resolution — and a header built from a\n * value captured at construction would name whatever was true before that resolution ran.\n */\n readonly model: () => string\n /** The toolset fingerprint at open, on the same thunk reasoning as `model` above. */\n readonly toolsetHash: () => string\n /**\n * WHICH DOOR THIS LOG BELONGS TO (Phase 400 plan 03, D-04). Absent ⇒ no tag is written.\n *\n * A VALUE AND NOT A THUNK, which is the opposite of `model` and `toolsetHash` above and for the\n * mirror of their reason. Those are resolved lazily because a composition's model can arrive\n * after the log does and can drift afterwards; a surface cannot. Which door composed this host is\n * decided at the composition root and is a constant for the life of the process, so a thunk would\n * be a seam for a value to change through — and a header is written once and never rewritten,\n * so a changing surface has nowhere to go.\n *\n * ABSENT IS THE PRE-400 CLI-CHAT POSTURE, stated in `ChatSessionHeader.surface` and preserved\n * here: a host that names no surface writes a header byte-identical to the ones every build\n * before this one wrote.\n */\n readonly surface?: string\n /** Random source for the id suffix, injectable so a test can pin an id. */\n readonly random?: () => number\n}\n\n/** One session, as a listing knows it: everything the header line says, plus how long the log is. */\nexport interface ChatSessionListEntry {\n readonly sessionId: string\n readonly createdAt: string\n /** The model in force when the session OPENED. Drift after that is `model_change` events. */\n readonly model: string\n /**\n * Event lines on the file, counted without parsing one.\n *\n * An EVENT count and not a turn count, and the difference is not a shortcut. A turn count is not\n * a header fact and cannot become one — the header is written once and never rewritten, which is\n * the property CHAT-05 asks for by name — so the only way to produce one is to parse every line\n * of every log, which is the work a listing exists to avoid. The line count answers \"is there\n * anything in here\" for a fraction of the cost, and `open()` answers everything else.\n */\n readonly eventCount: number\n}\n\n/** One session file the listing could not read, surfaced as data rather than thrown over. */\nexport interface RefusedChatSessionFile {\n /** The file's own name, which is what a person has to go and look at. */\n readonly file: string\n readonly reason: string\n}\n\nexport interface ChatSessionListing {\n readonly sessions: readonly ChatSessionListEntry[]\n readonly refused: readonly RefusedChatSessionFile[]\n}\n\n/**\n * `chat-<UTCyyyymmdd-HHMMSS>-<4 base36>`.\n *\n * Sorted-by-name equals sorted-by-time, which is what makes a plain directory listing the session\n * list; the random tail is what keeps two sessions opened in the same second distinct. Every\n * character is in `SAFE_PATH_SEGMENT` by construction, so a minted id can never be refused by the\n * guard that protects a supplied one.\n */\nexport function mintChatSessionId(nowIso: string, random: () => number): string {\n const stamp = nowIso.replace(/[-:]/g, '').replace(/\\.\\d+Z$/, 'Z').replace('T', '-').replace('Z', '')\n const suffix = Math.floor(random() * 36 ** 4)\n .toString(36)\n .padStart(4, '0')\n return `chat-${stamp}-${suffix}`\n}\n\nfunction requireSessionId(sessionId: string): string {\n if (!SAFE_PATH_SEGMENT.test(sessionId)) throw new InvalidChatSessionIdError(sessionId)\n return sessionId\n}\n\nfunction isSwallowableDirectoryFsyncError(error: unknown): boolean {\n const code = (error as NodeJS.ErrnoException).code\n return DIRECTORY_FSYNC_SWALLOWED_CODES.some((allowed) => allowed === code)\n}\n\n/**\n * The header guard: version BEFORE shape.\n *\n * The order is the same decision `job-checkpoint-store.ts:231-237` states — a version mismatch has\n * a remedy an operator can act on, and reporting it as a generic shape failure names a field\n * instead. The `readonly` cast is safe because the value is re-validated field by field below.\n */\nfunction guardHeader(sessionId: string, line: string): ChatSessionHeader {\n let parsed: unknown\n try {\n parsed = JSON.parse(line)\n } catch {\n throw new ChatSessionHeaderError(sessionId, 'its first line is not JSON')\n }\n if (parsed === null || typeof parsed !== 'object') {\n throw new ChatSessionHeaderError(sessionId, 'its header line is not an object')\n }\n const header = parsed as Record<string, unknown>\n if (header.schemaVersion !== CURRENT_CHAT_SESSION_SCHEMA_VERSION) {\n throw new ChatSessionHeaderError(\n sessionId,\n `it declares schemaVersion ${String(header.schemaVersion)} and this build reads `\n + String(CURRENT_CHAT_SESSION_SCHEMA_VERSION),\n )\n }\n if (header.sessionId !== sessionId) {\n throw new ChatSessionHeaderError(\n sessionId,\n `its header names session ${String(header.sessionId)}`,\n )\n }\n if (typeof header.createdAt !== 'string' || typeof header.model !== 'string') {\n throw new ChatSessionHeaderError(sessionId, 'its header names no creation instant or model')\n }\n // THE TAG IS OPTIONAL AND THE CHECK IS ON ITS TYPE, NOT ON ITS PRESENCE (400-03, D-04). An absent\n // `surface` is the pre-400 CLI-chat population and passes untouched — that absence is the whole\n // back-compatibility claim. A PRESENT one that is not a string is refused for the reason this\n // whole guard exists: the cast below hands the caller a typed record, and a header that would\n // make `header.surface` a number is a header this build cannot read rather than one it may\n // quietly narrow.\n if (header.surface !== undefined && typeof header.surface !== 'string') {\n throw new ChatSessionHeaderError(\n sessionId,\n `its header names a surface of type ${typeof header.surface} and this build reads a string`,\n )\n }\n return header as unknown as ChatSessionHeader\n}\n\n/**\n * Every session under one runtime root, read from headers alone (D-17).\n *\n * A DAMAGED FILE IS DATA, NOT AN EXCEPTION — the posture the grant ledger had (391; deleted in 432-18).\n * A corrupt neighbour costs the caller that one entry and nothing else; throwing would let a single\n * unreadable file hide every healthy session from the person trying to find their conversation.\n *\n * It reads through the real filesystem with no injection seam, and that absence is on purpose: the\n * seam beside `createJsonlSessionLogOn` exists because syscall ORDER is a durability property no\n * crash test can observe. A listing has no such property. What it returns is its whole contract,\n * and a temp directory proves that directly.\n */\nexport function listSessions(root: string): ChatSessionListing {\n if (!isAbsolute(root)) throw new TypeError('chat session log root must be absolute')\n const fs = REAL_CHAT_SESSION_FS\n const sessionsRoot = join(root, CHAT_SESSIONS_SUBDIR)\n\n let files: string[]\n try {\n files = fs.readdirSync(sessionsRoot)\n } catch (error) {\n // No sessions directory is no sessions, not a failure: a project that has never opened chat is\n // in exactly that state, and it is the state the very first `chat` command starts from.\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return { sessions: [], refused: [] }\n throw error\n }\n\n const sessions: ChatSessionListEntry[] = []\n const refused: RefusedChatSessionFile[] = []\n\n for (const file of [...files].sort()) {\n if (!file.endsWith(SESSION_FILE_SUFFIX)) continue\n const sessionId = file.slice(0, -SESSION_FILE_SUFFIX.length)\n try {\n const scanned = scanSessionFile(fs, join(sessionsRoot, file))\n if (scanned.headerLine === undefined) {\n refused.push({ file, reason: 'it carries no complete header line' })\n continue\n }\n const header = guardHeader(sessionId, scanned.headerLine)\n sessions.push({\n sessionId: header.sessionId,\n createdAt: header.createdAt,\n model: header.model,\n eventCount: Math.max(scanned.lineCount - 1, 0),\n })\n } catch (error) {\n refused.push({ file, reason: error instanceof Error ? error.message : String(error) })\n }\n }\n\n return { sessions, refused }\n}\n\n/**\n * One pass over a session file: its first line, and how many complete lines it has.\n *\n * Constant memory by construction — one reused chunk buffer, no accumulation past the header line,\n * and NO EVENT IS EVER PARSED. A listing that guarded every line would be `open()` wearing a\n * cheaper name, and would inherit `open()`'s right to refuse a whole session over one damaged line.\n */\nfunction scanSessionFile(\n fs: ChatSessionFs,\n path: string,\n): { headerLine: string | undefined; lineCount: number } {\n const fd = fs.openSync(path, 'r')\n try {\n const buffer = Buffer.allocUnsafe(CHAT_SESSION_READ_CHUNK_BYTES)\n let headerLine: string | undefined\n let headerBytes = ''\n let lineCount = 0\n let read = fs.readSync(fd, buffer, 0, buffer.length, null)\n while (read > 0) {\n const chunk = buffer.subarray(0, read)\n for (let index = 0; index < chunk.length; index += 1) {\n if (chunk[index] === 0x0a) lineCount += 1\n }\n if (headerLine === undefined) {\n headerBytes += chunk.toString('utf8')\n const newline = headerBytes.indexOf('\\n')\n if (newline >= 0) headerLine = headerBytes.slice(0, newline)\n // A \"header\" longer than one chunk is not a header this build wrote; stop accumulating so\n // one damaged file cannot be read into memory in its entirety by a listing.\n else if (headerBytes.length > CHAT_SESSION_READ_CHUNK_BYTES) break\n }\n read = fs.readSync(fd, buffer, 0, buffer.length, null)\n }\n return { headerLine, lineCount }\n } finally {\n fs.closeSync(fd)\n }\n}\n\nexport function createJsonlSessionLog(options: CreateJsonlSessionLogOptions): SessionLogPort {\n return createJsonlSessionLogOn(REAL_CHAT_SESSION_FS, options)\n}\n\n/**\n * The same log over an injected filesystem. TEST SEAM — production uses the factory above.\n *\n * It exists because the syscall ORDER is the durability property and no crash test can observe it\n * (the kernel does not drop pages it already holds when a process dies). Keeping it a separate\n * function rather than an optional field means a production construction cannot reach it by filling\n * in one more property, and keeping it off this package's barrel means no other package can reach\n * it at all. A test asserts that nothing outside `__tests__` calls it.\n */\nexport function createJsonlSessionLogOn(\n fs: ChatSessionFs,\n options: CreateJsonlSessionLogOptions,\n): SessionLogPort {\n if (!isAbsolute(options.root)) {\n throw new TypeError('chat session log root must be absolute')\n }\n const sessionsRoot = join(options.root, CHAT_SESSIONS_SUBDIR)\n const random = options.random ?? Math.random\n\n // THE WHOLE OF THE RE-KEYING (392-12, CR-01). What used to be `let fd` — one descriptor for the\n // adapter, repointed by whichever `open()` ran last — is a map from SESSION ID to the descriptor\n // that session's handle owns. Nothing here is \"current\": an adapter serving two conversations\n // holds two entries and no opinion about which of them a given caller means, because a caller\n // never asks. It holds its handle.\n const liveDescriptors = new Map<string, number>()\n\n function pathFor(sessionId: string): string {\n return join(sessionsRoot, `${sessionId}.jsonl`)\n }\n\n function bestEffortFsyncDirectory(dir: string): void {\n let directoryFd: number | undefined\n try {\n directoryFd = fs.openSync(dir, 'r')\n fs.fsyncSync(directoryFd)\n } catch (error) {\n if (!isSwallowableDirectoryFsyncError(error)) throw error\n } finally {\n if (directoryFd !== undefined) fs.closeSync(directoryFd)\n }\n }\n\n function readLines(\n sessionId: string,\n ): { lines: { lineNumber: number; text: string }[]; terminated: boolean } | undefined {\n let text: string\n try {\n text = fs.readFileSync(pathFor(sessionId), 'utf8')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined\n throw error\n }\n return {\n // Line numbers are 1-based and count the header, so a refusal names what an editor shows the\n // person who has to go and look at the file.\n lines: text\n .split('\\n')\n .map((line, index) => ({ lineNumber: index + 1, text: line }))\n .filter((line) => line.text !== ''),\n // Every line this adapter writes ends in a newline, so a file that does not is a file whose\n // last write was cut short. That fact cannot be recovered once the lines are split, and the\n // append path needs it BEFORE it writes anything (see `terminateTornTail`).\n terminated: text === '' || text.endsWith('\\n'),\n }\n }\n\n function writeEvent(target: number, event: ChatSessionEvent): void {\n // One JSON document per line, written through an `O_APPEND` fd so the kernel places it at the\n // end of file. No offset is tracked here, which is what makes a second writer's line impossible\n // to interleave with a partial one of ours.\n fs.writeFileSync(target, `${JSON.stringify(event)}\\n`, 'utf8')\n }\n\n /**\n * One session's handle, closing over the descriptor THAT session's open produced.\n *\n * The descriptor is a closure variable of one handle rather than a field of the adapter, which is\n * the structural statement of the contract: there is no expression anywhere in this module that\n * reaches another session's fd, so no interleaving of two callers' awaits can produce one.\n */\n function handleFor(\n id: string,\n fd: number,\n opened: OpenedChatSession,\n ): ChatSessionHandle {\n let live = true\n const requireLive = (verb: string): void => {\n if (!live) {\n throw new TypeError(\n `a chat session ${verb} cannot go through a closed handle for ${id}. Open the session `\n + 'again to write to it.',\n )\n }\n }\n const handle: ChatSessionHandle = {\n header: opened.header,\n events: opened.events,\n refusedLines: opened.refusedLines,\n append(event: ChatSessionEvent): Promise<void> {\n requireLive('event')\n writeEvent(fd, event)\n return Promise.resolve()\n },\n turnBoundary(): Promise<void> {\n // A REFUSAL rather than a silent no-op: a boundary that quietly skipped its fsync would\n // report a durability guarantee it did not buy, which is the one lie this file is built\n // to make impossible.\n requireLive('turn boundary')\n fs.fsyncSync(fd)\n return Promise.resolve()\n },\n close(): Promise<void> {\n // Idempotent, so a caller's `finally` may call it unconditionally — the turn engine's does.\n if (live) {\n live = false\n liveDescriptors.delete(id)\n fs.closeSync(fd)\n }\n return Promise.resolve()\n },\n }\n liveDescriptors.set(id, fd)\n return handle\n }\n\n return {\n open(sessionId?: string): Promise<ChatSessionHandle> {\n fs.mkdirSync(sessionsRoot, { recursive: true })\n\n if (sessionId !== undefined) {\n const id = requireSessionId(sessionId)\n // BEFORE ANY WORK, and before any byte is read: a busy session is a refusal, not a second\n // descriptor. Asked first so a double-submit costs a caller nothing but the answer.\n if (liveDescriptors.has(id)) throw new ChatSessionBusyError(id)\n const read = readLines(id)\n // The refusal, not a create. See `UnknownChatSessionError`.\n if (read === undefined || read.lines.length === 0) throw new UnknownChatSessionError(id)\n const header = guardHeader(id, read.lines[0]!.text)\n // REPAIR BEFORE ANY CALLER SEES AN EVENT (CHAT-05). The declared version travels as an\n // argument, taken off the header this path has just validated — the log states its version\n // once and no line restates it (392-01's decision, unchanged).\n const repair = repairSession(read.lines.slice(1), {\n declaredVersion: header.schemaVersion,\n now: options.now,\n })\n const resumed = fs.openSync(pathFor(id), 'a')\n // TERMINATE A TORN TAIL BEFORE APPENDING ANYTHING. A crash leaves the last line without\n // its newline, so the very next append would land ON that fragment and fuse two records\n // into one unreadable line — turning a bounded, understood loss into permanent damage\n // that the next open would mistake for a fresh tear and lose all over again. One newline\n // closes the fragment where it stopped. It is still an APPEND: no existing byte moves,\n // and the fragment survives verbatim as its own refused line for anyone auditing the file.\n let wroteDuringRepair = false\n if (!read.terminated) {\n fs.writeFileSync(resumed, '\\n', 'utf8')\n wroteDuringRepair = true\n }\n for (const event of repair.synthesized) {\n writeEvent(resumed, event)\n wroteDuringRepair = true\n }\n if (wroteDuringRepair) {\n // A repair CLOSES the dangling turn, so it lands like any other turn boundary. A\n // synthesized abort a second crash could lose would leave the same session dangling\n // again, and the loss bound would stop being the in-flight turn.\n fs.fsyncSync(resumed)\n }\n return Promise.resolve(\n handleFor(id, resumed, {\n header,\n events: repair.repaired,\n refusedLines: repair.refusedLines,\n }),\n )\n }\n\n const createdAt = options.now()\n const id = mintChatSessionId(createdAt, random)\n const header: ChatSessionHeader = {\n schemaVersion: CURRENT_CHAT_SESSION_SCHEMA_VERSION,\n sessionId: id,\n createdAt,\n model: options.model(),\n toolsetHash: options.toolsetHash(),\n // CONDITIONALLY SPREAD, on the composition's own idiom (400-01) and for its reason: an\n // unconditional `surface: options.surface` would put `\"surface\":undefined` through\n // `JSON.stringify` — which drops it — but would also make an explicit `undefined` and an\n // unsupplied option two spellings of one state at every call site above. Absent here means\n // the option was never given, and that is exactly the pre-400 population's meaning.\n ...(options.surface === undefined ? {} : { surface: options.surface }),\n }\n // Exclusive create, then fsync the header BEFORE the file is used, then fsync the directory\n // that now names it: a session file that exists at all is a session file whose header is on\n // the device, and whose entry survives the crash that follows.\n const created = fs.openSync(pathFor(id), 'wx')\n try {\n fs.writeFileSync(created, `${JSON.stringify(header)}\\n`, 'utf8')\n fs.fsyncSync(created)\n } finally {\n fs.closeSync(created)\n }\n bestEffortFsyncDirectory(sessionsRoot)\n const appendFd = fs.openSync(pathFor(id), 'a')\n return Promise.resolve(handleFor(id, appendFd, { header, events: [], refusedLines: [] }))\n },\n }\n}\n","// Per-job checkpoint files for the agent job queue (Phase 385, D-01 / JOBQ-05).\n//\n// Under the hybrid split, sqlite owns the job LIFECYCLE and each checkpoint is its own file\n// under `.agent-qa/agent-jobs/checkpoints/<jobId>/<checkpointId>.json`. Three reasons, in\n// order of weight: JOBQ-05 asks literally for a rename with a parent-directory fsync;\n// authored model output can be large and does not belong in a row a claim transaction has\n// to move past; and a checkpoint that guards a filesystem side effect should be durable in\n// the same medium as the thing it guards, or the two can disagree after a crash.\n//\n// The publish sequence and its error allowlist are generalized verbatim from v51's\n// per-candidate intent journal (knowledge-local, journal/intent-journal.ts). It is not\n// reinvented here: the allowlist below encodes platform quirks already debugged once, and\n// re-deriving it by hand is how a directory fsync silently becomes best-effort everywhere.\n//\n// 385 plan 03 added the OBSERVATION SEAM the ordering proof needs. Killing a process does\n// not drop the pages the kernel already holds, so a publisher missing an fsync passes every\n// crash test run on one machine; the only way to know the sequence is right is to watch the\n// calls. The seam is deliberately shaped so it cannot become a way to skip a sync in\n// production: `CreateJobCheckpointStoreOptions` has no filesystem member, so no production\n// call site has anywhere to put one, and the seam factory is a second exported function that\n// a test names explicitly. A test asserts nothing outside `__tests__` ever calls it.\n\nimport { randomUUID } from 'node:crypto'\nimport {\n closeSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n rmSync,\n writeFileSync,\n} from 'node:fs'\nimport { dirname, isAbsolute, join } from 'node:path'\n\nimport {\n canonicalJson,\n asJobId,\n JOB_CHECKPOINT_SCHEMA_VERSION,\n jobCheckpointEnvelopeSchema,\n} from '@vostride/agent-qa-schema'\nimport type { JobCheckpointEnvelope } from '@vostride/agent-qa-schema'\n\nimport {\n InvalidJobCheckpointIdError,\n JobCheckpointSchemaVersionError,\n} from './store-errors.js'\n\n/** Directory segments under the agent-qa root, per the D-21 \"agent job queue\" naming. */\nexport const JOB_CHECKPOINT_SUBDIR = ['agent-jobs', 'checkpoints'] as const\n\n/**\n * Ids that are safe as a single path segment.\n *\n * Leading dots are excluded, so `..` cannot be an id at all, and the class admits no\n * separator on any platform.\n */\nconst SAFE_PATH_SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/\n\n/**\n * The errno set a parent-directory fsync may legitimately fail with.\n *\n * Copied code for code from v51 rather than re-derived. Each entry is a platform or\n * filesystem on which syncing a directory descriptor is either unsupported or meaningless;\n * anything else is a real I/O failure and must not be swallowed, or the \"best effort\" in\n * `bestEffortFsyncDirectory` quietly becomes \"no effort\" everywhere.\n */\nexport const DIRECTORY_FSYNC_SWALLOWED_CODES = [\n 'ENOENT',\n 'EINVAL',\n 'EISDIR',\n 'EPERM',\n 'ENOTSUP',\n] as const\n\n/**\n * Exactly the filesystem calls this module makes, and nothing else.\n *\n * Narrow on purpose. A wide facade invites a test to answer on its own behalf; this one is\n * small enough that the only reasonable implementation besides the real functions is a\n * recorder that calls through to them.\n */\nexport interface JobCheckpointFs {\n mkdirSync(path: string, options: { readonly recursive: true }): void\n openSync(path: string, flags: 'wx' | 'r'): number\n writeFileSync(fd: number, data: string, encoding: 'utf8'): void\n fsyncSync(fd: number): void\n closeSync(fd: number): void\n renameSync(from: string, to: string): void\n rmSync(path: string, options: { readonly force: true }): void\n readFileSync(path: string, encoding: 'utf8'): string\n}\n\n/** The production implementation, frozen so it cannot be patched from a distance. */\nexport const REAL_JOB_CHECKPOINT_FS: JobCheckpointFs = Object.freeze({\n mkdirSync,\n openSync,\n writeFileSync,\n fsyncSync,\n closeSync,\n renameSync,\n rmSync,\n readFileSync,\n})\n\nexport interface JobCheckpointStore {\n publish(jobId: string, checkpointId: string, payload: unknown): void\n read(jobId: string, checkpointId: string): { found: false } | { found: true; payload: unknown }\n /**\n * Remove one published checkpoint file (413-13).\n *\n * The file is a CACHE of the fenced sqlite record, and this verb exists only so the cache\n * cannot outlive the record it caches: an operator requeue deletes the authoritative rows,\n * and a file left behind would keep answering the logical dump's digest with a checkpoint\n * no row backs. It never affects recovery in either direction — `readCheckpoint` finds no\n * row and answers `found: false` before it ever consults a file — so a discard that failed\n * to happen would be a dump artifact, not a resumed stand-in.\n *\n * Exactly one file, never a directory and never recursively. An empty per-job directory is\n * harmless and keeping it that way keeps the filesystem facade as narrow as it is.\n */\n discard(jobId: string, checkpointId: string): void\n /** Exposed so a test can assert on the real file, not on a reader that could agree. */\n checkpointPath(jobId: string, checkpointId: string): string\n /** The directory the deterministic logical dump digests (D-03). */\n readonly checkpointsRoot: string\n}\n\n/**\n * What a production caller supplies: a root, and nothing else.\n *\n * The absence here is the guarantee. There is no filesystem member, so \"publish without the\n * fsync\" is not a one-argument change any composition root could make by accident.\n */\nexport interface CreateJobCheckpointStoreOptions {\n /** Absolute path to the agent-qa runtime root, typically `<project>/.agent-qa`. */\n readonly root: string\n}\n\nfunction requireSegment(field: 'jobId' | 'checkpointId', value: string): string {\n if (!SAFE_PATH_SEGMENT.test(value)) {\n throw new InvalidJobCheckpointIdError(field, value)\n }\n return value\n}\n\nfunction checkpointPath(root: string, jobId: string, checkpointId: string): string {\n if (!isAbsolute(root)) throw new TypeError('agent job checkpoint root must be absolute')\n return join(root, ...JOB_CHECKPOINT_SUBDIR, requireSegment('jobId', jobId),\n `${requireSegment('checkpointId', checkpointId)}.json`)\n}\n\nfunction readEnvelopeOn(\n fs: Pick<JobCheckpointFs, 'readFileSync'>,\n root: string,\n jobId: string,\n checkpointId: string,\n): { found: false } | { found: true; envelope: JobCheckpointEnvelope } {\n const file = checkpointPath(root, jobId, checkpointId)\n let text: string\n try {\n text = fs.readFileSync(file, 'utf8')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return { found: false }\n throw error\n }\n const raw = JSON.parse(text) as { schemaVersion?: unknown } | null\n // Preserve the named version refusal before structural validation.\n if (raw?.schemaVersion !== JOB_CHECKPOINT_SCHEMA_VERSION) {\n throw new JobCheckpointSchemaVersionError(file, raw?.schemaVersion)\n }\n const envelope = jobCheckpointEnvelopeSchema.parse(raw)\n if (envelope.jobId !== jobId || envelope.checkpointId !== checkpointId) {\n throw new TypeError('Agent job checkpoint envelope does not match its address')\n }\n return { found: true, envelope }\n}\n\n/** Cold read only: no store construction, directory creation or checkpoint publication. */\nexport function readJobCheckpointEnvelope(\n options: CreateJobCheckpointStoreOptions,\n jobId: string,\n checkpointId: string,\n): { found: false } | { found: true; envelope: JobCheckpointEnvelope } {\n return readEnvelopeOn(REAL_JOB_CHECKPOINT_FS, options.root, jobId, checkpointId)\n}\n\nfunction isSwallowableDirectoryFsyncError(error: unknown): boolean {\n const code = (error as NodeJS.ErrnoException).code\n return DIRECTORY_FSYNC_SWALLOWED_CODES.some((allowed) => allowed === code)\n}\n\nexport function createJobCheckpointStore(\n options: CreateJobCheckpointStoreOptions,\n): JobCheckpointStore {\n return createJobCheckpointStoreOn(REAL_JOB_CHECKPOINT_FS, options)\n}\n\n/**\n * The same store over an injected filesystem. TEST SEAM — production uses the factory above.\n *\n * It exists because the syscall ORDER is the durability property and no crash test can\n * observe it. Keeping it a separate function, rather than an optional field on the\n * production options, means a production construction cannot reach it by filling in one more\n * property; a test asserts that no non-test file in the workspace names it.\n */\nexport function createJobCheckpointStoreOn(\n fs: JobCheckpointFs,\n options: CreateJobCheckpointStoreOptions,\n): JobCheckpointStore {\n if (!isAbsolute(options.root)) {\n throw new TypeError('agent job checkpoint root must be absolute')\n }\n\n const checkpointsRoot = join(options.root, ...JOB_CHECKPOINT_SUBDIR)\n\n function pathFor(jobId: string, checkpointId: string): string {\n return checkpointPath(options.root, jobId, checkpointId)\n }\n\n function bestEffortFsyncDirectory(dir: string): void {\n let fd: number | undefined\n try {\n fd = fs.openSync(dir, 'r')\n fs.fsyncSync(fd)\n } catch (error) {\n if (!isSwallowableDirectoryFsyncError(error)) {\n throw error\n }\n } finally {\n if (fd !== undefined) fs.closeSync(fd)\n }\n }\n\n return {\n checkpointsRoot,\n checkpointPath: pathFor,\n\n publish(jobId, checkpointId, payload) {\n const file = pathFor(jobId, checkpointId)\n // Typed as the shipped envelope contract rather than as an ad-hoc literal (385 plan\n // 02): the bytes this writes are the bytes the contract describes, so a field added on\n // one side and forgotten on the other stops compiling instead of shipping.\n const envelope: JobCheckpointEnvelope = {\n schemaVersion: JOB_CHECKPOINT_SCHEMA_VERSION,\n jobId: asJobId(jobId),\n checkpointId,\n payload,\n }\n fs.mkdirSync(dirname(file), { recursive: true })\n const temporary = `${file}.tmp-${randomUUID()}`\n let fd: number | undefined\n try {\n // Exclusive create, so a torn temporary from an earlier crash can never be mistaken\n // for this one's; then fsync the fd BEFORE the rename, so the rename can only\n // publish bytes that are already on the device.\n fd = fs.openSync(temporary, 'wx')\n fs.writeFileSync(fd, `${canonicalJson(envelope)}\\n`, 'utf8')\n fs.fsyncSync(fd)\n fs.closeSync(fd)\n fd = undefined\n fs.renameSync(temporary, file)\n // The rename itself is a directory mutation, and a directory entry is not durable\n // until its parent is synced — this is the line JOBQ-05 names.\n bestEffortFsyncDirectory(dirname(file))\n } finally {\n if (fd !== undefined) fs.closeSync(fd)\n fs.rmSync(temporary, { force: true })\n }\n },\n\n discard(jobId, checkpointId) {\n // `pathFor` validates BOTH segments against `SAFE_PATH_SEGMENT` before they are joined,\n // so a crafted id is refused by name rather than reaching `rmSync` as a traversal.\n fs.rmSync(pathFor(jobId, checkpointId), { force: true })\n },\n\n read(jobId, checkpointId) {\n const read = readEnvelopeOn(fs, options.root, jobId, checkpointId)\n return read.found ? { found: true, payload: read.envelope.payload } : read\n },\n }\n}\n","// Every named refusal the agent job queue's local store raises (Phase 385 plan 03).\n//\n// The rule this module exists to state, because a small package with two error files and no\n// rule for which one gets what is how a vocabulary forks: a refusal DECLARED here is one the\n// storage implementation owns, and a refusal the PORT owns is re-exported here rather than\n// re-declared. `StaleJobStoreEpochError` is the second case — 386 binds the real writer lease\n// to that exact class, so a second class in this package meaning the same condition would\n// hand one situation two identities and make the binding a choice instead of a wiring.\n//\n// Shapes follow v51's writer-lease convention: `override readonly name`, the observed value\n// attached as a field, and a message that names a remedy rather than a symptom.\n\nimport { JOB_CHECKPOINT_SCHEMA_VERSION } from '@vostride/agent-qa-schema'\n\n// Both are the second case the rule above describes: the PORT declares them, this module\n// re-exports them. `QuarantinedJobRequeueError` is a condition of the requeue CONTRACT — every\n// store that implements `requeueTerminal` owes the same refusal — so a second class declared here\n// would let two stores disagree about what an operator is being told.\nexport { QuarantinedJobRequeueError, StaleJobStoreEpochError } from '@vostride/agent-qa-agent'\n\n/**\n * The database on disk was written by a build that does not agree with this one (D-04).\n *\n * There is no migration machinery in the agent job queue and there is not meant to be: the\n * milestone ships nothing between releases, so a version that does not match is a development\n * artifact, not a user's history. The message therefore carries the remedy — clear agent job\n * queue state — since an operator reading it can act on that and cannot act on a version number\n * alone. The remedy names WHICH queue because three of them coexist (D-21): an operator told to\n * \"clear queue state\" could reasonably clear the curation queue instead.\n */\nexport class JobStoreSchemaVersionError extends Error {\n override readonly name = 'JobStoreSchemaVersionError'\n\n constructor(\n readonly path: string,\n readonly expectedVersion: number,\n readonly observedVersion: number,\n ) {\n super(\n `The agent job store at ${path} is stamped at schema version ${observedVersion}, but ` +\n `this build reads version ${expectedVersion}. There is no migration machinery by ` +\n 'design — clear agent job queue state (delete the agent job database and its ' +\n 'checkpoint directory) and re-enqueue.',\n )\n }\n}\n\n/** A job id that no row answers to. */\nexport class UnknownJobRowError extends Error {\n override readonly name = 'UnknownJobRowError'\n\n constructor(readonly jobId: string) {\n super(`No agent job row with id ${jobId}`)\n }\n}\n\n/**\n * An id that cannot safely become one path segment.\n *\n * Validated BEFORE any join, following the v51 candidate-id precedent: a job id and a\n * checkpoint id both become directory and file names, and an id validated after joining has\n * already escaped.\n */\nexport class InvalidJobCheckpointIdError extends Error {\n override readonly name = 'InvalidJobCheckpointIdError'\n\n constructor(\n readonly field: 'jobId' | 'checkpointId',\n readonly value: string,\n ) {\n super(\n `Unusable ${field} for a checkpoint path: ${JSON.stringify(value)}. A checkpoint id ` +\n 'becomes a path segment, so it is validated before the path is built rather than ' +\n 'after.',\n )\n }\n}\n\n/** A checkpoint file written at a layout version this build does not read (D-04). */\nexport class JobCheckpointSchemaVersionError extends Error {\n override readonly name = 'JobCheckpointSchemaVersionError'\n\n constructor(\n readonly path: string,\n readonly observedVersion: unknown,\n ) {\n super(\n `Agent job checkpoint ${path} was written at schema version ${String(observedVersion)}, ` +\n `but this build reads version ${JOB_CHECKPOINT_SCHEMA_VERSION}. There is no migration ` +\n 'machinery by design — clear agent job queue state and re-enqueue.',\n )\n }\n}\n","// The durable chip-truth read (Phase 388, D-14 / RESEARCH Pitfall 4).\n//\n// A status query must be able to answer \"what became of that run's analysis\" from a cold\n// process with no socket held, and it must be able to do so WITHOUT changing anything —\n// including whether a queue exists at all.\n//\n// That second half is the whole reason this module exists rather than the read going through\n// `host.jobs()`. Opening the store CREATES `agent-jobs.db` and the checkpoint directory; that\n// is why `jobs()` is deferred in the first place. Routing a status read through it would mean\n// a project that has never enqueued anything grows a queue database the moment somebody asks\n// whether it has one — an observation that changes what it observes. So the file is checked for\n// existence FIRST, and opened READ-ONLY when it is there: two independent reasons the read\n// cannot bring state into being, because one of them is a check somebody could later move.\n//\n// Reads are fence-free by design. Reading claims no authority, so this neither adopts an epoch\n// nor competes with whichever process holds one — a status query beside a live daemon drain is\n// an ordinary concurrent reader on a WAL database, which is exactly what WAL is for.\n\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { DatabaseSync } from 'node:sqlite'\n\nimport { canonicalJson, CurationSnapshotSchema, guardRunNotification, isJobKind, sha256hex } from '@vostride/agent-qa-schema'\nimport type { JobConclusionKind, JobStatus, RunNotification } from '@vostride/agent-qa-schema'\nimport type {\n ChainJobIds,\n JobIdSource,\n PostProcessingChainState,\n PostProcessingJobRow,\n PostProcessingReaderPort,\n} from '@vostride/agent-qa-agent'\n\nimport {\n AGENT_JOB_STORE_BUSY_TIMEOUT_MS,\n AGENT_JOB_STORE_DB_FILE,\n AGENT_JOB_STORE_USER_VERSION,\n QUARANTINED_UNREADABLE_KIND_REASON,\n} from './sqlite-job-store.js'\nimport { JobStoreSchemaVersionError } from './store-errors.js'\nimport { readJobCheckpointEnvelope } from './job-checkpoint-store.js'\n\n/** Invalid authoritative checkpoint facts cannot be presented as an empty curation. */\nexport class CurationSnapshotReadError extends Error {\n override readonly name = 'CurationSnapshotReadError'\n\n constructor() {\n // No persisted prose or payload values in a read failure: they have not crossed MaskFn.\n super('The recorded curation checkpoint is invalid; its snapshot cannot be read.')\n }\n}\n\nfunction recordOf(value: unknown): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new CurationSnapshotReadError()\n }\n return value as Record<string, unknown>\n}\n\nfunction readCurationSnapshot(\n db: DatabaseSync,\n root: string,\n ids: ChainJobIds,\n runId: string,\n): PostProcessingChainState['curationSnapshot'] {\n const checkpointId = 'bundle-committed'\n // Match the store's latest fenced row. Files alone cannot resurrect a requeued checkpoint.\n const row = db.prepare(`SELECT payload_json, payload_digest, attempt FROM job_checkpoints\n WHERE job_id = ? AND checkpoint_id = ? ORDER BY attempt DESC LIMIT 1`)\n .get(String(ids.curateMemory), checkpointId)\n if (row === undefined) return undefined\n try {\n const authoritative: unknown = JSON.parse(String(row.payload_json))\n if (sha256hex(canonicalJson(authoritative)) !== row.payload_digest) {\n throw new CurationSnapshotReadError()\n }\n let payload = authoritative\n try {\n const cached = readJobCheckpointEnvelope({ root }, String(ids.curateMemory), checkpointId)\n if (cached.found && sha256hex(canonicalJson(cached.envelope.payload)) === row.payload_digest) {\n payload = cached.envelope.payload\n }\n } catch {\n // Like sqlite-job-store.readCheckpoint: a damaged cache cannot overrule the fenced row.\n }\n const checkpoint = recordOf(payload)\n if (checkpoint.jobId !== ids.curateMemory || checkpoint.checkpointId !== checkpointId\n || checkpoint.attempt !== Number(row.attempt) || !Number.isInteger(checkpoint.attempt)\n || Number(checkpoint.attempt) < 1 || typeof checkpoint.recordedAt !== 'string'\n || checkpoint.recordedAt.length === 0) throw new CurationSnapshotReadError()\n const value = recordOf(checkpoint.value)\n if (value.curationSnapshot === undefined) return undefined\n const job = db.prepare('SELECT kind, idempotency_key, payload, attempts FROM jobs WHERE id = ?')\n .get(String(ids.curateMemory))\n if (job === undefined || job.kind !== 'curate-memory'\n || job.idempotency_key !== `${ids.analyzeRun}->curate-memory`\n || Number(job.attempts) < Number(checkpoint.attempt)\n || recordOf(JSON.parse(String(job.payload))).runId !== runId\n || value.runId !== runId) throw new CurationSnapshotReadError()\n return CurationSnapshotSchema.parse(value.curationSnapshot)\n } catch {\n throw new CurationSnapshotReadError()\n }\n}\n\nexport interface CreatePostProcessingReaderOptions {\n /** The project's runtime root, i.e. `<configDir>/.agent-qa`. Absolute. */\n readonly agentQaRoot: string\n /**\n * The id source THIS host's queue enqueues through.\n *\n * REQUIRED rather than defaulted to the production digest source, and the requirement is the\n * guarantee: the composition hands the reader the very source it built the queue with, so the\n * ids projected and the ids enqueued cannot be two different derivations. A reader that\n * defaulted would silently address other rows in any composition that configured its own\n * source, and would report `pending` about a chain that had already finished.\n */\n readonly idSource: JobIdSource\n}\n\nfunction toNumber(value: unknown): number {\n return typeof value === 'bigint' ? Number(value) : Number(value)\n}\n\nfunction toRow(row: Record<string, unknown> | undefined): PostProcessingJobRow | undefined {\n if (row === undefined) return undefined\n // The job store has no conclusion column. Match sqlite-job-store's quarantineConclusionOf:\n // only the complete recorded quarantine landing supports this conclusion (422 D-16).\n const conclusionKind: JobConclusionKind | undefined =\n !isJobKind(String(row.kind))\n && row.status === 'failed'\n && row.last_failure_kind === 'permanent'\n && row.last_failure_reason === QUARANTINED_UNREADABLE_KIND_REASON\n ? 'unreadable_kind'\n : undefined\n return {\n status: String(row.status) as JobStatus,\n claimed: row.claimed_at !== null,\n attempts: toNumber(row.attempts),\n createdAt: String(row.created_at),\n updatedAt: String(row.updated_at),\n ...(row.claimed_at === null ? {} : { claimedAt: String(row.claimed_at) }),\n ...(row.started_at === null ? {} : { startedAt: String(row.started_at) }),\n ...(conclusionKind === undefined ? {} : { conclusionKind }),\n ...(row.last_failure_kind === null ? {} : { lastFailureKind: String(row.last_failure_kind) }),\n ...(row.last_failure_reason === null ? {} : { lastFailureReason: String(row.last_failure_reason) }),\n }\n}\n\n/**\n * Bind the `runs.postprocessing` port over this project's queue database.\n *\n * The port's own contract forbids materializing anything, and this implementation honours it\n * structurally rather than carefully: `existsSync` short-circuits before a handle is\n * constructed, and the handle that would be constructed is read-only, which refuses to create\n * a file even if the check were removed.\n */\nexport function createPostProcessingReader(\n options: CreatePostProcessingReaderOptions,\n): PostProcessingReaderPort {\n const path = join(options.agentQaRoot, AGENT_JOB_STORE_DB_FILE)\n\n return {\n idSource: options.idSource,\n\n async readChain(\n ids: ChainJobIds,\n runId: string,\n ): Promise<PostProcessingChainState | undefined> {\n // Pitfall 4, stated as the first line of the read: no database, no chain, nothing\n // created. `undefined` rather than an empty state, because the two are different facts\n // and the projection is entitled to know which one it is looking at.\n if (!existsSync(path)) return undefined\n\n const db = new DatabaseSync(path, {\n readOnly: true,\n timeout: AGENT_JOB_STORE_BUSY_TIMEOUT_MS,\n })\n try {\n // The same stamp-and-refuse gate the writer applies (385 D-04). A database another\n // build wrote is bytes this one cannot read, and answering `pending` from it would be\n // indistinguishable from a run that was never enqueued — which is the silent widening\n // the version stamp exists to refuse. A fresh, never-stamped file reads 0 and is\n // treated as readable-but-empty rather than refused: it holds no rows to misread.\n const stamped = toNumber(db.prepare('PRAGMA user_version').get()?.user_version)\n if (stamped !== 0 && stamped !== AGENT_JOB_STORE_USER_VERSION) {\n throw new JobStoreSchemaVersionError(path, AGENT_JOB_STORE_USER_VERSION, stamped)\n }\n\n const selectJob = db.prepare(`\n SELECT kind, status, attempts, created_at, claimed_at, started_at, updated_at,\n last_failure_kind, last_failure_reason\n FROM jobs WHERE id = ?\n `)\n const notificationRow = db\n .prepare('SELECT payload FROM notifications WHERE run_id = ?')\n .get(runId) as Record<string, unknown> | undefined\n\n const analyzeRun = toRow(\n selectJob.get(String(ids.analyzeRun)) as Record<string, unknown> | undefined,\n )\n const curateMemory = toRow(\n selectJob.get(String(ids.curateMemory)) as Record<string, unknown> | undefined,\n )\n const proposeImprovements = toRow(\n selectJob.get(String(ids.proposeImprovements)) as Record<string, unknown> | undefined,\n )\n // Parsed through the schema guard on the way out, like `listNotifications`: the column\n // is bytes another process wrote, and a record that lost a stage must not travel as a\n // `RunNotification` to a surface that renders it.\n const notification: RunNotification | undefined =\n notificationRow === undefined\n ? undefined\n : guardRunNotification(JSON.parse(String(notificationRow.payload)) as unknown)\n const curationSnapshot = readCurationSnapshot(db, options.agentQaRoot, ids, runId)\n\n // Absent members are OMITTED rather than set undefined, so the state a projection reads\n // says the same thing whether it was built here or by a test's literal.\n return {\n ...(analyzeRun === undefined ? {} : { analyzeRun }),\n ...(curateMemory === undefined ? {} : { curateMemory }),\n ...(proposeImprovements === undefined ? {} : { proposeImprovements }),\n ...(notification === undefined ? {} : { notification }),\n ...(curationSnapshot === undefined ? {} : { curationSnapshot }),\n }\n } finally {\n db.close()\n }\n },\n }\n}\n","// The agent job queue's durable lifecycle store (Phase 385, D-01 / D-02 / D-04 / D-08).\n//\n// Built on Node's own sqlite binding, so the queue adds ZERO runtime dependencies (JOBQ-02)\n// while still getting real transactions and a real unique index. Every compound verb of\n// `JobStorePort` is exactly one `BEGIN IMMEDIATE ... COMMIT` here: the binding is\n// synchronous, so a verb cannot interleave with another verb in this process, and\n// `BEGIN IMMEDIATE` plus a busy timeout covers the writer in the next process (D-02).\n// There is no transaction helper in the binding, so every one of them is written out and\n// the catch-block rollback is guarded on `isTransaction` — rolling back when no transaction\n// is open throws, which would replace the real error with a confusing one.\n//\n// One thing this file deliberately does NOT do is invent a claim STATUS. `JobStatus` is a\n// shipped kernel vocabulary that the C6 break extended by exactly two terminal members, and\n// a job in flight is not a new public state — it is a fact about who holds it. So the claim\n// lives in a `claimed_at` column the store owns, and the row's published status stays the\n// one the contract already names.\n\nimport { mkdirSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { DatabaseSync } from 'node:sqlite'\n\nimport {\n JobCancellationNotRequestedError,\n MissingIdempotencyKeyError,\n QuarantinedJobRequeueError,\n StaleJobStoreEpochError,\n} from '@vostride/agent-qa-agent'\nimport type {\n ChainTerminalRecord,\n ClaimNextOptions,\n ClockPort,\n JobCancelOutcome,\n JobCheckpointRecord,\n JobCheckpointReadOutcome,\n JobClaimOutcome,\n JobCompleteOutcome,\n JobEnqueueOutcome,\n JobFailureDisposition,\n JobInsert,\n JobRequeueOutcome,\n JobStoreDump,\n JobStoreDumpRow,\n JobStoreFence,\n JobStorePort,\n} from '@vostride/agent-qa-agent'\nimport {\n canonicalJson,\n guardRunNotification,\n isJobKind,\n jobSchema,\n sha256hex,\n} from '@vostride/agent-qa-schema'\nimport type {\n Job,\n JobConclusionKind,\n JobId,\n JobStatus,\n RunNotification,\n} from '@vostride/agent-qa-schema'\n\nimport type { JobCheckpointStore } from './job-checkpoint-store.js'\nimport { canonicalLogicalDump, createLogicalDump, selectOrderedRows } from './logical-dump.js'\nimport type { LogicalDump } from './logical-dump.js'\nimport { JobStoreSchemaVersionError, UnknownJobRowError } from './store-errors.js'\n\n/**\n * Stamped into `PRAGMA user_version` at creation and checked on every open (D-04).\n *\n * Stamp and hard-fail, never migrate. The milestone ships nothing between its releases, so a\n * database written by another build is a development artifact rather than a user's history,\n * and migration machinery for it would be code with no user that everything afterwards has\n * to keep working.\n */\nexport const AGENT_JOB_STORE_USER_VERSION = 2\n\n/**\n * Busy timeout for every connection to the job database.\n *\n * D-02's whole cross-process story is \"several processes write small transactions and\n * sqlite arbitrates\", which only works if a writer waiting on the write lock retries rather\n * than failing immediately. The binding's constructor `timeout` option is that retry\n * window.\n */\nexport const AGENT_JOB_STORE_BUSY_TIMEOUT_MS = 2000\n\n/** The store's own file name under the agent-qa root, per the D-21 naming. */\nexport const AGENT_JOB_STORE_DB_FILE = 'agent-jobs.db'\n\nexport interface CreateSqliteJobStoreOptions {\n /** Absolute path to the database file, typically `<root>/agent-jobs.db`. */\n readonly path: string\n readonly clock: ClockPort\n readonly checkpoints: JobCheckpointStore\n readonly timeoutMs?: number\n readonly hooks?: SqliteJobStoreHooks\n}\n\n/** Test-only observation points around cross-media publication. Production omits them. */\nexport interface SqliteJobStoreHooks {\n /** Runs after the fenced row commits and immediately before the checkpoint file is replaced. */\n readonly beforeCheckpointFilePublish?: () => void | Promise<void>\n}\n\n/** One chain-terminal notification row, with its payload guarded on the way out (388 D-09). */\nexport interface JobStoreNotification {\n readonly runId: string\n readonly payload: RunNotification\n readonly createdAt: string\n}\n\nexport interface SqliteJobStore extends JobStorePort {\n close(): void\n\n /**\n * The chain-terminal notifications this database holds, ordered by run.\n *\n * On the implementation rather than the neutral port, beside `logicalDump`, and for the\n * same reason: the port is the ENGINE's vocabulary and the engine never reads a\n * notification — it writes one, once, as part of ending a job. Every reader of these rows\n * is a surface, and 388 D-14 routes surfaces through the function layer, not through here.\n *\n * The payload is parsed through the schema guard rather than handed back as text: the\n * column is bytes another build could have written, and a row that lost a stage cannot be\n * allowed to travel as a `RunNotification`.\n */\n listNotifications(): Promise<readonly JobStoreNotification[]>\n\n /**\n * The D-03 comparison basis, in full: every table this database holds plus a digest per\n * checkpoint file.\n *\n * Kept beside `dumpState()` rather than replacing it, because the two answer different\n * questions and collapsing them would weaken both. `dumpState()` is the typed, engine-facing\n * projection of the job rows and it is part of the neutral port. This one is the storage\n * implementation's own full-state instrument: it knows about the checkpoint directory and\n * about tables the port has no vocabulary for, and it is the thing a crash comparison holds\n * up against another run.\n */\n logicalDump(): Promise<LogicalDump>\n\n /** The same dump as one comparable string. Byte equality here is state equality. */\n dumpLogicalState(): Promise<string>\n}\n\nconst SCHEMA_STATEMENTS = [\n `CREATE TABLE IF NOT EXISTS jobs (\n id TEXT PRIMARY KEY,\n kind TEXT NOT NULL,\n idempotency_key TEXT NOT NULL,\n status TEXT NOT NULL,\n summary TEXT NOT NULL,\n payload TEXT NOT NULL,\n attempts INTEGER NOT NULL,\n claimed_at TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n -- The disposition the engine DECIDED, recorded so a failed job says why it failed.\n -- Nullable because most rows never fail; written only by recordFailure.\n last_failure_kind TEXT,\n last_failure_reason TEXT,\n -- When somebody asked this job to stop (D-19). A column rather than a status, for the\n -- same reason the claim is one: the job status vocabulary describes lifecycle stages,\n -- and \"still queued, but asked to stop\" is a fact about a request, not a stage.\n -- Appended LAST deliberately - a column inserted in the middle would move every\n -- positional read of this table for no gain.\n cancel_requested_at TEXT,\n -- The instant this row was FIRST claimed, kept after the lease is released (425). The\n -- claim column answers who holds the row now; no column answered how long the work took.\n -- Written once by the claim, cleared only by the operator requeue. Appended last, as above.\n started_at TEXT,\n -- 444.1 D-23: a retrying row is not claimable before this instant. Appended last, as above.\n not_before TEXT\n )`,\n // D-08's dedupe is THIS line. Making it a store-level constraint rather than a check the\n // caller performs is what turns \"two enqueues of the same work produce one job\" from a\n // convention into something no caller, in any process, can get wrong.\n `CREATE UNIQUE INDEX IF NOT EXISTS jobs_kind_idempotency_key\n ON jobs (kind, idempotency_key)`,\n `CREATE TABLE IF NOT EXISTS job_store_fence (\n id INTEGER PRIMARY KEY CHECK (id = 1),\n epoch INTEGER NOT NULL\n )`,\n // The row is the authoritative checkpoint. The file remains a durable projection for\n // cross-process observability, but recovery accepts its bytes only when their digest agrees\n // with the latest fenced row for this job/checkpoint. Attempt stays in the key so retries\n // preserve their recorded history while a same-attempt takeover replaces only that attempt.\n `CREATE TABLE IF NOT EXISTS job_checkpoints (\n job_id TEXT NOT NULL,\n checkpoint_id TEXT NOT NULL,\n attempt INTEGER NOT NULL,\n payload_json TEXT NOT NULL,\n payload_digest TEXT NOT NULL,\n epoch INTEGER NOT NULL,\n PRIMARY KEY (job_id, attempt, checkpoint_id)\n )`,\n // 388 D-09: the chain-terminal record, beside the jobs it summarizes rather than in a\n // second durable medium. `created_at` is written from the injected clock like every other\n // timestamp in this file — a SQL-side default would leak host time into the D-03 dump and\n // make two identical histories compare unequal.\n `CREATE TABLE IF NOT EXISTS notifications (\n run_id TEXT NOT NULL,\n payload TEXT NOT NULL,\n created_at TEXT NOT NULL\n )`,\n // D-10's dedupe is THIS line, and it is the same idiom as the jobs index above for the same\n // reason: a crash-replayed chain terminal re-attempts the insert, and \"one notification per\n // run, ever\" has to be something no caller — in this process or the next — can get wrong.\n `CREATE UNIQUE INDEX IF NOT EXISTS notifications_run_id\n ON notifications (run_id)`,\n] as const\n\n/** The statuses a job never leaves. A cancel arriving at one of them moves nothing. */\nconst TERMINAL_JOB_STATUSES: readonly JobStatus[] = ['done', 'failed', 'cancelled']\n\n/**\n * The conclusion a quarantined row records (422 D-16). A CONCLUSION, never a kind.\n *\n * Declared as `JobConclusionKind` rather than inferred, so removing the member from the shipped\n * vocabulary fails to compile HERE as well as in the schema's own contract tests — the store may\n * not go on recording an outcome the contract no longer publishes.\n */\nconst UNREADABLE_KIND_CONCLUSION: JobConclusionKind = 'unreadable_kind'\n\n/**\n * The FIXED reason a quarantine writes, carrying none of the bytes it is about (422 D-16).\n *\n * Masked deliberately. The unreadable kind is a string an EARLIER build — or anything with write\n * access to this database — put in a column, and `last_failure_reason` is rendered on operator\n * terminals and copied into logs. Interpolating it here would take the one field of the row this\n * build refuses to trust and paste it into the one place an operator is most likely to read\n * without thinking. The original kind stays in the `kind` column, where a reader has to ask for it\n * and knows what it is when they do.\n */\nexport const QUARANTINED_UNREADABLE_KIND_REASON =\n 'agent job quarantined at claim: this build does not read the kind recorded for this row, so '\n + 'the row was landed permanently without being parsed. The original kind, id and payload are '\n + 'preserved in the row for inspection.'\n\n/**\n * How many rows one claim will pass over before it gives up.\n *\n * The quarantine loop below is already monotone — every iteration either returns a claim or moves\n * a row out of the claimable set — so this bound is unreachable by construction. It is here for\n * the same reason `AGENT_JOBS_PUMP_BOUND` is: an unbounded loop inside a write transaction is not\n * something to leave resting on an argument, and a store that somehow stopped shrinking its own\n * queue must say so rather than spin holding the write lock.\n */\nconst QUARANTINE_SCAN_BOUND = 1_000\n\n/**\n * Whether this row's kind is one this build cannot read (422 D-16).\n *\n * Asked of the RAW column, before `rowToJob`, and that ordering is the entire fix. `claimNext`\n * spends the attempt at the claim (D-18) and then parses; a kind the contract does not contain\n * threw out of `jobSchema.parse` INSIDE the transaction, so `inTransaction` rolled the spent\n * attempt back with it and the very next claim was offered the same row again — a crash-loop\n * reached with no crash, starving every valid row behind it. Recognising the row here means the\n * quarantine and the attempt commit together.\n */\nfunction isUnreadableKindRow(row: Record<string, unknown>): boolean {\n return !isJobKind(String(row.kind))\n}\n\n/**\n * The conclusion a quarantined row is READ back with — derived, never a column (422 D-16).\n *\n * Derived because it is derivable: the three facts below are already on the row, which is why 422\n * declined a column for it under D-04's stamp-and-hard-fail rule. The durable record IS the three\n * facts this reads — an unreadable kind, a permanent landing, and the fixed reason above — and the\n * conclusion is their name rather than a fourth fact that could disagree with them. It is\n * deliberately NOT \"any row whose kind is unreadable\": a retired-kind row still sitting queued has\n * not been quarantined yet, and saying it had would be a receipt for an event that has not happened.\n */\nfunction quarantineConclusionOf(row: Record<string, unknown>): JobConclusionKind | undefined {\n if (!isUnreadableKindRow(row)) return undefined\n if (String(row.status) !== 'failed') return undefined\n if (String(row.last_failure_kind) !== 'permanent') return undefined\n if (String(row.last_failure_reason) !== QUARANTINED_UNREADABLE_KIND_REASON) return undefined\n return UNREADABLE_KIND_CONCLUSION\n}\n\n\n/**\n * The run a job's payload column names, if it names one as a non-empty string.\n *\n * `chainTerminalFor`'s predicate verbatim (`engine.ts`), and it has to be verbatim: the key that\n * function derives IS the `notifications.run_id` a terminal writes, because `dedupeKey` is the\n * run id and nothing else. A looser reader here would disown a receipt no requeue is entitled to\n * disown; a stricter one would leave behind a receipt `ON CONFLICT (run_id) DO NOTHING` can never\n * replace. The column is bytes this store's own `enqueue` wrote with `JSON.stringify`, read the\n * same way `dumpRow` reads it.\n */\nfunction runIdOfPayloadColumn(payload: unknown): string | undefined {\n const record = JSON.parse(String(payload)) as unknown\n if (typeof record !== 'object' || record === null || Array.isArray(record)) return undefined\n const runId = (record as { runId?: unknown }).runId\n return typeof runId === 'string' && runId !== '' ? runId : undefined\n}\n\nfunction toNumber(value: unknown): number {\n return typeof value === 'bigint' ? Number(value) : Number(value)\n}\n\nexport function createSqliteJobStore(options: CreateSqliteJobStoreOptions): SqliteJobStore {\n const { clock, checkpoints, hooks } = options\n\n mkdirSync(dirname(options.path), { recursive: true })\n const db = new DatabaseSync(options.path, {\n timeout: options.timeoutMs ?? AGENT_JOB_STORE_BUSY_TIMEOUT_MS,\n })\n db.exec('PRAGMA journal_mode=WAL')\n\n // The version is read BEFORE a single schema statement runs, so a database this build\n // cannot read is not touched on the way to being refused. A hard fail that had already\n // created a table, or re-stamped the header, would be a migration nobody wrote.\n const stampedVersion = toNumber(db.prepare('PRAGMA user_version').get()?.user_version)\n if (stampedVersion !== 0 && stampedVersion !== AGENT_JOB_STORE_USER_VERSION) {\n db.close()\n throw new JobStoreSchemaVersionError(\n options.path,\n AGENT_JOB_STORE_USER_VERSION,\n stampedVersion,\n )\n }\n for (const statement of SCHEMA_STATEMENTS) db.exec(statement)\n if (stampedVersion === 0) {\n db.exec(`PRAGMA user_version=${AGENT_JOB_STORE_USER_VERSION}`)\n }\n\n const insertJob = db.prepare(\n `INSERT INTO jobs\n (id, kind, idempotency_key, status, summary, payload, attempts, claimed_at,\n created_at, updated_at, last_failure_kind, last_failure_reason,\n cancel_requested_at, started_at, not_before)\n VALUES (?, ?, ?, 'queued', ?, ?, 0, NULL, ?, ?, NULL, NULL, NULL, NULL, NULL)\n ON CONFLICT (kind, idempotency_key) DO NOTHING`,\n )\n const selectByKey = db.prepare('SELECT * FROM jobs WHERE kind = ? AND idempotency_key = ?')\n const selectById = db.prepare('SELECT * FROM jobs WHERE id = ?')\n const selectClaimable = db.prepare(\n `SELECT * FROM jobs\n WHERE status = 'queued' AND claimed_at IS NULL\n AND (not_before IS NULL OR not_before <= ?)\n ORDER BY created_at ASC, id ASC\n LIMIT 1`,\n )\n // The exclusion path's statements, cached by placeholder ARITY so a hot claim path never\n // re-prepares (388-09). Bound parameters only — one `?` per excluded kind — even though\n // `JobKind` is a closed vocabulary: the bound form costs nothing and removes the question\n // of a caller string ever reaching the SQL text (T-388-22). The predicate is the SAME\n // WHERE plus `kind NOT IN (...)`, same ORDER BY, so the only thing an exclusion changes is\n // which row the SELECT offers — never what claiming does to it (T-388-21/23).\n const selectClaimableExcluding = new Map<number, ReturnType<typeof db.prepare>>()\n function claimableStatementFor(excludedCount: number): ReturnType<typeof db.prepare> {\n const cached = selectClaimableExcluding.get(excludedCount)\n if (cached !== undefined) return cached\n const placeholders = Array.from({ length: excludedCount }, () => '?').join(', ')\n const prepared = db.prepare(\n `SELECT * FROM jobs\n WHERE status = 'queued' AND claimed_at IS NULL\n AND (not_before IS NULL OR not_before <= ?) AND kind NOT IN (${placeholders})\n ORDER BY created_at ASC, id ASC\n LIMIT 1`,\n )\n selectClaimableExcluding.set(excludedCount, prepared)\n return prepared\n }\n // COALESCE because the first claim IS the start: a later claim after a retryable failure is a\n // second attempt at work that already began, and overwriting the start would time only it.\n const markClaimed = db.prepare(\n `UPDATE jobs\n SET claimed_at = ?, started_at = COALESCE(started_at, ?), attempts = attempts + 1,\n updated_at = ?\n WHERE id = ?`,\n )\n const markDone = db.prepare(\n \"UPDATE jobs SET status = 'done', claimed_at = NULL, updated_at = ? WHERE id = ?\",\n )\n // 422 D-16: the quarantine landing. Terminal, claim released, reason fixed — and the row's\n // `kind`, `id` and `payload` untouched, because the point of landing it rather than deleting it\n // is that an operator can still see what an earlier build wrote. `attempts` is not named here:\n // the claim immediately above this statement already spent it, and this transaction commits\n // both, which is the difference between a spent attempt and a rolled-back one.\n const markQuarantined = db.prepare(\n `UPDATE jobs\n SET status = 'failed', claimed_at = NULL, last_failure_kind = 'permanent',\n last_failure_reason = ?, updated_at = ?\n WHERE id = ?`,\n )\n const touchJob = db.prepare('UPDATE jobs SET updated_at = ? WHERE id = ?')\n // Two statements, because the two dispositions are two different outcomes: a retryable\n // failure releases the claim and leaves the row queued for the next attempt, while a\n // permanent one is terminal. Whether a retryable REPORT becomes a retry disposition at all\n // is the engine's call under D-18's bound — the store records the decision, never makes it.\n const markRetryable = db.prepare(\n `UPDATE jobs\n SET claimed_at = NULL, last_failure_kind = 'retry', last_failure_reason = ?,\n updated_at = ?, not_before = ?\n WHERE id = ?`,\n )\n // An aborted attempt did not fail, so its attempt is refunded and its claim released. The last\n // failure, not-before and started_at are kept; a first attempt's start is the refunded claim's.\n const markInterrupted = db.prepare(\n `UPDATE jobs\n SET claimed_at = NULL, attempts = MAX(attempts - 1, 0), updated_at = ?\n WHERE id = ?`,\n )\n const markFailed = db.prepare(\n `UPDATE jobs\n SET status = 'failed', claimed_at = NULL, last_failure_kind = 'permanent',\n last_failure_reason = ?, updated_at = ?\n WHERE id = ?`,\n )\n // The two halves of D-19, as two statements, because they are two different transitions.\n // One stops a job nobody is running; the other only records that somebody asked, and leaves\n // the row exactly as claimable as it was so the driver can finish its step.\n const markCancelledNow = db.prepare(\n `UPDATE jobs\n SET status = 'cancelled', claimed_at = NULL, cancel_requested_at = ?, updated_at = ?\n WHERE id = ?`,\n )\n const markCancelRequested = db.prepare(\n 'UPDATE jobs SET cancel_requested_at = ?, updated_at = ? WHERE id = ?',\n )\n const markCancelHonoured = db.prepare(\n `UPDATE jobs\n SET status = 'cancelled', claimed_at = NULL, updated_at = ?\n WHERE id = ?`,\n )\n // The operator requeue's three statements (413-13). The UPDATE clears every column that\n // recorded HOW the row finished as well as the status itself — a requeued job that kept its\n // failure reason or its cancel request would be a queued row still carrying the verdict of\n // an attempt that no longer exists, and the next drainer would read it as its own. The start\n // goes with them: a requeued row that kept it would time a queue life that no longer exists.\n const markRequeued = db.prepare(\n `UPDATE jobs\n SET status = 'queued', claimed_at = NULL, started_at = NULL, attempts = 0,\n last_failure_kind = NULL, last_failure_reason = NULL, cancel_requested_at = NULL,\n not_before = NULL, updated_at = ?\n WHERE id = ?`,\n )\n // DISTINCT because the checkpoint key carries the attempt: one checkpoint id published\n // across two attempts is two rows and one file, and the file is discarded once.\n const selectCheckpointIdsForJob = db.prepare(\n 'SELECT DISTINCT checkpoint_id FROM job_checkpoints WHERE job_id = ?',\n )\n const deleteCheckpointsForJob = db.prepare('DELETE FROM job_checkpoints WHERE job_id = ?')\n const selectFence = db.prepare('SELECT epoch FROM job_store_fence WHERE id = 1')\n const upsertFence = db.prepare(\n `INSERT INTO job_store_fence (id, epoch) VALUES (1, ?)\n ON CONFLICT (id) DO UPDATE SET epoch = excluded.epoch`,\n )\n const upsertCheckpoint = db.prepare(\n `INSERT INTO job_checkpoints\n (job_id, checkpoint_id, attempt, payload_json, payload_digest, epoch)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT (job_id, attempt, checkpoint_id) DO UPDATE SET\n payload_json = excluded.payload_json,\n payload_digest = excluded.payload_digest,\n epoch = excluded.epoch`,\n )\n const selectLatestCheckpoint = db.prepare(\n `SELECT payload_json, payload_digest, attempt, epoch\n FROM job_checkpoints\n WHERE job_id = ? AND checkpoint_id = ?\n ORDER BY attempt DESC\n LIMIT 1`,\n )\n // ON CONFLICT DO NOTHING rather than a caller-side \"already notified?\" read: the read and\n // the write would be two decisions about one row, and the window between them is precisely\n // where a replayed terminal writes the second notification (D-09/D-10).\n const insertNotification = db.prepare(\n `INSERT INTO notifications (run_id, payload, created_at) VALUES (?, ?, ?)\n ON CONFLICT (run_id) DO NOTHING`,\n )\n const selectJobStatus = db.prepare('SELECT status FROM jobs WHERE id = ?')\n const selectNotifications = db.prepare(\n 'SELECT run_id, payload, created_at FROM notifications ORDER BY run_id ASC',\n )\n const deleteNotificationForRun = db.prepare('DELETE FROM notifications WHERE run_id = ?')\n\n function inTransaction<T>(body: () => T): T {\n db.exec('BEGIN IMMEDIATE')\n try {\n const result = body()\n db.exec('COMMIT')\n return result\n } catch (error) {\n if (db.isTransaction) db.exec('ROLLBACK')\n throw error\n }\n }\n\n /** No epoch adopted yet reads as epoch 0, so an un-adopted store refuses every drain. */\n function currentEpoch(): number {\n const row = selectFence.get()\n return row === undefined ? 0 : toNumber(row.epoch)\n }\n\n /**\n * The fence check, called from INSIDE each drain-side verb's transaction.\n *\n * Inside is the whole point: checking before `BEGIN IMMEDIATE` would leave a window in\n * which another writer adopts a newer epoch between the check and the mutation, which is\n * precisely the split-brain the fence exists to exclude. The epoch is re-read every time\n * and never cached (the v51 lease discipline).\n */\n function requireFence(fence: JobStoreFence): void {\n const observed = currentEpoch()\n if (observed !== fence.epoch) {\n throw new StaleJobStoreEpochError(fence.epoch, observed)\n }\n }\n\n /**\n * Every row leaves this store through the shipped zod contract.\n *\n * That is a boundary check, not ceremony: the payload column is opaque text a second\n * process wrote, and the columns around it are only as trustworthy as whatever produced\n * them. Parsing means a row that lost its attempt count or its timestamps cannot travel\n * as a `Job` — which is exactly the class of row the C6 break exists to forbid.\n */\n function rowToJob(row: Record<string, unknown> | undefined): Job {\n if (row === undefined) {\n throw new UnknownJobRowError('<missing>')\n }\n return jobSchema.parse({\n id: String(row.id),\n kind: String(row.kind),\n status: String(row.status),\n summary: String(row.summary),\n attempts: toNumber(row.attempts),\n createdAt: String(row.created_at),\n updatedAt: String(row.updated_at),\n })\n }\n\n function requireRow(jobId: string): Record<string, unknown> {\n const row = selectById.get(jobId)\n if (row === undefined) {\n throw new UnknownJobRowError(jobId)\n }\n return row\n }\n\n function insertOrGet(request: JobInsert, now: string): JobEnqueueOutcome {\n // Checked HERE and not only in the engine. D-02 lets any process open this database, so\n // the store is where dedupe is guaranteed, and an empty key satisfies the unique index\n // while collapsing every job of a kind onto one slot — the failure the guarantee exists\n // to prevent. The engine's error is reused rather than reprinted: one condition, one name.\n if (request.idempotencyKey.trim() === '') {\n throw new MissingIdempotencyKeyError(request.kind)\n }\n const changes = insertJob.run(\n String(request.id),\n request.kind,\n request.idempotencyKey,\n request.summary,\n JSON.stringify(request.payload ?? null),\n now,\n now,\n ).changes\n return {\n job: rowToJob(selectByKey.get(request.kind, request.idempotencyKey)),\n deduped: toNumber(changes) === 0,\n }\n }\n\n /**\n * Record the chain-terminal notification, if the chain really has terminated.\n *\n * Called from INSIDE both terminal transactions, and the placement is the guarantee: the\n * statuses it reads are the ones this very transaction just wrote, so there is no instant\n * between \"the last job became terminal\" and \"the run was notified\" for a crash to land in.\n *\n * The rule is stated over the candidates that EXIST rather than over a membership list,\n * which is what lets a candidate have an id and no row without making every\n * chain look incomplete (D-04). Its head must exist, though: a chain-member job that arrived\n * with a run id but whose analyze-run row was never written is not a run's chain at all, and\n * notifying for it would mint a dedupe key nothing else in the system agrees with.\n *\n * 2026-09-02 (Phase 412): the reserved sixth job kind that first motivated the rule left\n * with the Issue-slot cleanup.\n */\n function recordChainTerminal(chainTerminal: ChainTerminalRecord, now: string): void {\n let headExists = false\n for (const candidate of chainTerminal.candidateJobIds) {\n const row = selectJobStatus.get(String(candidate))\n if (row === undefined) continue\n headExists ||= String(candidate) === String(chainTerminal.candidateJobIds[0])\n if (!TERMINAL_JOB_STATUSES.includes(String(row.status) as JobStatus)) return\n }\n if (!headExists) return\n insertNotification.run(chainTerminal.dedupeKey, chainTerminal.payloadJson, now)\n }\n\n function dumpRow(row: Record<string, unknown>): JobStoreDumpRow {\n const conclusionKind = quarantineConclusionOf(row)\n return {\n id: String(row.id),\n kind: String(row.kind),\n idempotencyKey: String(row.idempotency_key),\n status: String(row.status),\n summary: String(row.summary),\n payload: JSON.parse(String(row.payload)) as unknown,\n attempts: toNumber(row.attempts),\n claimed: row.claimed_at !== null,\n cancelRequested: row.cancel_requested_at !== null,\n // 422 D-16: OMITTED rather than `undefined` when there is nothing to say, so a reader that\n // serializes this row does not publish an empty conclusion key for every ordinary job.\n ...(conclusionKind === undefined ? {} : { conclusionKind }),\n createdAt: String(row.created_at),\n updatedAt: String(row.updated_at),\n }\n }\n\n return {\n close() {\n db.close()\n },\n\n async adoptEpoch(epoch: number): Promise<JobStoreFence> {\n return inTransaction(() => {\n const observed = currentEpoch()\n // Authority only ever moves forward. A store that accepted a lower epoch would let\n // a writer that already lost its lease re-arm itself simply by asking again.\n if (epoch < observed) {\n throw new StaleJobStoreEpochError(epoch, observed)\n }\n upsertFence.run(epoch)\n return { epoch }\n })\n },\n\n async enqueue(request: JobInsert): Promise<JobEnqueueOutcome> {\n const now = clock.now()\n return inTransaction(() => insertOrGet(request, now))\n },\n\n async claimNext(fence: JobStoreFence, options?: ClaimNextOptions): Promise<JobClaimOutcome> {\n const now = clock.now()\n // Honoured in the SELECT itself, never by claiming and undoing: per D-18 the attempt\n // is spent at the claim, and (388-09 M-2) a released row is re-offered ahead of every\n // younger row, so claim-and-undo would burn the bound or starve the queue.\n const excludeKinds = options?.excludeKinds ?? []\n return inTransaction(() => {\n // FIRST, and before the loop rather than inside it: a quarantine is a WRITE, so a caller\n // whose epoch the store does not recognise must be refused having moved nothing at all.\n requireFence(fence)\n for (let scanned = 0; scanned <= QUARANTINE_SCAN_BOUND; scanned += 1) {\n const row =\n excludeKinds.length === 0\n ? selectClaimable.get(now)\n : claimableStatementFor(excludeKinds.length).get(now, ...excludeKinds)\n if (row === undefined) {\n return { claimed: false }\n }\n // D-18: the attempt is counted HERE, at the claim, not when a failure is recorded.\n // A job that kills its host on every attempt records no failures at all, so a\n // failure-time counter would let it retry forever.\n markClaimed.run(now, now, now, String(row.id))\n const claimed = requireRow(String(row.id))\n // 422 D-16: asked of the RAW row, BEFORE `rowToJob`. The landing joins the claim's own\n // transaction, so the attempt this claim just spent commits with it instead of being\n // rolled back by a parser throwing on the way out — and the loop then offers the next\n // claimable row, so several poisoned heads cost one pass rather than one per row.\n if (isUnreadableKindRow(claimed)) {\n markQuarantined.run(QUARANTINED_UNREADABLE_KIND_REASON, now, String(row.id))\n continue\n }\n // The payload travels with the claim, not on the job row's DTO: it is the opaque\n // input this kind's handler reads, and the handler is the only thing that can.\n return {\n claimed: true,\n job: rowToJob(claimed),\n payload: JSON.parse(String(claimed.payload)) as unknown,\n }\n }\n // Unreachable by construction — every iteration above either returns or moves a row to a\n // terminal status, which removes it from the claimable set. Recorded rather than trusted,\n // and a throw rather than a silent `{claimed: false}`: reaching it means the claimable\n // predicate stopped shrinking, and reporting an empty queue would hide that forever.\n throw new Error(\n `agent job claim scanned ${QUARANTINE_SCAN_BOUND} rows without reaching a claimable or `\n + 'exhausted queue; the claimable set is not shrinking, so no row was claimed and the '\n + 'transaction is rolled back rather than reporting an empty queue',\n )\n })\n },\n\n async completeAndChain(\n jobId: JobId,\n next: readonly JobInsert[],\n fence: JobStoreFence,\n chainTerminal?: ChainTerminalRecord,\n ): Promise<JobCompleteOutcome> {\n const now = clock.now()\n return inTransaction(() => {\n requireFence(fence)\n requireRow(String(jobId))\n markDone.run(now, String(jobId))\n // Same transaction as the completion: two transactions would leave a window where a\n // crash loses the chain while the predecessor already reads as done, and nothing\n // downstream would ever notice the successor never existed.\n const chained = next.map((request) => insertOrGet(request, now))\n if (chainTerminal !== undefined) recordChainTerminal(chainTerminal, now)\n return { job: rowToJob(requireRow(String(jobId))), chained }\n })\n },\n\n async failAndChain(\n jobId: JobId,\n disposition: Extract<JobFailureDisposition, { readonly kind: 'permanent' }>,\n next: readonly JobInsert[],\n fence: JobStoreFence,\n chainTerminal?: ChainTerminalRecord,\n ) {\n const now = clock.now()\n return inTransaction(() => {\n requireFence(fence)\n requireRow(String(jobId))\n markFailed.run(disposition.reason, now, String(jobId))\n // Parent transition and every insert share this transaction. If any insert raises,\n // inTransaction rolls the parent and all earlier successors back before surfacing it.\n const chained = next.map((request) => insertOrGet(request, now))\n // D-12's other half. Notify rides the failure terminal on exactly the same footing as\n // the success one, because a chain that gave up is when a user most needs to hear.\n if (chainTerminal !== undefined) recordChainTerminal(chainTerminal, now)\n return { job: rowToJob(requireRow(String(jobId))), chained }\n })\n },\n\n async recordFailure(\n jobId: JobId,\n disposition: JobFailureDisposition,\n fence: JobStoreFence,\n ): Promise<void> {\n const now = clock.now()\n inTransaction(() => {\n requireFence(fence)\n requireRow(String(jobId))\n // The attempt count is NOT touched here. D-18 spends it at the claim, so a job that\n // kills its host before it can report anything still exhausts its bound; incrementing\n // again on the way out would charge a reported failure twice and an unreported one\n // never.\n if (disposition.kind === 'retry') {\n // Lexical comparison in the claim holds only because both sides are toISOString().\n const notBefore =\n disposition.retryAfterMs === undefined\n ? null\n : new Date(Date.parse(now) + disposition.retryAfterMs).toISOString()\n markRetryable.run(disposition.reason, now, notBefore, String(jobId))\n } else {\n markFailed.run(disposition.reason, now, String(jobId))\n }\n })\n },\n\n async releaseInterrupted(jobId: JobId, fence: JobStoreFence): Promise<void> {\n const now = clock.now()\n inTransaction(() => {\n requireFence(fence)\n requireRow(String(jobId))\n markInterrupted.run(now, String(jobId))\n })\n },\n\n async requestCancel(jobId: JobId, fence: JobStoreFence): Promise<JobCancelOutcome> {\n const now = clock.now()\n return inTransaction(() => {\n requireFence(fence)\n const row = requireRow(String(jobId))\n const status = String(row.status) as JobStatus\n // Read and written inside ONE transaction: which of the three things a cancel means\n // depends on whether the row is claimed at this instant, and deciding that from a\n // read taken outside the transaction would let a claim land in between.\n if (TERMINAL_JOB_STATUSES.includes(status)) {\n return { outcome: 'already-terminal', status }\n }\n if (row.claimed_at !== null) {\n // In flight. The request is recorded and the row stays exactly as it was, so the\n // step the handler is part way through finishes and is checkpointed; the driver\n // stops it at the next boundary.\n markCancelRequested.run(now, now, String(jobId))\n return { outcome: 'cancel-requested' }\n }\n // Nobody is running it, so there is no step to protect and no boundary to wait for.\n // The request is stamped as well as the status, so `cancelled` never appears without\n // the record of the ask that produced it.\n markCancelledNow.run(now, now, String(jobId))\n return { outcome: 'cancelled' }\n })\n },\n\n async recordCancellation(jobId: JobId, fence: JobStoreFence): Promise<void> {\n const now = clock.now()\n inTransaction(() => {\n requireFence(fence)\n const row = requireRow(String(jobId))\n if (row.cancel_requested_at === null) {\n throw new JobCancellationNotRequestedError(jobId)\n }\n markCancelHonoured.run(now, String(jobId))\n })\n },\n\n // The 413-13 gap closure, and the checkpoint forget is its load-bearing half.\n //\n // Phase 413's pump composed with no post-run capabilities, so the kind registry selected\n // the STAND-IN analyze-run handler: nineteen rows recorded a `verdicts-authored`\n // checkpoint and reached `done` with nothing authored. Resetting the status alone would\n // not undo that, it would REPEAT it — `selectLatestCheckpoint` reads\n // `ORDER BY attempt DESC`, so the real handler's next attempt would resume on the\n // stand-in's recorded value, author nothing again, and report completion again. So the\n // rows go with the status, inside the same transaction, and the files follow the rows.\n async requeueTerminal(jobId: JobId, fence: JobStoreFence): Promise<JobRequeueOutcome> {\n const now = clock.now()\n const decided = inTransaction((): JobRequeueOutcome & { readonly discard?: string[] } => {\n requireFence(fence)\n const row = requireRow(String(jobId))\n const status = String(row.status) as JobStatus\n // 422 D-16, BEFORE the terminal check and before every write below. A quarantined row is\n // terminal, so the ordinary path would accept it and then spend the whole remedy on it:\n // the attempts reset, the checkpoint rows and files deleted, the run's chain-terminal\n // notification disowned — and the next claim would quarantine it again, because no\n // registered kind can run it. Refusing here, inside the transaction and ahead of the first\n // mutation, is what makes \"the history survives an operator's mistake\" a store guarantee\n // rather than a rule the surface has to remember. Checked on the RAW kind, never parsed.\n if (isUnreadableKindRow(row)) {\n throw new QuarantinedJobRequeueError(String(jobId), String(row.kind))\n }\n // Read and written in ONE transaction for the same reason a cancel is: whether this\n // row is a drainer's is a fact about the instant of the write, and a status read\n // taken outside would let a claim land in between and be reset out from under it.\n if (!TERMINAL_JOB_STATUSES.includes(status)) {\n return { outcome: 'not-terminal', status }\n }\n const discard = selectCheckpointIdsForJob\n .all(String(jobId))\n .map((checkpoint) => String(checkpoint.checkpoint_id))\n deleteCheckpointsForJob.run(String(jobId))\n // The THIRD medium, and the one that cannot be corrected later. If this row's last\n // attempt landed the chain terminal, `recordChainTerminal` wrote a `notifications` row\n // keyed on the run this payload names — and `insertNotification` is\n // `ON CONFLICT (run_id) DO NOTHING`, so a receipt left here wins forever: the re-run's\n // real handler chains a successor, which makes `chainTerminalFor` answer `undefined`\n // and offer no replacement at all. Leaving it would publish \"this run's chain\n // terminated with these values\" over an attempt whose every other trace this very\n // transaction is deleting. Inside the transaction with the rows for the same reason\n // they are: the three media are one disowning, or the crash between them is a state\n // recovery has no vocabulary for.\n const requeuedRun = runIdOfPayloadColumn(row.payload)\n if (requeuedRun !== undefined) deleteNotificationForRun.run(requeuedRun)\n markRequeued.run(now, String(jobId))\n return { outcome: 'requeued', discard }\n })\n // Files AFTER the authoritative rows commit — `publishCheckpoint`'s ordering, run\n // backwards, and for the same reason. The row decides what recovery believes, so a\n // crash between the commit and these removals leaves stale FILES behind a row that no\n // longer exists, which `readCheckpoint` already ignores; the opposite order would leave\n // a live row whose file is gone, and that is a real loss.\n if (decided.outcome === 'requeued') {\n for (const checkpointId of decided.discard ?? []) {\n checkpoints.discard(String(jobId), checkpointId)\n }\n return { outcome: 'requeued' }\n }\n return decided\n },\n\n async publishCheckpoint(\n jobId: JobId,\n checkpointId: string,\n payload: JobCheckpointRecord,\n fence: JobStoreFence,\n ): Promise<void> {\n const now = clock.now()\n const payloadJson = canonicalJson(payload)\n const payloadDigest = sha256hex(payloadJson)\n inTransaction(() => {\n requireFence(fence)\n requireRow(String(jobId))\n touchJob.run(now, String(jobId))\n // This INSERT belongs to the SAME transaction as both requireFence and the job touch.\n // Once it commits, this row decides what recovery believes; a later file writer cannot\n // change checkpoint authorship without first winning another fenced transaction.\n upsertCheckpoint.run(\n String(jobId),\n checkpointId,\n payload.attempt,\n payloadJson,\n payloadDigest,\n fence.epoch,\n )\n })\n // File AFTER the authoritative row commits: it remains the fsync'd cross-process\n // projection, but the read path digest-checks it against the row before trusting it.\n // A takeover here may let the stale host replace the file; it cannot replace the row.\n if (hooks?.beforeCheckpointFilePublish !== undefined) {\n await hooks.beforeCheckpointFilePublish()\n }\n checkpoints.publish(String(jobId), checkpointId, payload)\n },\n\n async readCheckpoint(\n jobId: JobId,\n checkpointId: string,\n ): Promise<JobCheckpointReadOutcome> {\n const row = selectLatestCheckpoint.get(String(jobId), checkpointId)\n if (row === undefined) return { found: false }\n\n const authoritative = {\n found: true as const,\n payload: JSON.parse(String(row.payload_json)) as unknown,\n }\n try {\n const projection = checkpoints.read(String(jobId), checkpointId)\n if (!projection.found) return authoritative\n const projectionDigest = sha256hex(canonicalJson(projection.payload))\n return projectionDigest === String(row.payload_digest) ? projection : authoritative\n } catch {\n // The file is a cache now. Missing, malformed, unreadable, or otherwise untrustworthy\n // projection bytes cannot block recovery from the fenced SQLite record.\n return authoritative\n }\n },\n\n async dumpState(): Promise<JobStoreDump> {\n return {\n schemaVersion: AGENT_JOB_STORE_USER_VERSION,\n epoch: currentEpoch(),\n // The same ordered read the logical dump uses, so the typed projection and the\n // equality instrument cannot disagree about which rows exist or in what order.\n jobs: selectOrderedRows(db, 'jobs').rows.map(dumpRow),\n }\n },\n\n async listNotifications(): Promise<readonly JobStoreNotification[]> {\n return selectNotifications.all().map((row) => ({\n runId: String(row.run_id),\n payload: guardRunNotification(JSON.parse(String(row.payload)) as unknown),\n createdAt: String(row.created_at),\n }))\n },\n\n async logicalDump(): Promise<LogicalDump> {\n return createLogicalDump({\n db,\n schemaVersion: AGENT_JOB_STORE_USER_VERSION,\n checkpointsRoot: checkpoints.checkpointsRoot,\n })\n },\n\n async dumpLogicalState(): Promise<string> {\n return canonicalLogicalDump(\n createLogicalDump({\n db,\n schemaVersion: AGENT_JOB_STORE_USER_VERSION,\n checkpointsRoot: checkpoints.checkpointsRoot,\n }),\n )\n },\n }\n}\n","// The equality instrument the kill matrix compares (Phase 385 plan 03, D-03).\n//\n// Never raw database bytes. Sqlite's page layout is not deterministic across two histories\n// that reached the same state by different routes, and while a connection is open the `-wal`\n// and `-shm` sidecars exist beside the file, so a byte comparison of the database would\n// report differences that mean nothing and miss differences that mean everything. What is\n// compared instead is the LOGICAL state: every table, every row, in an order this module\n// states explicitly, serialized with the repo's byte-stability primitive — plus a digest per\n// checkpoint file, since under the hybrid split half the durable state is not in the database\n// at all.\n//\n// Two rules make the result trustworthy rather than merely stable:\n//\n// Tables are enumerated from the database's own catalogue, not from a list kept here. A\n// list would silently stop covering a table added later, and the first thing a stale\n// comparison instrument does is agree that two different states are the same.\n//\n// Every SELECT carries an explicit ORDER BY over all of the table's columns. Row order\n// implied by physical layout is not order at all: two databases holding identical rows\n// inserted in a different sequence would serialize differently, which is exactly the false\n// difference that gets an equality assertion loosened until it proves nothing.\n\nimport { readdirSync, readFileSync } from 'node:fs'\nimport { join, relative, sep } from 'node:path'\n\nimport { DatabaseSync } from 'node:sqlite'\n\nimport { canonicalJson, sha256hex } from '@vostride/agent-qa-schema'\n\n/** Identifiers that are safe to interpolate; sqlite has no placeholders for them. */\nconst SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/\n\nexport interface LogicalDumpTable {\n readonly table: string\n readonly orderBy: readonly string[]\n readonly rows: readonly Record<string, unknown>[]\n}\n\nexport interface LogicalDumpCheckpoint {\n /** Relative to the checkpoint root, so two runs under different temp roots compare. */\n readonly path: string\n readonly digest: string\n}\n\nexport interface LogicalDump {\n readonly schemaVersion: number\n readonly tables: readonly LogicalDumpTable[]\n readonly checkpoints: readonly LogicalDumpCheckpoint[]\n}\n\nfunction requireIdentifier(value: string): string {\n if (!SAFE_IDENTIFIER.test(value)) {\n throw new TypeError(`unusable sqlite identifier in a logical dump: ${JSON.stringify(value)}`)\n }\n return value\n}\n\n/** The full-table SELECT for one table. Exported so a test can read the ORDER BY itself. */\nexport function orderedSelectSql(table: string, columns: readonly string[]): string {\n if (columns.length === 0) {\n throw new TypeError(`table ${table} reports no columns, so no order can be stated`)\n }\n const order = columns.map((column) => `\"${requireIdentifier(column)}\" ASC`).join(', ')\n return `SELECT * FROM \"${requireIdentifier(table)}\" ORDER BY ${order}`\n}\n\nexport function listStoreTables(db: DatabaseSync): string[] {\n return db\n .prepare(\n `SELECT name FROM sqlite_master\n WHERE type = 'table' AND name NOT LIKE 'sqlite_%'\n ORDER BY name ASC`,\n )\n .all()\n .map((row) => String(row.name))\n}\n\nexport function tableColumns(db: DatabaseSync, table: string): string[] {\n return db\n .prepare(`PRAGMA table_info(\"${requireIdentifier(table)}\")`)\n .all()\n .map((row) => String(row.name))\n}\n\n/**\n * Values sqlite hands back, in a form the canonical serializer accepts.\n *\n * Integer columns arrive as bigints on this binding, and a bigint cannot be serialized at\n * all — so this is a correctness step rather than a cosmetic one.\n */\nfunction normalize(value: unknown): unknown {\n if (typeof value === 'bigint') return Number(value)\n if (value instanceof Uint8Array) return { base16: Buffer.from(value).toString('hex') }\n return value\n}\n\nexport function selectOrderedRows(db: DatabaseSync, table: string): LogicalDumpTable {\n const columns = tableColumns(db, table)\n const rows = db\n .prepare(orderedSelectSql(table, columns))\n .all()\n .map((row) => {\n const normalized: Record<string, unknown> = {}\n for (const column of columns) normalized[column] = normalize(row[column])\n return normalized\n })\n return { table, orderBy: columns, rows }\n}\n\n/**\n * Every checkpoint file under the root, sorted, with a digest of its bytes.\n *\n * Digests rather than contents: the comparison only ever asks whether the bytes are the same,\n * and a dump that inlined every authored payload would be dominated by the thing it is least\n * interested in. Only the checkpoint directory is walked — the database and its sidecars live\n * elsewhere, and a filesystem-wide listing would make the sidecars part of the comparison.\n */\nexport function checkpointDigests(checkpointsRoot: string): LogicalDumpCheckpoint[] {\n const found: LogicalDumpCheckpoint[] = []\n\n function walk(dir: string): void {\n let entries\n try {\n entries = readdirSync(dir, { withFileTypes: true })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return\n throw error\n }\n for (const entry of entries) {\n const path = join(dir, entry.name)\n if (entry.isDirectory()) {\n walk(path)\n continue\n }\n found.push({\n path: relative(checkpointsRoot, path).split(sep).join('/'),\n digest: sha256hex(readFileSync(path, 'utf8')),\n })\n }\n }\n\n walk(checkpointsRoot)\n return found.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0))\n}\n\nexport interface CreateLogicalDumpInput {\n readonly db: DatabaseSync\n readonly schemaVersion: number\n readonly checkpointsRoot: string\n}\n\nexport function createLogicalDump(input: CreateLogicalDumpInput): LogicalDump {\n return {\n schemaVersion: input.schemaVersion,\n tables: listStoreTables(input.db).map((table) => selectOrderedRows(input.db, table)),\n checkpoints: checkpointDigests(input.checkpointsRoot),\n }\n}\n\n/** The comparable form. Two dumps of the same logical state are the same string. */\nexport function canonicalLogicalDump(dump: LogicalDump): string {\n return canonicalJson(dump)\n}\n","// The build-ordinal edge (Phase 387, D-20).\n//\n// Build ordinals and build tags are run-persistence machinery: the ordinal counter and the\n// tag map both live in `runner-local` beside the stores that write them, and that is the\n// right home. What was wrong was WHO reached them. Two CLI commands named `runner-local`\n// directly to resolve a tag and to reserve an ordinal, and a surface naming a persistence\n// package is the private power the FUNC-02 firewall exists to remove — the same debt the\n// firewall ledger carried for `knowledge-read.ts` and `knowledge-maintain.ts` until this phase.\n//\n// So the edge moves here, to the composition subtree a surface is already sanctioned to reach\n// (`SURFACE_ALLOWED_INTERNAL_PACKAGES`), and nothing else changes: these are re-exports, not\n// wrappers. A wrapper would have been a second, composition-local definition of what a build\n// ordinal is, and the first time the two disagreed the disagreement would be invisible. The\n// composition subtree may name `runner-local` by the arch carve-out (`COMPOSITION_ONLY_PACKAGES`)\n// precisely so that edges like this have one legal place to live.\n//\n// The reach this grants a surface is exactly three names, and each is already reachable by the\n// hosts that compose runs — this hands a CLI nothing the daemon did not already have.\n\nexport {\n BuildOrdinalReservationError,\n reserveBuildOrdinalForProducts,\n latestBuildOrdinal,\n} from '@vostride/agent-qa-runner-local'\nexport { resolveBuildTag } from '@vostride/agent-qa-runner-local'\n","// The recovery/resume composition entry (Phase 385 plan 06, D-11 layer 3).\n//\n// A host that adopts authority over the job queue has to do two things before it can pump: open the\n// durable store, and return every claim whose holder is gone. Doing that inline in each host is how\n// two hosts end up recovering differently — and one of them wrongly, because the ordering is not\n// obvious: `claimNext` never re-offers a row whose `claimed_at` is set, so a crashed job is stuck\n// rather than retryable until something releases it, and releasing it AFTER pumping would take a\n// job away from a handler still running it.\n//\n// What this file is FOR, though, is narrower than convenience. It is the named place the D-11 proof\n// points at: the resume path composes a store, a kind registry and the engine, and nothing else.\n// Every heavy first-party dependency the sibling composition legitimately names is absent here, and\n// so is the provider substrate — the capability a job authors with arrives already built, from the\n// host, as an ordinary argument. That is what makes \"recovery cannot reach a model on its own\" a\n// property of the import graph instead of a habit, and plan 07's named arch rule reads this file.\n//\n// Why the capability is REQUIRED rather than absent. Resuming is not the same as never authoring: a\n// host that died BEFORE its first checkpoint reached the store recorded nothing, and re-authoring\n// there is the correct behaviour rather than a violation — JOBQ-03 forbids re-invoking on a\n// RECORDED checkpoint, which the memoizing primitive makes impossible by control flow. An entry\n// that bound no capability at all would therefore be unable to finish exactly the jobs recovery\n// exists for, and the version of \"model-free\" it would buy is about the wrong thing: not that the\n// resume path never authors, but that this package never CONSTRUCTS the means to.\n\nimport { join } from 'node:path'\n\nimport { createAgentJobQueue, createRealJobKindRegistry } from '@vostride/agent-qa-agent'\nimport type {\n AgentJobQueue,\n ClockPort,\n JobIdSource,\n JobKindRegistry,\n JobModelCapability,\n JobStoreFence,\n RecoverAbandonedClaimsOutcome,\n RunNextJobOutcome,\n} from '@vostride/agent-qa-agent'\n\nimport { createJobCheckpointStore } from '../store/job-checkpoint-store.js'\nimport { AGENT_JOB_STORE_DB_FILE, createSqliteJobStore } from '../store/sqlite-job-store.js'\nimport type { SqliteJobStore } from '../store/sqlite-job-store.js'\n\n/**\n * How many jobs one `resumePending` call will run before it refuses to continue.\n *\n * A bound rather than a loop that trusts the queue to empty: recovery runs against a store any\n * process may have written, and a chain that keeps enqueuing successors would otherwise turn a\n * recovery call into an unbounded drain. Exceeding it raises rather than truncating — a resume that\n * quietly stopped early would report success over work it left behind.\n */\nexport const JOB_RECOVERY_MAX_RESUMED_JOBS = 64\n\nexport interface ComposeJobRecoveryInput {\n /** The project's runtime root, i.e. `<configDir>/.agent-qa`. Absolute. */\n readonly agentQaRoot: string\n /** Every column and dump row this host writes is stamped from here (D-03). */\n readonly clock: ClockPort\n /** Ids derived from `(kind, idempotencyKey)`, so a resumed chain addresses the same rows. */\n readonly idSource: JobIdSource\n /**\n * The capability a resumed job may author with, supplied by the host.\n *\n * Required and not defaultable, on the same reasoning as the queue's own option: an optional\n * capability means a host can compose recovery with none, and the only place to discover that is\n * inside an author callback far from the composition that forgot it.\n */\n readonly model: JobModelCapability\n /** Defaults to the six real declarations. Injected so a harness can drive its own handlers. */\n readonly jobKinds?: JobKindRegistry\n}\n\nexport interface JobRecoveryHost {\n readonly store: SqliteJobStore\n readonly kinds: JobKindRegistry\n readonly queue: AgentJobQueue\n /**\n * Return every outstanding claim to the queue, keeping the attempt each one spent.\n *\n * Call this FIRST. Only one process drains under a given fence, so at the moment authority is\n * adopted every outstanding claim belongs to a host that is gone; calling it beside a live pump\n * would reclaim a job from the handler still running it.\n */\n recoverAbandonedClaims(fence: JobStoreFence): Promise<RecoverAbandonedClaimsOutcome>\n /** Pump until no row is claimable. No timers, no sleeping — not a dispatcher. */\n resumePending(fence: JobStoreFence, maxJobs?: number): Promise<readonly RunNextJobOutcome[]>\n close(): void\n}\n\nexport function composeJobRecovery(input: ComposeJobRecoveryInput): JobRecoveryHost {\n const store = createSqliteJobStore({\n path: join(input.agentQaRoot, AGENT_JOB_STORE_DB_FILE),\n clock: input.clock,\n checkpoints: createJobCheckpointStore({ root: input.agentQaRoot }),\n })\n const kinds = input.jobKinds ?? createRealJobKindRegistry()\n const queue = createAgentJobQueue({\n store,\n registry: kinds,\n clock: input.clock,\n idSource: input.idSource,\n model: input.model,\n })\n\n return {\n store,\n kinds,\n queue,\n\n recoverAbandonedClaims(fence: JobStoreFence): Promise<RecoverAbandonedClaimsOutcome> {\n return queue.recoverAbandonedClaims({ fence })\n },\n\n async resumePending(\n fence: JobStoreFence,\n maxJobs: number = JOB_RECOVERY_MAX_RESUMED_JOBS,\n ): Promise<readonly RunNextJobOutcome[]> {\n const outcomes: RunNextJobOutcome[] = []\n for (;;) {\n if (outcomes.length >= maxJobs) {\n throw new Error(\n `agent job recovery ran ${maxJobs} jobs without emptying the agent job queue; the ` +\n 'bound exists so a chain that keeps enqueuing successors cannot turn recovery into an unbounded ' +\n 'drain, and stopping early without saying so would report success over work left behind',\n )\n }\n const outcome = await queue.runNextJob({ fence })\n if (!outcome.ran) return outcomes\n outcomes.push(outcome)\n }\n },\n\n close(): void {\n store.close()\n },\n }\n}\n","// The in-memory session log twin (Phase 392, D-14 — storage stays a port).\n//\n// It exists so a hermetic test can drive a whole turn without a temp directory, and it implements\n// the SAME `SessionLogPort` the disk adapter does — which is the only reason a twin is honest. A\n// second, looser shape would let a test pass against a contract production never signs.\n//\n// It is NOT a stand-in for the durability properties. `turnBoundary` here is a no-op because there\n// is nothing to sync, and any test whose subject is the fsync ORDER must drive the disk adapter\n// through its recorder facade instead (`createJsonlSessionLogOn`). Using this twin for that would\n// be measuring a promise nobody made.\n\nimport { repairSession } from '@vostride/agent-qa-agent'\nimport { CURRENT_CHAT_SESSION_SCHEMA_VERSION } from '@vostride/agent-qa-schema'\nimport type {\n ChatSessionEvent,\n ChatSessionHandle,\n ChatSessionHeader,\n OpenedChatSession,\n SessionLogPort,\n} from '@vostride/agent-qa-schema'\n\nimport {\n ChatSessionBusyError,\n UnknownChatSessionError,\n mintChatSessionId,\n} from './jsonl-session-log.js'\n\nexport interface CreateMemorySessionLogOptions {\n readonly now: () => string\n readonly model: () => string\n readonly toolsetHash: () => string\n readonly random?: () => number\n}\n\nexport interface MemorySessionLog extends SessionLogPort {\n /** Everything written, for assertions. A copy, so a caller cannot edit the log through it. */\n snapshot(sessionId: string): OpenedChatSession | undefined\n}\n\nexport function createMemorySessionLog(\n options: CreateMemorySessionLogOptions,\n): MemorySessionLog {\n const sessions = new Map<string, { header: ChatSessionHeader; events: ChatSessionEvent[] }>()\n const random = options.random ?? Math.random\n // THE TWIN CARRIES THE CONCURRENCY CONTRACT TOO (392-12, CR-01). What was `let current` here —\n // the same single-session shape the disk adapter's single `fd` had — is gone, and for the reason\n // 390 paid for once: a read-side fix without its write-side twin is a regression generator. A\n // twin that kept a \"current session\" would let every hermetic test pass against a contract\n // production no longer signs, which is the failure this file's own header already warns about.\n const liveSessions = new Set<string>()\n\n function handleFor(id: string, opened: OpenedChatSession): ChatSessionHandle {\n let live = true\n const requireLive = (verb: string): void => {\n if (!live) {\n throw new TypeError(\n `a chat session ${verb} cannot go through a closed handle for ${id}. Open the session `\n + 'again to write to it.',\n )\n }\n }\n liveSessions.add(id)\n return {\n header: opened.header,\n events: opened.events,\n refusedLines: opened.refusedLines,\n append(event: ChatSessionEvent): Promise<void> {\n requireLive('event')\n sessions.get(id)!.events.push(event)\n return Promise.resolve()\n },\n turnBoundary(): Promise<void> {\n // A no-op because there is nothing to sync — and a REFUSAL after close, so the twin\n // answers the same question the disk adapter does rather than a laxer one.\n requireLive('turn boundary')\n return Promise.resolve()\n },\n close(): Promise<void> {\n if (live) {\n live = false\n liveSessions.delete(id)\n }\n return Promise.resolve()\n },\n }\n }\n\n return {\n open(sessionId?: string): Promise<ChatSessionHandle> {\n if (sessionId !== undefined) {\n const existing = sessions.get(sessionId)\n // The same refusal the disk adapter raises, and deliberately the same class: a test that\n // proves the refusal against this twin proves it about the vocabulary production uses.\n if (existing === undefined) throw new UnknownChatSessionError(sessionId)\n if (liveSessions.has(sessionId)) throw new ChatSessionBusyError(sessionId)\n // THE SAME REPAIR PATH, not a twin of it. A hermetic test that resumed a dangling session\n // here and saw no synthesized abort would be passing against a contract production does\n // not sign. The events are re-serialized so they enter `repairSession` exactly as disk\n // lines do — the twin cannot produce a torn line or a damaged one, which is precisely why\n // it must not get its own shortcut for deciding what a resumed session means.\n const repair = repairSession(\n existing.events.map((event, index) => ({\n lineNumber: index + 2,\n text: JSON.stringify(event),\n })),\n { declaredVersion: existing.header.schemaVersion, now: options.now },\n )\n existing.events.push(...repair.synthesized)\n return Promise.resolve(\n handleFor(sessionId, {\n header: existing.header,\n events: [...existing.events],\n // Always empty here, and that is the honest answer rather than a placeholder: this\n // twin stores typed records, so no line of it can be damaged in the way a file's can.\n refusedLines: repair.refusedLines,\n }),\n )\n }\n const createdAt = options.now()\n const id = mintChatSessionId(createdAt, random)\n const header: ChatSessionHeader = {\n schemaVersion: CURRENT_CHAT_SESSION_SCHEMA_VERSION,\n sessionId: id,\n createdAt,\n model: options.model(),\n toolsetHash: options.toolsetHash(),\n }\n sessions.set(id, { header, events: [] })\n return Promise.resolve(handleFor(id, { header, events: [], refusedLines: [] }))\n },\n\n snapshot(sessionId: string): OpenedChatSession | undefined {\n const found = sessions.get(sessionId)\n return found === undefined\n ? undefined\n : { header: found.header, events: [...found.events], refusedLines: [] }\n },\n }\n}\n"],"mappings":"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AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,6BAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,wBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,uBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,wBAAwB;AAAA,EACxB;AAAA,OACK;AAYP,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA,cAAAC;AAAA,EAEA;AAAA,EACA,eAAAC;AAAA,EACA;AAAA,EACA,cAAAC;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA,WAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACvLP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA8BA,SAAS,0BACd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","names":["dirname","dirname","existsSync","FsEvidenceArtifactStore","RUNS_SUBDIR","slugBranch","slugBranch","randomUUID","existsSync","readdirSync","readFileSync","dirname","join","DatabaseSync","foldQuarantineLedgerState","readQuarantineLedger","openKnowledgeReader","FsEventLog","RUNS_SUBDIR","slugBranch","asJobId","dirname","join","closeSync","fsyncSync","mkdirSync","openSync","readFileSync","writeFileSync","isAbsolute","join","randomUUID","closeSync","fsyncSync","openSync","renameSync","rmSync","writeFileSync","dirname","isAbsolute","join","canonicalJson","JOB_CHECKPOINT_SCHEMA_VERSION","openSync","writeFileSync","fsyncSync","closeSync","renameSync","rmSync","isAbsolute","join","JOB_CHECKPOINT_SCHEMA_VERSION","dirname","randomUUID","canonicalJson","SAFE_PATH_SEGMENT","mkdirSync","openSync","writeFileSync","fsyncSync","closeSync","readFileSync","isSwallowableDirectoryFsyncError","isAbsolute","join","id","header","existsSync","join","DatabaseSync","canonicalJson","guardRunNotification","isJobKind","sha256hex","mkdirSync","dirname","DatabaseSync","QuarantinedJobRequeueError","StaleJobStoreEpochError","canonicalJson","sha256hex","readdirSync","readFileSync","join","canonicalJson","mkdirSync","dirname","DatabaseSync","StaleJobStoreEpochError","options","QuarantinedJobRequeueError","canonicalJson","sha256hex","sha256hex","canonicalJson","toNumber","isJobKind","join","existsSync","DatabaseSync","guardRunNotification","join","dirname","openKnowledgeReader","RUNS_SUBDIR","existsSync","readdirSync","FsEventLog","readFileSync","randomUUID","DatabaseSync","slugBranch","asJobId","foldQuarantineLedgerState","readQuarantineLedger","opened","join","createAgentJobQueue","createRealJobKindRegistry","join","createRealJobKindRegistry","createAgentJobQueue","repairSession","CURRENT_CHAT_SESSION_SCHEMA_VERSION","repairSession","CURRENT_CHAT_SESSION_SCHEMA_VERSION"]}
1
+ {"version":3,"sources":["../src/composition/run-composition.ts","../src/composition/knowledge-budgets.ts","../src/composition/knowledge-reader.ts","../src/composition/run-invocation-core.ts","../src/composition/run-drive-vocabulary.ts","../src/composition/evidence-blob-reader.ts","../src/composition/quarantine-snapshot.ts","../src/composition/quarantine-vocabulary.ts","../src/composition/compose-local-agent.ts","../src/composition/knowledge-review-reader.ts","../src/analysis/persist-analysis.ts","../src/session/jsonl-session-log.ts","../src/store/job-checkpoint-store.ts","../src/store/store-errors.ts","../src/store/post-processing-reader.ts","../src/store/sqlite-job-store.ts","../src/store/logical-dump.ts","../src/composition/build-ordinals.ts","../src/store/mark-ledger.ts","../src/composition/run-layout.ts","../src/store/mark-lock.ts","../src/composition/action-cache.ts","../src/composition/compose-job-recovery.ts","../src/session/memory-session-log.ts"],"sourcesContent":["// The run composition both hosts build a `RunConfig` from, without importing a CLI.\n\nimport { createHash } from 'node:crypto'\nimport { dirname, isAbsolute, resolve } from 'node:path'\nimport { detectExecutionContext } from '@vostride/agent-qa-safety-local'\nimport { guardToolOutput } from '@vostride/agent-qa-model'\nimport type { TokenAccounting } from '@vostride/agent-qa-model'\nimport type {\n ModelCapabilities,\n RecordedRetrievalRung,\n RecordId,\n ReadTrace,\n ScopeKey,\n} from '@vostride/agent-qa-schema'\nimport {\n FsEventLog,\n FsEvidenceArtifactStore,\n FsHandoffStore,\n FsRunArtifactStore,\n nextBuildOrdinal,\n recordBuildTag,\n RUNS_SUBDIR,\n slugBranch,\n SharpScreenshotCompressor,\n} from '@vostride/agent-qa-runner-local'\nimport type { ScreenshotCompressorLogger } from '@vostride/agent-qa-runner-local'\nimport {\n coerceRunJSResult,\n createMemoryTools,\n createRecordLedger,\n liveStreamFor,\n resolveSecretEnv,\n resolveSecretTemplatesInValue,\n} from '@vostride/agent-qa-runner'\nimport type {\n Action,\n AccessibilityCheckHandler,\n ActionPlanCache,\n AppiumScriptHandler,\n ConfigDigests,\n EventLogPort,\n EvidenceArtifactStorePort,\n FailureScreenshotWriter,\n HandoffStorePort,\n HookDefinition,\n HookExecutorPort,\n LoopLogger,\n MemberEventSink,\n MemberRunConfig,\n MemberStepSpec,\n MemberTest,\n MemberTestExecutor,\n MemberTestRunContext,\n NonActionToolMap,\n PlannerConfig,\n Planner,\n PlatformAdapter,\n KnowledgeHintReader,\n PostVerdictPort,\n RecordLedger,\n RunArtifactStorePort,\n RunJsHandler,\n RunMemberDescriptor,\n SandboxRunnerOptions,\n ScreenshotCompressor,\n SecretRedactorPort,\n SecretStore,\n StorageStatePort,\n TestResult,\n Verifier,\n WorkingMemoryPort,\n} from '@vostride/agent-qa-runner'\nimport {\n computeKnowledgeBudgets,\n memoryToolGate,\n scaledRecordCap,\n type KnowledgeBudgets,\n} from './knowledge-budgets.js'\nimport { constructKnowledgeReader } from './knowledge-reader.js'\nimport type { ConstructKnowledgeReaderInput } from './knowledge-reader.js'\n\n// ---- Local structural types -----------------------------------------------------------------\n\n/** Mirror of schema's ExecutionContext union (safety-local's detectExecutionContext returns it). */\nexport type RunExecutionContext = 'local-interactive' | 'local-headless' | 'ci' | 'cloud'\n\n// The runner's own model type, which keeps a provider-substrate edge off this package.\ntype RunLanguageModel = MemberRunConfig['plannerModel']\n\n/** The message shape the token accountant estimates, taken from the accountant's own signature. */\ntype AccountedMessage = Parameters<TokenAccounting['estimate']>[0][number]\n\n// ---- (0) run-scoped knowledge serving composition ----------\n\ntype KnowledgeAccounting = Pick<TokenAccounting, 'estimate' | 'getCeilings'>\n\n// Injected, because a second importer of knowledge-local's main entry breaks the singleton rule.\nexport type RetrievalRungResolver = (\n options: { knowledgeRoot: string; agentQaRoot?: string },\n) => Promise<RecordedRetrievalRung>\n\nexport interface RunKnowledgeComposition {\n reader: KnowledgeHintReader\n budgets: KnowledgeBudgets\n // A promise awaited once by the first recorder; the rung dates the serve and is never re-probed.\n retrievalRung: Promise<RecordedRetrievalRung>\n recordLedger: RecordLedger\n nonActionTools?: NonActionToolMap\n beginMemoryTurn?: (scope?: ScopeKey, exposedIds?: readonly RecordId[]) => void\n drainMemoryReadTraces?: () => ReadTrace[]\n}\n\nexport interface OpenRunKnowledgeCompositionInput {\n knowledgeRoot: string\n product?: string\n scope: ScopeKey\n /** Known containing scopes for a member (the suite scope on prepared-suite runs). */\n parentScopes?: readonly ScopeKey[]\n asOfBuild: number\n capabilities: ModelCapabilities\n accounting: KnowledgeAccounting\n qaRulesText: string\n workingContextText: string\n // The runtime root the embedder probe finds its worker under; absent uses the acquirer's rule.\n agentQaRoot?: string\n // Production passes `resolveHostRetrievalRung`; tests pass a fake and never touch the host.\n resolveRetrievalRung: RetrievalRungResolver\n}\n\n/**\n * Open and bind the complete serving stack once per run/planner scope. The composition root can\n * estimate only prompt material it owns, so `qaRulesText` is the run-start capability/rules appendix\n * and `workingContextText` is the resolved suite/test context plus steps. Both ride the same model\n * accounting estimator as planning calls; static runner rules remain covered by the reserved\n * output and conservative fractional allocation rather than a second character heuristic.\n */\nexport function openRunKnowledgeComposition(\n input: OpenRunKnowledgeCompositionInput,\n): RunKnowledgeComposition {\n const ceilings = input.accounting.getCeilings()\n const qaRulesTokens = input.accounting.estimate([\n { role: 'system', content: input.qaRulesText } as AccountedMessage,\n ])\n const workingContextTokens = input.accounting.estimate([\n { role: 'user', content: input.workingContextText } as AccountedMessage,\n ])\n const computed = computeKnowledgeBudgets({\n contextWindow: ceilings.contextWindow,\n reservedOutput: ceilings.maxOutput,\n qaRulesTokens,\n workingContextTokens,\n })\n const budgets: KnowledgeBudgets = {\n ...computed,\n recordCap: scaledRecordCap(input.capabilities),\n }\n const reader = constructKnowledgeReader({\n knowledgeRoot: input.knowledgeRoot,\n ...(input.product === undefined ? {} : { product: input.product }),\n ...(input.parentScopes === undefined ? {} : { parentScopes: input.parentScopes }),\n asOfBuild: input.asOfBuild,\n recordCap: budgets.recordCap,\n })\n // A no-op catch, because nothing awaits the probe until the first step's recorder does.\n const retrievalRung = input.resolveRetrievalRung({\n knowledgeRoot: input.knowledgeRoot,\n ...(input.agentQaRoot === undefined ? {} : { agentQaRoot: input.agentQaRoot }),\n })\n retrievalRung.catch(() => undefined)\n const channel2Enabled = memoryToolGate(input.capabilities)\n const recordLedger = createRecordLedger({\n cap: budgets.recordCap,\n budget: budgets.brief + budgets.caution + (channel2Enabled ? budgets.searchResults : 0),\n seedRecords: [],\n })\n\n // Non-action memory registers only for capable models; no model-visible flag enables Channel 2.\n const memory = channel2Enabled\n ? createMemoryTools({\n reader,\n scope: input.scope,\n asOfBuild: input.asOfBuild,\n searchResultBudget: budgets.searchResults,\n readBodyBudget: budgets.readBody,\n recordLedger,\n estimateTokens: (text) => input.accounting.estimate([\n { role: 'user', content: text } as AccountedMessage,\n ]),\n })\n : undefined\n\n return {\n reader,\n budgets,\n retrievalRung,\n recordLedger,\n nonActionTools: memory?.tools,\n beginMemoryTurn: memory?.beginTurn,\n drainMemoryReadTraces: memory?.drainReadTraces,\n }\n}\n\n// ---- (1) computeRunConfigDigests — the ONE digest mint --------------------------------\n\n/** One member's file inputs to the digest mint. `suiteFileContent` is absent on the single-test path. */\nexport interface RunDigestMemberInput {\n testFileContent: string\n suiteFileContent?: string\n}\n\n// Both pairs come from one call, so run identity and handoff identity cannot fork.\nexport interface RunConfigDigests {\n runLevel: ConfigDigests\n perMember: ConfigDigests[]\n}\n\n/** 16-hex SHA-256 digest of a UTF-8 string, the `sha256hex16` value. */\nfunction digest16(input: string): string {\n return createHash('sha256').update(input, 'utf8').digest('hex').slice(0, 16)\n}\n\n// Run-level digests hash the ordered member digests; a single-member run keeps the member's values.\nexport function computeRunConfigDigests(input: {\n configContent: string\n members: readonly RunDigestMemberInput[]\n}): RunConfigDigests {\n const perMember: ConfigDigests[] = input.members.map((m) => ({\n suiteConfigDigest: digest16(input.configContent + '\\n' + (m.suiteFileContent ?? '')),\n testConfigDigest: digest16(m.testFileContent),\n }))\n\n if (perMember.length === 1) {\n // Single-member runs collapse the run-level pair to the member values.\n return { runLevel: { ...perMember[0] }, perMember }\n }\n\n const distinctSuiteDigests: string[] = []\n const seen = new Set<string>()\n for (const pair of perMember) {\n if (!seen.has(pair.suiteConfigDigest)) {\n seen.add(pair.suiteConfigDigest)\n distinctSuiteDigests.push(pair.suiteConfigDigest)\n }\n }\n\n const runLevel: ConfigDigests = {\n suiteConfigDigest: digest16(distinctSuiteDigests.join('\\n')),\n testConfigDigest: digest16(perMember.map((p) => p.testConfigDigest).join('\\n')),\n }\n\n return { runLevel, perMember }\n}\n\n// ---- (2) resolveRunExecutionContext — canonical resolver ------------------------------\n\n// An explicit override wins over safety-local's `detectExecutionContext`.\nexport function resolveRunExecutionContext(override?: RunExecutionContext): RunExecutionContext {\n return detectExecutionContext(override) as RunExecutionContext\n}\n\n// ---- (3) buildRunPorts + buildOrdinal — runner-local persistence tier -------\n\n/** The durable run ports the shell wires behind `RunConfig.ports` (event log + handoff + artifact). */\nexport interface RunPersistencePorts {\n eventLog: EventLogPort\n handoffStore: HandoffStorePort\n runArtifactStore: RunArtifactStorePort\n // Built once from the same root and run id: the one instance every member persists into.\n evidenceArtifacts: EvidenceArtifactStorePort\n // Declared here too, because `assembleCliRun` spreads this interface into `RunConfig.ports`.\n onSubscriberFault?: (code: string, message: string) => void\n // Declared here for the same spread, and threaded from the host; `buildRunPorts` never builds it.\n postVerdict?: PostVerdictPort\n}\n\n// All four stores write under one `<configDir>/.agent-qa/runs/<slug(runId)>/` directory.\nexport function buildRunPorts(input: { configDir: string; runId: string }): RunPersistencePorts {\n const root = resolve(input.configDir, '.agent-qa')\n return {\n eventLog: new FsEventLog({ root, runId: input.runId }),\n handoffStore: new FsHandoffStore({ root, runId: input.runId }),\n runArtifactStore: new FsRunArtifactStore({ root, runId: input.runId }),\n evidenceArtifacts: new FsEvidenceArtifactStore({ root, runId: input.runId }),\n // A NAMED, observable, non-durable destination: greppable by code, visible to a test through\n // `process.once('warning', …)`, and no `console.` call in a package that makes none.\n onSubscriberFault: (code, message) => {\n process.emitWarning(message, { code })\n },\n }\n}\n\n// Built at the composition root, the sharp host adapter's home, and injected into every member.\nexport function buildScreenshotCompressor(logger?: ScreenshotCompressorLogger): ScreenshotCompressor {\n return new SharpScreenshotCompressor(logger)\n}\n\n// Resolves build-tag precedence without reading ambient process state.\nexport function resolveBuildTagSetting(input: {\n flag?: string\n env?: string\n use?: { buildTag?: string }\n}): string | undefined {\n for (const value of [input.flag, input.env, input.use?.buildTag]) {\n const trimmed = value?.trim()\n if (trimmed) return trimmed\n }\n return undefined\n}\n\n// Both files are lock-free, best-effort runtime state; the ordinal rides `RunConfig.buildOrdinal`.\nexport async function resolveRunBuildOrdinal(input: {\n configDir: string\n product: string\n buildTag?: string\n}): Promise<number> {\n const root = resolve(input.configDir, '.agent-qa')\n const ordinal = await nextBuildOrdinal({ root, product: input.product })\n if (input.buildTag !== undefined) {\n await recordBuildTag({\n root,\n product: input.product,\n tag: input.buildTag,\n ordinal,\n })\n }\n return ordinal\n}\n\n// ---- (4) createSuiteLifecycle — lazy per-suite setup/teardown --------------------------------\n\n// One lane for all suites: members share their suite's single adapter page, so they cannot overlap.\nexport const SUITE_LIFECYCLE_LANE = 'suite-lifecycle'\n\n/** The setup/teardown pair a suite runs when it first becomes active / when it is torn down. */\nexport interface SuiteLifecycleHooks {\n /** Suite-level setup: setup hooks + adapter.setup + suite-URL navigation. */\n setup(): Promise<void>\n /** Suite-level teardown: teardown hooks + auth-state capture (when all passed) + adapter.cleanup. */\n teardown(): Promise<void>\n}\n\n// Held from admission until the member settles; the suite cannot tear down while a hold is out.\nexport interface SuiteMemberLease {\n /** Drop this member's hold. Idempotent — a double release never double-decrements. */\n release(): void\n}\n\n// Tearing down the live suite instead would close the browser under a running test.\nexport class SuiteBoundaryWhileLiveError extends Error {\n constructor(\n readonly activeSuiteKey: string,\n readonly requestedSuiteKey: string,\n readonly liveMembers: number,\n ) {\n super(\n `Cannot enter suite \"${requestedSuiteKey}\": suite \"${activeSuiteKey}\" still has ` +\n `${liveMembers} live member(s). Suite boundaries are serialized.`,\n )\n this.name = 'SuiteBoundaryWhileLiveError'\n }\n}\n\nexport interface SuiteLifecycle {\n /**\n * Admit a member to `suiteKey` and resolve once the suite is ready. The FIRST member to arrive\n * starts the suite's setup; every other member of that suite awaits the SAME setup promise\n * rather than starting a second one. Crossing a suite boundary tears down the previous suite —\n * but only once its last member has released; a boundary crossed while members are live is a\n * {@link SuiteBoundaryWhileLiveError}, never a silent teardown.\n *\n * The returned {@link SuiteMemberLease} MUST be released when the member settles (pass or fail);\n * `buildSuiteMemberExecutor` does it in a `finally`.\n */\n ensureReady(suiteKey: string, hooks: SuiteLifecycleHooks): Promise<SuiteMemberLease>\n /** Tear down the last active suite (if any). Called once at run end after `session.done`. */\n finalize(): Promise<void>\n}\n\n// Key, teardown and setup latch are assigned synchronously before any await, so setup runs once.\nexport function createSuiteLifecycle(): SuiteLifecycle {\n let activeKey: string | undefined\n let activeSetup: Promise<void> | undefined\n let activeTeardown: (() => Promise<void>) | undefined\n let liveMembers = 0\n\n const tearDownActive = async (): Promise<void> => {\n const teardown = activeTeardown\n activeKey = undefined\n activeSetup = undefined\n activeTeardown = undefined\n liveMembers = 0\n if (teardown) await teardown()\n }\n\n return {\n async ensureReady(suiteKey, hooks) {\n if (activeKey !== undefined && activeKey !== suiteKey) {\n if (liveMembers > 0) {\n throw new SuiteBoundaryWhileLiveError(activeKey, suiteKey, liveMembers)\n }\n await tearDownActive()\n }\n\n if (activeKey !== suiteKey) {\n // THE ONCE-LATCH. All three assignments are synchronous and happen before the setup body\n // can suspend, so the check above and the state below can never be split by an await.\n activeKey = suiteKey\n activeTeardown = hooks.teardown\n activeSetup = (async () => {\n try {\n await hooks.setup()\n } catch (error) {\n // A suite that never came up has nothing to take down, and the latch stays rejected so\n // every later member of this suite inherits the same failure instead of retrying.\n activeTeardown = undefined\n throw error\n }\n })()\n }\n\n const setup = activeSetup\n // Counted BEFORE the await: a boundary crossing that races this member must see the hold.\n liveMembers += 1\n let released = false\n const lease: SuiteMemberLease = {\n release() {\n if (released) return\n released = true\n liveMembers -= 1\n },\n }\n try {\n await setup\n } catch (error) {\n lease.release()\n throw error\n }\n return lease\n },\n async finalize() {\n await tearDownActive()\n },\n }\n}\n\n// ---- (5) buildSuiteMemberExecutor — the MemberTestExecutor closure ---------------------\n\n/**\n * One prepared suite member: its suite key + lifecycle hooks (setup runs on the first member of\n * that suite) and a `run(ctx)` that builds the member's bound `SuiteMemberInput` around core's\n * per-test machinery and returns `executeSuiteMember(...)` with the shell-provided ctx seams\n * (abortSignal, events, per-member configDigests) threaded in.\n */\nexport interface SuiteMemberBinding {\n suiteKey: string\n hooks: SuiteLifecycleHooks\n // Read only to declare its live stream, after `ensureReady` runs `setup()`, before step one.\n adapter?: PlatformAdapter\n run(ctx: MemberTestRunContext): Promise<TestResult>\n}\n\n// A continuous stream gets the labelled 1s snapshot fallback; with neither, nothing registers.\nexport function registerAdapterLiveStream(\n ctx: MemberTestRunContext,\n adapter: PlatformAdapter | undefined,\n): void {\n const registration = liveStreamFor(adapter)\n ctx.registerLiveStream?.(registration?.capability, registration?.fallback)\n}\n\n// Looks the binding up by `testIndex`, the authoritative array position, then readies its suite.\nexport function buildSuiteMemberExecutor(input: {\n lifecycle: SuiteLifecycle\n bindings: readonly SuiteMemberBinding[]\n}): MemberTestExecutor {\n return async (member: RunMemberDescriptor, ctx: MemberTestRunContext): Promise<TestResult> => {\n const binding = input.bindings[ctx.testIndex]\n if (!binding) {\n throw new Error(`No suite-member binding for testIndex ${ctx.testIndex} (testId ${member.testId})`)\n }\n const lease = await input.lifecycle.ensureReady(binding.suiteKey, binding.hooks)\n try {\n // The suite is up, so the member's live stream is declarable before its first step.\n registerAdapterLiveStream(ctx, binding.adapter)\n return await binding.run(ctx)\n } finally {\n // The hold is dropped on EVERY exit, throw included — a leaked hold would block the next\n // suite's boundary forever with a SuiteBoundaryWhileLiveError.\n lease.release()\n }\n }\n}\n\n// The run directory, extracted so the collision refusal asks the same path the artifacts use.\nexport function runDirFor(input: { configDir: string; runId: string }): string {\n return resolve(input.configDir, '.agent-qa', RUNS_SUBDIR, slugBranch(input.runId))\n}\n\n// ---- (9) member-run-config builder --------------------------------------------------\n\n// Best-effort: `undefined` when the adapter cannot screenshot or capture throws.\nasync function captureFailureScreenshotFromAdapter(adapter: PlatformAdapter): Promise<Buffer | undefined> {\n try {\n const shot = (adapter as { screenshot?: () => Promise<Buffer> }).screenshot\n if (typeof shot !== 'function') return undefined\n return await shot.call(adapter)\n } catch {\n return undefined\n }\n}\n\n// Web-only: a page-less adapter returns a `[runJS error: …]` value the runner splices in.\nfunction buildRunJsHandler(adapter: PlatformAdapter): RunJsHandler {\n return async (code, ctx) => {\n if (adapter.platform !== 'web') {\n return { value: '[runJS error: runJS is only supported on web platform]', error: 'runJS is only supported on web platform' }\n }\n const page = 'getPage' in adapter\n ? (adapter as { getPage: () => { evaluate: (c: string) => Promise<unknown> } | undefined }).getPage()\n : undefined\n if (!page) {\n return { value: '[runJS error: no browser page available]', error: 'no browser page available' }\n }\n void ctx\n const raw = await page.evaluate(code)\n return { value: coerceRunJSResult(raw) }\n }\n}\n\n// Resolves secret templates in the action before executing it on the adapter.\nfunction buildAppiumScriptHandler(adapter: PlatformAdapter, secretStore?: SecretStore): AppiumScriptHandler {\n return async (action) => adapter.execute(resolveSecretTemplatesInValue(action as Action, secretStore) as Action)\n}\n\n// A lost page is a capture failure, never a successful zero-violation check.\nfunction buildAccessibilityCheckHandler(adapter: PlatformAdapter): AccessibilityCheckHandler {\n return async (opts) => {\n const page = 'getPage' in adapter ? (adapter as { getPage: () => unknown }).getPage() : undefined\n if (!page) throw new Error('Accessibility capture requires an active browser page')\n const web = await import('@vostride/agent-qa-web')\n return web.runAccessibilityCheck(page as any, opts)\n }\n}\n\n/** Build the injected failure-screenshot writer. Captures from the adapter into the member's\n * `result.screenshot` (in-run buffer, the same artifact the reporter subscribers persist beside the\n * run dir). */\nfunction buildFailureScreenshotWriter(adapter: PlatformAdapter): FailureScreenshotWriter {\n return async () => captureFailureScreenshotFromAdapter(adapter)\n}\n\n/** The runner-owned `MemberTest` shape derived from a resolved (already suite-patched) TestDefinition.\n * `filePath` is the member's own file. A suite-patched test carries no `url` (the suite owns nav), so\n * `runMemberTest` skips the per-test navigate for suite members. */\nexport function toMemberTest(test: any, filePath: string): MemberTest {\n return {\n testId: (test['test-id'] as string | undefined) ?? test.name,\n name: test.name,\n filePath,\n url: test.url as string | undefined,\n context: test.context as string | undefined,\n steps: test.steps as Array<string | MemberStepSpec>,\n meta: test.meta as MemberTest['meta'],\n }\n}\n\n// Handlers are built here from `adapter` and `secretStore`, so the two executor sites cannot drift.\nexport interface BuildMemberRunConfigInput {\n // loop host impls\n adapter: PlatformAdapter\n planner: Planner\n verifier: Verifier\n cache?: ActionPlanCache\n workingMemory?: WorkingMemoryPort\n storageState?: StorageStatePort\n compressor?: ScreenshotCompressor\n knowledgeReader?: KnowledgeHintReader\n // The composed rung, carried untouched to the loop's evidence recorder.\n knowledgeRetrievalRung?: Promise<RecordedRetrievalRung>\n knowledgeBudgets?: KnowledgeBudgets\n knowledgeAsOfBuild?: number\n recordLedger?: RecordLedger\n beginMemoryTurn?: (scope?: ScopeKey, exposedIds?: readonly RecordId[]) => void\n drainMemoryReadTraces?: () => ReadTrace[]\n configDigests?: ConfigDigests\n // models\n plannerModel: RunLanguageModel\n verifierModel: RunLanguageModel\n stepModelScope?: MemberRunConfig['stepModelScope']\n // variable seeds\n envFileVars?: Record<string, string>\n inlineVars?: Record<string, string>\n suiteVars?: Record<string, string>\n cliVars?: Record<string, string>\n hookSetupVars?: Record<string, string>\n // inline hooks\n inlineHookDefs?: Map<string, HookDefinition>\n sandboxOptions?: SandboxRunnerOptions\n // secrets — the concrete SecretStore (superset of SecretResolver); resolveSecretEnv needs forEachSecret.\n secretStore?: SecretStore\n secretRedactor?: SecretRedactorPort\n // per-member ctx (bound by the run shell)\n sink: MemberEventSink\n testIndex: number\n abortSignal: AbortSignal\n // The run-scoped evidence store the shell threads onto the member context.\n evidenceArtifacts?: EvidenceArtifactStorePort\n // run config\n captureScreenshots?: boolean\n accessibility?: MemberRunConfig['accessibility']\n timeouts?: MemberRunConfig['timeouts']\n plannerConfig?: PlannerConfig\n logger?: LoopLogger\n logCapture?: { console?: boolean; network?: boolean }\n vision?: { screenshotSize?: number; effectiveResolution?: number }\n visionGate?: { attachImage: boolean; captureMode: 'full' | 'textOnly'; promptNote: string }\n contextWindow?: number\n suiteContext?: string\n /** The member's own file, for the core-parity fileUpload path resolver. */\n filePath: string\n}\n\n// Wires the adapter-backed handlers and the secret and upload-path resolvers for `runMemberTest`.\nexport function buildMemberRunConfig(input: BuildMemberRunConfigInput): MemberRunConfig {\n const sandbox = input.sandboxOptions\n return {\n adapter: input.adapter,\n planner: input.planner,\n verifier: input.verifier,\n cache: input.cache,\n workingMemory: input.workingMemory,\n storageState: input.storageState,\n // The model's canonical compaction applies to every tool-output value.\n guardBlob: guardToolOutput,\n compressor: input.compressor,\n knowledgeReader: input.knowledgeReader,\n knowledgeRetrievalRung: input.knowledgeRetrievalRung,\n knowledgeBudgets: input.knowledgeBudgets,\n knowledgeAsOfBuild: input.knowledgeAsOfBuild,\n recordLedger: input.recordLedger,\n beginMemoryTurn: input.beginMemoryTurn,\n drainMemoryReadTraces: input.drainMemoryReadTraces,\n configDigests: input.configDigests,\n\n plannerModel: input.plannerModel,\n verifierModel: input.verifierModel,\n stepModelScope: input.stepModelScope,\n\n envFileVars: input.envFileVars,\n inlineVars: input.inlineVars,\n suiteVars: input.suiteVars,\n cliVars: input.cliVars,\n hookSetupVars: input.hookSetupVars,\n\n // Inline hooks: the runner-local DockerHookExecutor + sandbox env/authState come off the resolved\n // sandbox options; the per-run secret env is resolved store-side (never crosses into the runner).\n hookExecutor: sandbox?.executor as HookExecutorPort | undefined,\n inlineHookDefs: input.inlineHookDefs,\n hookEnvVars: sandbox?.envVars,\n hookSecretEnv: resolveSecretEnv(input.secretStore),\n hookAuthState: sandbox?.authState,\n\n runJs: buildRunJsHandler(input.adapter),\n appiumScript: buildAppiumScriptHandler(input.adapter, input.secretStore),\n accessibilityCheck: 'getPage' in input.adapter && typeof input.adapter.getPage === 'function'\n ? buildAccessibilityCheckHandler(input.adapter)\n : undefined,\n persistFailureScreenshot: buildFailureScreenshotWriter(input.adapter),\n\n resolveSecrets: (text: string) => resolveSecretTemplatesInValue(text, input.secretStore),\n secretStore: input.secretStore,\n secretRedactor: input.secretRedactor,\n\n sink: input.sink,\n testIndex: input.testIndex,\n abortSignal: input.abortSignal,\n evidenceArtifacts: input.evidenceArtifacts,\n\n captureScreenshots: input.captureScreenshots,\n accessibility: input.accessibility,\n timeouts: input.timeouts,\n plannerConfig: input.plannerConfig,\n logger: input.logger,\n logCapture: input.logCapture,\n vision: input.vision,\n visionGate: input.visionGate,\n contextWindow: input.contextWindow,\n suiteContext: input.suiteContext,\n resolveUploadPath: (rawPath: string) =>\n isAbsolute(rawPath) ? rawPath : resolve(dirname(input.filePath), rawPath),\n }\n}\n","// The budget arithmetic touches no terminal, so it sits beside the reader binding it sizes.\n\nimport type { ModelCapabilities } from '@vostride/agent-qa-schema'\n\n/** Provisional share of usable model context reserved for the frozen Channel-1 brief. */\nexport const BRIEF_FRACTION = 0.05\n\n/** Provisional share of usable model context reserved for one-shot Channel-3 cautions. */\nexport const CAUTION_FRACTION = 0.01\n\n/** Provisional non-zero Channel-1 floor; field evidence may tune it in a later milestone. */\nexport const MIN_BRIEF = 256\n\n/** Provisional non-zero Channel-3 floor sized to preserve at least one concise caution line. */\nexport const MIN_CAUTION = 64\n\n/** Provisional upper bound for learned Channel-1 brief tokens, independent of model size. */\nexport const BRIEF_CEILING = 2_048\n\n/** Provisional share of usable context available to cumulative Channel-2 record bodies per turn. */\nexport const READ_BODY_FRACTION = 0.1\n\n/** Provisional hard cap on distinct records admitted across all three channels in one turn. */\nexport const GLOBAL_RECORD_CAP = 24\n\n/** Provisional multiplier applied to the distinct-record cap for gate-failing weak models. */\nexport const WEAK_MODEL_CAP_SCALE = 0.5\n\n/** Provisional minimum context window required before the optional Channel-2 tool surface is useful. */\nexport const MIN_MEMORY_TOOL_CONTEXT_WINDOW = 16_384\n\nexport interface KnowledgeBudgets {\n brief: number\n /** Wrapper-fixed Channel-2 search-result budget; never exposed in the tool schema. */\n searchResults: number\n caution: number\n readBody: number\n recordCap: number\n}\n\nexport interface ComputeKnowledgeBudgetsInput {\n contextWindow: number\n reservedOutput: number\n qaRulesTokens: number\n workingContextTokens: number\n}\n\nfunction floorFinite(value: number): number {\n if (Number.isNaN(value)) return 0\n if (value === Number.POSITIVE_INFINITY) return Number.MAX_SAFE_INTEGER\n if (value === Number.NEGATIVE_INFINITY) return Number.MIN_SAFE_INTEGER\n return Math.floor(value)\n}\n\nfunction clamp(value: number, minimum: number, maximum: number): number {\n return Math.min(maximum, Math.max(minimum, value))\n}\n\n// The raw fraction is floored before the clamp; the reader and loop receive only plain numbers.\nexport function computeKnowledgeBudgets(input: ComputeKnowledgeBudgetsInput): KnowledgeBudgets {\n const usableContext = input.contextWindow\n - input.reservedOutput\n - input.qaRulesTokens\n - input.workingContextTokens\n\n const brief = clamp(\n floorFinite(usableContext * BRIEF_FRACTION),\n MIN_BRIEF,\n BRIEF_CEILING,\n )\n const caution = Math.max(MIN_CAUTION, floorFinite(usableContext * CAUTION_FRACTION))\n const readBody = Math.max(MIN_BRIEF, floorFinite(usableContext * READ_BODY_FRACTION))\n\n // Search entries and Channel-1 learned lines are both summary-sized projections. Reuse the\n // same bounded allocation rather than inventing a model-controlled or unbounded search knob.\n const searchResults = brief\n return { brief, searchResults, caution, readBody, recordCap: GLOBAL_RECORD_CAP }\n}\n\n// Channel 2 is absent when the model cannot call tools, is text-only or has too little context.\nexport function memoryToolGate(capabilities: ModelCapabilities): boolean {\n return capabilities.toolCalling\n && capabilities.vision\n && capabilities.contextWindow >= MIN_MEMORY_TOOL_CONTEXT_WINDOW\n}\n\n// Applies the weak-model cap reduction through the same gate predicate.\nexport function scaledRecordCap(capabilities: ModelCapabilities): number {\n if (memoryToolGate(capabilities)) return GLOBAL_RECORD_CAP\n return Math.max(1, Math.floor(GLOBAL_RECORD_CAP * WEAK_MODEL_CAP_SCALE))\n}\n","import { openKnowledgeReader } from '@vostride/agent-qa-knowledge-local/reader'\nimport type { KnowledgeHintReader, ServedRunBrief } from '@vostride/agent-qa-runner'\nimport type { ScopeKey } from '@vostride/agent-qa-schema'\n\n/** Inputs the composition root resolves when opening the run-scoped knowledge reader. */\nexport interface ConstructKnowledgeReaderInput {\n knowledgeRoot: string\n product?: string\n /** Known containing scopes for a member (the suite scope on prepared-suite runs). */\n parentScopes?: readonly ScopeKey[]\n asOfBuild: number\n recordCap: number\n}\n\n// The memo holds the whole composite, so a repeat serve returns the trace from the real assembly.\nexport function createFrozenKnowledgeReader(reader: KnowledgeHintReader): KnowledgeHintReader {\n const briefs = new Map<string, ServedRunBrief>()\n const scopeKey = (scope: ScopeKey): string => JSON.stringify([scope.tier, scope.key])\n\n return {\n getRunBrief(scope, budget) {\n const key = scopeKey(scope)\n const existing = briefs.get(key)\n if (existing !== undefined) return existing\n const brief = reader.getRunBrief(scope, budget)\n briefs.set(key, brief)\n return brief\n },\n search: (query, options) => reader.search(query, options),\n read: (id, options) => reader.read(id, options),\n getCautions: (anchors, budget) => reader.getCautions(anchors, budget),\n getProcedure: (intent, screenState, availability) =>\n reader.getProcedure(intent, screenState, availability),\n emitCanaryOutcome: (payload) => reader.emitCanaryOutcome(payload),\n }\n}\n\n/**\n * Construct the run-scoped reader through the physically read-only package subpath, then freeze\n * its Channel-1 brief for the lifetime of the run.\n */\nexport function constructKnowledgeReader(\n input: ConstructKnowledgeReaderInput,\n): KnowledgeHintReader {\n return createFrozenKnowledgeReader(openKnowledgeReader({\n knowledgeRoot: input.knowledgeRoot,\n ...(input.product === undefined ? {} : { product: input.product }),\n scopeDefaults: {\n asOfBuild: input.asOfBuild,\n ...(input.parentScopes === undefined ? {} : { parentScopes: input.parentScopes }),\n },\n budgets: { recordCap: input.recordCap },\n }))\n}\n","// Every local run trigger starts here, and id refusals precede assembly, which probes the target.\n\nimport { existsSync } from 'node:fs'\nimport { dirname } from 'node:path'\n\nimport type {\n RunId,\n RunSession,\n RunsStartInput,\n} from '@vostride/agent-qa-schema'\nimport { startRun } from '@vostride/agent-qa-runner'\nimport type { PostVerdictPort, RunConfig } from '@vostride/agent-qa-runner'\n\nimport { buildRunPorts, runDirFor } from './run-composition.js'\nimport type { RunExecutionContext, RunPersistencePorts } from './run-composition.js'\n\n// Types pass through: the composition carve-out admits the runner only under `composition/`.\nexport type {\n BaselineProbeResult,\n ConfigDigests,\n MemberTestExecutor,\n // The post-verdict vocabulary: a host writing the factory below needs the shape it returns.\n PostVerdictOutcome,\n PostVerdictPort,\n PostVerdictStepInput,\n RunConfig,\n RunMemberDescriptor,\n} from '@vostride/agent-qa-runner'\n\n// Schema cannot import the ids package, so the minted-id predicate is passed in beside `mintRunId`.\nexport class RunIdNotMintedError extends Error {\n constructor(readonly runId: string) {\n super(\n `agent-qa cannot start a run under ${JSON.stringify(runId)}: a caller-named run id must be `\n + 'one this system minted. Start the run without naming an id and read the id back off the '\n + 'acknowledgment, or name an id `agent-qa` handed you.',\n )\n this.name = 'RunIdNotMintedError'\n }\n}\n\n// Refused before the record is touched, or a collision appends to the victim's log.\nexport class RunIdAlreadyInUseError extends Error {\n constructor(readonly runId: string) {\n super(\n `agent-qa cannot start a run under ${JSON.stringify(runId)}: that id already names a run in `\n + 'this project. Starting a second run under it would append to the first run\\'s event log '\n + 'and overwrite its handoff. Start the run without naming an id.',\n )\n this.name = 'RunIdAlreadyInUseError'\n }\n}\n\n/**\n * The identity refusals, asked against the run's own directory: an id this system would not have\n * minted, or one that already names a run.\n */\nfunction refuseUnavailableRunId(input: {\n readonly configDir: string\n readonly runId: string\n readonly isMintedRunId: (value: string) => boolean\n}): void {\n if (!input.isMintedRunId(input.runId)) throw new RunIdNotMintedError(input.runId)\n if (existsSync(runDirFor({ configDir: input.configDir, runId: input.runId }))) {\n throw new RunIdAlreadyInUseError(input.runId)\n }\n}\n\n/** What the assembler is handed: everything the core resolved, and nothing it did not. */\nexport interface RunAssemblyContext {\n /** The run's identity, already resolved. The core starts the run under THIS id and no other. */\n readonly runId: string\n /** The caller's request, its run id already checked. */\n readonly request: RunsStartInput\n /** The context the door carried — the same value, so a run cannot record a different one. */\n readonly executionContext: RunExecutionContext\n /** The durable ports, rooted at `<configDir>/.agent-qa`, the evidence check's root. */\n readonly ports: RunPersistencePorts\n /** `dirname(agentQaRoot)` — the project directory the config sits in. */\n readonly configDir: string\n /** The config file this run resolves against (request override honoured). */\n readonly configPath: string\n}\n\n/**\n * Build the `RunConfig` the runner shell starts.\n *\n * A PORT rather than shared code, on `RunExecutionPort`'s own argument: members, executor,\n * reporters and masking are decisions a host answers differently. What crosses into the core is\n * the type; what stays with the door is the assembly. The core supplies the identity fields\n * (`runId` and the markers) over whatever the assembler returns, so a door cannot start a run\n * under an id the caller was not acknowledged with.\n *\n * EVERYTHING WITH A SIDE EFFECT BELONGS HERE, not in the door's pre-flight: the baseline probe\n * (network), the build-ordinal advance (a durable write), the quarantine fold. This function is\n * called below every refusal, so a refused run costs the target nothing.\n */\nexport type RunAssembler = (context: RunAssemblyContext) => Promise<RunConfig> | RunConfig\n\nexport interface RunInvocationCoreOptions {\n /** The config file runs resolve against unless the request names another. */\n readonly configPath: string\n /** The project's runtime root, i.e. `<configDir>/.agent-qa`. */\n readonly agentQaRoot: string\n // Caller-resolved, never sniffed: the context is a fact about the door, not the machine.\n readonly executionContext: RunExecutionContext\n /** Build the `RunConfig`. Called ONLY once every refusal has passed. */\n readonly assembleRun: RunAssembler\n /**\n * Mint a run id when the request carries none.\n *\n * REQUIRED rather than defaulted: the id generator lives in `@vostride/agent-qa-ids` (via core),\n * which this package does not depend on, and a locally invented id shape would be a second\n * spelling of a run's identity. Every shipped door already holds `generateRunId`.\n */\n readonly mintRunId: () => string\n // Required with no fallback: the canonical shape lives in `@vostride/agent-qa-ids`.\n readonly isMintedRunId: (value: string) => boolean\n // Called synchronously before the core awaits the session; the bus replays from seq 1.\n readonly onSession?: (session: RunSession) => void\n // Built once per run after every refusal; absent, the shell reports `detached` with no warning.\n readonly postVerdict?: (input: {\n readonly runId: string\n readonly configDir: string\n }) => PostVerdictPort\n /**\n * The door's own code, awaited once the request and its run id are allowed and before any port.\n * A door opens its run record and loads its plugins here.\n */\n readonly afterRefusal?: () => Promise<void>\n}\n\n// No defensive catch: a hard crash takes the host down, and runner budgets contain the rest.\nexport function createRunInvocationCore(\n options: RunInvocationCoreOptions,\n): { execute(request: RunsStartInput): Promise<{ runId: RunId }> } {\n const configDir = dirname(options.agentQaRoot)\n\n return {\n async execute(request: RunsStartInput): Promise<{ runId: RunId }> {\n // Both refusals sit above `afterRefusal` and assembly, so a refused id changes no byte.\n if (request.runId !== undefined) {\n refuseUnavailableRunId({\n configDir,\n runId: request.runId,\n isMintedRunId: options.isMintedRunId,\n })\n }\n const runId = request.runId ?? options.mintRunId()\n\n // (2) The door's own code runs only for an allowed request, and a failure here still leaves\n // no run directory.\n await options.afterRefusal?.()\n\n // (3) Assembly — the first line that may touch the target, and it is below every refusal.\n const ports = buildRunPorts({ configDir, runId })\n // Spread into the assembler's ports, so it reaches `RunConfig.ports` without the door's help.\n const postVerdict = options.postVerdict?.({ runId, configDir })\n const assembled = await options.assembleRun({\n runId,\n request,\n executionContext: options.executionContext,\n ports: {\n ...ports,\n ...(postVerdict === undefined ? {} : { postVerdict }),\n },\n configDir,\n configPath: request.configPath ?? options.configPath,\n })\n\n // (4) Start. Markers ride from the request to the RunConfig; only a literal `true` carries.\n const session = startRun({\n ...assembled,\n runId: runId as RunId,\n ...(request.gateRun === true ? { gateRun: true as const } : {}),\n ...(request.excludedFromOutcomes === true\n ? { excludedFromOutcomes: true as const }\n : {}),\n })\n\n options.onSession?.(session)\n\n // The handoff is assembled and persisted before `done` resolves (runner shell's terminal\n // sequence), so awaiting it is awaiting the run AND its durable record.\n await session.done\n\n return { runId: runId as RunId }\n },\n }\n}\n","// Re-exported for the CLI drive; the core's ambient-context scan forbids them there.\n\nexport { runSafetyScope } from '@vostride/agent-qa-safety-local'\nexport type { SafetyScopeBundle } from '@vostride/agent-qa-safety-local'\nexport { mapVerdictToExitCode } from '@vostride/agent-qa-runner'\n\n","// Both consumers bind here, and only the run directory tells an unknown run from a missing blob.\n\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { EvidenceBlobReaderPort } from '@vostride/agent-qa-agent'\nimport type { EvidenceBlobLookup, EvidenceBlobPresence, RunId } from '@vostride/agent-qa-schema'\nimport { FsEvidenceArtifactStore, RUNS_SUBDIR, slugBranch } from '@vostride/agent-qa-runner-local'\n\n/** The lowercase 64-hex shape a content address has. The store's own rule, checked before it. */\nconst SHA256_HEX_RE = /^[0-9a-f]{64}$/\n\nexport interface CreateEvidenceBlobReaderInput {\n /** The runtime root, i.e. `<configDir>/.agent-qa` — the parent of `runs/`. */\n readonly agentQaRoot: string\n}\n\n/**\n * THE LOOKUP — one run, one sha, three answers. Synchronous, because the store is.\n *\n * THIS IS THE SHARED RULE, and both consumers below are shapings of it. The analysis job wants\n * bytes-or-nothing and the op wants the three-arm split; writing the rule once and adapting it\n * twice is what keeps \"where does a blob live\" a single sentence in this repository.\n *\n * The regex guard is deliberately redundant with `RunsArtifactInputSchema`: the schema already\n * refused every malformed sha before the op ran, so that branch is unreachable through the shipped\n * path. It stays because an in-layer caller has no schema in front of it, and the alternative to\n * guarding here is handing an unchecked string on toward a `join` — which is the one thing a port\n * implementation may never do, reachable or not.\n */\nfunction runDirectoryExists(input: CreateEvidenceBlobReaderInput, runId: string): boolean {\n // THE RUN-EXISTENCE QUESTION, asked of the directory rather than of a handoff: a run that is\n // mid-flight has a directory and no `handoff.json`, and answering `unknown_run` for it would\n // make a live run's screenshots read as a broken link.\n //\n // ONE FUNCTION RATHER THAN TWO SPELLINGS, because the read and the stat below are the same rule\n // at two costs: a second `existsSync` here is a second definition of what a known run IS, and\n // the day one of them learns about a new layout the other reports a live run as unknown.\n return existsSync(join(input.agentQaRoot, RUNS_SUBDIR, slugBranch(runId)))\n}\n\nexport function lookupEvidenceBlob(\n input: CreateEvidenceBlobReaderInput,\n runId: string,\n sha: string,\n): EvidenceBlobLookup {\n if (!SHA256_HEX_RE.test(sha)) return { status: 'blob_absent' }\n if (!runDirectoryExists(input, runId)) return { status: 'unknown_run' }\n const bytes = new FsEvidenceArtifactStore({ root: input.agentQaRoot, runId }).getBlob(sha)\n return bytes === undefined ? { status: 'blob_absent' } : { status: 'found', bytes }\n}\n\n// The lookup's split, but a stat instead of a read, so annotating refs loads no screenshots.\nexport function statEvidenceBlob(\n input: CreateEvidenceBlobReaderInput,\n runId: string,\n sha: string,\n): EvidenceBlobPresence {\n if (!SHA256_HEX_RE.test(sha)) return 'blob_absent'\n if (!runDirectoryExists(input, runId)) return 'unknown_run'\n return new FsEvidenceArtifactStore({ root: input.agentQaRoot, runId }).hasBlob(sha)\n ? 'found'\n : 'blob_absent'\n}\n\nexport function statEvidenceBlobSize(\n input: CreateEvidenceBlobReaderInput,\n runId: string,\n sha: string,\n): Awaited<ReturnType<NonNullable<EvidenceBlobReaderPort['stat']>>> {\n if (!SHA256_HEX_RE.test(sha)) return { status: 'blob_absent' }\n if (!runDirectoryExists(input, runId)) return { status: 'unknown_run' }\n const byteLength = new FsEvidenceArtifactStore({ root: input.agentQaRoot, runId }).blobSize(sha)\n return byteLength === undefined ? { status: 'blob_absent' } : { status: 'found', byteLength }\n}\n\nexport function readEvidenceBlobRange(\n input: CreateEvidenceBlobReaderInput,\n runId: string,\n sha: string,\n start: number,\n end: number,\n): EvidenceBlobLookup {\n if (!SHA256_HEX_RE.test(sha)) return { status: 'blob_absent' }\n if (!runDirectoryExists(input, runId)) return { status: 'unknown_run' }\n const bytes = new FsEvidenceArtifactStore({ root: input.agentQaRoot, runId }).readBlobRange(sha, start, end)\n return bytes === undefined ? { status: 'blob_absent' } : { status: 'found', bytes }\n}\n\n// Async though the store is not, because a host without local blobs must satisfy the same port.\nexport function createEvidenceBlobReader(\n input: CreateEvidenceBlobReaderInput,\n): EvidenceBlobReaderPort {\n return {\n read: (runId: RunId, sha: string): Promise<EvidenceBlobLookup> =>\n Promise.resolve(lookupEvidenceBlob(input, String(runId), sha)),\n has: (runId: RunId, sha: string): Promise<EvidenceBlobPresence> =>\n Promise.resolve(statEvidenceBlob(input, String(runId), sha)),\n stat: (runId, sha) => Promise.resolve(statEvidenceBlobSize(input, String(runId), sha)),\n readRange: (runId, sha, start, end) =>\n Promise.resolve(readEvidenceBlobRange(input, String(runId), sha, start, end)),\n }\n}\n\n/**\n * The analysis job's shaping: the bytes, or nothing, with the two absences collapsed.\n *\n * THE COLLAPSE IS THIS CALLER'S, not the rule's. An evidence-diet pass has the same work to do\n * whether a run is unknown or its blob was already collected — there is no screenshot either way —\n * so it takes the narrower answer rather than making the shared rule narrower for everyone.\n */\nexport function readEvidenceBlobBytes(\n input: CreateEvidenceBlobReaderInput,\n runId: string,\n sha: string,\n): Uint8Array | undefined {\n const lookup = lookupEvidenceBlob(input, runId, sha)\n return lookup.status === 'found' ? lookup.bytes : undefined\n}\n","// Folded once before `startRun`; a ledger read failure answers an empty set with a warning.\n\nimport { slugBranch } from '@vostride/agent-qa-schema'\nimport type { QuarantineAppliedEntry } from '@vostride/agent-qa-schema'\nimport {\n QUARANTINE_LEDGER_FILENAME,\n foldQuarantineLedgerState,\n readQuarantineLedger,\n} from '@vostride/agent-qa-knowledge-local/reader'\n\nexport interface RunQuarantineSnapshotInput {\n /** The committed knowledge root, already resolved (`resolveKnowledgeRoot`). */\n knowledgeRoot: string\n /** The run's RAW product / scope key; slugged here to match the projection partition law. */\n product: string\n /** Run-start instant as an ISO-8601 string — the ONE clock read, made by the caller. */\n now: string\n warn?: (message: string) => void\n}\n\n// Active entries of this product only; a lapsed entry fails a build before the fold re-enters it.\nexport function resolveRunQuarantineSnapshot(\n input: RunQuarantineSnapshotInput,\n): readonly QuarantineAppliedEntry[] {\n const warn = input.warn ?? ((): void => {})\n const product = slugBranch(input.product)\n\n let read: ReturnType<typeof readQuarantineLedger>\n try {\n read = readQuarantineLedger(input.knowledgeRoot)\n } catch (error) {\n // Includes the typed version refusal: a ledger this build cannot read is surfaced loudly and\n // then treated as absent for THIS run. Suppressing nothing is the safe direction.\n warn(\n `${QUARANTINE_LEDGER_FILENAME} could not be read (${\n error instanceof Error ? error.message : String(error)\n }); no test is quarantined for this run`,\n )\n return []\n }\n\n if (read.refusedLines.length > 0) {\n // Refusal-as-data reaching a human: the healthy entries still apply, and the damaged lines are\n // named by line number so they can be fixed in the file they live in.\n warn(\n `${QUARANTINE_LEDGER_FILENAME} has ${read.refusedLines.length} unreadable line(s) — ${read.refusedLines\n .map((refused) => `line ${refused.lineNumber}: ${refused.reason}`)\n .join('; ')}`,\n )\n }\n\n return foldQuarantineLedgerState(read.events, input.now)\n .filter((entry) => entry.state === 'quarantined' && entry.product === product)\n .map((entry) => ({\n product: entry.product,\n filePath: entry.filePath,\n testName: entry.testName,\n expiresAt: entry.expiresAt,\n }))\n}\n","// The render reads the tables `autoQuarantines` refuses on, so the remedy line and the gate agree.\nexport {\n QUARANTINE_CLASS_DISPOSITIONS,\n QUARANTINE_FLOOR_ELIGIBILITY,\n} from '@vostride/agent-qa-knowledge-local/reader'\nexport type {\n QuarantineDisposition,\n QuarantineFloorEligibility,\n} from '@vostride/agent-qa-knowledge-local/reader'\n","// `packages/agent` may not touch `node:*`, so every host port is built here, once, for both hosts.\n\nimport { randomUUID } from 'node:crypto'\nimport { existsSync, readdirSync, readFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dirname, join } from 'node:path'\nimport { DatabaseSync } from 'node:sqlite'\n\nimport { canaryOutcomeObservationId, planMarkEvidence, projectMarkEvidenceOutcome } from '@vostride/agent-qa-knowledge-local/reader'\nimport {\n AUTHORING_DRAFT_VERIFY_FUNCTION_ID,\n CHAT_HELP_TEXT,\n CHAT_RESOLVER_TABLE,\n createAgentJobQueue,\n createChatCompactionHook,\n createChatState,\n createFunctionRegistry,\n createPlannerStage,\n createRealJobKindRegistry,\n createTurnEngine,\n deterministicOverrideStrategy,\n foldFunctionResult,\n invokeFunction,\n projectPlannerTools,\n RUNS_START_FUNCTION_ID,\n replayToModelMessages,\n splitClauses,\n} from '@vostride/agent-qa-agent'\nimport type {\n AgentJobQueue,\n AuthoringFunnelPortLike,\n CapabilityCatalogPort,\n ChatConfigState,\n ChatDirectiveHandlers,\n ChatLanguageModel,\n ChatStateContainer,\n ChatStateSnapshot,\n ChatTokenAccounting,\n CompactionHook,\n LiveViewPort,\n PlannerStagePort,\n RunDetailReaderPort,\n ReconcileStrategy,\n AnalysisArtifactReaderPort,\n ClockPort,\n ConfigFilesPortLike,\n ConfigReaderPort,\n ConfigScaffoldContentPortLike,\n ConfigValidatePortLike,\n EntityDirectoryPort,\n FunctionDeps,\n FunctionRegistry,\n JobIdSource,\n JobKindRegistry,\n JobModelCapability,\n KnowledgeReaderPort,\n PostRunJobCapabilities,\n RecurrenceLadder,\n RecurrenceProvider,\n RunInvocationPort,\n RunsReaderPort,\n StartedRun,\n StepEvidenceAddress,\n StepEvidenceLookup,\n} from '@vostride/agent-qa-agent'\nimport {\n ADDRESSING_LEDGER_DB_FILE,\n acquireEmbedder,\n acquireWriterLease,\n classifyIndexFace,\n countPendingCurationJobs,\n createMemorySightingSource,\n createLocalKnowledgeStore,\n createQuarantineOperations,\n QUARANTINE_FLAG_FLOOR,\n describeAllEntities,\n embedPendingEntities,\n countRemainingCurationWork,\n deriveWriterLeaseFreshness,\n drainQueue,\n DRAIN_BUDGET_MS,\n EMBEDDER_WORKER_REGISTRATION_FILE,\n EMBEDDER_WORKER_START_TIMEOUT_MS,\n EMBEDDER_WORKER_TERM_GRACE_MS,\n EmbedderWorkerTimeoutError,\n embedderWorkerProcessIsAlive,\n embedderWorkerSocketPath,\n enqueueCurationCandidateProjection,\n failureRecurrence,\n fingerprintRecurrence,\n listTestsInFile,\n foldQuarantineLedgerState,\n foldRetrievalRung,\n foldRunOutcomes,\n createDraftReceiptsStore,\n createSuiteFingerprintIndex,\n indexDbPath,\n readQuarantineLedger,\n readTestOutcomeHistory,\n getEntityDescriptor,\n heartbeatLease,\n inspectDrainableCurationWork,\n isLeaseStale,\n listQueuedCandidates,\n openAddressingLedger,\n openEntityIndex,\n openKnowledgeReader,\n purgeAffectedSetFingerprint,\n probeEmbedderWorkerSocket,\n purgeRecord,\n readCanonicalBundleAnchors,\n readEmbedderWorkerRegistration,\n readWriterLease,\n rebuildIndex,\n reconcileRunOutcomesProjection,\n entityIndexDbPath,\n resolveEntityRef,\n sightEntity,\n refreshWriterLeaseAuthority,\n releaseLease,\n removeEmbedderWorkerRegistration,\n resetEmbedderCapability,\n resolveEmbedderCapability,\n resolveProcessIncarnation,\n verifyEmbedderWorkerIncarnation,\n resolvePurgeAffectedSet,\n resolveRollbackAffectedSet,\n rollbackAffectedSetFingerprint,\n rollbackCampaign,\n rollbackCurationJob,\n runMaintenanceTail,\n sweepEntityIndex,\n RUN_OUTCOMES_PROJECTION_VERSION,\n ENTITY_INDEX_SWEEP_INTERVAL_MS,\n type EmbedderWorkerRegistration,\n type EntityIndexSweepReport,\n type ResolveEntityRefDeps,\n applyExplicitReview,\n appendMarkEvidence,\n triageMark,\n servedIdsOn,\n procedureReadOn,\n applyFeedback,\n enumerateBundleDirs,\n loadBundle,\n verifyBundleIntegrity,\n createAuthoringReader,\n openAddressingLedger as openAddressingLedgerForReview,\n resolveRetrievalRung,\n} from '@vostride/agent-qa-knowledge-local'\nimport type {\n ExplicitReviewDelegate,\n ExplicitReviewRequest,\n ExplicitReviewResult,\n CreateLocalKnowledgeStoreConfig,\n} from '@vostride/agent-qa-knowledge-local'\nimport type { KnowledgeReviewPort } from '@vostride/agent-qa-agent'\nimport type { FeedbackPort, FeedbackReadsPort } from '@vostride/agent-qa-schema'\nimport type { ArtifactRef } from '@vostride/agent-qa-schema'\nimport type { ServedRecordFacts } from '@vostride/agent-qa-knowledge-local'\nexport type { ServedRecordFacts, MarkTriage, ApplyFeedbackInput } from '@vostride/agent-qa-knowledge-local'\nimport { ReplayIncompleteError } from '@vostride/agent-qa-runner'\nimport {\n getActiveExecutionContext,\n setActiveExecutionContextResolver,\n} from '@vostride/agent-qa-safety'\nimport {\n ARTIFACT_FILE,\n FsEventLog,\n FsEvidenceArtifactStore,\n HANDOFF_FILE,\n RUNS_SUBDIR,\n loadCompletedRunHandoff,\n slugBranch,\n} from '@vostride/agent-qa-runner-local'\nimport {\n admitAnalysisArtifactForRun,\n ANALYSIS_FILE,\n asJobId,\n DEFAULT_EMBEDDING_PROFILE,\n guardRunAnalysisArtifact,\n maskPayloadTree,\n sha256hex16,\n} from '@vostride/agent-qa-schema'\nimport type {\n AuthoringBrief,\n AuthoringVerifyDraftInput,\n ChatSessionEvent,\n ChatSessionHandle,\n CompletedRunHandoff,\n DraftReceipt,\n ExecutionContext,\n GateReceipt,\n GateReceiptRecordOutcome,\n KnowledgeChangeOutput,\n KnowledgeChangeVerb,\n MaskFn,\n PromotionOutcome,\n RecordId,\n FunctionCaller,\n JobKind,\n QuarantineEntryStateName,\n QuarantineLadderState,\n RecordedTargets,\n RunEventEnvelope,\n RunId,\n RunStartAcknowledgement,\n TestEditPatchSet,\n TestFileWrite,\n RunsStartInput,\n ScopeKey,\n SessionLogPort,\n} from '@vostride/agent-qa-schema'\n\nimport { createKnowledgeReaderPort } from './knowledge-review-reader.js'\nimport type { SightMemoryEntities } from './knowledge-review-reader.js'\nimport { createEvidenceBlobReader, readEvidenceBlobBytes } from './evidence-blob-reader.js'\nimport { buildRunPorts } from './run-composition.js'\nimport type { RetrievalRungResolver } from './run-composition.js'\nimport { writeAnalysisArtifact } from '../analysis/persist-analysis.js'\nimport { createJsonlSessionLog } from '../session/jsonl-session-log.js'\nimport { createJobCheckpointStore } from '../store/job-checkpoint-store.js'\nimport { createPostProcessingReader } from '../store/post-processing-reader.js'\nimport { AGENT_JOB_STORE_DB_FILE, createSqliteJobStore } from '../store/sqlite-job-store.js'\nimport type { SqliteJobStore } from '../store/sqlite-job-store.js'\n\n// The one file naming the writer-gated entry; reader-carveout fails on a second or on none.\n\n// `run-composition.ts` takes this as an input, so the resolver keeps one importer of its package.\nexport const resolveHostRetrievalRung: RetrievalRungResolver = resolveRetrievalRung\n\n// Read-only probes, so a diagnostic gets both axes without a second fold or any mutation.\nexport interface LocalKnowledgeProbeCapabilities {\n readonly classifyIndexFace: typeof classifyIndexFace\n readonly foldRetrievalRung: typeof foldRetrievalRung\n readonly indexDbPath: typeof indexDbPath\n readonly readEmbedderWorkerRegistration: typeof readEmbedderWorkerRegistration\n readonly readWriterLease: typeof readWriterLease\n readonly resolveEmbedderCapability: typeof resolveEmbedderCapability\n}\n\nexport const LOCAL_KNOWLEDGE_PROBES: LocalKnowledgeProbeCapabilities = Object.freeze({\n classifyIndexFace,\n foldRetrievalRung,\n indexDbPath,\n readEmbedderWorkerRegistration,\n readWriterLease,\n resolveEmbedderCapability,\n})\n\n// The probe vocabulary the three doctor rows are typed against, re-exported through the same one\n// edge. Types are erased, so this hands a caller no power the frozen table above does not.\nexport type {\n AcquireEmbedderOutcome,\n IndexFace,\n ReadEmbedderWorkerRegistrationOutcome,\n ResolveEmbedderCapabilityOptions,\n} from '@vostride/agent-qa-knowledge-local'\n\n// The delegate transport's vocabulary, re-exported through the edge that names the writer entry.\nexport type {\n ExplicitReviewDelegate,\n ExplicitReviewDelegation,\n ExplicitReviewRequest,\n ExplicitReviewResult,\n} from '@vostride/agent-qa-knowledge-local'\n\nexport type {\n AcquireWriterLeaseOutcome,\n AuthorOutcome,\n AuthoringTestRef,\n CurationCandidateProjection,\n CurationJobView,\n CurationProjectionArtifactSource,\n CuratorAuthor,\n EnqueueCurationCandidateProjectionOutcome,\n HeartbeatLeaseOutcome,\n LeaseOperationOptions,\n NeighborRecord,\n OpenServingKnowledgeReaderConfig,\n PurgeAffectedSet,\n PurgeReceipt,\n RebuildReport,\n ReadWriterLeaseOutcome,\n ReleaseLeaseOutcome,\n RollbackAffectedSet,\n RollbackCampaignInput,\n RollbackCurationJobInput,\n RollbackReport,\n WriterLease,\n WriterLeaseAuthority,\n WriterLeaseFreshness,\n} from '@vostride/agent-qa-knowledge-local'\n\n// Surface hosts reach worker lifecycle vocabulary through this one legal composition edge.\nexport {\n // Re-exported so the post-run tail and the curation drain share one bound.\n DRAIN_BUDGET_MS,\n EMBEDDER_WORKER_REGISTRATION_FILE,\n EMBEDDER_WORKER_START_TIMEOUT_MS,\n EMBEDDER_WORKER_TERM_GRACE_MS,\n EmbedderWorkerTimeoutError,\n // The projection's maintenance cadence reaches the daemon host through the same one edge.\n ENTITY_INDEX_SWEEP_INTERVAL_MS,\n}\n\n/**\n * The standing daemon's writer-authority substrate, published through the same one composition\n * edge as every other local writer capability. Surface packages may import agent-local, but the\n * architecture firewall deliberately forbids them from naming knowledge-local or safety\n * directly; keeping this frozen table here preserves that boundary without duplicating lease\n * behavior in the CLI host.\n */\nexport interface LocalDaemonCapabilities {\n readonly acquireWriterLease: typeof acquireWriterLease\n readonly heartbeatLease: typeof heartbeatLease\n readonly releaseLease: typeof releaseLease\n readonly readWriterLease: typeof readWriterLease\n readonly isLeaseStale: typeof isLeaseStale\n // Recoverability reads this verdict, not the lease file, and must handle `unknown` explicitly.\n readonly deriveWriterLeaseFreshness: typeof deriveWriterLeaseFreshness\n readonly countPendingCurationJobs: typeof countPendingCurationJobs\n readonly countRemainingCurationWork: typeof countRemainingCurationWork\n readonly inspectDrainableCurationWork: typeof inspectDrainableCurationWork\n readonly listQueuedCandidates: typeof listQueuedCandidates\n readonly acquireEmbedder: typeof acquireEmbedder\n readonly drainQueue: typeof drainQueue\n readonly runMaintenanceTail: typeof runMaintenanceTail\n readonly resolveEmbedderWorkerEntryPath: () => string\n readonly readEmbedderWorkerRegistration: typeof readEmbedderWorkerRegistration\n readonly embedderWorkerProcessIsAlive: typeof embedderWorkerProcessIsAlive\n readonly embedderWorkerSocketPath: typeof embedderWorkerSocketPath\n readonly probeEmbedderWorkerSocket: typeof probeEmbedderWorkerSocket\n // No surface may signal a registered worker pid unless this verdict is `match`.\n readonly verifyEmbedderWorkerIncarnation: typeof verifyEmbedderWorkerIncarnation\n // A run owner's start time, read for the CLI's `runs.db` ownership.\n readonly resolveProcessIncarnation: typeof resolveProcessIncarnation\n readonly removeEmbedderWorkerRegistration: (\n agentQaRoot: string,\n expected: EmbedderWorkerRegistration,\n ) => ReturnType<typeof removeEmbedderWorkerRegistration>\n readonly resetEmbedderCapability: () => void\n readonly pinLocalHeadlessExecutionContext: () => void\n}\n\nfunction resolveEmbedderWorkerEntryPath(): string {\n const requireBase = typeof __filename === 'string'\n ? __filename\n : import.meta.url\n const knowledgeEntry = createRequire(requireBase).resolve('@vostride/agent-qa-knowledge-local')\n return join(dirname(knowledgeEntry), 'embedder-worker', 'worker-entry.js')\n}\n\nexport const LOCAL_DAEMON_CAPABILITIES: LocalDaemonCapabilities = Object.freeze({\n acquireWriterLease,\n heartbeatLease,\n releaseLease,\n readWriterLease,\n deriveWriterLeaseFreshness,\n isLeaseStale,\n countPendingCurationJobs,\n countRemainingCurationWork,\n inspectDrainableCurationWork,\n listQueuedCandidates,\n acquireEmbedder,\n drainQueue,\n runMaintenanceTail,\n resolveEmbedderWorkerEntryPath,\n readEmbedderWorkerRegistration,\n embedderWorkerProcessIsAlive,\n embedderWorkerSocketPath,\n probeEmbedderWorkerSocket,\n verifyEmbedderWorkerIncarnation,\n resolveProcessIncarnation,\n removeEmbedderWorkerRegistration,\n resetEmbedderCapability: () => resetEmbedderCapability(DEFAULT_EMBEDDING_PROFILE),\n pinLocalHeadlessExecutionContext: () => {\n setActiveExecutionContextResolver(() => 'local-headless')\n },\n})\n\n/**\n * Index maintenance and the campaign/job rollback verbs, plus the lease every one of them is only\n * legal to hold under. Grouped rather than flattened because they share that precondition: a host\n * reaching for `purgeRecord` without a lease is the mistake the grouping makes visible.\n */\nexport interface LocalKnowledgeMaintenanceCapabilities {\n readonly acquireWriterLease: typeof acquireWriterLease\n readonly refreshWriterLeaseAuthority: typeof refreshWriterLeaseAuthority\n readonly releaseLease: typeof releaseLease\n readonly rebuildIndex: typeof rebuildIndex\n readonly purgeRecord: typeof purgeRecord\n readonly resolvePurgeAffectedSet: typeof resolvePurgeAffectedSet\n readonly purgeAffectedSetFingerprint: typeof purgeAffectedSetFingerprint\n readonly rollbackCampaign: typeof rollbackCampaign\n readonly rollbackCurationJob: typeof rollbackCurationJob\n readonly resolveRollbackAffectedSet: typeof resolveRollbackAffectedSet\n readonly rollbackAffectedSetFingerprint: typeof rollbackAffectedSetFingerprint\n}\n\ninterface ReceiptWriterInput extends Pick<CreateLocalKnowledgeStoreConfig,\n 'knowledgeRoot' | 'executionContext' | 'sourceBuildOrdinal' | 'sourceRunId'> {\n /** The caller already holds this authority; these capabilities never acquire a lease. */\n lease: { leaseId: string; epoch: number }\n}\n\nexport interface RecordGateReceiptInput extends ReceiptWriterInput {\n receipt: GateReceipt\n}\n\nexport interface PromoteWithReceiptsInput extends ReceiptWriterInput {\n candidateId: RecordId\n receipts?: readonly GateReceipt[]\n}\n\nfunction receiptWriter(input: ReceiptWriterInput) {\n return createLocalKnowledgeStore({\n knowledgeRoot: input.knowledgeRoot,\n executionContext: input.executionContext,\n writerLeaseId: input.lease.leaseId,\n epoch: input.lease.epoch,\n ...(input.sourceBuildOrdinal === undefined ? {} : { sourceBuildOrdinal: input.sourceBuildOrdinal }),\n ...(input.sourceRunId === undefined ? {} : { sourceRunId: input.sourceRunId }),\n })\n}\n\nfunction recordGateReceipt(input: RecordGateReceiptInput): Promise<GateReceiptRecordOutcome> {\n return receiptWriter(input).recordGateReceipt(input.receipt)\n}\n\nfunction promoteWithReceipts(input: PromoteWithReceiptsInput): Promise<PromotionOutcome> {\n return receiptWriter(input).promote(input.candidateId, input.receipts)\n}\n\n/** Internal facts only: public showRecord deliberately omits bundle construction fields. */\nfunction readFeedbackRecord(input: { knowledgeRoot: string; recordId: string; evidenceRef?: ArtifactRef }): ServedRecordFacts | undefined {\n const matches = enumerateBundleDirs(input.knowledgeRoot).flatMap(entry => {\n const result = loadBundle(entry.dir)\n return result.kind === 'loaded' && result.bundle.manifest.id === input.recordId\n && verifyBundleIntegrity(entry.dir).ok ? [result.bundle] : []\n })\n if (matches.length !== 1) return undefined\n const bundle = matches[0]!\n const artifact = input.evidenceRef ?? bundle.artifactsIndex.artifacts[0]\n if (artifact === undefined) return undefined\n return { recordId: input.recordId, kind: bundle.frontmatter.kind,\n ...(bundle.frontmatter.subtype === undefined ? {} : { subtype: bundle.frontmatter.subtype }),\n anchors: bundle.frontmatter.anchors.map(anchor => anchor.raw), scope: bundle.frontmatter.scope,\n summary: bundle.summary, distilledEvidenceRef: { id: artifact.id, sha: artifact.sha },\n // This is the only admitted draft construction stage; user origin belongs on the delta.\n originStage: 'run-curation' }\n}\n\nexport interface LocalCurationCapabilities {\n readonly readFeedbackRecord: typeof readFeedbackRecord\n readonly appendMarkEvidence: typeof appendMarkEvidence\n // The lease-free planning half of `appendMarkEvidence`, so a preview runs without the writer.\n readonly planMarkEvidence: typeof planMarkEvidence\n readonly projectMarkEvidenceOutcome: typeof projectMarkEvidenceOutcome\n readonly triageMark: typeof triageMark\n readonly servedIdsOn: typeof servedIdsOn\n readonly procedureReadOn: typeof procedureReadOn\n readonly applyFeedback: typeof applyFeedback\n readonly recordGateReceipt: typeof recordGateReceipt\n readonly promoteWithReceipts: typeof promoteWithReceipts\n /** Serving-side reader the tail folds against; read-only despite arriving on the writer edge. */\n readonly openKnowledgeReader: typeof openKnowledgeReader\n readonly drainQueue: typeof drainQueue\n readonly foldRunOutcomes: typeof foldRunOutcomes\n // A version bump refolds through this rebuild, invoked per CLI tail sweep and per daemon lease.\n readonly reconcileRunOutcomesProjection: typeof reconcileRunOutcomesProjection\n readonly enqueueCurationCandidateProjection: typeof enqueueCurationCandidateProjection\n readonly readCanonicalBundleAnchors: typeof readCanonicalBundleAnchors\n // Reuses the writer's observation identity through the CLI bridge.\n readonly canaryOutcomeObservationId: typeof canaryOutcomeObservationId\n /**\n * Component of the tail's receipt: a bump refolds runs already receipted at the old version.\n * The receipt is the per-run half of that promise; `reconcileRunOutcomesProjection` above is\n * the half that actually re-derives the rows.\n */\n readonly runOutcomesProjectionVersion: typeof RUN_OUTCOMES_PROJECTION_VERSION\n readonly maintenance: LocalKnowledgeMaintenanceCapabilities\n}\n\nexport const LOCAL_CURATION_CAPABILITIES: LocalCurationCapabilities = Object.freeze({\n readFeedbackRecord,\n appendMarkEvidence,\n planMarkEvidence,\n projectMarkEvidenceOutcome,\n triageMark,\n servedIdsOn,\n procedureReadOn,\n applyFeedback,\n recordGateReceipt,\n promoteWithReceipts,\n openKnowledgeReader,\n drainQueue,\n foldRunOutcomes,\n reconcileRunOutcomesProjection,\n enqueueCurationCandidateProjection,\n readCanonicalBundleAnchors,\n runOutcomesProjectionVersion: RUN_OUTCOMES_PROJECTION_VERSION,\n canaryOutcomeObservationId,\n maintenance: Object.freeze({\n acquireWriterLease,\n refreshWriterLeaseAuthority,\n releaseLease,\n rebuildIndex,\n purgeRecord,\n resolvePurgeAffectedSet,\n purgeAffectedSetFingerprint,\n rollbackCampaign,\n rollbackCurationJob,\n resolveRollbackAffectedSet,\n rollbackAffectedSetFingerprint,\n }),\n})\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction isTargetName(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0\n}\n\n// The target names a run recorded in its untrusted `artifact.json`. Anything but a non-empty list\n// of non-empty names answers `unknown`, so a run recorded without them never reads as recorded.\nfunction recordedTargetsOf(artifact: unknown): RecordedTargets {\n const targets = isRecord(artifact) ? artifact.targets : undefined\n if (!Array.isArray(targets) || targets.length === 0 || !targets.every(isTargetName)) {\n return { status: 'unknown' }\n }\n return { status: 'recorded', names: [...new Set(targets)].sort() }\n}\n\n/**\n * Enumerate `<agentQaRoot>/runs/<slug>/handoff.json`. A project with no runs directory is an\n * ordinary empty result, not an error; an individual unreadable or version-rejected document is\n * skipped so one bad run never hides every other run.\n */\nexport function createRunsReader(agentQaRoot: string): RunsReaderPort {\n function enumerate(): CompletedRunHandoff[] {\n const runsDir = join(agentQaRoot, RUNS_SUBDIR)\n if (!existsSync(runsDir)) return []\n\n const documents: CompletedRunHandoff[] = []\n for (const entry of readdirSync(runsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const handoffPath = join(runsDir, entry.name, HANDOFF_FILE)\n if (!existsSync(handoffPath)) continue\n try {\n documents.push(loadCompletedRunHandoff(handoffPath))\n } catch {\n continue\n }\n }\n return documents\n }\n\n return {\n list(): Promise<readonly CompletedRunHandoff[]> {\n return Promise.resolve(enumerate())\n },\n // Matches the recorded `runId` over enumerated documents, so `../../etc` addresses nothing.\n get(runId: RunId): Promise<CompletedRunHandoff | undefined> {\n return Promise.resolve(enumerate().find((document) => document.runId === runId))\n },\n // A resume point below the earliest surviving seq throws `ReplayIncompleteError`.\n readEvents(runId: RunId, fromSeq: number): Promise<readonly RunEventEnvelope[]> {\n const recorded = [...new FsEventLog({ root: agentQaRoot, runId }).read(0)]\n .sort((left, right) => left.seq - right.seq)\n if (recorded.length === 0) return Promise.resolve([])\n\n const earliestAvailableSeq = recorded[0]!.seq\n if (fromSeq < earliestAvailableSeq) {\n return Promise.reject(new ReplayIncompleteError(fromSeq, earliestAvailableSeq))\n }\n return Promise.resolve(recorded.filter((event) => event.seq >= fromSeq))\n },\n // Read through the version guard; an ambiguous step reports its candidates instead of guessing.\n readStepEvidence(runId: RunId, address: StepEvidenceAddress): Promise<StepEvidenceLookup> {\n const document = enumerate().find((candidate) => candidate.runId === runId)\n if (document === undefined) return Promise.resolve({ kind: 'run-not-recorded' })\n\n const candidates = document.tests.filter((test) => (\n (address.testId === undefined || test.testId === address.testId)\n && test.steps.some((step) => step.stepIndex === address.stepIndex)\n ))\n if (candidates.length === 0) return Promise.resolve({ kind: 'step-not-found' })\n if (candidates.length > 1) {\n return Promise.resolve({\n kind: 'ambiguous-step-address',\n // Sorted, so the refusal a surface prints is the same list twice running.\n testIds: candidates.map((test) => test.testId).sort(),\n })\n }\n\n const evidence = candidates[0]!.steps.find((step) => step.stepIndex === address.stepIndex)\n return Promise.resolve(\n evidence === undefined\n ? { kind: 'step-not-found' }\n : { kind: 'found', evidence },\n )\n },\n // The caller's id is compared, never joined onto a path; an absent snapshot is `unknown`.\n getRecordedTargets(runId: RunId): Promise<RecordedTargets> {\n const runsDir = join(agentQaRoot, RUNS_SUBDIR)\n if (!existsSync(runsDir)) return Promise.resolve({ status: 'unknown' })\n\n const entry = readdirSync(runsDir, { withFileTypes: true })\n .find((candidate) => candidate.isDirectory() && candidate.name === runId)\n if (entry === undefined) return Promise.resolve({ status: 'unknown' })\n\n try {\n const runDir = join(runsDir, entry.name)\n if (loadCompletedRunHandoff(join(runDir, HANDOFF_FILE)).runId !== runId) {\n return Promise.resolve({ status: 'unknown' })\n }\n return Promise.resolve(\n recordedTargetsOf(JSON.parse(readFileSync(join(runDir, ARTIFACT_FILE), 'utf8'))),\n )\n } catch {\n return Promise.resolve({ status: 'unknown' })\n }\n },\n }\n}\n\n// The read verbs live in the reader carve-out; only the sighting site, which mints, stays here.\nexport function createKnowledgeReader(\n resolveKnowledgeRoot: () => Promise<string> | string,\n sightMemoryEntities?: SightMemoryEntities,\n): KnowledgeReaderPort {\n return createKnowledgeReaderPort({\n resolveKnowledgeRoot,\n ...(sightMemoryEntities === undefined ? {} : { sightMemoryEntities }),\n })\n}\n\n// ---- knowledge review: the WRITE half of the verb family --------\n\nexport interface CreateKnowledgeReviewInput {\n readonly agentQaRoot: string\n readonly resolveKnowledgeRoot: () => Promise<string> | string\n // The lease this host holds: a holder cannot acquire it twice, and supplies no delegate.\n readonly resolveWriterAuthority?: () => { readonly leaseId: string; readonly epoch: number } | undefined\n // How a direct change reaches a live lease holder; absent, a held lease refuses it by name.\n readonly knowledgeChangeDelegate?: ExplicitReviewDelegate\n // The context a change is recorded under; absent means the process resolver.\n readonly resolveExecutionContext?: () => ExecutionContext\n}\n\n/** The public answer to one direct change, from the explicit writer's own result. */\nfunction knowledgeChangeOutput(\n verb: KnowledgeChangeVerb,\n operationId: string,\n result: ExplicitReviewResult,\n): KnowledgeChangeOutput {\n switch (result.outcome) {\n case 'applied':\n return {\n outcome: 'applied',\n verb,\n operationId,\n recordIds: [...result.recordIds],\n ...(result.forgetReceipt === undefined ? {} : { forgetReceipt: result.forgetReceipt }),\n ...(result.commitReceipt === undefined ? {} : { commitReceipt: result.commitReceipt }),\n }\n case 'target-not-found':\n return { outcome: 'target-not-found', verb, operationId, target: result.target }\n case 'policy-materialize-refused':\n return { outcome: 'refused', verb, operationId, reason: 'policy-materialize-refused' }\n default:\n return result satisfies never\n }\n}\n\n/**\n * Bind the mutating review verbs over the review modules and the Curator's one commit path.\n *\n * A SEPARATE factory from `createKnowledgeReader`, mirroring the port split it implements: this\n * is the object whose presence makes accept/reject/forget report `bound`, and a host that wants\n * only the read verbs simply does not build one. The `MEM-` short-ID leg resolves through the\n * addressing ledger, opened per call and closed again on exactly the reasoning the entity\n * directory uses — a durable file the composition root owns, never a handle a review module holds.\n */\nexport function createKnowledgeReview(input: CreateKnowledgeReviewInput): KnowledgeReviewPort {\n async function roots(): Promise<{ knowledgeRoot: string }> {\n return { knowledgeRoot: await input.resolveKnowledgeRoot() }\n }\n\n // One change at a time, or two in-process changes find the lease held by each other and refuse.\n let changeChain: Promise<unknown> = Promise.resolve()\n function serialized<T>(work: () => Promise<T>): Promise<T> {\n const next = changeChain.then(work, work)\n changeChain = next.then(() => undefined, () => undefined)\n return next\n }\n\n return {\n // A missing identity is minted once per call and returned, so a retry is the same change.\n change: (request) => serialized(async () => {\n const { knowledgeRoot } = await roots()\n const operationId = request.operationId ?? randomUUID()\n const authority = input.resolveWriterAuthority?.()\n const result = await applyKnowledgeChange({\n agentQaRoot: input.agentQaRoot,\n knowledgeRoot,\n request: { verb: request.verb, input: request.input } as ExplicitReviewRequest,\n operationId,\n // The op that made the change, stamped on Gate-3 receipts: `knowledge.accept`,\n // `knowledge.reject` or `knowledge.forget`, which is the verb's own op id.\n opId: `knowledge.${request.verb}`,\n executionContext: (input.resolveExecutionContext ?? getActiveExecutionContext)(),\n ...(input.knowledgeChangeDelegate === undefined ? {} : { delegate: input.knowledgeChangeDelegate }),\n ...(authority === undefined ? {} : { writerAuthority: authority }),\n })\n return knowledgeChangeOutput(request.verb, operationId, result)\n }),\n }\n}\n\n\n\n// ---- an explicit knowledge change, applied in the call ------------------------\n\nexport interface ApplyKnowledgeChangeInput {\n readonly agentQaRoot: string\n readonly knowledgeRoot: string\n readonly request: ExplicitReviewRequest\n /** The caller's stable identity for this change: a retry with the same identity lands nothing twice. */\n readonly operationId: string\n /** The op making the change, stamped on its Gate-3 receipts. */\n readonly opId: string\n /** The caller's actual context, recorded as-is. An explicit change applies in every context. */\n readonly executionContext: ExecutionContext\n /**\n * How this host reaches a live writer-lease holder. The holder receives exactly the validated\n * request and identity, bounded; the lease is never taken. Absent, a held lease refuses by name.\n */\n readonly delegate?: ExplicitReviewDelegate\n /** The lease this host already holds, when it is the holder. Exclusive with {@link delegate}. */\n readonly writerAuthority?: { readonly leaseId: string; readonly epoch: number }\n}\n\n// Nothing is filed: the change is committed through the direct writer, or refused by type.\nexport async function applyKnowledgeChange(input: ApplyKnowledgeChangeInput): Promise<ExplicitReviewResult> {\n const ledger = openAddressingLedgerForReview({\n path: join(input.agentQaRoot, ADDRESSING_LEDGER_DB_FILE),\n })\n try {\n return await applyExplicitReview({\n agentQaRoot: input.agentQaRoot,\n knowledgeRoot: input.knowledgeRoot,\n request: input.request,\n operationId: input.operationId,\n opId: input.opId,\n executionContext: input.executionContext,\n resolveBundleShortId: (shortId) => ledger.lookupByShortId(shortId)?.machineId,\n ...(input.delegate === undefined ? {} : { delegate: input.delegate }),\n ...(input.writerAuthority === undefined ? {} : { writerAuthority: input.writerAuthority }),\n })\n } finally {\n ledger.close()\n }\n}\n\n// ---- entities: the addressing ledger and the tier-(a) resolver ----------\n\nexport interface CreateEntityDirectoryInput {\n readonly agentQaRoot: string\n readonly resolveKnowledgeRoot: () => Promise<string> | string\n}\n\n// Opened per call so no ledger file appears early, and closed again because minting is lease-free.\nexport function createEntityDirectory(input: CreateEntityDirectoryInput): EntityDirectoryPort {\n return {\n resolve(ref) {\n return withEntityResolutionDeps(input, (deps) => resolveEntityRef(ref, deps))\n },\n get(ref) {\n return withEntityResolutionDeps(input, (deps) => getEntityDescriptor(ref, deps))\n },\n }\n}\n\n// Sights through the resolver's own `sightEntity` leg, so the list verbs share one minting path.\nexport function createMemorySightingHook(\n input: CreateEntityDirectoryInput,\n): SightMemoryEntities {\n return (bundleIds) => withEntityResolutionDeps(input, (deps) => {\n for (const bundleId of bundleIds) sightEntity(bundleId, deps)\n })\n}\n\n/**\n * Open the addressing ledger and the entity-index projection for ONE span, run `body`, close.\n *\n * Shared by the directory port and the list-verb sighting hook so both obey the same open/close\n * law rather than two copies of it.\n */\nasync function withEntityResolutionDeps<T>(\n input: CreateEntityDirectoryInput,\n body: (deps: ResolveEntityRefDeps) => T | Promise<T>,\n): Promise<T> {\n const knowledgeRoot = await input.resolveKnowledgeRoot()\n const ledger = openAddressingLedger({\n path: join(input.agentQaRoot, ADDRESSING_LEDGER_DB_FILE),\n })\n // The projection lives under the knowledge root and is disposable; the ledger is never rebuilt.\n const entityIndex = openEntityIndex({ path: entityIndexDbPath(knowledgeRoot), knowledgeRoot })\n try {\n // AWAITED inside the try, not returned from it: tier (b)'s dense leg is asynchronous, so\n // returning the promise would close both databases while the resolution was still using\n // them. The bug is invisible while every caller is synchronous, which is exactly why it\n // is worth the word.\n return await body({\n ledger,\n entityIndex,\n sources: [createMemorySightingSource(() => knowledgeRoot)],\n })\n } finally {\n entityIndex.close()\n ledger.close()\n }\n}\n\nexport interface SweepEntityIndexInput extends CreateEntityDirectoryInput {\n /**\n * Test seam ONLY. Production omission runs the real acquisition ladder, which is what makes\n * the dense rung appear on hosts that have a model and stay absent on hosts that do not.\n */\n readonly acquireEmbedderCapability?: typeof acquireEmbedder\n}\n\nexport interface SweepEntityIndexOutcome extends EntityIndexSweepReport {\n /** How many renderings gained a vector this sweep. Zero on a floor host, by design. */\n readonly embedded: number\n}\n\n// Takes no writer lease and never writes the ledger, so a one-shot CLI process can run it.\nexport async function sweepEntityIndexProjection(\n input: SweepEntityIndexInput,\n): Promise<SweepEntityIndexOutcome> {\n const knowledgeRoot = await input.resolveKnowledgeRoot()\n const ledger = openAddressingLedger({\n path: join(input.agentQaRoot, ADDRESSING_LEDGER_DB_FILE),\n })\n const entityIndex = openEntityIndex({ path: entityIndexDbPath(knowledgeRoot), knowledgeRoot })\n try {\n const report = sweepEntityIndex(entityIndex, describeAllEntities({\n ledger,\n sources: [createMemorySightingSource(() => knowledgeRoot)],\n }))\n\n let embedded = 0\n const acquire = input.acquireEmbedderCapability ?? acquireEmbedder\n const capability = await acquire({\n preferredProfile: DEFAULT_EMBEDDING_PROFILE,\n allowDownload: false,\n agentQaRoot: input.agentQaRoot,\n })\n if (capability.kind === 'ready') {\n embedded = await embedPendingEntities(\n entityIndex,\n capability.embedder,\n capability.profile,\n )\n }\n return { ...report, embedded }\n } finally {\n entityIndex.close()\n ledger.close()\n }\n}\n\n// ---- runs.start: the composition's binding ---------------------------------------------\n\n// A port, because the process model, signals, reporters and exit discipline differ per host.\nexport interface RunExecutionPort {\n execute(request: RunsStartInput): Promise<StartedRun>\n}\n\n// An empty event log means no run took place, because the bus writes `runStarted` first.\nexport class RunProducedNoEventsError extends Error {\n constructor(readonly runId: string) {\n super(\n `The host reported run ${runId}, but no run events were recorded for it. ` +\n 'A run that started at all writes runStarted before anything else, so an empty ' +\n 'event log means no run took place under that id.',\n )\n this.name = 'RunProducedNoEventsError'\n }\n}\n\n/**\n * Bind `runs.start` over a host's run execution.\n *\n * The composition contributes the half a host must not be trusted with: after the host says a\n * run happened, the run's own durable event log is read back and an empty one is refused. The\n * op then builds its acknowledgment from the completed-run record through the SAME reader\n * `runs.get` answers from, so \"the run is real\" and \"the run is addressable\" are one fact.\n */\nexport function createLocalRunInvocation(input: {\n readonly agentQaRoot: string\n readonly execution: RunExecutionPort\n}): RunInvocationPort {\n return {\n async start(request: RunsStartInput): Promise<StartedRun> {\n const started = await input.execution.execute(request)\n const { eventLog } = buildRunPorts({\n configDir: dirname(input.agentQaRoot),\n runId: String(started.runId),\n })\n if (eventLog.read(0).length === 0) {\n throw new RunProducedNoEventsError(String(started.runId))\n }\n return started\n },\n }\n}\n\n// ---- authoring.draft.verify: the keep-gate evaluator's binding --------------\n\n/** The stable test identity, spelled once for this binding. */\ninterface DraftIdentity {\n readonly filePath: string\n readonly testName: string\n}\n\n/**\n * A parsed draft, as the HOST hands it over.\n *\n * Structurally identical to `packages/agent`'s `ParsedDraftLike`, and mirrored here rather than\n * imported for the reason every mirror in this graph exists: that type lives inside `agent`'s\n * `authoring/` and is not on its barrel, and publishing it to give a composition a name would put\n * a gate-orchestration type on the surface that publishes exactly one dispatch.\n *\n * `filePath` MUST be the workspace-relative identity the runner records on\n * `PerTestOutcome.filePath` — `workspaceRelativeIdentityPath`, the one spelling of that recipe.\n * Gates 1-2 find the draft's own member inside each run document by comparing against those bytes,\n * so a path spelled any other way makes every gate-run report `absent` for its own draft and gate\n * 1 fail for a join reason wearing a draft reason's clothes.\n */\nexport interface ParsedDraftDescriptor {\n readonly testId: string\n readonly filePath: string\n readonly testName: string\n // Required: without it, child gate runs hit a name `resolveTarget` throws on.\n readonly target: string\n readonly steps: readonly string[]\n /**\n * The parsed test's `context` block — an EDITABLE root, and therefore one the credential gate\n * scans. Structurally identical to `ParsedDraftLike.context`; a mirror that dropped it would\n * hand `packages/agent` a draft whose context can no longer be screened.\n */\n readonly context?: string\n readonly contentDigest: string\n}\n\n// `packages/agent` cannot stat a path, so the host answers each refusal arm and the op names it.\nexport type DraftParseOutcome =\n | { readonly kind: 'parsed'; readonly draft: ParsedDraftDescriptor }\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// One authored suite test as text, for gate 3's degraded lane.\nexport interface SuiteTextEntry {\n readonly filePath: string\n readonly testName: string\n readonly stepsText: readonly string[]\n}\n\n// Both verbs or neither: parse alone leaves gate 3's text lane empty, so a duplicate looks novel.\nexport interface DraftAuthoringPort {\n parseDraft(filePath: string): Promise<DraftParseOutcome>\n suiteTextCorpus(): Promise<readonly SuiteTextEntry[]>\n // Enumerates and never refuses; a project declaring no targets answers an empty list.\n configuredTargetNames(): Promise<readonly string[]>\n // Throws rather than answering `undefined`, because only the host knows which candidates it saw.\n deriveDefaultScope(): Promise<ScopeKey>\n // Parse before write, in one verb, so an unparsable draft writes nothing.\n stageDraft(contents: string): Promise<DraftStageOutcome>\n // Answers `DraftStageOutcome`, so an unrunnable patched document leaves the shelf untouched.\n applyPatchesToDraft(\n draft: ParsedDraftDescriptor,\n patchSet: TestEditPatchSet,\n ): Promise<DraftStageOutcome>\n // Checks the boundary and the read bytes, writes via a sibling temp and a rename, runs no git.\n publishDraft(request: DraftPublishRequest): Promise<TestFileWrite>\n}\n\n/** One draft to write: its shelf path, its target, and what the target held when it was read. */\nexport interface DraftPublishRequest {\n readonly draftPath: string\n readonly targetPath: string\n readonly sourceDigest?: string\n}\n\n/**\n * What staging produced: a parsed draft that IS on the shelf, or a refusal that wrote nothing.\n *\n * Structurally the mirror of `agent`'s `DraftStageOutcome`, on this file's own mirror discipline\n * — that type lives inside `agent`'s `authoring/` and the value crossing this seam is assignable\n * to it unchanged.\n */\nexport type DraftStageOutcome =\n | { readonly kind: 'staged'; readonly draft: ParsedDraftDescriptor }\n | { readonly kind: 'unparsable'; readonly reason: string }\n\n/** The suite comparison, materialized once per evaluation. */\ninterface FingerprintSnapshot {\n readonly union: ReadonlySet<string>\n readonly covered: readonly DraftIdentity[]\n readonly elements: ReadonlyMap<string, readonly string[]>\n}\n\nconst EMPTY_FINGERPRINT_SNAPSHOT: FingerprintSnapshot = {\n union: new Set<string>(),\n covered: [],\n elements: new Map<string, readonly string[]>(),\n}\n\n// Spelled as the escape `\\u0000`: a raw control byte makes `grep` treat the file as data.\nfunction draftIdentityKey(identity: DraftIdentity): string {\n return `${identity.filePath}\\u0000${identity.testName}`\n}\n\n// Excludes the draft's own identity before the union, or gate 3 compares the draft to itself.\nfunction readSuiteFingerprints(\n knowledgeRoot: string,\n product: string,\n draft: DraftIdentity,\n): FingerprintSnapshot {\n const path = indexDbPath(knowledgeRoot)\n if (!existsSync(path)) return EMPTY_FINGERPRINT_SNAPSHOT\n const db = new DatabaseSync(path, { readOnly: true })\n try {\n const index = createSuiteFingerprintIndex(db, { product })\n const draftKey = draftIdentityKey(draft)\n const covered = index\n .coveredTests()\n .filter((identity) => draftIdentityKey(identity) !== draftKey)\n const elements = new Map<string, readonly string[]>()\n const union = new Set<string>()\n for (const identity of covered) {\n const own = index.elementsForTest(identity.filePath, identity.testName)\n elements.set(draftIdentityKey(identity), own)\n for (const element of own) union.add(element)\n }\n return { union, covered, elements }\n } catch (error) {\n if (error instanceof Error && error.message.includes('no such table')) {\n return EMPTY_FINGERPRINT_SNAPSHOT\n }\n throw error\n } finally {\n db.close()\n }\n}\n\ninterface DraftEvaluationBindingInput {\n readonly authoring: DraftAuthoringPort\n readonly agentQaRoot: string\n readonly knowledgeRoot: () => Promise<string> | string\n /** The SAME reader `runs.get` answers from — see below. */\n readonly readRun: (runId: string) => Promise<CompletedRunHandoff | undefined>\n // Dispatches one gate-run through the real `runs.start` op.\n readonly startGateRun: (request: RunsStartInput) => Promise<RunStartAcknowledgement>\n // The same object `authoring.funnel.get` binds, so gate 2 reads no second projection.\n readonly authoringFunnel: AuthoringFunnelPortLike\n}\n\n// Gate runs go through the `runs.start` op, whose acknowledgment reads the run's own record.\nfunction createDraftEvaluation(input: DraftEvaluationBindingInput) {\n return {\n resolveDraft(draftPath: string): Promise<DraftParseOutcome> {\n return input.authoring.parseDraft(draftPath)\n },\n async openEvaluation(draft: ParsedDraftDescriptor) {\n const knowledgeRoot = await input.knowledgeRoot()\n const draftIdentity: DraftIdentity = {\n filePath: draft.filePath,\n testName: draft.testName,\n }\n const draftKey = draftIdentityKey(draftIdentity)\n // The authored universe MINUS the draft itself. Handed its own bytes to compare against,\n // the text lane scores 1.0 and reads the draft as already covered — by itself.\n const textCorpus = (await input.authoring.suiteTextCorpus()).filter(\n (entry) => draftIdentityKey(entry) !== draftKey,\n )\n\n let observedProduct: string | undefined\n let snapshot: FingerprintSnapshot | undefined\n const fingerprints = (): FingerprintSnapshot => {\n if (snapshot !== undefined) return snapshot\n snapshot = observedProduct === undefined\n ? EMPTY_FINGERPRINT_SNAPSHOT\n : readSuiteFingerprints(knowledgeRoot, observedProduct, draftIdentity)\n return snapshot\n }\n\n return {\n runs: {\n async start(request: RunsStartInput): Promise<RunStartAcknowledgement> {\n const acknowledgement = await input.startGateRun(request)\n observedProduct ??= slugBranch(acknowledgement.scope.key)\n return acknowledgement\n },\n get: (runId: string) => input.readRun(runId),\n },\n fingerprints: {\n elementUnion: () => fingerprints().union,\n coveredTests: () => fingerprints().covered,\n elementsForTest: (filePath: string, testName: string) =>\n fingerprints().elements.get(draftIdentityKey({ filePath, testName })) ?? [],\n },\n textCorpus,\n // Receipts are machine-local working state under the runtime root, not committed artifacts.\n receipts: createDraftReceiptsStore({ resolveAgentQaRoot: () => input.agentQaRoot }),\n // `product` is gate 3's observed product: stability and the index ask about one app.\n suiteStability: {\n port: input.authoringFunnel,\n product: () => observedProduct,\n },\n }\n },\n }\n}\n\n// `origin: agent`, because the runs answering a verify request are the system's own doing.\nconst AUTHORING_GATE_RUN_CALLER: FunctionCaller = Object.freeze({\n surface: 'authoring',\n origin: 'agent',\n})\n\n// No second caller for `runs.start`: every gate-run starts inside `authoring.draft.verify`.\nconst AUTHORING_LOOP_VERIFY_CALLER: FunctionCaller = Object.freeze({\n surface: 'authoring',\n origin: 'agent',\n})\n\n/** Wall-clock in the one format every store column and dump row is written in. */\nexport const SYSTEM_CLOCK: ClockPort = Object.freeze({\n now: (): string => new Date().toISOString(),\n})\n\n/**\n * Job ids are derived from `(kind, idempotencyKey)` rather than minted at random, so two hosts\n * enqueuing the same logical work address the same row and the store's unique index has something\n * stable to deduplicate on.\n */\nconst digestJobIdSource: JobIdSource = {\n jobIdFor: (kind, idempotencyKey) =>\n asJobId(`job_${sha256hex16(`${kind} ${idempotencyKey}`)}`),\n}\nexport const DIGEST_JOB_ID_SOURCE: JobIdSource = Object.freeze(digestJobIdSource)\n\n// The concrete sqlite store, because the host that opened the database closes and dumps it.\nexport interface LocalAgentJobs {\n readonly queue: AgentJobQueue\n readonly store: SqliteJobStore\n readonly kinds: JobKindRegistry\n /** The capability the queue was constructed with, exposed so a host can assert what it bound. */\n readonly model: JobModelCapability\n /**\n * The id source the queue was constructed with.\n *\n * Exposed because a caller that watches this queue's outcomes must be able to derive the same\n * ids the enqueue addressed — the push half of a run's chip trail and the pull half of its\n * status have to agree about which rows belong to which run. Publishing the SOURCE makes that\n * agreement structural; re-deriving a default at the call site would make it a convention, and\n * a convention is exactly what breaks the first time a host is composed with a different one.\n */\n readonly idSource: JobIdSource\n /**\n * The kind exclusion the queue was constructed with, resolved from\n * `UNCLAIMABLE_BY_PROSE_POSTURE` and published for the same stated reason `idSource` is:\n * a caller that must assert what its queue was constructed with should read the value\n * rather than re-derive a default. Empty when the host declared `'masker-active'` or was\n * composed with no `postRun` at all.\n */\n readonly unclaimableKinds: readonly JobKind[]\n}\n\n/** Refusal returned when durable capabilities are requested after their composition was closed. */\nexport class LocalAgentClosedError extends Error {\n override readonly name = 'LocalAgentClosedError'\n\n constructor(readonly agentQaRoot: string) {\n super(\n `The local agent composition for ${agentQaRoot} is closed. A closed composition cannot `\n + 'reopen its job store; create a new composition with fresh lifecycle ownership instead.',\n )\n }\n}\n\nexport interface LocalAgentHost {\n /** The function registry with every seed capability bound over local storage. */\n readonly registry: FunctionRegistry\n // Present on every host, or `agent.ask` would be bound with its state absent.\n readonly chat: LocalAgentChatSession\n /** The knowledge-writer powers this host grants — the same frozen object for every host. */\n readonly curation: LocalCurationCapabilities\n /** The clock every store column, dump row and audit stamp in this host is written against. */\n readonly clock: ClockPort\n /**\n * Open (once) the durable job queue and its sqlite store over this host's runtime root.\n *\n * A method rather than an eager member, and the reason is a behaviour rather than a taste:\n * constructing the store CREATES `<agentQaRoot>/agent-jobs.db` and the checkpoint directory. A\n * host that only lists the registry — `agent-qa fn --list` is exactly that — would otherwise\n * bring a queue database into existence in a project that has never enqueued anything. Repeated\n * calls return the same instance, so \"opened once\" is a property of the handle and not of the\n * caller's discipline.\n */\n jobs(): Promise<LocalAgentJobs>\n /** Close whatever was opened and join an open already in flight. Idempotent. */\n close(): Promise<void>\n}\n\n// Required wherever `postRun` is supplied, so the typechecker makes each host state its masking.\nexport type CandidateProsePosture = 'masker-active' | 'no-masker'\n\n// A total `Record`, so a third posture cannot compile unmapped; `unclaimableKinds` derives from it.\nexport const UNCLAIMABLE_BY_PROSE_POSTURE: Record<CandidateProsePosture, readonly JobKind[]>\n = Object.freeze({\n // Frozen deep, because the inner arrays are what the queue claims against.\n 'masker-active': Object.freeze([]),\n 'no-masker': Object.freeze(['curate-memory'] as const),\n })\n\nexport interface ComposeLocalAgentInput {\n // The declared-secret mask for chat projections and run reads.\n readonly mask: MaskFn\n readonly feedback?: FeedbackPort\n // Absent leaves `runs.marks.history` and `runs.mark.preview` unbound by name.\n readonly feedbackReads?: FeedbackReadsPort\n /** The project's runtime root, i.e. `<configDir>/.agent-qa`. Absolute. */\n readonly agentQaRoot: string\n // Injected because flattening and masking need the host's loader, and masking is its boundary.\n readonly config: ConfigReaderPort\n /** Resolves the knowledge root this invocation serves from. See `createKnowledgeReader`. */\n readonly knowledgeRoot: () => Promise<string> | string\n // A required factory: the queue needs a model, and resolving one costs a config and auth read.\n readonly model: () => JobModelCapability | Promise<JobModelCapability>\n // Optional: a host without it lists `runs.start` as `unbound` and refuses it by name.\n readonly runExecution?: RunExecutionPort\n // Optional: `authoring.draft.verify` binds only where this and `runExecution` are both present.\n readonly draftAuthoring?: DraftAuthoringPort\n // Host-supplied because the edit uses `yaml`'s Document API, which this package may not name.\n readonly configFiles?: ConfigFilesPortLike\n // Host-supplied: `AgentQaConfigSchema` lives in core, which this package may not name.\n readonly configValidate?: ConfigValidatePortLike\n // Optional: its absence leaves only `config.project.scaffold` unbound.\n readonly scaffoldContent?: ConfigScaffoldContentPortLike\n // Host-supplied because its transaction is shared per path with the dashboard's own writes.\n readonly configWrite?: FunctionDeps['configWrite']\n // Optional: absent lists `agent.explain` as `unbound` rather than answering from model memory.\n readonly capabilityCatalog?: CapabilityCatalogPort\n // Optional: a host with no HTTP origin lists `runs.liveurl` as `unbound`, never a dead link.\n readonly liveView?: LiveViewPort\n // Optional: a host with no projection to read lists `runs.detail` as `unbound` by name.\n readonly runDetail?: RunDetailReaderPort\n // `agent-local` cannot name a socket, so the CLI injects a closure over `invokeViaDaemon`.\n readonly knowledgeChangeDelegate?: ExplicitReviewDelegate\n /** The writer lease a leaseholding host already owns. See `createKnowledgeReview`. */\n readonly resolveWriterAuthority?: () => { readonly leaseId: string; readonly epoch: number } | undefined\n // Required: only a host knows the checkout root, and a guessed root mints unreadable identities.\n readonly mintQuarantineIdentityPath: (filePath: string) => string\n readonly clock?: ClockPort\n readonly idSource?: JobIdSource\n /** The kind registry the queue dispatches through. Defaults to the real declarations. */\n readonly jobKinds?: JobKindRegistry\n // Optional: with it the real analyze-run and curate-memory bodies run; without it, scripted ones.\n readonly postRun?: {\n readonly curateRun: PostRunJobCapabilities['curateRun']\n // Required, so a `postRun` that omits its masking posture does not typecheck.\n readonly candidateProse: CandidateProsePosture\n }\n // Optional factory, resolved at queue open; answering `undefined` sends packs whole.\n readonly analysisTokenBudget?: () =>\n | Promise<PostRunJobCapabilities['analysisTokenBudget']>\n | PostRunJobCapabilities['analysisTokenBudget']\n // Injected per composition, so a host's posture does not leak through the process global.\n readonly resolveExecutionContext?: () => ExecutionContext\n // Called after the event is on file; its return is discarded and a throw swallowed.\n readonly observeSessionEvent?: (sessionId: string, event: ChatSessionEvent) => void\n // Never config-reachable: disabling the deterministic override removes a safety property.\n readonly chatReconcile?: ReconcileStrategy\n // A built model, never an id the SDK resolves past the masking middleware; absent is headless.\n readonly chatModel?: ChatLanguageModel\n // Host-resolved with the chat model, or a session compacts against a window the model lacks.\n readonly chatAccounting?: ChatTokenAccounting\n // Absent, `/model` records the declared model and emits `model_change` but resolves no client.\n readonly chatModelFor?: (name: string) => ChatLanguageModel | Promise<ChatLanguageModel>\n // Passed through to the engine's `present`; absent, nothing renders mid-turn.\n readonly chatPresent?: (text: string) => void | Promise<void>\n}\n\n// Exposed for REPL state and closing an interrupted turn; everything else goes through `agent.ask`.\nexport interface LocalAgentChatSession {\n // A lookup, because these facts belong to one session; reading never creates a scope.\n stateFor(sessionId: string): ChatStateSnapshot | undefined\n // A no-op between turns: `aborted` after `turn_complete` would trim a finished turn on repair.\n abortActiveTurn(): Promise<void>\n}\n\n// Absent data answers `undefined`, not an empty row; any other read failure propagates.\nfunction readProjectedTestHistory(\n knowledgeRoot: string,\n query: { readonly product: string; readonly filePath: string; readonly testName: string },\n): ReturnType<typeof readTestOutcomeHistory> {\n const path = indexDbPath(knowledgeRoot)\n if (!existsSync(path)) return undefined\n const db = new DatabaseSync(path, { readOnly: true })\n try {\n return readTestOutcomeHistory(db, {\n product: query.product,\n filePath: query.filePath,\n testName: query.testName,\n })\n } catch (error) {\n if (error instanceof Error && error.message.includes('no such table')) return undefined\n throw error\n } finally {\n db.close()\n }\n}\n\n// `kth` and `windowBuilds` are the renderer's vocabulary, whichever window answers them.\ninterface ProjectedRecurrence {\n readonly kth: number\n readonly windowBuilds: number\n}\n\n// A fingerprint query reads the fingerprint window, else the per-test one; one ordinal serves both.\nfunction readProjectedRecurrence(\n knowledgeRoot: string,\n query: { readonly product: string; readonly filePath: string; readonly testName: string\n readonly fingerprint?: string },\n): ProjectedRecurrence | undefined {\n const path = indexDbPath(knowledgeRoot)\n if (!existsSync(path)) return undefined\n const db = new DatabaseSync(path, { readOnly: true })\n try {\n const history = readTestOutcomeHistory(db, {\n product: query.product,\n filePath: query.filePath,\n testName: query.testName,\n })\n if (history === undefined) return undefined\n const currentBuildOrdinal =\n history.lastBuildOrdinal\n ?? history.lastOutcomes.reduce((max, entry) => Math.max(max, entry.buildOrdinal), 0)\n if (query.fingerprint === undefined) return failureRecurrence(history, currentBuildOrdinal)\n const windowed = fingerprintRecurrence(\n db,\n { product: query.product, fingerprint: query.fingerprint },\n currentBuildOrdinal,\n )\n return { kth: windowed.occurrenceOrdinals, windowBuilds: windowed.windowOrdinals }\n } catch (error) {\n if (error instanceof Error && error.message.includes('no such table')) return undefined\n throw error\n } finally {\n db.close()\n }\n}\n\n// Total over ledger states, so a new state cannot compile unmapped; `released` maps to no rung.\nconst LADDER_STATE_FOR_ENTRY = {\n quarantined: 'quarantined',\n expired: 'expired',\n released: undefined,\n} as const satisfies Record<QuarantineEntryStateName, QuarantineLadderState | undefined>\n\n// An unreadable ledger propagates its error; healing would render a suppressed test as ordinary.\nfunction readQuarantineLadder(\n knowledgeRoot: string,\n identity: { readonly product: string; readonly filePath: string; readonly testName: string },\n now: string,\n recurrence: ProjectedRecurrence,\n): RecurrenceLadder | undefined {\n const entries = foldQuarantineLedgerState(readQuarantineLedger(knowledgeRoot).events, now)\n const entry = entries.find((candidate) =>\n candidate.product === identity.product\n && candidate.filePath === identity.filePath\n && candidate.testName === identity.testName)\n const state = entry === undefined ? undefined : LADDER_STATE_FOR_ENTRY[entry.state]\n if (entry !== undefined && state !== undefined) return { state, expiresAt: entry.expiresAt }\n if (recurrence.kth >= QUARANTINE_FLAG_FLOOR) return { state: 'flagged' }\n return undefined\n}\n\ninterface ProjectionRecurrence {\n readonly provider: RecurrenceProvider\n /**\n * Resolve (and cache) the knowledge root the SYNC provider reads under. See the\n * `runs.get` wrapper in `composeLocalAgent` for why this exists and where it is awaited.\n */\n prime(): Promise<void>\n}\n\n// Both reads run per call and nothing about the answer is cached; only the knowledge root is kept.\nfunction createProjectionRecurrenceProvider(\n resolveKnowledgeRoot: () => Promise<string> | string,\n /** The host clock, read ONCE per query — the ladder's expiry comparison needs an instant. */\n now: () => string,\n): ProjectionRecurrence {\n let root: string | undefined\n let resolving: Promise<void> | undefined\n\n function beginResolve(): Promise<void> | undefined {\n if (resolving !== undefined) return resolving // reuse the in-flight resolution; never mint a second promise\n let answer: Promise<string> | string\n try {\n answer = resolveKnowledgeRoot()\n } catch {\n return undefined // sync throw: swallowed here, retried on the next query\n }\n if (typeof answer === 'string') {\n root = answer\n return undefined\n }\n // A failed resolution clears the marker so the next query retries rather than\n // pinning the provider to permanent no-history over a transient host error.\n resolving = answer.then(\n (value) => {\n root = value\n },\n () => {\n resolving = undefined\n },\n )\n return resolving\n }\n\n function rootNow(): string | undefined {\n if (root !== undefined) return root\n beginResolve()\n return root\n }\n\n return {\n prime(): Promise<void> {\n if (root !== undefined) return Promise.resolve()\n // Both stored handlers swallow, so prime never rejects — the awaited runs.get hop\n // cannot fail on a knowledge-root problem.\n return beginResolve() ?? Promise.resolve()\n },\n provider: {\n failureRecurrence(query) {\n const knowledgeRoot = rootNow()\n if (knowledgeRoot === undefined) return undefined\n const recurrence = readProjectedRecurrence(knowledgeRoot, query)\n // No recorded history is the no-history clause, ladder or not.\n if (recurrence === undefined) return undefined\n const ladder = readQuarantineLadder(knowledgeRoot, query, now(), recurrence)\n return ladder === undefined ? recurrence : { ...recurrence, ladder }\n },\n },\n }\n}\n\n// Absent is `undefined`; a newer schema, bad bytes or another run's id are refused, not absent.\nfunction createAnalysisArtifactReader(agentQaRoot: string): AnalysisArtifactReaderPort {\n return {\n getArtifact(runId) {\n const path = join(agentQaRoot, RUNS_SUBDIR, slugBranch(runId), ANALYSIS_FILE)\n let bytes: string\n try {\n bytes = readFileSync(path, 'utf8')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined\n throw error\n }\n const admission = admitAnalysisArtifactForRun(\n guardRunAnalysisArtifact(JSON.parse(bytes)),\n runId,\n )\n return admission.kind === 'admitted' ? admission.artifact : undefined\n },\n }\n}\n\n// The handoff path derives from `runId` through `slugBranch`, so `../../etc` addresses nothing.\nexport function postRunCapabilities(\n input: ComposeLocalAgentInput,\n /**\n * The RESOLVED knowledge root. `openJobs` awaits the host's resolver once at queue open\n * — the same once-at-open idiom the model factory follows — so the SYNC capability\n * members below never race an async resolution mid-job.\n */\n knowledgeRoot: string,\n /** The RESOLVED budget, awaited from the input factory at the same open (see above). */\n analysisTokenBudget?: PostRunJobCapabilities['analysisTokenBudget'],\n): PostRunJobCapabilities | undefined {\n const postRun = input.postRun\n if (postRun === undefined) return undefined\n return {\n loadCompletedRunHandoff: (runId: string) =>\n loadCompletedRunHandoff(\n join(input.agentQaRoot, RUNS_SUBDIR, slugBranch(runId), HANDOFF_FILE),\n ),\n curateRun: postRun.curateRun,\n // Derived from the artifact's own `runId` through `slugBranch`; a payload carries no path.\n persistAnalysis: (artifact) =>\n writeAnalysisArtifact(\n join(input.agentQaRoot, RUNS_SUBDIR, slugBranch(artifact.runId), ANALYSIS_FILE),\n artifact,\n ),\n // Keyed by the stable identity (product, filePath, testName), never a per-run id; read-only.\n readTestHistory: (query) => readProjectedTestHistory(knowledgeRoot, query),\n // Through the shared `lookupEvidenceBlob`, so `runs.artifact` and this job agree on blobs.\n readEvidenceBlob: (runId, sha) =>\n readEvidenceBlobBytes({ agentQaRoot: input.agentQaRoot }, runId, sha),\n // Host-resolved from the job model's profile; this composition adds no knob.\n ...(analysisTokenBudget === undefined ? {} : { analysisTokenBudget }),\n }\n}\n\n// Identical but for `origin`: a typed alias is a person's call and a planned one is not.\nexport const CHAT_RESOLVER_CALLER: FunctionCaller = Object.freeze({\n surface: 'chat',\n origin: 'human',\n})\n\nexport const CHAT_PLANNER_CALLER: FunctionCaller = Object.freeze({\n surface: 'chat',\n origin: 'agent',\n})\n\n// Derived from the registry, so a build that gains an op gains it here; unbuilt answers `unbound`.\nfunction chatToolsetIds(registry: FunctionRegistry | undefined): readonly string[] {\n if (registry === undefined) return []\n return registry\n .list(CHAT_RESOLVER_CALLER)\n .map((declaration) => declaration.id)\n .sort()\n}\n\nfunction chatToolsetHash(registry: FunctionRegistry | undefined): string {\n if (registry === undefined) return 'unbound'\n // Sorted before hashing, so the hash identifies the set, not the walk order.\n return sha256hex16(chatToolsetIds(registry).join('\\n'))\n}\n\n// Masks written text, keeps the guard's closed vocabulary; an unnamed member masks as a tree.\ntype ChatMemberRule = 'as-written' | 'text' | 'tree' | ((value: unknown, mask: MaskFn) => unknown)\ntype ChatMemberRules = Readonly<Record<string, ChatMemberRule>>\n\nfunction projectChatMembers<T extends object>(value: T, rules: ChatMemberRules, mask: MaskFn): T {\n return Object.fromEntries(Object.entries(value).map(([key, member]) => {\n const rule = Object.hasOwn(rules, key) ? rules[key]! : 'tree'\n if (rule === 'as-written') return [key, member]\n if (typeof rule === 'function') return [key, rule(member, mask)]\n if (rule === 'text' && typeof member === 'string') return [key, mask(member)]\n return [key, maskPayloadTree(member, mask)]\n })) as T\n}\n\nconst eachChatRecord = (rules: ChatMemberRules): ChatMemberRule => (value, mask) => {\n const project = (entry: unknown) =>\n isRecord(entry) ? projectChatMembers(entry, rules, mask) : maskPayloadTree(entry, mask)\n return Array.isArray(value) ? value.map(project) : project(value)\n}\n\nconst CHAT_EVENT_BASE: ChatMemberRules = {\n kind: 'as-written', turnId: 'as-written', at: 'as-written',\n}\nconst CHAT_CLAUSE_RECEIPT_RULES: ChatMemberRules = {\n clause: 'text', functionId: 'as-written', origin: 'as-written', status: 'as-written', outcome: 'text',\n}\nconst CHAT_EVENT_RULES: Readonly<Record<ChatSessionEvent['kind'], ChatMemberRules>> = {\n user_message: { ...CHAT_EVENT_BASE, text: 'text' },\n stage_outcome: { ...CHAT_EVENT_BASE, stage: 'as-written', outcome: 'as-written' },\n clause_receipt: { ...CHAT_EVENT_BASE, ...CHAT_CLAUSE_RECEIPT_RULES },\n clause_result: { ...CHAT_EVENT_BASE, functionId: 'as-written', payload: 'tree' },\n approval_decision: {\n ...CHAT_EVENT_BASE, actionClass: 'as-written', decision: 'as-written', source: 'as-written',\n },\n mark_unhandled: { ...CHAT_EVENT_BASE, clause: 'text', reason: 'text' },\n model_change: { ...CHAT_EVENT_BASE, from: 'text', to: 'text', source: 'as-written' },\n active_tools_change: {\n ...CHAT_EVENT_BASE, addedIds: 'as-written', removedIds: 'as-written', toolsetHash: 'as-written',\n },\n compaction: {\n ...CHAT_EVENT_BASE, beforeTokens: 'as-written', afterTokens: 'as-written', outcome: 'as-written',\n },\n aborted: { ...CHAT_EVENT_BASE, source: 'as-written' },\n turn_complete: { ...CHAT_EVENT_BASE, status: 'as-written' },\n}\n\nconst CHAT_INVOKE_ANSWER_RULES: ChatMemberRules = {\n payload: 'tree',\n verdict: eachChatRecord({ status: 'as-written', outcome: 'text' }),\n foldLines: 'tree',\n}\n\nconst CHAT_TURN_RESULT_RULES: ChatMemberRules = {\n sessionId: 'as-written',\n turnId: 'as-written',\n status: 'as-written',\n answer: 'text',\n receipts: eachChatRecord(CHAT_CLAUSE_RECEIPT_RULES),\n results: eachChatRecord({ functionId: 'as-written', payload: 'tree' }),\n unhandled: eachChatRecord({ clause: 'text', reason: 'text' }),\n refusedLineCount: 'as-written',\n}\n\nfunction projectChatSessionEvent(event: ChatSessionEvent, mask: MaskFn): ChatSessionEvent {\n const rules = Object.hasOwn(CHAT_EVENT_RULES, event.kind)\n ? CHAT_EVENT_RULES[event.kind]\n : CHAT_EVENT_BASE\n return projectChatMembers(event, rules, mask)\n}\n\nexport function composeLocalAgent(input: ComposeLocalAgentInput): LocalAgentHost {\n const clock = input.clock ?? SYSTEM_CLOCK\n\n const entityResolutionInput = {\n agentQaRoot: input.agentQaRoot,\n resolveKnowledgeRoot: input.knowledgeRoot,\n }\n\n // the recurrence seam and its root priming. `analysis.get` awaits\n // `deps.runs.get` before any recurrence join runs (analysis-get.ts invoke order), so\n // priming the root inside that awaited hop is what makes the SYNC provider correct on a\n // host whose knowledge-root resolver is async (the CLI): by the time the join runs, the\n // root string is cached. A resolution failure is swallowed HERE only — the provider then\n // answers the honest no-history clause, and the knowledge verbs report their own errors\n // through their own awaited resolutions.\n const recurrence = createProjectionRecurrenceProvider(input.knowledgeRoot, () => clock.now())\n const runsReader = createRunsReader(input.agentQaRoot)\n\n // Reads `composedRegistry` at call time, so a turn crosses the same registry's gate.\n let composedRegistry: FunctionRegistry | undefined\n // `unbound` when no model is bound; binding one later drifts by a `model_change` event.\n const composedChatModelName = input.chatModel === undefined ? 'unbound' : input.chatModel.modelId\n\n // Keyed by session: one container per host leaked one person's history into another's request.\n interface ChatSessionScope {\n readonly state: ChatStateContainer\n }\n const chatScopes = new Map<string, ChatSessionScope>()\n const chatScopeFor = (sessionId: string): ChatSessionScope => {\n const existing = chatScopes.get(sessionId)\n if (existing !== undefined) return existing\n if (composedRegistry === undefined) {\n throw new TypeError('a chat session opened before its registry finished composing')\n }\n const scope: ChatSessionScope = {\n // An UNBORN session has run no `/model`, so it opens under the model this host composed —\n // which is also what its header will say. A container seeded from another session's override\n // would make one conversation's verb the next conversation's opening posture.\n state: createChatState({ activeModel: composedChatModelName }),\n }\n chatScopes.set(sessionId, scope)\n return scope\n }\n\n // Read, never captured: a thunk holding the composed model undoes a `/model` on the next turn.\n const chatModelNameFor = (sessionId: string): string =>\n chatScopeFor(sessionId).state.read().activeModel\n\n // The live model OBJECT for a model name. Keyed by name rather than by session, because\n // `chatModelFor` is a resolution of a name and two sessions naming the same model mean the same\n // model — the same reason the planner stage cache below is keyed that way. Which name a session\n // is under is the per-session fact, and it lives in that session's state.\n const chatModelsByName = new Map<string, ChatLanguageModel>()\n if (input.chatModel !== undefined) chatModelsByName.set(composedChatModelName, input.chatModel)\n\n const chatSessionLog = createJsonlSessionLog({\n root: input.agentQaRoot,\n now: () => clock.now(),\n // The composed model, masked: a live override would stamp one session's switch on later ones.\n model: () => input.mask(composedChatModelName),\n toolsetHash: () => chatToolsetHash(composedRegistry),\n })\n\n // Writers outside a turn name it by its logged id; a turn nobody holds gets no row.\n const liveChatSessions = new Map<string, { handle: ChatSessionHandle; turnIds: Set<string> }>()\n\n const trackedChatSessionLog: SessionLogPort = {\n async open(sessionId?: string): Promise<ChatSessionHandle> {\n const opened = await chatSessionLog.open(sessionId)\n const id = opened.header.sessionId\n const turnIds = new Set<string>()\n const tracked: ChatSessionHandle = {\n header: opened.header,\n events: opened.events,\n refusedLines: opened.refusedLines,\n append: async (event) => {\n // Every event carries the declared mask, per member.\n const projected = projectChatSessionEvent(event, input.mask)\n turnIds.add(projected.turnId)\n await opened.append(projected)\n // The host's copy, taken after the write; a failing push must not fail its turn.\n try {\n input.observeSessionEvent?.(id, projected)\n } catch { /* a push channel's failure is not the turn's */ }\n },\n turnBoundary: () => opened.turnBoundary(),\n close: async () => {\n // Unregistered BEFORE the descriptor goes, so nothing can pick this handle up in the\n // window between the two and write through a closed one.\n liveChatSessions.delete(id)\n await opened.close()\n },\n }\n liveChatSessions.set(id, { handle: tracked, turnIds })\n return tracked\n },\n }\n\n /** The open session whose file already carries this turn, or none if nobody here holds it. */\n const chatSessionHoldingTurn = (turnId: string): ChatSessionHandle | undefined => {\n for (const entry of liveChatSessions.values()) {\n if (entry.turnIds.has(turnId)) return entry.handle\n }\n return undefined\n }\n\n // Built lazily, per model in force, because a stage binds its model.\n const plannerStages = new Map<string, PlannerStagePort>()\n const chatPlanner: PlannerStagePort | undefined =\n input.chatModel === undefined\n ? undefined\n : {\n plan: (request) => {\n if (composedRegistry === undefined) {\n throw new TypeError('a chat turn ran before its registry finished composing')\n }\n const activeName = chatModelNameFor(request.sessionId)\n let stage = plannerStages.get(activeName)\n if (stage === undefined) {\n stage = createPlannerStage({\n model: (chatModelsByName.get(activeName) ?? input.chatModel) as ChatLanguageModel,\n tools: projectPlannerTools(composedRegistry, CHAT_PLANNER_CALLER),\n // Read per request: a stage is shared by every session planning under one model.\n context: (contextRequest) => {\n const scope = chatScopeFor(contextRequest.sessionId).state.read()\n return { activeModel: scope.activeModel, conversation: scope.conversation }\n },\n })\n plannerStages.set(activeName, stage)\n }\n return stage.plan(request)\n },\n }\n\n // Bound when the host supplies accounting; its event goes through the per-turn handle.\n const chatCompaction: CompactionHook | undefined =\n input.chatAccounting === undefined\n ? undefined\n : createChatCompactionHook({\n accounting: input.chatAccounting,\n now: () => clock.now(),\n // What compaction leaves is the conversation the prompt renders, kept per session.\n onConversation: (messages, sessionId) => {\n chatScopeFor(sessionId).state.setConversation(messages)\n },\n })\n\n const chatTurn = createTurnEngine({\n table: CHAT_RESOLVER_TABLE,\n // The real conjunction grammar, quote-aware.\n split: splitClauses,\n reconcile: input.chatReconcile ?? deterministicOverrideStrategy,\n sessionLog: trackedChatSessionLog,\n // Minted per stage: a table hit is a person typing (`human`); a planned call is `agent`.\n mint: {\n forStage: (stage) => (stage === 'resolver' ? CHAT_RESOLVER_CALLER : CHAT_PLANNER_CALLER),\n },\n // Classify the original bytes before projecting: `invokeFunction` does not mask.\n invoke: async (functionId, invokeInput, caller) => {\n if (composedRegistry === undefined) {\n throw new TypeError('a chat turn ran before its registry finished composing')\n }\n const payload = await invokeFunction(composedRegistry, functionId, invokeInput, caller)\n const fold = foldFunctionResult(composedRegistry, functionId, payload)\n return projectChatMembers({ payload, ...fold }, CHAT_INVOKE_ANSWER_RULES, input.mask)\n },\n ...(chatPlanner === undefined ? {} : { planner: chatPlanner }),\n ...(chatCompaction === undefined ? {} : { compaction: chatCompaction }),\n // Resolved per session: `/model` and `/quit` act on the conversation running the turn.\n directives: (sessionId) => ({\n // Applies nothing: `/model` resolves and caches by name, so the apply cannot throw midway.\n validate: async (directive, argument) => {\n if (directive === 'model' && argument !== undefined && input.chatModelFor !== undefined) {\n chatModelsByName.set(argument, await input.chatModelFor(argument))\n }\n },\n model: async (name) => {\n const scope = chatScopeFor(sessionId)\n const from = scope.state.read().activeModel\n // Resolved ALREADY, when this host publishes `validate` — the pre-flight cached it under\n // this name and the apply reuses it rather than resolving a second time. Two resolutions\n // of one name on one turn would be two chances to disagree, and the second of them would\n // be running after the batch had been declared safe.\n if (input.chatModelFor !== undefined && !chatModelsByName.has(name)) {\n // A failed resolution refuses by name rather than silently keeping the old model.\n chatModelsByName.set(name, await input.chatModelFor(name))\n }\n scope.state.setActiveModel(name)\n return { from, to: name, line: `model: ${from} → ${name}` }\n },\n help: () => CHAT_HELP_TEXT,\n quit: () => {\n chatScopeFor(sessionId).state.requestClose()\n return 'closing this session'\n },\n }),\n state: (sessionId) => chatScopeFor(sessionId).state,\n // Re-read per turn and per session, and masked like the log it is compared with.\n config: (sessionId): ChatConfigState => {\n const ids = chatToolsetIds(composedRegistry)\n return {\n model: input.mask(chatModelNameFor(sessionId)),\n toolset: { hash: chatToolsetHash(composedRegistry), ids },\n }\n },\n // Bound only where the loop is; elsewhere an empty vocabulary refuses with the wrong cause.\n ...(input.draftAuthoring !== undefined && input.runExecution !== undefined\n ? { configuredTargets: () => (input.draftAuthoring as DraftAuthoringPort).configuredTargetNames() }\n : {}),\n // Spread conditionally, so a host binding no surface leaves `present` absent.\n ...(input.chatPresent === undefined ? {} : { present: input.chatPresent }),\n now: () => clock.now(),\n mintTurnId: () => `turn-${randomUUID()}`,\n })\n\n // `runExecution` is in the condition because stage 4 dispatches `authoring.draft.verify`.\n const authoringLoopHost = input.draftAuthoring !== undefined && input.runExecution !== undefined\n ? input.draftAuthoring\n : undefined\n\n // Assembled once for the funnel op and the gate-2 consultation, so both read one answer.\n const authoringFunnel: AuthoringFunnelPortLike = {\n receipts: createDraftReceiptsStore({ resolveAgentQaRoot: () => input.agentQaRoot }),\n quarantine: {\n list: async () => (await createQuarantineOperations({\n resolveKnowledgeRoot: input.knowledgeRoot,\n now: () => clock.now(),\n mintIdentityPath: input.mintQuarantineIdentityPath,\n ...(input.resolveWriterAuthority === undefined\n ? {}\n : { resolveWriterAuthority: input.resolveWriterAuthority }),\n }).list()),\n },\n // One read-only connection per verb; absent data answers empty, other failures propagate.\n outcomes: {\n testsIn: async (product: string, filePath: string) => {\n const knowledgeRoot = await input.knowledgeRoot()\n const path = indexDbPath(knowledgeRoot)\n if (!existsSync(path)) return []\n const db = new DatabaseSync(path, { readOnly: true })\n try {\n return listTestsInFile(db, { product, filePath })\n .map((testName) => ({ filePath, testName }))\n } catch (error) {\n if (error instanceof Error && error.message.includes('no such table')) return []\n throw error\n } finally {\n db.close()\n }\n },\n outcomesFor: async (product: string, filePath: string, testName: string) => {\n const knowledgeRoot = await input.knowledgeRoot()\n const history = readProjectedTestHistory(knowledgeRoot, { product, filePath, testName })\n if (history === undefined) return []\n return history.lastOutcomes.map((entry) => (entry.passed ? 'passed' : 'failed'))\n },\n },\n }\n\n const registry = createFunctionRegistry({\n deps: {\n secretMask: input.mask,\n runs: {\n ...runsReader,\n get: async (runId) => {\n await recurrence.prime()\n return runsReader.get(runId)\n },\n },\n // List verbs are live sighting sites: an entity gets its address when first surfaced.\n knowledge: createKnowledgeReader(\n input.knowledgeRoot,\n createMemorySightingHook(entityResolutionInput),\n ),\n config: input.config,\n entities: createEntityDirectory(entityResolutionInput),\n // Optional, so a read-only host reports the mutating verbs as `unbound` by name.\n knowledgeReview: createKnowledgeReview({\n agentQaRoot: input.agentQaRoot,\n resolveKnowledgeRoot: input.knowledgeRoot,\n ...(input.knowledgeChangeDelegate === undefined\n ? {}\n : { knowledgeChangeDelegate: input.knowledgeChangeDelegate }),\n ...(input.resolveWriterAuthority === undefined\n ? {}\n : { resolveWriterAuthority: input.resolveWriterAuthority }),\n // The host's own context, so a direct change records the context it is made in.\n ...(input.resolveExecutionContext === undefined\n ? {}\n : { resolveExecutionContext: input.resolveExecutionContext }),\n }),\n // On every host, unlike `postRun`: a host that never drains still reads what the chain did.\n postProcessing: createPostProcessingReader({\n agentQaRoot: input.agentQaRoot,\n idSource: input.idSource ?? DIGEST_JOB_ID_SOURCE,\n }),\n // An absent port must be an absent field: the registry lists capabilities off this record.\n ...(input.runDetail === undefined ? {} : { runDetail: input.runDetail }),\n // On every host, and the same reader the analysis job uses, so both agree where a blob is.\n evidenceBlobs: createEvidenceBlobReader({ agentQaRoot: input.agentQaRoot }),\n // Present only if this host can run; the registry lists `runs.start` from the same record.\n ...(input.runExecution === undefined ? {} : {\n runInvocation: createLocalRunInvocation({\n agentQaRoot: input.agentQaRoot,\n execution: input.runExecution,\n }),\n }),\n // Bindable from the roots alone, so every host serves the floor or the no-history clause.\n analysis: createAnalysisArtifactReader(input.agentQaRoot),\n recurrence: recurrence.provider,\n // Spread conditionally so `agent.explain` lists `unbound` where no catalog is handed in.\n ...(input.capabilityCatalog === undefined\n ? {}\n : { capabilityCatalog: input.capabilityCatalog }),\n // Spread conditionally, so `runs.liveurl` declares `unbound` where no origin is served.\n ...(input.liveView === undefined ? {} : { liveView: input.liveView }),\n // The funnel reads records this host owns, so it is unconditional; its receipts port lists.\n authoringFunnel,\n ...(input.feedback === undefined ? {} : { feedback: input.feedback }),\n ...(input.feedbackReads === undefined ? {} : { feedbackReads: input.feedbackReads }),\n quarantine: createQuarantineOperations({\n resolveKnowledgeRoot: input.knowledgeRoot,\n now: () => clock.now(),\n mintIdentityPath: input.mintQuarantineIdentityPath,\n ...(input.resolveWriterAuthority === undefined\n ? {}\n : { resolveWriterAuthority: input.resolveWriterAuthority }),\n }),\n // Bound here, so `agent.ask` is a real capability on every host.\n chatTurn: {\n // The engine also echoes authored clause text on receipts and refusal answers. Mask\n // the complete outward projection after execution, never the message it dispatches.\n runTurn: async turnInput =>\n projectChatMembers(await chatTurn.runTurn(turnInput), CHAT_TURN_RESULT_RULES, input.mask),\n },\n // Both halves spread conditionally: a host that can parse but not run says `unbound`.\n ...(input.draftAuthoring === undefined || input.runExecution === undefined ? {} : {\n draftEvaluation: createDraftEvaluation({\n authoring: input.draftAuthoring,\n agentQaRoot: input.agentQaRoot,\n knowledgeRoot: input.knowledgeRoot,\n authoringFunnel,\n readRun: (runId) => runsReader.get(runId as RunId),\n startGateRun: async (request) => {\n if (composedRegistry === undefined) {\n throw new TypeError('a gate-run started before its registry finished composing')\n }\n return await invokeFunction(\n composedRegistry,\n RUNS_START_FUNCTION_ID,\n request,\n AUTHORING_GATE_RUN_CALLER,\n ) as RunStartAcknowledgement\n },\n }),\n }),\n // The arch import scan reads comments too: never put a quote after the word `from`.\n ...(authoringLoopHost === undefined ? {} : {\n authoringRead: {\n async getAuthoringBrief(intent: string, scope: ScopeKey): Promise<AuthoringBrief> {\n const knowledgeRoot = await input.knowledgeRoot()\n return createAuthoringReader({ knowledgeRoot }).getAuthoringBrief(intent, scope)\n },\n suiteTextCorpus: () => authoringLoopHost.suiteTextCorpus(),\n // Off the same port as the brief and corpus, so a loop host names its own targets.\n configuredTargetNames: () => authoringLoopHost.configuredTargetNames(),\n },\n // Its own key: a scope needs config and workspace, the brief needs an index.\n authoringScope: {\n deriveDefault: () => authoringLoopHost.deriveDefaultScope(),\n },\n draftShelf: {\n model: async () => await input.model(),\n write: (contents: string) => authoringLoopHost.stageDraft(contents),\n // The one RFC 6902 applier, at the host because it needs `core`'s yaml CST.\n applyPatches: (draft, patchSet) => authoringLoopHost.applyPatchesToDraft(draft, patchSet),\n // Same seam as the verbs above: the boundary check needs `core`.\n publish: (request) => authoringLoopHost.publishDraft(request),\n // The evaluator's reader; probes use the gate-run caller, so outcomes exclude them.\n runs: {\n start: async (request): Promise<RunStartAcknowledgement> => {\n if (composedRegistry === undefined) {\n throw new TypeError('a repair probe started before its registry finished composing')\n }\n return await invokeFunction(\n composedRegistry,\n RUNS_START_FUNCTION_ID,\n request,\n AUTHORING_GATE_RUN_CALLER,\n ) as RunStartAcknowledgement\n },\n get: (runId: string) => runsReader.get(runId as RunId),\n },\n verifyDraft: async (verifyInput: AuthoringVerifyDraftInput): Promise<DraftReceipt> => {\n if (composedRegistry === undefined) {\n throw new TypeError('a draft was verified before its registry finished composing')\n }\n return await invokeFunction(\n composedRegistry,\n AUTHORING_DRAFT_VERIFY_FUNCTION_ID,\n verifyInput,\n AUTHORING_LOOP_VERIFY_CALLER,\n ) as DraftReceipt\n },\n },\n }),\n // Each config-editor half spreads on its own condition, so a missing one reads `unbound`.\n ...(input.configFiles === undefined ? {} : { configFiles: input.configFiles }),\n ...(input.configValidate === undefined ? {} : { configValidate: input.configValidate }),\n ...(input.scaffoldContent === undefined\n ? {}\n : { scaffoldContent: input.scaffoldContent }),\n ...(input.configWrite === undefined ? {} : { configWrite: input.configWrite }),\n },\n })\n // Closes the cycle the turn engine's dispatch binding was built against. It happens exactly\n // here, on the line after the registry exists, so there is no window in which a turn could run\n // against an unset reference — and the engine's own guard names that state if one ever appears.\n composedRegistry = registry\n\n let opened: LocalAgentJobs | undefined\n let opening: Promise<LocalAgentJobs> | undefined\n let closing: Promise<void> | undefined\n let lifecycleGeneration = 0\n let closed = false\n\n async function openJobs(openGeneration: number): Promise<LocalAgentJobs> {\n const model = await input.model()\n // Resolved ONCE at queue open, the same idiom as the model above: the post-run\n // capability members read synchronously, and the knowledge root is a process fact.\n const knowledgeRoot = await input.knowledgeRoot()\n const analysisTokenBudget = input.analysisTokenBudget === undefined\n ? undefined\n : await input.analysisTokenBudget()\n const store = createSqliteJobStore({\n path: join(input.agentQaRoot, AGENT_JOB_STORE_DB_FILE),\n clock,\n checkpoints: createJobCheckpointStore({ root: input.agentQaRoot }),\n })\n let jobs: LocalAgentJobs\n try {\n const kinds = input.jobKinds\n ?? createRealJobKindRegistry(\n postRunCapabilities(input, knowledgeRoot, analysisTokenBudget),\n )\n // Resolved ONCE and used for both the queue and the published field: the value a watcher\n // derives ids from has to be the value the queue mints them with, and two spellings of the\n // same default is how those two drift.\n const idSource = input.idSource ?? DIGEST_JOB_ID_SOURCE\n // No `postRun` folds to `no-masker`: an undeclared fold posture cannot have been reviewed.\n const unclaimableKinds: readonly JobKind[]\n = UNCLAIMABLE_BY_PROSE_POSTURE[input.postRun?.candidateProse ?? 'no-masker']\n jobs = {\n queue: createAgentJobQueue({\n store,\n registry: kinds,\n clock,\n idSource,\n model,\n ...(unclaimableKinds.length === 0 ? {} : { unclaimableKinds }),\n }),\n store,\n kinds,\n model,\n idSource,\n unclaimableKinds,\n }\n } catch (error) {\n store.close()\n throw error\n }\n if (closed || openGeneration !== lifecycleGeneration) {\n // The model can resolve after close. Constructing then invalidating here keeps the open\n // transactional: the late store proves it can initialize, but it never becomes reachable.\n store.close()\n throw new LocalAgentClosedError(input.agentQaRoot)\n }\n opened = jobs\n return jobs\n }\n\n return {\n registry,\n chat: {\n stateFor: (sessionId) => chatScopes.get(sessionId)?.state.read(),\n async abortActiveTurn(): Promise<void> {\n // Each live session aborts its own turn in flight; between turns it writes nothing.\n for (const [sessionId, entry] of liveChatSessions) {\n const turnId = chatScopes.get(sessionId)?.state.read().activeTurnId\n if (turnId === undefined) continue\n if (!entry.turnIds.has(turnId)) continue\n await entry.handle.append({\n kind: 'aborted',\n turnId,\n at: clock.now(),\n source: 'explicit',\n })\n // Fsynced immediately rather than at a turn boundary that is not coming: this is the\n // last thing this process writes, and an unflushed `aborted` is exactly the event the\n // repair it exists to make unnecessary would have to reconstruct.\n await entry.handle.turnBoundary()\n }\n },\n },\n curation: LOCAL_CURATION_CAPABILITIES,\n clock,\n jobs(): Promise<LocalAgentJobs> {\n if (closed) return Promise.reject(new LocalAgentClosedError(input.agentQaRoot))\n // Memoized on the PROMISE, not on the resolved value: two concurrent callers awaiting a\n // value-memoized opener would each run the factory and each open the database.\n opening ??= openJobs(lifecycleGeneration)\n return opening\n },\n close(): Promise<void> {\n if (closing !== undefined) return closing\n closed = true\n lifecycleGeneration += 1\n const pending = opening\n const current = opened\n opened = undefined\n // Closing synchronously releases the handle even for callers that do not await `close`.\n current?.store.close()\n closing = (async () => {\n if (pending !== undefined) {\n try {\n const late = await pending\n if (late !== current) late.store.close()\n } catch {\n // A superseded opener closes its own store; a model/open failure owns no live handle.\n }\n }\n opening = undefined\n })()\n return closing\n },\n }\n}\n","// On the reader carve-out list, so this file cannot name the writer entry; sighting is injected.\n\nimport {\n canaryAttributionsFor,\n gateReceiptsFor,\n diffSince,\n inspectRecords,\n listBundles,\n showRecord,\n showRecords,\n} from '@vostride/agent-qa-knowledge-local/reader'\nimport type { KnowledgeReaderPort } from '@vostride/agent-qa-agent'\n\n/**\n * Hand every entity id an output surfaced to the addressing ledger's sighting seam.\n *\n * Fire-and-forget by contract: it resolves when the sighting is recorded, and a rejection is\n * not the read's problem. An address is a permanent fact about an entity and a listing is a\n * question about the store; failing the question because the bookkeeping failed would let the\n * ledger take down the answer it exists to annotate.\n */\nexport type SightMemoryEntities = (bundleIds: readonly string[]) => Promise<void>\n\nexport interface ConstructKnowledgeReaderPortInput {\n /**\n * Which knowledge root this invocation serves from, resolved per call.\n *\n * A host-supplied resolver rather than a string, on the same reasoning the bundle listing\n * already carried: deciding which configuration file is in force is a decision a daemon\n * makes differently from a terminal.\n */\n resolveKnowledgeRoot: () => Promise<string> | string\n // The sighting site; absent in hosts that bind no addressing ledger.\n sightMemoryEntities?: SightMemoryEntities\n}\n\nexport function createKnowledgeReaderPort(\n input: ConstructKnowledgeReaderPortInput,\n): KnowledgeReaderPort {\n async function sight(bundleIds: readonly string[]): Promise<void> {\n if (input.sightMemoryEntities === undefined || bundleIds.length === 0) return\n try {\n await input.sightMemoryEntities(bundleIds)\n } catch {\n // See `SightMemoryEntities`: the read already answered.\n }\n }\n\n return {\n // The caller supplied the identity; forward the reader's answer verbatim.\n async gateReceipts({ candidateId }) {\n return gateReceiptsFor({\n knowledgeRoot: await input.resolveKnowledgeRoot(),\n candidateId,\n })\n },\n async listBundles() {\n const rows = listBundles(await input.resolveKnowledgeRoot())\n await sight(rows.map((row) => row.bundleId))\n return rows\n },\n async inspectRecords({ filter }) {\n const records = inspectRecords({\n knowledgeRoot: await input.resolveKnowledgeRoot(),\n filter,\n })\n await sight(records.map((record) => record.recordId))\n return records\n },\n async diffSince({ sinceOrdinal }) {\n const changes = diffSince({\n knowledgeRoot: await input.resolveKnowledgeRoot(),\n sinceOrdinal,\n })\n // A change list names records by id including ones whose bundle is gone (a purge\n // change). Those simply are not sighted: the sighting seam requires a source to\n // RECOGNISE the id, so a purged record mints nothing and the ledger stays a record of\n // entities that were actually seen rather than of ids that were mentioned.\n await sight(changes.map((change) => change.recordId))\n return changes\n },\n async showRecord({ recordId }) {\n const result = showRecord({\n knowledgeRoot: await input.resolveKnowledgeRoot(),\n recordId,\n })\n await sight(result.kind === 'found' ? [result.record.recordId] : [])\n return result\n },\n // Caller-supplied union IDs are already known, like canary tuples below. Forward\n // the maintenance batch without address-ledger sightings or per-record scans.\n async showRecords({ recordIds }) {\n return showRecords({ knowledgeRoot: await input.resolveKnowledgeRoot(), recordIds })\n },\n // Not sighted; `skippedBundles` is forwarded verbatim so a half-read store never looks clean.\n async canaryAttributions({ runId, tuples }) {\n return canaryAttributionsFor({\n knowledgeRoot: await input.resolveKnowledgeRoot(),\n runId,\n tuples,\n })\n },\n }\n}\n","// Stage, fsync, rename, fsync the directory: the artifact is what a chip's `done` promises exists.\n\nimport { closeSync, fsyncSync, openSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport { randomUUID } from 'node:crypto'\nimport { dirname, join } from 'node:path'\n\nimport { canonicalJson } from '@vostride/agent-qa-schema'\nimport type { RunAnalysisArtifact } from '@vostride/agent-qa-schema'\n\n/** The staged-file marker, kept distinct from the receipt writer's so residue is attributable. */\nconst ANALYSIS_STAGE_PREFIX = 'analysis.json'\n\nfunction fsyncFile(file: string): void {\n const fd = openSync(file, 'r')\n try {\n fsyncSync(fd)\n } finally {\n closeSync(fd)\n }\n}\n\n// The caller owns the path; this helper owns only the bytes and their durability.\nexport function writeAnalysisArtifact(path: string, artifact: RunAnalysisArtifact): void {\n const dir = dirname(path)\n const staged = join(dir, `.${ANALYSIS_STAGE_PREFIX}.${randomUUID()}.tmp`)\n try {\n writeFileSync(staged, `${canonicalJson(artifact)}\\n`, { encoding: 'utf8', mode: 0o600 })\n fsyncFile(staged)\n renameSync(staged, path)\n fsyncFile(dir)\n } finally {\n rmSync(staged, { force: true })\n }\n}\n","// Append-only, one fsync on the header and one per turn, one descriptor per session handle.\n\nimport {\n closeSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readSync,\n readFileSync,\n readdirSync,\n writeFileSync,\n} from 'node:fs'\nimport { isAbsolute, join } from 'node:path'\n\nimport { repairSession } from '@vostride/agent-qa-agent'\nimport { CURRENT_CHAT_SESSION_SCHEMA_VERSION } from '@vostride/agent-qa-schema'\nimport type {\n ChatSessionEvent,\n ChatSessionHandle,\n ChatSessionHeader,\n OpenedChatSession,\n SessionLogPort,\n} from '@vostride/agent-qa-schema'\n\nimport { DIRECTORY_FSYNC_SWALLOWED_CODES } from '../store/job-checkpoint-store.js'\n\n// Directory segment under the agent-qa runtime root; gitignored.\nexport const CHAT_SESSIONS_SUBDIR = 'sessions'\n\n/** The file extension every session log carries. A listing filters on it, nothing else. */\nconst SESSION_FILE_SUFFIX = '.jsonl'\n\nexport const CHAT_SESSION_READ_CHUNK_BYTES = 64 * 1024\n\n/**\n * Ids that are safe as a single path segment.\n *\n * The same class `job-checkpoint-store.ts` uses, and the same reasoning: leading dots are excluded\n * so `..` cannot be an id at all, and the class admits no separator on any platform.\n */\nconst SAFE_PATH_SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/\n\n/** A caller-supplied session id that could not be a path segment. */\nexport class InvalidChatSessionIdError extends Error {\n override readonly name = 'InvalidChatSessionIdError'\n\n constructor(readonly sessionId: string) {\n super(\n `${JSON.stringify(sessionId)} is not a usable chat session id. Ids are minted by this `\n + 'adapter and are limited to letters, digits, dot, dash and underscore.',\n )\n }\n}\n\n// A refusal, never a create: a fresh session for a mistyped id would claim the history is lost.\nexport class UnknownChatSessionError extends Error {\n override readonly name = 'UnknownChatSessionError'\n\n constructor(readonly sessionId: string) {\n super(`No chat session ${sessionId} exists under this project's runtime root.`)\n }\n}\n\n// A refusal by name, not a second descriptor; the id is on the error so a caller can wait.\nexport class ChatSessionBusyError extends Error {\n override readonly name = 'ChatSessionBusyError'\n\n constructor(readonly sessionId: string) {\n super(\n `Chat session ${sessionId} is already open in this process. One writer at a time: a second `\n + 'handle would interleave two turns in one conversation.',\n )\n }\n}\n\n/** Bytes that do not describe a session this build can append to. */\nexport class ChatSessionHeaderError extends Error {\n override readonly name = 'ChatSessionHeaderError'\n\n constructor(\n readonly sessionId: string,\n readonly detail: string,\n ) {\n super(`The session file for ${sessionId} cannot be read: ${detail}.`)\n }\n}\n\n/**\n * Exactly the filesystem calls this module makes, and nothing else.\n *\n * `'a'` is the append-mode open the whole design rests on: the kernel places every write at the\n * current end of file, so two writers cannot interleave a partial line, and no offset bookkeeping\n * exists here to get wrong. `'r'` appears twice for two unrelated reasons — the parent-directory\n * fsync needs a descriptor on the directory, and the listing needs a bounded read on a file.\n *\n * `writeFileSync` on a descriptor rather than `writeSync` is deliberate. `writeSync` may report a\n * SHORT write and leave the caller to loop; a loop is exactly the offset bookkeeping the append\n * mode was chosen to abolish, and a forgotten one is a half-written line — the damage shape this\n * file is otherwise built to survive. `writeFileSync` writes the whole buffer or throws, which is\n * also what the checkpoint store's facade takes.\n */\nexport interface ChatSessionFs {\n mkdirSync(path: string, options: { readonly recursive: true }): void\n openSync(path: string, flags: 'a' | 'wx' | 'r'): number\n writeFileSync(fd: number, data: string, encoding: 'utf8'): void\n fsyncSync(fd: number): void\n closeSync(fd: number): void\n readSync(\n fd: number,\n buffer: Buffer,\n offset: number,\n length: number,\n position: number | null,\n ): number\n readFileSync(path: string, encoding: 'utf8'): string\n readdirSync(path: string): string[]\n}\n\n/** The production implementation, frozen so it cannot be patched from a distance. */\nexport const REAL_CHAT_SESSION_FS: ChatSessionFs = Object.freeze({\n mkdirSync,\n openSync,\n writeFileSync,\n fsyncSync,\n closeSync,\n readSync,\n readFileSync,\n readdirSync,\n})\n\n/**\n * What a production caller supplies: a root and the session's opening context.\n *\n * The absence of an fs member is the guarantee, exactly as it is on `CreateJobCheckpointStoreOptions`.\n */\nexport interface CreateJsonlSessionLogOptions {\n /** Absolute path to the agent-qa runtime root, typically `<project>/.agent-qa`. */\n readonly root: string\n /** ISO instant source — the composition's clock, never `Date.now()` reached for here. */\n readonly now: () => string\n /**\n * The model in force when the session opens. Drift is `model_change` events, never a rewrite.\n *\n * A THUNK rather than a string, because a composition root resolves its model lazily — a host\n * that only lists the registry must not pay a provider resolution — and a header built from a\n * value captured at construction would name whatever was true before that resolution ran.\n */\n readonly model: () => string\n /** The toolset fingerprint at open, on the same thunk reasoning as `model` above. */\n readonly toolsetHash: () => string\n // A value, not a thunk, because the header is written once; absent writes no tag.\n readonly surface?: string\n /** Random source for the id suffix, injectable so a test can pin an id. */\n readonly random?: () => number\n}\n\n/** One session, as a listing knows it: everything the header line says, plus how long the log is. */\nexport interface ChatSessionListEntry {\n readonly sessionId: string\n readonly createdAt: string\n /** The model in force when the session OPENED. Drift after that is `model_change` events. */\n readonly model: string\n // An event count, because a turn count would mean parsing every line of every log.\n readonly eventCount: number\n}\n\n/** One session file the listing could not read, surfaced as data rather than thrown over. */\nexport interface RefusedChatSessionFile {\n /** The file's own name, which is what a person has to go and look at. */\n readonly file: string\n readonly reason: string\n}\n\nexport interface ChatSessionListing {\n readonly sessions: readonly ChatSessionListEntry[]\n readonly refused: readonly RefusedChatSessionFile[]\n}\n\n/**\n * `chat-<UTCyyyymmdd-HHMMSS>-<4 base36>`.\n *\n * Sorted-by-name equals sorted-by-time, which is what makes a plain directory listing the session\n * list; the random tail is what keeps two sessions opened in the same second distinct. Every\n * character is in `SAFE_PATH_SEGMENT` by construction, so a minted id can never be refused by the\n * guard that protects a supplied one.\n */\nexport function mintChatSessionId(nowIso: string, random: () => number): string {\n const stamp = nowIso.replace(/[-:]/g, '').replace(/\\.\\d+Z$/, 'Z').replace('T', '-').replace('Z', '')\n const suffix = Math.floor(random() * 36 ** 4)\n .toString(36)\n .padStart(4, '0')\n return `chat-${stamp}-${suffix}`\n}\n\nfunction requireSessionId(sessionId: string): string {\n if (!SAFE_PATH_SEGMENT.test(sessionId)) throw new InvalidChatSessionIdError(sessionId)\n return sessionId\n}\n\nfunction isSwallowableDirectoryFsyncError(error: unknown): boolean {\n const code = (error as NodeJS.ErrnoException).code\n return DIRECTORY_FSYNC_SWALLOWED_CODES.some((allowed) => allowed === code)\n}\n\n/**\n * The header guard: version BEFORE shape.\n *\n * The order is the same decision `job-checkpoint-store.ts:231-237` states — a version mismatch has\n * a remedy an operator can act on, and reporting it as a generic shape failure names a field\n * instead. The `readonly` cast is safe because the value is re-validated field by field below.\n */\nfunction guardHeader(sessionId: string, line: string): ChatSessionHeader {\n let parsed: unknown\n try {\n parsed = JSON.parse(line)\n } catch {\n throw new ChatSessionHeaderError(sessionId, 'its first line is not JSON')\n }\n if (parsed === null || typeof parsed !== 'object') {\n throw new ChatSessionHeaderError(sessionId, 'its header line is not an object')\n }\n const header = parsed as Record<string, unknown>\n if (header.schemaVersion !== CURRENT_CHAT_SESSION_SCHEMA_VERSION) {\n throw new ChatSessionHeaderError(\n sessionId,\n `it declares schemaVersion ${String(header.schemaVersion)} and this build reads `\n + String(CURRENT_CHAT_SESSION_SCHEMA_VERSION),\n )\n }\n if (header.sessionId !== sessionId) {\n throw new ChatSessionHeaderError(\n sessionId,\n `its header names session ${String(header.sessionId)}`,\n )\n }\n if (typeof header.createdAt !== 'string' || typeof header.model !== 'string') {\n throw new ChatSessionHeaderError(sessionId, 'its header names no creation instant or model')\n }\n // Absent passes; a present non-string `surface` is refused rather than narrowed.\n if (header.surface !== undefined && typeof header.surface !== 'string') {\n throw new ChatSessionHeaderError(\n sessionId,\n `its header names a surface of type ${typeof header.surface} and this build reads a string`,\n )\n }\n return header as unknown as ChatSessionHeader\n}\n\n// A damaged file costs only its own entry; throwing would hide every healthy session.\nexport function listSessions(root: string): ChatSessionListing {\n if (!isAbsolute(root)) throw new TypeError('chat session log root must be absolute')\n const fs = REAL_CHAT_SESSION_FS\n const sessionsRoot = join(root, CHAT_SESSIONS_SUBDIR)\n\n let files: string[]\n try {\n files = fs.readdirSync(sessionsRoot)\n } catch (error) {\n // No sessions directory is no sessions, not a failure: a project that has never opened chat is\n // in exactly that state, and it is the state the very first `chat` command starts from.\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return { sessions: [], refused: [] }\n throw error\n }\n\n const sessions: ChatSessionListEntry[] = []\n const refused: RefusedChatSessionFile[] = []\n\n for (const file of [...files].sort()) {\n if (!file.endsWith(SESSION_FILE_SUFFIX)) continue\n const sessionId = file.slice(0, -SESSION_FILE_SUFFIX.length)\n try {\n const scanned = scanSessionFile(fs, join(sessionsRoot, file))\n if (scanned.headerLine === undefined) {\n refused.push({ file, reason: 'it carries no complete header line' })\n continue\n }\n const header = guardHeader(sessionId, scanned.headerLine)\n sessions.push({\n sessionId: header.sessionId,\n createdAt: header.createdAt,\n model: header.model,\n eventCount: Math.max(scanned.lineCount - 1, 0),\n })\n } catch (error) {\n refused.push({ file, reason: error instanceof Error ? error.message : String(error) })\n }\n }\n\n return { sessions, refused }\n}\n\n/**\n * One pass over a session file: its first line, and how many complete lines it has.\n *\n * Constant memory by construction — one reused chunk buffer, no accumulation past the header line,\n * and NO EVENT IS EVER PARSED. A listing that guarded every line would be `open()` wearing a\n * cheaper name, and would inherit `open()`'s right to refuse a whole session over one damaged line.\n */\nfunction scanSessionFile(\n fs: ChatSessionFs,\n path: string,\n): { headerLine: string | undefined; lineCount: number } {\n const fd = fs.openSync(path, 'r')\n try {\n const buffer = Buffer.allocUnsafe(CHAT_SESSION_READ_CHUNK_BYTES)\n let headerLine: string | undefined\n let headerBytes = ''\n let lineCount = 0\n let read = fs.readSync(fd, buffer, 0, buffer.length, null)\n while (read > 0) {\n const chunk = buffer.subarray(0, read)\n for (let index = 0; index < chunk.length; index += 1) {\n if (chunk[index] === 0x0a) lineCount += 1\n }\n if (headerLine === undefined) {\n headerBytes += chunk.toString('utf8')\n const newline = headerBytes.indexOf('\\n')\n if (newline >= 0) headerLine = headerBytes.slice(0, newline)\n // A \"header\" longer than one chunk is not a header this build wrote; stop accumulating so\n // one damaged file cannot be read into memory in its entirety by a listing.\n else if (headerBytes.length > CHAT_SESSION_READ_CHUNK_BYTES) break\n }\n read = fs.readSync(fd, buffer, 0, buffer.length, null)\n }\n return { headerLine, lineCount }\n } finally {\n fs.closeSync(fd)\n }\n}\n\nexport function createJsonlSessionLog(options: CreateJsonlSessionLogOptions): SessionLogPort {\n return createJsonlSessionLogOn(REAL_CHAT_SESSION_FS, options)\n}\n\n/**\n * The same log over an injected filesystem. TEST SEAM — production uses the factory above.\n *\n * It exists because the syscall ORDER is the durability property and no crash test can observe it\n * (the kernel does not drop pages it already holds when a process dies). Keeping it a separate\n * function rather than an optional field means a production construction cannot reach it by filling\n * in one more property, and keeping it off this package's barrel means no other package can reach\n * it at all. A test asserts that nothing outside `__tests__` calls it.\n */\nexport function createJsonlSessionLogOn(\n fs: ChatSessionFs,\n options: CreateJsonlSessionLogOptions,\n): SessionLogPort {\n if (!isAbsolute(options.root)) {\n throw new TypeError('chat session log root must be absolute')\n }\n const sessionsRoot = join(options.root, CHAT_SESSIONS_SUBDIR)\n const random = options.random ?? Math.random\n\n // Descriptors are keyed by session id and reached only through the handle that owns each.\n const liveDescriptors = new Map<string, number>()\n\n function pathFor(sessionId: string): string {\n return join(sessionsRoot, `${sessionId}.jsonl`)\n }\n\n function bestEffortFsyncDirectory(dir: string): void {\n let directoryFd: number | undefined\n try {\n directoryFd = fs.openSync(dir, 'r')\n fs.fsyncSync(directoryFd)\n } catch (error) {\n if (!isSwallowableDirectoryFsyncError(error)) throw error\n } finally {\n if (directoryFd !== undefined) fs.closeSync(directoryFd)\n }\n }\n\n function readLines(\n sessionId: string,\n ): { lines: { lineNumber: number; text: string }[]; terminated: boolean } | undefined {\n let text: string\n try {\n text = fs.readFileSync(pathFor(sessionId), 'utf8')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined\n throw error\n }\n return {\n // Line numbers are 1-based and count the header, so a refusal names what an editor shows the\n // person who has to go and look at the file.\n lines: text\n .split('\\n')\n .map((line, index) => ({ lineNumber: index + 1, text: line }))\n .filter((line) => line.text !== ''),\n // Every line this adapter writes ends in a newline, so a file that does not is a file whose\n // last write was cut short. That fact cannot be recovered once the lines are split, and the\n // append path needs it BEFORE it writes anything (see `terminateTornTail`).\n terminated: text === '' || text.endsWith('\\n'),\n }\n }\n\n function writeEvent(target: number, event: ChatSessionEvent): void {\n // One JSON document per line, written through an `O_APPEND` fd so the kernel places it at the\n // end of file. No offset is tracked here, which is what makes a second writer's line impossible\n // to interleave with a partial one of ours.\n fs.writeFileSync(target, `${JSON.stringify(event)}\\n`, 'utf8')\n }\n\n /**\n * One session's handle, closing over the descriptor THAT session's open produced.\n *\n * The descriptor is a closure variable of one handle rather than a field of the adapter, which is\n * the structural statement of the contract: there is no expression anywhere in this module that\n * reaches another session's fd, so no interleaving of two callers' awaits can produce one.\n */\n function handleFor(\n id: string,\n fd: number,\n opened: OpenedChatSession,\n ): ChatSessionHandle {\n let live = true\n const requireLive = (verb: string): void => {\n if (!live) {\n throw new TypeError(\n `a chat session ${verb} cannot go through a closed handle for ${id}. Open the session `\n + 'again to write to it.',\n )\n }\n }\n const handle: ChatSessionHandle = {\n header: opened.header,\n events: opened.events,\n refusedLines: opened.refusedLines,\n append(event: ChatSessionEvent): Promise<void> {\n requireLive('event')\n writeEvent(fd, event)\n return Promise.resolve()\n },\n turnBoundary(): Promise<void> {\n // A REFUSAL rather than a silent no-op: a boundary that quietly skipped its fsync would\n // report a durability guarantee it did not buy, which is the one lie this file is built\n // to make impossible.\n requireLive('turn boundary')\n fs.fsyncSync(fd)\n return Promise.resolve()\n },\n close(): Promise<void> {\n // Idempotent, so a caller's `finally` may call it unconditionally — the turn engine's does.\n if (live) {\n live = false\n liveDescriptors.delete(id)\n fs.closeSync(fd)\n }\n return Promise.resolve()\n },\n }\n liveDescriptors.set(id, fd)\n return handle\n }\n\n return {\n open(sessionId?: string): Promise<ChatSessionHandle> {\n fs.mkdirSync(sessionsRoot, { recursive: true })\n\n if (sessionId !== undefined) {\n const id = requireSessionId(sessionId)\n // BEFORE ANY WORK, and before any byte is read: a busy session is a refusal, not a second\n // descriptor. Asked first so a double-submit costs a caller nothing but the answer.\n if (liveDescriptors.has(id)) throw new ChatSessionBusyError(id)\n const read = readLines(id)\n // The refusal, not a create. See `UnknownChatSessionError`.\n if (read === undefined || read.lines.length === 0) throw new UnknownChatSessionError(id)\n const header = guardHeader(id, read.lines[0]!.text)\n // Repair runs before any caller sees an event; the version comes from the validated header.\n const repair = repairSession(read.lines.slice(1), {\n declaredVersion: header.schemaVersion,\n now: options.now,\n })\n const resumed = fs.openSync(pathFor(id), 'a')\n // TERMINATE A TORN TAIL BEFORE APPENDING ANYTHING. A crash leaves the last line without\n // its newline, so the very next append would land ON that fragment and fuse two records\n // into one unreadable line — turning a bounded, understood loss into permanent damage\n // that the next open would mistake for a fresh tear and lose all over again. One newline\n // closes the fragment where it stopped. It is still an APPEND: no existing byte moves,\n // and the fragment survives verbatim as its own refused line for anyone auditing the file.\n let wroteDuringRepair = false\n if (!read.terminated) {\n fs.writeFileSync(resumed, '\\n', 'utf8')\n wroteDuringRepair = true\n }\n for (const event of repair.synthesized) {\n writeEvent(resumed, event)\n wroteDuringRepair = true\n }\n if (wroteDuringRepair) {\n // A repair CLOSES the dangling turn, so it lands like any other turn boundary. A\n // synthesized abort a second crash could lose would leave the same session dangling\n // again, and the loss bound would stop being the in-flight turn.\n fs.fsyncSync(resumed)\n }\n return Promise.resolve(\n handleFor(id, resumed, {\n header,\n events: repair.repaired,\n refusedLines: repair.refusedLines,\n }),\n )\n }\n\n const createdAt = options.now()\n const id = mintChatSessionId(createdAt, random)\n const header: ChatSessionHeader = {\n schemaVersion: CURRENT_CHAT_SESSION_SCHEMA_VERSION,\n sessionId: id,\n createdAt,\n model: options.model(),\n toolsetHash: options.toolsetHash(),\n // Spread conditionally, so absent means the option is not given.\n ...(options.surface === undefined ? {} : { surface: options.surface }),\n }\n // Exclusive create, then fsync the header BEFORE the file is used, then fsync the directory\n // that now names it: a session file that exists at all is a session file whose header is on\n // the device, and whose entry survives the crash that follows.\n const created = fs.openSync(pathFor(id), 'wx')\n try {\n fs.writeFileSync(created, `${JSON.stringify(header)}\\n`, 'utf8')\n fs.fsyncSync(created)\n } finally {\n fs.closeSync(created)\n }\n bestEffortFsyncDirectory(sessionsRoot)\n const appendFd = fs.openSync(pathFor(id), 'a')\n return Promise.resolve(handleFor(id, appendFd, { header, events: [], refusedLines: [] }))\n },\n }\n}\n","// Each checkpoint is its own file, published by rename with a parent-directory fsync.\n\nimport { randomUUID } from 'node:crypto'\nimport {\n closeSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n rmSync,\n writeFileSync,\n} from 'node:fs'\nimport { dirname, isAbsolute, join } from 'node:path'\n\nimport {\n canonicalJson,\n asJobId,\n JOB_CHECKPOINT_SCHEMA_VERSION,\n jobCheckpointEnvelopeSchema,\n} from '@vostride/agent-qa-schema'\nimport type { JobCheckpointEnvelope } from '@vostride/agent-qa-schema'\n\nimport {\n InvalidJobCheckpointIdError,\n JobCheckpointSchemaVersionError,\n} from './store-errors.js'\n\n// Directory segments under the agent-qa root.\nexport const JOB_CHECKPOINT_SUBDIR = ['agent-jobs', 'checkpoints'] as const\n\n/**\n * Ids that are safe as a single path segment.\n *\n * Leading dots are excluded, so `..` cannot be an id at all, and the class admits no\n * separator on any platform.\n */\nconst SAFE_PATH_SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/\n\n// Platforms where a directory fsync is unsupported; anything else is a real I/O failure.\nexport const DIRECTORY_FSYNC_SWALLOWED_CODES = [\n 'ENOENT',\n 'EINVAL',\n 'EISDIR',\n 'EPERM',\n 'ENOTSUP',\n] as const\n\n/**\n * Exactly the filesystem calls this module makes, and nothing else.\n *\n * Narrow on purpose. A wide facade invites a test to answer on its own behalf; this one is\n * small enough that the only reasonable implementation besides the real functions is a\n * recorder that calls through to them.\n */\nexport interface JobCheckpointFs {\n mkdirSync(path: string, options: { readonly recursive: true }): void\n openSync(path: string, flags: 'wx' | 'r'): number\n writeFileSync(fd: number, data: string, encoding: 'utf8'): void\n fsyncSync(fd: number): void\n closeSync(fd: number): void\n renameSync(from: string, to: string): void\n rmSync(path: string, options: { readonly force: true }): void\n readFileSync(path: string, encoding: 'utf8'): string\n}\n\n/** The production implementation, frozen so it cannot be patched from a distance. */\nexport const REAL_JOB_CHECKPOINT_FS: JobCheckpointFs = Object.freeze({\n mkdirSync,\n openSync,\n writeFileSync,\n fsyncSync,\n closeSync,\n renameSync,\n rmSync,\n readFileSync,\n})\n\nexport interface JobCheckpointStore {\n publish(jobId: string, checkpointId: string, payload: unknown): void\n read(jobId: string, checkpointId: string): { found: false } | { found: true; payload: unknown }\n // The file caches the fenced sqlite record, so it is deleted when a requeue deletes that record.\n discard(jobId: string, checkpointId: string): void\n /** Exposed so a test can assert on the real file, not on a reader that could agree. */\n checkpointPath(jobId: string, checkpointId: string): string\n /** The directory the deterministic logical dump digests. */\n readonly checkpointsRoot: string\n}\n\n/**\n * What a production caller supplies: a root, and nothing else.\n *\n * The absence here is the guarantee. There is no filesystem member, so \"publish without the\n * fsync\" is not a one-argument change any composition root could make by accident.\n */\nexport interface CreateJobCheckpointStoreOptions {\n /** Absolute path to the agent-qa runtime root, typically `<project>/.agent-qa`. */\n readonly root: string\n}\n\nfunction requireSegment(field: 'jobId' | 'checkpointId', value: string): string {\n if (!SAFE_PATH_SEGMENT.test(value)) {\n throw new InvalidJobCheckpointIdError(field, value)\n }\n return value\n}\n\nfunction checkpointPath(root: string, jobId: string, checkpointId: string): string {\n if (!isAbsolute(root)) throw new TypeError('agent job checkpoint root must be absolute')\n return join(root, ...JOB_CHECKPOINT_SUBDIR, requireSegment('jobId', jobId),\n `${requireSegment('checkpointId', checkpointId)}.json`)\n}\n\nfunction readEnvelopeOn(\n fs: Pick<JobCheckpointFs, 'readFileSync'>,\n root: string,\n jobId: string,\n checkpointId: string,\n): { found: false } | { found: true; envelope: JobCheckpointEnvelope } {\n const file = checkpointPath(root, jobId, checkpointId)\n let text: string\n try {\n text = fs.readFileSync(file, 'utf8')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return { found: false }\n throw error\n }\n const raw = JSON.parse(text) as { schemaVersion?: unknown } | null\n // Preserve the named version refusal before structural validation.\n if (raw?.schemaVersion !== JOB_CHECKPOINT_SCHEMA_VERSION) {\n throw new JobCheckpointSchemaVersionError(file, raw?.schemaVersion)\n }\n const envelope = jobCheckpointEnvelopeSchema.parse(raw)\n if (envelope.jobId !== jobId || envelope.checkpointId !== checkpointId) {\n throw new TypeError('Agent job checkpoint envelope does not match its address')\n }\n return { found: true, envelope }\n}\n\n/** Cold read only: no store construction, directory creation or checkpoint publication. */\nexport function readJobCheckpointEnvelope(\n options: CreateJobCheckpointStoreOptions,\n jobId: string,\n checkpointId: string,\n): { found: false } | { found: true; envelope: JobCheckpointEnvelope } {\n return readEnvelopeOn(REAL_JOB_CHECKPOINT_FS, options.root, jobId, checkpointId)\n}\n\nfunction isSwallowableDirectoryFsyncError(error: unknown): boolean {\n const code = (error as NodeJS.ErrnoException).code\n return DIRECTORY_FSYNC_SWALLOWED_CODES.some((allowed) => allowed === code)\n}\n\nexport function createJobCheckpointStore(\n options: CreateJobCheckpointStoreOptions,\n): JobCheckpointStore {\n return createJobCheckpointStoreOn(REAL_JOB_CHECKPOINT_FS, options)\n}\n\n/**\n * The same store over an injected filesystem. TEST SEAM — production uses the factory above.\n *\n * It exists because the syscall ORDER is the durability property and no crash test can\n * observe it. Keeping it a separate function, rather than an optional field on the\n * production options, means a production construction cannot reach it by filling in one more\n * property; a test asserts that no non-test file in the workspace names it.\n */\nexport function createJobCheckpointStoreOn(\n fs: JobCheckpointFs,\n options: CreateJobCheckpointStoreOptions,\n): JobCheckpointStore {\n if (!isAbsolute(options.root)) {\n throw new TypeError('agent job checkpoint root must be absolute')\n }\n\n const checkpointsRoot = join(options.root, ...JOB_CHECKPOINT_SUBDIR)\n\n function pathFor(jobId: string, checkpointId: string): string {\n return checkpointPath(options.root, jobId, checkpointId)\n }\n\n function bestEffortFsyncDirectory(dir: string): void {\n let fd: number | undefined\n try {\n fd = fs.openSync(dir, 'r')\n fs.fsyncSync(fd)\n } catch (error) {\n if (!isSwallowableDirectoryFsyncError(error)) {\n throw error\n }\n } finally {\n if (fd !== undefined) fs.closeSync(fd)\n }\n }\n\n return {\n checkpointsRoot,\n checkpointPath: pathFor,\n\n publish(jobId, checkpointId, payload) {\n const file = pathFor(jobId, checkpointId)\n // Typed as the shipped envelope contract, so a field added on one side stops compiling.\n const envelope: JobCheckpointEnvelope = {\n schemaVersion: JOB_CHECKPOINT_SCHEMA_VERSION,\n jobId: asJobId(jobId),\n checkpointId,\n payload,\n }\n fs.mkdirSync(dirname(file), { recursive: true })\n const temporary = `${file}.tmp-${randomUUID()}`\n let fd: number | undefined\n try {\n // Exclusive create, so a torn temporary from an earlier crash can never be mistaken\n // for this one's; then fsync the fd BEFORE the rename, so the rename can only\n // publish bytes that are already on the device.\n fd = fs.openSync(temporary, 'wx')\n fs.writeFileSync(fd, `${canonicalJson(envelope)}\\n`, 'utf8')\n fs.fsyncSync(fd)\n fs.closeSync(fd)\n fd = undefined\n fs.renameSync(temporary, file)\n // A rename is a directory mutation, durable only once its parent directory is synced.\n bestEffortFsyncDirectory(dirname(file))\n } finally {\n if (fd !== undefined) fs.closeSync(fd)\n fs.rmSync(temporary, { force: true })\n }\n },\n\n discard(jobId, checkpointId) {\n // `pathFor` validates BOTH segments against `SAFE_PATH_SEGMENT` before they are joined,\n // so a crafted id is refused by name rather than reaching `rmSync` as a traversal.\n fs.rmSync(pathFor(jobId, checkpointId), { force: true })\n },\n\n read(jobId, checkpointId) {\n const read = readEnvelopeOn(fs, options.root, jobId, checkpointId)\n return read.found ? { found: true, payload: read.envelope.payload } : read\n },\n }\n}\n","// Refusals the store owns are declared here; those the port owns are re-exported, never redeclared.\n\nimport { JOB_CHECKPOINT_SCHEMA_VERSION } from '@vostride/agent-qa-schema'\n\n// Both are the second case the rule above describes: the PORT declares them, this module\n// re-exports them. `QuarantinedJobRequeueError` is a condition of the requeue CONTRACT — every\n// store that implements `requeueTerminal` owes the same refusal — so a second class declared here\n// would let two stores disagree about what an operator is being told.\nexport { QuarantinedJobRequeueError, StaleJobStoreEpochError } from '@vostride/agent-qa-agent'\n\n// No migration: the message names the agent job queue's state as the thing to clear.\nexport class JobStoreSchemaVersionError extends Error {\n override readonly name = 'JobStoreSchemaVersionError'\n\n constructor(\n readonly path: string,\n readonly expectedVersion: number,\n readonly observedVersion: number,\n ) {\n super(\n `The agent job store at ${path} is stamped at schema version ${observedVersion}, but ` +\n `this build reads version ${expectedVersion}. There is no migration machinery by ` +\n 'design — clear agent job queue state (delete the agent job database and its ' +\n 'checkpoint directory) and re-enqueue.',\n )\n }\n}\n\n/** A job id that no row answers to. */\nexport class UnknownJobRowError extends Error {\n override readonly name = 'UnknownJobRowError'\n\n constructor(readonly jobId: string) {\n super(`No agent job row with id ${jobId}`)\n }\n}\n\n// Validated before any join, because an id validated after joining has already escaped.\nexport class InvalidJobCheckpointIdError extends Error {\n override readonly name = 'InvalidJobCheckpointIdError'\n\n constructor(\n readonly field: 'jobId' | 'checkpointId',\n readonly value: string,\n ) {\n super(\n `Unusable ${field} for a checkpoint path: ${JSON.stringify(value)}. A checkpoint id ` +\n 'becomes a path segment, so it is validated before the path is built rather than ' +\n 'after.',\n )\n }\n}\n\n/** A checkpoint file written at a layout version this build does not read. */\nexport class JobCheckpointSchemaVersionError extends Error {\n override readonly name = 'JobCheckpointSchemaVersionError'\n\n constructor(\n readonly path: string,\n readonly observedVersion: unknown,\n ) {\n super(\n `Agent job checkpoint ${path} was written at schema version ${String(observedVersion)}, ` +\n `but this build reads version ${JOB_CHECKPOINT_SCHEMA_VERSION}. There is no migration ` +\n 'machinery by design — clear agent job queue state and re-enqueue.',\n )\n }\n}\n","// Checks the file exists, then opens it read-only, so a status query never creates a queue.\n\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { DatabaseSync } from 'node:sqlite'\n\nimport { canonicalJson, CurationSnapshotSchema, guardRunNotification, isJobKind, sha256hex } from '@vostride/agent-qa-schema'\nimport type { JobConclusionKind, JobStatus, RunNotification } from '@vostride/agent-qa-schema'\nimport type {\n ChainJobIds,\n JobIdSource,\n PostProcessingChainState,\n PostProcessingJobRow,\n PostProcessingReaderPort,\n} from '@vostride/agent-qa-agent'\n\nimport {\n AGENT_JOB_STORE_BUSY_TIMEOUT_MS,\n AGENT_JOB_STORE_DB_FILE,\n AGENT_JOB_STORE_USER_VERSION,\n QUARANTINED_UNREADABLE_KIND_REASON,\n} from './sqlite-job-store.js'\nimport { JobStoreSchemaVersionError } from './store-errors.js'\nimport { readJobCheckpointEnvelope } from './job-checkpoint-store.js'\n\n/** Invalid authoritative checkpoint facts cannot be presented as an empty curation. */\nexport class CurationSnapshotReadError extends Error {\n override readonly name = 'CurationSnapshotReadError'\n\n constructor() {\n // No persisted prose or payload values in a read failure: they have not crossed MaskFn.\n super('The recorded curation checkpoint is invalid; its snapshot cannot be read.')\n }\n}\n\nfunction recordOf(value: unknown): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new CurationSnapshotReadError()\n }\n return value as Record<string, unknown>\n}\n\nfunction readCurationSnapshot(\n db: DatabaseSync,\n root: string,\n ids: ChainJobIds,\n runId: string,\n): PostProcessingChainState['curationSnapshot'] {\n const checkpointId = 'bundle-committed'\n // Match the store's latest fenced row. Files alone cannot resurrect a requeued checkpoint.\n const row = db.prepare(`SELECT payload_json, payload_digest, attempt FROM job_checkpoints\n WHERE job_id = ? AND checkpoint_id = ? ORDER BY attempt DESC LIMIT 1`)\n .get(String(ids.curateMemory), checkpointId)\n if (row === undefined) return undefined\n try {\n const authoritative: unknown = JSON.parse(String(row.payload_json))\n if (sha256hex(canonicalJson(authoritative)) !== row.payload_digest) {\n throw new CurationSnapshotReadError()\n }\n let payload = authoritative\n try {\n const cached = readJobCheckpointEnvelope({ root }, String(ids.curateMemory), checkpointId)\n if (cached.found && sha256hex(canonicalJson(cached.envelope.payload)) === row.payload_digest) {\n payload = cached.envelope.payload\n }\n } catch {\n // Like sqlite-job-store.readCheckpoint: a damaged cache cannot overrule the fenced row.\n }\n const checkpoint = recordOf(payload)\n if (checkpoint.jobId !== ids.curateMemory || checkpoint.checkpointId !== checkpointId\n || checkpoint.attempt !== Number(row.attempt) || !Number.isInteger(checkpoint.attempt)\n || Number(checkpoint.attempt) < 1 || typeof checkpoint.recordedAt !== 'string'\n || checkpoint.recordedAt.length === 0) throw new CurationSnapshotReadError()\n const value = recordOf(checkpoint.value)\n if (value.curationSnapshot === undefined) return undefined\n const job = db.prepare('SELECT kind, idempotency_key, payload, attempts FROM jobs WHERE id = ?')\n .get(String(ids.curateMemory))\n if (job === undefined || job.kind !== 'curate-memory'\n || job.idempotency_key !== `${ids.analyzeRun}->curate-memory`\n || Number(job.attempts) < Number(checkpoint.attempt)\n || recordOf(JSON.parse(String(job.payload))).runId !== runId\n || value.runId !== runId) throw new CurationSnapshotReadError()\n return CurationSnapshotSchema.parse(value.curationSnapshot)\n } catch {\n throw new CurationSnapshotReadError()\n }\n}\n\nexport interface CreatePostProcessingReaderOptions {\n /** The project's runtime root, i.e. `<configDir>/.agent-qa`. Absolute. */\n readonly agentQaRoot: string\n /**\n * The id source THIS host's queue enqueues through.\n *\n * REQUIRED rather than defaulted to the production digest source, and the requirement is the\n * guarantee: the composition hands the reader the very source it built the queue with, so the\n * ids projected and the ids enqueued cannot be two different derivations. A reader that\n * defaulted would silently address other rows in any composition that configured its own\n * source, and would report `pending` about a chain that had already finished.\n */\n readonly idSource: JobIdSource\n}\n\nfunction toNumber(value: unknown): number {\n return typeof value === 'bigint' ? Number(value) : Number(value)\n}\n\nfunction toRow(row: Record<string, unknown> | undefined): PostProcessingJobRow | undefined {\n if (row === undefined) return undefined\n // The store has no conclusion column; only a complete recorded quarantine landing supports one.\n const conclusionKind: JobConclusionKind | undefined =\n !isJobKind(String(row.kind))\n && row.status === 'failed'\n && row.last_failure_kind === 'permanent'\n && row.last_failure_reason === QUARANTINED_UNREADABLE_KIND_REASON\n ? 'unreadable_kind'\n : undefined\n return {\n status: String(row.status) as JobStatus,\n claimed: row.claimed_at !== null,\n attempts: toNumber(row.attempts),\n createdAt: String(row.created_at),\n updatedAt: String(row.updated_at),\n ...(row.claimed_at === null ? {} : { claimedAt: String(row.claimed_at) }),\n ...(row.started_at === null ? {} : { startedAt: String(row.started_at) }),\n ...(conclusionKind === undefined ? {} : { conclusionKind }),\n ...(row.last_failure_kind === null ? {} : { lastFailureKind: String(row.last_failure_kind) }),\n ...(row.last_failure_reason === null ? {} : { lastFailureReason: String(row.last_failure_reason) }),\n }\n}\n\n/**\n * Bind the `runs.postprocessing` port over this project's queue database.\n *\n * The port's own contract forbids materializing anything, and this implementation honours it\n * structurally rather than carefully: `existsSync` short-circuits before a handle is\n * constructed, and the handle that would be constructed is read-only, which refuses to create\n * a file even if the check were removed.\n */\nexport function createPostProcessingReader(\n options: CreatePostProcessingReaderOptions,\n): PostProcessingReaderPort {\n const path = join(options.agentQaRoot, AGENT_JOB_STORE_DB_FILE)\n\n return {\n idSource: options.idSource,\n\n async readChain(\n ids: ChainJobIds,\n runId: string,\n ): Promise<PostProcessingChainState | undefined> {\n // No database means no chain: `undefined`, not an empty state, and nothing is created.\n if (!existsSync(path)) return undefined\n\n const db = new DatabaseSync(path, {\n readOnly: true,\n timeout: AGENT_JOB_STORE_BUSY_TIMEOUT_MS,\n })\n try {\n // Another build's database is refused; a never-stamped file reads 0 and is readable, empty.\n const stamped = toNumber(db.prepare('PRAGMA user_version').get()?.user_version)\n if (stamped !== 0 && stamped !== AGENT_JOB_STORE_USER_VERSION) {\n throw new JobStoreSchemaVersionError(path, AGENT_JOB_STORE_USER_VERSION, stamped)\n }\n\n const selectJob = db.prepare(`\n SELECT kind, status, attempts, created_at, claimed_at, started_at, updated_at,\n last_failure_kind, last_failure_reason\n FROM jobs WHERE id = ?\n `)\n const notificationRow = db\n .prepare('SELECT payload FROM notifications WHERE run_id = ?')\n .get(runId) as Record<string, unknown> | undefined\n\n const analyzeRun = toRow(\n selectJob.get(String(ids.analyzeRun)) as Record<string, unknown> | undefined,\n )\n const curateMemory = toRow(\n selectJob.get(String(ids.curateMemory)) as Record<string, unknown> | undefined,\n )\n // Parsed through the schema guard on the way out, like `listNotifications`: the column\n // is bytes another process wrote, and a record that lost a stage must not travel as a\n // `RunNotification` to a surface that renders it.\n const notification: RunNotification | undefined =\n notificationRow === undefined\n ? undefined\n : guardRunNotification(JSON.parse(String(notificationRow.payload)) as unknown)\n const curationSnapshot = readCurationSnapshot(db, options.agentQaRoot, ids, runId)\n\n // Absent members are OMITTED rather than set undefined, so the state a projection reads\n // says the same thing whether it was built here or by a test's literal.\n return {\n ...(analyzeRun === undefined ? {} : { analyzeRun }),\n ...(curateMemory === undefined ? {} : { curateMemory }),\n ...(notification === undefined ? {} : { notification }),\n ...(curationSnapshot === undefined ? {} : { curationSnapshot }),\n }\n } finally {\n db.close()\n }\n },\n }\n}\n","// Each compound verb is one `BEGIN IMMEDIATE`; rollback first checks `isTransaction`.\n\nimport { mkdirSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { DatabaseSync } from 'node:sqlite'\n\nimport {\n JobCancellationNotRequestedError,\n MissingIdempotencyKeyError,\n QuarantinedJobRequeueError,\n StaleJobStoreEpochError,\n} from '@vostride/agent-qa-agent'\nimport type {\n ChainTerminalRecord,\n ClaimNextOptions,\n ClockPort,\n JobCancelOutcome,\n JobCheckpointRecord,\n JobCheckpointReadOutcome,\n JobClaimOutcome,\n JobCompleteOutcome,\n JobEnqueueOutcome,\n JobFailureDisposition,\n JobInsert,\n JobRequeueOutcome,\n JobStoreDump,\n JobStoreDumpRow,\n JobStoreFence,\n JobStorePort,\n} from '@vostride/agent-qa-agent'\nimport {\n canonicalJson,\n guardRunNotification,\n isJobKind,\n jobSchema,\n sha256hex,\n} from '@vostride/agent-qa-schema'\nimport type {\n Job,\n JobConclusionKind,\n JobId,\n JobStatus,\n RunNotification,\n} from '@vostride/agent-qa-schema'\n\nimport type { JobCheckpointStore } from './job-checkpoint-store.js'\nimport { canonicalLogicalDump, createLogicalDump, selectOrderedRows } from './logical-dump.js'\nimport type { LogicalDump } from './logical-dump.js'\nimport { JobStoreSchemaVersionError, UnknownJobRowError } from './store-errors.js'\n\n// Stamped at creation and checked on every open; a mismatch hard-fails, never migrates.\nexport const AGENT_JOB_STORE_USER_VERSION = 2\n\n// A writer waiting on the lock retries for this long instead of failing at once.\nexport const AGENT_JOB_STORE_BUSY_TIMEOUT_MS = 2000\n\n// The store's file name under the agent-qa root.\nexport const AGENT_JOB_STORE_DB_FILE = 'agent-jobs.db'\n\nexport interface CreateSqliteJobStoreOptions {\n /** Absolute path to the database file, typically `<root>/agent-jobs.db`. */\n readonly path: string\n readonly clock: ClockPort\n readonly checkpoints: JobCheckpointStore\n readonly timeoutMs?: number\n readonly hooks?: SqliteJobStoreHooks\n}\n\n/** Test-only observation points around cross-media publication. Production omits them. */\nexport interface SqliteJobStoreHooks {\n /** Runs after the fenced row commits and immediately before the checkpoint file is replaced. */\n readonly beforeCheckpointFilePublish?: () => void | Promise<void>\n}\n\n/** One chain-terminal notification row, with its payload guarded on the way out. */\nexport interface JobStoreNotification {\n readonly runId: string\n readonly payload: RunNotification\n readonly createdAt: string\n}\n\nexport interface SqliteJobStore extends JobStorePort {\n close(): void\n\n // On the implementation, not the port: only surfaces read notifications; the payload is guarded.\n listNotifications(): Promise<readonly JobStoreNotification[]>\n\n // The full-state comparison basis, including checkpoint files and tables the port cannot name.\n logicalDump(): Promise<LogicalDump>\n\n /** The same dump as one comparable string. Byte equality here is state equality. */\n dumpLogicalState(): Promise<string>\n}\n\nconst SCHEMA_STATEMENTS = [\n `CREATE TABLE IF NOT EXISTS jobs (\n id TEXT PRIMARY KEY,\n kind TEXT NOT NULL,\n idempotency_key TEXT NOT NULL,\n status TEXT NOT NULL,\n summary TEXT NOT NULL,\n payload TEXT NOT NULL,\n attempts INTEGER NOT NULL,\n claimed_at TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n -- The disposition the engine DECIDED, recorded so a failed job says why it failed.\n -- Nullable because most rows never fail; written only by recordFailure.\n last_failure_kind TEXT,\n last_failure_reason TEXT,\n -- A stop request, not a lifecycle stage. New columns go last, or positional reads would move.\n cancel_requested_at TEXT,\n -- When the row was first claimed; survives lease release, cleared only by operator requeue.\n started_at TEXT,\n -- A retrying row is not claimable before this instant.\n not_before TEXT\n )`,\n // The dedupe is this unique index, so no caller in any process can enqueue the same work twice.\n `CREATE UNIQUE INDEX IF NOT EXISTS jobs_kind_idempotency_key\n ON jobs (kind, idempotency_key)`,\n `CREATE TABLE IF NOT EXISTS job_store_fence (\n id INTEGER PRIMARY KEY CHECK (id = 1),\n epoch INTEGER NOT NULL\n )`,\n // The row is the authoritative checkpoint. The file remains a durable projection for\n // cross-process observability, but recovery accepts its bytes only when their digest agrees\n // with the latest fenced row for this job/checkpoint. Attempt stays in the key so retries\n // preserve their recorded history while a same-attempt takeover replaces only that attempt.\n `CREATE TABLE IF NOT EXISTS job_checkpoints (\n job_id TEXT NOT NULL,\n checkpoint_id TEXT NOT NULL,\n attempt INTEGER NOT NULL,\n payload_json TEXT NOT NULL,\n payload_digest TEXT NOT NULL,\n epoch INTEGER NOT NULL,\n PRIMARY KEY (job_id, attempt, checkpoint_id)\n )`,\n // `created_at` comes from the injected clock; a SQL default would leak host time into the dump.\n `CREATE TABLE IF NOT EXISTS notifications (\n run_id TEXT NOT NULL,\n payload TEXT NOT NULL,\n created_at TEXT NOT NULL\n )`,\n // One notification per run, ever: a crash-replayed terminal hits this unique index.\n `CREATE UNIQUE INDEX IF NOT EXISTS notifications_run_id\n ON notifications (run_id)`,\n] as const\n\n/** The statuses a job never leaves. A cancel arriving at one of them moves nothing. */\nconst TERMINAL_JOB_STATUSES: readonly JobStatus[] = ['done', 'failed', 'cancelled']\n\n// Typed as `JobConclusionKind`, so removing the member from the contract fails to compile here.\nconst UNREADABLE_KIND_CONCLUSION: JobConclusionKind = 'unreadable_kind'\n\n// Fixed text: the unreadable kind is untrusted bytes, and this reason reaches operator terminals.\nexport const QUARANTINED_UNREADABLE_KIND_REASON =\n 'agent job quarantined at claim: this build does not read the kind recorded for this row, so '\n + 'the row was landed permanently without being parsed. The original kind, id and payload are '\n + 'preserved in the row for inspection.'\n\n/**\n * How many rows one claim will pass over before it gives up.\n *\n * The quarantine loop below is already monotone — every iteration either returns a claim or moves\n * a row out of the claimable set — so this bound is unreachable by construction. It is here for\n * the same reason `AGENT_JOBS_PUMP_BOUND` is: an unbounded loop inside a write transaction is not\n * something to leave resting on an argument, and a store that somehow stopped shrinking its own\n * queue must say so rather than spin holding the write lock.\n */\nconst QUARANTINE_SCAN_BOUND = 1_000\n\n// Asked of the raw column before `rowToJob`, so the quarantine commits with the spent attempt.\nfunction isUnreadableKindRow(row: Record<string, unknown>): boolean {\n return !isJobKind(String(row.kind))\n}\n\n// Derived from the unreadable kind, the permanent landing and the fixed reason; never a column.\nfunction quarantineConclusionOf(row: Record<string, unknown>): JobConclusionKind | undefined {\n if (!isUnreadableKindRow(row)) return undefined\n if (String(row.status) !== 'failed') return undefined\n if (String(row.last_failure_kind) !== 'permanent') return undefined\n if (String(row.last_failure_reason) !== QUARANTINED_UNREADABLE_KIND_REASON) return undefined\n return UNREADABLE_KIND_CONCLUSION\n}\n\n\n/**\n * The run a job's payload column names, if it names one as a non-empty string.\n *\n * `chainTerminalFor`'s predicate verbatim (`engine.ts`), and it has to be verbatim: the key that\n * function derives IS the `notifications.run_id` a terminal writes, because `dedupeKey` is the\n * run id and nothing else. A looser reader here would disown a receipt no requeue is entitled to\n * disown; a stricter one would leave behind a receipt `ON CONFLICT (run_id) DO NOTHING` can never\n * replace. The column is bytes this store's own `enqueue` wrote with `JSON.stringify`, read the\n * same way `dumpRow` reads it.\n */\nfunction runIdOfPayloadColumn(payload: unknown): string | undefined {\n const record = JSON.parse(String(payload)) as unknown\n if (typeof record !== 'object' || record === null || Array.isArray(record)) return undefined\n const runId = (record as { runId?: unknown }).runId\n return typeof runId === 'string' && runId !== '' ? runId : undefined\n}\n\nfunction toNumber(value: unknown): number {\n return typeof value === 'bigint' ? Number(value) : Number(value)\n}\n\nexport function createSqliteJobStore(options: CreateSqliteJobStoreOptions): SqliteJobStore {\n const { clock, checkpoints, hooks } = options\n\n mkdirSync(dirname(options.path), { recursive: true })\n const db = new DatabaseSync(options.path, {\n timeout: options.timeoutMs ?? AGENT_JOB_STORE_BUSY_TIMEOUT_MS,\n })\n db.exec('PRAGMA journal_mode=WAL')\n\n // The version is read BEFORE a single schema statement runs, so a database this build\n // cannot read is not touched on the way to being refused. A hard fail that had already\n // created a table, or re-stamped the header, would be a migration nobody wrote.\n const stampedVersion = toNumber(db.prepare('PRAGMA user_version').get()?.user_version)\n if (stampedVersion !== 0 && stampedVersion !== AGENT_JOB_STORE_USER_VERSION) {\n db.close()\n throw new JobStoreSchemaVersionError(\n options.path,\n AGENT_JOB_STORE_USER_VERSION,\n stampedVersion,\n )\n }\n for (const statement of SCHEMA_STATEMENTS) db.exec(statement)\n if (stampedVersion === 0) {\n db.exec(`PRAGMA user_version=${AGENT_JOB_STORE_USER_VERSION}`)\n }\n\n const insertJob = db.prepare(\n `INSERT INTO jobs\n (id, kind, idempotency_key, status, summary, payload, attempts, claimed_at,\n created_at, updated_at, last_failure_kind, last_failure_reason,\n cancel_requested_at, started_at, not_before)\n VALUES (?, ?, ?, 'queued', ?, ?, 0, NULL, ?, ?, NULL, NULL, NULL, NULL, NULL)\n ON CONFLICT (kind, idempotency_key) DO NOTHING`,\n )\n const selectByKey = db.prepare('SELECT * FROM jobs WHERE kind = ? AND idempotency_key = ?')\n const selectById = db.prepare('SELECT * FROM jobs WHERE id = ?')\n const selectClaimable = db.prepare(\n `SELECT * FROM jobs\n WHERE status = 'queued' AND claimed_at IS NULL\n AND (not_before IS NULL OR not_before <= ?)\n ORDER BY created_at ASC, id ASC\n LIMIT 1`,\n )\n // Cached per placeholder arity, bound parameters only; an exclusion only changes which row.\n const selectClaimableExcluding = new Map<number, ReturnType<typeof db.prepare>>()\n function claimableStatementFor(excludedCount: number): ReturnType<typeof db.prepare> {\n const cached = selectClaimableExcluding.get(excludedCount)\n if (cached !== undefined) return cached\n const placeholders = Array.from({ length: excludedCount }, () => '?').join(', ')\n const prepared = db.prepare(\n `SELECT * FROM jobs\n WHERE status = 'queued' AND claimed_at IS NULL\n AND (not_before IS NULL OR not_before <= ?) AND kind NOT IN (${placeholders})\n ORDER BY created_at ASC, id ASC\n LIMIT 1`,\n )\n selectClaimableExcluding.set(excludedCount, prepared)\n return prepared\n }\n // COALESCE because the first claim IS the start: a later claim after a retryable failure is a\n // second attempt at work that already began, and overwriting the start would time only it.\n const markClaimed = db.prepare(\n `UPDATE jobs\n SET claimed_at = ?, started_at = COALESCE(started_at, ?), attempts = attempts + 1,\n updated_at = ?\n WHERE id = ?`,\n )\n const markDone = db.prepare(\n \"UPDATE jobs SET status = 'done', claimed_at = NULL, updated_at = ? WHERE id = ?\",\n )\n // Terminal and released with `kind`, `id` and `payload` kept; the spent attempt commits too.\n const markQuarantined = db.prepare(\n `UPDATE jobs\n SET status = 'failed', claimed_at = NULL, last_failure_kind = 'permanent',\n last_failure_reason = ?, updated_at = ?\n WHERE id = ?`,\n )\n const touchJob = db.prepare('UPDATE jobs SET updated_at = ? WHERE id = ?')\n // Two statements for two outcomes; whether a report becomes a retry is the engine's call.\n const markRetryable = db.prepare(\n `UPDATE jobs\n SET claimed_at = NULL, last_failure_kind = 'retry', last_failure_reason = ?,\n updated_at = ?, not_before = ?\n WHERE id = ?`,\n )\n // An aborted attempt did not fail, so its attempt is refunded and its claim released. The last\n // failure, not-before and started_at are kept; a first attempt's start is the refunded claim's.\n const markInterrupted = db.prepare(\n `UPDATE jobs\n SET claimed_at = NULL, attempts = MAX(attempts - 1, 0), updated_at = ?\n WHERE id = ?`,\n )\n const markFailed = db.prepare(\n `UPDATE jobs\n SET status = 'failed', claimed_at = NULL, last_failure_kind = 'permanent',\n last_failure_reason = ?, updated_at = ?\n WHERE id = ?`,\n )\n // Two transitions: stop an unclaimed job, or record the request and leave the row claimable.\n const markCancelledNow = db.prepare(\n `UPDATE jobs\n SET status = 'cancelled', claimed_at = NULL, cancel_requested_at = ?, updated_at = ?\n WHERE id = ?`,\n )\n const markCancelRequested = db.prepare(\n 'UPDATE jobs SET cancel_requested_at = ?, updated_at = ? WHERE id = ?',\n )\n const markCancelHonoured = db.prepare(\n `UPDATE jobs\n SET status = 'cancelled', claimed_at = NULL, updated_at = ?\n WHERE id = ?`,\n )\n // Clears every column recording how the row finished, start included, so no verdict carries over.\n const markRequeued = db.prepare(\n `UPDATE jobs\n SET status = 'queued', claimed_at = NULL, started_at = NULL, attempts = 0,\n last_failure_kind = NULL, last_failure_reason = NULL, cancel_requested_at = NULL,\n not_before = NULL, updated_at = ?\n WHERE id = ?`,\n )\n // DISTINCT because the checkpoint key carries the attempt: one checkpoint id published\n // across two attempts is two rows and one file, and the file is discarded once.\n const selectCheckpointIdsForJob = db.prepare(\n 'SELECT DISTINCT checkpoint_id FROM job_checkpoints WHERE job_id = ?',\n )\n const deleteCheckpointsForJob = db.prepare('DELETE FROM job_checkpoints WHERE job_id = ?')\n const selectFence = db.prepare('SELECT epoch FROM job_store_fence WHERE id = 1')\n const upsertFence = db.prepare(\n `INSERT INTO job_store_fence (id, epoch) VALUES (1, ?)\n ON CONFLICT (id) DO UPDATE SET epoch = excluded.epoch`,\n )\n const upsertCheckpoint = db.prepare(\n `INSERT INTO job_checkpoints\n (job_id, checkpoint_id, attempt, payload_json, payload_digest, epoch)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT (job_id, attempt, checkpoint_id) DO UPDATE SET\n payload_json = excluded.payload_json,\n payload_digest = excluded.payload_digest,\n epoch = excluded.epoch`,\n )\n const selectLatestCheckpoint = db.prepare(\n `SELECT payload_json, payload_digest, attempt, epoch\n FROM job_checkpoints\n WHERE job_id = ? AND checkpoint_id = ?\n ORDER BY attempt DESC\n LIMIT 1`,\n )\n // `ON CONFLICT DO NOTHING`, because a read-then-write leaves a window for a second notification.\n const insertNotification = db.prepare(\n `INSERT INTO notifications (run_id, payload, created_at) VALUES (?, ?, ?)\n ON CONFLICT (run_id) DO NOTHING`,\n )\n const selectJobStatus = db.prepare('SELECT status FROM jobs WHERE id = ?')\n const selectNotifications = db.prepare(\n 'SELECT run_id, payload, created_at FROM notifications ORDER BY run_id ASC',\n )\n const deleteNotificationForRun = db.prepare('DELETE FROM notifications WHERE run_id = ?')\n\n function inTransaction<T>(body: () => T): T {\n db.exec('BEGIN IMMEDIATE')\n try {\n const result = body()\n db.exec('COMMIT')\n return result\n } catch (error) {\n if (db.isTransaction) db.exec('ROLLBACK')\n throw error\n }\n }\n\n /** No epoch adopted yet reads as epoch 0, so an un-adopted store refuses every drain. */\n function currentEpoch(): number {\n const row = selectFence.get()\n return row === undefined ? 0 : toNumber(row.epoch)\n }\n\n // Inside each drain verb's transaction, or another writer can adopt a newer epoch in between.\n function requireFence(fence: JobStoreFence): void {\n const observed = currentEpoch()\n if (observed !== fence.epoch) {\n throw new StaleJobStoreEpochError(fence.epoch, observed)\n }\n }\n\n // Parsed through the zod contract, because the payload is opaque text another process wrote.\n function rowToJob(row: Record<string, unknown> | undefined): Job {\n if (row === undefined) {\n throw new UnknownJobRowError('<missing>')\n }\n return jobSchema.parse({\n id: String(row.id),\n kind: String(row.kind),\n status: String(row.status),\n summary: String(row.summary),\n attempts: toNumber(row.attempts),\n createdAt: String(row.created_at),\n updatedAt: String(row.updated_at),\n })\n }\n\n function requireRow(jobId: string): Record<string, unknown> {\n const row = selectById.get(jobId)\n if (row === undefined) {\n throw new UnknownJobRowError(jobId)\n }\n return row\n }\n\n function insertOrGet(request: JobInsert, now: string): JobEnqueueOutcome {\n // Checked in the store: an empty key passes the unique index but collapses a kind to one slot.\n if (request.idempotencyKey.trim() === '') {\n throw new MissingIdempotencyKeyError(request.kind)\n }\n const changes = insertJob.run(\n String(request.id),\n request.kind,\n request.idempotencyKey,\n request.summary,\n JSON.stringify(request.payload ?? null),\n now,\n now,\n ).changes\n return {\n job: rowToJob(selectByKey.get(request.kind, request.idempotencyKey)),\n deduped: toNumber(changes) === 0,\n }\n }\n\n // Inside both terminal transactions, so no crash lands between the last job and the notify.\n function recordChainTerminal(chainTerminal: ChainTerminalRecord, now: string): void {\n let headExists = false\n for (const candidate of chainTerminal.candidateJobIds) {\n const row = selectJobStatus.get(String(candidate))\n if (row === undefined) continue\n headExists ||= String(candidate) === String(chainTerminal.candidateJobIds[0])\n if (!TERMINAL_JOB_STATUSES.includes(String(row.status) as JobStatus)) return\n }\n if (!headExists) return\n insertNotification.run(chainTerminal.dedupeKey, chainTerminal.payloadJson, now)\n }\n\n function dumpRow(row: Record<string, unknown>): JobStoreDumpRow {\n const conclusionKind = quarantineConclusionOf(row)\n return {\n id: String(row.id),\n kind: String(row.kind),\n idempotencyKey: String(row.idempotency_key),\n status: String(row.status),\n summary: String(row.summary),\n payload: JSON.parse(String(row.payload)) as unknown,\n attempts: toNumber(row.attempts),\n claimed: row.claimed_at !== null,\n cancelRequested: row.cancel_requested_at !== null,\n // Omitted rather than `undefined`, so a serialized row publishes no empty conclusion key.\n ...(conclusionKind === undefined ? {} : { conclusionKind }),\n createdAt: String(row.created_at),\n updatedAt: String(row.updated_at),\n }\n }\n\n return {\n close() {\n db.close()\n },\n\n async adoptEpoch(epoch: number): Promise<JobStoreFence> {\n return inTransaction(() => {\n const observed = currentEpoch()\n // Authority only ever moves forward. A store that accepted a lower epoch would let\n // a writer that already lost its lease re-arm itself simply by asking again.\n if (epoch < observed) {\n throw new StaleJobStoreEpochError(epoch, observed)\n }\n upsertFence.run(epoch)\n return { epoch }\n })\n },\n\n async enqueue(request: JobInsert): Promise<JobEnqueueOutcome> {\n const now = clock.now()\n return inTransaction(() => insertOrGet(request, now))\n },\n\n async claimNext(fence: JobStoreFence, options?: ClaimNextOptions): Promise<JobClaimOutcome> {\n const now = clock.now()\n // Excluded in the SELECT, because claim-and-undo would spend an attempt or starve the queue.\n const excludeKinds = options?.excludeKinds ?? []\n return inTransaction(() => {\n // FIRST, and before the loop rather than inside it: a quarantine is a WRITE, so a caller\n // whose epoch the store does not recognise must be refused having moved nothing at all.\n requireFence(fence)\n for (let scanned = 0; scanned <= QUARANTINE_SCAN_BOUND; scanned += 1) {\n const row =\n excludeKinds.length === 0\n ? selectClaimable.get(now)\n : claimableStatementFor(excludeKinds.length).get(now, ...excludeKinds)\n if (row === undefined) {\n return { claimed: false }\n }\n // Counted at the claim, because a job that kills its host records no failures.\n markClaimed.run(now, now, now, String(row.id))\n const claimed = requireRow(String(row.id))\n // Asked of the raw row before `rowToJob`, so the landing commits with the spent attempt.\n if (isUnreadableKindRow(claimed)) {\n markQuarantined.run(QUARANTINED_UNREADABLE_KIND_REASON, now, String(row.id))\n continue\n }\n // The payload travels with the claim, not on the job row's DTO: it is the opaque\n // input this kind's handler reads, and the handler is the only thing that can.\n return {\n claimed: true,\n job: rowToJob(claimed),\n payload: JSON.parse(String(claimed.payload)) as unknown,\n }\n }\n // Unreachable by construction — every iteration above either returns or moves a row to a\n // terminal status, which removes it from the claimable set. Recorded rather than trusted,\n // and a throw rather than a silent `{claimed: false}`: reaching it means the claimable\n // predicate stopped shrinking, and reporting an empty queue would hide that forever.\n throw new Error(\n `agent job claim scanned ${QUARANTINE_SCAN_BOUND} rows without reaching a claimable or `\n + 'exhausted queue; the claimable set is not shrinking, so no row was claimed and the '\n + 'transaction is rolled back rather than reporting an empty queue',\n )\n })\n },\n\n async completeAndChain(\n jobId: JobId,\n next: readonly JobInsert[],\n fence: JobStoreFence,\n chainTerminal?: ChainTerminalRecord,\n ): Promise<JobCompleteOutcome> {\n const now = clock.now()\n return inTransaction(() => {\n requireFence(fence)\n requireRow(String(jobId))\n markDone.run(now, String(jobId))\n // Same transaction as the completion: two transactions would leave a window where a\n // crash loses the chain while the predecessor already reads as done, and nothing\n // downstream would ever notice the successor never existed.\n const chained = next.map((request) => insertOrGet(request, now))\n if (chainTerminal !== undefined) recordChainTerminal(chainTerminal, now)\n return { job: rowToJob(requireRow(String(jobId))), chained }\n })\n },\n\n async failAndChain(\n jobId: JobId,\n disposition: Extract<JobFailureDisposition, { readonly kind: 'permanent' }>,\n next: readonly JobInsert[],\n fence: JobStoreFence,\n chainTerminal?: ChainTerminalRecord,\n ) {\n const now = clock.now()\n return inTransaction(() => {\n requireFence(fence)\n requireRow(String(jobId))\n markFailed.run(disposition.reason, now, String(jobId))\n // Parent transition and every insert share this transaction. If any insert raises,\n // inTransaction rolls the parent and all earlier successors back before surfacing it.\n const chained = next.map((request) => insertOrGet(request, now))\n // Notify on the failure terminal too: a chain that gave up is when a user most needs it.\n if (chainTerminal !== undefined) recordChainTerminal(chainTerminal, now)\n return { job: rowToJob(requireRow(String(jobId))), chained }\n })\n },\n\n async recordFailure(\n jobId: JobId,\n disposition: JobFailureDisposition,\n fence: JobStoreFence,\n ): Promise<void> {\n const now = clock.now()\n inTransaction(() => {\n requireFence(fence)\n requireRow(String(jobId))\n // Attempts are spent at the claim; incrementing here would charge a reported failure twice.\n if (disposition.kind === 'retry') {\n // Lexical comparison in the claim holds only because both sides are toISOString().\n const notBefore =\n disposition.retryAfterMs === undefined\n ? null\n : new Date(Date.parse(now) + disposition.retryAfterMs).toISOString()\n markRetryable.run(disposition.reason, now, notBefore, String(jobId))\n } else {\n markFailed.run(disposition.reason, now, String(jobId))\n }\n })\n },\n\n async releaseInterrupted(jobId: JobId, fence: JobStoreFence): Promise<void> {\n const now = clock.now()\n inTransaction(() => {\n requireFence(fence)\n requireRow(String(jobId))\n markInterrupted.run(now, String(jobId))\n })\n },\n\n async requestCancel(jobId: JobId, fence: JobStoreFence): Promise<JobCancelOutcome> {\n const now = clock.now()\n return inTransaction(() => {\n requireFence(fence)\n const row = requireRow(String(jobId))\n const status = String(row.status) as JobStatus\n // Read and written inside ONE transaction: which of the three things a cancel means\n // depends on whether the row is claimed at this instant, and deciding that from a\n // read taken outside the transaction would let a claim land in between.\n if (TERMINAL_JOB_STATUSES.includes(status)) {\n return { outcome: 'already-terminal', status }\n }\n if (row.claimed_at !== null) {\n // In flight. The request is recorded and the row stays exactly as it was, so the\n // step the handler is part way through finishes and is checkpointed; the driver\n // stops it at the next boundary.\n markCancelRequested.run(now, now, String(jobId))\n return { outcome: 'cancel-requested' }\n }\n // Nobody is running it, so there is no step to protect and no boundary to wait for.\n // The request is stamped as well as the status, so `cancelled` never appears without\n // the record of the ask that produced it.\n markCancelledNow.run(now, now, String(jobId))\n return { outcome: 'cancelled' }\n })\n },\n\n async recordCancellation(jobId: JobId, fence: JobStoreFence): Promise<void> {\n const now = clock.now()\n inTransaction(() => {\n requireFence(fence)\n const row = requireRow(String(jobId))\n if (row.cancel_requested_at === null) {\n throw new JobCancellationNotRequestedError(jobId)\n }\n markCancelHonoured.run(now, String(jobId))\n })\n },\n\n // Checkpoint rows go with the status, or the real handler resumes on the stand-in's value.\n async requeueTerminal(jobId: JobId, fence: JobStoreFence): Promise<JobRequeueOutcome> {\n const now = clock.now()\n const decided = inTransaction((): JobRequeueOutcome & { readonly discard?: string[] } => {\n requireFence(fence)\n const row = requireRow(String(jobId))\n const status = String(row.status) as JobStatus\n // Refused before the terminal check and any write, or a quarantined row loses its history.\n if (isUnreadableKindRow(row)) {\n throw new QuarantinedJobRequeueError(String(jobId), String(row.kind))\n }\n // Read and written in ONE transaction for the same reason a cancel is: whether this\n // row is a drainer's is a fact about the instant of the write, and a status read\n // taken outside would let a claim land in between and be reset out from under it.\n if (!TERMINAL_JOB_STATUSES.includes(status)) {\n return { outcome: 'not-terminal', status }\n }\n const discard = selectCheckpointIdsForJob\n .all(String(jobId))\n .map((checkpoint) => String(checkpoint.checkpoint_id))\n deleteCheckpointsForJob.run(String(jobId))\n // The THIRD medium, and the one that cannot be corrected later. If this row's last\n // attempt landed the chain terminal, `recordChainTerminal` wrote a `notifications` row\n // keyed on the run this payload names — and `insertNotification` is\n // `ON CONFLICT (run_id) DO NOTHING`, so a receipt left here wins forever: the re-run's\n // real handler chains a successor, which makes `chainTerminalFor` answer `undefined`\n // and offer no replacement at all. Leaving it would publish \"this run's chain\n // terminated with these values\" over an attempt whose every other trace this very\n // transaction is deleting. Inside the transaction with the rows for the same reason\n // they are: the three media are one disowning, or the crash between them is a state\n // recovery has no vocabulary for.\n const requeuedRun = runIdOfPayloadColumn(row.payload)\n if (requeuedRun !== undefined) deleteNotificationForRun.run(requeuedRun)\n markRequeued.run(now, String(jobId))\n return { outcome: 'requeued', discard }\n })\n // Files AFTER the authoritative rows commit — `publishCheckpoint`'s ordering, run\n // backwards, and for the same reason. The row decides what recovery believes, so a\n // crash between the commit and these removals leaves stale FILES behind a row that no\n // longer exists, which `readCheckpoint` already ignores; the opposite order would leave\n // a live row whose file is gone, and that is a real loss.\n if (decided.outcome === 'requeued') {\n for (const checkpointId of decided.discard ?? []) {\n checkpoints.discard(String(jobId), checkpointId)\n }\n return { outcome: 'requeued' }\n }\n return decided\n },\n\n async publishCheckpoint(\n jobId: JobId,\n checkpointId: string,\n payload: JobCheckpointRecord,\n fence: JobStoreFence,\n ): Promise<void> {\n const now = clock.now()\n const payloadJson = canonicalJson(payload)\n const payloadDigest = sha256hex(payloadJson)\n inTransaction(() => {\n requireFence(fence)\n requireRow(String(jobId))\n touchJob.run(now, String(jobId))\n // This INSERT belongs to the SAME transaction as both requireFence and the job touch.\n // Once it commits, this row decides what recovery believes; a later file writer cannot\n // change checkpoint authorship without first winning another fenced transaction.\n upsertCheckpoint.run(\n String(jobId),\n checkpointId,\n payload.attempt,\n payloadJson,\n payloadDigest,\n fence.epoch,\n )\n })\n // File AFTER the authoritative row commits: it remains the fsync'd cross-process\n // projection, but the read path digest-checks it against the row before trusting it.\n // A takeover here may let the stale host replace the file; it cannot replace the row.\n if (hooks?.beforeCheckpointFilePublish !== undefined) {\n await hooks.beforeCheckpointFilePublish()\n }\n checkpoints.publish(String(jobId), checkpointId, payload)\n },\n\n async readCheckpoint(\n jobId: JobId,\n checkpointId: string,\n ): Promise<JobCheckpointReadOutcome> {\n const row = selectLatestCheckpoint.get(String(jobId), checkpointId)\n if (row === undefined) return { found: false }\n\n const authoritative = {\n found: true as const,\n payload: JSON.parse(String(row.payload_json)) as unknown,\n }\n try {\n const projection = checkpoints.read(String(jobId), checkpointId)\n if (!projection.found) return authoritative\n const projectionDigest = sha256hex(canonicalJson(projection.payload))\n return projectionDigest === String(row.payload_digest) ? projection : authoritative\n } catch {\n // The file is a cache now. Missing, malformed, unreadable, or otherwise untrustworthy\n // projection bytes cannot block recovery from the fenced SQLite record.\n return authoritative\n }\n },\n\n async dumpState(): Promise<JobStoreDump> {\n return {\n schemaVersion: AGENT_JOB_STORE_USER_VERSION,\n epoch: currentEpoch(),\n // The same ordered read the logical dump uses, so the typed projection and the\n // equality instrument cannot disagree about which rows exist or in what order.\n jobs: selectOrderedRows(db, 'jobs').rows.map(dumpRow),\n }\n },\n\n async listNotifications(): Promise<readonly JobStoreNotification[]> {\n return selectNotifications.all().map((row) => ({\n runId: String(row.run_id),\n payload: guardRunNotification(JSON.parse(String(row.payload)) as unknown),\n createdAt: String(row.created_at),\n }))\n },\n\n async logicalDump(): Promise<LogicalDump> {\n return createLogicalDump({\n db,\n schemaVersion: AGENT_JOB_STORE_USER_VERSION,\n checkpointsRoot: checkpoints.checkpointsRoot,\n })\n },\n\n async dumpLogicalState(): Promise<string> {\n return canonicalLogicalDump(\n createLogicalDump({\n db,\n schemaVersion: AGENT_JOB_STORE_USER_VERSION,\n checkpointsRoot: checkpoints.checkpointsRoot,\n }),\n )\n },\n }\n}\n","// Logical state, not bytes: tables come from the catalogue and every SELECT orders by all columns.\n\nimport { readdirSync, readFileSync } from 'node:fs'\nimport { join, relative, sep } from 'node:path'\n\nimport { DatabaseSync } from 'node:sqlite'\n\nimport { canonicalJson, sha256hex } from '@vostride/agent-qa-schema'\n\n/** Identifiers that are safe to interpolate; sqlite has no placeholders for them. */\nconst SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/\n\nexport interface LogicalDumpTable {\n readonly table: string\n readonly orderBy: readonly string[]\n readonly rows: readonly Record<string, unknown>[]\n}\n\nexport interface LogicalDumpCheckpoint {\n /** Relative to the checkpoint root, so two runs under different temp roots compare. */\n readonly path: string\n readonly digest: string\n}\n\nexport interface LogicalDump {\n readonly schemaVersion: number\n readonly tables: readonly LogicalDumpTable[]\n readonly checkpoints: readonly LogicalDumpCheckpoint[]\n}\n\nfunction requireIdentifier(value: string): string {\n if (!SAFE_IDENTIFIER.test(value)) {\n throw new TypeError(`unusable sqlite identifier in a logical dump: ${JSON.stringify(value)}`)\n }\n return value\n}\n\n/** The full-table SELECT for one table. Exported so a test can read the ORDER BY itself. */\nexport function orderedSelectSql(table: string, columns: readonly string[]): string {\n if (columns.length === 0) {\n throw new TypeError(`table ${table} reports no columns, so no order can be stated`)\n }\n const order = columns.map((column) => `\"${requireIdentifier(column)}\" ASC`).join(', ')\n return `SELECT * FROM \"${requireIdentifier(table)}\" ORDER BY ${order}`\n}\n\nexport function listStoreTables(db: DatabaseSync): string[] {\n return db\n .prepare(\n `SELECT name FROM sqlite_master\n WHERE type = 'table' AND name NOT LIKE 'sqlite_%'\n ORDER BY name ASC`,\n )\n .all()\n .map((row) => String(row.name))\n}\n\nexport function tableColumns(db: DatabaseSync, table: string): string[] {\n return db\n .prepare(`PRAGMA table_info(\"${requireIdentifier(table)}\")`)\n .all()\n .map((row) => String(row.name))\n}\n\n/**\n * Values sqlite hands back, in a form the canonical serializer accepts.\n *\n * Integer columns arrive as bigints on this binding, and a bigint cannot be serialized at\n * all — so this is a correctness step rather than a cosmetic one.\n */\nfunction normalize(value: unknown): unknown {\n if (typeof value === 'bigint') return Number(value)\n if (value instanceof Uint8Array) return { base16: Buffer.from(value).toString('hex') }\n return value\n}\n\nexport function selectOrderedRows(db: DatabaseSync, table: string): LogicalDumpTable {\n const columns = tableColumns(db, table)\n const rows = db\n .prepare(orderedSelectSql(table, columns))\n .all()\n .map((row) => {\n const normalized: Record<string, unknown> = {}\n for (const column of columns) normalized[column] = normalize(row[column])\n return normalized\n })\n return { table, orderBy: columns, rows }\n}\n\n/**\n * Every checkpoint file under the root, sorted, with a digest of its bytes.\n *\n * Digests rather than contents: the comparison only ever asks whether the bytes are the same,\n * and a dump that inlined every authored payload would be dominated by the thing it is least\n * interested in. Only the checkpoint directory is walked — the database and its sidecars live\n * elsewhere, and a filesystem-wide listing would make the sidecars part of the comparison.\n */\nexport function checkpointDigests(checkpointsRoot: string): LogicalDumpCheckpoint[] {\n const found: LogicalDumpCheckpoint[] = []\n\n function walk(dir: string): void {\n let entries\n try {\n entries = readdirSync(dir, { withFileTypes: true })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return\n throw error\n }\n for (const entry of entries) {\n const path = join(dir, entry.name)\n if (entry.isDirectory()) {\n walk(path)\n continue\n }\n found.push({\n path: relative(checkpointsRoot, path).split(sep).join('/'),\n digest: sha256hex(readFileSync(path, 'utf8')),\n })\n }\n }\n\n walk(checkpointsRoot)\n return found.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0))\n}\n\nexport interface CreateLogicalDumpInput {\n readonly db: DatabaseSync\n readonly schemaVersion: number\n readonly checkpointsRoot: string\n}\n\nexport function createLogicalDump(input: CreateLogicalDumpInput): LogicalDump {\n return {\n schemaVersion: input.schemaVersion,\n tables: listStoreTables(input.db).map((table) => selectOrderedRows(input.db, table)),\n checkpoints: checkpointDigests(input.checkpointsRoot),\n }\n}\n\n/** The comparable form. Two dumps of the same logical state are the same string. */\nexport function canonicalLogicalDump(dump: LogicalDump): string {\n return canonicalJson(dump)\n}\n","// Re-exports, not wrappers, so a surface reaches `runner-local`'s ordinals without naming it.\n\nexport {\n BuildOrdinalReservationError,\n reserveBuildOrdinalForProducts,\n latestBuildOrdinal,\n} from '@vostride/agent-qa-runner-local'\nexport { resolveBuildTag } from '@vostride/agent-qa-runner-local'\n","import { closeSync, existsSync, fsyncSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport {\n canonicalJson,\n ImprovementPlanSchema,\n MarkReceiptSchema,\n markAddressKey,\n slugBranch,\n type MarkAddress,\n type MarkReceipt,\n} from '@vostride/agent-qa-schema'\nimport { z } from 'zod'\nimport { HANDOFF_FILE, RUNS_SUBDIR } from '../composition/run-layout.js'\nimport { acquireMarkLock } from './mark-lock.js'\n\nexport const MARKS_LEDGER_FILE = 'marks.jsonl'\nexport const MARKS_LEDGER_LOCK_FILE = 'marks.jsonl.lock'\n/** A run's one unfinished mark, beside its ledger. */\nexport const MARK_INTENT_FILE = 'mark-intent.json'\n/**\n * The resumable mark. `operationId` is the stable identity every\n * effect of this mark carries (the knowledge change id derives from it), so a retry at any stage\n * lands the same fix once. `applied` is the last stage: the fix is published and the receipt is\n * next, and only the receipt remains to be written. The applied change itself rides the mark's\n * own disposition, so there is one record of what changed.\n */\nexport const MARK_INTENT_STAGES = ['prepared', 'evidence', 'applied'] as const\nconst intentSchema = z.object({\n schemaVersion: z.literal(2), mark: MarkReceiptSchema,\n stage: z.enum(MARK_INTENT_STAGES),\n operationId: z.uuid(),\n plan: ImprovementPlanSchema.optional(),\n}).strict().superRefine((intent, ctx) => {\n if (intent.stage === 'applied' && intent.mark.disposition.kind === 'drafted') {\n ctx.addIssue({ code: 'custom', path: ['mark', 'disposition'], message: 'a mark applies its fix; it never files a draft' })\n }\n})\nexport type MarkIntent = z.infer<typeof intentSchema>\n\nfunction atomicPublish(path: string, text: string): void {\n const staged = `${path}.pending`\n const fd = openSync(staged, 'w', 0o600)\n try { writeFileSync(fd, text); fsyncSync(fd) } finally { closeSync(fd) }\n renameSync(staged, path)\n}\n\nexport class MarkLedgerBusyError extends Error {\n constructor() {\n super('Mark ledger is busy; retry the mark after the current transaction finishes')\n this.name = 'MarkLedgerBusyError'\n }\n}\n\nexport class MarkLedgerCorruptError extends Error {\n constructor(readonly line: number) {\n // Never echo malformed user text or parser diagnostics into a host surface.\n super(`Mark ledger is corrupt at line ${line}`)\n this.name = 'MarkLedgerCorruptError'\n }\n}\n\n/**\n * The run's unfinished-mark record cannot be resumed, refused by the record's own name. Nothing is\n * migrated or read further; the message names the file to remove, after which the run can be\n * marked again.\n */\nexport class MarkIntentUnusableError extends Error {\n constructor(\n readonly intentPath: string,\n readonly reason: 'earlier-version' | 'unreadable' | 'mismatched',\n ) {\n const what = reason === 'earlier-version'\n ? 'was written by an earlier agent-qa version, which this version does not read'\n : reason === 'unreadable' ? 'is unreadable' : 'does not match this run\\'s mark ledger'\n // Never echo the record's bytes or parser diagnostics into a host surface.\n super(`The unfinished-mark record ${intentPath} ${what}; nothing was marked. Remove that file, `\n + 'then mark again.')\n this.name = 'MarkIntentUnusableError'\n }\n}\n\n/** Keys only an older intent carried: a filed proposal, the drafted stage, a stored test draft. */\nfunction isEarlierVersionIntent(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false\n const intent = value as Record<string, unknown>\n return 'proposalUuid' in intent || 'testDraft' in intent || intent['stage'] === 'drafted'\n}\n\n/** The one latest-per-address rule, over receipts a caller has already read once. */\nexport function latestMarkReceiptsPerAddress(receipts: readonly MarkReceipt[]): MarkReceipt[] {\n const latest = new Map<string, MarkReceipt>()\n for (const receipt of receipts) {\n const key = markAddressKey(receipt)\n if ((latest.get(key)?.ordinal ?? 0) < receipt.ordinal) latest.set(key, receipt)\n }\n return [...latest.values()].sort((a, b) =>\n a.testIndex - b.testIndex || (a.stepIndex ?? -1) - (b.stepIndex ?? -1),\n )\n}\n\nexport function latestMarkReceiptFor(\n receipts: readonly MarkReceipt[],\n runId: string,\n address: MarkAddress,\n): MarkReceipt | undefined {\n if (address.runId !== runId) return undefined\n return latestMarkReceiptsPerAddress(receipts).find(receipt => markAddressKey(receipt) === markAddressKey(address)\n && (address.testId === undefined || receipt.testId === address.testId))\n}\n\nexport class MarkLedgerNoRunError extends Error {\n constructor() {\n super('run-not-found: mark ledger requires a completed run handoff')\n this.name = 'MarkLedgerNoRunError'\n }\n}\n\n/** The per-run marks ledger under the run directory. */\nexport class FsMarkLedger {\n private readonly dir: string\n private readonly file: string\n private readonly lock: string\n private readonly runId: string\n private readonly runSlug: string\n private inTransaction = false\n private intentValue: MarkIntent | undefined\n\n constructor(config: { root: string; runId: string }) {\n this.runId = config.runId\n this.runSlug = slugBranch(config.runId)\n this.dir = join(config.root, RUNS_SUBDIR, this.runSlug)\n this.file = join(this.dir, MARKS_LEDGER_FILE)\n this.lock = join(this.dir, MARKS_LEDGER_LOCK_FILE)\n }\n\n read(): MarkReceipt[] {\n let text: string\n try {\n text = readFileSync(this.file, 'utf8')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return []\n throw error\n }\n if (text === '') return []\n const lines = text.split('\\n')\n // A missing terminator may be a torn append; concatenating another receipt would corrupt it.\n if (lines.pop() !== '') throw new MarkLedgerCorruptError(lines.length + 1)\n return lines.map((line, index) => {\n try {\n const receipt = MarkReceiptSchema.parse(JSON.parse(line))\n if (receipt.ordinal !== index + 1 || receipt.runId !== this.runId || receipt.runSlug !== this.runSlug) {\n throw new Error('ledger identity or ordinal mismatch')\n }\n return receipt\n } catch {\n throw new MarkLedgerCorruptError(index + 1)\n }\n })\n }\n\n latestPerAddress(): MarkReceipt[] {\n return latestMarkReceiptsPerAddress(this.read())\n }\n\n latestFor(address: MarkAddress): MarkReceipt | undefined {\n // A foreign address never reads this run's ledger.\n if (address.runId !== this.runId) return undefined\n return latestMarkReceiptFor(this.read(), this.runId, address)\n }\n\n /** Private resumable state is admitted only while this run's existing lock is held. */\n prepareIntent(mark: MarkReceipt, operationId: string): MarkIntent {\n if (!this.inTransaction) throw new Error('mark intent requires the run transaction')\n const prior = this.intentValue\n if (prior !== undefined) {\n const request = (value: MarkReceipt) => ({ runId: value.runId, testIndex: value.testIndex,\n testId: value.testId, stepIndex: value.stepIndex, kind: value.kind, note: value.note })\n if (canonicalJson(request(prior.mark)) !== canonicalJson(request(mark))) {\n throw new Error('An unfinished mark must be retried with its original address, kind and note')\n }\n return prior\n }\n return this.checkpointIntent({ schemaVersion: 2, mark, operationId, stage: 'prepared' })\n }\n\n checkpointIntent(value: MarkIntent): MarkIntent {\n if (!this.inTransaction) throw new Error('mark intent requires the run transaction')\n const intent = intentSchema.parse(value)\n if (intent.mark.runId !== this.runId || intent.mark.runSlug !== this.runSlug\n || intent.mark.ordinal !== this.read().length + 1) throw new MarkLedgerCorruptError(intent.mark.ordinal)\n atomicPublish(join(this.dir, MARK_INTENT_FILE), `${canonicalJson(intent)}\\n`)\n this.intentValue = intent\n return intent\n }\n\n async transact(\n fn: (nextOrdinal: number) => Promise<Omit<MarkReceipt, 'ordinal'> | undefined>,\n ): Promise<MarkReceipt | undefined> {\n if (!existsSync(join(this.dir, HANDOFF_FILE))) throw new MarkLedgerNoRunError()\n const release = await acquireMarkLock(this.lock, this.runId, () => new MarkLedgerBusyError())\n try {\n // Freeze and draft inside this callback: the next host sees the entire prior receipt.\n const receipts = this.read()\n const nextOrdinal = receipts.length + 1\n const intentPath = join(this.dir, MARK_INTENT_FILE)\n this.intentValue = undefined\n if (existsSync(intentPath)) {\n let raw: unknown\n try {\n raw = JSON.parse(readFileSync(intentPath, 'utf8'))\n } catch { throw new MarkIntentUnusableError(intentPath, 'unreadable') }\n const parsed = intentSchema.safeParse(raw)\n if (!parsed.success) {\n throw new MarkIntentUnusableError(intentPath,\n isEarlierVersionIntent(raw) ? 'earlier-version' : 'unreadable')\n }\n const intent = parsed.data\n if (intent.mark.runId !== this.runId || intent.mark.runSlug !== this.runSlug) {\n throw new MarkIntentUnusableError(intentPath, 'mismatched')\n }\n if (intent.mark.ordinal === nextOrdinal) this.intentValue = intent\n else if (canonicalJson(receipts[intent.mark.ordinal - 1]) === canonicalJson(intent.mark)) unlinkSync(intentPath)\n else throw new MarkIntentUnusableError(intentPath, 'mismatched')\n }\n this.inTransaction = true\n const record = await fn(nextOrdinal)\n if (record === undefined) return undefined\n const receipt = MarkReceiptSchema.parse({ ...record, ordinal: nextOrdinal })\n if (receipt.runId !== this.runId || receipt.runSlug !== this.runSlug) {\n throw new Error('mark receipt does not belong to this run ledger')\n }\n if (this.intentValue !== undefined && (this.intentValue.stage !== 'applied'\n || canonicalJson(this.intentValue.mark) !== canonicalJson(receipt))) {\n throw new MarkLedgerCorruptError(nextOrdinal)\n }\n // Preserve the exact historical prefix while atomically publishing the next complete line.\n const before = existsSync(this.file) ? readFileSync(this.file, 'utf8') : ''\n atomicPublish(this.file, `${before}${canonicalJson(receipt)}\\n`)\n if (this.intentValue !== undefined) unlinkSync(intentPath)\n return receipt\n } finally {\n this.inTransaction = false\n this.intentValue = undefined\n release()\n }\n }\n\n append(record: Omit<MarkReceipt, 'ordinal'>): Promise<MarkReceipt | undefined> {\n return this.transact(async () => record)\n }\n}\n","// runner-local is reachable only from the composition subtree; the store reads the run layout here.\nexport { HANDOFF_FILE, RUNS_SUBDIR, loadCompletedRunHandoff } from '@vostride/agent-qa-runner-local'\n","import { randomUUID } from 'node:crypto'\nimport { closeSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { z } from 'zod'\n\nconst ownerSchema = z.object({ schemaVersion: z.literal(2), kind: z.literal('mark-ledger-lock'),\n pid: z.number().int().positive(), token: z.uuid(), runId: z.string().min(1) }).strict()\ntype Owner = z.infer<typeof ownerSchema>\n\nfunction syncDirectory(path: string): void {\n const fd = openSync(path, 'r')\n try { fsyncSync(fd) } finally { closeSync(fd) }\n}\n\nfunction readOwner(path: string, runId: string): Owner | undefined {\n try {\n const directory = lstatSync(path)\n if (!directory.isDirectory() || directory.isSymbolicLink()) return undefined\n const ownerFile = join(path, 'owner.json')\n const file = lstatSync(ownerFile)\n if (!file.isFile() || file.isSymbolicLink()) return undefined\n const parsed = ownerSchema.safeParse(JSON.parse(readFileSync(ownerFile, 'utf8')))\n return parsed.success && parsed.data.runId === runId ? parsed.data : undefined\n } catch { return undefined }\n}\n\nfunction positivelyDead(pid: number): boolean {\n try { process.kill(pid, 0); return false }\n catch (error) { return (error as NodeJS.ErrnoException).code === 'ESRCH' }\n}\n\n/** Complete owner publication; malformed, legacy and uncertain owners are never reaped. */\nexport async function acquireMarkLock(lock: string, runId: string, busy: () => Error): Promise<() => void> {\n const owner: Owner = { schemaVersion: 2, kind: 'mark-ledger-lock', pid: process.pid, token: randomUUID(), runId }\n const candidate = `${lock}.candidate-${owner.token}`\n mkdirSync(candidate)\n const fd = openSync(join(candidate, 'owner.json'), 'wx', 0o600)\n try { writeFileSync(fd, JSON.stringify(owner)); fsyncSync(fd) } finally { closeSync(fd) }\n syncDirectory(candidate)\n const started = Date.now()\n let acquired = false\n try {\n while (!acquired) {\n try {\n // mkdir is create-only even against an empty legacy/partial directory. Publish the\n // complete owner immediately afterward; death in this tiny gap remains busy by law.\n mkdirSync(lock)\n renameSync(join(candidate, 'owner.json'), join(lock, 'owner.json'))\n syncDirectory(lock)\n syncDirectory(dirname(lock))\n rmSync(candidate, { recursive: true })\n acquired = true\n } catch (error) {\n if (!['EEXIST', 'ENOTEMPTY', 'ENOTDIR', 'EISDIR', 'EPERM', 'EACCES'].includes((error as NodeJS.ErrnoException).code ?? '')) throw error\n const current = readOwner(lock, runId)\n if (current !== undefined && positivelyDead(current.pid)) {\n try {\n // Retain this NONEMPTY generation tombstone. A delayed reclaimer of G cannot\n // rename a newer live H over dead-G after another contender already moved G.\n renameSync(lock, `${lock}.dead-${current.token}`)\n syncDirectory(dirname(lock))\n continue\n } catch (recoveryError) {\n if ((recoveryError as NodeJS.ErrnoException).code === 'ENOENT') continue\n if (!['EEXIST', 'ENOTEMPTY', 'ENOTDIR', 'EISDIR', 'EPERM', 'EACCES'].includes((recoveryError as NodeJS.ErrnoException).code ?? '')) throw recoveryError\n }\n }\n const remaining = 10_000 - (Date.now() - started)\n if (remaining <= 0) throw busy()\n await new Promise(resolve => setTimeout(resolve, Math.min(50, remaining)))\n }\n }\n } finally {\n if (!acquired) rmSync(candidate, { recursive: true, force: true })\n }\n return () => {\n if (readOwner(lock, runId)?.token !== owner.token) return\n const released = `${lock}.released-${owner.token}`\n renameSync(lock, released)\n syncDirectory(dirname(lock))\n rmSync(released, { recursive: true })\n syncDirectory(dirname(lock))\n }\n}\n","// The action cache's purge lives in runner-local beside the cache that writes the entries. A\n// surface reaches it through this re-export instead of naming runner-local itself.\nexport { purgeActionCache } from '@vostride/agent-qa-runner-local'\n","// Release dead claims before pumping: `claimNext` never re-offers a row with `claimed_at` set.\n\nimport { join } from 'node:path'\n\nimport { createAgentJobQueue, createRealJobKindRegistry } from '@vostride/agent-qa-agent'\nimport type {\n AgentJobQueue,\n ClockPort,\n JobIdSource,\n JobKindRegistry,\n JobModelCapability,\n JobStoreFence,\n RecoverAbandonedClaimsOutcome,\n RunNextJobOutcome,\n} from '@vostride/agent-qa-agent'\n\nimport { createJobCheckpointStore } from '../store/job-checkpoint-store.js'\nimport { AGENT_JOB_STORE_DB_FILE, createSqliteJobStore } from '../store/sqlite-job-store.js'\nimport type { SqliteJobStore } from '../store/sqlite-job-store.js'\n\n/**\n * How many jobs one `resumePending` call will run before it refuses to continue.\n *\n * A bound rather than a loop that trusts the queue to empty: recovery runs against a store any\n * process may have written, and a chain that keeps enqueuing successors would otherwise turn a\n * recovery call into an unbounded drain. Exceeding it raises rather than truncating — a resume that\n * quietly stopped early would report success over work it left behind.\n */\nexport const JOB_RECOVERY_MAX_RESUMED_JOBS = 64\n\nexport interface ComposeJobRecoveryInput {\n /** The project's runtime root, i.e. `<configDir>/.agent-qa`. Absolute. */\n readonly agentQaRoot: string\n /** Every column and dump row this host writes is stamped from here. */\n readonly clock: ClockPort\n /** Ids derived from `(kind, idempotencyKey)`, so a resumed chain addresses the same rows. */\n readonly idSource: JobIdSource\n /**\n * The capability a resumed job may author with, supplied by the host.\n *\n * Required and not defaultable, on the same reasoning as the queue's own option: an optional\n * capability means a host can compose recovery with none, and the only place to discover that is\n * inside an author callback far from the composition that forgot it.\n */\n readonly model: JobModelCapability\n /** Defaults to the six real declarations. Injected so a harness can drive its own handlers. */\n readonly jobKinds?: JobKindRegistry\n}\n\nexport interface JobRecoveryHost {\n readonly store: SqliteJobStore\n readonly kinds: JobKindRegistry\n readonly queue: AgentJobQueue\n /**\n * Return every outstanding claim to the queue, keeping the attempt each one spent.\n *\n * Call this FIRST. Only one process drains under a given fence, so at the moment authority is\n * adopted every outstanding claim belongs to a host that is gone; calling it beside a live pump\n * would reclaim a job from the handler still running it.\n */\n recoverAbandonedClaims(fence: JobStoreFence): Promise<RecoverAbandonedClaimsOutcome>\n /** Pump until no row is claimable. No timers, no sleeping — not a dispatcher. */\n resumePending(fence: JobStoreFence, maxJobs?: number): Promise<readonly RunNextJobOutcome[]>\n close(): void\n}\n\nexport function composeJobRecovery(input: ComposeJobRecoveryInput): JobRecoveryHost {\n const store = createSqliteJobStore({\n path: join(input.agentQaRoot, AGENT_JOB_STORE_DB_FILE),\n clock: input.clock,\n checkpoints: createJobCheckpointStore({ root: input.agentQaRoot }),\n })\n const kinds = input.jobKinds ?? createRealJobKindRegistry()\n const queue = createAgentJobQueue({\n store,\n registry: kinds,\n clock: input.clock,\n idSource: input.idSource,\n model: input.model,\n })\n\n return {\n store,\n kinds,\n queue,\n\n recoverAbandonedClaims(fence: JobStoreFence): Promise<RecoverAbandonedClaimsOutcome> {\n return queue.recoverAbandonedClaims({ fence })\n },\n\n async resumePending(\n fence: JobStoreFence,\n maxJobs: number = JOB_RECOVERY_MAX_RESUMED_JOBS,\n ): Promise<readonly RunNextJobOutcome[]> {\n const outcomes: RunNextJobOutcome[] = []\n for (;;) {\n if (outcomes.length >= maxJobs) {\n throw new Error(\n `agent job recovery ran ${maxJobs} jobs without emptying the agent job queue; the ` +\n 'bound exists so a chain that keeps enqueuing successors cannot turn recovery into an unbounded ' +\n 'drain, and stopping early without saying so would report success over work left behind',\n )\n }\n const outcome = await queue.runNextJob({ fence })\n if (!outcome.ran) return outcomes\n outcomes.push(outcome)\n }\n },\n\n close(): void {\n store.close()\n },\n }\n}\n","// Implements the same `SessionLogPort` for hermetic tests; fsync order needs the disk adapter.\n\nimport { repairSession } from '@vostride/agent-qa-agent'\nimport { CURRENT_CHAT_SESSION_SCHEMA_VERSION } from '@vostride/agent-qa-schema'\nimport type {\n ChatSessionEvent,\n ChatSessionHandle,\n ChatSessionHeader,\n OpenedChatSession,\n SessionLogPort,\n} from '@vostride/agent-qa-schema'\n\nimport {\n ChatSessionBusyError,\n UnknownChatSessionError,\n mintChatSessionId,\n} from './jsonl-session-log.js'\n\nexport interface CreateMemorySessionLogOptions {\n readonly now: () => string\n readonly model: () => string\n readonly toolsetHash: () => string\n readonly random?: () => number\n}\n\nexport interface MemorySessionLog extends SessionLogPort {\n /** Everything written, for assertions. A copy, so a caller cannot edit the log through it. */\n snapshot(sessionId: string): OpenedChatSession | undefined\n}\n\nexport function createMemorySessionLog(\n options: CreateMemorySessionLogOptions,\n): MemorySessionLog {\n const sessions = new Map<string, { header: ChatSessionHeader; events: ChatSessionEvent[] }>()\n const random = options.random ?? Math.random\n // Live sessions are a set, matching the disk adapter's per-session handles.\n const liveSessions = new Set<string>()\n\n function handleFor(id: string, opened: OpenedChatSession): ChatSessionHandle {\n let live = true\n const requireLive = (verb: string): void => {\n if (!live) {\n throw new TypeError(\n `a chat session ${verb} cannot go through a closed handle for ${id}. Open the session `\n + 'again to write to it.',\n )\n }\n }\n liveSessions.add(id)\n return {\n header: opened.header,\n events: opened.events,\n refusedLines: opened.refusedLines,\n append(event: ChatSessionEvent): Promise<void> {\n requireLive('event')\n sessions.get(id)!.events.push(event)\n return Promise.resolve()\n },\n turnBoundary(): Promise<void> {\n // A no-op because there is nothing to sync — and a REFUSAL after close, so the twin\n // answers the same question the disk adapter does rather than a laxer one.\n requireLive('turn boundary')\n return Promise.resolve()\n },\n close(): Promise<void> {\n if (live) {\n live = false\n liveSessions.delete(id)\n }\n return Promise.resolve()\n },\n }\n }\n\n return {\n open(sessionId?: string): Promise<ChatSessionHandle> {\n if (sessionId !== undefined) {\n const existing = sessions.get(sessionId)\n // The same refusal the disk adapter raises, and deliberately the same class: a test that\n // proves the refusal against this twin proves it about the vocabulary production uses.\n if (existing === undefined) throw new UnknownChatSessionError(sessionId)\n if (liveSessions.has(sessionId)) throw new ChatSessionBusyError(sessionId)\n // THE SAME REPAIR PATH, not a twin of it. A hermetic test that resumed a dangling session\n // here and saw no synthesized abort would be passing against a contract production does\n // not sign. The events are re-serialized so they enter `repairSession` exactly as disk\n // lines do — the twin cannot produce a torn line or a damaged one, which is precisely why\n // it must not get its own shortcut for deciding what a resumed session means.\n const repair = repairSession(\n existing.events.map((event, index) => ({\n lineNumber: index + 2,\n text: JSON.stringify(event),\n })),\n { declaredVersion: existing.header.schemaVersion, now: options.now },\n )\n existing.events.push(...repair.synthesized)\n return Promise.resolve(\n handleFor(sessionId, {\n header: existing.header,\n events: [...existing.events],\n // Always empty here, and that is the honest answer rather than a placeholder: this\n // twin stores typed records, so no line of it can be damaged in the way a file's can.\n refusedLines: repair.refusedLines,\n }),\n )\n }\n const createdAt = options.now()\n const id = mintChatSessionId(createdAt, random)\n const header: ChatSessionHeader = {\n schemaVersion: CURRENT_CHAT_SESSION_SCHEMA_VERSION,\n sessionId: id,\n createdAt,\n model: options.model(),\n toolsetHash: options.toolsetHash(),\n }\n sessions.set(id, { header, events: [] })\n return Promise.resolve(handleFor(id, { header, events: [], refusedLines: [] }))\n },\n\n snapshot(sessionId: string): OpenedChatSession | undefined {\n const found = sessions.get(sessionId)\n return found === undefined\n ? undefined\n : { header: found.header, events: [...found.events], refusedLines: [] }\n },\n }\n}\n"],"mappings":";AAEA,SAAS,kBAAkB;AAC3B,SAAS,SAAS,YAAY,eAAe;AAC7C,SAAS,8BAA8B;AACvC,SAAS,uBAAuB;AAShC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;AC5BA,IAAM,iBAAiB;AAGvB,IAAM,mBAAmB;AAGzB,IAAM,YAAY;AAGlB,IAAM,cAAc;AAGpB,IAAM,gBAAgB;AAGtB,IAAM,qBAAqB;AAG3B,IAAM,oBAAoB;AAG1B,IAAM,uBAAuB;AAG7B,IAAM,iCAAiC;AAkB9C,SAAS,YAAY,OAAuB;AAC1C,MAAI,OAAO,MAAM,KAAK,EAAG,QAAO;AAChC,MAAI,UAAU,OAAO,kBAAmB,QAAO,OAAO;AACtD,MAAI,UAAU,OAAO,kBAAmB,QAAO,OAAO;AACtD,SAAO,KAAK,MAAM,KAAK;AACzB;AAEA,SAAS,MAAM,OAAe,SAAiB,SAAyB;AACtE,SAAO,KAAK,IAAI,SAAS,KAAK,IAAI,SAAS,KAAK,CAAC;AACnD;AAGO,SAAS,wBAAwB,OAAuD;AAC7F,QAAM,gBAAgB,MAAM,gBACxB,MAAM,iBACN,MAAM,gBACN,MAAM;AAEV,QAAM,QAAQ;AAAA,IACZ,YAAY,gBAAgB,cAAc;AAAA,IAC1C;AAAA,IACA;AAAA,EACF;AACA,QAAM,UAAU,KAAK,IAAI,aAAa,YAAY,gBAAgB,gBAAgB,CAAC;AACnF,QAAM,WAAW,KAAK,IAAI,WAAW,YAAY,gBAAgB,kBAAkB,CAAC;AAIpF,QAAM,gBAAgB;AACtB,SAAO,EAAE,OAAO,eAAe,SAAS,UAAU,WAAW,kBAAkB;AACjF;AAGO,SAAS,eAAe,cAA0C;AACvE,SAAO,aAAa,eACf,aAAa,UACb,aAAa,iBAAiB;AACrC;AAGO,SAAS,gBAAgB,cAAyC;AACvE,MAAI,eAAe,YAAY,EAAG,QAAO;AACzC,SAAO,KAAK,IAAI,GAAG,KAAK,MAAM,oBAAoB,oBAAoB,CAAC;AACzE;;;AC1FA,SAAS,2BAA2B;AAe7B,SAAS,4BAA4B,QAAkD;AAC5F,QAAM,SAAS,oBAAI,IAA4B;AAC/C,QAAM,WAAW,CAAC,UAA4B,KAAK,UAAU,CAAC,MAAM,MAAM,MAAM,GAAG,CAAC;AAEpF,SAAO;AAAA,IACL,YAAY,OAAO,QAAQ;AACzB,YAAM,MAAM,SAAS,KAAK;AAC1B,YAAM,WAAW,OAAO,IAAI,GAAG;AAC/B,UAAI,aAAa,OAAW,QAAO;AACnC,YAAM,QAAQ,OAAO,YAAY,OAAO,MAAM;AAC9C,aAAO,IAAI,KAAK,KAAK;AACrB,aAAO;AAAA,IACT;AAAA,IACA,QAAQ,CAAC,OAAO,YAAY,OAAO,OAAO,OAAO,OAAO;AAAA,IACxD,MAAM,CAAC,IAAI,YAAY,OAAO,KAAK,IAAI,OAAO;AAAA,IAC9C,aAAa,CAAC,SAAS,WAAW,OAAO,YAAY,SAAS,MAAM;AAAA,IACpE,cAAc,CAAC,QAAQ,aAAa,iBAClC,OAAO,aAAa,QAAQ,aAAa,YAAY;AAAA,IACvD,mBAAmB,CAAC,YAAY,OAAO,kBAAkB,OAAO;AAAA,EAClE;AACF;AAMO,SAAS,yBACd,OACqB;AACrB,SAAO,4BAA4B,oBAAoB;AAAA,IACrD,eAAe,MAAM;AAAA,IACrB,GAAI,MAAM,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,MAAM,QAAQ;AAAA,IAChE,eAAe;AAAA,MACb,WAAW,MAAM;AAAA,MACjB,GAAI,MAAM,iBAAiB,SAAY,CAAC,IAAI,EAAE,cAAc,MAAM,aAAa;AAAA,IACjF;AAAA,IACA,SAAS,EAAE,WAAW,MAAM,UAAU;AAAA,EACxC,CAAC,CAAC;AACJ;;;AFmFO,SAAS,4BACd,OACyB;AACzB,QAAM,WAAW,MAAM,WAAW,YAAY;AAC9C,QAAM,gBAAgB,MAAM,WAAW,SAAS;AAAA,IAC9C,EAAE,MAAM,UAAU,SAAS,MAAM,YAAY;AAAA,EAC/C,CAAC;AACD,QAAM,uBAAuB,MAAM,WAAW,SAAS;AAAA,IACrD,EAAE,MAAM,QAAQ,SAAS,MAAM,mBAAmB;AAAA,EACpD,CAAC;AACD,QAAM,WAAW,wBAAwB;AAAA,IACvC,eAAe,SAAS;AAAA,IACxB,gBAAgB,SAAS;AAAA,IACzB;AAAA,IACA;AAAA,EACF,CAAC;AACD,QAAM,UAA4B;AAAA,IAChC,GAAG;AAAA,IACH,WAAW,gBAAgB,MAAM,YAAY;AAAA,EAC/C;AACA,QAAM,SAAS,yBAAyB;AAAA,IACtC,eAAe,MAAM;AAAA,IACrB,GAAI,MAAM,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,MAAM,QAAQ;AAAA,IAChE,GAAI,MAAM,iBAAiB,SAAY,CAAC,IAAI,EAAE,cAAc,MAAM,aAAa;AAAA,IAC/E,WAAW,MAAM;AAAA,IACjB,WAAW,QAAQ;AAAA,EACrB,CAAC;AAED,QAAM,gBAAgB,MAAM,qBAAqB;AAAA,IAC/C,eAAe,MAAM;AAAA,IACrB,GAAI,MAAM,gBAAgB,SAAY,CAAC,IAAI,EAAE,aAAa,MAAM,YAAY;AAAA,EAC9E,CAAC;AACD,gBAAc,MAAM,MAAM,MAAS;AACnC,QAAM,kBAAkB,eAAe,MAAM,YAAY;AACzD,QAAM,eAAe,mBAAmB;AAAA,IACtC,KAAK,QAAQ;AAAA,IACb,QAAQ,QAAQ,QAAQ,QAAQ,WAAW,kBAAkB,QAAQ,gBAAgB;AAAA,IACrF,aAAa,CAAC;AAAA,EAChB,CAAC;AAGD,QAAM,SAAS,kBACX,kBAAkB;AAAA,IAChB;AAAA,IACA,OAAO,MAAM;AAAA,IACb,WAAW,MAAM;AAAA,IACjB,oBAAoB,QAAQ;AAAA,IAC5B,gBAAgB,QAAQ;AAAA,IACxB;AAAA,IACA,gBAAgB,CAAC,SAAS,MAAM,WAAW,SAAS;AAAA,MAClD,EAAE,MAAM,QAAQ,SAAS,KAAK;AAAA,IAChC,CAAC;AAAA,EACH,CAAC,IACD;AAEJ,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB,QAAQ;AAAA,IACxB,iBAAiB,QAAQ;AAAA,IACzB,uBAAuB,QAAQ;AAAA,EACjC;AACF;AAiBA,SAAS,SAAS,OAAuB;AACvC,SAAO,WAAW,QAAQ,EAAE,OAAO,OAAO,MAAM,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC7E;AAGO,SAAS,wBAAwB,OAGnB;AACnB,QAAM,YAA6B,MAAM,QAAQ,IAAI,CAAC,OAAO;AAAA,IAC3D,mBAAmB,SAAS,MAAM,gBAAgB,QAAQ,EAAE,oBAAoB,GAAG;AAAA,IACnF,kBAAkB,SAAS,EAAE,eAAe;AAAA,EAC9C,EAAE;AAEF,MAAI,UAAU,WAAW,GAAG;AAE1B,WAAO,EAAE,UAAU,EAAE,GAAG,UAAU,CAAC,EAAE,GAAG,UAAU;AAAA,EACpD;AAEA,QAAM,uBAAiC,CAAC;AACxC,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,QAAQ,WAAW;AAC5B,QAAI,CAAC,KAAK,IAAI,KAAK,iBAAiB,GAAG;AACrC,WAAK,IAAI,KAAK,iBAAiB;AAC/B,2BAAqB,KAAK,KAAK,iBAAiB;AAAA,IAClD;AAAA,EACF;AAEA,QAAM,WAA0B;AAAA,IAC9B,mBAAmB,SAAS,qBAAqB,KAAK,IAAI,CAAC;AAAA,IAC3D,kBAAkB,SAAS,UAAU,IAAI,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;AAAA,EAChF;AAEA,SAAO,EAAE,UAAU,UAAU;AAC/B;AAKO,SAAS,2BAA2B,UAAqD;AAC9F,SAAO,uBAAuB,QAAQ;AACxC;AAkBO,SAAS,cAAc,OAAkE;AAC9F,QAAM,OAAO,QAAQ,MAAM,WAAW,WAAW;AACjD,SAAO;AAAA,IACL,UAAU,IAAI,WAAW,EAAE,MAAM,OAAO,MAAM,MAAM,CAAC;AAAA,IACrD,cAAc,IAAI,eAAe,EAAE,MAAM,OAAO,MAAM,MAAM,CAAC;AAAA,IAC7D,kBAAkB,IAAI,mBAAmB,EAAE,MAAM,OAAO,MAAM,MAAM,CAAC;AAAA,IACrE,mBAAmB,IAAI,wBAAwB,EAAE,MAAM,OAAO,MAAM,MAAM,CAAC;AAAA;AAAA;AAAA,IAG3E,mBAAmB,CAAC,MAAM,YAAY;AACpC,cAAQ,YAAY,SAAS,EAAE,KAAK,CAAC;AAAA,IACvC;AAAA,EACF;AACF;AAGO,SAAS,0BAA0B,QAA2D;AACnG,SAAO,IAAI,0BAA0B,MAAM;AAC7C;AAGO,SAAS,uBAAuB,OAIhB;AACrB,aAAW,SAAS,CAAC,MAAM,MAAM,MAAM,KAAK,MAAM,KAAK,QAAQ,GAAG;AAChE,UAAM,UAAU,OAAO,KAAK;AAC5B,QAAI,QAAS,QAAO;AAAA,EACtB;AACA,SAAO;AACT;AAGA,eAAsB,uBAAuB,OAIzB;AAClB,QAAM,OAAO,QAAQ,MAAM,WAAW,WAAW;AACjD,QAAM,UAAU,MAAM,iBAAiB,EAAE,MAAM,SAAS,MAAM,QAAQ,CAAC;AACvE,MAAI,MAAM,aAAa,QAAW;AAChC,UAAM,eAAe;AAAA,MACnB;AAAA,MACA,SAAS,MAAM;AAAA,MACf,KAAK,MAAM;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAKO,IAAM,uBAAuB;AAiB7B,IAAM,8BAAN,cAA0C,MAAM;AAAA,EACrD,YACW,gBACA,mBACA,aACT;AACA;AAAA,MACE,uBAAuB,iBAAiB,aAAa,cAAc,eAC9D,WAAW;AAAA,IAClB;AAPS;AACA;AACA;AAMT,SAAK,OAAO;AAAA,EACd;AACF;AAmBO,SAAS,uBAAuC;AACrD,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,cAAc;AAElB,QAAM,iBAAiB,YAA2B;AAChD,UAAM,WAAW;AACjB,gBAAY;AACZ,kBAAc;AACd,qBAAiB;AACjB,kBAAc;AACd,QAAI,SAAU,OAAM,SAAS;AAAA,EAC/B;AAEA,SAAO;AAAA,IACL,MAAM,YAAY,UAAU,OAAO;AACjC,UAAI,cAAc,UAAa,cAAc,UAAU;AACrD,YAAI,cAAc,GAAG;AACnB,gBAAM,IAAI,4BAA4B,WAAW,UAAU,WAAW;AAAA,QACxE;AACA,cAAM,eAAe;AAAA,MACvB;AAEA,UAAI,cAAc,UAAU;AAG1B,oBAAY;AACZ,yBAAiB,MAAM;AACvB,uBAAe,YAAY;AACzB,cAAI;AACF,kBAAM,MAAM,MAAM;AAAA,UACpB,SAAS,OAAO;AAGd,6BAAiB;AACjB,kBAAM;AAAA,UACR;AAAA,QACF,GAAG;AAAA,MACL;AAEA,YAAM,QAAQ;AAEd,qBAAe;AACf,UAAI,WAAW;AACf,YAAM,QAA0B;AAAA,QAC9B,UAAU;AACR,cAAI,SAAU;AACd,qBAAW;AACX,yBAAe;AAAA,QACjB;AAAA,MACF;AACA,UAAI;AACF,cAAM;AAAA,MACR,SAAS,OAAO;AACd,cAAM,QAAQ;AACd,cAAM;AAAA,MACR;AACA,aAAO;AAAA,IACT;AAAA,IACA,MAAM,WAAW;AACf,YAAM,eAAe;AAAA,IACvB;AAAA,EACF;AACF;AAmBO,SAAS,0BACd,KACA,SACM;AACN,QAAM,eAAe,cAAc,OAAO;AAC1C,MAAI,qBAAqB,cAAc,YAAY,cAAc,QAAQ;AAC3E;AAGO,SAAS,yBAAyB,OAGlB;AACrB,SAAO,OAAO,QAA6B,QAAmD;AAC5F,UAAM,UAAU,MAAM,SAAS,IAAI,SAAS;AAC5C,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,yCAAyC,IAAI,SAAS,YAAY,OAAO,MAAM,GAAG;AAAA,IACpG;AACA,UAAM,QAAQ,MAAM,MAAM,UAAU,YAAY,QAAQ,UAAU,QAAQ,KAAK;AAC/E,QAAI;AAEF,gCAA0B,KAAK,QAAQ,OAAO;AAC9C,aAAO,MAAM,QAAQ,IAAI,GAAG;AAAA,IAC9B,UAAE;AAGA,YAAM,QAAQ;AAAA,IAChB;AAAA,EACF;AACF;AAGO,SAAS,UAAU,OAAqD;AAC7E,SAAO,QAAQ,MAAM,WAAW,aAAa,aAAa,WAAW,MAAM,KAAK,CAAC;AACnF;AAKA,eAAe,oCAAoC,SAAuD;AACxG,MAAI;AACF,UAAM,OAAQ,QAAmD;AACjE,QAAI,OAAO,SAAS,WAAY,QAAO;AACvC,WAAO,MAAM,KAAK,KAAK,OAAO;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,kBAAkB,SAAwC;AACjE,SAAO,OAAO,MAAM,QAAQ;AAC1B,QAAI,QAAQ,aAAa,OAAO;AAC9B,aAAO,EAAE,OAAO,0DAA0D,OAAO,0CAA0C;AAAA,IAC7H;AACA,UAAM,OAAO,aAAa,UACrB,QAAyF,QAAQ,IAClG;AACJ,QAAI,CAAC,MAAM;AACT,aAAO,EAAE,OAAO,4CAA4C,OAAO,4BAA4B;AAAA,IACjG;AACA,SAAK;AACL,UAAM,MAAM,MAAM,KAAK,SAAS,IAAI;AACpC,WAAO,EAAE,OAAO,kBAAkB,GAAG,EAAE;AAAA,EACzC;AACF;AAGA,SAAS,yBAAyB,SAA0B,aAAgD;AAC1G,SAAO,OAAO,WAAW,QAAQ,QAAQ,8BAA8B,QAAkB,WAAW,CAAW;AACjH;AAGA,SAAS,+BAA+B,SAAqD;AAC3F,SAAO,OAAO,SAAS;AACrB,UAAM,OAAO,aAAa,UAAW,QAAuC,QAAQ,IAAI;AACxF,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,uDAAuD;AAClF,UAAM,MAAM,MAAM,OAAO,wBAAwB;AACjD,WAAO,IAAI,sBAAsB,MAAa,IAAI;AAAA,EACpD;AACF;AAKA,SAAS,6BAA6B,SAAmD;AACvF,SAAO,YAAY,oCAAoC,OAAO;AAChE;AAKO,SAAS,aAAa,MAAW,UAA8B;AACpE,SAAO;AAAA,IACL,QAAS,KAAK,SAAS,KAA4B,KAAK;AAAA,IACxD,MAAM,KAAK;AAAA,IACX;AAAA,IACA,KAAK,KAAK;AAAA,IACV,SAAS,KAAK;AAAA,IACd,OAAO,KAAK;AAAA,IACZ,MAAM,KAAK;AAAA,EACb;AACF;AA2DO,SAAS,qBAAqB,OAAmD;AACtF,QAAM,UAAU,MAAM;AACtB,SAAO;AAAA,IACL,SAAS,MAAM;AAAA,IACf,SAAS,MAAM;AAAA,IACf,UAAU,MAAM;AAAA,IAChB,OAAO,MAAM;AAAA,IACb,eAAe,MAAM;AAAA,IACrB,cAAc,MAAM;AAAA;AAAA,IAEpB,WAAW;AAAA,IACX,YAAY,MAAM;AAAA,IAClB,iBAAiB,MAAM;AAAA,IACvB,wBAAwB,MAAM;AAAA,IAC9B,kBAAkB,MAAM;AAAA,IACxB,oBAAoB,MAAM;AAAA,IAC1B,cAAc,MAAM;AAAA,IACpB,iBAAiB,MAAM;AAAA,IACvB,uBAAuB,MAAM;AAAA,IAC7B,eAAe,MAAM;AAAA,IAErB,cAAc,MAAM;AAAA,IACpB,eAAe,MAAM;AAAA,IACrB,gBAAgB,MAAM;AAAA,IAEtB,aAAa,MAAM;AAAA,IACnB,YAAY,MAAM;AAAA,IAClB,WAAW,MAAM;AAAA,IACjB,SAAS,MAAM;AAAA,IACf,eAAe,MAAM;AAAA;AAAA;AAAA,IAIrB,cAAc,SAAS;AAAA,IACvB,gBAAgB,MAAM;AAAA,IACtB,aAAa,SAAS;AAAA,IACtB,eAAe,iBAAiB,MAAM,WAAW;AAAA,IACjD,eAAe,SAAS;AAAA,IAExB,OAAO,kBAAkB,MAAM,OAAO;AAAA,IACtC,cAAc,yBAAyB,MAAM,SAAS,MAAM,WAAW;AAAA,IACvE,oBAAoB,aAAa,MAAM,WAAW,OAAO,MAAM,QAAQ,YAAY,aAC/E,+BAA+B,MAAM,OAAO,IAC5C;AAAA,IACJ,0BAA0B,6BAA6B,MAAM,OAAO;AAAA,IAEpE,gBAAgB,CAAC,SAAiB,8BAA8B,MAAM,MAAM,WAAW;AAAA,IACvF,aAAa,MAAM;AAAA,IACnB,gBAAgB,MAAM;AAAA,IAEtB,MAAM,MAAM;AAAA,IACZ,WAAW,MAAM;AAAA,IACjB,aAAa,MAAM;AAAA,IACnB,mBAAmB,MAAM;AAAA,IAEzB,oBAAoB,MAAM;AAAA,IAC1B,eAAe,MAAM;AAAA,IACrB,UAAU,MAAM;AAAA,IAChB,eAAe,MAAM;AAAA,IACrB,QAAQ,MAAM;AAAA,IACd,YAAY,MAAM;AAAA,IAClB,QAAQ,MAAM;AAAA,IACd,YAAY,MAAM;AAAA,IAClB,eAAe,MAAM;AAAA,IACrB,cAAc,MAAM;AAAA,IACpB,mBAAmB,CAAC,YAClB,WAAW,OAAO,IAAI,UAAU,QAAQ,QAAQ,MAAM,QAAQ,GAAG,OAAO;AAAA,EAC5E;AACF;;;AGjrBA,SAAS,kBAAkB;AAC3B,SAAS,WAAAA,gBAAe;AAOxB,SAAS,gBAAgB;AAoBlB,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C,YAAqB,OAAe;AAClC;AAAA,MACE,qCAAqC,KAAK,UAAU,KAAK,CAAC;AAAA,IAG5D;AALmB;AAMnB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAChD,YAAqB,OAAe;AAClC;AAAA,MACE,qCAAqC,KAAK,UAAU,KAAK,CAAC;AAAA,IAG5D;AALmB;AAMnB,SAAK,OAAO;AAAA,EACd;AACF;AAMA,SAAS,uBAAuB,OAIvB;AACP,MAAI,CAAC,MAAM,cAAc,MAAM,KAAK,EAAG,OAAM,IAAI,oBAAoB,MAAM,KAAK;AAChF,MAAI,WAAW,UAAU,EAAE,WAAW,MAAM,WAAW,OAAO,MAAM,MAAM,CAAC,CAAC,GAAG;AAC7E,UAAM,IAAI,uBAAuB,MAAM,KAAK;AAAA,EAC9C;AACF;AAmEO,SAAS,wBACd,SACiE;AACjE,QAAM,YAAYC,SAAQ,QAAQ,WAAW;AAE7C,SAAO;AAAA,IACL,MAAM,QAAQ,SAAoD;AAEhE,UAAI,QAAQ,UAAU,QAAW;AAC/B,+BAAuB;AAAA,UACrB;AAAA,UACA,OAAO,QAAQ;AAAA,UACf,eAAe,QAAQ;AAAA,QACzB,CAAC;AAAA,MACH;AACA,YAAM,QAAQ,QAAQ,SAAS,QAAQ,UAAU;AAIjD,YAAM,QAAQ,eAAe;AAG7B,YAAM,QAAQ,cAAc,EAAE,WAAW,MAAM,CAAC;AAEhD,YAAM,cAAc,QAAQ,cAAc,EAAE,OAAO,UAAU,CAAC;AAC9D,YAAM,YAAY,MAAM,QAAQ,YAAY;AAAA,QAC1C;AAAA,QACA;AAAA,QACA,kBAAkB,QAAQ;AAAA,QAC1B,OAAO;AAAA,UACL,GAAG;AAAA,UACH,GAAI,gBAAgB,SAAY,CAAC,IAAI,EAAE,YAAY;AAAA,QACrD;AAAA,QACA;AAAA,QACA,YAAY,QAAQ,cAAc,QAAQ;AAAA,MAC5C,CAAC;AAGD,YAAM,UAAU,SAAS;AAAA,QACvB,GAAG;AAAA,QACH;AAAA,QACA,GAAI,QAAQ,YAAY,OAAO,EAAE,SAAS,KAAc,IAAI,CAAC;AAAA,QAC7D,GAAI,QAAQ,yBAAyB,OACjC,EAAE,sBAAsB,KAAc,IACtC,CAAC;AAAA,MACP,CAAC;AAED,cAAQ,YAAY,OAAO;AAI3B,YAAM,QAAQ;AAEd,aAAO,EAAE,MAAsB;AAAA,IACjC;AAAA,EACF;AACF;;;AC3LA,SAAS,sBAAsB;AAE/B,SAAS,4BAA4B;;;ACFrC,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,YAAY;AAIrB,SAAS,2BAAAC,0BAAyB,eAAAC,cAAa,cAAAC,mBAAkB;AAGjE,IAAM,gBAAgB;AAoBtB,SAAS,mBAAmB,OAAsC,OAAwB;AAQxF,SAAOH,YAAW,KAAK,MAAM,aAAaE,cAAaC,YAAW,KAAK,CAAC,CAAC;AAC3E;AAEO,SAAS,mBACd,OACA,OACA,KACoB;AACpB,MAAI,CAAC,cAAc,KAAK,GAAG,EAAG,QAAO,EAAE,QAAQ,cAAc;AAC7D,MAAI,CAAC,mBAAmB,OAAO,KAAK,EAAG,QAAO,EAAE,QAAQ,cAAc;AACtE,QAAM,QAAQ,IAAIF,yBAAwB,EAAE,MAAM,MAAM,aAAa,MAAM,CAAC,EAAE,QAAQ,GAAG;AACzF,SAAO,UAAU,SAAY,EAAE,QAAQ,cAAc,IAAI,EAAE,QAAQ,SAAS,MAAM;AACpF;AAGO,SAAS,iBACd,OACA,OACA,KACsB;AACtB,MAAI,CAAC,cAAc,KAAK,GAAG,EAAG,QAAO;AACrC,MAAI,CAAC,mBAAmB,OAAO,KAAK,EAAG,QAAO;AAC9C,SAAO,IAAIA,yBAAwB,EAAE,MAAM,MAAM,aAAa,MAAM,CAAC,EAAE,QAAQ,GAAG,IAC9E,UACA;AACN;AAEO,SAAS,qBACd,OACA,OACA,KACkE;AAClE,MAAI,CAAC,cAAc,KAAK,GAAG,EAAG,QAAO,EAAE,QAAQ,cAAc;AAC7D,MAAI,CAAC,mBAAmB,OAAO,KAAK,EAAG,QAAO,EAAE,QAAQ,cAAc;AACtE,QAAM,aAAa,IAAIA,yBAAwB,EAAE,MAAM,MAAM,aAAa,MAAM,CAAC,EAAE,SAAS,GAAG;AAC/F,SAAO,eAAe,SAAY,EAAE,QAAQ,cAAc,IAAI,EAAE,QAAQ,SAAS,WAAW;AAC9F;AAEO,SAAS,sBACd,OACA,OACA,KACA,OACA,KACoB;AACpB,MAAI,CAAC,cAAc,KAAK,GAAG,EAAG,QAAO,EAAE,QAAQ,cAAc;AAC7D,MAAI,CAAC,mBAAmB,OAAO,KAAK,EAAG,QAAO,EAAE,QAAQ,cAAc;AACtE,QAAM,QAAQ,IAAIA,yBAAwB,EAAE,MAAM,MAAM,aAAa,MAAM,CAAC,EAAE,cAAc,KAAK,OAAO,GAAG;AAC3G,SAAO,UAAU,SAAY,EAAE,QAAQ,cAAc,IAAI,EAAE,QAAQ,SAAS,MAAM;AACpF;AAGO,SAAS,yBACd,OACwB;AACxB,SAAO;AAAA,IACL,MAAM,CAAC,OAAc,QACnB,QAAQ,QAAQ,mBAAmB,OAAO,OAAO,KAAK,GAAG,GAAG,CAAC;AAAA,IAC/D,KAAK,CAAC,OAAc,QAClB,QAAQ,QAAQ,iBAAiB,OAAO,OAAO,KAAK,GAAG,GAAG,CAAC;AAAA,IAC7D,MAAM,CAAC,OAAO,QAAQ,QAAQ,QAAQ,qBAAqB,OAAO,OAAO,KAAK,GAAG,GAAG,CAAC;AAAA,IACrF,WAAW,CAAC,OAAO,KAAK,OAAO,QAC7B,QAAQ,QAAQ,sBAAsB,OAAO,OAAO,KAAK,GAAG,KAAK,OAAO,GAAG,CAAC;AAAA,EAChF;AACF;AASO,SAAS,sBACd,OACA,OACA,KACwB;AACxB,QAAM,SAAS,mBAAmB,OAAO,OAAO,GAAG;AACnD,SAAO,OAAO,WAAW,UAAU,OAAO,QAAQ;AACpD;;;ACpHA,SAAS,cAAAG,mBAAkB;AAE3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAaA,SAAS,6BACd,OACmC;AACnC,QAAM,OAAO,MAAM,SAAS,MAAY;AAAA,EAAC;AACzC,QAAM,UAAUA,YAAW,MAAM,OAAO;AAExC,MAAI;AACJ,MAAI;AACF,WAAO,qBAAqB,MAAM,aAAa;AAAA,EACjD,SAAS,OAAO;AAGd;AAAA,MACE,GAAG,0BAA0B,uBAC3B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;AAAA,IACF;AACA,WAAO,CAAC;AAAA,EACV;AAEA,MAAI,KAAK,aAAa,SAAS,GAAG;AAGhC;AAAA,MACE,GAAG,0BAA0B,QAAQ,KAAK,aAAa,MAAM,8BAAyB,KAAK,aACxF,IAAI,CAAC,YAAY,QAAQ,QAAQ,UAAU,KAAK,QAAQ,MAAM,EAAE,EAChE,KAAK,IAAI,CAAC;AAAA,IACf;AAAA,EACF;AAEA,SAAO,0BAA0B,KAAK,QAAQ,MAAM,GAAG,EACpD,OAAO,CAAC,UAAU,MAAM,UAAU,iBAAiB,MAAM,YAAY,OAAO,EAC5E,IAAI,CAAC,WAAW;AAAA,IACf,SAAS,MAAM;AAAA,IACf,UAAU,MAAM;AAAA,IAChB,UAAU,MAAM;AAAA,IAChB,WAAW,MAAM;AAAA,EACnB,EAAE;AACN;;;AC1DA;AAAA,EACE;AAAA,EACA;AAAA,OACK;;;ACFP,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,cAAAC,aAAY,eAAAC,cAAa,gBAAAC,qBAAoB;AACtD,SAAS,qBAAqB;AAC9B,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAC9B,SAAS,gBAAAC,qBAAoB;AAE7B,SAAS,4BAA4B,kBAAkB,kCAAkC;AACzF;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AAsCP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,6BAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,wBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,uBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,wBAAwB;AAAA,EACxB;AAAA,OACK;AAYP,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA,cAAAC;AAAA,EAEA;AAAA,EACA,eAAAC;AAAA,EACA;AAAA,EACA,cAAAC;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA,WAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACrLP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA0BA,SAAS,0BACd,OACqB;AACrB,iBAAe,MAAM,WAA6C;AAChE,QAAI,MAAM,wBAAwB,UAAa,UAAU,WAAW,EAAG;AACvE,QAAI;AACF,YAAM,MAAM,oBAAoB,SAAS;AAAA,IAC3C,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AAAA;AAAA,IAEL,MAAM,aAAa,EAAE,YAAY,GAAG;AAClC,aAAO,gBAAgB;AAAA,QACrB,eAAe,MAAM,MAAM,qBAAqB;AAAA,QAChD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,MAAM,cAAc;AAClB,YAAM,OAAO,YAAY,MAAM,MAAM,qBAAqB,CAAC;AAC3D,YAAM,MAAM,KAAK,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC;AAC3C,aAAO;AAAA,IACT;AAAA,IACA,MAAM,eAAe,EAAE,OAAO,GAAG;AAC/B,YAAM,UAAU,eAAe;AAAA,QAC7B,eAAe,MAAM,MAAM,qBAAqB;AAAA,QAChD;AAAA,MACF,CAAC;AACD,YAAM,MAAM,QAAQ,IAAI,CAAC,WAAW,OAAO,QAAQ,CAAC;AACpD,aAAO;AAAA,IACT;AAAA,IACA,MAAM,UAAU,EAAE,aAAa,GAAG;AAChC,YAAM,UAAU,UAAU;AAAA,QACxB,eAAe,MAAM,MAAM,qBAAqB;AAAA,QAChD;AAAA,MACF,CAAC;AAKD,YAAM,MAAM,QAAQ,IAAI,CAAC,WAAW,OAAO,QAAQ,CAAC;AACpD,aAAO;AAAA,IACT;AAAA,IACA,MAAM,WAAW,EAAE,SAAS,GAAG;AAC7B,YAAM,SAAS,WAAW;AAAA,QACxB,eAAe,MAAM,MAAM,qBAAqB;AAAA,QAChD;AAAA,MACF,CAAC;AACD,YAAM,MAAM,OAAO,SAAS,UAAU,CAAC,OAAO,OAAO,QAAQ,IAAI,CAAC,CAAC;AACnE,aAAO;AAAA,IACT;AAAA;AAAA;AAAA,IAGA,MAAM,YAAY,EAAE,UAAU,GAAG;AAC/B,aAAO,YAAY,EAAE,eAAe,MAAM,MAAM,qBAAqB,GAAG,UAAU,CAAC;AAAA,IACrF;AAAA;AAAA,IAEA,MAAM,mBAAmB,EAAE,OAAO,OAAO,GAAG;AAC1C,aAAO,sBAAsB;AAAA,QAC3B,eAAe,MAAM,MAAM,qBAAqB;AAAA,QAChD;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ACrGA,SAAS,WAAW,WAAW,UAAU,YAAY,QAAQ,qBAAqB;AAClF,SAAS,kBAAkB;AAC3B,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAE9B,SAAS,qBAAqB;AAI9B,IAAM,wBAAwB;AAE9B,SAAS,UAAU,MAAoB;AACrC,QAAM,KAAK,SAAS,MAAM,GAAG;AAC7B,MAAI;AACF,cAAU,EAAE;AAAA,EACd,UAAE;AACA,cAAU,EAAE;AAAA,EACd;AACF;AAGO,SAAS,sBAAsB,MAAc,UAAqC;AACvF,QAAM,MAAMD,SAAQ,IAAI;AACxB,QAAM,SAASC,MAAK,KAAK,IAAI,qBAAqB,IAAI,WAAW,CAAC,MAAM;AACxE,MAAI;AACF,kBAAc,QAAQ,GAAG,cAAc,QAAQ,CAAC;AAAA,GAAM,EAAE,UAAU,QAAQ,MAAM,IAAM,CAAC;AACvF,cAAU,MAAM;AAChB,eAAW,QAAQ,IAAI;AACvB,cAAU,GAAG;AAAA,EACf,UAAE;AACA,WAAO,QAAQ,EAAE,OAAO,KAAK,CAAC;AAAA,EAChC;AACF;;;AC/BA;AAAA,EACE,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,YAAAC;AAAA,EACA;AAAA,EACA,gBAAAC;AAAA,EACA;AAAA,EACA,iBAAAC;AAAA,OACK;AACP,SAAS,cAAAC,aAAY,QAAAC,aAAY;AAEjC,SAAS,qBAAqB;AAC9B,SAAS,2CAA2C;;;ACbpD,SAAS,cAAAC,mBAAkB;AAC3B;AAAA,EACE,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA;AAAA,EACA,YAAAC;AAAA,EACA;AAAA,EACA,cAAAC;AAAA,EACA,UAAAC;AAAA,EACA,iBAAAC;AAAA,OACK;AACP,SAAS,WAAAC,UAAS,cAAAC,aAAY,QAAAC,aAAY;AAE1C;AAAA,EACE,iBAAAC;AAAA,EACA;AAAA,EACA,iCAAAC;AAAA,EACA;AAAA,OACK;;;AClBP,SAAS,qCAAqC;AAM9C,SAAS,4BAA4B,+BAA+B;AAG7D,IAAM,6BAAN,cAAyC,MAAM;AAAA,EAGpD,YACW,MACA,iBACA,iBACT;AACA;AAAA,MACE,0BAA0B,IAAI,iCAAiC,eAAe,kCAChD,eAAe;AAAA,IAG/C;AATS;AACA;AACA;AAAA,EAQX;AAAA,EAbkB,OAAO;AAc3B;AAGO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAG5C,YAAqB,OAAe;AAClC,UAAM,4BAA4B,KAAK,EAAE;AADtB;AAAA,EAErB;AAAA,EAJkB,OAAO;AAK3B;AAGO,IAAM,8BAAN,cAA0C,MAAM;AAAA,EAGrD,YACW,OACA,OACT;AACA;AAAA,MACE,YAAY,KAAK,2BAA2B,KAAK,UAAU,KAAK,CAAC;AAAA,IAGnE;AAPS;AACA;AAAA,EAOX;AAAA,EAXkB,OAAO;AAY3B;AAGO,IAAM,kCAAN,cAA8C,MAAM;AAAA,EAGzD,YACW,MACA,iBACT;AACA;AAAA,MACE,wBAAwB,IAAI,kCAAkC,OAAO,eAAe,CAAC,kCACnD,6BAA6B;AAAA,IAEjE;AAPS;AACA;AAAA,EAOX;AAAA,EAXkB,OAAO;AAY3B;;;ADtCO,IAAM,wBAAwB,CAAC,cAAc,aAAa;AAQjE,IAAM,oBAAoB;AAGnB,IAAM,kCAAkC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAqBO,IAAM,yBAA0C,OAAO,OAAO;AAAA,EACnE;AAAA,EACA,UAAAC;AAAA,EACA,eAAAC;AAAA,EACA,WAAAC;AAAA,EACA,WAAAC;AAAA,EACA,YAAAC;AAAA,EACA,QAAAC;AAAA,EACA;AACF,CAAC;AAwBD,SAAS,eAAe,OAAiC,OAAuB;AAC9E,MAAI,CAAC,kBAAkB,KAAK,KAAK,GAAG;AAClC,UAAM,IAAI,4BAA4B,OAAO,KAAK;AAAA,EACpD;AACA,SAAO;AACT;AAEA,SAAS,eAAe,MAAc,OAAe,cAA8B;AACjF,MAAI,CAACC,YAAW,IAAI,EAAG,OAAM,IAAI,UAAU,4CAA4C;AACvF,SAAOC;AAAA,IAAK;AAAA,IAAM,GAAG;AAAA,IAAuB,eAAe,SAAS,KAAK;AAAA,IACvE,GAAG,eAAe,gBAAgB,YAAY,CAAC;AAAA,EAAO;AAC1D;AAEA,SAAS,eACP,IACA,MACA,OACA,cACqE;AACrE,QAAM,OAAO,eAAe,MAAM,OAAO,YAAY;AACrD,MAAI;AACJ,MAAI;AACF,WAAO,GAAG,aAAa,MAAM,MAAM;AAAA,EACrC,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,SAAU,QAAO,EAAE,OAAO,MAAM;AAC9E,UAAM;AAAA,EACR;AACA,QAAM,MAAM,KAAK,MAAM,IAAI;AAE3B,MAAI,KAAK,kBAAkBC,gCAA+B;AACxD,UAAM,IAAI,gCAAgC,MAAM,KAAK,aAAa;AAAA,EACpE;AACA,QAAM,WAAW,4BAA4B,MAAM,GAAG;AACtD,MAAI,SAAS,UAAU,SAAS,SAAS,iBAAiB,cAAc;AACtE,UAAM,IAAI,UAAU,0DAA0D;AAAA,EAChF;AACA,SAAO,EAAE,OAAO,MAAM,SAAS;AACjC;AAGO,SAAS,0BACd,SACA,OACA,cACqE;AACrE,SAAO,eAAe,wBAAwB,QAAQ,MAAM,OAAO,YAAY;AACjF;AAEA,SAAS,iCAAiC,OAAyB;AACjE,QAAM,OAAQ,MAAgC;AAC9C,SAAO,gCAAgC,KAAK,CAAC,YAAY,YAAY,IAAI;AAC3E;AAEO,SAAS,yBACd,SACoB;AACpB,SAAO,2BAA2B,wBAAwB,OAAO;AACnE;AAUO,SAAS,2BACd,IACA,SACoB;AACpB,MAAI,CAACF,YAAW,QAAQ,IAAI,GAAG;AAC7B,UAAM,IAAI,UAAU,4CAA4C;AAAA,EAClE;AAEA,QAAM,kBAAkBC,MAAK,QAAQ,MAAM,GAAG,qBAAqB;AAEnE,WAAS,QAAQ,OAAe,cAA8B;AAC5D,WAAO,eAAe,QAAQ,MAAM,OAAO,YAAY;AAAA,EACzD;AAEA,WAAS,yBAAyB,KAAmB;AACnD,QAAI;AACJ,QAAI;AACF,WAAK,GAAG,SAAS,KAAK,GAAG;AACzB,SAAG,UAAU,EAAE;AAAA,IACjB,SAAS,OAAO;AACd,UAAI,CAAC,iCAAiC,KAAK,GAAG;AAC5C,cAAM;AAAA,MACR;AAAA,IACF,UAAE;AACA,UAAI,OAAO,OAAW,IAAG,UAAU,EAAE;AAAA,IACvC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,gBAAgB;AAAA,IAEhB,QAAQ,OAAO,cAAc,SAAS;AACpC,YAAM,OAAO,QAAQ,OAAO,YAAY;AAExC,YAAM,WAAkC;AAAA,QACtC,eAAeC;AAAA,QACf,OAAO,QAAQ,KAAK;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AACA,SAAG,UAAUC,SAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC/C,YAAM,YAAY,GAAG,IAAI,QAAQC,YAAW,CAAC;AAC7C,UAAI;AACJ,UAAI;AAIF,aAAK,GAAG,SAAS,WAAW,IAAI;AAChC,WAAG,cAAc,IAAI,GAAGC,eAAc,QAAQ,CAAC;AAAA,GAAM,MAAM;AAC3D,WAAG,UAAU,EAAE;AACf,WAAG,UAAU,EAAE;AACf,aAAK;AACL,WAAG,WAAW,WAAW,IAAI;AAE7B,iCAAyBF,SAAQ,IAAI,CAAC;AAAA,MACxC,UAAE;AACA,YAAI,OAAO,OAAW,IAAG,UAAU,EAAE;AACrC,WAAG,OAAO,WAAW,EAAE,OAAO,KAAK,CAAC;AAAA,MACtC;AAAA,IACF;AAAA,IAEA,QAAQ,OAAO,cAAc;AAG3B,SAAG,OAAO,QAAQ,OAAO,YAAY,GAAG,EAAE,OAAO,KAAK,CAAC;AAAA,IACzD;AAAA,IAEA,KAAK,OAAO,cAAc;AACxB,YAAM,OAAO,eAAe,IAAI,QAAQ,MAAM,OAAO,YAAY;AACjE,aAAO,KAAK,QAAQ,EAAE,OAAO,MAAM,SAAS,KAAK,SAAS,QAAQ,IAAI;AAAA,IACxE;AAAA,EACF;AACF;;;ADrNO,IAAM,uBAAuB;AAGpC,IAAM,sBAAsB;AAErB,IAAM,gCAAgC,KAAK;AAQlD,IAAMG,qBAAoB;AAGnB,IAAM,4BAAN,cAAwC,MAAM;AAAA,EAGnD,YAAqB,WAAmB;AACtC;AAAA,MACE,GAAG,KAAK,UAAU,SAAS,CAAC;AAAA,IAE9B;AAJmB;AAAA,EAKrB;AAAA,EAPkB,OAAO;AAQ3B;AAGO,IAAM,0BAAN,cAAsC,MAAM;AAAA,EAGjD,YAAqB,WAAmB;AACtC,UAAM,mBAAmB,SAAS,4CAA4C;AAD3D;AAAA,EAErB;AAAA,EAJkB,OAAO;AAK3B;AAGO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAG9C,YAAqB,WAAmB;AACtC;AAAA,MACE,gBAAgB,SAAS;AAAA,IAE3B;AAJmB;AAAA,EAKrB;AAAA,EAPkB,OAAO;AAQ3B;AAGO,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAGhD,YACW,WACA,QACT;AACA,UAAM,wBAAwB,SAAS,oBAAoB,MAAM,GAAG;AAH3D;AACA;AAAA,EAGX;AAAA,EAPkB,OAAO;AAQ3B;AAkCO,IAAM,uBAAsC,OAAO,OAAO;AAAA,EAC/D,WAAAC;AAAA,EACA,UAAAC;AAAA,EACA,eAAAC;AAAA,EACA,WAAAC;AAAA,EACA,WAAAC;AAAA,EACA;AAAA,EACA,cAAAC;AAAA,EACA;AACF,CAAC;AA0DM,SAAS,kBAAkB,QAAgB,QAA8B;AAC9E,QAAM,QAAQ,OAAO,QAAQ,SAAS,EAAE,EAAE,QAAQ,WAAW,GAAG,EAAE,QAAQ,KAAK,GAAG,EAAE,QAAQ,KAAK,EAAE;AACnG,QAAM,SAAS,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,EACzC,SAAS,EAAE,EACX,SAAS,GAAG,GAAG;AAClB,SAAO,QAAQ,KAAK,IAAI,MAAM;AAChC;AAEA,SAAS,iBAAiB,WAA2B;AACnD,MAAI,CAACN,mBAAkB,KAAK,SAAS,EAAG,OAAM,IAAI,0BAA0B,SAAS;AACrF,SAAO;AACT;AAEA,SAASO,kCAAiC,OAAyB;AACjE,QAAM,OAAQ,MAAgC;AAC9C,SAAO,gCAAgC,KAAK,CAAC,YAAY,YAAY,IAAI;AAC3E;AASA,SAAS,YAAY,WAAmB,MAAiC;AACvE,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,IAAI;AAAA,EAC1B,QAAQ;AACN,UAAM,IAAI,uBAAuB,WAAW,4BAA4B;AAAA,EAC1E;AACA,MAAI,WAAW,QAAQ,OAAO,WAAW,UAAU;AACjD,UAAM,IAAI,uBAAuB,WAAW,kCAAkC;AAAA,EAChF;AACA,QAAM,SAAS;AACf,MAAI,OAAO,kBAAkB,qCAAqC;AAChE,UAAM,IAAI;AAAA,MACR;AAAA,MACA,6BAA6B,OAAO,OAAO,aAAa,CAAC,2BACvD,OAAO,mCAAmC;AAAA,IAC9C;AAAA,EACF;AACA,MAAI,OAAO,cAAc,WAAW;AAClC,UAAM,IAAI;AAAA,MACR;AAAA,MACA,4BAA4B,OAAO,OAAO,SAAS,CAAC;AAAA,IACtD;AAAA,EACF;AACA,MAAI,OAAO,OAAO,cAAc,YAAY,OAAO,OAAO,UAAU,UAAU;AAC5E,UAAM,IAAI,uBAAuB,WAAW,+CAA+C;AAAA,EAC7F;AAEA,MAAI,OAAO,YAAY,UAAa,OAAO,OAAO,YAAY,UAAU;AACtE,UAAM,IAAI;AAAA,MACR;AAAA,MACA,sCAAsC,OAAO,OAAO,OAAO;AAAA,IAC7D;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,aAAa,MAAkC;AAC7D,MAAI,CAACC,YAAW,IAAI,EAAG,OAAM,IAAI,UAAU,wCAAwC;AACnF,QAAM,KAAK;AACX,QAAM,eAAeC,MAAK,MAAM,oBAAoB;AAEpD,MAAI;AACJ,MAAI;AACF,YAAQ,GAAG,YAAY,YAAY;AAAA,EACrC,SAAS,OAAO;AAGd,QAAK,MAAgC,SAAS,SAAU,QAAO,EAAE,UAAU,CAAC,GAAG,SAAS,CAAC,EAAE;AAC3F,UAAM;AAAA,EACR;AAEA,QAAM,WAAmC,CAAC;AAC1C,QAAM,UAAoC,CAAC;AAE3C,aAAW,QAAQ,CAAC,GAAG,KAAK,EAAE,KAAK,GAAG;AACpC,QAAI,CAAC,KAAK,SAAS,mBAAmB,EAAG;AACzC,UAAM,YAAY,KAAK,MAAM,GAAG,CAAC,oBAAoB,MAAM;AAC3D,QAAI;AACF,YAAM,UAAU,gBAAgB,IAAIA,MAAK,cAAc,IAAI,CAAC;AAC5D,UAAI,QAAQ,eAAe,QAAW;AACpC,gBAAQ,KAAK,EAAE,MAAM,QAAQ,qCAAqC,CAAC;AACnE;AAAA,MACF;AACA,YAAM,SAAS,YAAY,WAAW,QAAQ,UAAU;AACxD,eAAS,KAAK;AAAA,QACZ,WAAW,OAAO;AAAA,QAClB,WAAW,OAAO;AAAA,QAClB,OAAO,OAAO;AAAA,QACd,YAAY,KAAK,IAAI,QAAQ,YAAY,GAAG,CAAC;AAAA,MAC/C,CAAC;AAAA,IACH,SAAS,OAAO;AACd,cAAQ,KAAK,EAAE,MAAM,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;AAAA,IACvF;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,QAAQ;AAC7B;AASA,SAAS,gBACP,IACA,MACuD;AACvD,QAAM,KAAK,GAAG,SAAS,MAAM,GAAG;AAChC,MAAI;AACF,UAAM,SAAS,OAAO,YAAY,6BAA6B;AAC/D,QAAI;AACJ,QAAI,cAAc;AAClB,QAAI,YAAY;AAChB,QAAI,OAAO,GAAG,SAAS,IAAI,QAAQ,GAAG,OAAO,QAAQ,IAAI;AACzD,WAAO,OAAO,GAAG;AACf,YAAM,QAAQ,OAAO,SAAS,GAAG,IAAI;AACrC,eAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,YAAI,MAAM,KAAK,MAAM,GAAM,cAAa;AAAA,MAC1C;AACA,UAAI,eAAe,QAAW;AAC5B,uBAAe,MAAM,SAAS,MAAM;AACpC,cAAM,UAAU,YAAY,QAAQ,IAAI;AACxC,YAAI,WAAW,EAAG,cAAa,YAAY,MAAM,GAAG,OAAO;AAAA,iBAGlD,YAAY,SAAS,8BAA+B;AAAA,MAC/D;AACA,aAAO,GAAG,SAAS,IAAI,QAAQ,GAAG,OAAO,QAAQ,IAAI;AAAA,IACvD;AACA,WAAO,EAAE,YAAY,UAAU;AAAA,EACjC,UAAE;AACA,OAAG,UAAU,EAAE;AAAA,EACjB;AACF;AAEO,SAAS,sBAAsB,SAAuD;AAC3F,SAAO,wBAAwB,sBAAsB,OAAO;AAC9D;AAWO,SAAS,wBACd,IACA,SACgB;AAChB,MAAI,CAACD,YAAW,QAAQ,IAAI,GAAG;AAC7B,UAAM,IAAI,UAAU,wCAAwC;AAAA,EAC9D;AACA,QAAM,eAAeC,MAAK,QAAQ,MAAM,oBAAoB;AAC5D,QAAM,SAAS,QAAQ,UAAU,KAAK;AAGtC,QAAM,kBAAkB,oBAAI,IAAoB;AAEhD,WAAS,QAAQ,WAA2B;AAC1C,WAAOA,MAAK,cAAc,GAAG,SAAS,QAAQ;AAAA,EAChD;AAEA,WAAS,yBAAyB,KAAmB;AACnD,QAAI;AACJ,QAAI;AACF,oBAAc,GAAG,SAAS,KAAK,GAAG;AAClC,SAAG,UAAU,WAAW;AAAA,IAC1B,SAAS,OAAO;AACd,UAAI,CAACF,kCAAiC,KAAK,EAAG,OAAM;AAAA,IACtD,UAAE;AACA,UAAI,gBAAgB,OAAW,IAAG,UAAU,WAAW;AAAA,IACzD;AAAA,EACF;AAEA,WAAS,UACP,WACoF;AACpF,QAAI;AACJ,QAAI;AACF,aAAO,GAAG,aAAa,QAAQ,SAAS,GAAG,MAAM;AAAA,IACnD,SAAS,OAAO;AACd,UAAK,MAAgC,SAAS,SAAU,QAAO;AAC/D,YAAM;AAAA,IACR;AACA,WAAO;AAAA;AAAA;AAAA,MAGL,OAAO,KACJ,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,WAAW,EAAE,YAAY,QAAQ,GAAG,MAAM,KAAK,EAAE,EAC5D,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE;AAAA;AAAA;AAAA;AAAA,MAIpC,YAAY,SAAS,MAAM,KAAK,SAAS,IAAI;AAAA,IAC/C;AAAA,EACF;AAEA,WAAS,WAAW,QAAgB,OAA+B;AAIjE,OAAG,cAAc,QAAQ,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,GAAM,MAAM;AAAA,EAC/D;AASA,WAAS,UACP,IACA,IACA,QACmB;AACnB,QAAI,OAAO;AACX,UAAM,cAAc,CAAC,SAAuB;AAC1C,UAAI,CAAC,MAAM;AACT,cAAM,IAAI;AAAA,UACR,kBAAkB,IAAI,0CAA0C,EAAE;AAAA,QAEpE;AAAA,MACF;AAAA,IACF;AACA,UAAM,SAA4B;AAAA,MAChC,QAAQ,OAAO;AAAA,MACf,QAAQ,OAAO;AAAA,MACf,cAAc,OAAO;AAAA,MACrB,OAAO,OAAwC;AAC7C,oBAAY,OAAO;AACnB,mBAAW,IAAI,KAAK;AACpB,eAAO,QAAQ,QAAQ;AAAA,MACzB;AAAA,MACA,eAA8B;AAI5B,oBAAY,eAAe;AAC3B,WAAG,UAAU,EAAE;AACf,eAAO,QAAQ,QAAQ;AAAA,MACzB;AAAA,MACA,QAAuB;AAErB,YAAI,MAAM;AACR,iBAAO;AACP,0BAAgB,OAAO,EAAE;AACzB,aAAG,UAAU,EAAE;AAAA,QACjB;AACA,eAAO,QAAQ,QAAQ;AAAA,MACzB;AAAA,IACF;AACA,oBAAgB,IAAI,IAAI,EAAE;AAC1B,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,KAAK,WAAgD;AACnD,SAAG,UAAU,cAAc,EAAE,WAAW,KAAK,CAAC;AAE9C,UAAI,cAAc,QAAW;AAC3B,cAAMG,MAAK,iBAAiB,SAAS;AAGrC,YAAI,gBAAgB,IAAIA,GAAE,EAAG,OAAM,IAAI,qBAAqBA,GAAE;AAC9D,cAAM,OAAO,UAAUA,GAAE;AAEzB,YAAI,SAAS,UAAa,KAAK,MAAM,WAAW,EAAG,OAAM,IAAI,wBAAwBA,GAAE;AACvF,cAAMC,UAAS,YAAYD,KAAI,KAAK,MAAM,CAAC,EAAG,IAAI;AAElD,cAAM,SAAS,cAAc,KAAK,MAAM,MAAM,CAAC,GAAG;AAAA,UAChD,iBAAiBC,QAAO;AAAA,UACxB,KAAK,QAAQ;AAAA,QACf,CAAC;AACD,cAAM,UAAU,GAAG,SAAS,QAAQD,GAAE,GAAG,GAAG;AAO5C,YAAI,oBAAoB;AACxB,YAAI,CAAC,KAAK,YAAY;AACpB,aAAG,cAAc,SAAS,MAAM,MAAM;AACtC,8BAAoB;AAAA,QACtB;AACA,mBAAW,SAAS,OAAO,aAAa;AACtC,qBAAW,SAAS,KAAK;AACzB,8BAAoB;AAAA,QACtB;AACA,YAAI,mBAAmB;AAIrB,aAAG,UAAU,OAAO;AAAA,QACtB;AACA,eAAO,QAAQ;AAAA,UACb,UAAUA,KAAI,SAAS;AAAA,YACrB,QAAAC;AAAA,YACA,QAAQ,OAAO;AAAA,YACf,cAAc,OAAO;AAAA,UACvB,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,YAAY,QAAQ,IAAI;AAC9B,YAAM,KAAK,kBAAkB,WAAW,MAAM;AAC9C,YAAM,SAA4B;AAAA,QAChC,eAAe;AAAA,QACf,WAAW;AAAA,QACX;AAAA,QACA,OAAO,QAAQ,MAAM;AAAA,QACrB,aAAa,QAAQ,YAAY;AAAA;AAAA,QAEjC,GAAI,QAAQ,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;AAAA,MACtE;AAIA,YAAM,UAAU,GAAG,SAAS,QAAQ,EAAE,GAAG,IAAI;AAC7C,UAAI;AACF,WAAG,cAAc,SAAS,GAAG,KAAK,UAAU,MAAM,CAAC;AAAA,GAAM,MAAM;AAC/D,WAAG,UAAU,OAAO;AAAA,MACtB,UAAE;AACA,WAAG,UAAU,OAAO;AAAA,MACtB;AACA,+BAAyB,YAAY;AACrC,YAAM,WAAW,GAAG,SAAS,QAAQ,EAAE,GAAG,GAAG;AAC7C,aAAO,QAAQ,QAAQ,UAAU,IAAI,UAAU,EAAE,QAAQ,QAAQ,CAAC,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;AAAA,IAC1F;AAAA,EACF;AACF;;;AGhhBA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,aAAY;AACrB,SAAS,gBAAAC,qBAAoB;AAE7B,SAAS,iBAAAC,gBAAe,wBAAwB,wBAAAC,uBAAsB,aAAAC,YAAW,aAAAC,kBAAiB;;;ACJlG,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,WAAAC,gBAAe;AACxB,SAAS,gBAAAC,qBAAoB;AAE7B;AAAA,EACE;AAAA,EACA;AAAA,EACA,8BAAAC;AAAA,EACA,2BAAAC;AAAA,OACK;AAmBP;AAAA,EACE,iBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAAC;AAAA,OACK;;;AClCP,SAAS,eAAAC,cAAa,gBAAAC,qBAAoB;AAC1C,SAAS,QAAAC,OAAM,UAAU,WAAW;AAEpC,OAA6B;AAE7B,SAAS,iBAAAC,gBAAe,iBAAiB;AAGzC,IAAM,kBAAkB;AAoBxB,SAAS,kBAAkB,OAAuB;AAChD,MAAI,CAAC,gBAAgB,KAAK,KAAK,GAAG;AAChC,UAAM,IAAI,UAAU,iDAAiD,KAAK,UAAU,KAAK,CAAC,EAAE;AAAA,EAC9F;AACA,SAAO;AACT;AAGO,SAAS,iBAAiB,OAAe,SAAoC;AAClF,MAAI,QAAQ,WAAW,GAAG;AACxB,UAAM,IAAI,UAAU,SAAS,KAAK,gDAAgD;AAAA,EACpF;AACA,QAAM,QAAQ,QAAQ,IAAI,CAAC,WAAW,IAAI,kBAAkB,MAAM,CAAC,OAAO,EAAE,KAAK,IAAI;AACrF,SAAO,kBAAkB,kBAAkB,KAAK,CAAC,cAAc,KAAK;AACtE;AAEO,SAAS,gBAAgB,IAA4B;AAC1D,SAAO,GACJ;AAAA,IACC;AAAA;AAAA;AAAA,EAGF,EACC,IAAI,EACJ,IAAI,CAAC,QAAQ,OAAO,IAAI,IAAI,CAAC;AAClC;AAEO,SAAS,aAAa,IAAkB,OAAyB;AACtE,SAAO,GACJ,QAAQ,sBAAsB,kBAAkB,KAAK,CAAC,IAAI,EAC1D,IAAI,EACJ,IAAI,CAAC,QAAQ,OAAO,IAAI,IAAI,CAAC;AAClC;AAQA,SAAS,UAAU,OAAyB;AAC1C,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK;AAClD,MAAI,iBAAiB,WAAY,QAAO,EAAE,QAAQ,OAAO,KAAK,KAAK,EAAE,SAAS,KAAK,EAAE;AACrF,SAAO;AACT;AAEO,SAAS,kBAAkB,IAAkB,OAAiC;AACnF,QAAM,UAAU,aAAa,IAAI,KAAK;AACtC,QAAM,OAAO,GACV,QAAQ,iBAAiB,OAAO,OAAO,CAAC,EACxC,IAAI,EACJ,IAAI,CAAC,QAAQ;AACZ,UAAM,aAAsC,CAAC;AAC7C,eAAW,UAAU,QAAS,YAAW,MAAM,IAAI,UAAU,IAAI,MAAM,CAAC;AACxE,WAAO;AAAA,EACT,CAAC;AACH,SAAO,EAAE,OAAO,SAAS,SAAS,KAAK;AACzC;AAUO,SAAS,kBAAkB,iBAAkD;AAClF,QAAM,QAAiC,CAAC;AAExC,WAAS,KAAK,KAAmB;AAC/B,QAAI;AACJ,QAAI;AACF,gBAAUH,aAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,IACpD,SAAS,OAAO;AACd,UAAK,MAAgC,SAAS,SAAU;AACxD,YAAM;AAAA,IACR;AACA,eAAW,SAAS,SAAS;AAC3B,YAAM,OAAOE,MAAK,KAAK,MAAM,IAAI;AACjC,UAAI,MAAM,YAAY,GAAG;AACvB,aAAK,IAAI;AACT;AAAA,MACF;AACA,YAAM,KAAK;AAAA,QACT,MAAM,SAAS,iBAAiB,IAAI,EAAE,MAAM,GAAG,EAAE,KAAK,GAAG;AAAA,QACzD,QAAQ,UAAUD,cAAa,MAAM,MAAM,CAAC;AAAA,MAC9C,CAAC;AAAA,IACH;AAAA,EACF;AAEA,OAAK,eAAe;AACpB,SAAO,MAAM,KAAK,CAAC,MAAM,UAAW,KAAK,OAAO,MAAM,OAAO,KAAK,KAAK,OAAO,MAAM,OAAO,IAAI,CAAE;AACnG;AAQO,SAAS,kBAAkB,OAA4C;AAC5E,SAAO;AAAA,IACL,eAAe,MAAM;AAAA,IACrB,QAAQ,gBAAgB,MAAM,EAAE,EAAE,IAAI,CAAC,UAAU,kBAAkB,MAAM,IAAI,KAAK,CAAC;AAAA,IACnF,aAAa,kBAAkB,MAAM,eAAe;AAAA,EACtD;AACF;AAGO,SAAS,qBAAqB,MAA2B;AAC9D,SAAOE,eAAc,IAAI;AAC3B;;;AD3FO,IAAM,+BAA+B;AAGrC,IAAM,kCAAkC;AAGxC,IAAM,0BAA0B;AAqCvC,IAAM,oBAAoB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA;AAAA;AAAA,EAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA;AAEF;AAGA,IAAM,wBAA8C,CAAC,QAAQ,UAAU,WAAW;AAGlF,IAAM,6BAAgD;AAG/C,IAAM,qCACX;AAaF,IAAM,wBAAwB;AAG9B,SAAS,oBAAoB,KAAuC;AAClE,SAAO,CAAC,UAAU,OAAO,IAAI,IAAI,CAAC;AACpC;AAGA,SAAS,uBAAuB,KAA6D;AAC3F,MAAI,CAAC,oBAAoB,GAAG,EAAG,QAAO;AACtC,MAAI,OAAO,IAAI,MAAM,MAAM,SAAU,QAAO;AAC5C,MAAI,OAAO,IAAI,iBAAiB,MAAM,YAAa,QAAO;AAC1D,MAAI,OAAO,IAAI,mBAAmB,MAAM,mCAAoC,QAAO;AACnF,SAAO;AACT;AAaA,SAAS,qBAAqB,SAAsC;AAClE,QAAM,SAAS,KAAK,MAAM,OAAO,OAAO,CAAC;AACzC,MAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,EAAG,QAAO;AACnF,QAAM,QAAS,OAA+B;AAC9C,SAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AAC7D;AAEA,SAAS,SAAS,OAAwB;AACxC,SAAO,OAAO,UAAU,WAAW,OAAO,KAAK,IAAI,OAAO,KAAK;AACjE;AAEO,SAAS,qBAAqB,SAAsD;AACzF,QAAM,EAAE,OAAO,aAAa,MAAM,IAAI;AAEtC,EAAAC,WAAUC,SAAQ,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACpD,QAAM,KAAK,IAAIC,cAAa,QAAQ,MAAM;AAAA,IACxC,SAAS,QAAQ,aAAa;AAAA,EAChC,CAAC;AACD,KAAG,KAAK,yBAAyB;AAKjC,QAAM,iBAAiB,SAAS,GAAG,QAAQ,qBAAqB,EAAE,IAAI,GAAG,YAAY;AACrF,MAAI,mBAAmB,KAAK,mBAAmB,8BAA8B;AAC3E,OAAG,MAAM;AACT,UAAM,IAAI;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,aAAW,aAAa,kBAAmB,IAAG,KAAK,SAAS;AAC5D,MAAI,mBAAmB,GAAG;AACxB,OAAG,KAAK,uBAAuB,4BAA4B,EAAE;AAAA,EAC/D;AAEA,QAAM,YAAY,GAAG;AAAA,IACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMF;AACA,QAAM,cAAc,GAAG,QAAQ,2DAA2D;AAC1F,QAAM,aAAa,GAAG,QAAQ,iCAAiC;AAC/D,QAAM,kBAAkB,GAAG;AAAA,IACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKF;AAEA,QAAM,2BAA2B,oBAAI,IAA2C;AAChF,WAAS,sBAAsB,eAAsD;AACnF,UAAM,SAAS,yBAAyB,IAAI,aAAa;AACzD,QAAI,WAAW,OAAW,QAAO;AACjC,UAAM,eAAe,MAAM,KAAK,EAAE,QAAQ,cAAc,GAAG,MAAM,GAAG,EAAE,KAAK,IAAI;AAC/E,UAAM,WAAW,GAAG;AAAA,MAClB;AAAA;AAAA,wEAEkE,YAAY;AAAA;AAAA;AAAA,IAGhF;AACA,6BAAyB,IAAI,eAAe,QAAQ;AACpD,WAAO;AAAA,EACT;AAGA,QAAM,cAAc,GAAG;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA,EAIF;AACA,QAAM,WAAW,GAAG;AAAA,IAClB;AAAA,EACF;AAEA,QAAM,kBAAkB,GAAG;AAAA,IACzB;AAAA;AAAA;AAAA;AAAA,EAIF;AACA,QAAM,WAAW,GAAG,QAAQ,6CAA6C;AAEzE,QAAM,gBAAgB,GAAG;AAAA,IACvB;AAAA;AAAA;AAAA;AAAA,EAIF;AAGA,QAAM,kBAAkB,GAAG;AAAA,IACzB;AAAA;AAAA;AAAA,EAGF;AACA,QAAM,aAAa,GAAG;AAAA,IACpB;AAAA;AAAA;AAAA;AAAA,EAIF;AAEA,QAAM,mBAAmB,GAAG;AAAA,IAC1B;AAAA;AAAA;AAAA,EAGF;AACA,QAAM,sBAAsB,GAAG;AAAA,IAC7B;AAAA,EACF;AACA,QAAM,qBAAqB,GAAG;AAAA,IAC5B;AAAA;AAAA;AAAA,EAGF;AAEA,QAAM,eAAe,GAAG;AAAA,IACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKF;AAGA,QAAM,4BAA4B,GAAG;AAAA,IACnC;AAAA,EACF;AACA,QAAM,0BAA0B,GAAG,QAAQ,8CAA8C;AACzF,QAAM,cAAc,GAAG,QAAQ,gDAAgD;AAC/E,QAAM,cAAc,GAAG;AAAA,IACrB;AAAA;AAAA,EAEF;AACA,QAAM,mBAAmB,GAAG;AAAA,IAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOF;AACA,QAAM,yBAAyB,GAAG;AAAA,IAChC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKF;AAEA,QAAM,qBAAqB,GAAG;AAAA,IAC5B;AAAA;AAAA,EAEF;AACA,QAAM,kBAAkB,GAAG,QAAQ,sCAAsC;AACzE,QAAM,sBAAsB,GAAG;AAAA,IAC7B;AAAA,EACF;AACA,QAAM,2BAA2B,GAAG,QAAQ,4CAA4C;AAExF,WAAS,cAAiB,MAAkB;AAC1C,OAAG,KAAK,iBAAiB;AACzB,QAAI;AACF,YAAM,SAAS,KAAK;AACpB,SAAG,KAAK,QAAQ;AAChB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,GAAG,cAAe,IAAG,KAAK,UAAU;AACxC,YAAM;AAAA,IACR;AAAA,EACF;AAGA,WAAS,eAAuB;AAC9B,UAAM,MAAM,YAAY,IAAI;AAC5B,WAAO,QAAQ,SAAY,IAAI,SAAS,IAAI,KAAK;AAAA,EACnD;AAGA,WAAS,aAAa,OAA4B;AAChD,UAAM,WAAW,aAAa;AAC9B,QAAI,aAAa,MAAM,OAAO;AAC5B,YAAM,IAAIC,yBAAwB,MAAM,OAAO,QAAQ;AAAA,IACzD;AAAA,EACF;AAGA,WAAS,SAAS,KAA+C;AAC/D,QAAI,QAAQ,QAAW;AACrB,YAAM,IAAI,mBAAmB,WAAW;AAAA,IAC1C;AACA,WAAO,UAAU,MAAM;AAAA,MACrB,IAAI,OAAO,IAAI,EAAE;AAAA,MACjB,MAAM,OAAO,IAAI,IAAI;AAAA,MACrB,QAAQ,OAAO,IAAI,MAAM;AAAA,MACzB,SAAS,OAAO,IAAI,OAAO;AAAA,MAC3B,UAAU,SAAS,IAAI,QAAQ;AAAA,MAC/B,WAAW,OAAO,IAAI,UAAU;AAAA,MAChC,WAAW,OAAO,IAAI,UAAU;AAAA,IAClC,CAAC;AAAA,EACH;AAEA,WAAS,WAAW,OAAwC;AAC1D,UAAM,MAAM,WAAW,IAAI,KAAK;AAChC,QAAI,QAAQ,QAAW;AACrB,YAAM,IAAI,mBAAmB,KAAK;AAAA,IACpC;AACA,WAAO;AAAA,EACT;AAEA,WAAS,YAAY,SAAoB,KAAgC;AAEvE,QAAI,QAAQ,eAAe,KAAK,MAAM,IAAI;AACxC,YAAM,IAAI,2BAA2B,QAAQ,IAAI;AAAA,IACnD;AACA,UAAM,UAAU,UAAU;AAAA,MACxB,OAAO,QAAQ,EAAE;AAAA,MACjB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,KAAK,UAAU,QAAQ,WAAW,IAAI;AAAA,MACtC;AAAA,MACA;AAAA,IACF,EAAE;AACF,WAAO;AAAA,MACL,KAAK,SAAS,YAAY,IAAI,QAAQ,MAAM,QAAQ,cAAc,CAAC;AAAA,MACnE,SAAS,SAAS,OAAO,MAAM;AAAA,IACjC;AAAA,EACF;AAGA,WAAS,oBAAoB,eAAoC,KAAmB;AAClF,QAAI,aAAa;AACjB,eAAW,aAAa,cAAc,iBAAiB;AACrD,YAAM,MAAM,gBAAgB,IAAI,OAAO,SAAS,CAAC;AACjD,UAAI,QAAQ,OAAW;AACvB,qBAAe,OAAO,SAAS,MAAM,OAAO,cAAc,gBAAgB,CAAC,CAAC;AAC5E,UAAI,CAAC,sBAAsB,SAAS,OAAO,IAAI,MAAM,CAAc,EAAG;AAAA,IACxE;AACA,QAAI,CAAC,WAAY;AACjB,uBAAmB,IAAI,cAAc,WAAW,cAAc,aAAa,GAAG;AAAA,EAChF;AAEA,WAAS,QAAQ,KAA+C;AAC9D,UAAM,iBAAiB,uBAAuB,GAAG;AACjD,WAAO;AAAA,MACL,IAAI,OAAO,IAAI,EAAE;AAAA,MACjB,MAAM,OAAO,IAAI,IAAI;AAAA,MACrB,gBAAgB,OAAO,IAAI,eAAe;AAAA,MAC1C,QAAQ,OAAO,IAAI,MAAM;AAAA,MACzB,SAAS,OAAO,IAAI,OAAO;AAAA,MAC3B,SAAS,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC;AAAA,MACvC,UAAU,SAAS,IAAI,QAAQ;AAAA,MAC/B,SAAS,IAAI,eAAe;AAAA,MAC5B,iBAAiB,IAAI,wBAAwB;AAAA;AAAA,MAE7C,GAAI,mBAAmB,SAAY,CAAC,IAAI,EAAE,eAAe;AAAA,MACzD,WAAW,OAAO,IAAI,UAAU;AAAA,MAChC,WAAW,OAAO,IAAI,UAAU;AAAA,IAClC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ;AACN,SAAG,MAAM;AAAA,IACX;AAAA,IAEA,MAAM,WAAW,OAAuC;AACtD,aAAO,cAAc,MAAM;AACzB,cAAM,WAAW,aAAa;AAG9B,YAAI,QAAQ,UAAU;AACpB,gBAAM,IAAIA,yBAAwB,OAAO,QAAQ;AAAA,QACnD;AACA,oBAAY,IAAI,KAAK;AACrB,eAAO,EAAE,MAAM;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,QAAQ,SAAgD;AAC5D,YAAM,MAAM,MAAM,IAAI;AACtB,aAAO,cAAc,MAAM,YAAY,SAAS,GAAG,CAAC;AAAA,IACtD;AAAA,IAEA,MAAM,UAAU,OAAsBC,UAAsD;AAC1F,YAAM,MAAM,MAAM,IAAI;AAEtB,YAAM,eAAeA,UAAS,gBAAgB,CAAC;AAC/C,aAAO,cAAc,MAAM;AAGzB,qBAAa,KAAK;AAClB,iBAAS,UAAU,GAAG,WAAW,uBAAuB,WAAW,GAAG;AACpE,gBAAM,MACJ,aAAa,WAAW,IACpB,gBAAgB,IAAI,GAAG,IACvB,sBAAsB,aAAa,MAAM,EAAE,IAAI,KAAK,GAAG,YAAY;AACzE,cAAI,QAAQ,QAAW;AACrB,mBAAO,EAAE,SAAS,MAAM;AAAA,UAC1B;AAEA,sBAAY,IAAI,KAAK,KAAK,KAAK,OAAO,IAAI,EAAE,CAAC;AAC7C,gBAAM,UAAU,WAAW,OAAO,IAAI,EAAE,CAAC;AAEzC,cAAI,oBAAoB,OAAO,GAAG;AAChC,4BAAgB,IAAI,oCAAoC,KAAK,OAAO,IAAI,EAAE,CAAC;AAC3E;AAAA,UACF;AAGA,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,KAAK,SAAS,OAAO;AAAA,YACrB,SAAS,KAAK,MAAM,OAAO,QAAQ,OAAO,CAAC;AAAA,UAC7C;AAAA,QACF;AAKA,cAAM,IAAI;AAAA,UACR,2BAA2B,qBAAqB;AAAA,QAGlD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,iBACJ,OACA,MACA,OACA,eAC6B;AAC7B,YAAM,MAAM,MAAM,IAAI;AACtB,aAAO,cAAc,MAAM;AACzB,qBAAa,KAAK;AAClB,mBAAW,OAAO,KAAK,CAAC;AACxB,iBAAS,IAAI,KAAK,OAAO,KAAK,CAAC;AAI/B,cAAM,UAAU,KAAK,IAAI,CAAC,YAAY,YAAY,SAAS,GAAG,CAAC;AAC/D,YAAI,kBAAkB,OAAW,qBAAoB,eAAe,GAAG;AACvE,eAAO,EAAE,KAAK,SAAS,WAAW,OAAO,KAAK,CAAC,CAAC,GAAG,QAAQ;AAAA,MAC7D,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,aACJ,OACA,aACA,MACA,OACA,eACA;AACA,YAAM,MAAM,MAAM,IAAI;AACtB,aAAO,cAAc,MAAM;AACzB,qBAAa,KAAK;AAClB,mBAAW,OAAO,KAAK,CAAC;AACxB,mBAAW,IAAI,YAAY,QAAQ,KAAK,OAAO,KAAK,CAAC;AAGrD,cAAM,UAAU,KAAK,IAAI,CAAC,YAAY,YAAY,SAAS,GAAG,CAAC;AAE/D,YAAI,kBAAkB,OAAW,qBAAoB,eAAe,GAAG;AACvE,eAAO,EAAE,KAAK,SAAS,WAAW,OAAO,KAAK,CAAC,CAAC,GAAG,QAAQ;AAAA,MAC7D,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,cACJ,OACA,aACA,OACe;AACf,YAAM,MAAM,MAAM,IAAI;AACtB,oBAAc,MAAM;AAClB,qBAAa,KAAK;AAClB,mBAAW,OAAO,KAAK,CAAC;AAExB,YAAI,YAAY,SAAS,SAAS;AAEhC,gBAAM,YACJ,YAAY,iBAAiB,SACzB,OACA,IAAI,KAAK,KAAK,MAAM,GAAG,IAAI,YAAY,YAAY,EAAE,YAAY;AACvE,wBAAc,IAAI,YAAY,QAAQ,KAAK,WAAW,OAAO,KAAK,CAAC;AAAA,QACrE,OAAO;AACL,qBAAW,IAAI,YAAY,QAAQ,KAAK,OAAO,KAAK,CAAC;AAAA,QACvD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,mBAAmB,OAAc,OAAqC;AAC1E,YAAM,MAAM,MAAM,IAAI;AACtB,oBAAc,MAAM;AAClB,qBAAa,KAAK;AAClB,mBAAW,OAAO,KAAK,CAAC;AACxB,wBAAgB,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,cAAc,OAAc,OAAiD;AACjF,YAAM,MAAM,MAAM,IAAI;AACtB,aAAO,cAAc,MAAM;AACzB,qBAAa,KAAK;AAClB,cAAM,MAAM,WAAW,OAAO,KAAK,CAAC;AACpC,cAAM,SAAS,OAAO,IAAI,MAAM;AAIhC,YAAI,sBAAsB,SAAS,MAAM,GAAG;AAC1C,iBAAO,EAAE,SAAS,oBAAoB,OAAO;AAAA,QAC/C;AACA,YAAI,IAAI,eAAe,MAAM;AAI3B,8BAAoB,IAAI,KAAK,KAAK,OAAO,KAAK,CAAC;AAC/C,iBAAO,EAAE,SAAS,mBAAmB;AAAA,QACvC;AAIA,yBAAiB,IAAI,KAAK,KAAK,OAAO,KAAK,CAAC;AAC5C,eAAO,EAAE,SAAS,YAAY;AAAA,MAChC,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,mBAAmB,OAAc,OAAqC;AAC1E,YAAM,MAAM,MAAM,IAAI;AACtB,oBAAc,MAAM;AAClB,qBAAa,KAAK;AAClB,cAAM,MAAM,WAAW,OAAO,KAAK,CAAC;AACpC,YAAI,IAAI,wBAAwB,MAAM;AACpC,gBAAM,IAAI,iCAAiC,KAAK;AAAA,QAClD;AACA,2BAAmB,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,MAC3C,CAAC;AAAA,IACH;AAAA;AAAA,IAGA,MAAM,gBAAgB,OAAc,OAAkD;AACpF,YAAM,MAAM,MAAM,IAAI;AACtB,YAAM,UAAU,cAAc,MAA2D;AACvF,qBAAa,KAAK;AAClB,cAAM,MAAM,WAAW,OAAO,KAAK,CAAC;AACpC,cAAM,SAAS,OAAO,IAAI,MAAM;AAEhC,YAAI,oBAAoB,GAAG,GAAG;AAC5B,gBAAM,IAAIC,4BAA2B,OAAO,KAAK,GAAG,OAAO,IAAI,IAAI,CAAC;AAAA,QACtE;AAIA,YAAI,CAAC,sBAAsB,SAAS,MAAM,GAAG;AAC3C,iBAAO,EAAE,SAAS,gBAAgB,OAAO;AAAA,QAC3C;AACA,cAAM,UAAU,0BACb,IAAI,OAAO,KAAK,CAAC,EACjB,IAAI,CAAC,eAAe,OAAO,WAAW,aAAa,CAAC;AACvD,gCAAwB,IAAI,OAAO,KAAK,CAAC;AAWzC,cAAM,cAAc,qBAAqB,IAAI,OAAO;AACpD,YAAI,gBAAgB,OAAW,0BAAyB,IAAI,WAAW;AACvE,qBAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AACnC,eAAO,EAAE,SAAS,YAAY,QAAQ;AAAA,MACxC,CAAC;AAMD,UAAI,QAAQ,YAAY,YAAY;AAClC,mBAAW,gBAAgB,QAAQ,WAAW,CAAC,GAAG;AAChD,sBAAY,QAAQ,OAAO,KAAK,GAAG,YAAY;AAAA,QACjD;AACA,eAAO,EAAE,SAAS,WAAW;AAAA,MAC/B;AACA,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,kBACJ,OACA,cACA,SACA,OACe;AACf,YAAM,MAAM,MAAM,IAAI;AACtB,YAAM,cAAcC,eAAc,OAAO;AACzC,YAAM,gBAAgBC,WAAU,WAAW;AAC3C,oBAAc,MAAM;AAClB,qBAAa,KAAK;AAClB,mBAAW,OAAO,KAAK,CAAC;AACxB,iBAAS,IAAI,KAAK,OAAO,KAAK,CAAC;AAI/B,yBAAiB;AAAA,UACf,OAAO,KAAK;AAAA,UACZ;AAAA,UACA,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AAID,UAAI,OAAO,gCAAgC,QAAW;AACpD,cAAM,MAAM,4BAA4B;AAAA,MAC1C;AACA,kBAAY,QAAQ,OAAO,KAAK,GAAG,cAAc,OAAO;AAAA,IAC1D;AAAA,IAEA,MAAM,eACJ,OACA,cACmC;AACnC,YAAM,MAAM,uBAAuB,IAAI,OAAO,KAAK,GAAG,YAAY;AAClE,UAAI,QAAQ,OAAW,QAAO,EAAE,OAAO,MAAM;AAE7C,YAAM,gBAAgB;AAAA,QACpB,OAAO;AAAA,QACP,SAAS,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC;AAAA,MAC9C;AACA,UAAI;AACF,cAAM,aAAa,YAAY,KAAK,OAAO,KAAK,GAAG,YAAY;AAC/D,YAAI,CAAC,WAAW,MAAO,QAAO;AAC9B,cAAM,mBAAmBA,WAAUD,eAAc,WAAW,OAAO,CAAC;AACpE,eAAO,qBAAqB,OAAO,IAAI,cAAc,IAAI,aAAa;AAAA,MACxE,QAAQ;AAGN,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,MAAM,YAAmC;AACvC,aAAO;AAAA,QACL,eAAe;AAAA,QACf,OAAO,aAAa;AAAA;AAAA;AAAA,QAGpB,MAAM,kBAAkB,IAAI,MAAM,EAAE,KAAK,IAAI,OAAO;AAAA,MACtD;AAAA,IACF;AAAA,IAEA,MAAM,oBAA8D;AAClE,aAAO,oBAAoB,IAAI,EAAE,IAAI,CAAC,SAAS;AAAA,QAC7C,OAAO,OAAO,IAAI,MAAM;AAAA,QACxB,SAAS,qBAAqB,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,CAAY;AAAA,QACxE,WAAW,OAAO,IAAI,UAAU;AAAA,MAClC,EAAE;AAAA,IACJ;AAAA,IAEA,MAAM,cAAoC;AACxC,aAAO,kBAAkB;AAAA,QACvB;AAAA,QACA,eAAe;AAAA,QACf,iBAAiB,YAAY;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,mBAAoC;AACxC,aAAO;AAAA,QACL,kBAAkB;AAAA,UAChB;AAAA,UACA,eAAe;AAAA,UACf,iBAAiB,YAAY;AAAA,QAC/B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;;;AD3vBO,IAAM,4BAAN,cAAwC,MAAM;AAAA,EACjC,OAAO;AAAA,EAEzB,cAAc;AAEZ,UAAM,2EAA2E;AAAA,EACnF;AACF;AAEA,SAAS,SAAS,OAAyC;AACzD,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACvE,UAAM,IAAI,0BAA0B;AAAA,EACtC;AACA,SAAO;AACT;AAEA,SAAS,qBACP,IACA,MACA,KACA,OAC8C;AAC9C,QAAM,eAAe;AAErB,QAAM,MAAM,GAAG,QAAQ;AAAA,yEACgD,EACpE,IAAI,OAAO,IAAI,YAAY,GAAG,YAAY;AAC7C,MAAI,QAAQ,OAAW,QAAO;AAC9B,MAAI;AACF,UAAM,gBAAyB,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC;AAClE,QAAIE,WAAUC,eAAc,aAAa,CAAC,MAAM,IAAI,gBAAgB;AAClE,YAAM,IAAI,0BAA0B;AAAA,IACtC;AACA,QAAI,UAAU;AACd,QAAI;AACF,YAAM,SAAS,0BAA0B,EAAE,KAAK,GAAG,OAAO,IAAI,YAAY,GAAG,YAAY;AACzF,UAAI,OAAO,SAASD,WAAUC,eAAc,OAAO,SAAS,OAAO,CAAC,MAAM,IAAI,gBAAgB;AAC5F,kBAAU,OAAO,SAAS;AAAA,MAC5B;AAAA,IACF,QAAQ;AAAA,IAER;AACA,UAAM,aAAa,SAAS,OAAO;AACnC,QAAI,WAAW,UAAU,IAAI,gBAAgB,WAAW,iBAAiB,gBACpE,WAAW,YAAY,OAAO,IAAI,OAAO,KAAK,CAAC,OAAO,UAAU,WAAW,OAAO,KAClF,OAAO,WAAW,OAAO,IAAI,KAAK,OAAO,WAAW,eAAe,YACnE,WAAW,WAAW,WAAW,EAAG,OAAM,IAAI,0BAA0B;AAC7E,UAAM,QAAQ,SAAS,WAAW,KAAK;AACvC,QAAI,MAAM,qBAAqB,OAAW,QAAO;AACjD,UAAM,MAAM,GAAG,QAAQ,wEAAwE,EAC5F,IAAI,OAAO,IAAI,YAAY,CAAC;AAC/B,QAAI,QAAQ,UAAa,IAAI,SAAS,mBACjC,IAAI,oBAAoB,GAAG,IAAI,UAAU,qBACzC,OAAO,IAAI,QAAQ,IAAI,OAAO,WAAW,OAAO,KAChD,SAAS,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,CAAC,EAAE,UAAU,SACpD,MAAM,UAAU,MAAO,OAAM,IAAI,0BAA0B;AAChE,WAAO,uBAAuB,MAAM,MAAM,gBAAgB;AAAA,EAC5D,QAAQ;AACN,UAAM,IAAI,0BAA0B;AAAA,EACtC;AACF;AAiBA,SAASC,UAAS,OAAwB;AACxC,SAAO,OAAO,UAAU,WAAW,OAAO,KAAK,IAAI,OAAO,KAAK;AACjE;AAEA,SAAS,MAAM,KAA4E;AACzF,MAAI,QAAQ,OAAW,QAAO;AAE9B,QAAM,iBACJ,CAACC,WAAU,OAAO,IAAI,IAAI,CAAC,KACxB,IAAI,WAAW,YACf,IAAI,sBAAsB,eAC1B,IAAI,wBAAwB,qCAC3B,oBACA;AACN,SAAO;AAAA,IACL,QAAQ,OAAO,IAAI,MAAM;AAAA,IACzB,SAAS,IAAI,eAAe;AAAA,IAC5B,UAAUD,UAAS,IAAI,QAAQ;AAAA,IAC/B,WAAW,OAAO,IAAI,UAAU;AAAA,IAChC,WAAW,OAAO,IAAI,UAAU;AAAA,IAChC,GAAI,IAAI,eAAe,OAAO,CAAC,IAAI,EAAE,WAAW,OAAO,IAAI,UAAU,EAAE;AAAA,IACvE,GAAI,IAAI,eAAe,OAAO,CAAC,IAAI,EAAE,WAAW,OAAO,IAAI,UAAU,EAAE;AAAA,IACvE,GAAI,mBAAmB,SAAY,CAAC,IAAI,EAAE,eAAe;AAAA,IACzD,GAAI,IAAI,sBAAsB,OAAO,CAAC,IAAI,EAAE,iBAAiB,OAAO,IAAI,iBAAiB,EAAE;AAAA,IAC3F,GAAI,IAAI,wBAAwB,OAAO,CAAC,IAAI,EAAE,mBAAmB,OAAO,IAAI,mBAAmB,EAAE;AAAA,EACnG;AACF;AAUO,SAAS,2BACd,SAC0B;AAC1B,QAAM,OAAOE,MAAK,QAAQ,aAAa,uBAAuB;AAE9D,SAAO;AAAA,IACL,UAAU,QAAQ;AAAA,IAElB,MAAM,UACJ,KACA,OAC+C;AAE/C,UAAI,CAACC,YAAW,IAAI,EAAG,QAAO;AAE9B,YAAM,KAAK,IAAIC,cAAa,MAAM;AAAA,QAChC,UAAU;AAAA,QACV,SAAS;AAAA,MACX,CAAC;AACD,UAAI;AAEF,cAAM,UAAUJ,UAAS,GAAG,QAAQ,qBAAqB,EAAE,IAAI,GAAG,YAAY;AAC9E,YAAI,YAAY,KAAK,YAAY,8BAA8B;AAC7D,gBAAM,IAAI,2BAA2B,MAAM,8BAA8B,OAAO;AAAA,QAClF;AAEA,cAAM,YAAY,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA,SAI5B;AACD,cAAM,kBAAkB,GACrB,QAAQ,oDAAoD,EAC5D,IAAI,KAAK;AAEZ,cAAM,aAAa;AAAA,UACjB,UAAU,IAAI,OAAO,IAAI,UAAU,CAAC;AAAA,QACtC;AACA,cAAM,eAAe;AAAA,UACnB,UAAU,IAAI,OAAO,IAAI,YAAY,CAAC;AAAA,QACxC;AAIA,cAAM,eACJ,oBAAoB,SAChB,SACAK,sBAAqB,KAAK,MAAM,OAAO,gBAAgB,OAAO,CAAC,CAAY;AACjF,cAAM,mBAAmB,qBAAqB,IAAI,QAAQ,aAAa,KAAK,KAAK;AAIjF,eAAO;AAAA,UACL,GAAI,eAAe,SAAY,CAAC,IAAI,EAAE,WAAW;AAAA,UACjD,GAAI,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa;AAAA,UACrD,GAAI,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa;AAAA,UACrD,GAAI,qBAAqB,SAAY,CAAC,IAAI,EAAE,iBAAiB;AAAA,QAC/D;AAAA,MACF,UAAE;AACA,WAAG,MAAM;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACF;;;AN2BO,IAAM,2BAAkD;AAYxD,IAAM,yBAA0D,OAAO,OAAO;AAAA,EACnF;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAiGD,SAAS,iCAAyC;AAChD,QAAM,cAAc,OAAO,eAAe,WACtC,aACA,YAAY;AAChB,QAAM,iBAAiB,cAAc,WAAW,EAAE,QAAQ,oCAAoC;AAC9F,SAAOC,MAAKC,SAAQ,cAAc,GAAG,mBAAmB,iBAAiB;AAC3E;AAEO,IAAM,4BAAqD,OAAO,OAAO;AAAA,EAC9E;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,yBAAyB,MAAM,wBAAwB,yBAAyB;AAAA,EAChF,kCAAkC,MAAM;AACtC,sCAAkC,MAAM,gBAAgB;AAAA,EAC1D;AACF,CAAC;AAoCD,SAAS,cAAc,OAA2B;AAChD,SAAO,0BAA0B;AAAA,IAC/B,eAAe,MAAM;AAAA,IACrB,kBAAkB,MAAM;AAAA,IACxB,eAAe,MAAM,MAAM;AAAA,IAC3B,OAAO,MAAM,MAAM;AAAA,IACnB,GAAI,MAAM,uBAAuB,SAAY,CAAC,IAAI,EAAE,oBAAoB,MAAM,mBAAmB;AAAA,IACjG,GAAI,MAAM,gBAAgB,SAAY,CAAC,IAAI,EAAE,aAAa,MAAM,YAAY;AAAA,EAC9E,CAAC;AACH;AAEA,SAAS,kBAAkB,OAAkE;AAC3F,SAAO,cAAc,KAAK,EAAE,kBAAkB,MAAM,OAAO;AAC7D;AAEA,SAAS,oBAAoB,OAA4D;AACvF,SAAO,cAAc,KAAK,EAAE,QAAQ,MAAM,aAAa,MAAM,QAAQ;AACvE;AAGA,SAAS,mBAAmB,OAA8G;AACxI,QAAM,UAAU,oBAAoB,MAAM,aAAa,EAAE,QAAQ,WAAS;AACxE,UAAM,SAAS,WAAW,MAAM,GAAG;AACnC,WAAO,OAAO,SAAS,YAAY,OAAO,OAAO,SAAS,OAAO,MAAM,YAClE,sBAAsB,MAAM,GAAG,EAAE,KAAK,CAAC,OAAO,MAAM,IAAI,CAAC;AAAA,EAChE,CAAC;AACD,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QAAM,SAAS,QAAQ,CAAC;AACxB,QAAM,WAAW,MAAM,eAAe,OAAO,eAAe,UAAU,CAAC;AACvE,MAAI,aAAa,OAAW,QAAO;AACnC,SAAO;AAAA,IAAE,UAAU,MAAM;AAAA,IAAU,MAAM,OAAO,YAAY;AAAA,IAC1D,GAAI,OAAO,YAAY,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,OAAO,YAAY,QAAQ;AAAA,IAC1F,SAAS,OAAO,YAAY,QAAQ,IAAI,YAAU,OAAO,GAAG;AAAA,IAAG,OAAO,OAAO,YAAY;AAAA,IACzF,SAAS,OAAO;AAAA,IAAS,sBAAsB,EAAE,IAAI,SAAS,IAAI,KAAK,SAAS,IAAI;AAAA;AAAA,IAEpF,aAAa;AAAA,EAAe;AAChC;AAiCO,IAAM,8BAAyD,OAAO,OAAO;AAAA,EAClF;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,qBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,8BAA8B;AAAA,EAC9B;AAAA,EACA,aAAa,OAAO,OAAO;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH,CAAC;AAED,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,aAAa,OAAiC;AACrD,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS;AAC5D;AAIA,SAAS,kBAAkB,UAAoC;AAC7D,QAAM,UAAU,SAAS,QAAQ,IAAI,SAAS,UAAU;AACxD,MAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,KAAK,CAAC,QAAQ,MAAM,YAAY,GAAG;AACnF,WAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B;AACA,SAAO,EAAE,QAAQ,YAAY,OAAO,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC,EAAE,KAAK,EAAE;AACnE;AAOO,SAAS,iBAAiB,aAAqC;AACpE,WAAS,YAAmC;AAC1C,UAAM,UAAUF,MAAK,aAAaG,YAAW;AAC7C,QAAI,CAACC,YAAW,OAAO,EAAG,QAAO,CAAC;AAElC,UAAM,YAAmC,CAAC;AAC1C,eAAW,SAASC,aAAY,SAAS,EAAE,eAAe,KAAK,CAAC,GAAG;AACjE,UAAI,CAAC,MAAM,YAAY,EAAG;AAC1B,YAAM,cAAcL,MAAK,SAAS,MAAM,MAAM,YAAY;AAC1D,UAAI,CAACI,YAAW,WAAW,EAAG;AAC9B,UAAI;AACF,kBAAU,KAAK,wBAAwB,WAAW,CAAC;AAAA,MACrD,QAAQ;AACN;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,OAAgD;AAC9C,aAAO,QAAQ,QAAQ,UAAU,CAAC;AAAA,IACpC;AAAA;AAAA,IAEA,IAAI,OAAwD;AAC1D,aAAO,QAAQ,QAAQ,UAAU,EAAE,KAAK,CAAC,aAAa,SAAS,UAAU,KAAK,CAAC;AAAA,IACjF;AAAA;AAAA,IAEA,WAAW,OAAc,SAAuD;AAC9E,YAAM,WAAW,CAAC,GAAG,IAAIE,YAAW,EAAE,MAAM,aAAa,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,EACtE,KAAK,CAAC,MAAM,UAAU,KAAK,MAAM,MAAM,GAAG;AAC7C,UAAI,SAAS,WAAW,EAAG,QAAO,QAAQ,QAAQ,CAAC,CAAC;AAEpD,YAAM,uBAAuB,SAAS,CAAC,EAAG;AAC1C,UAAI,UAAU,sBAAsB;AAClC,eAAO,QAAQ,OAAO,IAAI,sBAAsB,SAAS,oBAAoB,CAAC;AAAA,MAChF;AACA,aAAO,QAAQ,QAAQ,SAAS,OAAO,CAAC,UAAU,MAAM,OAAO,OAAO,CAAC;AAAA,IACzE;AAAA;AAAA,IAEA,iBAAiB,OAAc,SAA2D;AACxF,YAAM,WAAW,UAAU,EAAE,KAAK,CAAC,cAAc,UAAU,UAAU,KAAK;AAC1E,UAAI,aAAa,OAAW,QAAO,QAAQ,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE/E,YAAM,aAAa,SAAS,MAAM,OAAO,CAAC,UACvC,QAAQ,WAAW,UAAa,KAAK,WAAW,QAAQ,WACtD,KAAK,MAAM,KAAK,CAAC,SAAS,KAAK,cAAc,QAAQ,SAAS,CAClE;AACD,UAAI,WAAW,WAAW,EAAG,QAAO,QAAQ,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC9E,UAAI,WAAW,SAAS,GAAG;AACzB,eAAO,QAAQ,QAAQ;AAAA,UACrB,MAAM;AAAA;AAAA,UAEN,SAAS,WAAW,IAAI,CAAC,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,QACtD,CAAC;AAAA,MACH;AAEA,YAAM,WAAW,WAAW,CAAC,EAAG,MAAM,KAAK,CAAC,SAAS,KAAK,cAAc,QAAQ,SAAS;AACzF,aAAO,QAAQ;AAAA,QACb,aAAa,SACT,EAAE,MAAM,iBAAiB,IACzB,EAAE,MAAM,SAAS,SAAS;AAAA,MAChC;AAAA,IACF;AAAA;AAAA,IAEA,mBAAmB,OAAwC;AACzD,YAAM,UAAUN,MAAK,aAAaG,YAAW;AAC7C,UAAI,CAACC,YAAW,OAAO,EAAG,QAAO,QAAQ,QAAQ,EAAE,QAAQ,UAAU,CAAC;AAEtE,YAAM,QAAQC,aAAY,SAAS,EAAE,eAAe,KAAK,CAAC,EACvD,KAAK,CAAC,cAAc,UAAU,YAAY,KAAK,UAAU,SAAS,KAAK;AAC1E,UAAI,UAAU,OAAW,QAAO,QAAQ,QAAQ,EAAE,QAAQ,UAAU,CAAC;AAErE,UAAI;AACF,cAAM,SAASL,MAAK,SAAS,MAAM,IAAI;AACvC,YAAI,wBAAwBA,MAAK,QAAQ,YAAY,CAAC,EAAE,UAAU,OAAO;AACvE,iBAAO,QAAQ,QAAQ,EAAE,QAAQ,UAAU,CAAC;AAAA,QAC9C;AACA,eAAO,QAAQ;AAAA,UACb,kBAAkB,KAAK,MAAMO,cAAaP,MAAK,QAAQ,aAAa,GAAG,MAAM,CAAC,CAAC;AAAA,QACjF;AAAA,MACF,QAAQ;AACN,eAAO,QAAQ,QAAQ,EAAE,QAAQ,UAAU,CAAC;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AACF;AAGO,SAAS,sBACd,sBACA,qBACqB;AACrB,SAAO,0BAA0B;AAAA,IAC/B;AAAA,IACA,GAAI,wBAAwB,SAAY,CAAC,IAAI,EAAE,oBAAoB;AAAA,EACrE,CAAC;AACH;AAgBA,SAAS,sBACP,MACA,aACA,QACuB;AACvB,UAAQ,OAAO,SAAS;AAAA,IACtB,KAAK;AACH,aAAO;AAAA,QACL,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,WAAW,CAAC,GAAG,OAAO,SAAS;AAAA,QAC/B,GAAI,OAAO,kBAAkB,SAAY,CAAC,IAAI,EAAE,eAAe,OAAO,cAAc;AAAA,QACpF,GAAI,OAAO,kBAAkB,SAAY,CAAC,IAAI,EAAE,eAAe,OAAO,cAAc;AAAA,MACtF;AAAA,IACF,KAAK;AACH,aAAO,EAAE,SAAS,oBAAoB,MAAM,aAAa,QAAQ,OAAO,OAAO;AAAA,IACjF,KAAK;AACH,aAAO,EAAE,SAAS,WAAW,MAAM,aAAa,QAAQ,6BAA6B;AAAA,IACvF;AACE,aAAO;AAAA,EACX;AACF;AAWO,SAAS,sBAAsB,OAAwD;AAC5F,iBAAe,QAA4C;AACzD,WAAO,EAAE,eAAe,MAAM,MAAM,qBAAqB,EAAE;AAAA,EAC7D;AAGA,MAAI,cAAgC,QAAQ,QAAQ;AACpD,WAAS,WAAc,MAAoC;AACzD,UAAM,OAAO,YAAY,KAAK,MAAM,IAAI;AACxC,kBAAc,KAAK,KAAK,MAAM,QAAW,MAAM,MAAS;AACxD,WAAO;AAAA,EACT;AAEA,SAAO;AAAA;AAAA,IAEL,QAAQ,CAAC,YAAY,WAAW,YAAY;AAC1C,YAAM,EAAE,cAAc,IAAI,MAAM,MAAM;AACtC,YAAM,cAAc,QAAQ,eAAeQ,YAAW;AACtD,YAAM,YAAY,MAAM,yBAAyB;AACjD,YAAM,SAAS,MAAM,qBAAqB;AAAA,QACxC,aAAa,MAAM;AAAA,QACnB;AAAA,QACA,SAAS,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,MAAM;AAAA,QACpD;AAAA;AAAA;AAAA,QAGA,MAAM,aAAa,QAAQ,IAAI;AAAA,QAC/B,mBAAmB,MAAM,2BAA2B,2BAA2B;AAAA,QAC/E,GAAI,MAAM,4BAA4B,SAAY,CAAC,IAAI,EAAE,UAAU,MAAM,wBAAwB;AAAA,QACjG,GAAI,cAAc,SAAY,CAAC,IAAI,EAAE,iBAAiB,UAAU;AAAA,MAClE,CAAC;AACD,aAAO,sBAAsB,QAAQ,MAAM,aAAa,MAAM;AAAA,IAChE,CAAC;AAAA,EACH;AACF;AA0BA,eAAsB,qBAAqB,OAAiE;AAC1G,QAAM,SAAS,8BAA8B;AAAA,IAC3C,MAAMR,MAAK,MAAM,aAAa,yBAAyB;AAAA,EACzD,CAAC;AACD,MAAI;AACF,WAAO,MAAM,oBAAoB;AAAA,MAC/B,aAAa,MAAM;AAAA,MACnB,eAAe,MAAM;AAAA,MACrB,SAAS,MAAM;AAAA,MACf,aAAa,MAAM;AAAA,MACnB,MAAM,MAAM;AAAA,MACZ,kBAAkB,MAAM;AAAA,MACxB,sBAAsB,CAAC,YAAY,OAAO,gBAAgB,OAAO,GAAG;AAAA,MACpE,GAAI,MAAM,aAAa,SAAY,CAAC,IAAI,EAAE,UAAU,MAAM,SAAS;AAAA,MACnE,GAAI,MAAM,oBAAoB,SAAY,CAAC,IAAI,EAAE,iBAAiB,MAAM,gBAAgB;AAAA,IAC1F,CAAC;AAAA,EACH,UAAE;AACA,WAAO,MAAM;AAAA,EACf;AACF;AAUO,SAAS,sBAAsB,OAAwD;AAC5F,SAAO;AAAA,IACL,QAAQ,KAAK;AACX,aAAO,yBAAyB,OAAO,CAAC,SAAS,iBAAiB,KAAK,IAAI,CAAC;AAAA,IAC9E;AAAA,IACA,IAAI,KAAK;AACP,aAAO,yBAAyB,OAAO,CAAC,SAAS,oBAAoB,KAAK,IAAI,CAAC;AAAA,IACjF;AAAA,EACF;AACF;AAGO,SAAS,yBACd,OACqB;AACrB,SAAO,CAAC,cAAc,yBAAyB,OAAO,CAAC,SAAS;AAC9D,eAAW,YAAY,UAAW,aAAY,UAAU,IAAI;AAAA,EAC9D,CAAC;AACH;AAQA,eAAe,yBACb,OACA,MACY;AACZ,QAAM,gBAAgB,MAAM,MAAM,qBAAqB;AACvD,QAAM,SAAS,qBAAqB;AAAA,IAClC,MAAMA,MAAK,MAAM,aAAa,yBAAyB;AAAA,EACzD,CAAC;AAED,QAAM,cAAc,gBAAgB,EAAE,MAAM,kBAAkB,aAAa,GAAG,cAAc,CAAC;AAC7F,MAAI;AAKF,WAAO,MAAM,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,MACA,SAAS,CAAC,2BAA2B,MAAM,aAAa,CAAC;AAAA,IAC3D,CAAC;AAAA,EACH,UAAE;AACA,gBAAY,MAAM;AAClB,WAAO,MAAM;AAAA,EACf;AACF;AAgBA,eAAsB,2BACpB,OACkC;AAClC,QAAM,gBAAgB,MAAM,MAAM,qBAAqB;AACvD,QAAM,SAAS,qBAAqB;AAAA,IAClC,MAAMA,MAAK,MAAM,aAAa,yBAAyB;AAAA,EACzD,CAAC;AACD,QAAM,cAAc,gBAAgB,EAAE,MAAM,kBAAkB,aAAa,GAAG,cAAc,CAAC;AAC7F,MAAI;AACF,UAAM,SAAS,iBAAiB,aAAa,oBAAoB;AAAA,MAC/D;AAAA,MACA,SAAS,CAAC,2BAA2B,MAAM,aAAa,CAAC;AAAA,IAC3D,CAAC,CAAC;AAEF,QAAI,WAAW;AACf,UAAM,UAAU,MAAM,6BAA6B;AACnD,UAAM,aAAa,MAAM,QAAQ;AAAA,MAC/B,kBAAkB;AAAA,MAClB,eAAe;AAAA,MACf,aAAa,MAAM;AAAA,IACrB,CAAC;AACD,QAAI,WAAW,SAAS,SAAS;AAC/B,iBAAW,MAAM;AAAA,QACf;AAAA,QACA,WAAW;AAAA,QACX,WAAW;AAAA,MACb;AAAA,IACF;AACA,WAAO,EAAE,GAAG,QAAQ,SAAS;AAAA,EAC/B,UAAE;AACA,gBAAY,MAAM;AAClB,WAAO,MAAM;AAAA,EACf;AACF;AAUO,IAAM,2BAAN,cAAuC,MAAM;AAAA,EAClD,YAAqB,OAAe;AAClC;AAAA,MACE,yBAAyB,KAAK;AAAA,IAGhC;AALmB;AAMnB,SAAK,OAAO;AAAA,EACd;AACF;AAUO,SAAS,yBAAyB,OAGnB;AACpB,SAAO;AAAA,IACL,MAAM,MAAM,SAA8C;AACxD,YAAM,UAAU,MAAM,MAAM,UAAU,QAAQ,OAAO;AACrD,YAAM,EAAE,SAAS,IAAI,cAAc;AAAA,QACjC,WAAWC,SAAQ,MAAM,WAAW;AAAA,QACpC,OAAO,OAAO,QAAQ,KAAK;AAAA,MAC7B,CAAC;AACD,UAAI,SAAS,KAAK,CAAC,EAAE,WAAW,GAAG;AACjC,cAAM,IAAI,yBAAyB,OAAO,QAAQ,KAAK,CAAC;AAAA,MAC1D;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAmGA,IAAM,6BAAkD;AAAA,EACtD,OAAO,oBAAI,IAAY;AAAA,EACvB,SAAS,CAAC;AAAA,EACV,UAAU,oBAAI,IAA+B;AAC/C;AAGA,SAAS,iBAAiB,UAAiC;AACzD,SAAO,GAAG,SAAS,QAAQ,KAAS,SAAS,QAAQ;AACvD;AAGA,SAAS,sBACP,eACA,SACA,OACqB;AACrB,QAAM,OAAO,YAAY,aAAa;AACtC,MAAI,CAACG,YAAW,IAAI,EAAG,QAAO;AAC9B,QAAM,KAAK,IAAIK,cAAa,MAAM,EAAE,UAAU,KAAK,CAAC;AACpD,MAAI;AACF,UAAM,QAAQ,4BAA4B,IAAI,EAAE,QAAQ,CAAC;AACzD,UAAM,WAAW,iBAAiB,KAAK;AACvC,UAAM,UAAU,MACb,aAAa,EACb,OAAO,CAAC,aAAa,iBAAiB,QAAQ,MAAM,QAAQ;AAC/D,UAAM,WAAW,oBAAI,IAA+B;AACpD,UAAM,QAAQ,oBAAI,IAAY;AAC9B,eAAW,YAAY,SAAS;AAC9B,YAAM,MAAM,MAAM,gBAAgB,SAAS,UAAU,SAAS,QAAQ;AACtE,eAAS,IAAI,iBAAiB,QAAQ,GAAG,GAAG;AAC5C,iBAAW,WAAW,IAAK,OAAM,IAAI,OAAO;AAAA,IAC9C;AACA,WAAO,EAAE,OAAO,SAAS,SAAS;AAAA,EACpC,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,eAAe,GAAG;AACrE,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR,UAAE;AACA,OAAG,MAAM;AAAA,EACX;AACF;AAeA,SAAS,sBAAsB,OAAoC;AACjE,SAAO;AAAA,IACL,aAAa,WAA+C;AAC1D,aAAO,MAAM,UAAU,WAAW,SAAS;AAAA,IAC7C;AAAA,IACA,MAAM,eAAe,OAA8B;AACjD,YAAM,gBAAgB,MAAM,MAAM,cAAc;AAChD,YAAM,gBAA+B;AAAA,QACnC,UAAU,MAAM;AAAA,QAChB,UAAU,MAAM;AAAA,MAClB;AACA,YAAM,WAAW,iBAAiB,aAAa;AAG/C,YAAM,cAAc,MAAM,MAAM,UAAU,gBAAgB,GAAG;AAAA,QAC3D,CAAC,UAAU,iBAAiB,KAAK,MAAM;AAAA,MACzC;AAEA,UAAI;AACJ,UAAI;AACJ,YAAM,eAAe,MAA2B;AAC9C,YAAI,aAAa,OAAW,QAAO;AACnC,mBAAW,oBAAoB,SAC3B,6BACA,sBAAsB,eAAe,iBAAiB,aAAa;AACvE,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,QACL,MAAM;AAAA,UACJ,MAAM,MAAM,SAA2D;AACrE,kBAAM,kBAAkB,MAAM,MAAM,aAAa,OAAO;AACxD,gCAAoBC,YAAW,gBAAgB,MAAM,GAAG;AACxD,mBAAO;AAAA,UACT;AAAA,UACA,KAAK,CAAC,UAAkB,MAAM,QAAQ,KAAK;AAAA,QAC7C;AAAA,QACA,cAAc;AAAA,UACZ,cAAc,MAAM,aAAa,EAAE;AAAA,UACnC,cAAc,MAAM,aAAa,EAAE;AAAA,UACnC,iBAAiB,CAAC,UAAkB,aAClC,aAAa,EAAE,SAAS,IAAI,iBAAiB,EAAE,UAAU,SAAS,CAAC,CAAC,KAAK,CAAC;AAAA,QAC9E;AAAA,QACA;AAAA;AAAA,QAEA,UAAU,yBAAyB,EAAE,oBAAoB,MAAM,MAAM,YAAY,CAAC;AAAA;AAAA,QAElF,gBAAgB;AAAA,UACd,MAAM,MAAM;AAAA,UACZ,SAAS,MAAM;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,IAAM,4BAA4C,OAAO,OAAO;AAAA,EAC9D,SAAS;AAAA,EACT,QAAQ;AACV,CAAC;AAGD,IAAM,+BAA+C,OAAO,OAAO;AAAA,EACjE,SAAS;AAAA,EACT,QAAQ;AACV,CAAC;AAGM,IAAM,eAA0B,OAAO,OAAO;AAAA,EACnD,KAAK,OAAc,oBAAI,KAAK,GAAE,YAAY;AAC5C,CAAC;AAOD,IAAM,oBAAiC;AAAA,EACrC,UAAU,CAAC,MAAM,mBACfC,SAAQ,OAAO,YAAY,GAAG,IAAI,IAAI,cAAc,EAAE,CAAC,EAAE;AAC7D;AACO,IAAM,uBAAoC,OAAO,OAAO,iBAAiB;AA8BzE,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAG/C,YAAqB,aAAqB;AACxC;AAAA,MACE,mCAAmC,WAAW;AAAA,IAEhD;AAJmB;AAAA,EAKrB;AAAA,EAPkB,OAAO;AAQ3B;AA8BO,IAAM,+BACT,OAAO,OAAO;AAAA;AAAA,EAEd,iBAAiB,OAAO,OAAO,CAAC,CAAC;AAAA,EACjC,aAAa,OAAO,OAAO,CAAC,eAAe,CAAU;AACvD,CAAC;AA+EH,SAAS,yBACP,eACA,OAC2C;AAC3C,QAAM,OAAO,YAAY,aAAa;AACtC,MAAI,CAACP,YAAW,IAAI,EAAG,QAAO;AAC9B,QAAM,KAAK,IAAIK,cAAa,MAAM,EAAE,UAAU,KAAK,CAAC;AACpD,MAAI;AACF,WAAO,uBAAuB,IAAI;AAAA,MAChC,SAAS,MAAM;AAAA,MACf,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,IAClB,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,eAAe,EAAG,QAAO;AAC9E,UAAM;AAAA,EACR,UAAE;AACA,OAAG,MAAM;AAAA,EACX;AACF;AASA,SAAS,wBACP,eACA,OAEiC;AACjC,QAAM,OAAO,YAAY,aAAa;AACtC,MAAI,CAACL,YAAW,IAAI,EAAG,QAAO;AAC9B,QAAM,KAAK,IAAIK,cAAa,MAAM,EAAE,UAAU,KAAK,CAAC;AACpD,MAAI;AACF,UAAM,UAAU,uBAAuB,IAAI;AAAA,MACzC,SAAS,MAAM;AAAA,MACf,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,IAClB,CAAC;AACD,QAAI,YAAY,OAAW,QAAO;AAClC,UAAM,sBACJ,QAAQ,oBACL,QAAQ,aAAa,OAAO,CAAC,KAAK,UAAU,KAAK,IAAI,KAAK,MAAM,YAAY,GAAG,CAAC;AACrF,QAAI,MAAM,gBAAgB,OAAW,QAAO,kBAAkB,SAAS,mBAAmB;AAC1F,UAAM,WAAW;AAAA,MACf;AAAA,MACA,EAAE,SAAS,MAAM,SAAS,aAAa,MAAM,YAAY;AAAA,MACzD;AAAA,IACF;AACA,WAAO,EAAE,KAAK,SAAS,oBAAoB,cAAc,SAAS,eAAe;AAAA,EACnF,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,eAAe,EAAG,QAAO;AAC9E,UAAM;AAAA,EACR,UAAE;AACA,OAAG,MAAM;AAAA,EACX;AACF;AAGA,IAAM,yBAAyB;AAAA,EAC7B,aAAa;AAAA,EACb,SAAS;AAAA,EACT,UAAU;AACZ;AAGA,SAAS,qBACP,eACA,UACA,KACA,YAC8B;AAC9B,QAAM,UAAUG,2BAA0BC,sBAAqB,aAAa,EAAE,QAAQ,GAAG;AACzF,QAAM,QAAQ,QAAQ,KAAK,CAAC,cAC1B,UAAU,YAAY,SAAS,WAC5B,UAAU,aAAa,SAAS,YAChC,UAAU,aAAa,SAAS,QAAQ;AAC7C,QAAM,QAAQ,UAAU,SAAY,SAAY,uBAAuB,MAAM,KAAK;AAClF,MAAI,UAAU,UAAa,UAAU,OAAW,QAAO,EAAE,OAAO,WAAW,MAAM,UAAU;AAC3F,MAAI,WAAW,OAAO,sBAAuB,QAAO,EAAE,OAAO,UAAU;AACvE,SAAO;AACT;AAYA,SAAS,mCACP,sBAEA,KACsB;AACtB,MAAI;AACJ,MAAI;AAEJ,WAAS,eAA0C;AACjD,QAAI,cAAc,OAAW,QAAO;AACpC,QAAI;AACJ,QAAI;AACF,eAAS,qBAAqB;AAAA,IAChC,QAAQ;AACN,aAAO;AAAA,IACT;AACA,QAAI,OAAO,WAAW,UAAU;AAC9B,aAAO;AACP,aAAO;AAAA,IACT;AAGA,gBAAY,OAAO;AAAA,MACjB,CAAC,UAAU;AACT,eAAO;AAAA,MACT;AAAA,MACA,MAAM;AACJ,oBAAY;AAAA,MACd;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,UAA8B;AACrC,QAAI,SAAS,OAAW,QAAO;AAC/B,iBAAa;AACb,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,QAAuB;AACrB,UAAI,SAAS,OAAW,QAAO,QAAQ,QAAQ;AAG/C,aAAO,aAAa,KAAK,QAAQ,QAAQ;AAAA,IAC3C;AAAA,IACA,UAAU;AAAA,MACR,kBAAkB,OAAO;AACvB,cAAM,gBAAgB,QAAQ;AAC9B,YAAI,kBAAkB,OAAW,QAAO;AACxC,cAAM,aAAa,wBAAwB,eAAe,KAAK;AAE/D,YAAI,eAAe,OAAW,QAAO;AACrC,cAAM,SAAS,qBAAqB,eAAe,OAAO,IAAI,GAAG,UAAU;AAC3E,eAAO,WAAW,SAAY,aAAa,EAAE,GAAG,YAAY,OAAO;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,6BAA6B,aAAiD;AACrF,SAAO;AAAA,IACL,YAAY,OAAO;AACjB,YAAM,OAAOb,MAAK,aAAaG,cAAaO,YAAW,KAAK,GAAG,aAAa;AAC5E,UAAI;AACJ,UAAI;AACF,gBAAQH,cAAa,MAAM,MAAM;AAAA,MACnC,SAAS,OAAO;AACd,YAAK,MAAgC,SAAS,SAAU,QAAO;AAC/D,cAAM;AAAA,MACR;AACA,YAAM,YAAY;AAAA,QAChB,yBAAyB,KAAK,MAAM,KAAK,CAAC;AAAA,QAC1C;AAAA,MACF;AACA,aAAO,UAAU,SAAS,aAAa,UAAU,WAAW;AAAA,IAC9D;AAAA,EACF;AACF;AAGO,SAAS,oBACd,OAMA,eAEA,qBACoC;AACpC,QAAM,UAAU,MAAM;AACtB,MAAI,YAAY,OAAW,QAAO;AAClC,SAAO;AAAA,IACL,yBAAyB,CAAC,UACxB;AAAA,MACEP,MAAK,MAAM,aAAaG,cAAaO,YAAW,KAAK,GAAG,YAAY;AAAA,IACtE;AAAA,IACF,WAAW,QAAQ;AAAA;AAAA,IAEnB,iBAAiB,CAAC,aAChB;AAAA,MACEV,MAAK,MAAM,aAAaG,cAAaO,YAAW,SAAS,KAAK,GAAG,aAAa;AAAA,MAC9E;AAAA,IACF;AAAA;AAAA,IAEF,iBAAiB,CAAC,UAAU,yBAAyB,eAAe,KAAK;AAAA;AAAA,IAEzE,kBAAkB,CAAC,OAAO,QACxB,sBAAsB,EAAE,aAAa,MAAM,YAAY,GAAG,OAAO,GAAG;AAAA;AAAA,IAEtE,GAAI,wBAAwB,SAAY,CAAC,IAAI,EAAE,oBAAoB;AAAA,EACrE;AACF;AAGO,IAAM,uBAAuC,OAAO,OAAO;AAAA,EAChE,SAAS;AAAA,EACT,QAAQ;AACV,CAAC;AAEM,IAAM,sBAAsC,OAAO,OAAO;AAAA,EAC/D,SAAS;AAAA,EACT,QAAQ;AACV,CAAC;AAGD,SAAS,eAAe,UAA2D;AACjF,MAAI,aAAa,OAAW,QAAO,CAAC;AACpC,SAAO,SACJ,KAAK,oBAAoB,EACzB,IAAI,CAAC,gBAAgB,YAAY,EAAE,EACnC,KAAK;AACV;AAEA,SAAS,gBAAgB,UAAgD;AACvE,MAAI,aAAa,OAAW,QAAO;AAEnC,SAAO,YAAY,eAAe,QAAQ,EAAE,KAAK,IAAI,CAAC;AACxD;AAMA,SAAS,mBAAqC,OAAU,OAAwB,MAAiB;AAC/F,SAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,MAAM,MAAM;AACrE,UAAM,OAAO,OAAO,OAAO,OAAO,GAAG,IAAI,MAAM,GAAG,IAAK;AACvD,QAAI,SAAS,aAAc,QAAO,CAAC,KAAK,MAAM;AAC9C,QAAI,OAAO,SAAS,WAAY,QAAO,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC;AAC/D,QAAI,SAAS,UAAU,OAAO,WAAW,SAAU,QAAO,CAAC,KAAK,KAAK,MAAM,CAAC;AAC5E,WAAO,CAAC,KAAK,gBAAgB,QAAQ,IAAI,CAAC;AAAA,EAC5C,CAAC,CAAC;AACJ;AAEA,IAAM,iBAAiB,CAAC,UAA2C,CAAC,OAAO,SAAS;AAClF,QAAM,UAAU,CAAC,UACf,SAAS,KAAK,IAAI,mBAAmB,OAAO,OAAO,IAAI,IAAI,gBAAgB,OAAO,IAAI;AACxF,SAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,IAAI,OAAO,IAAI,QAAQ,KAAK;AAClE;AAEA,IAAM,kBAAmC;AAAA,EACvC,MAAM;AAAA,EAAc,QAAQ;AAAA,EAAc,IAAI;AAChD;AACA,IAAM,4BAA6C;AAAA,EACjD,QAAQ;AAAA,EAAQ,YAAY;AAAA,EAAc,QAAQ;AAAA,EAAc,QAAQ;AAAA,EAAc,SAAS;AACjG;AACA,IAAM,mBAAgF;AAAA,EACpF,cAAc,EAAE,GAAG,iBAAiB,MAAM,OAAO;AAAA,EACjD,eAAe,EAAE,GAAG,iBAAiB,OAAO,cAAc,SAAS,aAAa;AAAA,EAChF,gBAAgB,EAAE,GAAG,iBAAiB,GAAG,0BAA0B;AAAA,EACnE,eAAe,EAAE,GAAG,iBAAiB,YAAY,cAAc,SAAS,OAAO;AAAA,EAC/E,mBAAmB;AAAA,IACjB,GAAG;AAAA,IAAiB,aAAa;AAAA,IAAc,UAAU;AAAA,IAAc,QAAQ;AAAA,EACjF;AAAA,EACA,gBAAgB,EAAE,GAAG,iBAAiB,QAAQ,QAAQ,QAAQ,OAAO;AAAA,EACrE,cAAc,EAAE,GAAG,iBAAiB,MAAM,QAAQ,IAAI,QAAQ,QAAQ,aAAa;AAAA,EACnF,qBAAqB;AAAA,IACnB,GAAG;AAAA,IAAiB,UAAU;AAAA,IAAc,YAAY;AAAA,IAAc,aAAa;AAAA,EACrF;AAAA,EACA,YAAY;AAAA,IACV,GAAG;AAAA,IAAiB,cAAc;AAAA,IAAc,aAAa;AAAA,IAAc,SAAS;AAAA,EACtF;AAAA,EACA,SAAS,EAAE,GAAG,iBAAiB,QAAQ,aAAa;AAAA,EACpD,eAAe,EAAE,GAAG,iBAAiB,QAAQ,aAAa;AAC5D;AAEA,IAAM,2BAA4C;AAAA,EAChD,SAAS;AAAA,EACT,SAAS,eAAe,EAAE,QAAQ,cAAc,SAAS,OAAO,CAAC;AAAA,EACjE,WAAW;AACb;AAEA,IAAM,yBAA0C;AAAA,EAC9C,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU,eAAe,yBAAyB;AAAA,EAClD,SAAS,eAAe,EAAE,YAAY,cAAc,SAAS,OAAO,CAAC;AAAA,EACrE,WAAW,eAAe,EAAE,QAAQ,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAC5D,kBAAkB;AACpB;AAEA,SAAS,wBAAwB,OAAyB,MAAgC;AACxF,QAAM,QAAQ,OAAO,OAAO,kBAAkB,MAAM,IAAI,IACpD,iBAAiB,MAAM,IAAI,IAC3B;AACJ,SAAO,mBAAmB,OAAO,OAAO,IAAI;AAC9C;AAEO,SAAS,kBAAkB,OAA+C;AAC/E,QAAM,QAAQ,MAAM,SAAS;AAE7B,QAAM,wBAAwB;AAAA,IAC5B,aAAa,MAAM;AAAA,IACnB,sBAAsB,MAAM;AAAA,EAC9B;AASA,QAAM,aAAa,mCAAmC,MAAM,eAAe,MAAM,MAAM,IAAI,CAAC;AAC5F,QAAM,aAAa,iBAAiB,MAAM,WAAW;AAGrD,MAAI;AAEJ,QAAM,wBAAwB,MAAM,cAAc,SAAY,YAAY,MAAM,UAAU;AAM1F,QAAM,aAAa,oBAAI,IAA8B;AACrD,QAAM,eAAe,CAAC,cAAwC;AAC5D,UAAM,WAAW,WAAW,IAAI,SAAS;AACzC,QAAI,aAAa,OAAW,QAAO;AACnC,QAAI,qBAAqB,QAAW;AAClC,YAAM,IAAI,UAAU,8DAA8D;AAAA,IACpF;AACA,UAAM,QAA0B;AAAA;AAAA;AAAA;AAAA,MAI9B,OAAO,gBAAgB,EAAE,aAAa,sBAAsB,CAAC;AAAA,IAC/D;AACA,eAAW,IAAI,WAAW,KAAK;AAC/B,WAAO;AAAA,EACT;AAGA,QAAM,mBAAmB,CAAC,cACxB,aAAa,SAAS,EAAE,MAAM,KAAK,EAAE;AAMvC,QAAM,mBAAmB,oBAAI,IAA+B;AAC5D,MAAI,MAAM,cAAc,OAAW,kBAAiB,IAAI,uBAAuB,MAAM,SAAS;AAE9F,QAAM,iBAAiB,sBAAsB;AAAA,IAC3C,MAAM,MAAM;AAAA,IACZ,KAAK,MAAM,MAAM,IAAI;AAAA;AAAA,IAErB,OAAO,MAAM,MAAM,KAAK,qBAAqB;AAAA,IAC7C,aAAa,MAAM,gBAAgB,gBAAgB;AAAA,EACrD,CAAC;AAGD,QAAM,mBAAmB,oBAAI,IAAiE;AAE9F,QAAM,wBAAwC;AAAA,IAC5C,MAAM,KAAK,WAAgD;AACzD,YAAMI,UAAS,MAAM,eAAe,KAAK,SAAS;AAClD,YAAM,KAAKA,QAAO,OAAO;AACzB,YAAM,UAAU,oBAAI,IAAY;AAChC,YAAM,UAA6B;AAAA,QACjC,QAAQA,QAAO;AAAA,QACf,QAAQA,QAAO;AAAA,QACf,cAAcA,QAAO;AAAA,QACrB,QAAQ,OAAO,UAAU;AAEvB,gBAAM,YAAY,wBAAwB,OAAO,MAAM,IAAI;AAC3D,kBAAQ,IAAI,UAAU,MAAM;AAC5B,gBAAMA,QAAO,OAAO,SAAS;AAE7B,cAAI;AACF,kBAAM,sBAAsB,IAAI,SAAS;AAAA,UAC3C,QAAQ;AAAA,UAAmD;AAAA,QAC7D;AAAA,QACA,cAAc,MAAMA,QAAO,aAAa;AAAA,QACxC,OAAO,YAAY;AAGjB,2BAAiB,OAAO,EAAE;AAC1B,gBAAMA,QAAO,MAAM;AAAA,QACrB;AAAA,MACF;AACA,uBAAiB,IAAI,IAAI,EAAE,QAAQ,SAAS,QAAQ,CAAC;AACrD,aAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,yBAAyB,CAAC,WAAkD;AAChF,eAAW,SAAS,iBAAiB,OAAO,GAAG;AAC7C,UAAI,MAAM,QAAQ,IAAI,MAAM,EAAG,QAAO,MAAM;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AAGA,QAAM,gBAAgB,oBAAI,IAA8B;AACxD,QAAM,cACJ,MAAM,cAAc,SAChB,SACA;AAAA,IACE,MAAM,CAAC,YAAY;AACjB,UAAI,qBAAqB,QAAW;AAClC,cAAM,IAAI,UAAU,wDAAwD;AAAA,MAC9E;AACA,YAAM,aAAa,iBAAiB,QAAQ,SAAS;AACrD,UAAI,QAAQ,cAAc,IAAI,UAAU;AACxC,UAAI,UAAU,QAAW;AACvB,gBAAQ,mBAAmB;AAAA,UACzB,OAAQ,iBAAiB,IAAI,UAAU,KAAK,MAAM;AAAA,UAClD,OAAO,oBAAoB,kBAAkB,mBAAmB;AAAA;AAAA,UAEhE,SAAS,CAAC,mBAAmB;AAC3B,kBAAM,QAAQ,aAAa,eAAe,SAAS,EAAE,MAAM,KAAK;AAChE,mBAAO,EAAE,aAAa,MAAM,aAAa,cAAc,MAAM,aAAa;AAAA,UAC5E;AAAA,QACF,CAAC;AACD,sBAAc,IAAI,YAAY,KAAK;AAAA,MACrC;AACA,aAAO,MAAM,KAAK,OAAO;AAAA,IAC3B;AAAA,EACF;AAGN,QAAM,iBACJ,MAAM,mBAAmB,SACrB,SACA,yBAAyB;AAAA,IACvB,YAAY,MAAM;AAAA,IAClB,KAAK,MAAM,MAAM,IAAI;AAAA;AAAA,IAErB,gBAAgB,CAAC,UAAU,cAAc;AACvC,mBAAa,SAAS,EAAE,MAAM,gBAAgB,QAAQ;AAAA,IACxD;AAAA,EACF,CAAC;AAEP,QAAM,WAAW,iBAAiB;AAAA,IAChC,OAAO;AAAA;AAAA,IAEP,OAAO;AAAA,IACP,WAAW,MAAM,iBAAiB;AAAA,IAClC,YAAY;AAAA;AAAA,IAEZ,MAAM;AAAA,MACJ,UAAU,CAAC,UAAW,UAAU,aAAa,uBAAuB;AAAA,IACtE;AAAA;AAAA,IAEA,QAAQ,OAAO,YAAY,aAAa,WAAW;AACjD,UAAI,qBAAqB,QAAW;AAClC,cAAM,IAAI,UAAU,wDAAwD;AAAA,MAC9E;AACA,YAAM,UAAU,MAAM,eAAe,kBAAkB,YAAY,aAAa,MAAM;AACtF,YAAM,OAAO,mBAAmB,kBAAkB,YAAY,OAAO;AACrE,aAAO,mBAAmB,EAAE,SAAS,GAAG,KAAK,GAAG,0BAA0B,MAAM,IAAI;AAAA,IACtF;AAAA,IACA,GAAI,gBAAgB,SAAY,CAAC,IAAI,EAAE,SAAS,YAAY;AAAA,IAC5D,GAAI,mBAAmB,SAAY,CAAC,IAAI,EAAE,YAAY,eAAe;AAAA;AAAA,IAErE,YAAY,CAAC,eAAe;AAAA;AAAA,MAE1B,UAAU,OAAO,WAAW,aAAa;AACvC,YAAI,cAAc,WAAW,aAAa,UAAa,MAAM,iBAAiB,QAAW;AACvF,2BAAiB,IAAI,UAAU,MAAM,MAAM,aAAa,QAAQ,CAAC;AAAA,QACnE;AAAA,MACF;AAAA,MACA,OAAO,OAAO,SAAS;AACrB,cAAM,QAAQ,aAAa,SAAS;AACpC,cAAM,OAAO,MAAM,MAAM,KAAK,EAAE;AAKhC,YAAI,MAAM,iBAAiB,UAAa,CAAC,iBAAiB,IAAI,IAAI,GAAG;AAEnE,2BAAiB,IAAI,MAAM,MAAM,MAAM,aAAa,IAAI,CAAC;AAAA,QAC3D;AACA,cAAM,MAAM,eAAe,IAAI;AAC/B,eAAO,EAAE,MAAM,IAAI,MAAM,MAAM,UAAU,IAAI,WAAM,IAAI,GAAG;AAAA,MAC5D;AAAA,MACA,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AACV,qBAAa,SAAS,EAAE,MAAM,aAAa;AAC3C,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,OAAO,CAAC,cAAc,aAAa,SAAS,EAAE;AAAA;AAAA,IAE9C,QAAQ,CAAC,cAA+B;AACtC,YAAM,MAAM,eAAe,gBAAgB;AAC3C,aAAO;AAAA,QACL,OAAO,MAAM,KAAK,iBAAiB,SAAS,CAAC;AAAA,QAC7C,SAAS,EAAE,MAAM,gBAAgB,gBAAgB,GAAG,IAAI;AAAA,MAC1D;AAAA,IACF;AAAA;AAAA,IAEA,GAAI,MAAM,mBAAmB,UAAa,MAAM,iBAAiB,SAC7D,EAAE,mBAAmB,MAAO,MAAM,eAAsC,sBAAsB,EAAE,IAChG,CAAC;AAAA;AAAA,IAEL,GAAI,MAAM,gBAAgB,SAAY,CAAC,IAAI,EAAE,SAAS,MAAM,YAAY;AAAA,IACxE,KAAK,MAAM,MAAM,IAAI;AAAA,IACrB,YAAY,MAAM,QAAQN,YAAW,CAAC;AAAA,EACxC,CAAC;AAGD,QAAM,oBAAoB,MAAM,mBAAmB,UAAa,MAAM,iBAAiB,SACnF,MAAM,iBACN;AAGJ,QAAM,kBAA2C;AAAA,IAC/C,UAAU,yBAAyB,EAAE,oBAAoB,MAAM,MAAM,YAAY,CAAC;AAAA,IAClF,YAAY;AAAA,MACV,MAAM,YAAa,MAAM,2BAA2B;AAAA,QAClD,sBAAsB,MAAM;AAAA,QAC5B,KAAK,MAAM,MAAM,IAAI;AAAA,QACrB,kBAAkB,MAAM;AAAA,QACxB,GAAI,MAAM,2BAA2B,SACjC,CAAC,IACD,EAAE,wBAAwB,MAAM,uBAAuB;AAAA,MAC7D,CAAC,EAAE,KAAK;AAAA,IACV;AAAA;AAAA,IAEA,UAAU;AAAA,MACR,SAAS,OAAO,SAAiB,aAAqB;AACpD,cAAM,gBAAgB,MAAM,MAAM,cAAc;AAChD,cAAM,OAAO,YAAY,aAAa;AACtC,YAAI,CAACJ,YAAW,IAAI,EAAG,QAAO,CAAC;AAC/B,cAAM,KAAK,IAAIK,cAAa,MAAM,EAAE,UAAU,KAAK,CAAC;AACpD,YAAI;AACF,iBAAO,gBAAgB,IAAI,EAAE,SAAS,SAAS,CAAC,EAC7C,IAAI,CAAC,cAAc,EAAE,UAAU,SAAS,EAAE;AAAA,QAC/C,SAAS,OAAO;AACd,cAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,eAAe,EAAG,QAAO,CAAC;AAC/E,gBAAM;AAAA,QACR,UAAE;AACA,aAAG,MAAM;AAAA,QACX;AAAA,MACF;AAAA,MACA,aAAa,OAAO,SAAiB,UAAkB,aAAqB;AAC1E,cAAM,gBAAgB,MAAM,MAAM,cAAc;AAChD,cAAM,UAAU,yBAAyB,eAAe,EAAE,SAAS,UAAU,SAAS,CAAC;AACvF,YAAI,YAAY,OAAW,QAAO,CAAC;AACnC,eAAO,QAAQ,aAAa,IAAI,CAAC,UAAW,MAAM,SAAS,WAAW,QAAS;AAAA,MACjF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,uBAAuB;AAAA,IACtC,MAAM;AAAA,MACJ,YAAY,MAAM;AAAA,MAClB,MAAM;AAAA,QACJ,GAAG;AAAA,QACH,KAAK,OAAO,UAAU;AACpB,gBAAM,WAAW,MAAM;AACvB,iBAAO,WAAW,IAAI,KAAK;AAAA,QAC7B;AAAA,MACF;AAAA;AAAA,MAEA,WAAW;AAAA,QACT,MAAM;AAAA,QACN,yBAAyB,qBAAqB;AAAA,MAChD;AAAA,MACA,QAAQ,MAAM;AAAA,MACd,UAAU,sBAAsB,qBAAqB;AAAA;AAAA,MAErD,iBAAiB,sBAAsB;AAAA,QACrC,aAAa,MAAM;AAAA,QACnB,sBAAsB,MAAM;AAAA,QAC5B,GAAI,MAAM,4BAA4B,SAClC,CAAC,IACD,EAAE,yBAAyB,MAAM,wBAAwB;AAAA,QAC7D,GAAI,MAAM,2BAA2B,SACjC,CAAC,IACD,EAAE,wBAAwB,MAAM,uBAAuB;AAAA;AAAA,QAE3D,GAAI,MAAM,4BAA4B,SAClC,CAAC,IACD,EAAE,yBAAyB,MAAM,wBAAwB;AAAA,MAC/D,CAAC;AAAA;AAAA,MAED,gBAAgB,2BAA2B;AAAA,QACzC,aAAa,MAAM;AAAA,QACnB,UAAU,MAAM,YAAY;AAAA,MAC9B,CAAC;AAAA;AAAA,MAED,GAAI,MAAM,cAAc,SAAY,CAAC,IAAI,EAAE,WAAW,MAAM,UAAU;AAAA;AAAA,MAEtE,eAAe,yBAAyB,EAAE,aAAa,MAAM,YAAY,CAAC;AAAA;AAAA,MAE1E,GAAI,MAAM,iBAAiB,SAAY,CAAC,IAAI;AAAA,QAC1C,eAAe,yBAAyB;AAAA,UACtC,aAAa,MAAM;AAAA,UACnB,WAAW,MAAM;AAAA,QACnB,CAAC;AAAA,MACH;AAAA;AAAA,MAEA,UAAU,6BAA6B,MAAM,WAAW;AAAA,MACxD,YAAY,WAAW;AAAA;AAAA,MAEvB,GAAI,MAAM,sBAAsB,SAC5B,CAAC,IACD,EAAE,mBAAmB,MAAM,kBAAkB;AAAA;AAAA,MAEjD,GAAI,MAAM,aAAa,SAAY,CAAC,IAAI,EAAE,UAAU,MAAM,SAAS;AAAA;AAAA,MAEnE;AAAA,MACA,GAAI,MAAM,aAAa,SAAY,CAAC,IAAI,EAAE,UAAU,MAAM,SAAS;AAAA,MACnE,GAAI,MAAM,kBAAkB,SAAY,CAAC,IAAI,EAAE,eAAe,MAAM,cAAc;AAAA,MAClF,YAAY,2BAA2B;AAAA,QACrC,sBAAsB,MAAM;AAAA,QAC5B,KAAK,MAAM,MAAM,IAAI;AAAA,QACrB,kBAAkB,MAAM;AAAA,QACxB,GAAI,MAAM,2BAA2B,SACjC,CAAC,IACD,EAAE,wBAAwB,MAAM,uBAAuB;AAAA,MAC7D,CAAC;AAAA;AAAA,MAED,UAAU;AAAA;AAAA;AAAA,QAGR,SAAS,OAAM,cACb,mBAAmB,MAAM,SAAS,QAAQ,SAAS,GAAG,wBAAwB,MAAM,IAAI;AAAA,MAC5F;AAAA;AAAA,MAEA,GAAI,MAAM,mBAAmB,UAAa,MAAM,iBAAiB,SAAY,CAAC,IAAI;AAAA,QAChF,iBAAiB,sBAAsB;AAAA,UACrC,WAAW,MAAM;AAAA,UACjB,aAAa,MAAM;AAAA,UACnB,eAAe,MAAM;AAAA,UACrB;AAAA,UACA,SAAS,CAAC,UAAU,WAAW,IAAI,KAAc;AAAA,UACjD,cAAc,OAAO,YAAY;AAC/B,gBAAI,qBAAqB,QAAW;AAClC,oBAAM,IAAI,UAAU,2DAA2D;AAAA,YACjF;AACA,mBAAO,MAAM;AAAA,cACX;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA;AAAA,MAEA,GAAI,sBAAsB,SAAY,CAAC,IAAI;AAAA,QACzC,eAAe;AAAA,UACb,MAAM,kBAAkB,QAAgB,OAA0C;AAChF,kBAAM,gBAAgB,MAAM,MAAM,cAAc;AAChD,mBAAO,sBAAsB,EAAE,cAAc,CAAC,EAAE,kBAAkB,QAAQ,KAAK;AAAA,UACjF;AAAA,UACA,iBAAiB,MAAM,kBAAkB,gBAAgB;AAAA;AAAA,UAEzD,uBAAuB,MAAM,kBAAkB,sBAAsB;AAAA,QACvE;AAAA;AAAA,QAEA,gBAAgB;AAAA,UACd,eAAe,MAAM,kBAAkB,mBAAmB;AAAA,QAC5D;AAAA,QACA,YAAY;AAAA,UACV,OAAO,YAAY,MAAM,MAAM,MAAM;AAAA,UACrC,OAAO,CAAC,aAAqB,kBAAkB,WAAW,QAAQ;AAAA;AAAA,UAElE,cAAc,CAAC,OAAO,aAAa,kBAAkB,oBAAoB,OAAO,QAAQ;AAAA;AAAA,UAExF,SAAS,CAAC,YAAY,kBAAkB,aAAa,OAAO;AAAA;AAAA,UAE5D,MAAM;AAAA,YACJ,OAAO,OAAO,YAA8C;AAC1D,kBAAI,qBAAqB,QAAW;AAClC,sBAAM,IAAI,UAAU,+DAA+D;AAAA,cACrF;AACA,qBAAO,MAAM;AAAA,gBACX;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,YACA,KAAK,CAAC,UAAkB,WAAW,IAAI,KAAc;AAAA,UACvD;AAAA,UACA,aAAa,OAAO,gBAAkE;AACpF,gBAAI,qBAAqB,QAAW;AAClC,oBAAM,IAAI,UAAU,6DAA6D;AAAA,YACnF;AACA,mBAAO,MAAM;AAAA,cACX;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA;AAAA,MAEA,GAAI,MAAM,gBAAgB,SAAY,CAAC,IAAI,EAAE,aAAa,MAAM,YAAY;AAAA,MAC5E,GAAI,MAAM,mBAAmB,SAAY,CAAC,IAAI,EAAE,gBAAgB,MAAM,eAAe;AAAA,MACrF,GAAI,MAAM,oBAAoB,SAC1B,CAAC,IACD,EAAE,iBAAiB,MAAM,gBAAgB;AAAA,MAC7C,GAAI,MAAM,gBAAgB,SAAY,CAAC,IAAI,EAAE,aAAa,MAAM,YAAY;AAAA,IAC9E;AAAA,EACF,CAAC;AAID,qBAAmB;AAEnB,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,sBAAsB;AAC1B,MAAI,SAAS;AAEb,iBAAe,SAAS,gBAAiD;AACvE,UAAM,QAAQ,MAAM,MAAM,MAAM;AAGhC,UAAM,gBAAgB,MAAM,MAAM,cAAc;AAChD,UAAM,sBAAsB,MAAM,wBAAwB,SACtD,SACA,MAAM,MAAM,oBAAoB;AACpC,UAAM,QAAQ,qBAAqB;AAAA,MACjC,MAAMT,MAAK,MAAM,aAAa,uBAAuB;AAAA,MACrD;AAAA,MACA,aAAa,yBAAyB,EAAE,MAAM,MAAM,YAAY,CAAC;AAAA,IACnE,CAAC;AACD,QAAI;AACJ,QAAI;AACF,YAAM,QAAQ,MAAM,YACf;AAAA,QACD,oBAAoB,OAAO,eAAe,mBAAmB;AAAA,MAC/D;AAIF,YAAM,WAAW,MAAM,YAAY;AAEnC,YAAM,mBACF,6BAA6B,MAAM,SAAS,kBAAkB,WAAW;AAC7E,aAAO;AAAA,QACL,OAAO,oBAAoB;AAAA,UACzB;AAAA,UACA,UAAU;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA,GAAI,iBAAiB,WAAW,IAAI,CAAC,IAAI,EAAE,iBAAiB;AAAA,QAC9D,CAAC;AAAA,QACD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,MAAM;AACZ,YAAM;AAAA,IACR;AACA,QAAI,UAAU,mBAAmB,qBAAqB;AAGpD,YAAM,MAAM;AACZ,YAAM,IAAI,sBAAsB,MAAM,WAAW;AAAA,IACnD;AACA,aAAS;AACT,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,MACJ,UAAU,CAAC,cAAc,WAAW,IAAI,SAAS,GAAG,MAAM,KAAK;AAAA,MAC/D,MAAM,kBAAiC;AAErC,mBAAW,CAAC,WAAW,KAAK,KAAK,kBAAkB;AACjD,gBAAM,SAAS,WAAW,IAAI,SAAS,GAAG,MAAM,KAAK,EAAE;AACvD,cAAI,WAAW,OAAW;AAC1B,cAAI,CAAC,MAAM,QAAQ,IAAI,MAAM,EAAG;AAChC,gBAAM,MAAM,OAAO,OAAO;AAAA,YACxB,MAAM;AAAA,YACN;AAAA,YACA,IAAI,MAAM,IAAI;AAAA,YACd,QAAQ;AAAA,UACV,CAAC;AAID,gBAAM,MAAM,OAAO,aAAa;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,OAAgC;AAC9B,UAAI,OAAQ,QAAO,QAAQ,OAAO,IAAI,sBAAsB,MAAM,WAAW,CAAC;AAG9E,kBAAY,SAAS,mBAAmB;AACxC,aAAO;AAAA,IACT;AAAA,IACA,QAAuB;AACrB,UAAI,YAAY,OAAW,QAAO;AAClC,eAAS;AACT,6BAAuB;AACvB,YAAM,UAAU;AAChB,YAAM,UAAU;AAChB,eAAS;AAET,eAAS,MAAM,MAAM;AACrB,iBAAW,YAAY;AACrB,YAAI,YAAY,QAAW;AACzB,cAAI;AACF,kBAAM,OAAO,MAAM;AACnB,gBAAI,SAAS,QAAS,MAAK,MAAM,MAAM;AAAA,UACzC,QAAQ;AAAA,UAER;AAAA,QACF;AACA,kBAAU;AAAA,MACZ,GAAG;AACH,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AS3mEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;;;ACPhC,SAAS,aAAAe,YAAW,cAAAC,aAAY,aAAAC,YAAW,YAAAC,WAAU,gBAAAC,eAAc,cAAAC,aAAY,YAAY,iBAAAC,sBAAqB;AAChH,SAAS,QAAAC,aAAY;AAErB;AAAA,EACE,iBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAAC;AAAA,OAGK;AACP,SAAS,KAAAC,UAAS;;;ACXlB,SAAS,gBAAAC,eAAc,eAAAC,cAAa,2BAAAC,gCAA+B;;;ACDnE,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,aAAAC,YAAW,aAAAC,YAAW,WAAW,aAAAC,YAAW,YAAAC,WAAU,gBAAAC,eAAc,cAAAC,aAAY,UAAAC,SAAQ,iBAAAC,sBAAqB;AACtH,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAC9B,SAAS,SAAS;AAElB,IAAM,cAAc,EAAE,OAAO;AAAA,EAAE,eAAe,EAAE,QAAQ,CAAC;AAAA,EAAG,MAAM,EAAE,QAAQ,kBAAkB;AAAA,EAC5F,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EAAG,OAAO,EAAE,KAAK;AAAA,EAAG,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AAAE,CAAC,EAAE,OAAO;AAGxF,SAAS,cAAc,MAAoB;AACzC,QAAM,KAAKN,UAAS,MAAM,GAAG;AAC7B,MAAI;AAAE,IAAAF,WAAU,EAAE;AAAA,EAAE,UAAE;AAAU,IAAAD,WAAU,EAAE;AAAA,EAAE;AAChD;AAEA,SAAS,UAAU,MAAc,OAAkC;AACjE,MAAI;AACF,UAAM,YAAY,UAAU,IAAI;AAChC,QAAI,CAAC,UAAU,YAAY,KAAK,UAAU,eAAe,EAAG,QAAO;AACnE,UAAM,YAAYS,MAAK,MAAM,YAAY;AACzC,UAAM,OAAO,UAAU,SAAS;AAChC,QAAI,CAAC,KAAK,OAAO,KAAK,KAAK,eAAe,EAAG,QAAO;AACpD,UAAM,SAAS,YAAY,UAAU,KAAK,MAAML,cAAa,WAAW,MAAM,CAAC,CAAC;AAChF,WAAO,OAAO,WAAW,OAAO,KAAK,UAAU,QAAQ,OAAO,OAAO;AAAA,EACvE,QAAQ;AAAE,WAAO;AAAA,EAAU;AAC7B;AAEA,SAAS,eAAe,KAAsB;AAC5C,MAAI;AAAE,YAAQ,KAAK,KAAK,CAAC;AAAG,WAAO;AAAA,EAAM,SAClC,OAAO;AAAE,WAAQ,MAAgC,SAAS;AAAA,EAAQ;AAC3E;AAGA,eAAsB,gBAAgB,MAAc,OAAe,MAAwC;AACzG,QAAM,QAAe,EAAE,eAAe,GAAG,MAAM,oBAAoB,KAAK,QAAQ,KAAK,OAAOL,YAAW,GAAG,MAAM;AAChH,QAAM,YAAY,GAAG,IAAI,cAAc,MAAM,KAAK;AAClD,EAAAG,WAAU,SAAS;AACnB,QAAM,KAAKC,UAASM,MAAK,WAAW,YAAY,GAAG,MAAM,GAAK;AAC9D,MAAI;AAAE,IAAAF,eAAc,IAAI,KAAK,UAAU,KAAK,CAAC;AAAG,IAAAN,WAAU,EAAE;AAAA,EAAE,UAAE;AAAU,IAAAD,WAAU,EAAE;AAAA,EAAE;AACxF,gBAAc,SAAS;AACvB,QAAM,UAAU,KAAK,IAAI;AACzB,MAAI,WAAW;AACf,MAAI;AACF,WAAO,CAAC,UAAU;AAChB,UAAI;AAGF,QAAAE,WAAU,IAAI;AACd,QAAAG,YAAWI,MAAK,WAAW,YAAY,GAAGA,MAAK,MAAM,YAAY,CAAC;AAClE,sBAAc,IAAI;AAClB,sBAAcD,SAAQ,IAAI,CAAC;AAC3B,QAAAF,QAAO,WAAW,EAAE,WAAW,KAAK,CAAC;AACrC,mBAAW;AAAA,MACb,SAAS,OAAO;AACd,YAAI,CAAC,CAAC,UAAU,aAAa,WAAW,UAAU,SAAS,QAAQ,EAAE,SAAU,MAAgC,QAAQ,EAAE,EAAG,OAAM;AAClI,cAAM,UAAU,UAAU,MAAM,KAAK;AACrC,YAAI,YAAY,UAAa,eAAe,QAAQ,GAAG,GAAG;AACxD,cAAI;AAGF,YAAAD,YAAW,MAAM,GAAG,IAAI,SAAS,QAAQ,KAAK,EAAE;AAChD,0BAAcG,SAAQ,IAAI,CAAC;AAC3B;AAAA,UACF,SAAS,eAAe;AACtB,gBAAK,cAAwC,SAAS,SAAU;AAChE,gBAAI,CAAC,CAAC,UAAU,aAAa,WAAW,UAAU,SAAS,QAAQ,EAAE,SAAU,cAAwC,QAAQ,EAAE,EAAG,OAAM;AAAA,UAC5I;AAAA,QACF;AACA,cAAM,YAAY,OAAU,KAAK,IAAI,IAAI;AACzC,YAAI,aAAa,EAAG,OAAM,KAAK;AAC/B,cAAM,IAAI,QAAQ,CAAAE,aAAW,WAAWA,UAAS,KAAK,IAAI,IAAI,SAAS,CAAC,CAAC;AAAA,MAC3E;AAAA,IACF;AAAA,EACF,UAAE;AACA,QAAI,CAAC,SAAU,CAAAJ,QAAO,WAAW,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACnE;AACA,SAAO,MAAM;AACX,QAAI,UAAU,MAAM,KAAK,GAAG,UAAU,MAAM,MAAO;AACnD,UAAM,WAAW,GAAG,IAAI,aAAa,MAAM,KAAK;AAChD,IAAAD,YAAW,MAAM,QAAQ;AACzB,kBAAcG,SAAQ,IAAI,CAAC;AAC3B,IAAAF,QAAO,UAAU,EAAE,WAAW,KAAK,CAAC;AACpC,kBAAcE,SAAQ,IAAI,CAAC;AAAA,EAC7B;AACF;;;AFnEO,IAAM,oBAAoB;AAC1B,IAAM,yBAAyB;AAE/B,IAAM,mBAAmB;AAQzB,IAAM,qBAAqB,CAAC,YAAY,YAAY,SAAS;AACpE,IAAM,eAAeG,GAAE,OAAO;AAAA,EAC5B,eAAeA,GAAE,QAAQ,CAAC;AAAA,EAAG,MAAM;AAAA,EACnC,OAAOA,GAAE,KAAK,kBAAkB;AAAA,EAChC,aAAaA,GAAE,KAAK;AAAA,EACpB,MAAM,sBAAsB,SAAS;AACvC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,QAAQ,QAAQ;AACvC,MAAI,OAAO,UAAU,aAAa,OAAO,KAAK,YAAY,SAAS,WAAW;AAC5E,QAAI,SAAS,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,aAAa,GAAG,SAAS,iDAAiD,CAAC;AAAA,EAC3H;AACF,CAAC;AAGD,SAAS,cAAc,MAAc,MAAoB;AACvD,QAAM,SAAS,GAAG,IAAI;AACtB,QAAM,KAAKC,UAAS,QAAQ,KAAK,GAAK;AACtC,MAAI;AAAE,IAAAC,eAAc,IAAI,IAAI;AAAG,IAAAC,WAAU,EAAE;AAAA,EAAE,UAAE;AAAU,IAAAC,WAAU,EAAE;AAAA,EAAE;AACvE,EAAAC,YAAW,QAAQ,IAAI;AACzB;AAEO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C,cAAc;AACZ,UAAM,4EAA4E;AAClF,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAChD,YAAqB,MAAc;AAEjC,UAAM,kCAAkC,IAAI,EAAE;AAF3B;AAGnB,SAAK,OAAO;AAAA,EACd;AACF;AAOO,IAAM,0BAAN,cAAsC,MAAM;AAAA,EACjD,YACW,YACA,QACT;AACA,UAAM,OAAO,WAAW,oBACpB,iFACA,WAAW,eAAe,kBAAkB;AAEhD,UAAM,8BAA8B,UAAU,IAAI,IAAI,0DAChC;AARb;AACA;AAQT,SAAK,OAAO;AAAA,EACd;AACF;AAGA,SAAS,uBAAuB,OAAyB;AACvD,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,QAAM,SAAS;AACf,SAAO,kBAAkB,UAAU,eAAe,UAAU,OAAO,OAAO,MAAM;AAClF;AAGO,SAAS,6BAA6B,UAAiD;AAC5F,QAAM,SAAS,oBAAI,IAAyB;AAC5C,aAAW,WAAW,UAAU;AAC9B,UAAM,MAAM,eAAe,OAAO;AAClC,SAAK,OAAO,IAAI,GAAG,GAAG,WAAW,KAAK,QAAQ,QAAS,QAAO,IAAI,KAAK,OAAO;AAAA,EAChF;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE;AAAA,IAAK,CAAC,GAAG,MACnC,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,OAAO,EAAE,aAAa;AAAA,EACrE;AACF;AAEO,SAAS,qBACd,UACA,OACA,SACyB;AACzB,MAAI,QAAQ,UAAU,MAAO,QAAO;AACpC,SAAO,6BAA6B,QAAQ,EAAE,KAAK,aAAW,eAAe,OAAO,MAAM,eAAe,OAAO,MAC1G,QAAQ,WAAW,UAAa,QAAQ,WAAW,QAAQ,OAAO;AAC1E;AAEO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC9C,cAAc;AACZ,UAAM,6DAA6D;AACnE,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,eAAN,MAAmB;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,gBAAgB;AAAA,EAChB;AAAA,EAER,YAAY,QAAyC;AACnD,SAAK,QAAQ,OAAO;AACpB,SAAK,UAAUC,YAAW,OAAO,KAAK;AACtC,SAAK,MAAMC,MAAK,OAAO,MAAMC,cAAa,KAAK,OAAO;AACtD,SAAK,OAAOD,MAAK,KAAK,KAAK,iBAAiB;AAC5C,SAAK,OAAOA,MAAK,KAAK,KAAK,sBAAsB;AAAA,EACnD;AAAA,EAEA,OAAsB;AACpB,QAAI;AACJ,QAAI;AACF,aAAOE,cAAa,KAAK,MAAM,MAAM;AAAA,IACvC,SAAS,OAAO;AACd,UAAK,MAAgC,SAAS,SAAU,QAAO,CAAC;AAChE,YAAM;AAAA,IACR;AACA,QAAI,SAAS,GAAI,QAAO,CAAC;AACzB,UAAM,QAAQ,KAAK,MAAM,IAAI;AAE7B,QAAI,MAAM,IAAI,MAAM,GAAI,OAAM,IAAI,uBAAuB,MAAM,SAAS,CAAC;AACzE,WAAO,MAAM,IAAI,CAAC,MAAM,UAAU;AAChC,UAAI;AACF,cAAM,UAAU,kBAAkB,MAAM,KAAK,MAAM,IAAI,CAAC;AACxD,YAAI,QAAQ,YAAY,QAAQ,KAAK,QAAQ,UAAU,KAAK,SAAS,QAAQ,YAAY,KAAK,SAAS;AACrG,gBAAM,IAAI,MAAM,qCAAqC;AAAA,QACvD;AACA,eAAO;AAAA,MACT,QAAQ;AACN,cAAM,IAAI,uBAAuB,QAAQ,CAAC;AAAA,MAC5C;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,mBAAkC;AAChC,WAAO,6BAA6B,KAAK,KAAK,CAAC;AAAA,EACjD;AAAA,EAEA,UAAU,SAA+C;AAEvD,QAAI,QAAQ,UAAU,KAAK,MAAO,QAAO;AACzC,WAAO,qBAAqB,KAAK,KAAK,GAAG,KAAK,OAAO,OAAO;AAAA,EAC9D;AAAA;AAAA,EAGA,cAAc,MAAmB,aAAiC;AAChE,QAAI,CAAC,KAAK,cAAe,OAAM,IAAI,MAAM,0CAA0C;AACnF,UAAM,QAAQ,KAAK;AACnB,QAAI,UAAU,QAAW;AACvB,YAAM,UAAU,CAAC,WAAwB;AAAA,QAAE,OAAO,MAAM;AAAA,QAAO,WAAW,MAAM;AAAA,QAC9E,QAAQ,MAAM;AAAA,QAAQ,WAAW,MAAM;AAAA,QAAW,MAAM,MAAM;AAAA,QAAM,MAAM,MAAM;AAAA,MAAK;AACvF,UAAIC,eAAc,QAAQ,MAAM,IAAI,CAAC,MAAMA,eAAc,QAAQ,IAAI,CAAC,GAAG;AACvE,cAAM,IAAI,MAAM,6EAA6E;AAAA,MAC/F;AACA,aAAO;AAAA,IACT;AACA,WAAO,KAAK,iBAAiB,EAAE,eAAe,GAAG,MAAM,aAAa,OAAO,WAAW,CAAC;AAAA,EACzF;AAAA,EAEA,iBAAiB,OAA+B;AAC9C,QAAI,CAAC,KAAK,cAAe,OAAM,IAAI,MAAM,0CAA0C;AACnF,UAAM,SAAS,aAAa,MAAM,KAAK;AACvC,QAAI,OAAO,KAAK,UAAU,KAAK,SAAS,OAAO,KAAK,YAAY,KAAK,WAChE,OAAO,KAAK,YAAY,KAAK,KAAK,EAAE,SAAS,EAAG,OAAM,IAAI,uBAAuB,OAAO,KAAK,OAAO;AACzG,kBAAcH,MAAK,KAAK,KAAK,gBAAgB,GAAG,GAAGG,eAAc,MAAM,CAAC;AAAA,CAAI;AAC5E,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SACJ,IACkC;AAClC,QAAI,CAACC,YAAWJ,MAAK,KAAK,KAAKK,aAAY,CAAC,EAAG,OAAM,IAAI,qBAAqB;AAC9E,UAAM,UAAU,MAAM,gBAAgB,KAAK,MAAM,KAAK,OAAO,MAAM,IAAI,oBAAoB,CAAC;AAC5F,QAAI;AAEF,YAAM,WAAW,KAAK,KAAK;AAC3B,YAAM,cAAc,SAAS,SAAS;AACtC,YAAM,aAAaL,MAAK,KAAK,KAAK,gBAAgB;AAClD,WAAK,cAAc;AACnB,UAAII,YAAW,UAAU,GAAG;AAC1B,YAAI;AACJ,YAAI;AACF,gBAAM,KAAK,MAAMF,cAAa,YAAY,MAAM,CAAC;AAAA,QACnD,QAAQ;AAAE,gBAAM,IAAI,wBAAwB,YAAY,YAAY;AAAA,QAAE;AACtE,cAAM,SAAS,aAAa,UAAU,GAAG;AACzC,YAAI,CAAC,OAAO,SAAS;AACnB,gBAAM,IAAI;AAAA,YAAwB;AAAA,YAChC,uBAAuB,GAAG,IAAI,oBAAoB;AAAA,UAAY;AAAA,QAClE;AACA,cAAM,SAAS,OAAO;AACtB,YAAI,OAAO,KAAK,UAAU,KAAK,SAAS,OAAO,KAAK,YAAY,KAAK,SAAS;AAC5E,gBAAM,IAAI,wBAAwB,YAAY,YAAY;AAAA,QAC5D;AACA,YAAI,OAAO,KAAK,YAAY,YAAa,MAAK,cAAc;AAAA,iBACnDC,eAAc,SAAS,OAAO,KAAK,UAAU,CAAC,CAAC,MAAMA,eAAc,OAAO,IAAI,EAAG,YAAW,UAAU;AAAA,YAC1G,OAAM,IAAI,wBAAwB,YAAY,YAAY;AAAA,MACjE;AACA,WAAK,gBAAgB;AACrB,YAAM,SAAS,MAAM,GAAG,WAAW;AACnC,UAAI,WAAW,OAAW,QAAO;AACjC,YAAM,UAAU,kBAAkB,MAAM,EAAE,GAAG,QAAQ,SAAS,YAAY,CAAC;AAC3E,UAAI,QAAQ,UAAU,KAAK,SAAS,QAAQ,YAAY,KAAK,SAAS;AACpE,cAAM,IAAI,MAAM,iDAAiD;AAAA,MACnE;AACA,UAAI,KAAK,gBAAgB,WAAc,KAAK,YAAY,UAAU,aAC7DA,eAAc,KAAK,YAAY,IAAI,MAAMA,eAAc,OAAO,IAAI;AACrE,cAAM,IAAI,uBAAuB,WAAW;AAAA,MAC9C;AAEA,YAAM,SAASC,YAAW,KAAK,IAAI,IAAIF,cAAa,KAAK,MAAM,MAAM,IAAI;AACzE,oBAAc,KAAK,MAAM,GAAG,MAAM,GAAGC,eAAc,OAAO,CAAC;AAAA,CAAI;AAC/D,UAAI,KAAK,gBAAgB,OAAW,YAAW,UAAU;AACzD,aAAO;AAAA,IACT,UAAE;AACA,WAAK,gBAAgB;AACrB,WAAK,cAAc;AACnB,cAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,OAAO,QAAwE;AAC7E,WAAO,KAAK,SAAS,YAAY,MAAM;AAAA,EACzC;AACF;;;AGzPA,SAAS,wBAAwB;;;ACAjC,SAAS,QAAAG,cAAY;AAErB,SAAS,uBAAAC,sBAAqB,6BAAAC,kCAAiC;AAwBxD,IAAM,gCAAgC;AAsCtC,SAAS,mBAAmB,OAAiD;AAClF,QAAM,QAAQ,qBAAqB;AAAA,IACjC,MAAMC,OAAK,MAAM,aAAa,uBAAuB;AAAA,IACrD,OAAO,MAAM;AAAA,IACb,aAAa,yBAAyB,EAAE,MAAM,MAAM,YAAY,CAAC;AAAA,EACnE,CAAC;AACD,QAAM,QAAQ,MAAM,YAAYC,2BAA0B;AAC1D,QAAM,QAAQC,qBAAoB;AAAA,IAChC;AAAA,IACA,UAAU;AAAA,IACV,OAAO,MAAM;AAAA,IACb,UAAU,MAAM;AAAA,IAChB,OAAO,MAAM;AAAA,EACf,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IAEA,uBAAuB,OAA8D;AACnF,aAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC;AAAA,IAC/C;AAAA,IAEA,MAAM,cACJ,OACA,UAAkB,+BACqB;AACvC,YAAM,WAAgC,CAAC;AACvC,iBAAS;AACP,YAAI,SAAS,UAAU,SAAS;AAC9B,gBAAM,IAAI;AAAA,YACR,0BAA0B,OAAO;AAAA,UAGnC;AAAA,QACF;AACA,cAAM,UAAU,MAAM,MAAM,WAAW,EAAE,MAAM,CAAC;AAChD,YAAI,CAAC,QAAQ,IAAK,QAAO;AACzB,iBAAS,KAAK,OAAO;AAAA,MACvB;AAAA,IACF;AAAA,IAEA,QAAc;AACZ,YAAM,MAAM;AAAA,IACd;AAAA,EACF;AACF;;;AC/GA,SAAS,iBAAAC,sBAAqB;AAC9B,SAAS,uCAAAC,4CAA2C;AA2B7C,SAAS,uBACd,SACkB;AAClB,QAAM,WAAW,oBAAI,IAAuE;AAC5F,QAAM,SAAS,QAAQ,UAAU,KAAK;AAEtC,QAAM,eAAe,oBAAI,IAAY;AAErC,WAAS,UAAU,IAAY,QAA8C;AAC3E,QAAI,OAAO;AACX,UAAM,cAAc,CAAC,SAAuB;AAC1C,UAAI,CAAC,MAAM;AACT,cAAM,IAAI;AAAA,UACR,kBAAkB,IAAI,0CAA0C,EAAE;AAAA,QAEpE;AAAA,MACF;AAAA,IACF;AACA,iBAAa,IAAI,EAAE;AACnB,WAAO;AAAA,MACL,QAAQ,OAAO;AAAA,MACf,QAAQ,OAAO;AAAA,MACf,cAAc,OAAO;AAAA,MACrB,OAAO,OAAwC;AAC7C,oBAAY,OAAO;AACnB,iBAAS,IAAI,EAAE,EAAG,OAAO,KAAK,KAAK;AACnC,eAAO,QAAQ,QAAQ;AAAA,MACzB;AAAA,MACA,eAA8B;AAG5B,oBAAY,eAAe;AAC3B,eAAO,QAAQ,QAAQ;AAAA,MACzB;AAAA,MACA,QAAuB;AACrB,YAAI,MAAM;AACR,iBAAO;AACP,uBAAa,OAAO,EAAE;AAAA,QACxB;AACA,eAAO,QAAQ,QAAQ;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK,WAAgD;AACnD,UAAI,cAAc,QAAW;AAC3B,cAAM,WAAW,SAAS,IAAI,SAAS;AAGvC,YAAI,aAAa,OAAW,OAAM,IAAI,wBAAwB,SAAS;AACvE,YAAI,aAAa,IAAI,SAAS,EAAG,OAAM,IAAI,qBAAqB,SAAS;AAMzE,cAAM,SAASC;AAAA,UACb,SAAS,OAAO,IAAI,CAAC,OAAO,WAAW;AAAA,YACrC,YAAY,QAAQ;AAAA,YACpB,MAAM,KAAK,UAAU,KAAK;AAAA,UAC5B,EAAE;AAAA,UACF,EAAE,iBAAiB,SAAS,OAAO,eAAe,KAAK,QAAQ,IAAI;AAAA,QACrE;AACA,iBAAS,OAAO,KAAK,GAAG,OAAO,WAAW;AAC1C,eAAO,QAAQ;AAAA,UACb,UAAU,WAAW;AAAA,YACnB,QAAQ,SAAS;AAAA,YACjB,QAAQ,CAAC,GAAG,SAAS,MAAM;AAAA;AAAA;AAAA,YAG3B,cAAc,OAAO;AAAA,UACvB,CAAC;AAAA,QACH;AAAA,MACF;AACA,YAAM,YAAY,QAAQ,IAAI;AAC9B,YAAM,KAAK,kBAAkB,WAAW,MAAM;AAC9C,YAAM,SAA4B;AAAA,QAChC,eAAeC;AAAA,QACf,WAAW;AAAA,QACX;AAAA,QACA,OAAO,QAAQ,MAAM;AAAA,QACrB,aAAa,QAAQ,YAAY;AAAA,MACnC;AACA,eAAS,IAAI,IAAI,EAAE,QAAQ,QAAQ,CAAC,EAAE,CAAC;AACvC,aAAO,QAAQ,QAAQ,UAAU,IAAI,EAAE,QAAQ,QAAQ,CAAC,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;AAAA,IAChF;AAAA,IAEA,SAAS,WAAkD;AACzD,YAAM,QAAQ,SAAS,IAAI,SAAS;AACpC,aAAO,UAAU,SACb,SACA,EAAE,QAAQ,MAAM,QAAQ,QAAQ,CAAC,GAAG,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE;AAAA,IAC1E;AAAA,EACF;AACF;","names":["dirname","dirname","existsSync","FsEvidenceArtifactStore","RUNS_SUBDIR","slugBranch","slugBranch","randomUUID","existsSync","readdirSync","readFileSync","dirname","join","DatabaseSync","foldQuarantineLedgerState","readQuarantineLedger","openKnowledgeReader","FsEventLog","RUNS_SUBDIR","slugBranch","asJobId","dirname","join","closeSync","fsyncSync","mkdirSync","openSync","readFileSync","writeFileSync","isAbsolute","join","randomUUID","closeSync","fsyncSync","openSync","renameSync","rmSync","writeFileSync","dirname","isAbsolute","join","canonicalJson","JOB_CHECKPOINT_SCHEMA_VERSION","openSync","writeFileSync","fsyncSync","closeSync","renameSync","rmSync","isAbsolute","join","JOB_CHECKPOINT_SCHEMA_VERSION","dirname","randomUUID","canonicalJson","SAFE_PATH_SEGMENT","mkdirSync","openSync","writeFileSync","fsyncSync","closeSync","readFileSync","isSwallowableDirectoryFsyncError","isAbsolute","join","id","header","existsSync","join","DatabaseSync","canonicalJson","guardRunNotification","isJobKind","sha256hex","mkdirSync","dirname","DatabaseSync","QuarantinedJobRequeueError","StaleJobStoreEpochError","canonicalJson","sha256hex","readdirSync","readFileSync","join","canonicalJson","mkdirSync","dirname","DatabaseSync","StaleJobStoreEpochError","options","QuarantinedJobRequeueError","canonicalJson","sha256hex","sha256hex","canonicalJson","toNumber","isJobKind","join","existsSync","DatabaseSync","guardRunNotification","join","dirname","openKnowledgeReader","RUNS_SUBDIR","existsSync","readdirSync","FsEventLog","readFileSync","randomUUID","DatabaseSync","slugBranch","asJobId","foldQuarantineLedgerState","readQuarantineLedger","opened","closeSync","existsSync","fsyncSync","openSync","readFileSync","renameSync","writeFileSync","join","canonicalJson","slugBranch","z","HANDOFF_FILE","RUNS_SUBDIR","loadCompletedRunHandoff","randomUUID","closeSync","fsyncSync","mkdirSync","openSync","readFileSync","renameSync","rmSync","writeFileSync","dirname","join","resolve","z","openSync","writeFileSync","fsyncSync","closeSync","renameSync","slugBranch","join","RUNS_SUBDIR","readFileSync","canonicalJson","existsSync","HANDOFF_FILE","join","createAgentJobQueue","createRealJobKindRegistry","join","createRealJobKindRegistry","createAgentJobQueue","repairSession","CURRENT_CHAT_SESSION_SCHEMA_VERSION","repairSession","CURRENT_CHAT_SESSION_SCHEMA_VERSION"]}