@effect-agent/testing 0.1.0-beta.111 → 0.1.0-beta.112
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/Certification.mjs +2 -2
- package/dist/Certification.mjs.map +1 -1
- package/dist/Chaos.mjs +1 -1
- package/dist/Chaos.mjs.map +1 -1
- package/dist/DocsResearcher.mjs +3 -3
- package/dist/DocsResearcher.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Certification.ts +3 -3
- package/src/Chaos.ts +2 -2
- package/src/fixtures/docs-researcher/mcp.ts +4 -4
package/dist/Certification.mjs
CHANGED
|
@@ -395,8 +395,8 @@ const verifyLane = Effect.fn("Certification.verifyLane")(function* (lane, batchP
|
|
|
395
395
|
const exported = yield* store.export(ThreadExportRequest.make({ threadId: lane }));
|
|
396
396
|
const rows = /* @__PURE__ */ new Map();
|
|
397
397
|
const nonterminal = yield* Stream.runCollect(ledger.scanNonterminal);
|
|
398
|
-
for (const submission of nonterminal) if (submission.threadId === lane) rows.set(submission.submissionId, submission);
|
|
399
398
|
const named = /* @__PURE__ */ new Set();
|
|
399
|
+
for (const submission of nonterminal) if (submission.threadId === lane) named.add(submission.submissionId);
|
|
400
400
|
for (const envelope of exported.records) {
|
|
401
401
|
const payload = envelope.record.payload;
|
|
402
402
|
if (payload._tag === "UserInputRecorded" || payload._tag === "SubmissionSettled" || payload._tag === "AbortRequested") {
|
|
@@ -469,7 +469,7 @@ const runSweepCell = Effect.fn("Certification.runSweepCell")(function* (scenario
|
|
|
469
469
|
let converged = false;
|
|
470
470
|
for (let round = 0; round < MAX_REDRIVE_ROUNDS && !converged; round++) {
|
|
471
471
|
yield* TestClock.adjust(leaseAdvance);
|
|
472
|
-
yield* Effect.exit(runtime.runRecovery);
|
|
472
|
+
yield* Effect.exit(runtime.runRecovery());
|
|
473
473
|
for (const lane of lanes) yield* Effect.exit(driveLane(lane));
|
|
474
474
|
for (const lane of lanes) {
|
|
475
475
|
const explains = yield* Effect.exit(runtime.explainThread(lane));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Certification.mjs","names":[],"sources":["../src/internal/certification-report.ts","../src/Certification.ts"],"sourcesContent":["import { CertificationReport } from \"effect-agent/testing/certification\";\n\n/** Fold executed results without acquiring adapters or claiming coverage from citations. */\nexport const makeCertificationReport = (\n results: Pick<CertificationReport, \"adapter\" | \"generatedAt\" | \"tier1\" | \"tier2\" | \"tier3\">,\n): CertificationReport => {\n const { adapter, tier1, tier2, tier3 } = results;\n\n const ok =\n tier1.every((result) => result.status === \"passed\") &&\n tier2.every((result) => result.status !== \"failed\") &&\n tier3.cases.every((result) => result.status === \"passed\");\n\n return CertificationReport.make({\n format: \"effect-agent/certification@2\",\n ...results,\n ok,\n fullyCertified:\n ok &&\n adapter.durability !== \"non-durable\" &&\n tier3.status === \"exercised\" &&\n tier3.cases.length > 0 &&\n tier3.cases.every((result) => result.suite === \"real-loss\"),\n });\n};\n","import type { Crypto } from \"effect\";\nimport {\n Cause,\n Clock,\n DateTime,\n Duration,\n Effect,\n Exit,\n Layer,\n Option,\n Ref,\n Schema,\n Stream,\n} from \"effect\";\nimport * as Agent from \"effect-agent/agent\";\nimport { AgentPolicy } from \"effect-agent/agent-policy\";\nimport { DurableWorkerBinding, type ResolvedBinding } from \"effect-agent/agent-registration\";\nimport {\n DurableAgentRuntime,\n DurableRuntimeConfig,\n type DurableSubmitFailure,\n type DurableSubmitOptions,\n type Receipt,\n} from \"effect-agent/durable-agent-runtime\";\nimport {\n DurableRuntimeFailpointError,\n DurableRuntimeFailpointLocation,\n} from \"effect-agent/durable-failpoint\";\nimport { DurableStep, DurableStepError } from \"effect-agent/durable-step\";\nimport { IdGenerator } from \"effect-agent/id-generator\";\nimport {\n ThreadId,\n RunId,\n ToolCallId,\n TurnId,\n type AgentId,\n type SubmissionId,\n} from \"effect-agent/identifiers\";\nimport {\n DefinitionDigests,\n DeploymentId,\n Digest,\n ProducerId,\n type BatchId,\n} from \"effect-agent/records\";\nimport { childThreadIdFor } from \"effect-agent/run-journal\";\nimport { RunToolAuthorization } from \"effect-agent/run-options\";\nimport * as Subagent from \"effect-agent/subagent\";\nimport { SubagentPolicy } from \"effect-agent/subagent\";\nimport { SubagentReservationsMemoryLive } from \"effect-agent/subagent-reservations\";\nimport {\n ApprovalDecisionCommand,\n IdempotencyKey,\n Principal,\n ResolutionSafeToRetry,\n SubmissionLedger,\n SubmissionLookupById,\n UnknownResolutionCommand,\n DEFAULT_OWNERSHIP_LEASE_DURATION,\n type SubmissionSnapshot,\n} from \"effect-agent/submission-ledger\";\nimport {\n type CertificationCaseResult,\n type CertificationReport,\n CertificationSweepResult,\n CertificationTierThreeReport,\n CertifiedAdapterIdentity,\n certifyPorts,\n type CertificationScenario,\n} from \"effect-agent/testing/certification\";\nimport { DurableRuntimeFailpointTestControl } from \"effect-agent/testing/durable-failpoint-test-control\";\nimport { verifyThreadInvariants } from \"effect-agent/thread-invariants\";\nimport { ThreadExportRequest, ThreadStore, LoadCheckpointRequest } from \"effect-agent/thread-store\";\nimport { ToolReconciler } from \"effect-agent/tool-reconciler\";\nimport { WakeScheduler } from \"effect-agent/wake-scheduler\";\nimport { TestClock } from \"effect/testing\";\nimport { LanguageModel, Model, Tool, Toolkit, type Response } from \"effect/unstable/ai\";\n\nimport { makeCertificationReport } from \"./internal/certification-report.ts\";\n\n/**\n * P7 WP2 — `certifyDurableAdapters` (plan §1): the one certification entry point a durable\n * adapter pair runs to earn a Schema-encoded certificate.\n *\n * - **Tier 1 — port contract**: the two shared conformance case arrays, verbatim, through\n * `certifyPorts` (TEST-004/STORE-010).\n * - **Tier 2 — coordinator protocol + failpoint convergence**: the durable coordinator is\n * assembled over the CANDIDATE Layer pair with a scripted deterministic model; every\n * reached `DurableRuntimeFailpointLocation` is armed one-shot across the six scenario shapes\n * (plain / uncertain-tool / durable-steps / approval / join / delegation). Unreached locations\n * share a verified clean run per shape; new unaccounted-for locations get a full sweep.\n * After the injected fault the runner asserts the state stays CLASSIFIABLE (recovery +\n * the public unblocking operations `resolveUnknown`/`resolveApproval` are the only levers\n * used) and that the re-drive CONVERGES to `verifyThreadInvariants` with `requireAllSettled`,\n * including a fully discharged digest-chain check, because the runner captures per-batch producer\n * identity at append time.\n * - **Tier 3 — real loss lever**: recorded honestly. A durable adapter either supplies a\n * `CertificationCrashLever` executed in this run, cites its committed real-loss evidence\n * (process-kill / eviction suites), or the certificate says `not-exercised`. A non-durable\n * reference adapter records `not-applicable`.\n *\n * The runner is adapter-neutral and platform-neutral: it imports nothing Node-only, so the\n * same entry point runs under `@effect/vitest` on Node and inside workerd (storage-cloudflare's\n * in-workerd runner). It must run under a TestClock (Tier 1 drives lease expiry through\n * virtual time), and requires only `Crypto.Crypto` from the environment.\n */\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\n/**\n * A real-loss lever supplied by an adapter that wants Tier 3 exercised IN this certification\n * run (kill/evict/reopen around a designated row subset). Rows report with\n * `suite: \"real-loss\"`. Failures must be captured per-row — the lever's error channel is\n * `never` so a certificate is always produced.\n */\nexport type CertificationCrashLever = Effect.Effect<ReadonlyArray<CertificationCaseResult>>;\n\nexport interface CertifyDurableAdaptersOptions<LedgerE = never, StoreE = never> {\n /** Adapter pair identity named by the certificate (durability is read from the ledger). */\n readonly adapter: {\n readonly name: string;\n readonly version?: string | undefined;\n };\n /**\n * The candidate Layer pair. When both ports must share one connection root (the ADR-0011\n * \"same file\" rule), pass the SAME combined Layer instance for both fields — Layer\n * memoization builds it once. A candidate may require `Crypto.Crypto` (the memory reference\n * does); the certification's own environment supplies nothing else.\n */\n readonly submissionLedger: Layer.Layer<SubmissionLedger, LedgerE, Crypto.Crypto>;\n readonly threadStore: Layer.Layer<ThreadStore, StoreE, Crypto.Crypto>;\n /** Defaults to `WakeScheduler.layerNoop`; the runner re-drives lanes explicitly. */\n readonly wakeScheduler?: Layer.Layer<WakeScheduler> | undefined;\n /** Executes Tier 3 in this run; takes precedence over `tierThreeEvidence`. */\n readonly crashLever?: CertificationCrashLever | undefined;\n /** Repository-relative citations of committed real-loss suites (Tier 3 `recorded-evidence`). */\n readonly tierThreeEvidence?: ReadonlyArray<string> | undefined;\n /**\n * The candidate ledger's configured ownership lease (defaults to the D5 default, 30s).\n * Every Tier-2 re-drive round advances the TestClock past this lease before reclaiming:\n * a live lease may block ALL new claims (the SQL adapters do; the memory reference also\n * allows same-producer reclaim), so the adapter-NEUTRAL recovery lever after a mid-Attempt\n * fault is lease expiry — exactly the documented D5 liveness mechanism, driven through\n * virtual time.\n */\n readonly ownershipLeaseDuration?: Duration.Duration | undefined;\n}\n\n/** The six Tier-2 scenario shapes in sweep order. */\nexport const CERTIFICATION_SCENARIOS: ReadonlyArray<CertificationScenario> = [\n \"plain\",\n \"uncertain-tool\",\n \"durable-steps\",\n \"approval\",\n \"join\",\n \"delegation\",\n];\n\n/**\n * Coordinator failpoint locations that none of the six scenario shapes can reach, recorded\n * honestly instead of silently claimed. These require operator, compaction, reservation,\n * background-worker, or Agent-update paths the shapes do not take. They are pinned in-process\n * by the P5/S2 suites (`packages/testing/test/durable-tools.test.ts` \"resolveUnknown is idempotent across the\n * intent failpoint\", `durable-runtime.test.ts` abort rows,\n * `durable-subagents.test.ts` abort propagation) and by the process-kill/eviction crash\n * matrices. Runner tests assert the observed never-fired set equals EXACTLY this list, so a\n * protocol change that silently stops exercising a location fails the certification.\n */\nexport const TIER2_UNREACHED_LOCATIONS: ReadonlyArray<DurableRuntimeFailpointLocation> = [\n // Active timeout recording is covered before/after append by durable-runtime.test.ts.\n \"run:before-duration-append\",\n \"run:after-duration-append\",\n // Tier 2 has no native compaction; dedicated checkpoint process-loss tests cover these.\n \"checkpoint:before-save\",\n \"checkpoint:after-save\",\n \"abort:after-intent\",\n // Compaction requires a `contextTokenLimit` policy plus prior-Run history\n // none of the six scenario shapes carries; pinned in-process by the\n // RUN-026 rows in `packages/testing/test/durable-runtime.test.ts`\n // (compaction failpoint idempotence across re-drive).\n \"compaction:before-canonical-append\",\n \"compaction:after-canonical-append\",\n // These shapes use neither programmatic Tools nor grace finalization. Their reservations\n // are exercised before/after append in the public durable-runtime regression suite.\n \"policy:before-reservation-append\",\n \"policy:after-reservation-append\",\n \"resolve:after-intent\",\n // All six shapes retain their original Tool contracts, so none retires an unavailable\n // operation. The deployment continuity matrix in durable-runtime.test.ts exercises the\n // actual before/after-unavailable append boundaries, asserting absent/present canonical\n // ToolUnavailable results at the crash and one original-call settlement after re-drive.\n \"tools:before-unavailable-append\",\n \"tools:after-unavailable-append\",\n \"subagent:after-child-abort-intent\",\n // Background workers use retained delivery, source capacity, and child-origin paths absent\n // from these six attached/ordinary scenarios. The before/after creation and completion\n // boundaries are exercised by packages/effect-agent/test/durable/worker-host.test.ts.\n \"worker:before-source-append\",\n \"worker:after-source-append\",\n \"worker:before-origin-append\",\n \"worker:after-origin-append\",\n \"worker:before-completion-append\",\n \"worker:after-completion-append\",\n // Root attached declarations keep their independent pool; nested shared subtree mutations\n // are covered by the same focused worker-host failpoint suite.\n \"worker:before-subtree-append\",\n \"worker:after-subtree-append\",\n // Automatic report decisions and retained delivery insertion have dedicated worker crash tests.\n \"worker:before-report-append\",\n \"worker:after-report-append\",\n \"worker:before-report-delivery\",\n \"worker:after-report-delivery\",\n // None of the six shapes emits Agent updates. All four boundaries are exercised separately\n // by packages/effect-agent/test/durable/worker-host.test.ts (\"repairs an accepted parent update after ...\").\n // Node restart/lost-ack coverage is in packages/platform-node/test/worker-updates.test.ts;\n // Cloudflare eviction/alarm recovery is in packages/platform-cloudflare/test/background-workers.test.ts.\n // These suites are not executed by this certification runner; its update rows remain not-triggered.\n \"update:before-canonical-append\",\n \"update:after-canonical-append\",\n \"update:before-delivery-insert\",\n \"update:after-delivery-insert\",\n];\n\n/** Locations of `tier2` rows whose armed fault never fired in ANY scenario, sorted. */\nexport const tier2NeverFiredLocations = (\n tier2: ReadonlyArray<CertificationSweepResult>,\n): ReadonlyArray<DurableRuntimeFailpointLocation> => {\n const fired = new Set<DurableRuntimeFailpointLocation>();\n\n for (const row of tier2) {\n if (row.failpointFired) fired.add(row.location);\n }\n\n return DurableRuntimeFailpointLocation.literals.filter((location) => !fired.has(location)).sort();\n};\n\n// ---------------------------------------------------------------------------\n// Deterministic fixtures (scripted prompt-shape models, agents, delegation)\n// ---------------------------------------------------------------------------\n\nconst SHA_A = Schema.decodeSync(Digest)(\"a\".repeat(64));\nconst DIGESTS = DefinitionDigests.make({ agent: SHA_A, model: SHA_A, tools: SHA_A });\n\nconst CHILD_DIGEST_STRINGS = {\n agent: \"b\".repeat(64),\n model: \"c\".repeat(64),\n tools: \"d\".repeat(64),\n} as const;\n\nconst CHILD_DIGESTS = DefinitionDigests.make({\n agent: Schema.decodeSync(Digest)(CHILD_DIGEST_STRINGS.agent),\n model: Schema.decodeSync(Digest)(CHILD_DIGEST_STRINGS.model),\n tools: Schema.decodeSync(Digest)(CHILD_DIGEST_STRINGS.tools),\n});\n\nconst PRINCIPAL = Schema.decodeSync(Principal)(\"principal-certification\");\nconst decodeThreadId = Schema.decodeSync(ThreadId);\nconst decodeIdempotencyKey = Schema.decodeSync(IdempotencyKey);\nconst decodeToolCallId = Schema.decodeSync(ToolCallId);\n\nconst usage = { inputTokens: {}, outputTokens: {} };\n\nconst finalParts = (text: string): ReadonlyArray<Response.StreamPartEncoded> => [\n { type: \"text-start\", id: \"answer\" },\n { type: \"text-delta\", id: \"answer\", delta: text },\n { type: \"text-end\", id: \"answer\" },\n { type: \"finish\", reason: \"stop\", usage },\n];\n\nconst toolCallPart = (id: string, name: string, params: unknown): Response.StreamPartEncoded => ({\n type: \"tool-call\",\n id,\n name,\n params,\n providerExecuted: false,\n});\n\nconst toolTurn = (\n ...calls: ReadonlyArray<Response.StreamPartEncoded>\n): ReadonlyArray<Response.StreamPartEncoded> => [\n ...calls,\n { type: \"finish\", reason: \"tool-calls\", usage },\n];\n\n/**\n * Stateless scripted model that decides by PROMPT SHAPE instead of call count: while the\n * prompt carries no committed tool result the model declares `toolParts` (when given),\n * otherwise it answers with the final text. Deciding on the canonical prompt keeps every cell\n * deterministic regardless of where the injected fault fell — a re-invoked Turn re-declares\n * the same batch and a resumed batch flows into the final answer, so every scenario always\n * exercises its tool path and always converges.\n */\nconst promptShapeModel = (\n name: string,\n finalText: string,\n toolParts?: ReadonlyArray<Response.StreamPartEncoded>,\n) =>\n Model.make(\n \"scripted\",\n name,\n Layer.effect(\n LanguageModel.LanguageModel,\n LanguageModel.make({\n generateText: () => Effect.succeed([]),\n streamText: (request) => {\n const hasToolResult = request.prompt.content.some((message) => message.role === \"tool\");\n\n const parts =\n toolParts === undefined || hasToolResult ? finalParts(finalText) : toolParts;\n\n return Stream.fromIterable(parts);\n },\n }),\n ),\n );\n\n// Tier-2 intentionally advances virtual time past a 30-second ownership lease on every\n// re-drive round. Keep its business-policy duration above the full eight-round sweep so this\n// fixture certifies crash convergence rather than accidentally relying on a fresh duration\n// allowance per replacement Attempt. RUN-030 owns the dedicated duration-expiry coverage.\nconst CERTIFICATION_MAX_DURATION = \"10 minutes\" as const;\n\nconst policy = AgentPolicy.make({\n maxTurns: 4,\n maxToolCalls: 4,\n maxDuration: CERTIFICATION_MAX_DURATION,\n toolConcurrency: 2,\n});\n\nconst QuestionInput = Schema.Struct({ question: Schema.String });\nconst AnswerOutput = Schema.Struct({ answer: Schema.String });\n\n/** plain / join: no tools — the pure Turn/submission/join seams. */\nconst plainDefinition = Agent.make(\"certify-plain\", {\n input: QuestionInput,\n output: AnswerOutput,\n instructions: \"Answer as JSON.\",\n toolkit: Toolkit.empty,\n policy,\n});\n\n/** uncertain-tool: unannotated → fail-closed `uncertain`, enters the prepared/settled protocol. */\nconst Book = Tool.make(\"book\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ confirmation: Schema.String }),\n});\n\nconst bookToolkit = Toolkit.make(Book);\n\nconst uncertainDefinition = Agent.make(\"certify-uncertain\", {\n input: QuestionInput,\n output: AnswerOutput,\n instructions: \"Book it.\",\n toolkit: bookToolkit,\n policy,\n});\n\n/** durable-steps: declaring `DurableStep` as a dependency is what makes the Tool durable. */\nconst Itinerary = Tool.make(\"itinerary\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ state: Schema.String }),\n failure: DurableStepError,\n dependencies: [DurableStep],\n});\n\nconst itineraryToolkit = Toolkit.make(Itinerary);\n\nconst stepsDefinition = Agent.make(\"certify-steps\", {\n input: QuestionInput,\n output: AnswerOutput,\n instructions: \"Reserve the itinerary.\",\n toolkit: itineraryToolkit,\n policy,\n});\n\n/** approval: fail-closed — no `DurableApprovalResolver` Layer, so undecided approvals suspend. */\nconst BookApproval = Tool.make(\"book\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ confirmation: Schema.String }),\n needsApproval: true,\n});\n\nconst approvalToolkit = Toolkit.make(BookApproval);\n\nconst approvalDefinition = Agent.make(\"certify-approval\", {\n input: QuestionInput,\n output: AnswerOutput,\n instructions: \"Book after approval.\",\n toolkit: approvalToolkit,\n policy,\n});\n\n/** delegation: durable attached child plus an ordinary uncertain sibling in ONE batch. */\nconst childDefinition = Agent.make(\"certify-child\", {\n input: QuestionInput,\n output: AnswerOutput,\n instructions: \"Answer as JSON.\",\n toolkit: Toolkit.empty,\n policy: AgentPolicy.make({\n maxTurns: 2,\n maxToolCalls: 1,\n maxDuration: CERTIFICATION_MAX_DURATION,\n toolConcurrency: 1,\n }),\n});\n\nclass CertifyDelegationFailed extends Schema.TaggedError<CertifyDelegationFailed>()(\n \"CertifyDelegationFailed\",\n { childErrorTag: Schema.String },\n) {}\n\nconst researchDelegation = Subagent.define(\"delegate_research\", {\n description: \"Research one bounded question and return findings.\",\n target: childDefinition,\n parameters: Schema.Struct({ topic: Schema.String }),\n success: Schema.Struct({ summary: Schema.String }),\n failure: CertifyDelegationFailed,\n prepareInput: ({ topic }) => Effect.succeed({ question: `research:${topic}` }),\n projectResult: (output) => Effect.succeed({ summary: `finding:${output.answer}` }),\n policy: SubagentPolicy.make({\n maxChildren: 2,\n maxConcurrency: 2,\n maxTurns: 4,\n maxToolCalls: 4,\n maxDuration: CERTIFICATION_MAX_DURATION,\n }),\n});\n\nconst Lookup = Tool.make(\"lookup\", {\n parameters: Schema.Struct({ key: Schema.String }),\n success: Schema.Struct({ value: Schema.String }),\n});\n\nconst coordinatorDefinition = Agent.make(\"certify-coordinator\", {\n input: Schema.Struct({ mission: Schema.String }),\n output: Schema.Struct({ report: Schema.String }),\n instructions: \"Delegate and look up, then answer as JSON.\",\n toolkit: Toolkit.make(researchDelegation.tool, Lookup),\n policy: AgentPolicy.make({\n maxTurns: 4,\n maxToolCalls: 3,\n maxDuration: CERTIFICATION_MAX_DURATION,\n toolConcurrency: 2,\n }),\n});\n\nconst mapChildFailure = (failure: { readonly _tag: string }) =>\n CertifyDelegationFailed.make({ childErrorTag: failure._tag });\n\nconst DELEGATE_CALL = decodeToolCallId(\"delegate-1\");\n\n/** Fixture-only identity source consumed by the delegation Layer's ephemeral capture. */\nconst identifiers = Layer.effect(\n IdGenerator,\n Effect.gen(function* () {\n const counter = yield* Ref.make(0);\n\n const next = <A>(decode: (value: string) => A, prefix: string) =>\n Ref.getAndUpdate(counter, (value) => value + 1).pipe(\n Effect.map((value) => decode(`${prefix}-${value}`)),\n );\n\n return {\n nextThreadId: next(decodeThreadId, \"certify-fixture-thread\"),\n nextRunId: next(Schema.decodeSync(RunId), \"certify-fixture-run\"),\n nextTurnId: next(Schema.decodeSync(TurnId), \"certify-fixture-turn\"),\n };\n }),\n);\n\nconst delegationSupport = Layer.mergeAll(SubagentReservationsMemoryLive, identifiers);\n\n// ---------------------------------------------------------------------------\n// Tier 2 — scenario cells\n// ---------------------------------------------------------------------------\n\ninterface CertificationCell {\n readonly bindings: ReadonlyArray<ResolvedBinding>;\n /** Idempotent submission batch — safe to replay verbatim after a submit-boundary fault. */\n readonly submit: Effect.Effect<ReadonlyArray<Receipt>, DurableSubmitFailure, DurableAgentRuntime>;\n /** All lanes of the cell in drive order, computed from the (possibly replayed) receipts. */\n readonly lanes: (receipts: ReadonlyArray<Receipt>) => ReadonlyArray<ThreadId>;\n}\n\nconst submitOptionsFor = (slug: string, threadId: ThreadId): DurableSubmitOptions => ({\n threadId,\n principal: PRINCIPAL,\n idempotencyKey: decodeIdempotencyKey(`certify-key-${slug}`),\n definitions: DIGESTS,\n});\n\n/** One single-agent cell: one lane, one Submission, one registered exact-digest binding. */\nconst makeSingleAgentCell = (\n definition: { readonly id: AgentId; readonly input: typeof QuestionInput },\n resolved: ResolvedBinding,\n slug: string,\n): CertificationCell => {\n const threadId = decodeThreadId(`certify-${slug}`);\n\n const submit = Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n\n const receipt = yield* runtime.submit(\n { definition: { id: definition.id, input: definition.input } },\n { question: `certify ${slug}` },\n submitOptionsFor(slug, threadId),\n );\n\n return [receipt];\n });\n\n return {\n bindings: [resolved],\n submit,\n lanes: () => [threadId],\n };\n};\n\nconst makeCell = Effect.fn(\"Certification.makeCell\")(function* (\n scenario: CertificationScenario,\n slug: string,\n) {\n switch (scenario) {\n case \"plain\": {\n const binding = Agent.withModel(\n plainDefinition,\n promptShapeModel(\"certify-plain\", '{\"answer\":\"done\"}'),\n );\n\n const resolved = yield* DurableWorkerBinding.make(binding, DIGESTS);\n\n return makeSingleAgentCell(plainDefinition, resolved, slug);\n }\n case \"uncertain-tool\": {\n const binding = Agent.withModel(\n uncertainDefinition,\n promptShapeModel(\n \"certify-uncertain\",\n '{\"answer\":\"booked\"}',\n toolTurn(toolCallPart(\"book-1\", \"book\", { ref: `r-${slug}` })),\n ),\n );\n\n const toolLayer = bookToolkit.toLayer({\n book: ({ ref }) => Effect.succeed({ confirmation: `confirmed-${ref}` }),\n });\n\n const resolved = yield* DurableWorkerBinding.make(binding, DIGESTS).pipe(\n Effect.provide(toolLayer),\n );\n\n return makeSingleAgentCell(uncertainDefinition, resolved, slug);\n }\n case \"durable-steps\": {\n const binding = Agent.withModel(\n stepsDefinition,\n promptShapeModel(\n \"certify-steps\",\n '{\"answer\":\"reserved\"}',\n toolTurn(toolCallPart(\"itinerary-1\", \"itinerary\", { ref: `trip-${slug}` })),\n ),\n );\n\n const toolLayer = itineraryToolkit.toLayer({\n itinerary: ({ ref }) =>\n Effect.gen(function* () {\n const step = yield* DurableStep;\n\n const flight = yield* step.do(\n \"reserve-flight\",\n Schema.String,\n Effect.succeed(`flight-${ref}`),\n );\n\n const lodging = yield* step.do(\n \"reserve-lodging\",\n Schema.String,\n Effect.succeed(`lodging-${ref}`),\n );\n\n return { state: `${flight}+${lodging}` };\n }),\n });\n\n const resolved = yield* DurableWorkerBinding.make(binding, DIGESTS).pipe(\n Effect.provide(toolLayer),\n );\n\n return makeSingleAgentCell(stepsDefinition, resolved, slug);\n }\n case \"approval\": {\n const binding = Agent.withModel(\n approvalDefinition,\n promptShapeModel(\n \"certify-approval\",\n '{\"answer\":\"approved\"}',\n toolTurn(toolCallPart(\"book-1\", \"book\", { ref: `r-${slug}` })),\n ),\n );\n\n const toolLayer = approvalToolkit.toLayer({\n book: ({ ref }) => Effect.succeed({ confirmation: `confirmed-${ref}` }),\n });\n\n const resolved = yield* DurableWorkerBinding.make(binding, DIGESTS).pipe(\n Effect.provide(toolLayer),\n );\n\n return makeSingleAgentCell(approvalDefinition, resolved, slug);\n }\n case \"join\": {\n const binding = Agent.withModel(\n plainDefinition,\n promptShapeModel(\"certify-join\", '{\"answer\":\"host answer\"}'),\n );\n\n const resolved = yield* DurableWorkerBinding.make(binding, DIGESTS);\n const threadId = decodeThreadId(`certify-${slug}`);\n\n const submitOne = Effect.fn(\"Certification.submitOne\")(function* (\n key: string,\n question: string,\n ) {\n const runtime = yield* DurableAgentRuntime;\n\n return yield* runtime.submit(\n { definition: { id: plainDefinition.id, input: plainDefinition.input } },\n { question },\n {\n threadId,\n principal: PRINCIPAL,\n idempotencyKey: decodeIdempotencyKey(key),\n definitions: DIGESTS,\n },\n );\n });\n\n const cell: CertificationCell = {\n bindings: [resolved],\n submit: Effect.gen(function* () {\n const host = yield* submitOne(`certify-key-${slug}-host`, \"host question\");\n const queued = yield* submitOne(`certify-key-${slug}-queued`, \"queued question\");\n\n return [host, queued];\n }),\n lanes: () => [threadId],\n };\n\n return cell;\n }\n case \"delegation\": {\n const childBinding = Agent.withModel(\n childDefinition,\n promptShapeModel(\"certify-child\", '{\"answer\":\"child-answer\"}'),\n );\n\n const parentBinding = Agent.withModel(\n coordinatorDefinition,\n promptShapeModel(\n \"certify-parent\",\n '{\"report\":\"done\"}',\n toolTurn(\n toolCallPart(\"delegate-1\", \"delegate_research\", { topic: \"paris\" }),\n toolCallPart(\"lookup-1\", \"lookup\", { key: \"hotels\" }),\n ),\n ),\n );\n\n const delegationLayer = Subagent.layer(researchDelegation, childBinding, {\n mapChildFailure,\n durable: { targetDigests: CHILD_DIGEST_STRINGS },\n }).pipe(Layer.provide(delegationSupport));\n\n const lookupLayer = Toolkit.make(Lookup).toLayer({\n lookup: ({ key }) => Effect.succeed({ value: `found-${key}` }),\n });\n\n const parentResolved = yield* DurableWorkerBinding.make(parentBinding, DIGESTS).pipe(\n Effect.provide(Layer.mergeAll(delegationLayer, lookupLayer)),\n );\n\n const childResolved = yield* DurableWorkerBinding.make(childBinding, CHILD_DIGESTS);\n const threadId = decodeThreadId(`certify-${slug}`);\n\n const cell: CertificationCell = {\n bindings: [parentResolved, childResolved],\n submit: Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n\n const receipt = yield* runtime.submit(\n { definition: { id: coordinatorDefinition.id, input: coordinatorDefinition.input } },\n { mission: \"plan\" },\n submitOptionsFor(slug, threadId),\n );\n\n return [receipt];\n }),\n lanes: (receipts) => {\n const parent = receipts.at(0);\n\n return parent === undefined\n ? [threadId]\n : [threadId, childThreadIdFor(parent.submissionId, DELEGATE_CALL)];\n },\n };\n\n return cell;\n }\n }\n});\n\n/** Maximum recovery/drive/unblock rounds before a cell is reported non-convergent. */\nconst MAX_REDRIVE_ROUNDS = 8;\n\n/**\n * Verify one lane after convergence: canonical export + every lane Submission the ledger or\n * the log names (the same collection rule as the admin `verify` member), fed to the shared\n * invariant checker in convergence mode WITH the captured per-batch producer directory, so\n * the digest chain is fully recomputed instead of skipped.\n */\nconst verifyLane = Effect.fn(\"Certification.verifyLane\")(function* (\n lane: ThreadId,\n batchProducers: ReadonlyMap<BatchId, ProducerId>,\n) {\n const store = yield* ThreadStore;\n const ledger = yield* SubmissionLedger;\n const exported = yield* store.export(ThreadExportRequest.make({ threadId: lane }));\n const rows = new Map<SubmissionId, SubmissionSnapshot>();\n const nonterminal = yield* Stream.runCollect(ledger.scanNonterminal);\n\n for (const submission of nonterminal) {\n if (submission.threadId === lane) rows.set(submission.submissionId, submission);\n }\n const named = new Set<SubmissionId>();\n\n for (const envelope of exported.records) {\n const payload = envelope.record.payload;\n\n if (\n payload._tag === \"UserInputRecorded\" ||\n payload._tag === \"SubmissionSettled\" ||\n payload._tag === \"AbortRequested\"\n ) {\n if (payload.submissionId !== undefined) named.add(payload.submissionId);\n }\n }\n for (const submissionId of named) {\n if (rows.has(submissionId)) continue;\n const found = yield* ledger.lookup(SubmissionLookupById.make({ submissionId }));\n\n if (Option.isSome(found) && found.value.threadId === lane) {\n rows.set(submissionId, found.value);\n }\n }\n\n const checkpoint =\n store.checkpoints === undefined\n ? Option.none()\n : yield* store.checkpoints.load(LoadCheckpointRequest.make({ threadId: lane }));\n\n return yield* verifyThreadInvariants({\n export: exported,\n submissions: [...rows.values()],\n batchProducers,\n checkpoint: Option.getOrUndefined(checkpoint),\n checkpointsSupported: store.checkpoints !== undefined,\n requireAllSettled: true,\n });\n});\n\nconst failureTagOf = <E>(cause: Cause.Cause<E>): string => {\n const failure = Cause.findErrorOption(cause);\n\n if (Option.isSome(failure)) {\n const error: unknown = failure.value;\n\n if (typeof error === \"object\" && error !== null && \"_tag\" in error) {\n return String(error._tag);\n }\n\n return String(error).slice(0, 256);\n }\n\n return \"defect\";\n};\n\ntype SweepOutcome = Pick<\n CertificationSweepResult,\n \"failpointFired\" | \"status\" | \"digestChainVerified\" | \"detail\"\n>;\n\n/** Discover a clean path, or arm one location; both drives converge and verify real storage. */\nconst runSweepCell = Effect.fn(\"Certification.runSweepCell\")(function* (\n scenario: CertificationScenario,\n location: DurableRuntimeFailpointLocation | undefined,\n batchProducers: ReadonlyMap<BatchId, ProducerId>,\n leaseAdvance: Duration.Duration,\n reached: Set<DurableRuntimeFailpointLocation>,\n) {\n const ledger = yield* SubmissionLedger;\n const control = yield* DurableRuntimeFailpointTestControl;\n const slug = `${scenario}-${location?.replaceAll(\":\", \"-\") ?? \"discovery\"}`;\n\n const failed = (detail: string, fired: boolean): SweepOutcome => ({\n failpointFired: fired,\n status: \"failed\",\n digestChainVerified: false,\n detail: detail.slice(0, 4_096),\n });\n\n const cell = yield* makeCell(scenario, slug);\n\n const runtime = yield* DurableAgentRuntime.pipe(\n Effect.provide(\n DurableAgentRuntime.layerWithBindings(cell.bindings).pipe(\n Layer.provide(RunToolAuthorization.allowAll),\n ),\n ),\n );\n\n const submit = cell.submit.pipe(Effect.provideService(DurableAgentRuntime, runtime));\n\n // One-shot arm: the fault fires at most once anywhere in the cell (initial drive OR a\n // re-drive round's public unblocking operation), modelling one crash at this boundary.\n const fired = yield* Ref.make(false);\n\n yield* control.setHandler((hit) =>\n Effect.suspend(() => {\n reached.add(hit);\n\n return hit !== location\n ? Effect.void\n : Ref.getAndSet(fired, true).pipe(\n Effect.flatMap((already) =>\n already\n ? Effect.void\n : Effect.fail(DurableRuntimeFailpointError.make({ location: hit })),\n ),\n );\n }),\n );\n\n // Submissions are idempotent (DUR-001): one replay recovers a submit-boundary fault.\n let receipts: ReadonlyArray<Receipt>;\n const firstSubmit = yield* Effect.exit(submit);\n\n if (Exit.isSuccess(firstSubmit)) {\n receipts = firstSubmit.value;\n } else {\n const secondSubmit = yield* Effect.exit(submit);\n\n if (Exit.isFailure(secondSubmit)) {\n yield* control.clear;\n\n return failed(\n `submission replay did not recover: ${failureTagOf(secondSubmit.cause)}`,\n yield* Ref.get(fired),\n );\n }\n receipts = secondSubmit.value;\n }\n const lanes = cell.lanes(receipts);\n\n const driveLane = (lane: ThreadId) => runtime.processThreadResolved(lane);\n\n const allSettled = Effect.gen(function* () {\n for (const receipt of receipts) {\n const snapshot = yield* ledger.lookup(\n SubmissionLookupById.make({ submissionId: receipt.submissionId }),\n );\n\n if (Option.isNone(snapshot) || snapshot.value.state !== \"settled\") return false;\n }\n\n return true;\n });\n\n // Re-drive to convergence using ONLY public operations: worker drives, recovery passes,\n // and the authorized DUR-017/approval unblocking paths chosen from `explainThread`.\n let converged = false;\n\n for (let round = 0; round < MAX_REDRIVE_ROUNDS && !converged; round++) {\n // Expire any lease a faulted Attempt left behind (D5): virtual time is the\n // adapter-neutral reclaim lever — a live lease may block every new claim.\n yield* TestClock.adjust(leaseAdvance);\n yield* Effect.exit(runtime.runRecovery);\n for (const lane of lanes) {\n yield* Effect.exit(driveLane(lane));\n }\n for (const lane of lanes) {\n const explains = yield* Effect.exit(runtime.explainThread(lane));\n\n if (Exit.isFailure(explains)) continue;\n for (const explanation of explains.value) {\n for (const unknown of explanation.evidence.unknownCalls) {\n if (unknown.resolved) continue;\n yield* Effect.exit(\n runtime.resolveUnknown(\n UnknownResolutionCommand.make({\n submissionId: explanation.submission.submissionId,\n toolCallId: unknown.toolCallId,\n author: \"certification-runner\",\n reason: `re-drive after injected fault at ${location}`,\n resolution: ResolutionSafeToRetry.make(),\n }),\n ),\n );\n }\n for (const pending of explanation.evidence.approvalsPending) {\n const decided = explanation.evidence.approvalDecisions.some(\n (decision) => decision.toolCallId === pending.toolCallId,\n );\n\n if (decided) continue;\n yield* Effect.exit(\n runtime.resolveApproval(\n ApprovalDecisionCommand.make({\n submissionId: explanation.submission.submissionId,\n toolCallId: pending.toolCallId,\n decision: \"approved\",\n resolver: \"certification-runner\",\n reason: `re-drive after injected fault at ${location}`,\n }),\n ),\n );\n }\n }\n }\n const settled = yield* Effect.exit(allSettled);\n\n converged = Exit.isSuccess(settled) && settled.value;\n }\n yield* control.clear;\n const wasFired = yield* Ref.get(fired);\n\n if (!converged) {\n return failed(`did not converge within ${MAX_REDRIVE_ROUNDS} re-drive rounds`, wasFired);\n }\n\n // Every lane of the cell must verify in convergence mode with a recomputed digest chain.\n let digestChainVerified = true;\n const failedChecks: Array<string> = [];\n\n for (const lane of lanes) {\n const verdict = yield* Effect.exit(verifyLane(lane, batchProducers));\n\n if (Exit.isFailure(verdict)) {\n return failed(`lane ${lane} could not be verified: ${failureTagOf(verdict.cause)}`, wasFired);\n }\n for (const check of verdict.value.checks) {\n if (check.status === \"failed\") {\n failedChecks.push(\n `${lane}:${check.name}${check.detail === undefined ? \"\" : ` (${check.detail})`}`,\n );\n }\n if (check.name === \"digest-chain\" && check.status !== \"passed\") {\n digestChainVerified = false;\n }\n }\n }\n if (failedChecks.length > 0 || !digestChainVerified) {\n return failed(\n failedChecks.length > 0\n ? `invariant checks failed: ${failedChecks.join(\"; \")}`\n : \"the digest chain was not fully recomputed\",\n wasFired,\n );\n }\n\n return {\n failpointFired: wasFired,\n status: wasFired ? \"converged\" : \"not-triggered\",\n digestChainVerified,\n } satisfies SweepOutcome;\n});\n\n// ---------------------------------------------------------------------------\n// Tier 3 — real loss lever record\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the Tier-3 record honestly (plan §1): a non-durable reference adapter has no real\n * loss to exercise (`not-applicable`); a supplied lever runs NOW (`exercised`); committed\n * real-loss citations are recorded (`recorded-evidence`); otherwise the certificate says\n * `not-exercised` — a scoped statement, never a silent claim.\n */\nexport const resolveTierThree = Effect.fn(\"Certification.resolveTierThree\")(function* (\n durability: CertifiedAdapterIdentity[\"durability\"],\n options: {\n readonly crashLever?: CertificationCrashLever | undefined;\n readonly tierThreeEvidence?: ReadonlyArray<string> | undefined;\n },\n): Effect.fn.Return<CertificationTierThreeReport, never> {\n if (durability === \"non-durable\") {\n return CertificationTierThreeReport.make({\n status: \"not-applicable\",\n evidence: [],\n cases: [],\n detail:\n \"the adapter declares non-durable state (reference/conformance adapter); there is no real loss to exercise\",\n });\n }\n if (options.crashLever !== undefined) {\n const cases = yield* options.crashLever;\n\n return CertificationTierThreeReport.make({\n status: cases.length === 0 ? \"not-exercised\" : \"exercised\",\n evidence: options.tierThreeEvidence ?? [],\n cases,\n ...(cases.length === 0\n ? { detail: \"the supplied crash lever executed no real-loss cases\" }\n : {}),\n });\n }\n if (options.tierThreeEvidence !== undefined && options.tierThreeEvidence.length > 0) {\n return CertificationTierThreeReport.make({\n status: \"recorded-evidence\",\n evidence: options.tierThreeEvidence,\n cases: [],\n });\n }\n\n return CertificationTierThreeReport.make({\n status: \"not-exercised\",\n evidence: [],\n cases: [],\n detail:\n \"no crash lever was supplied and no committed real-loss evidence was cited; Tier 3 is NOT discharged for this adapter\",\n });\n});\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\nconst nowUtc: Effect.Effect<DateTime.Utc> = Effect.map(Clock.currentTimeMillis, (millis) =>\n DateTime.toUtc(DateTime.makeUnsafe(millis)),\n);\n\n/**\n * Certify one durable adapter pair (plan §1, §8 WP2). Runs Tier 2 FIRST over pristine\n * storage (each cell converges to all-settled before the next starts, so the recovery scan\n * never sees foreign leftovers), then Tier 1's port contract cases (whose lanes deliberately\n * end in every nonterminal shape), then records Tier 3. Requires `Crypto.Crypto` and a\n * TestClock-backed environment; the candidate Layers are built exactly once.\n */\nexport const certifyDurableAdapters = <LedgerE = never, StoreE = never>(\n options: CertifyDurableAdaptersOptions<LedgerE, StoreE>,\n): Effect.Effect<CertificationReport, LedgerE | StoreE, Crypto.Crypto> => {\n const batchProducers = new Map<BatchId, ProducerId>();\n\n // Interpose the candidate store with an append-time capture of each batch's producer\n // identity — the one value the ThreadStore port deliberately does not export — so\n // Tier 2's invariant verification recomputes the FULL digest chain instead of skipping it.\n const capturingStore = Layer.effect(ThreadStore)(\n Effect.gen(function* () {\n const inner = yield* ThreadStore;\n\n return ThreadStore.of({\n ...inner,\n append: (request) =>\n Effect.sync(() => {\n batchProducers.set(request.batch.batchId, request.batch.producerId);\n }).pipe(Effect.andThen(inner.append(request))),\n });\n }),\n ).pipe(Layer.provide(options.threadStore));\n\n // RUN-036: certification uses the default-none Tool failure observer. Trusted application\n // reporting adds no durable transition and is verified separately from adapter certification.\n const environment = Layer.mergeAll(\n options.submissionLedger,\n capturingStore,\n options.wakeScheduler ?? WakeScheduler.layerNoop,\n DurableRuntimeFailpointTestControl.layer,\n ToolReconciler.uncertain,\n DurableRuntimeConfig.layer({\n deploymentId: Schema.decodeSync(DeploymentId)(\"deployment-certification\"),\n producerId: Schema.decodeSync(ProducerId)(\"producer-certification\"),\n settlementPollInterval: Duration.millis(50),\n leaseRenewalInterval: Duration.seconds(5),\n abortPollInterval: Duration.millis(50),\n }),\n );\n\n const leaseAdvance = Duration.millis(\n Duration.toMillis(options.ownershipLeaseDuration ?? DEFAULT_OWNERSHIP_LEASE_DURATION) + 1_000,\n );\n\n const program = Effect.gen(function* () {\n const ledger = yield* SubmissionLedger;\n\n // Tier 2 — discover each deterministic shape without a fault. Unreached locations\n // would all repeat this same clean drive, including its full digest verification.\n const tier2: Array<CertificationSweepResult> = [];\n\n const discoveries: Array<{\n readonly scenario: CertificationScenario;\n readonly outcome: SweepOutcome;\n readonly reached: Set<DurableRuntimeFailpointLocation>;\n }> = [];\n\n for (const scenario of CERTIFICATION_SCENARIOS) {\n const reached = new Set<DurableRuntimeFailpointLocation>();\n\n const outcome = yield* runSweepCell(\n scenario,\n undefined,\n batchProducers,\n leaseAdvance,\n reached,\n );\n\n discoveries.push({ scenario, outcome, reached });\n }\n const observed = new Set(discoveries.flatMap(({ reached }) => [...reached]));\n\n // Never silently omit a new location: if neither discovery nor the documented\n // never-fired set accounts for it, arm it in EVERY shape. Tests pin the fired paths\n // per shape and the never-fired set, so new or lost routes require explicit review.\n const unaccounted = new Set(\n DurableRuntimeFailpointLocation.literals.filter(\n (location) => !observed.has(location) && !TIER2_UNREACHED_LOCATIONS.includes(location),\n ),\n );\n\n for (const discovery of discoveries) {\n const { scenario, reached } = discovery;\n const outcomes = new Map<DurableRuntimeFailpointLocation, SweepOutcome>();\n\n if (discovery.outcome.status !== \"failed\") {\n while (true) {\n // Recovery may expose another route. Discover those too, without re-running a\n // cell already checked. Schema order bounds this to one drive per location.\n const location = DurableRuntimeFailpointLocation.literals.find(\n (candidate) =>\n !outcomes.has(candidate) && (reached.has(candidate) || unaccounted.has(candidate)),\n );\n\n if (location === undefined) break;\n outcomes.set(\n location,\n yield* runSweepCell(scenario, location, batchProducers, leaseAdvance, reached),\n );\n }\n }\n for (const location of DurableRuntimeFailpointLocation.literals) {\n const outcome = outcomes.get(location) ?? discovery.outcome;\n\n tier2.push(\n CertificationSweepResult.make({\n scenario,\n location,\n ...outcome,\n ...(outcomes.has(location) || outcome.status === \"failed\"\n ? {}\n : { detail: \"verified clean scenario did not reach this location\" }),\n }),\n );\n }\n }\n\n // Tier 1 — the shared port contract suites, verbatim.\n const tier1 = yield* certifyPorts();\n\n // Tier 3 — the real loss lever record.\n const capabilities = yield* ledger.capabilities;\n const tier3 = yield* resolveTierThree(capabilities.durability, options);\n\n const generatedAt = yield* nowUtc;\n\n return makeCertificationReport({\n adapter: CertifiedAdapterIdentity.make({\n name: options.adapter.name,\n ...(options.adapter.version === undefined ? {} : { version: options.adapter.version }),\n durability: capabilities.durability,\n }),\n generatedAt,\n tier1,\n tier2,\n tier3,\n });\n });\n\n return program.pipe(Effect.provide(environment));\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Certification.mjs","names":[],"sources":["../src/internal/certification-report.ts","../src/Certification.ts"],"sourcesContent":["import { CertificationReport } from \"effect-agent/testing/certification\";\n\n/** Fold executed results without acquiring adapters or claiming coverage from citations. */\nexport const makeCertificationReport = (\n results: Pick<CertificationReport, \"adapter\" | \"generatedAt\" | \"tier1\" | \"tier2\" | \"tier3\">,\n): CertificationReport => {\n const { adapter, tier1, tier2, tier3 } = results;\n\n const ok =\n tier1.every((result) => result.status === \"passed\") &&\n tier2.every((result) => result.status !== \"failed\") &&\n tier3.cases.every((result) => result.status === \"passed\");\n\n return CertificationReport.make({\n format: \"effect-agent/certification@2\",\n ...results,\n ok,\n fullyCertified:\n ok &&\n adapter.durability !== \"non-durable\" &&\n tier3.status === \"exercised\" &&\n tier3.cases.length > 0 &&\n tier3.cases.every((result) => result.suite === \"real-loss\"),\n });\n};\n","import type { Crypto } from \"effect\";\nimport {\n Cause,\n Clock,\n DateTime,\n Duration,\n Effect,\n Exit,\n Layer,\n Option,\n Ref,\n Schema,\n Stream,\n} from \"effect\";\nimport * as Agent from \"effect-agent/agent\";\nimport { AgentPolicy } from \"effect-agent/agent-policy\";\nimport { DurableWorkerBinding, type ResolvedBinding } from \"effect-agent/agent-registration\";\nimport {\n DurableAgentRuntime,\n DurableRuntimeConfig,\n type DurableSubmitFailure,\n type DurableSubmitOptions,\n type Receipt,\n} from \"effect-agent/durable-agent-runtime\";\nimport {\n DurableRuntimeFailpointError,\n DurableRuntimeFailpointLocation,\n} from \"effect-agent/durable-failpoint\";\nimport { DurableStep, DurableStepError } from \"effect-agent/durable-step\";\nimport { IdGenerator } from \"effect-agent/id-generator\";\nimport {\n ThreadId,\n RunId,\n ToolCallId,\n TurnId,\n type AgentId,\n type SubmissionId,\n} from \"effect-agent/identifiers\";\nimport {\n DefinitionDigests,\n DeploymentId,\n Digest,\n ProducerId,\n type BatchId,\n} from \"effect-agent/records\";\nimport { childThreadIdFor } from \"effect-agent/run-journal\";\nimport { RunToolAuthorization } from \"effect-agent/run-options\";\nimport * as Subagent from \"effect-agent/subagent\";\nimport { SubagentPolicy } from \"effect-agent/subagent\";\nimport { SubagentReservationsMemoryLive } from \"effect-agent/subagent-reservations\";\nimport {\n ApprovalDecisionCommand,\n IdempotencyKey,\n Principal,\n ResolutionSafeToRetry,\n SubmissionLedger,\n SubmissionLookupById,\n UnknownResolutionCommand,\n DEFAULT_OWNERSHIP_LEASE_DURATION,\n type SubmissionSnapshot,\n} from \"effect-agent/submission-ledger\";\nimport {\n type CertificationCaseResult,\n type CertificationReport,\n CertificationSweepResult,\n CertificationTierThreeReport,\n CertifiedAdapterIdentity,\n certifyPorts,\n type CertificationScenario,\n} from \"effect-agent/testing/certification\";\nimport { DurableRuntimeFailpointTestControl } from \"effect-agent/testing/durable-failpoint-test-control\";\nimport { verifyThreadInvariants } from \"effect-agent/thread-invariants\";\nimport { ThreadExportRequest, ThreadStore, LoadCheckpointRequest } from \"effect-agent/thread-store\";\nimport { ToolReconciler } from \"effect-agent/tool-reconciler\";\nimport { WakeScheduler } from \"effect-agent/wake-scheduler\";\nimport { TestClock } from \"effect/testing\";\nimport { LanguageModel, Model, Tool, Toolkit, type Response } from \"effect/unstable/ai\";\n\nimport { makeCertificationReport } from \"./internal/certification-report.ts\";\n\n/**\n * P7 WP2 — `certifyDurableAdapters` (plan §1): the one certification entry point a durable\n * adapter pair runs to earn a Schema-encoded certificate.\n *\n * - **Tier 1 — port contract**: the two shared conformance case arrays, verbatim, through\n * `certifyPorts` (TEST-004/STORE-010).\n * - **Tier 2 — coordinator protocol + failpoint convergence**: the durable coordinator is\n * assembled over the CANDIDATE Layer pair with a scripted deterministic model; every\n * reached `DurableRuntimeFailpointLocation` is armed one-shot across the six scenario shapes\n * (plain / uncertain-tool / durable-steps / approval / join / delegation). Unreached locations\n * share a verified clean run per shape; new unaccounted-for locations get a full sweep.\n * After the injected fault the runner asserts the state stays CLASSIFIABLE (recovery +\n * the public unblocking operations `resolveUnknown`/`resolveApproval` are the only levers\n * used) and that the re-drive CONVERGES to `verifyThreadInvariants` with `requireAllSettled`,\n * including a fully discharged digest-chain check, because the runner captures per-batch producer\n * identity at append time.\n * - **Tier 3 — real loss lever**: recorded honestly. A durable adapter either supplies a\n * `CertificationCrashLever` executed in this run, cites its committed real-loss evidence\n * (process-kill / eviction suites), or the certificate says `not-exercised`. A non-durable\n * reference adapter records `not-applicable`.\n *\n * The runner is adapter-neutral and platform-neutral: it imports nothing Node-only, so the\n * same entry point runs under `@effect/vitest` on Node and inside workerd (storage-cloudflare's\n * in-workerd runner). It must run under a TestClock (Tier 1 drives lease expiry through\n * virtual time), and requires only `Crypto.Crypto` from the environment.\n */\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\n/**\n * A real-loss lever supplied by an adapter that wants Tier 3 exercised IN this certification\n * run (kill/evict/reopen around a designated row subset). Rows report with\n * `suite: \"real-loss\"`. Failures must be captured per-row — the lever's error channel is\n * `never` so a certificate is always produced.\n */\nexport type CertificationCrashLever = Effect.Effect<ReadonlyArray<CertificationCaseResult>>;\n\nexport interface CertifyDurableAdaptersOptions<LedgerE = never, StoreE = never> {\n /** Adapter pair identity named by the certificate (durability is read from the ledger). */\n readonly adapter: {\n readonly name: string;\n readonly version?: string | undefined;\n };\n /**\n * The candidate Layer pair. When both ports must share one connection root (the ADR-0011\n * \"same file\" rule), pass the SAME combined Layer instance for both fields — Layer\n * memoization builds it once. A candidate may require `Crypto.Crypto` (the memory reference\n * does); the certification's own environment supplies nothing else.\n */\n readonly submissionLedger: Layer.Layer<SubmissionLedger, LedgerE, Crypto.Crypto>;\n readonly threadStore: Layer.Layer<ThreadStore, StoreE, Crypto.Crypto>;\n /** Defaults to `WakeScheduler.layerNoop`; the runner re-drives lanes explicitly. */\n readonly wakeScheduler?: Layer.Layer<WakeScheduler> | undefined;\n /** Executes Tier 3 in this run; takes precedence over `tierThreeEvidence`. */\n readonly crashLever?: CertificationCrashLever | undefined;\n /** Repository-relative citations of committed real-loss suites (Tier 3 `recorded-evidence`). */\n readonly tierThreeEvidence?: ReadonlyArray<string> | undefined;\n /**\n * The candidate ledger's configured ownership lease (defaults to the D5 default, 30s).\n * Every Tier-2 re-drive round advances the TestClock past this lease before reclaiming:\n * a live lease may block ALL new claims (the SQL adapters do; the memory reference also\n * allows same-producer reclaim), so the adapter-NEUTRAL recovery lever after a mid-Attempt\n * fault is lease expiry — exactly the documented D5 liveness mechanism, driven through\n * virtual time.\n */\n readonly ownershipLeaseDuration?: Duration.Duration | undefined;\n}\n\n/** The six Tier-2 scenario shapes in sweep order. */\nexport const CERTIFICATION_SCENARIOS: ReadonlyArray<CertificationScenario> = [\n \"plain\",\n \"uncertain-tool\",\n \"durable-steps\",\n \"approval\",\n \"join\",\n \"delegation\",\n];\n\n/**\n * Coordinator failpoint locations that none of the six scenario shapes can reach, recorded\n * honestly instead of silently claimed. These require operator, compaction, reservation,\n * background-worker, or Agent-update paths the shapes do not take. They are pinned in-process\n * by the P5/S2 suites (`packages/testing/test/durable-tools.test.ts` \"resolveUnknown is idempotent across the\n * intent failpoint\", `durable-runtime.test.ts` abort rows,\n * `durable-subagents.test.ts` abort propagation) and by the process-kill/eviction crash\n * matrices. Runner tests assert the observed never-fired set equals EXACTLY this list, so a\n * protocol change that silently stops exercising a location fails the certification.\n */\nexport const TIER2_UNREACHED_LOCATIONS: ReadonlyArray<DurableRuntimeFailpointLocation> = [\n // Active timeout recording is covered before/after append by durable-runtime.test.ts.\n \"run:before-duration-append\",\n \"run:after-duration-append\",\n // Tier 2 has no native compaction; dedicated checkpoint process-loss tests cover these.\n \"checkpoint:before-save\",\n \"checkpoint:after-save\",\n \"abort:after-intent\",\n // Compaction requires a `contextTokenLimit` policy plus prior-Run history\n // none of the six scenario shapes carries; pinned in-process by the\n // RUN-026 rows in `packages/testing/test/durable-runtime.test.ts`\n // (compaction failpoint idempotence across re-drive).\n \"compaction:before-canonical-append\",\n \"compaction:after-canonical-append\",\n // These shapes use neither programmatic Tools nor grace finalization. Their reservations\n // are exercised before/after append in the public durable-runtime regression suite.\n \"policy:before-reservation-append\",\n \"policy:after-reservation-append\",\n \"resolve:after-intent\",\n // All six shapes retain their original Tool contracts, so none retires an unavailable\n // operation. The deployment continuity matrix in durable-runtime.test.ts exercises the\n // actual before/after-unavailable append boundaries, asserting absent/present canonical\n // ToolUnavailable results at the crash and one original-call settlement after re-drive.\n \"tools:before-unavailable-append\",\n \"tools:after-unavailable-append\",\n \"subagent:after-child-abort-intent\",\n // Background workers use retained delivery, source capacity, and child-origin paths absent\n // from these six attached/ordinary scenarios. The before/after creation and completion\n // boundaries are exercised by packages/effect-agent/test/durable/worker-host.test.ts.\n \"worker:before-source-append\",\n \"worker:after-source-append\",\n \"worker:before-origin-append\",\n \"worker:after-origin-append\",\n \"worker:before-completion-append\",\n \"worker:after-completion-append\",\n // Root attached declarations keep their independent pool; nested shared subtree mutations\n // are covered by the same focused worker-host failpoint suite.\n \"worker:before-subtree-append\",\n \"worker:after-subtree-append\",\n // Automatic report decisions and retained delivery insertion have dedicated worker crash tests.\n \"worker:before-report-append\",\n \"worker:after-report-append\",\n \"worker:before-report-delivery\",\n \"worker:after-report-delivery\",\n // None of the six shapes emits Agent updates. All four boundaries are exercised separately\n // by packages/effect-agent/test/durable/worker-host.test.ts (\"repairs an accepted parent update after ...\").\n // Node restart/lost-ack coverage is in packages/platform-node/test/worker-updates.test.ts;\n // Cloudflare eviction/alarm recovery is in packages/platform-cloudflare/test/background-workers.test.ts.\n // These suites are not executed by this certification runner; its update rows remain not-triggered.\n \"update:before-canonical-append\",\n \"update:after-canonical-append\",\n \"update:before-delivery-insert\",\n \"update:after-delivery-insert\",\n];\n\n/** Locations of `tier2` rows whose armed fault never fired in ANY scenario, sorted. */\nexport const tier2NeverFiredLocations = (\n tier2: ReadonlyArray<CertificationSweepResult>,\n): ReadonlyArray<DurableRuntimeFailpointLocation> => {\n const fired = new Set<DurableRuntimeFailpointLocation>();\n\n for (const row of tier2) {\n if (row.failpointFired) fired.add(row.location);\n }\n\n return DurableRuntimeFailpointLocation.literals.filter((location) => !fired.has(location)).sort();\n};\n\n// ---------------------------------------------------------------------------\n// Deterministic fixtures (scripted prompt-shape models, agents, delegation)\n// ---------------------------------------------------------------------------\n\nconst SHA_A = Schema.decodeSync(Digest)(\"a\".repeat(64));\nconst DIGESTS = DefinitionDigests.make({ agent: SHA_A, model: SHA_A, tools: SHA_A });\n\nconst CHILD_DIGEST_STRINGS = {\n agent: \"b\".repeat(64),\n model: \"c\".repeat(64),\n tools: \"d\".repeat(64),\n} as const;\n\nconst CHILD_DIGESTS = DefinitionDigests.make({\n agent: Schema.decodeSync(Digest)(CHILD_DIGEST_STRINGS.agent),\n model: Schema.decodeSync(Digest)(CHILD_DIGEST_STRINGS.model),\n tools: Schema.decodeSync(Digest)(CHILD_DIGEST_STRINGS.tools),\n});\n\nconst PRINCIPAL = Schema.decodeSync(Principal)(\"principal-certification\");\nconst decodeThreadId = Schema.decodeSync(ThreadId);\nconst decodeIdempotencyKey = Schema.decodeSync(IdempotencyKey);\nconst decodeToolCallId = Schema.decodeSync(ToolCallId);\n\nconst usage = { inputTokens: {}, outputTokens: {} };\n\nconst finalParts = (text: string): ReadonlyArray<Response.StreamPartEncoded> => [\n { type: \"text-start\", id: \"answer\" },\n { type: \"text-delta\", id: \"answer\", delta: text },\n { type: \"text-end\", id: \"answer\" },\n { type: \"finish\", reason: \"stop\", usage },\n];\n\nconst toolCallPart = (id: string, name: string, params: unknown): Response.StreamPartEncoded => ({\n type: \"tool-call\",\n id,\n name,\n params,\n providerExecuted: false,\n});\n\nconst toolTurn = (\n ...calls: ReadonlyArray<Response.StreamPartEncoded>\n): ReadonlyArray<Response.StreamPartEncoded> => [\n ...calls,\n { type: \"finish\", reason: \"tool-calls\", usage },\n];\n\n/**\n * Stateless scripted model that decides by PROMPT SHAPE instead of call count: while the\n * prompt carries no committed tool result the model declares `toolParts` (when given),\n * otherwise it answers with the final text. Deciding on the canonical prompt keeps every cell\n * deterministic regardless of where the injected fault fell — a re-invoked Turn re-declares\n * the same batch and a resumed batch flows into the final answer, so every scenario always\n * exercises its tool path and always converges.\n */\nconst promptShapeModel = (\n name: string,\n finalText: string,\n toolParts?: ReadonlyArray<Response.StreamPartEncoded>,\n) =>\n Model.make(\n \"scripted\",\n name,\n Layer.effect(\n LanguageModel.LanguageModel,\n LanguageModel.make({\n generateText: () => Effect.succeed([]),\n streamText: (request) => {\n const hasToolResult = request.prompt.content.some((message) => message.role === \"tool\");\n\n const parts =\n toolParts === undefined || hasToolResult ? finalParts(finalText) : toolParts;\n\n return Stream.fromIterable(parts);\n },\n }),\n ),\n );\n\n// Tier-2 intentionally advances virtual time past a 30-second ownership lease on every\n// re-drive round. Keep its business-policy duration above the full eight-round sweep so this\n// fixture certifies crash convergence rather than accidentally relying on a fresh duration\n// allowance per replacement Attempt. RUN-030 owns the dedicated duration-expiry coverage.\nconst CERTIFICATION_MAX_DURATION = \"10 minutes\" as const;\n\nconst policy = AgentPolicy.make({\n maxTurns: 4,\n maxToolCalls: 4,\n maxDuration: CERTIFICATION_MAX_DURATION,\n toolConcurrency: 2,\n});\n\nconst QuestionInput = Schema.Struct({ question: Schema.String });\nconst AnswerOutput = Schema.Struct({ answer: Schema.String });\n\n/** plain / join: no tools — the pure Turn/submission/join seams. */\nconst plainDefinition = Agent.make(\"certify-plain\", {\n input: QuestionInput,\n output: AnswerOutput,\n instructions: \"Answer as JSON.\",\n toolkit: Toolkit.empty,\n policy,\n});\n\n/** uncertain-tool: unannotated → fail-closed `uncertain`, enters the prepared/settled protocol. */\nconst Book = Tool.make(\"book\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ confirmation: Schema.String }),\n});\n\nconst bookToolkit = Toolkit.make(Book);\n\nconst uncertainDefinition = Agent.make(\"certify-uncertain\", {\n input: QuestionInput,\n output: AnswerOutput,\n instructions: \"Book it.\",\n toolkit: bookToolkit,\n policy,\n});\n\n/** durable-steps: declaring `DurableStep` as a dependency is what makes the Tool durable. */\nconst Itinerary = Tool.make(\"itinerary\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ state: Schema.String }),\n failure: DurableStepError,\n dependencies: [DurableStep],\n});\n\nconst itineraryToolkit = Toolkit.make(Itinerary);\n\nconst stepsDefinition = Agent.make(\"certify-steps\", {\n input: QuestionInput,\n output: AnswerOutput,\n instructions: \"Reserve the itinerary.\",\n toolkit: itineraryToolkit,\n policy,\n});\n\n/** approval: fail-closed — no `DurableApprovalResolver` Layer, so undecided approvals suspend. */\nconst BookApproval = Tool.make(\"book\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ confirmation: Schema.String }),\n needsApproval: true,\n});\n\nconst approvalToolkit = Toolkit.make(BookApproval);\n\nconst approvalDefinition = Agent.make(\"certify-approval\", {\n input: QuestionInput,\n output: AnswerOutput,\n instructions: \"Book after approval.\",\n toolkit: approvalToolkit,\n policy,\n});\n\n/** delegation: durable attached child plus an ordinary uncertain sibling in ONE batch. */\nconst childDefinition = Agent.make(\"certify-child\", {\n input: QuestionInput,\n output: AnswerOutput,\n instructions: \"Answer as JSON.\",\n toolkit: Toolkit.empty,\n policy: AgentPolicy.make({\n maxTurns: 2,\n maxToolCalls: 1,\n maxDuration: CERTIFICATION_MAX_DURATION,\n toolConcurrency: 1,\n }),\n});\n\nclass CertifyDelegationFailed extends Schema.TaggedError<CertifyDelegationFailed>()(\n \"CertifyDelegationFailed\",\n { childErrorTag: Schema.String },\n) {}\n\nconst researchDelegation = Subagent.define(\"delegate_research\", {\n description: \"Research one bounded question and return findings.\",\n target: childDefinition,\n parameters: Schema.Struct({ topic: Schema.String }),\n success: Schema.Struct({ summary: Schema.String }),\n failure: CertifyDelegationFailed,\n prepareInput: ({ topic }) => Effect.succeed({ question: `research:${topic}` }),\n projectResult: (output) => Effect.succeed({ summary: `finding:${output.answer}` }),\n policy: SubagentPolicy.make({\n maxChildren: 2,\n maxConcurrency: 2,\n maxTurns: 4,\n maxToolCalls: 4,\n maxDuration: CERTIFICATION_MAX_DURATION,\n }),\n});\n\nconst Lookup = Tool.make(\"lookup\", {\n parameters: Schema.Struct({ key: Schema.String }),\n success: Schema.Struct({ value: Schema.String }),\n});\n\nconst coordinatorDefinition = Agent.make(\"certify-coordinator\", {\n input: Schema.Struct({ mission: Schema.String }),\n output: Schema.Struct({ report: Schema.String }),\n instructions: \"Delegate and look up, then answer as JSON.\",\n toolkit: Toolkit.make(researchDelegation.tool, Lookup),\n policy: AgentPolicy.make({\n maxTurns: 4,\n maxToolCalls: 3,\n maxDuration: CERTIFICATION_MAX_DURATION,\n toolConcurrency: 2,\n }),\n});\n\nconst mapChildFailure = (failure: { readonly _tag: string }) =>\n CertifyDelegationFailed.make({ childErrorTag: failure._tag });\n\nconst DELEGATE_CALL = decodeToolCallId(\"delegate-1\");\n\n/** Fixture-only identity source consumed by the delegation Layer's ephemeral capture. */\nconst identifiers = Layer.effect(\n IdGenerator,\n Effect.gen(function* () {\n const counter = yield* Ref.make(0);\n\n const next = <A>(decode: (value: string) => A, prefix: string) =>\n Ref.getAndUpdate(counter, (value) => value + 1).pipe(\n Effect.map((value) => decode(`${prefix}-${value}`)),\n );\n\n return {\n nextThreadId: next(decodeThreadId, \"certify-fixture-thread\"),\n nextRunId: next(Schema.decodeSync(RunId), \"certify-fixture-run\"),\n nextTurnId: next(Schema.decodeSync(TurnId), \"certify-fixture-turn\"),\n };\n }),\n);\n\nconst delegationSupport = Layer.mergeAll(SubagentReservationsMemoryLive, identifiers);\n\n// ---------------------------------------------------------------------------\n// Tier 2 — scenario cells\n// ---------------------------------------------------------------------------\n\ninterface CertificationCell {\n readonly bindings: ReadonlyArray<ResolvedBinding>;\n /** Idempotent submission batch — safe to replay verbatim after a submit-boundary fault. */\n readonly submit: Effect.Effect<ReadonlyArray<Receipt>, DurableSubmitFailure, DurableAgentRuntime>;\n /** All lanes of the cell in drive order, computed from the (possibly replayed) receipts. */\n readonly lanes: (receipts: ReadonlyArray<Receipt>) => ReadonlyArray<ThreadId>;\n}\n\nconst submitOptionsFor = (slug: string, threadId: ThreadId): DurableSubmitOptions => ({\n threadId,\n principal: PRINCIPAL,\n idempotencyKey: decodeIdempotencyKey(`certify-key-${slug}`),\n definitions: DIGESTS,\n});\n\n/** One single-agent cell: one lane, one Submission, one registered exact-digest binding. */\nconst makeSingleAgentCell = (\n definition: { readonly id: AgentId; readonly input: typeof QuestionInput },\n resolved: ResolvedBinding,\n slug: string,\n): CertificationCell => {\n const threadId = decodeThreadId(`certify-${slug}`);\n\n const submit = Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n\n const receipt = yield* runtime.submit(\n { definition: { id: definition.id, input: definition.input } },\n { question: `certify ${slug}` },\n submitOptionsFor(slug, threadId),\n );\n\n return [receipt];\n });\n\n return {\n bindings: [resolved],\n submit,\n lanes: () => [threadId],\n };\n};\n\nconst makeCell = Effect.fn(\"Certification.makeCell\")(function* (\n scenario: CertificationScenario,\n slug: string,\n) {\n switch (scenario) {\n case \"plain\": {\n const binding = Agent.withModel(\n plainDefinition,\n promptShapeModel(\"certify-plain\", '{\"answer\":\"done\"}'),\n );\n\n const resolved = yield* DurableWorkerBinding.make(binding, DIGESTS);\n\n return makeSingleAgentCell(plainDefinition, resolved, slug);\n }\n case \"uncertain-tool\": {\n const binding = Agent.withModel(\n uncertainDefinition,\n promptShapeModel(\n \"certify-uncertain\",\n '{\"answer\":\"booked\"}',\n toolTurn(toolCallPart(\"book-1\", \"book\", { ref: `r-${slug}` })),\n ),\n );\n\n const toolLayer = bookToolkit.toLayer({\n book: ({ ref }) => Effect.succeed({ confirmation: `confirmed-${ref}` }),\n });\n\n const resolved = yield* DurableWorkerBinding.make(binding, DIGESTS).pipe(\n Effect.provide(toolLayer),\n );\n\n return makeSingleAgentCell(uncertainDefinition, resolved, slug);\n }\n case \"durable-steps\": {\n const binding = Agent.withModel(\n stepsDefinition,\n promptShapeModel(\n \"certify-steps\",\n '{\"answer\":\"reserved\"}',\n toolTurn(toolCallPart(\"itinerary-1\", \"itinerary\", { ref: `trip-${slug}` })),\n ),\n );\n\n const toolLayer = itineraryToolkit.toLayer({\n itinerary: ({ ref }) =>\n Effect.gen(function* () {\n const step = yield* DurableStep;\n\n const flight = yield* step.do(\n \"reserve-flight\",\n Schema.String,\n Effect.succeed(`flight-${ref}`),\n );\n\n const lodging = yield* step.do(\n \"reserve-lodging\",\n Schema.String,\n Effect.succeed(`lodging-${ref}`),\n );\n\n return { state: `${flight}+${lodging}` };\n }),\n });\n\n const resolved = yield* DurableWorkerBinding.make(binding, DIGESTS).pipe(\n Effect.provide(toolLayer),\n );\n\n return makeSingleAgentCell(stepsDefinition, resolved, slug);\n }\n case \"approval\": {\n const binding = Agent.withModel(\n approvalDefinition,\n promptShapeModel(\n \"certify-approval\",\n '{\"answer\":\"approved\"}',\n toolTurn(toolCallPart(\"book-1\", \"book\", { ref: `r-${slug}` })),\n ),\n );\n\n const toolLayer = approvalToolkit.toLayer({\n book: ({ ref }) => Effect.succeed({ confirmation: `confirmed-${ref}` }),\n });\n\n const resolved = yield* DurableWorkerBinding.make(binding, DIGESTS).pipe(\n Effect.provide(toolLayer),\n );\n\n return makeSingleAgentCell(approvalDefinition, resolved, slug);\n }\n case \"join\": {\n const binding = Agent.withModel(\n plainDefinition,\n promptShapeModel(\"certify-join\", '{\"answer\":\"host answer\"}'),\n );\n\n const resolved = yield* DurableWorkerBinding.make(binding, DIGESTS);\n const threadId = decodeThreadId(`certify-${slug}`);\n\n const submitOne = Effect.fn(\"Certification.submitOne\")(function* (\n key: string,\n question: string,\n ) {\n const runtime = yield* DurableAgentRuntime;\n\n return yield* runtime.submit(\n { definition: { id: plainDefinition.id, input: plainDefinition.input } },\n { question },\n {\n threadId,\n principal: PRINCIPAL,\n idempotencyKey: decodeIdempotencyKey(key),\n definitions: DIGESTS,\n },\n );\n });\n\n const cell: CertificationCell = {\n bindings: [resolved],\n submit: Effect.gen(function* () {\n const host = yield* submitOne(`certify-key-${slug}-host`, \"host question\");\n const queued = yield* submitOne(`certify-key-${slug}-queued`, \"queued question\");\n\n return [host, queued];\n }),\n lanes: () => [threadId],\n };\n\n return cell;\n }\n case \"delegation\": {\n const childBinding = Agent.withModel(\n childDefinition,\n promptShapeModel(\"certify-child\", '{\"answer\":\"child-answer\"}'),\n );\n\n const parentBinding = Agent.withModel(\n coordinatorDefinition,\n promptShapeModel(\n \"certify-parent\",\n '{\"report\":\"done\"}',\n toolTurn(\n toolCallPart(\"delegate-1\", \"delegate_research\", { topic: \"paris\" }),\n toolCallPart(\"lookup-1\", \"lookup\", { key: \"hotels\" }),\n ),\n ),\n );\n\n const delegationLayer = Subagent.layer(researchDelegation, childBinding, {\n mapChildFailure,\n durable: { targetDigests: CHILD_DIGEST_STRINGS },\n }).pipe(Layer.provide(delegationSupport));\n\n const lookupLayer = Toolkit.make(Lookup).toLayer({\n lookup: ({ key }) => Effect.succeed({ value: `found-${key}` }),\n });\n\n const parentResolved = yield* DurableWorkerBinding.make(parentBinding, DIGESTS).pipe(\n Effect.provide(Layer.mergeAll(delegationLayer, lookupLayer)),\n );\n\n const childResolved = yield* DurableWorkerBinding.make(childBinding, CHILD_DIGESTS);\n const threadId = decodeThreadId(`certify-${slug}`);\n\n const cell: CertificationCell = {\n bindings: [parentResolved, childResolved],\n submit: Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n\n const receipt = yield* runtime.submit(\n { definition: { id: coordinatorDefinition.id, input: coordinatorDefinition.input } },\n { mission: \"plan\" },\n submitOptionsFor(slug, threadId),\n );\n\n return [receipt];\n }),\n lanes: (receipts) => {\n const parent = receipts.at(0);\n\n return parent === undefined\n ? [threadId]\n : [threadId, childThreadIdFor(parent.submissionId, DELEGATE_CALL)];\n },\n };\n\n return cell;\n }\n }\n});\n\n/** Maximum recovery/drive/unblock rounds before a cell is reported non-convergent. */\nconst MAX_REDRIVE_ROUNDS = 8;\n\n/**\n * Verify one lane after convergence: canonical export + every lane Submission the ledger or\n * the log names (the same collection rule as the admin `verify` member), fed to the shared\n * invariant checker in convergence mode WITH the captured per-batch producer directory, so\n * the digest chain is fully recomputed instead of skipped.\n */\nconst verifyLane = Effect.fn(\"Certification.verifyLane\")(function* (\n lane: ThreadId,\n batchProducers: ReadonlyMap<BatchId, ProducerId>,\n) {\n const store = yield* ThreadStore;\n const ledger = yield* SubmissionLedger;\n const exported = yield* store.export(ThreadExportRequest.make({ threadId: lane }));\n const rows = new Map<SubmissionId, SubmissionSnapshot>();\n const nonterminal = yield* Stream.runCollect(ledger.scanNonterminal);\n const named = new Set<SubmissionId>();\n\n for (const submission of nonterminal) {\n if (submission.threadId === lane) named.add(submission.submissionId);\n }\n\n for (const envelope of exported.records) {\n const payload = envelope.record.payload;\n\n if (\n payload._tag === \"UserInputRecorded\" ||\n payload._tag === \"SubmissionSettled\" ||\n payload._tag === \"AbortRequested\"\n ) {\n if (payload.submissionId !== undefined) named.add(payload.submissionId);\n }\n }\n for (const submissionId of named) {\n if (rows.has(submissionId)) continue;\n const found = yield* ledger.lookup(SubmissionLookupById.make({ submissionId }));\n\n if (Option.isSome(found) && found.value.threadId === lane) {\n rows.set(submissionId, found.value);\n }\n }\n\n const checkpoint =\n store.checkpoints === undefined\n ? Option.none()\n : yield* store.checkpoints.load(LoadCheckpointRequest.make({ threadId: lane }));\n\n return yield* verifyThreadInvariants({\n export: exported,\n submissions: [...rows.values()],\n batchProducers,\n checkpoint: Option.getOrUndefined(checkpoint),\n checkpointsSupported: store.checkpoints !== undefined,\n requireAllSettled: true,\n });\n});\n\nconst failureTagOf = <E>(cause: Cause.Cause<E>): string => {\n const failure = Cause.findErrorOption(cause);\n\n if (Option.isSome(failure)) {\n const error: unknown = failure.value;\n\n if (typeof error === \"object\" && error !== null && \"_tag\" in error) {\n return String(error._tag);\n }\n\n return String(error).slice(0, 256);\n }\n\n return \"defect\";\n};\n\ntype SweepOutcome = Pick<\n CertificationSweepResult,\n \"failpointFired\" | \"status\" | \"digestChainVerified\" | \"detail\"\n>;\n\n/** Discover a clean path, or arm one location; both drives converge and verify real storage. */\nconst runSweepCell = Effect.fn(\"Certification.runSweepCell\")(function* (\n scenario: CertificationScenario,\n location: DurableRuntimeFailpointLocation | undefined,\n batchProducers: ReadonlyMap<BatchId, ProducerId>,\n leaseAdvance: Duration.Duration,\n reached: Set<DurableRuntimeFailpointLocation>,\n) {\n const ledger = yield* SubmissionLedger;\n const control = yield* DurableRuntimeFailpointTestControl;\n const slug = `${scenario}-${location?.replaceAll(\":\", \"-\") ?? \"discovery\"}`;\n\n const failed = (detail: string, fired: boolean): SweepOutcome => ({\n failpointFired: fired,\n status: \"failed\",\n digestChainVerified: false,\n detail: detail.slice(0, 4_096),\n });\n\n const cell = yield* makeCell(scenario, slug);\n\n const runtime = yield* DurableAgentRuntime.pipe(\n Effect.provide(\n DurableAgentRuntime.layerWithBindings(cell.bindings).pipe(\n Layer.provide(RunToolAuthorization.allowAll),\n ),\n ),\n );\n\n const submit = cell.submit.pipe(Effect.provideService(DurableAgentRuntime, runtime));\n\n // One-shot arm: the fault fires at most once anywhere in the cell (initial drive OR a\n // re-drive round's public unblocking operation), modelling one crash at this boundary.\n const fired = yield* Ref.make(false);\n\n yield* control.setHandler((hit) =>\n Effect.suspend(() => {\n reached.add(hit);\n\n return hit !== location\n ? Effect.void\n : Ref.getAndSet(fired, true).pipe(\n Effect.flatMap((already) =>\n already\n ? Effect.void\n : Effect.fail(DurableRuntimeFailpointError.make({ location: hit })),\n ),\n );\n }),\n );\n\n // Submissions are idempotent (DUR-001): one replay recovers a submit-boundary fault.\n let receipts: ReadonlyArray<Receipt>;\n const firstSubmit = yield* Effect.exit(submit);\n\n if (Exit.isSuccess(firstSubmit)) {\n receipts = firstSubmit.value;\n } else {\n const secondSubmit = yield* Effect.exit(submit);\n\n if (Exit.isFailure(secondSubmit)) {\n yield* control.clear;\n\n return failed(\n `submission replay did not recover: ${failureTagOf(secondSubmit.cause)}`,\n yield* Ref.get(fired),\n );\n }\n receipts = secondSubmit.value;\n }\n const lanes = cell.lanes(receipts);\n\n const driveLane = (lane: ThreadId) => runtime.processThreadResolved(lane);\n\n const allSettled = Effect.gen(function* () {\n for (const receipt of receipts) {\n const snapshot = yield* ledger.lookup(\n SubmissionLookupById.make({ submissionId: receipt.submissionId }),\n );\n\n if (Option.isNone(snapshot) || snapshot.value.state !== \"settled\") return false;\n }\n\n return true;\n });\n\n // Re-drive to convergence using ONLY public operations: worker drives, recovery passes,\n // and the authorized DUR-017/approval unblocking paths chosen from `explainThread`.\n let converged = false;\n\n for (let round = 0; round < MAX_REDRIVE_ROUNDS && !converged; round++) {\n // Expire any lease a faulted Attempt left behind (D5): virtual time is the\n // adapter-neutral reclaim lever — a live lease may block every new claim.\n yield* TestClock.adjust(leaseAdvance);\n yield* Effect.exit(runtime.runRecovery());\n for (const lane of lanes) {\n yield* Effect.exit(driveLane(lane));\n }\n for (const lane of lanes) {\n const explains = yield* Effect.exit(runtime.explainThread(lane));\n\n if (Exit.isFailure(explains)) continue;\n for (const explanation of explains.value) {\n for (const unknown of explanation.evidence.unknownCalls) {\n if (unknown.resolved) continue;\n yield* Effect.exit(\n runtime.resolveUnknown(\n UnknownResolutionCommand.make({\n submissionId: explanation.submission.submissionId,\n toolCallId: unknown.toolCallId,\n author: \"certification-runner\",\n reason: `re-drive after injected fault at ${location}`,\n resolution: ResolutionSafeToRetry.make(),\n }),\n ),\n );\n }\n for (const pending of explanation.evidence.approvalsPending) {\n const decided = explanation.evidence.approvalDecisions.some(\n (decision) => decision.toolCallId === pending.toolCallId,\n );\n\n if (decided) continue;\n yield* Effect.exit(\n runtime.resolveApproval(\n ApprovalDecisionCommand.make({\n submissionId: explanation.submission.submissionId,\n toolCallId: pending.toolCallId,\n decision: \"approved\",\n resolver: \"certification-runner\",\n reason: `re-drive after injected fault at ${location}`,\n }),\n ),\n );\n }\n }\n }\n const settled = yield* Effect.exit(allSettled);\n\n converged = Exit.isSuccess(settled) && settled.value;\n }\n yield* control.clear;\n const wasFired = yield* Ref.get(fired);\n\n if (!converged) {\n return failed(`did not converge within ${MAX_REDRIVE_ROUNDS} re-drive rounds`, wasFired);\n }\n\n // Every lane of the cell must verify in convergence mode with a recomputed digest chain.\n let digestChainVerified = true;\n const failedChecks: Array<string> = [];\n\n for (const lane of lanes) {\n const verdict = yield* Effect.exit(verifyLane(lane, batchProducers));\n\n if (Exit.isFailure(verdict)) {\n return failed(`lane ${lane} could not be verified: ${failureTagOf(verdict.cause)}`, wasFired);\n }\n for (const check of verdict.value.checks) {\n if (check.status === \"failed\") {\n failedChecks.push(\n `${lane}:${check.name}${check.detail === undefined ? \"\" : ` (${check.detail})`}`,\n );\n }\n if (check.name === \"digest-chain\" && check.status !== \"passed\") {\n digestChainVerified = false;\n }\n }\n }\n if (failedChecks.length > 0 || !digestChainVerified) {\n return failed(\n failedChecks.length > 0\n ? `invariant checks failed: ${failedChecks.join(\"; \")}`\n : \"the digest chain was not fully recomputed\",\n wasFired,\n );\n }\n\n return {\n failpointFired: wasFired,\n status: wasFired ? \"converged\" : \"not-triggered\",\n digestChainVerified,\n } satisfies SweepOutcome;\n});\n\n// ---------------------------------------------------------------------------\n// Tier 3 — real loss lever record\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the Tier-3 record honestly (plan §1): a non-durable reference adapter has no real\n * loss to exercise (`not-applicable`); a supplied lever runs NOW (`exercised`); committed\n * real-loss citations are recorded (`recorded-evidence`); otherwise the certificate says\n * `not-exercised` — a scoped statement, never a silent claim.\n */\nexport const resolveTierThree = Effect.fn(\"Certification.resolveTierThree\")(function* (\n durability: CertifiedAdapterIdentity[\"durability\"],\n options: {\n readonly crashLever?: CertificationCrashLever | undefined;\n readonly tierThreeEvidence?: ReadonlyArray<string> | undefined;\n },\n): Effect.fn.Return<CertificationTierThreeReport, never> {\n if (durability === \"non-durable\") {\n return CertificationTierThreeReport.make({\n status: \"not-applicable\",\n evidence: [],\n cases: [],\n detail:\n \"the adapter declares non-durable state (reference/conformance adapter); there is no real loss to exercise\",\n });\n }\n if (options.crashLever !== undefined) {\n const cases = yield* options.crashLever;\n\n return CertificationTierThreeReport.make({\n status: cases.length === 0 ? \"not-exercised\" : \"exercised\",\n evidence: options.tierThreeEvidence ?? [],\n cases,\n ...(cases.length === 0\n ? { detail: \"the supplied crash lever executed no real-loss cases\" }\n : {}),\n });\n }\n if (options.tierThreeEvidence !== undefined && options.tierThreeEvidence.length > 0) {\n return CertificationTierThreeReport.make({\n status: \"recorded-evidence\",\n evidence: options.tierThreeEvidence,\n cases: [],\n });\n }\n\n return CertificationTierThreeReport.make({\n status: \"not-exercised\",\n evidence: [],\n cases: [],\n detail:\n \"no crash lever was supplied and no committed real-loss evidence was cited; Tier 3 is NOT discharged for this adapter\",\n });\n});\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\nconst nowUtc: Effect.Effect<DateTime.Utc> = Effect.map(Clock.currentTimeMillis, (millis) =>\n DateTime.toUtc(DateTime.makeUnsafe(millis)),\n);\n\n/**\n * Certify one durable adapter pair (plan §1, §8 WP2). Runs Tier 2 FIRST over pristine\n * storage (each cell converges to all-settled before the next starts, so the recovery scan\n * never sees foreign leftovers), then Tier 1's port contract cases (whose lanes deliberately\n * end in every nonterminal shape), then records Tier 3. Requires `Crypto.Crypto` and a\n * TestClock-backed environment; the candidate Layers are built exactly once.\n */\nexport const certifyDurableAdapters = <LedgerE = never, StoreE = never>(\n options: CertifyDurableAdaptersOptions<LedgerE, StoreE>,\n): Effect.Effect<CertificationReport, LedgerE | StoreE, Crypto.Crypto> => {\n const batchProducers = new Map<BatchId, ProducerId>();\n\n // Interpose the candidate store with an append-time capture of each batch's producer\n // identity — the one value the ThreadStore port deliberately does not export — so\n // Tier 2's invariant verification recomputes the FULL digest chain instead of skipping it.\n const capturingStore = Layer.effect(ThreadStore)(\n Effect.gen(function* () {\n const inner = yield* ThreadStore;\n\n return ThreadStore.of({\n ...inner,\n append: (request) =>\n Effect.sync(() => {\n batchProducers.set(request.batch.batchId, request.batch.producerId);\n }).pipe(Effect.andThen(inner.append(request))),\n });\n }),\n ).pipe(Layer.provide(options.threadStore));\n\n // RUN-036: certification uses the default-none Tool failure observer. Trusted application\n // reporting adds no durable transition and is verified separately from adapter certification.\n const environment = Layer.mergeAll(\n options.submissionLedger,\n capturingStore,\n options.wakeScheduler ?? WakeScheduler.layerNoop,\n DurableRuntimeFailpointTestControl.layer,\n ToolReconciler.uncertain,\n DurableRuntimeConfig.layer({\n deploymentId: Schema.decodeSync(DeploymentId)(\"deployment-certification\"),\n producerId: Schema.decodeSync(ProducerId)(\"producer-certification\"),\n settlementPollInterval: Duration.millis(50),\n leaseRenewalInterval: Duration.seconds(5),\n abortPollInterval: Duration.millis(50),\n }),\n );\n\n const leaseAdvance = Duration.millis(\n Duration.toMillis(options.ownershipLeaseDuration ?? DEFAULT_OWNERSHIP_LEASE_DURATION) + 1_000,\n );\n\n const program = Effect.gen(function* () {\n const ledger = yield* SubmissionLedger;\n\n // Tier 2 — discover each deterministic shape without a fault. Unreached locations\n // would all repeat this same clean drive, including its full digest verification.\n const tier2: Array<CertificationSweepResult> = [];\n\n const discoveries: Array<{\n readonly scenario: CertificationScenario;\n readonly outcome: SweepOutcome;\n readonly reached: Set<DurableRuntimeFailpointLocation>;\n }> = [];\n\n for (const scenario of CERTIFICATION_SCENARIOS) {\n const reached = new Set<DurableRuntimeFailpointLocation>();\n\n const outcome = yield* runSweepCell(\n scenario,\n undefined,\n batchProducers,\n leaseAdvance,\n reached,\n );\n\n discoveries.push({ scenario, outcome, reached });\n }\n const observed = new Set(discoveries.flatMap(({ reached }) => [...reached]));\n\n // Never silently omit a new location: if neither discovery nor the documented\n // never-fired set accounts for it, arm it in EVERY shape. Tests pin the fired paths\n // per shape and the never-fired set, so new or lost routes require explicit review.\n const unaccounted = new Set(\n DurableRuntimeFailpointLocation.literals.filter(\n (location) => !observed.has(location) && !TIER2_UNREACHED_LOCATIONS.includes(location),\n ),\n );\n\n for (const discovery of discoveries) {\n const { scenario, reached } = discovery;\n const outcomes = new Map<DurableRuntimeFailpointLocation, SweepOutcome>();\n\n if (discovery.outcome.status !== \"failed\") {\n while (true) {\n // Recovery may expose another route. Discover those too, without re-running a\n // cell already checked. Schema order bounds this to one drive per location.\n const location = DurableRuntimeFailpointLocation.literals.find(\n (candidate) =>\n !outcomes.has(candidate) && (reached.has(candidate) || unaccounted.has(candidate)),\n );\n\n if (location === undefined) break;\n outcomes.set(\n location,\n yield* runSweepCell(scenario, location, batchProducers, leaseAdvance, reached),\n );\n }\n }\n for (const location of DurableRuntimeFailpointLocation.literals) {\n const outcome = outcomes.get(location) ?? discovery.outcome;\n\n tier2.push(\n CertificationSweepResult.make({\n scenario,\n location,\n ...outcome,\n ...(outcomes.has(location) || outcome.status === \"failed\"\n ? {}\n : { detail: \"verified clean scenario did not reach this location\" }),\n }),\n );\n }\n }\n\n // Tier 1 — the shared port contract suites, verbatim.\n const tier1 = yield* certifyPorts();\n\n // Tier 3 — the real loss lever record.\n const capabilities = yield* ledger.capabilities;\n const tier3 = yield* resolveTierThree(capabilities.durability, options);\n\n const generatedAt = yield* nowUtc;\n\n return makeCertificationReport({\n adapter: CertifiedAdapterIdentity.make({\n name: options.adapter.name,\n ...(options.adapter.version === undefined ? {} : { version: options.adapter.version }),\n durability: capabilities.durability,\n }),\n generatedAt,\n tier1,\n tier2,\n tier3,\n });\n });\n\n return program.pipe(Effect.provide(environment));\n};\n"],"mappings":"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"}
|
package/dist/Chaos.mjs
CHANGED
|
@@ -668,7 +668,7 @@ const runChaosPlan = Effect.fn("Chaos.runChaosPlan")(function* (plan, options) {
|
|
|
668
668
|
yield* resolutionPass(plan, states, desk);
|
|
669
669
|
yield* failpoints.clear;
|
|
670
670
|
if (options?.adapterFailpoints !== void 0) yield* options.adapterFailpoints.clear;
|
|
671
|
-
yield* tolerateTyped(runtime.runRecovery);
|
|
671
|
+
yield* tolerateTyped(runtime.runRecovery());
|
|
672
672
|
yield* resolutionPass(plan, states, desk);
|
|
673
673
|
if (yield* allSettled) {
|
|
674
674
|
converged = true;
|
package/dist/Chaos.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chaos.mjs","names":[],"sources":["../src/Chaos.ts"],"sourcesContent":["import { Cause, Effect, Exit, Layer, Option, Ref, Schema, Stream } from \"effect\";\nimport { ObligationThresholds } from \"effect-agent/admin\";\nimport * as Agent from \"effect-agent/agent\";\nimport { AgentPolicy } from \"effect-agent/agent-policy\";\nimport {\n DurableWorkerBinding,\n type DurableBindingFailure,\n type ResolvedBinding,\n} from \"effect-agent/agent-registration\";\nimport {\n DurableAgentRuntime,\n DurableRuntimeConfig,\n type DurableSubmitFailure,\n type DurableWorkerFailure,\n type Receipt,\n} from \"effect-agent/durable-agent-runtime\";\nimport {\n DurableRuntimeFailpointError,\n DurableRuntimeFailpointLocation,\n} from \"effect-agent/durable-failpoint\";\nimport { DurableStep, DurableStepError, ToolExecutionClass } from \"effect-agent/durable-step\";\nimport { IdGenerator } from \"effect-agent/id-generator\";\nimport { ThreadId, RunId, ToolCallId, TurnId, type SubmissionId } from \"effect-agent/identifiers\";\nimport {\n DefinitionDigests,\n Digest,\n type CanonicalRecordEnvelope,\n type BatchId,\n type ProducerId,\n} from \"effect-agent/records\";\nimport { childThreadIdFor } from \"effect-agent/run-journal\";\nimport { RunToolAuthorization } from \"effect-agent/run-options\";\nimport * as Subagent from \"effect-agent/subagent\";\nimport { SubagentPolicy } from \"effect-agent/subagent\";\nimport { SubagentReservationsMemoryLive } from \"effect-agent/subagent-reservations\";\nimport {\n AbortCommand,\n ApprovalDecisionCommand,\n IdempotencyKey,\n Principal,\n ResolutionAbortSubmission,\n ResolutionCompletedWithResult,\n ResolutionNeverHappened,\n SubmissionLedger,\n SubmissionLookupById,\n UnknownResolutionCommand,\n type Settlement,\n type SubmissionSnapshot,\n type UnknownResolution,\n} from \"effect-agent/submission-ledger\";\nimport { DurableRuntimeFailpointTestControl } from \"effect-agent/testing/durable-failpoint-test-control\";\nimport { verifyThreadInvariants } from \"effect-agent/thread-invariants\";\nimport { ThreadExportRequest, ThreadStore } from \"effect-agent/thread-store\";\nimport {\n LanguageModel,\n Model,\n Tool,\n Toolkit,\n type Prompt,\n type Response,\n} from \"effect/unstable/ai\";\nimport { Arbitrary } from \"effect/unstable/arbitrary\";\n\n/**\n * P7 WP4 chaos machinery (plan §5): a Schema-first `ChaosPlan`, a seeded generator over\n * `effect/unstable/arbitrary`, and a\n * deterministic runner that drives the durable coordinator over whatever adapter pair the test\n * provides. Every plan ends in the SAME claims the crash matrices make:\n *\n * 1. `verifyThreadInvariants` in convergence mode over every touched Thread (the\n * shared WP1 checker — one set of claims for admin verify, certification, chaos, and soak);\n * 2. `scanObligations` returning ZERO entries (everything settled; nothing invisibly stuck);\n * 3. supplier non-fabrication wherever the deterministic desk was in play (durability §10: no\n * canonical Tool success exists that the external store did not actually produce).\n *\n * Replay contract: the memory/SQLite chaos tests derive every plan from one root seed\n * (`CHAOS_SEED` env override; see `chaosSeedFromEnv`) and print that seed plus the failing\n * plan's own seed in the failure output, so any red run is replayable byte-for-byte.\n */\n\n// ---------------------------------------------------------------------------\n// ChaosPlan schema\n// ---------------------------------------------------------------------------\n\n/** The six durable scenario flavors a chaos lane can exercise (plan §5). */\nexport const ChaosScenarioKind = Schema.Literals([\n \"plain\",\n \"uncertain-tool\",\n \"durable-steps\",\n \"approval\",\n \"join\",\n \"delegation\",\n]);\n\nexport type ChaosScenarioKind = typeof ChaosScenarioKind.Type;\n\nconst LaneIndex = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(7));\n\n/** One Submission of a plan: which lane it queues into and that lane's scenario flavor. */\nexport class ChaosSubmissionSpec extends Schema.Class<ChaosSubmissionSpec>(\n \"@effect-agent/testing/ChaosSubmissionSpec\",\n)({\n lane: LaneIndex,\n /** The lane's flavor; the FIRST spec of a lane fixes the lane's agent. */\n kind: ChaosScenarioKind,\n}) {}\n\n/** How the runner resolves a durable Unknown Outcome it encounters (DUR-017 driver). */\nexport const ChaosResolutionKind = Schema.Literals([\n /** The call provably never started: the batch resumes and executes it. */\n \"never-happened\",\n /**\n * Recovered supplier truth: resolve with the EXACT value the desk produced. Falls back to\n * `never-happened` when the desk holds no value for the call, so the runner never fabricates.\n */\n \"completed-from-supplier\",\n /** Unresolvable: route into the abort path (settles aborted, audit retained). */\n \"abort-submission\",\n]);\n\nexport type ChaosResolutionKind = typeof ChaosResolutionKind.Type;\n\nexport const ChaosApprovalDecision = Schema.Literals([\"approved\", \"denied\"]);\nexport type ChaosApprovalDecision = typeof ChaosApprovalDecision.Type;\n\nconst BoundedAdapterArm = Schema.String.check(Schema.isMaxLength(128));\n\n/**\n * One seeded chaos plan (plan §5): the full fault schedule is data, so a failing run replays\n * from the plan alone. `failpointArms` are coordinator locations; `adapterArms` are\n * adapter-owned location names the adapter test validates (the memory runner has none).\n */\nexport class ChaosPlan extends Schema.Class<ChaosPlan>(\"@effect-agent/testing/ChaosPlan\")({\n /** Identifies this plan in failure output; derived from the root seed plus the plan index. */\n seed: Schema.Int,\n /** Lane count; submissions address lanes `0..lanes-1`. */\n lanes: Schema.Int.check(Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(8)),\n submissions: Schema.NonEmptyArray(ChaosSubmissionSpec),\n /** Coordinator failpoint arms, consumed one per round (each fails every hit that round). */\n failpointArms: Schema.Array(DurableRuntimeFailpointLocation),\n /** Adapter-owned failpoint arms (e.g. SQLite `ledger:*`/`append:*` locations). */\n adapterArms: Schema.Array(BoundedAdapterArm),\n /** Flattened submission indices to abort mid-plan (modulo the submission count). */\n abortInjections: Schema.Array(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),\n /** Resolution choices for Unknown Outcomes, indexed deterministically per open call. */\n resolutionInjections: Schema.Array(ChaosResolutionKind),\n /** Approval decisions for suspended approval lanes, indexed deterministically per call. */\n approvalDecisions: Schema.Array(ChaosApprovalDecision),\n}) {}\n\n/** Per-lane verification result inside a plan report. */\nexport class ChaosLaneReport extends Schema.Class<ChaosLaneReport>(\n \"@effect-agent/testing/ChaosLaneReport\",\n)({\n threadId: ThreadId,\n kind: ChaosScenarioKind,\n submissionCount: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Verdict of `verifyThreadInvariants` in convergence mode. */\n verified: Schema.Boolean,\n}) {}\n\n/** The Schema-first outcome of one executed chaos plan. */\nexport class ChaosPlanReport extends Schema.Class<ChaosPlanReport>(\n \"@effect-agent/testing/ChaosPlanReport\",\n)({\n seed: Schema.Int,\n rounds: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n lanes: Schema.Array(ChaosLaneReport),\n /** `scanObligations` entries after convergence — MUST be zero. */\n openObligations: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n}) {}\n\n/** Typed convergence/verification failure of one chaos plan (never a bare defect). */\nexport class ChaosConvergenceFailure extends Schema.TaggedError<ChaosConvergenceFailure>()(\n \"ChaosConvergenceFailure\",\n {\n seed: Schema.Int,\n message: Schema.String.check(Schema.isMaxLength(16_384)),\n },\n) {}\n\n// ---------------------------------------------------------------------------\n// Seeded generation\n// ---------------------------------------------------------------------------\n\n/** Default root seed for chaos suites; override with the `CHAOS_SEED` environment variable. */\nexport const DEFAULT_CHAOS_SEED = 20260813;\n\nconst ChaosSeedFromEnvironment = Schema.FiniteFromString.check(Schema.isInt());\nconst decodeChaosSeedFromEnvironment = Schema.decodeUnknownOption(ChaosSeedFromEnvironment);\n\n/** The root seed for this run: `CHAOS_SEED` when set to an integer, the default otherwise. */\nexport const chaosSeedFromEnv = (env: Record<string, string | undefined>): number => {\n const raw = env[\"CHAOS_SEED\"];\n\n if (raw === undefined || raw === \"\") return DEFAULT_CHAOS_SEED;\n\n return Option.getOrElse(decodeChaosSeedFromEnvironment(raw), () => DEFAULT_CHAOS_SEED);\n};\n\nexport interface ChaosGeneratorOptions {\n /** Root seed (print this in failure output for replay). */\n readonly seed: number;\n /** How many plans to derive. */\n readonly count: number;\n /** Adapter failpoint location names available to arm (empty for memory). */\n readonly adapterArms?: ReadonlyArray<string> | undefined;\n}\n\nconst GeneratedLane = Schema.Union([\n Schema.Struct({ kind: Schema.Literal(\"join\"), depth: Schema.Literals([2, 3]) }),\n Schema.Struct({ kind: Schema.Literal(\"plain\"), depth: Schema.Literals([1, 2]) }),\n Schema.Struct({\n kind: Schema.Literals([\"uncertain-tool\", \"durable-steps\", \"approval\", \"delegation\"]),\n depth: Schema.Literal(1),\n }),\n]);\n\ninterface ChaosPlanShape {\n readonly lanes: number;\n readonly submissions: readonly [ChaosSubmissionSpec, ...Array<ChaosSubmissionSpec>];\n readonly failpointArms: ReadonlyArray<DurableRuntimeFailpointLocation>;\n readonly adapterArms: ReadonlyArray<string>;\n readonly abortInjections: ReadonlyArray<number>;\n readonly resolutionInjections: ReadonlyArray<ChaosResolutionKind>;\n readonly approvalDecisions: ReadonlyArray<ChaosApprovalDecision>;\n}\n\nconst planShapeArbitrary = (\n adapterArms: ReadonlyArray<string>,\n): Arbitrary.Arbitrary<ChaosPlanShape> =>\n Arbitrary.schema(\n Schema.Struct({\n lanes: Schema.Array(GeneratedLane).check(Schema.isMinLength(1), Schema.isMaxLength(3)),\n failpointArms: Schema.Array(DurableRuntimeFailpointLocation).check(\n Schema.isUnique(),\n Schema.isMaxLength(3),\n ),\n adapterArms: Schema.Array(\n adapterArms.length === 0 ? Schema.String : Schema.Literals(adapterArms),\n ).check(Schema.isUnique(), Schema.isMaxLength(adapterArms.length === 0 ? 0 : 2)),\n abortInjections: Schema.Array(\n Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 15 })),\n ).check(Schema.isUnique(), Schema.isMaxLength(2)),\n resolutionInjections: Schema.Array(ChaosResolutionKind).check(Schema.isMaxLength(4)),\n approvalDecisions: Schema.Array(ChaosApprovalDecision).check(Schema.isMaxLength(2)),\n }),\n ).pipe(\n Arbitrary.map((shape) => {\n const submissions = shape.lanes.flatMap((lane, index) =>\n Array.from({ length: lane.depth }, () =>\n ChaosSubmissionSpec.make({ lane: index, kind: lane.kind }),\n ),\n );\n\n const [first, ...rest] = submissions;\n\n // `lanes` >= 1 and every lane has depth >= 1, so `first` always exists.\n if (first === undefined) throw new Error(\"chaos generator produced an empty plan\");\n\n return {\n lanes: shape.lanes.length,\n submissions: [first, ...rest] as const,\n failpointArms: shape.failpointArms,\n adapterArms: shape.adapterArms,\n abortInjections: shape.abortInjections,\n resolutionInjections: shape.resolutionInjections,\n approvalDecisions: shape.approvalDecisions,\n };\n }),\n );\n\n/**\n * Derive `count` chaos plans deterministically from one root seed. The same\n * `{seed, count, adapterArms}` triple always yields byte-identical plans, so a failure line\n * `CHAOS_SEED=<seed>` replays the exact schedule with the same pinned generator version.\n * Sampling is interruptible and reports bounded generation exhaustion as Arbitrary.SampleError.\n */\nexport const generateChaosPlans = Effect.fnUntraced(function* (\n options: ChaosGeneratorOptions,\n): Effect.fn.Return<ReadonlyArray<ChaosPlan>, Arbitrary.SampleError> {\n const sampled = yield* Arbitrary.sampleEffect(planShapeArbitrary(options.adapterArms ?? []), {\n seed: options.seed,\n count: options.count,\n });\n\n return sampled.map((shape, index) =>\n ChaosPlan.make({ ...shape, seed: (Math.imul(options.seed, 31) + index) | 0 }),\n );\n});\n\n/** Deterministic PRNG for the runner's small ordering choices (lane drive order). */\nconst mulberry32 = (seed: number): (() => number) => {\n let state = seed | 0;\n\n return () => {\n state = (state + 0x6d2b79f5) | 0;\n let t = Math.imul(state ^ (state >>> 15), 1 | state);\n\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n};\n\n// ---------------------------------------------------------------------------\n// Lane fixtures (agents, scripted models, deterministic desk)\n// ---------------------------------------------------------------------------\n\nconst usage = { inputTokens: {}, outputTokens: {} };\n\nconst finalParts = (text: string): ReadonlyArray<Response.StreamPartEncoded> => [\n { type: \"text-start\", id: \"answer\" },\n { type: \"text-delta\", id: \"answer\", delta: text },\n { type: \"text-end\", id: \"answer\" },\n { type: \"finish\", reason: \"stop\", usage },\n];\n\nconst toolTurn = (\n ...calls: ReadonlyArray<Response.StreamPartEncoded>\n): ReadonlyArray<Response.StreamPartEncoded> => [\n ...calls,\n { type: \"finish\", reason: \"tool-calls\", usage },\n];\n\nconst toolCallPart = (id: string, name: string, params: unknown): Response.StreamPartEncoded => ({\n type: \"tool-call\",\n id,\n name,\n params,\n providerExecuted: false,\n});\n\n/**\n * Prompt-shaped scripted model: the response depends ONLY on the request prompt, so it stays\n * deterministic across Attempt re-invocations, batch resumes, and joined steering — no counter\n * to drift when chaos re-enters a Turn.\n */\nconst promptScriptedModel = (\n label: string,\n script: (prompt: Prompt.Prompt) => ReadonlyArray<Response.StreamPartEncoded>,\n) =>\n Model.make(\n \"scripted\",\n label,\n Layer.effect(\n LanguageModel.LanguageModel,\n LanguageModel.make({\n generateText: () => Effect.succeed([]),\n streamText: (request) => Stream.fromIterable(script(request.prompt)),\n }),\n ),\n );\n\nconst lastRole = (prompt: Prompt.Prompt): string | undefined => prompt.content.at(-1)?.role;\n\nconst policy = AgentPolicy.make({\n maxTurns: 3,\n maxToolCalls: 4,\n maxDuration: \"30 seconds\",\n toolConcurrency: 2,\n});\n\nconst PlainInput = Schema.Struct({ question: Schema.String });\nconst PlainOutput = Schema.Struct({ answer: Schema.String });\n\nconst plainDefinition = Agent.make(\"chaos-plain\", {\n input: PlainInput,\n output: PlainOutput,\n instructions: \"Answer as JSON.\",\n toolkit: Toolkit.empty,\n policy,\n});\n\n/** Unannotated → fail-closed `uncertain`: enters the prepared/settled protocol (DUR-009). */\nconst BookUncertain = Tool.make(\"book\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ confirmation: Schema.String }),\n});\n\nconst bookTools = Toolkit.make(BookUncertain);\n\nconst bookDefinition = Agent.make(\"chaos-book\", {\n input: PlainInput,\n output: PlainOutput,\n instructions: \"Book it.\",\n toolkit: bookTools,\n policy,\n});\n\nconst BookApproval = Tool.make(\"book\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ confirmation: Schema.String }),\n needsApproval: true,\n});\n\nconst approvalTools = Toolkit.make(BookApproval);\n\nconst approvalDefinition = Agent.make(\"chaos-approval\", {\n input: PlainInput,\n output: PlainOutput,\n instructions: \"Book after approval.\",\n toolkit: approvalTools,\n policy,\n});\n\nconst Itinerary = Tool.make(\"itinerary\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ state: Schema.String }),\n failure: DurableStepError,\n dependencies: [DurableStep],\n}).annotate(ToolExecutionClass, \"uncertain\");\n\nconst itineraryTools = Toolkit.make(Itinerary);\n\nconst itineraryDefinition = Agent.make(\"chaos-itinerary\", {\n input: PlainInput,\n output: PlainOutput,\n instructions: \"Reserve the itinerary.\",\n toolkit: itineraryTools,\n policy,\n});\n\nconst childDefinition = Agent.make(\"chaos-child\", {\n input: PlainInput,\n output: PlainOutput,\n instructions: \"Answer as JSON.\",\n toolkit: Toolkit.empty,\n policy: AgentPolicy.make({\n maxTurns: 2,\n maxToolCalls: 1,\n maxDuration: \"30 seconds\",\n toolConcurrency: 1,\n }),\n});\n\nclass ChaosDelegationFailed extends Schema.TaggedError<ChaosDelegationFailed>()(\n \"ChaosDelegationFailed\",\n { childErrorTag: Schema.String },\n) {}\n\nconst chaosDelegation = Subagent.define(\"delegate_chaos\", {\n description: \"Delegate one bounded chaos question.\",\n target: childDefinition,\n parameters: Schema.Struct({ topic: Schema.String }),\n success: Schema.Struct({ summary: Schema.String }),\n failure: ChaosDelegationFailed,\n prepareInput: ({ topic }) => Effect.succeed({ question: `chaos:${topic}` }),\n projectResult: (output) => Effect.succeed({ summary: `finding:${output.answer}` }),\n policy: SubagentPolicy.make({\n maxChildren: 2,\n maxConcurrency: 2,\n maxTurns: 4,\n maxToolCalls: 4,\n maxDuration: \"30 seconds\",\n }),\n});\n\nconst coordinatorDefinition = Agent.make(\"chaos-coordinator\", {\n input: Schema.Struct({ mission: Schema.String }),\n output: Schema.Struct({ report: Schema.String }),\n instructions: \"Delegate, then report as JSON.\",\n toolkit: Toolkit.make(chaosDelegation.tool),\n policy,\n});\n\nconst DELEGATE_CALL_ID = \"chaos-delegate-1\";\n\nconst HEX = \"0123456789abcdef\";\nconst decodeDigest = Schema.decodeSync(Digest);\n\nconst laneDigests = (lane: number): DefinitionDigests => {\n const digest = decodeDigest(HEX.charAt(lane % 8).repeat(64));\n\n return DefinitionDigests.make({ agent: digest, model: digest, tools: digest });\n};\n\nconst childDigestStrings = (lane: number) => {\n const char = HEX.charAt(8 + (lane % 8));\n\n return { agent: char.repeat(64), model: char.repeat(64), tools: char.repeat(64) } as const;\n};\n\nconst childLaneDigests = (lane: number): DefinitionDigests => {\n const strings = childDigestStrings(lane);\n\n return DefinitionDigests.make({\n agent: decodeDigest(strings.agent),\n model: decodeDigest(strings.model),\n tools: decodeDigest(strings.tools),\n });\n};\n\nconst CHAOS_PRINCIPAL = Schema.decodeSync(Principal)(\"principal-chaos\");\nconst decodeThreadId = Schema.decodeSync(ThreadId);\nconst decodeIdempotencyKey = Schema.decodeSync(IdempotencyKey);\nconst decodeToolCallId = Schema.decodeSync(ToolCallId);\nconst decodeRunId = Schema.decodeSync(RunId);\nconst decodeTurnId = Schema.decodeSync(TurnId);\n\n/** Fixture-only identity source consumed by the delegation Layer's ephemeral capture. */\nconst chaosIdentifiers = Layer.effect(\n IdGenerator,\n Effect.gen(function* () {\n const counter = yield* Ref.make(0);\n\n const next = <A>(decode: (value: string) => A, prefix: string) =>\n Ref.getAndUpdate(counter, (value) => value + 1).pipe(\n Effect.map((value) => decode(`${prefix}-${value}`)),\n );\n\n return {\n nextThreadId: next(decodeThreadId, \"chaos-fixture-thread\"),\n nextRunId: next(decodeRunId, \"chaos-fixture-run\"),\n nextTurnId: next(decodeTurnId, \"chaos-fixture-turn\"),\n };\n }),\n);\n\nconst delegationSupport = Layer.mergeAll(SubagentReservationsMemoryLive, chaosIdentifiers);\n\n/**\n * The deterministic external desk of one plan: every produced value is recorded so the final\n * non-fabrication sweep can prove each canonical Tool success came from here (durability §10).\n */\ninterface ChaosDesk {\n readonly produced: Effect.Effect<ReadonlySet<string>>;\n readonly record: (value: string) => Effect.Effect<void>;\n}\n\nconst makeChaosDesk: Effect.Effect<ChaosDesk> = Effect.gen(function* () {\n const produced = yield* Ref.make<ReadonlySet<string>>(new Set());\n\n return {\n produced: Ref.get(produced),\n record: (value: string) => Ref.update(produced, (current) => new Set(current).add(value)),\n };\n});\n\nconst bookConfirmation = (ref: string): string => `confirmed-${ref}`;\nconst flightValue = (ref: string): string => `flight-${ref}`;\nconst lodgingValue = (ref: string): string => `lodging-${ref}`;\n\n// ---------------------------------------------------------------------------\n// Runner\n// ---------------------------------------------------------------------------\n\n/** Adapter-owned failpoint control the SQLite runner supplies; memory has none. */\nexport interface ChaosAdapterFailpoints {\n readonly arm: (location: string) => Effect.Effect<void>;\n readonly clear: Effect.Effect<void>;\n}\n\nexport interface ChaosRunOptions {\n readonly adapterFailpoints?: ChaosAdapterFailpoints | undefined;\n /**\n * Executed at the end of every round. Adapters whose ownership leases block every new claim\n * until expiry (the SQLite ledger's D5 semantics — expiry only revokes the liveness\n * assumption; producer epochs stay the correctness fence) pass a deterministic\n * `TestClock.adjust` here so a dead Attempt's lane becomes reclaimable next round. The memory\n * ledger needs nothing: it allows same-producer reclaim under a live lease.\n */\n readonly betweenRounds?: Effect.Effect<void> | undefined;\n}\n\n/** Tolerate typed failures while preserving every defect and interruption reason. */\nconst tolerateTyped = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n): Effect.Effect<Option.Option<A>, never, R> =>\n effect.pipe(\n Effect.exit,\n Effect.flatMap((exit) => {\n if (Exit.isSuccess(exit)) return Effect.succeed(Option.some(exit.value));\n const unexpected = exit.cause.reasons.filter((reason) => reason._tag !== \"Fail\");\n\n return unexpected.length === 0\n ? Effect.succeed(Option.none<A>())\n : Effect.failCause(Cause.fromReasons<never>(unexpected));\n }),\n );\n\ninterface LaneFixture {\n readonly index: number;\n readonly kind: ChaosScenarioKind;\n readonly threadId: ThreadId;\n readonly ref: string;\n readonly deskInPlay: boolean;\n readonly submissionIndexes: ReadonlyArray<number>;\n readonly submitOne: (flatIndex: number) => Effect.Effect<Receipt, DurableSubmitFailure>;\n readonly drives: (\n firstReceipt: Receipt | undefined,\n ) => ReadonlyArray<\n Effect.Effect<ReadonlyArray<Settlement>, DurableWorkerFailure | DurableBindingFailure>\n >;\n readonly childThreadOf: (firstReceipt: Receipt) => ThreadId | undefined;\n}\n\ninterface SubmissionState {\n readonly flatIndex: number;\n readonly lane: LaneFixture;\n receipt: Receipt | undefined;\n}\n\nconst scriptFor = (\n kind: ChaosScenarioKind,\n ref: string,\n): ((prompt: Prompt.Prompt) => ReadonlyArray<Response.StreamPartEncoded>) => {\n switch (kind) {\n case \"plain\":\n case \"join\":\n return () => finalParts('{\"answer\":\"chaos\"}');\n case \"uncertain-tool\":\n case \"approval\":\n return (prompt) =>\n lastRole(prompt) === \"tool\"\n ? finalParts('{\"answer\":\"booked\"}')\n : toolTurn(toolCallPart(`book-${ref}`, \"book\", { ref }));\n case \"durable-steps\":\n return (prompt) =>\n lastRole(prompt) === \"tool\"\n ? finalParts('{\"answer\":\"reserved\"}')\n : toolTurn(toolCallPart(`itinerary-${ref}`, \"itinerary\", { ref }));\n case \"delegation\":\n return (prompt) =>\n lastRole(prompt) === \"tool\"\n ? finalParts('{\"report\":\"done\"}')\n : toolTurn(toolCallPart(DELEGATE_CALL_ID, \"delegate_chaos\", { topic: ref }));\n }\n};\n\nconst makeLaneFixture = Effect.fn(\"Chaos.makeLaneFixture\")(function* (\n plan: ChaosPlan,\n laneIndex: number,\n kind: ChaosScenarioKind,\n submissionIndexes: ReadonlyArray<number>,\n desk: ChaosDesk,\n) {\n const runtime = yield* DurableAgentRuntime;\n const threadId = decodeThreadId(`chaos-${plan.seed}-lane-${laneIndex}`);\n const ref = `ref-l${laneIndex}`;\n const script = scriptFor(kind, ref);\n const model = promptScriptedModel(`chaos-${kind}-${laneIndex}`, script);\n const digests = laneDigests(laneIndex);\n\n const submitOptionsFor = (flatIndex: number) => ({\n threadId,\n principal: CHAOS_PRINCIPAL,\n idempotencyKey: decodeIdempotencyKey(`chaos-${plan.seed}-s${flatIndex}`),\n definitions: digests,\n });\n\n const bookToolLayerFor = (tools: typeof bookTools | typeof approvalTools) =>\n tools.toLayer({\n book: ({ ref: called }) =>\n desk\n .record(bookConfirmation(called))\n .pipe(Effect.as({ confirmation: bookConfirmation(called) })),\n });\n\n const plainLaneFixture = (\n deskInPlay: boolean,\n drive: Effect.Effect<ReadonlyArray<Settlement>, DurableWorkerFailure | DurableBindingFailure>,\n submitOne: (flatIndex: number) => Effect.Effect<Receipt, DurableSubmitFailure>,\n ): LaneFixture => ({\n index: laneIndex,\n kind,\n threadId,\n ref,\n deskInPlay,\n submissionIndexes,\n submitOne,\n drives: () => [drive],\n childThreadOf: () => undefined,\n });\n\n switch (kind) {\n case \"plain\":\n case \"join\": {\n const agent = Agent.withModel(plainDefinition, model);\n\n return plainLaneFixture(false, runtime.processThread(agent, threadId), (flatIndex) =>\n runtime.submit(agent, { question: `chaos ${flatIndex}` }, submitOptionsFor(flatIndex)),\n );\n }\n case \"uncertain-tool\": {\n const agent = Agent.withModel(bookDefinition, model);\n\n return plainLaneFixture(\n true,\n runtime.processThread(agent, threadId).pipe(Effect.provide(bookToolLayerFor(bookTools))),\n (flatIndex) =>\n runtime.submit(agent, { question: `chaos ${flatIndex}` }, submitOptionsFor(flatIndex)),\n );\n }\n case \"approval\": {\n const agent = Agent.withModel(approvalDefinition, model);\n\n return plainLaneFixture(\n true,\n runtime\n .processThread(agent, threadId)\n .pipe(Effect.provide(bookToolLayerFor(approvalTools))),\n (flatIndex) =>\n runtime.submit(agent, { question: `chaos ${flatIndex}` }, submitOptionsFor(flatIndex)),\n );\n }\n case \"durable-steps\": {\n const agent = Agent.withModel(itineraryDefinition, model);\n\n const toolLayer = itineraryTools.toLayer({\n itinerary: ({ ref: called }) =>\n Effect.gen(function* () {\n const step = yield* DurableStep;\n\n const flight = yield* step.do(\n \"reserve-flight\",\n Schema.String,\n desk.record(flightValue(called)).pipe(Effect.as(flightValue(called))),\n );\n\n const lodging = yield* step.do(\n \"reserve-lodging\",\n Schema.String,\n desk.record(lodgingValue(called)).pipe(Effect.as(lodgingValue(called))),\n );\n\n return { state: `${flight}+${lodging}` };\n }),\n });\n\n return plainLaneFixture(\n true,\n runtime.processThread(agent, threadId).pipe(Effect.provide(toolLayer)),\n (flatIndex) =>\n runtime.submit(agent, { question: `chaos ${flatIndex}` }, submitOptionsFor(flatIndex)),\n );\n }\n case \"delegation\": {\n const parentBinding = Agent.withModel(coordinatorDefinition, model);\n\n const childModel = promptScriptedModel(`chaos-child-${laneIndex}`, () =>\n finalParts('{\"answer\":\"child\"}'),\n );\n\n const childBinding = Agent.withModel(childDefinition, childModel);\n\n const delegationLayer = Subagent.layer(chaosDelegation, childBinding, {\n mapChildFailure: (failure) => ChaosDelegationFailed.make({ childErrorTag: failure._tag }),\n durable: { targetDigests: childDigestStrings(laneIndex) },\n }).pipe(Layer.provide(delegationSupport));\n\n const parentResolved: ResolvedBinding = yield* DurableWorkerBinding.make(\n parentBinding,\n digests,\n ).pipe(Effect.provide(delegationLayer));\n\n const childResolved: ResolvedBinding = yield* DurableWorkerBinding.make(\n childBinding,\n childLaneDigests(laneIndex),\n );\n\n const registeredRuntime = yield* DurableAgentRuntime.pipe(\n Effect.provide(\n DurableAgentRuntime.layerWithBindings([parentResolved, childResolved]).pipe(\n Layer.provide(RunToolAuthorization.allowAll),\n ),\n ),\n );\n\n const driveResolved = (thread: ThreadId) => registeredRuntime.processThreadResolved(thread);\n\n const fixture: LaneFixture = {\n index: laneIndex,\n kind,\n threadId,\n ref,\n deskInPlay: false,\n submissionIndexes,\n submitOne: (flatIndex) =>\n runtime.submit(\n { definition: { id: coordinatorDefinition.id, input: coordinatorDefinition.input } },\n { mission: `chaos ${flatIndex}` },\n submitOptionsFor(flatIndex),\n ),\n drives: (firstReceipt) => {\n const drives: Array<\n Effect.Effect<ReadonlyArray<Settlement>, DurableWorkerFailure | DurableBindingFailure>\n > = [driveResolved(threadId)];\n\n if (firstReceipt !== undefined) {\n drives.push(\n driveResolved(\n childThreadIdFor(firstReceipt.submissionId, decodeToolCallId(DELEGATE_CALL_ID)),\n ),\n );\n }\n\n return drives;\n },\n childThreadOf: (firstReceipt) =>\n childThreadIdFor(firstReceipt.submissionId, decodeToolCallId(DELEGATE_CALL_ID)),\n };\n\n return fixture;\n }\n }\n});\n\n/** Stable per-call index into an injection list (identical across resolution passes). */\nconst injectionIndex = (submissionFlatIndex: number, callId: string, length: number): number => {\n let hash = submissionFlatIndex + 1;\n\n for (const char of callId) hash = (Math.imul(hash, 31) + char.charCodeAt(0)) | 0;\n\n return ((hash % length) + length) % length;\n};\n\nconst resolutionFor = (\n kind: ChaosResolutionKind,\n toolName: string,\n ref: string,\n produced: ReadonlySet<string>,\n): UnknownResolution => {\n switch (kind) {\n case \"abort-submission\":\n return ResolutionAbortSubmission.make();\n case \"completed-from-supplier\": {\n if (toolName === \"book\" && produced.has(bookConfirmation(ref))) {\n return ResolutionCompletedWithResult.make({\n result: { confirmation: bookConfirmation(ref) },\n isFailure: false,\n });\n }\n if (\n toolName === \"itinerary\" &&\n produced.has(flightValue(ref)) &&\n produced.has(lodgingValue(ref))\n ) {\n return ResolutionCompletedWithResult.make({\n result: { state: `${flightValue(ref)}+${lodgingValue(ref)}` },\n isFailure: false,\n });\n }\n\n // The desk never produced a value for this call — resolving \"completed\" would fabricate.\n return ResolutionNeverHappened.make();\n }\n case \"never-happened\":\n return ResolutionNeverHappened.make();\n }\n};\n\n/** Drive one DUR-017 pass: resolve Unknown Outcomes and pending approvals from the plan. */\nconst resolutionPass = Effect.fn(\"Chaos.resolutionPass\")(function* (\n plan: ChaosPlan,\n states: ReadonlyArray<SubmissionState>,\n desk: ChaosDesk,\n) {\n const runtime = yield* DurableAgentRuntime;\n const ledger = yield* SubmissionLedger;\n const produced = yield* desk.produced;\n const nonterminal = yield* tolerateTyped(Stream.runCollect(ledger.scanNonterminal));\n\n if (Option.isNone(nonterminal)) return;\n const byId = new Map<SubmissionId, SubmissionState>();\n\n for (const state of states) {\n if (state.receipt !== undefined) byId.set(state.receipt.submissionId, state);\n }\n for (const row of nonterminal.value) {\n if (row.state !== \"unknown\" && row.state !== \"suspended\") continue;\n const state = byId.get(row.submissionId);\n const explanation = yield* tolerateTyped(runtime.explain(row.submissionId));\n\n if (Option.isNone(explanation)) continue;\n const flatIndex = state?.flatIndex ?? 0;\n const ref = state?.lane.ref ?? \"ref-child\";\n\n if (row.state === \"unknown\") {\n for (const call of explanation.value.evidence.unknownCalls) {\n if (call.resolved) continue;\n\n const kind =\n plan.resolutionInjections.length === 0\n ? \"never-happened\"\n : (plan.resolutionInjections.at(\n injectionIndex(flatIndex, call.toolCallId, plan.resolutionInjections.length),\n ) ?? \"never-happened\");\n\n yield* tolerateTyped(\n runtime.resolveUnknown(\n UnknownResolutionCommand.make({\n submissionId: row.submissionId,\n toolCallId: call.toolCallId,\n author: \"chaos-runner\",\n reason: `chaos plan ${plan.seed} resolution (${kind})`,\n resolution: resolutionFor(kind, call.toolName, ref, produced),\n }),\n ),\n );\n }\n } else {\n for (const pending of explanation.value.evidence.approvalsPending) {\n const decision =\n plan.approvalDecisions.length === 0\n ? \"approved\"\n : (plan.approvalDecisions.at(\n injectionIndex(flatIndex, pending.toolCallId, plan.approvalDecisions.length),\n ) ?? \"approved\");\n\n yield* tolerateTyped(\n runtime.resolveApproval(\n ApprovalDecisionCommand.make({\n submissionId: row.submissionId,\n toolCallId: pending.toolCallId,\n decision,\n resolver: \"chaos-runner\",\n reason: `chaos plan ${plan.seed} approval (${decision})`,\n }),\n ),\n );\n }\n }\n }\n});\n\nconst submissionIdsNamedBy = (\n records: ReadonlyArray<CanonicalRecordEnvelope>,\n): ReadonlySet<SubmissionId> => {\n const named = new Set<SubmissionId>();\n\n for (const envelope of records) {\n const payload = envelope.record.payload;\n\n if (\n payload._tag === \"UserInputRecorded\" ||\n payload._tag === \"SubmissionSettled\" ||\n payload._tag === \"AbortRequested\"\n ) {\n if (payload.submissionId !== undefined) named.add(payload.submissionId);\n }\n }\n\n return named;\n};\n\n/**\n * The final non-fabrication sweep (durability §10): every canonical Tool success recorded on a\n * desk-backed lane must be a value the desk actually produced.\n */\nconst BookResult = Schema.Struct({ confirmation: Schema.String });\nconst ItineraryResult = Schema.Struct({ state: Schema.String });\nconst decodeBookResult = Schema.decodeUnknownOption(BookResult);\nconst decodeItineraryResult = Schema.decodeUnknownOption(ItineraryResult);\nconst decodeStepOutput = Schema.decodeUnknownOption(Schema.String);\n\nconst assertNoFabrication = (\n plan: ChaosPlan,\n records: ReadonlyArray<CanonicalRecordEnvelope>,\n produced: ReadonlySet<string>,\n): Effect.Effect<void, ChaosConvergenceFailure> => {\n const fabricated: Array<string> = [];\n\n const requireProduced = (value: string, label: string): void => {\n if (!produced.has(value)) fabricated.push(`${label} \"${value}\"`);\n };\n\n for (const envelope of records) {\n const payload = envelope.record.payload;\n\n if (payload._tag === \"ToolCallSettled\" && !payload.isFailure) {\n if (payload.toolName === \"book\") {\n const result = decodeBookResult(payload.result);\n\n if (Option.isSome(result)) requireProduced(result.value.confirmation, \"book result\");\n }\n if (payload.toolName === \"itinerary\") {\n const result = decodeItineraryResult(payload.result);\n\n if (Option.isSome(result)) {\n for (const part of result.value.state.split(\"+\")) {\n requireProduced(part, \"itinerary step result\");\n }\n }\n }\n }\n if (payload._tag === \"ToolStepSettled\") {\n const output = decodeStepOutput(payload.output);\n\n if (Option.isSome(output)) requireProduced(output.value, \"step output\");\n }\n }\n\n return fabricated.length === 0\n ? Effect.void\n : Effect.fail(\n ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `fabricated Tool results absent from the desk: ${fabricated.join(\", \")}`,\n }),\n );\n};\n\n/**\n * Execute one chaos plan against whatever adapters the ambient Layer provides and end in the\n * shared invariant claims. Deterministic: same plan + same adapters → same schedule.\n */\nexport const runChaosPlan = Effect.fn(\"Chaos.runChaosPlan\")(function* (\n plan: ChaosPlan,\n options?: ChaosRunOptions,\n) {\n const runtime = yield* DurableAgentRuntime;\n const ledger = yield* SubmissionLedger;\n const store = yield* ThreadStore;\n const config = yield* DurableRuntimeConfig;\n const failpoints = yield* DurableRuntimeFailpointTestControl;\n const random = mulberry32(plan.seed);\n const desk = yield* makeChaosDesk;\n\n // Lane fixtures: the FIRST spec of each lane fixes the lane's agent kind.\n const laneKinds = new Map<number, ChaosScenarioKind>();\n const laneSubmissions = new Map<number, Array<number>>();\n\n plan.submissions.forEach((spec, flatIndex) => {\n const lane = spec.lane % plan.lanes;\n\n if (!laneKinds.has(lane)) laneKinds.set(lane, spec.kind);\n const list = laneSubmissions.get(lane) ?? [];\n\n list.push(flatIndex);\n laneSubmissions.set(lane, list);\n });\n const lanes: Array<LaneFixture> = [];\n\n for (const [lane, kind] of laneKinds) {\n lanes.push(yield* makeLaneFixture(plan, lane, kind, laneSubmissions.get(lane) ?? [], desk));\n }\n\n const lanesByIndex = new Map(lanes.map((lane) => [lane.index, lane]));\n const states: Array<SubmissionState> = [];\n\n for (const [flatIndex, spec] of plan.submissions.entries()) {\n const laneIndex = spec.lane % plan.lanes;\n const lane = lanesByIndex.get(laneIndex);\n\n if (lane === undefined) {\n return yield* ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `submission ${flatIndex} addresses missing lane ${laneIndex}`,\n });\n }\n states.push({ flatIndex, lane, receipt: undefined });\n }\n const appliedAborts = new Set<number>();\n\n type ArmEntry =\n | { readonly family: \"coordinator\"; readonly location: DurableRuntimeFailpointLocation }\n | { readonly family: \"adapter\"; readonly location: string };\n\n const armQueue: Array<ArmEntry> = [\n ...plan.failpointArms.map((location): ArmEntry => ({ family: \"coordinator\", location })),\n ...plan.adapterArms.map((location): ArmEntry => ({ family: \"adapter\", location })),\n ];\n\n const allSettled = Effect.gen(function* () {\n if (states.some((state) => state.receipt === undefined)) return false;\n const nonterminal = yield* tolerateTyped(Stream.runCollect(ledger.scanNonterminal));\n\n return Option.isSome(nonterminal) && Array.from(nonterminal.value).length === 0;\n });\n\n const maxRounds = armQueue.length + states.length * 2 + 12;\n let rounds = 0;\n let converged = false;\n\n for (let round = 0; round < maxRounds; round++) {\n rounds = round + 1;\n const arm = armQueue[round];\n\n if (arm?.family === \"coordinator\") {\n const location = arm.location;\n\n yield* failpoints.setHandler((hit) =>\n hit === location\n ? Effect.fail(DurableRuntimeFailpointError.make({ location: hit }))\n : Effect.void,\n );\n } else if (arm?.family === \"adapter\" && options?.adapterFailpoints !== undefined) {\n yield* options.adapterFailpoints.arm(arm.location);\n }\n\n // Admission chaos: pending submissions retry under the active arm until a Receipt lands;\n // the identical (thread, principal, key) triple reattaches, never duplicates.\n for (const state of states) {\n if (state.receipt !== undefined) continue;\n const receipt = yield* tolerateTyped(state.lane.submitOne(state.flatIndex));\n\n if (Option.isSome(receipt)) state.receipt = receipt.value;\n }\n\n // Drive every lane (and discovered child lanes) in seeded order under the active arm.\n const order = lanes\n .map((lane) => ({ lane, rank: random() }))\n .sort((left, right) => left.rank - right.rank || left.lane.index - right.lane.index)\n .map(({ lane }) => lane);\n\n for (const lane of order) {\n const firstFlat = lane.submissionIndexes[0];\n const firstReceipt = firstFlat === undefined ? undefined : states[firstFlat]?.receipt;\n\n for (const drive of lane.drives(firstReceipt)) {\n yield* tolerateTyped(drive);\n }\n }\n\n // Abort injections fire once, while arms may still be active (abort:after-intent etc.).\n if (round >= 1) {\n for (const rawIndex of plan.abortInjections) {\n const index = rawIndex % states.length;\n\n if (appliedAborts.has(index)) continue;\n const receipt = states[index]?.receipt;\n\n if (receipt === undefined) continue;\n appliedAborts.add(index);\n yield* tolerateTyped(\n runtime.abort(\n AbortCommand.make({\n submissionId: receipt.submissionId,\n author: \"chaos-runner\",\n reason: `chaos plan ${plan.seed} abort injection`,\n }),\n ),\n );\n }\n }\n\n // First resolution pass runs under the arm so resolve:* locations can fire.\n yield* resolutionPass(plan, states, desk);\n\n yield* failpoints.clear;\n if (options?.adapterFailpoints !== undefined) yield* options.adapterFailpoints.clear;\n\n yield* tolerateTyped(runtime.runRecovery);\n // Second, unarmed pass guarantees forward progress for newly marked Unknown lanes.\n yield* resolutionPass(plan, states, desk);\n\n if (yield* allSettled) {\n converged = true;\n break;\n }\n if (options?.betweenRounds !== undefined) yield* options.betweenRounds;\n }\n\n if (!converged) {\n const nonterminal = yield* tolerateTyped(Stream.runCollect(ledger.scanNonterminal));\n\n const detail = Option.isSome(nonterminal)\n ? Array.from(nonterminal.value)\n .map((row: SubmissionSnapshot) => `${row.submissionId}(${row.state})`)\n .join(\", \")\n : \"ledger scan failed\";\n\n return yield* ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `plan did not converge within ${maxRounds} rounds; nonterminal: [${detail}]; pending receipts: ${states.filter((state) => state.receipt === undefined).length}`,\n });\n }\n\n // Final claims: the shared invariant checker per touched Thread, in convergence mode,\n // with the full digest chain (single known producer), plus the desk non-fabrication sweep.\n const produced = yield* desk.produced;\n const laneReports: Array<ChaosLaneReport> = [];\n\n const verifyThread = Effect.fn(\"Chaos.verifyThread\")(function* (\n threadId: ThreadId,\n kind: ChaosScenarioKind,\n deskInPlay: boolean,\n ) {\n const exported = yield* store.export(ThreadExportRequest.make({ threadId })).pipe(\n Effect.mapError((error) =>\n ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `export of ${threadId} failed: ${String(error)}`,\n }),\n ),\n );\n\n const rows: Array<SubmissionSnapshot> = [];\n\n for (const submissionId of submissionIdsNamedBy(exported.records)) {\n const found = yield* ledger.lookup(SubmissionLookupById.make({ submissionId })).pipe(\n Effect.mapError((error) =>\n ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `lookup of ${submissionId} failed: ${String(error)}`,\n }),\n ),\n );\n\n if (Option.isSome(found)) rows.push(found.value);\n }\n\n const batchProducers = new Map<BatchId, ProducerId>(\n exported.records.map((envelope) => [envelope.batchId, config.producerId]),\n );\n\n const report = yield* verifyThreadInvariants({\n export: exported,\n submissions: rows,\n batchProducers,\n requireAllSettled: true,\n });\n\n if (!report.ok) {\n const failed = report.checks\n .filter((check) => check.status === \"failed\")\n .map((check) => `${check.name}: ${check.detail ?? \"failed\"}`)\n .join(\"; \");\n\n return yield* ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `invariants failed for ${threadId} (${kind}): ${failed}`,\n });\n }\n if (deskInPlay) {\n yield* assertNoFabrication(plan, exported.records, produced);\n }\n laneReports.push(\n ChaosLaneReport.make({\n threadId,\n kind,\n submissionCount: rows.length,\n verified: report.ok,\n }),\n );\n });\n\n for (const lane of lanes) {\n yield* verifyThread(lane.threadId, lane.kind, lane.deskInPlay);\n // Delegation lanes: verify every materialized child Thread too.\n for (const flatIndex of lane.submissionIndexes) {\n const receipt = states[flatIndex]?.receipt;\n\n if (receipt === undefined) continue;\n const child = lane.childThreadOf(receipt);\n\n if (child === undefined) continue;\n\n const childExport = yield* Effect.exit(\n store.export(ThreadExportRequest.make({ threadId: child })),\n );\n\n if (Exit.isSuccess(childExport) && childExport.value.records.length > 0) {\n yield* verifyThread(child, \"plain\", false);\n }\n }\n }\n\n const obligations = yield* runtime\n .scanObligations(ObligationThresholds.make({ agingSeconds: 0, overdueSeconds: 0 }))\n .pipe(\n Effect.mapError((error) =>\n ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `scanObligations failed: ${String(error)}`,\n }),\n ),\n );\n\n if (obligations.entries.length > 0) {\n return yield* ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `open obligations after convergence: ${obligations.entries\n .map((entry) => `${entry.submissionId}(${entry.blockedOn})`)\n .join(\", \")}`,\n });\n }\n\n return ChaosPlanReport.make({\n seed: plan.seed,\n rounds,\n lanes: laneReports,\n openObligations: obligations.entries.length,\n });\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Chaos.mjs","names":[],"sources":["../src/Chaos.ts"],"sourcesContent":["import { Cause, Effect, Exit, Layer, Option, Ref, Schema, Stream } from \"effect\";\nimport { ObligationThresholds } from \"effect-agent/admin\";\nimport * as Agent from \"effect-agent/agent\";\nimport { AgentPolicy } from \"effect-agent/agent-policy\";\nimport {\n DurableWorkerBinding,\n type DurableBindingFailure,\n type ResolvedBinding,\n} from \"effect-agent/agent-registration\";\nimport {\n DurableAgentRuntime,\n DurableRuntimeConfig,\n type DurableSubmitFailure,\n type DurableWorkerFailure,\n type Receipt,\n} from \"effect-agent/durable-agent-runtime\";\nimport {\n DurableRuntimeFailpointError,\n DurableRuntimeFailpointLocation,\n} from \"effect-agent/durable-failpoint\";\nimport { DurableStep, DurableStepError, ToolExecutionClass } from \"effect-agent/durable-step\";\nimport { IdGenerator } from \"effect-agent/id-generator\";\nimport { ThreadId, RunId, ToolCallId, TurnId, type SubmissionId } from \"effect-agent/identifiers\";\nimport {\n DefinitionDigests,\n Digest,\n type CanonicalRecordEnvelope,\n type BatchId,\n type ProducerId,\n} from \"effect-agent/records\";\nimport { childThreadIdFor } from \"effect-agent/run-journal\";\nimport { RunToolAuthorization } from \"effect-agent/run-options\";\nimport * as Subagent from \"effect-agent/subagent\";\nimport { SubagentPolicy } from \"effect-agent/subagent\";\nimport { SubagentReservationsMemoryLive } from \"effect-agent/subagent-reservations\";\nimport {\n AbortCommand,\n ApprovalDecisionCommand,\n IdempotencyKey,\n Principal,\n ResolutionAbortSubmission,\n ResolutionCompletedWithResult,\n ResolutionNeverHappened,\n SubmissionLedger,\n SubmissionLookupById,\n UnknownResolutionCommand,\n type Settlement,\n type SubmissionSnapshot,\n type UnknownResolution,\n} from \"effect-agent/submission-ledger\";\nimport { DurableRuntimeFailpointTestControl } from \"effect-agent/testing/durable-failpoint-test-control\";\nimport { verifyThreadInvariants } from \"effect-agent/thread-invariants\";\nimport { ThreadExportRequest, ThreadStore } from \"effect-agent/thread-store\";\nimport {\n LanguageModel,\n Model,\n Tool,\n Toolkit,\n type Prompt,\n type Response,\n} from \"effect/unstable/ai\";\nimport { Arbitrary } from \"effect/unstable/arbitrary\";\n\n/**\n * P7 WP4 chaos machinery (plan §5): a Schema-first `ChaosPlan`, a seeded generator over\n * `effect/unstable/arbitrary`, and a\n * deterministic runner that drives the durable coordinator over whatever adapter pair the test\n * provides. Every plan ends in the SAME claims the crash matrices make:\n *\n * 1. `verifyThreadInvariants` in convergence mode over every touched Thread (the\n * shared WP1 checker — one set of claims for admin verify, certification, chaos, and soak);\n * 2. `scanObligations` returning ZERO entries (everything settled; nothing invisibly stuck);\n * 3. supplier non-fabrication wherever the deterministic desk was in play (durability §10: no\n * canonical Tool success exists that the external store did not actually produce).\n *\n * Replay contract: the memory/SQLite chaos tests derive every plan from one root seed\n * (`CHAOS_SEED` env override; see `chaosSeedFromEnv`) and print that seed plus the failing\n * plan's own seed in the failure output, so any red run is replayable byte-for-byte.\n */\n\n// ---------------------------------------------------------------------------\n// ChaosPlan schema\n// ---------------------------------------------------------------------------\n\n/** The six durable scenario flavors a chaos lane can exercise (plan §5). */\nexport const ChaosScenarioKind = Schema.Literals([\n \"plain\",\n \"uncertain-tool\",\n \"durable-steps\",\n \"approval\",\n \"join\",\n \"delegation\",\n]);\n\nexport type ChaosScenarioKind = typeof ChaosScenarioKind.Type;\n\nconst LaneIndex = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(7));\n\n/** One Submission of a plan: which lane it queues into and that lane's scenario flavor. */\nexport class ChaosSubmissionSpec extends Schema.Class<ChaosSubmissionSpec>(\n \"@effect-agent/testing/ChaosSubmissionSpec\",\n)({\n lane: LaneIndex,\n /** The lane's flavor; the FIRST spec of a lane fixes the lane's agent. */\n kind: ChaosScenarioKind,\n}) {}\n\n/** How the runner resolves a durable Unknown Outcome it encounters (DUR-017 driver). */\nexport const ChaosResolutionKind = Schema.Literals([\n /** The call provably never started: the batch resumes and executes it. */\n \"never-happened\",\n /**\n * Recovered supplier truth: resolve with the EXACT value the desk produced. Falls back to\n * `never-happened` when the desk holds no value for the call, so the runner never fabricates.\n */\n \"completed-from-supplier\",\n /** Unresolvable: route into the abort path (settles aborted, audit retained). */\n \"abort-submission\",\n]);\n\nexport type ChaosResolutionKind = typeof ChaosResolutionKind.Type;\n\nexport const ChaosApprovalDecision = Schema.Literals([\"approved\", \"denied\"]);\nexport type ChaosApprovalDecision = typeof ChaosApprovalDecision.Type;\n\nconst BoundedAdapterArm = Schema.String.check(Schema.isMaxLength(128));\n\n/**\n * One seeded chaos plan (plan §5): the full fault schedule is data, so a failing run replays\n * from the plan alone. `failpointArms` are coordinator locations; `adapterArms` are\n * adapter-owned location names the adapter test validates (the memory runner has none).\n */\nexport class ChaosPlan extends Schema.Class<ChaosPlan>(\"@effect-agent/testing/ChaosPlan\")({\n /** Identifies this plan in failure output; derived from the root seed plus the plan index. */\n seed: Schema.Int,\n /** Lane count; submissions address lanes `0..lanes-1`. */\n lanes: Schema.Int.check(Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(8)),\n submissions: Schema.NonEmptyArray(ChaosSubmissionSpec),\n /** Coordinator failpoint arms, consumed one per round (each fails every hit that round). */\n failpointArms: Schema.Array(DurableRuntimeFailpointLocation),\n /** Adapter-owned failpoint arms (e.g. SQLite `ledger:*`/`append:*` locations). */\n adapterArms: Schema.Array(BoundedAdapterArm),\n /** Flattened submission indices to abort mid-plan (modulo the submission count). */\n abortInjections: Schema.Array(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),\n /** Resolution choices for Unknown Outcomes, indexed deterministically per open call. */\n resolutionInjections: Schema.Array(ChaosResolutionKind),\n /** Approval decisions for suspended approval lanes, indexed deterministically per call. */\n approvalDecisions: Schema.Array(ChaosApprovalDecision),\n}) {}\n\n/** Per-lane verification result inside a plan report. */\nexport class ChaosLaneReport extends Schema.Class<ChaosLaneReport>(\n \"@effect-agent/testing/ChaosLaneReport\",\n)({\n threadId: ThreadId,\n kind: ChaosScenarioKind,\n submissionCount: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Verdict of `verifyThreadInvariants` in convergence mode. */\n verified: Schema.Boolean,\n}) {}\n\n/** The Schema-first outcome of one executed chaos plan. */\nexport class ChaosPlanReport extends Schema.Class<ChaosPlanReport>(\n \"@effect-agent/testing/ChaosPlanReport\",\n)({\n seed: Schema.Int,\n rounds: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n lanes: Schema.Array(ChaosLaneReport),\n /** `scanObligations` entries after convergence — MUST be zero. */\n openObligations: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n}) {}\n\n/** Typed convergence/verification failure of one chaos plan (never a bare defect). */\nexport class ChaosConvergenceFailure extends Schema.TaggedError<ChaosConvergenceFailure>()(\n \"ChaosConvergenceFailure\",\n {\n seed: Schema.Int,\n message: Schema.String.check(Schema.isMaxLength(16_384)),\n },\n) {}\n\n// ---------------------------------------------------------------------------\n// Seeded generation\n// ---------------------------------------------------------------------------\n\n/** Default root seed for chaos suites; override with the `CHAOS_SEED` environment variable. */\nexport const DEFAULT_CHAOS_SEED = 20260813;\n\nconst ChaosSeedFromEnvironment = Schema.FiniteFromString.check(Schema.isInt());\nconst decodeChaosSeedFromEnvironment = Schema.decodeUnknownOption(ChaosSeedFromEnvironment);\n\n/** The root seed for this run: `CHAOS_SEED` when set to an integer, the default otherwise. */\nexport const chaosSeedFromEnv = (env: Record<string, string | undefined>): number => {\n const raw = env[\"CHAOS_SEED\"];\n\n if (raw === undefined || raw === \"\") return DEFAULT_CHAOS_SEED;\n\n return Option.getOrElse(decodeChaosSeedFromEnvironment(raw), () => DEFAULT_CHAOS_SEED);\n};\n\nexport interface ChaosGeneratorOptions {\n /** Root seed (print this in failure output for replay). */\n readonly seed: number;\n /** How many plans to derive. */\n readonly count: number;\n /** Adapter failpoint location names available to arm (empty for memory). */\n readonly adapterArms?: ReadonlyArray<string> | undefined;\n}\n\nconst GeneratedLane = Schema.Union([\n Schema.Struct({ kind: Schema.Literal(\"join\"), depth: Schema.Literals([2, 3]) }),\n Schema.Struct({ kind: Schema.Literal(\"plain\"), depth: Schema.Literals([1, 2]) }),\n Schema.Struct({\n kind: Schema.Literals([\"uncertain-tool\", \"durable-steps\", \"approval\", \"delegation\"]),\n depth: Schema.Literal(1),\n }),\n]);\n\ninterface ChaosPlanShape {\n readonly lanes: number;\n readonly submissions: readonly [ChaosSubmissionSpec, ...Array<ChaosSubmissionSpec>];\n readonly failpointArms: ReadonlyArray<DurableRuntimeFailpointLocation>;\n readonly adapterArms: ReadonlyArray<string>;\n readonly abortInjections: ReadonlyArray<number>;\n readonly resolutionInjections: ReadonlyArray<ChaosResolutionKind>;\n readonly approvalDecisions: ReadonlyArray<ChaosApprovalDecision>;\n}\n\nconst planShapeArbitrary = (\n adapterArms: ReadonlyArray<string>,\n): Arbitrary.Arbitrary<ChaosPlanShape> =>\n Arbitrary.schema(\n Schema.Struct({\n lanes: Schema.Array(GeneratedLane).check(Schema.isMinLength(1), Schema.isMaxLength(3)),\n failpointArms: Schema.Array(DurableRuntimeFailpointLocation).check(\n Schema.isUnique(),\n Schema.isMaxLength(3),\n ),\n adapterArms: Schema.Array(\n adapterArms.length === 0 ? Schema.String : Schema.Literals(adapterArms),\n ).check(Schema.isUnique(), Schema.isMaxLength(adapterArms.length === 0 ? 0 : 2)),\n abortInjections: Schema.Array(\n Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 15 })),\n ).check(Schema.isUnique(), Schema.isMaxLength(2)),\n resolutionInjections: Schema.Array(ChaosResolutionKind).check(Schema.isMaxLength(4)),\n approvalDecisions: Schema.Array(ChaosApprovalDecision).check(Schema.isMaxLength(2)),\n }),\n ).pipe(\n Arbitrary.map((shape) => {\n const submissions = shape.lanes.flatMap((lane, index) =>\n Array.from({ length: lane.depth }, () =>\n ChaosSubmissionSpec.make({ lane: index, kind: lane.kind }),\n ),\n );\n\n const [first, ...rest] = submissions;\n\n // `lanes` >= 1 and every lane has depth >= 1, so `first` always exists.\n if (first === undefined) throw new Error(\"chaos generator produced an empty plan\");\n\n return {\n lanes: shape.lanes.length,\n submissions: [first, ...rest] as const,\n failpointArms: shape.failpointArms,\n adapterArms: shape.adapterArms,\n abortInjections: shape.abortInjections,\n resolutionInjections: shape.resolutionInjections,\n approvalDecisions: shape.approvalDecisions,\n };\n }),\n );\n\n/**\n * Derive `count` chaos plans deterministically from one root seed. The same\n * `{seed, count, adapterArms}` triple always yields byte-identical plans, so a failure line\n * `CHAOS_SEED=<seed>` replays the exact schedule with the same pinned generator version.\n * Sampling is interruptible and reports bounded generation exhaustion as Arbitrary.SampleError.\n */\nexport const generateChaosPlans = Effect.fnUntraced(function* (\n options: ChaosGeneratorOptions,\n): Effect.fn.Return<ReadonlyArray<ChaosPlan>, Arbitrary.SampleError> {\n const sampled = yield* Arbitrary.sampleEffect(planShapeArbitrary(options.adapterArms ?? []), {\n seed: options.seed,\n count: options.count,\n });\n\n return sampled.map((shape, index) =>\n ChaosPlan.make({ ...shape, seed: (Math.imul(options.seed, 31) + index) | 0 }),\n );\n});\n\n/** Deterministic PRNG for the runner's small ordering choices (lane drive order). */\nconst mulberry32 = (seed: number): (() => number) => {\n let state = seed | 0;\n\n return () => {\n state = (state + 0x6d2b79f5) | 0;\n let t = Math.imul(state ^ (state >>> 15), 1 | state);\n\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n};\n\n// ---------------------------------------------------------------------------\n// Lane fixtures (agents, scripted models, deterministic desk)\n// ---------------------------------------------------------------------------\n\nconst usage = { inputTokens: {}, outputTokens: {} };\n\nconst finalParts = (text: string): ReadonlyArray<Response.StreamPartEncoded> => [\n { type: \"text-start\", id: \"answer\" },\n { type: \"text-delta\", id: \"answer\", delta: text },\n { type: \"text-end\", id: \"answer\" },\n { type: \"finish\", reason: \"stop\", usage },\n];\n\nconst toolTurn = (\n ...calls: ReadonlyArray<Response.StreamPartEncoded>\n): ReadonlyArray<Response.StreamPartEncoded> => [\n ...calls,\n { type: \"finish\", reason: \"tool-calls\", usage },\n];\n\nconst toolCallPart = (id: string, name: string, params: unknown): Response.StreamPartEncoded => ({\n type: \"tool-call\",\n id,\n name,\n params,\n providerExecuted: false,\n});\n\n/**\n * Prompt-shaped scripted model: the response depends ONLY on the request prompt, so it stays\n * deterministic across Attempt re-invocations, batch resumes, and joined steering — no counter\n * to drift when chaos re-enters a Turn.\n */\nconst promptScriptedModel = (\n label: string,\n script: (prompt: Prompt.Prompt) => ReadonlyArray<Response.StreamPartEncoded>,\n) =>\n Model.make(\n \"scripted\",\n label,\n Layer.effect(\n LanguageModel.LanguageModel,\n LanguageModel.make({\n generateText: () => Effect.succeed([]),\n streamText: (request) => Stream.fromIterable(script(request.prompt)),\n }),\n ),\n );\n\nconst lastRole = (prompt: Prompt.Prompt): string | undefined => prompt.content.at(-1)?.role;\n\nconst policy = AgentPolicy.make({\n maxTurns: 3,\n maxToolCalls: 4,\n maxDuration: \"30 seconds\",\n toolConcurrency: 2,\n});\n\nconst PlainInput = Schema.Struct({ question: Schema.String });\nconst PlainOutput = Schema.Struct({ answer: Schema.String });\n\nconst plainDefinition = Agent.make(\"chaos-plain\", {\n input: PlainInput,\n output: PlainOutput,\n instructions: \"Answer as JSON.\",\n toolkit: Toolkit.empty,\n policy,\n});\n\n/** Unannotated → fail-closed `uncertain`: enters the prepared/settled protocol (DUR-009). */\nconst BookUncertain = Tool.make(\"book\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ confirmation: Schema.String }),\n});\n\nconst bookTools = Toolkit.make(BookUncertain);\n\nconst bookDefinition = Agent.make(\"chaos-book\", {\n input: PlainInput,\n output: PlainOutput,\n instructions: \"Book it.\",\n toolkit: bookTools,\n policy,\n});\n\nconst BookApproval = Tool.make(\"book\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ confirmation: Schema.String }),\n needsApproval: true,\n});\n\nconst approvalTools = Toolkit.make(BookApproval);\n\nconst approvalDefinition = Agent.make(\"chaos-approval\", {\n input: PlainInput,\n output: PlainOutput,\n instructions: \"Book after approval.\",\n toolkit: approvalTools,\n policy,\n});\n\nconst Itinerary = Tool.make(\"itinerary\", {\n parameters: Schema.Struct({ ref: Schema.String }),\n success: Schema.Struct({ state: Schema.String }),\n failure: DurableStepError,\n dependencies: [DurableStep],\n}).annotate(ToolExecutionClass, \"uncertain\");\n\nconst itineraryTools = Toolkit.make(Itinerary);\n\nconst itineraryDefinition = Agent.make(\"chaos-itinerary\", {\n input: PlainInput,\n output: PlainOutput,\n instructions: \"Reserve the itinerary.\",\n toolkit: itineraryTools,\n policy,\n});\n\nconst childDefinition = Agent.make(\"chaos-child\", {\n input: PlainInput,\n output: PlainOutput,\n instructions: \"Answer as JSON.\",\n toolkit: Toolkit.empty,\n policy: AgentPolicy.make({\n maxTurns: 2,\n maxToolCalls: 1,\n maxDuration: \"30 seconds\",\n toolConcurrency: 1,\n }),\n});\n\nclass ChaosDelegationFailed extends Schema.TaggedError<ChaosDelegationFailed>()(\n \"ChaosDelegationFailed\",\n { childErrorTag: Schema.String },\n) {}\n\nconst chaosDelegation = Subagent.define(\"delegate_chaos\", {\n description: \"Delegate one bounded chaos question.\",\n target: childDefinition,\n parameters: Schema.Struct({ topic: Schema.String }),\n success: Schema.Struct({ summary: Schema.String }),\n failure: ChaosDelegationFailed,\n prepareInput: ({ topic }) => Effect.succeed({ question: `chaos:${topic}` }),\n projectResult: (output) => Effect.succeed({ summary: `finding:${output.answer}` }),\n policy: SubagentPolicy.make({\n maxChildren: 2,\n maxConcurrency: 2,\n maxTurns: 4,\n maxToolCalls: 4,\n maxDuration: \"30 seconds\",\n }),\n});\n\nconst coordinatorDefinition = Agent.make(\"chaos-coordinator\", {\n input: Schema.Struct({ mission: Schema.String }),\n output: Schema.Struct({ report: Schema.String }),\n instructions: \"Delegate, then report as JSON.\",\n toolkit: Toolkit.make(chaosDelegation.tool),\n policy,\n});\n\nconst DELEGATE_CALL_ID = \"chaos-delegate-1\";\n\nconst HEX = \"0123456789abcdef\";\nconst decodeDigest = Schema.decodeSync(Digest);\n\nconst laneDigests = (lane: number): DefinitionDigests => {\n const digest = decodeDigest(HEX.charAt(lane % 8).repeat(64));\n\n return DefinitionDigests.make({ agent: digest, model: digest, tools: digest });\n};\n\nconst childDigestStrings = (lane: number) => {\n const char = HEX.charAt(8 + (lane % 8));\n\n return { agent: char.repeat(64), model: char.repeat(64), tools: char.repeat(64) } as const;\n};\n\nconst childLaneDigests = (lane: number): DefinitionDigests => {\n const strings = childDigestStrings(lane);\n\n return DefinitionDigests.make({\n agent: decodeDigest(strings.agent),\n model: decodeDigest(strings.model),\n tools: decodeDigest(strings.tools),\n });\n};\n\nconst CHAOS_PRINCIPAL = Schema.decodeSync(Principal)(\"principal-chaos\");\nconst decodeThreadId = Schema.decodeSync(ThreadId);\nconst decodeIdempotencyKey = Schema.decodeSync(IdempotencyKey);\nconst decodeToolCallId = Schema.decodeSync(ToolCallId);\nconst decodeRunId = Schema.decodeSync(RunId);\nconst decodeTurnId = Schema.decodeSync(TurnId);\n\n/** Fixture-only identity source consumed by the delegation Layer's ephemeral capture. */\nconst chaosIdentifiers = Layer.effect(\n IdGenerator,\n Effect.gen(function* () {\n const counter = yield* Ref.make(0);\n\n const next = <A>(decode: (value: string) => A, prefix: string) =>\n Ref.getAndUpdate(counter, (value) => value + 1).pipe(\n Effect.map((value) => decode(`${prefix}-${value}`)),\n );\n\n return {\n nextThreadId: next(decodeThreadId, \"chaos-fixture-thread\"),\n nextRunId: next(decodeRunId, \"chaos-fixture-run\"),\n nextTurnId: next(decodeTurnId, \"chaos-fixture-turn\"),\n };\n }),\n);\n\nconst delegationSupport = Layer.mergeAll(SubagentReservationsMemoryLive, chaosIdentifiers);\n\n/**\n * The deterministic external desk of one plan: every produced value is recorded so the final\n * non-fabrication sweep can prove each canonical Tool success came from here (durability §10).\n */\ninterface ChaosDesk {\n readonly produced: Effect.Effect<ReadonlySet<string>>;\n readonly record: (value: string) => Effect.Effect<void>;\n}\n\nconst makeChaosDesk: Effect.Effect<ChaosDesk> = Effect.gen(function* () {\n const produced = yield* Ref.make<ReadonlySet<string>>(new Set());\n\n return {\n produced: Ref.get(produced),\n record: (value: string) => Ref.update(produced, (current) => new Set(current).add(value)),\n };\n});\n\nconst bookConfirmation = (ref: string): string => `confirmed-${ref}`;\nconst flightValue = (ref: string): string => `flight-${ref}`;\nconst lodgingValue = (ref: string): string => `lodging-${ref}`;\n\n// ---------------------------------------------------------------------------\n// Runner\n// ---------------------------------------------------------------------------\n\n/** Adapter-owned failpoint control the SQLite runner supplies; memory has none. */\nexport interface ChaosAdapterFailpoints {\n readonly arm: (location: string) => Effect.Effect<void>;\n readonly clear: Effect.Effect<void>;\n}\n\nexport interface ChaosRunOptions {\n readonly adapterFailpoints?: ChaosAdapterFailpoints | undefined;\n /**\n * Executed at the end of every round. Adapters whose ownership leases block every new claim\n * until expiry (the SQLite ledger's D5 semantics — expiry only revokes the liveness\n * assumption; producer epochs stay the correctness fence) pass a deterministic\n * `TestClock.adjust` here so a dead Attempt's lane becomes reclaimable next round. The memory\n * ledger needs nothing: it allows same-producer reclaim under a live lease.\n */\n readonly betweenRounds?: Effect.Effect<void> | undefined;\n}\n\n/** Tolerate typed failures while preserving every defect and interruption reason. */\nconst tolerateTyped = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n): Effect.Effect<Option.Option<A>, never, R> =>\n effect.pipe(\n Effect.exit,\n Effect.flatMap((exit) => {\n if (Exit.isSuccess(exit)) return Effect.succeed(Option.some(exit.value));\n const unexpected = exit.cause.reasons.filter((reason) => reason._tag !== \"Fail\");\n\n return unexpected.length === 0\n ? Effect.succeed(Option.none<A>())\n : Effect.failCause(Cause.fromReasons<never>(unexpected));\n }),\n );\n\ninterface LaneFixture {\n readonly index: number;\n readonly kind: ChaosScenarioKind;\n readonly threadId: ThreadId;\n readonly ref: string;\n readonly deskInPlay: boolean;\n readonly submissionIndexes: ReadonlyArray<number>;\n readonly submitOne: (flatIndex: number) => Effect.Effect<Receipt, DurableSubmitFailure>;\n readonly drives: (\n firstReceipt: Receipt | undefined,\n ) => ReadonlyArray<\n Effect.Effect<ReadonlyArray<Settlement>, DurableWorkerFailure | DurableBindingFailure>\n >;\n readonly childThreadOf: (firstReceipt: Receipt) => ThreadId | undefined;\n}\n\ninterface SubmissionState {\n readonly flatIndex: number;\n readonly lane: LaneFixture;\n receipt: Receipt | undefined;\n}\n\nconst scriptFor = (\n kind: ChaosScenarioKind,\n ref: string,\n): ((prompt: Prompt.Prompt) => ReadonlyArray<Response.StreamPartEncoded>) => {\n switch (kind) {\n case \"plain\":\n case \"join\":\n return () => finalParts('{\"answer\":\"chaos\"}');\n case \"uncertain-tool\":\n case \"approval\":\n return (prompt) =>\n lastRole(prompt) === \"tool\"\n ? finalParts('{\"answer\":\"booked\"}')\n : toolTurn(toolCallPart(`book-${ref}`, \"book\", { ref }));\n case \"durable-steps\":\n return (prompt) =>\n lastRole(prompt) === \"tool\"\n ? finalParts('{\"answer\":\"reserved\"}')\n : toolTurn(toolCallPart(`itinerary-${ref}`, \"itinerary\", { ref }));\n case \"delegation\":\n return (prompt) =>\n lastRole(prompt) === \"tool\"\n ? finalParts('{\"report\":\"done\"}')\n : toolTurn(toolCallPart(DELEGATE_CALL_ID, \"delegate_chaos\", { topic: ref }));\n }\n};\n\nconst makeLaneFixture = Effect.fn(\"Chaos.makeLaneFixture\")(function* (\n plan: ChaosPlan,\n laneIndex: number,\n kind: ChaosScenarioKind,\n submissionIndexes: ReadonlyArray<number>,\n desk: ChaosDesk,\n) {\n const runtime = yield* DurableAgentRuntime;\n const threadId = decodeThreadId(`chaos-${plan.seed}-lane-${laneIndex}`);\n const ref = `ref-l${laneIndex}`;\n const script = scriptFor(kind, ref);\n const model = promptScriptedModel(`chaos-${kind}-${laneIndex}`, script);\n const digests = laneDigests(laneIndex);\n\n const submitOptionsFor = (flatIndex: number) => ({\n threadId,\n principal: CHAOS_PRINCIPAL,\n idempotencyKey: decodeIdempotencyKey(`chaos-${plan.seed}-s${flatIndex}`),\n definitions: digests,\n });\n\n const bookToolLayerFor = (tools: typeof bookTools | typeof approvalTools) =>\n tools.toLayer({\n book: ({ ref: called }) =>\n desk\n .record(bookConfirmation(called))\n .pipe(Effect.as({ confirmation: bookConfirmation(called) })),\n });\n\n const plainLaneFixture = (\n deskInPlay: boolean,\n drive: Effect.Effect<ReadonlyArray<Settlement>, DurableWorkerFailure | DurableBindingFailure>,\n submitOne: (flatIndex: number) => Effect.Effect<Receipt, DurableSubmitFailure>,\n ): LaneFixture => ({\n index: laneIndex,\n kind,\n threadId,\n ref,\n deskInPlay,\n submissionIndexes,\n submitOne,\n drives: () => [drive],\n childThreadOf: () => undefined,\n });\n\n switch (kind) {\n case \"plain\":\n case \"join\": {\n const agent = Agent.withModel(plainDefinition, model);\n\n return plainLaneFixture(false, runtime.processThread(agent, threadId), (flatIndex) =>\n runtime.submit(agent, { question: `chaos ${flatIndex}` }, submitOptionsFor(flatIndex)),\n );\n }\n case \"uncertain-tool\": {\n const agent = Agent.withModel(bookDefinition, model);\n\n return plainLaneFixture(\n true,\n runtime.processThread(agent, threadId).pipe(Effect.provide(bookToolLayerFor(bookTools))),\n (flatIndex) =>\n runtime.submit(agent, { question: `chaos ${flatIndex}` }, submitOptionsFor(flatIndex)),\n );\n }\n case \"approval\": {\n const agent = Agent.withModel(approvalDefinition, model);\n\n return plainLaneFixture(\n true,\n runtime\n .processThread(agent, threadId)\n .pipe(Effect.provide(bookToolLayerFor(approvalTools))),\n (flatIndex) =>\n runtime.submit(agent, { question: `chaos ${flatIndex}` }, submitOptionsFor(flatIndex)),\n );\n }\n case \"durable-steps\": {\n const agent = Agent.withModel(itineraryDefinition, model);\n\n const toolLayer = itineraryTools.toLayer({\n itinerary: ({ ref: called }) =>\n Effect.gen(function* () {\n const step = yield* DurableStep;\n\n const flight = yield* step.do(\n \"reserve-flight\",\n Schema.String,\n desk.record(flightValue(called)).pipe(Effect.as(flightValue(called))),\n );\n\n const lodging = yield* step.do(\n \"reserve-lodging\",\n Schema.String,\n desk.record(lodgingValue(called)).pipe(Effect.as(lodgingValue(called))),\n );\n\n return { state: `${flight}+${lodging}` };\n }),\n });\n\n return plainLaneFixture(\n true,\n runtime.processThread(agent, threadId).pipe(Effect.provide(toolLayer)),\n (flatIndex) =>\n runtime.submit(agent, { question: `chaos ${flatIndex}` }, submitOptionsFor(flatIndex)),\n );\n }\n case \"delegation\": {\n const parentBinding = Agent.withModel(coordinatorDefinition, model);\n\n const childModel = promptScriptedModel(`chaos-child-${laneIndex}`, () =>\n finalParts('{\"answer\":\"child\"}'),\n );\n\n const childBinding = Agent.withModel(childDefinition, childModel);\n\n const delegationLayer = Subagent.layer(chaosDelegation, childBinding, {\n mapChildFailure: (failure) => ChaosDelegationFailed.make({ childErrorTag: failure._tag }),\n durable: { targetDigests: childDigestStrings(laneIndex) },\n }).pipe(Layer.provide(delegationSupport));\n\n const parentResolved: ResolvedBinding = yield* DurableWorkerBinding.make(\n parentBinding,\n digests,\n ).pipe(Effect.provide(delegationLayer));\n\n const childResolved: ResolvedBinding = yield* DurableWorkerBinding.make(\n childBinding,\n childLaneDigests(laneIndex),\n );\n\n const registeredRuntime = yield* DurableAgentRuntime.pipe(\n Effect.provide(\n DurableAgentRuntime.layerWithBindings([parentResolved, childResolved]).pipe(\n Layer.provide(RunToolAuthorization.allowAll),\n ),\n ),\n );\n\n const driveResolved = (thread: ThreadId) => registeredRuntime.processThreadResolved(thread);\n\n const fixture: LaneFixture = {\n index: laneIndex,\n kind,\n threadId,\n ref,\n deskInPlay: false,\n submissionIndexes,\n submitOne: (flatIndex) =>\n runtime.submit(\n { definition: { id: coordinatorDefinition.id, input: coordinatorDefinition.input } },\n { mission: `chaos ${flatIndex}` },\n submitOptionsFor(flatIndex),\n ),\n drives: (firstReceipt) => {\n const drives: Array<\n Effect.Effect<ReadonlyArray<Settlement>, DurableWorkerFailure | DurableBindingFailure>\n > = [driveResolved(threadId)];\n\n if (firstReceipt !== undefined) {\n drives.push(\n driveResolved(\n childThreadIdFor(firstReceipt.submissionId, decodeToolCallId(DELEGATE_CALL_ID)),\n ),\n );\n }\n\n return drives;\n },\n childThreadOf: (firstReceipt) =>\n childThreadIdFor(firstReceipt.submissionId, decodeToolCallId(DELEGATE_CALL_ID)),\n };\n\n return fixture;\n }\n }\n});\n\n/** Stable per-call index into an injection list (identical across resolution passes). */\nconst injectionIndex = (submissionFlatIndex: number, callId: string, length: number): number => {\n let hash = submissionFlatIndex + 1;\n\n for (const char of callId) hash = (Math.imul(hash, 31) + char.charCodeAt(0)) | 0;\n\n return ((hash % length) + length) % length;\n};\n\nconst resolutionFor = (\n kind: ChaosResolutionKind,\n toolName: string,\n ref: string,\n produced: ReadonlySet<string>,\n): UnknownResolution => {\n switch (kind) {\n case \"abort-submission\":\n return ResolutionAbortSubmission.make();\n case \"completed-from-supplier\": {\n if (toolName === \"book\" && produced.has(bookConfirmation(ref))) {\n return ResolutionCompletedWithResult.make({\n result: { confirmation: bookConfirmation(ref) },\n isFailure: false,\n });\n }\n if (\n toolName === \"itinerary\" &&\n produced.has(flightValue(ref)) &&\n produced.has(lodgingValue(ref))\n ) {\n return ResolutionCompletedWithResult.make({\n result: { state: `${flightValue(ref)}+${lodgingValue(ref)}` },\n isFailure: false,\n });\n }\n\n // The desk never produced a value for this call — resolving \"completed\" would fabricate.\n return ResolutionNeverHappened.make();\n }\n case \"never-happened\":\n return ResolutionNeverHappened.make();\n }\n};\n\n/** Drive one DUR-017 pass: resolve Unknown Outcomes and pending approvals from the plan. */\nconst resolutionPass = Effect.fn(\"Chaos.resolutionPass\")(function* (\n plan: ChaosPlan,\n states: ReadonlyArray<SubmissionState>,\n desk: ChaosDesk,\n) {\n const runtime = yield* DurableAgentRuntime;\n const ledger = yield* SubmissionLedger;\n const produced = yield* desk.produced;\n const nonterminal = yield* tolerateTyped(Stream.runCollect(ledger.scanNonterminal));\n\n if (Option.isNone(nonterminal)) return;\n const byId = new Map<SubmissionId, SubmissionState>();\n\n for (const state of states) {\n if (state.receipt !== undefined) byId.set(state.receipt.submissionId, state);\n }\n for (const row of nonterminal.value) {\n if (row.state !== \"unknown\" && row.state !== \"suspended\") continue;\n const state = byId.get(row.submissionId);\n const explanation = yield* tolerateTyped(runtime.explain(row.submissionId));\n\n if (Option.isNone(explanation)) continue;\n const flatIndex = state?.flatIndex ?? 0;\n const ref = state?.lane.ref ?? \"ref-child\";\n\n if (row.state === \"unknown\") {\n for (const call of explanation.value.evidence.unknownCalls) {\n if (call.resolved) continue;\n\n const kind =\n plan.resolutionInjections.length === 0\n ? \"never-happened\"\n : (plan.resolutionInjections.at(\n injectionIndex(flatIndex, call.toolCallId, plan.resolutionInjections.length),\n ) ?? \"never-happened\");\n\n yield* tolerateTyped(\n runtime.resolveUnknown(\n UnknownResolutionCommand.make({\n submissionId: row.submissionId,\n toolCallId: call.toolCallId,\n author: \"chaos-runner\",\n reason: `chaos plan ${plan.seed} resolution (${kind})`,\n resolution: resolutionFor(kind, call.toolName, ref, produced),\n }),\n ),\n );\n }\n } else {\n for (const pending of explanation.value.evidence.approvalsPending) {\n const decision =\n plan.approvalDecisions.length === 0\n ? \"approved\"\n : (plan.approvalDecisions.at(\n injectionIndex(flatIndex, pending.toolCallId, plan.approvalDecisions.length),\n ) ?? \"approved\");\n\n yield* tolerateTyped(\n runtime.resolveApproval(\n ApprovalDecisionCommand.make({\n submissionId: row.submissionId,\n toolCallId: pending.toolCallId,\n decision,\n resolver: \"chaos-runner\",\n reason: `chaos plan ${plan.seed} approval (${decision})`,\n }),\n ),\n );\n }\n }\n }\n});\n\nconst submissionIdsNamedBy = (\n records: ReadonlyArray<CanonicalRecordEnvelope>,\n): ReadonlySet<SubmissionId> => {\n const named = new Set<SubmissionId>();\n\n for (const envelope of records) {\n const payload = envelope.record.payload;\n\n if (\n payload._tag === \"UserInputRecorded\" ||\n payload._tag === \"SubmissionSettled\" ||\n payload._tag === \"AbortRequested\"\n ) {\n if (payload.submissionId !== undefined) named.add(payload.submissionId);\n }\n }\n\n return named;\n};\n\n/**\n * The final non-fabrication sweep (durability §10): every canonical Tool success recorded on a\n * desk-backed lane must be a value the desk actually produced.\n */\nconst BookResult = Schema.Struct({ confirmation: Schema.String });\nconst ItineraryResult = Schema.Struct({ state: Schema.String });\nconst decodeBookResult = Schema.decodeUnknownOption(BookResult);\nconst decodeItineraryResult = Schema.decodeUnknownOption(ItineraryResult);\nconst decodeStepOutput = Schema.decodeUnknownOption(Schema.String);\n\nconst assertNoFabrication = (\n plan: ChaosPlan,\n records: ReadonlyArray<CanonicalRecordEnvelope>,\n produced: ReadonlySet<string>,\n): Effect.Effect<void, ChaosConvergenceFailure> => {\n const fabricated: Array<string> = [];\n\n const requireProduced = (value: string, label: string): void => {\n if (!produced.has(value)) fabricated.push(`${label} \"${value}\"`);\n };\n\n for (const envelope of records) {\n const payload = envelope.record.payload;\n\n if (payload._tag === \"ToolCallSettled\" && !payload.isFailure) {\n if (payload.toolName === \"book\") {\n const result = decodeBookResult(payload.result);\n\n if (Option.isSome(result)) requireProduced(result.value.confirmation, \"book result\");\n }\n if (payload.toolName === \"itinerary\") {\n const result = decodeItineraryResult(payload.result);\n\n if (Option.isSome(result)) {\n for (const part of result.value.state.split(\"+\")) {\n requireProduced(part, \"itinerary step result\");\n }\n }\n }\n }\n if (payload._tag === \"ToolStepSettled\") {\n const output = decodeStepOutput(payload.output);\n\n if (Option.isSome(output)) requireProduced(output.value, \"step output\");\n }\n }\n\n return fabricated.length === 0\n ? Effect.void\n : Effect.fail(\n ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `fabricated Tool results absent from the desk: ${fabricated.join(\", \")}`,\n }),\n );\n};\n\n/**\n * Execute one chaos plan against whatever adapters the ambient Layer provides and end in the\n * shared invariant claims. Deterministic: same plan + same adapters → same schedule.\n */\nexport const runChaosPlan = Effect.fn(\"Chaos.runChaosPlan\")(function* (\n plan: ChaosPlan,\n options?: ChaosRunOptions,\n) {\n const runtime = yield* DurableAgentRuntime;\n const ledger = yield* SubmissionLedger;\n const store = yield* ThreadStore;\n const config = yield* DurableRuntimeConfig;\n const failpoints = yield* DurableRuntimeFailpointTestControl;\n const random = mulberry32(plan.seed);\n const desk = yield* makeChaosDesk;\n\n // Lane fixtures: the FIRST spec of each lane fixes the lane's agent kind.\n const laneKinds = new Map<number, ChaosScenarioKind>();\n const laneSubmissions = new Map<number, Array<number>>();\n\n plan.submissions.forEach((spec, flatIndex) => {\n const lane = spec.lane % plan.lanes;\n\n if (!laneKinds.has(lane)) laneKinds.set(lane, spec.kind);\n const list = laneSubmissions.get(lane) ?? [];\n\n list.push(flatIndex);\n laneSubmissions.set(lane, list);\n });\n const lanes: Array<LaneFixture> = [];\n\n for (const [lane, kind] of laneKinds) {\n lanes.push(yield* makeLaneFixture(plan, lane, kind, laneSubmissions.get(lane) ?? [], desk));\n }\n\n const lanesByIndex = new Map(lanes.map((lane) => [lane.index, lane]));\n const states: Array<SubmissionState> = [];\n\n for (const [flatIndex, spec] of plan.submissions.entries()) {\n const laneIndex = spec.lane % plan.lanes;\n const lane = lanesByIndex.get(laneIndex);\n\n if (lane === undefined) {\n return yield* ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `submission ${flatIndex} addresses missing lane ${laneIndex}`,\n });\n }\n states.push({ flatIndex, lane, receipt: undefined });\n }\n const appliedAborts = new Set<number>();\n\n type ArmEntry =\n | { readonly family: \"coordinator\"; readonly location: DurableRuntimeFailpointLocation }\n | { readonly family: \"adapter\"; readonly location: string };\n\n const armQueue: Array<ArmEntry> = [\n ...plan.failpointArms.map((location): ArmEntry => ({ family: \"coordinator\", location })),\n ...plan.adapterArms.map((location): ArmEntry => ({ family: \"adapter\", location })),\n ];\n\n const allSettled = Effect.gen(function* () {\n if (states.some((state) => state.receipt === undefined)) return false;\n const nonterminal = yield* tolerateTyped(Stream.runCollect(ledger.scanNonterminal));\n\n return Option.isSome(nonterminal) && Array.from(nonterminal.value).length === 0;\n });\n\n const maxRounds = armQueue.length + states.length * 2 + 12;\n let rounds = 0;\n let converged = false;\n\n for (let round = 0; round < maxRounds; round++) {\n rounds = round + 1;\n const arm = armQueue[round];\n\n if (arm?.family === \"coordinator\") {\n const location = arm.location;\n\n yield* failpoints.setHandler((hit) =>\n hit === location\n ? Effect.fail(DurableRuntimeFailpointError.make({ location: hit }))\n : Effect.void,\n );\n } else if (arm?.family === \"adapter\" && options?.adapterFailpoints !== undefined) {\n yield* options.adapterFailpoints.arm(arm.location);\n }\n\n // Admission chaos: pending submissions retry under the active arm until a Receipt lands;\n // the identical (thread, principal, key) triple reattaches, never duplicates.\n for (const state of states) {\n if (state.receipt !== undefined) continue;\n const receipt = yield* tolerateTyped(state.lane.submitOne(state.flatIndex));\n\n if (Option.isSome(receipt)) state.receipt = receipt.value;\n }\n\n // Drive every lane (and discovered child lanes) in seeded order under the active arm.\n const order = lanes\n .map((lane) => ({ lane, rank: random() }))\n .sort((left, right) => left.rank - right.rank || left.lane.index - right.lane.index)\n .map(({ lane }) => lane);\n\n for (const lane of order) {\n const firstFlat = lane.submissionIndexes[0];\n const firstReceipt = firstFlat === undefined ? undefined : states[firstFlat]?.receipt;\n\n for (const drive of lane.drives(firstReceipt)) {\n yield* tolerateTyped(drive);\n }\n }\n\n // Abort injections fire once, while arms may still be active (abort:after-intent etc.).\n if (round >= 1) {\n for (const rawIndex of plan.abortInjections) {\n const index = rawIndex % states.length;\n\n if (appliedAborts.has(index)) continue;\n const receipt = states[index]?.receipt;\n\n if (receipt === undefined) continue;\n appliedAborts.add(index);\n yield* tolerateTyped(\n runtime.abort(\n AbortCommand.make({\n submissionId: receipt.submissionId,\n author: \"chaos-runner\",\n reason: `chaos plan ${plan.seed} abort injection`,\n }),\n ),\n );\n }\n }\n\n // First resolution pass runs under the arm so resolve:* locations can fire.\n yield* resolutionPass(plan, states, desk);\n\n yield* failpoints.clear;\n if (options?.adapterFailpoints !== undefined) yield* options.adapterFailpoints.clear;\n\n yield* tolerateTyped(runtime.runRecovery());\n // Second, unarmed pass guarantees forward progress for newly marked Unknown lanes.\n yield* resolutionPass(plan, states, desk);\n\n if (yield* allSettled) {\n converged = true;\n break;\n }\n if (options?.betweenRounds !== undefined) yield* options.betweenRounds;\n }\n\n if (!converged) {\n const nonterminal = yield* tolerateTyped(Stream.runCollect(ledger.scanNonterminal));\n\n const detail = Option.isSome(nonterminal)\n ? Array.from(nonterminal.value)\n .map((row) => `${row.submissionId}(${row.state})`)\n .join(\", \")\n : \"ledger scan failed\";\n\n return yield* ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `plan did not converge within ${maxRounds} rounds; nonterminal: [${detail}]; pending receipts: ${states.filter((state) => state.receipt === undefined).length}`,\n });\n }\n\n // Final claims: the shared invariant checker per touched Thread, in convergence mode,\n // with the full digest chain (single known producer), plus the desk non-fabrication sweep.\n const produced = yield* desk.produced;\n const laneReports: Array<ChaosLaneReport> = [];\n\n const verifyThread = Effect.fn(\"Chaos.verifyThread\")(function* (\n threadId: ThreadId,\n kind: ChaosScenarioKind,\n deskInPlay: boolean,\n ) {\n const exported = yield* store.export(ThreadExportRequest.make({ threadId })).pipe(\n Effect.mapError((error) =>\n ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `export of ${threadId} failed: ${String(error)}`,\n }),\n ),\n );\n\n const rows: Array<SubmissionSnapshot> = [];\n\n for (const submissionId of submissionIdsNamedBy(exported.records)) {\n const found = yield* ledger.lookup(SubmissionLookupById.make({ submissionId })).pipe(\n Effect.mapError((error) =>\n ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `lookup of ${submissionId} failed: ${String(error)}`,\n }),\n ),\n );\n\n if (Option.isSome(found)) rows.push(found.value);\n }\n\n const batchProducers = new Map<BatchId, ProducerId>(\n exported.records.map((envelope) => [envelope.batchId, config.producerId]),\n );\n\n const report = yield* verifyThreadInvariants({\n export: exported,\n submissions: rows,\n batchProducers,\n requireAllSettled: true,\n });\n\n if (!report.ok) {\n const failed = report.checks\n .filter((check) => check.status === \"failed\")\n .map((check) => `${check.name}: ${check.detail ?? \"failed\"}`)\n .join(\"; \");\n\n return yield* ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `invariants failed for ${threadId} (${kind}): ${failed}`,\n });\n }\n if (deskInPlay) {\n yield* assertNoFabrication(plan, exported.records, produced);\n }\n laneReports.push(\n ChaosLaneReport.make({\n threadId,\n kind,\n submissionCount: rows.length,\n verified: report.ok,\n }),\n );\n });\n\n for (const lane of lanes) {\n yield* verifyThread(lane.threadId, lane.kind, lane.deskInPlay);\n // Delegation lanes: verify every materialized child Thread too.\n for (const flatIndex of lane.submissionIndexes) {\n const receipt = states[flatIndex]?.receipt;\n\n if (receipt === undefined) continue;\n const child = lane.childThreadOf(receipt);\n\n if (child === undefined) continue;\n\n const childExport = yield* Effect.exit(\n store.export(ThreadExportRequest.make({ threadId: child })),\n );\n\n if (Exit.isSuccess(childExport) && childExport.value.records.length > 0) {\n yield* verifyThread(child, \"plain\", false);\n }\n }\n }\n\n const obligations = yield* runtime\n .scanObligations(ObligationThresholds.make({ agingSeconds: 0, overdueSeconds: 0 }))\n .pipe(\n Effect.mapError((error) =>\n ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `scanObligations failed: ${String(error)}`,\n }),\n ),\n );\n\n if (obligations.entries.length > 0) {\n return yield* ChaosConvergenceFailure.make({\n seed: plan.seed,\n message: `open obligations after convergence: ${obligations.entries\n .map((entry) => `${entry.submissionId}(${entry.blockedOn})`)\n .join(\", \")}`,\n });\n }\n\n return ChaosPlanReport.make({\n seed: plan.seed,\n rounds,\n lanes: laneReports,\n openObligations: obligations.entries.length,\n });\n});\n"],"mappings":"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"}
|
package/dist/DocsResearcher.mjs
CHANGED
|
@@ -241,14 +241,14 @@ const docsMcpIdentity = McpServerIdentity.make({
|
|
|
241
241
|
*/
|
|
242
242
|
const JsonSchemaDefinitions = Schema.Record(Schema.String, Schema.Record(Schema.String, Schema.Unknown));
|
|
243
243
|
const decodeJsonSchemaDefinitions = Schema.decodeUnknownSync(JsonSchemaDefinitions);
|
|
244
|
-
const
|
|
244
|
+
const decodeToolJson = Schema.decodeUnknownSync(McpSchema.ToolJson);
|
|
245
245
|
const flattenTopLevelRef = (schema) => {
|
|
246
246
|
const ref = schema["$ref"];
|
|
247
|
-
if (typeof ref !== "string") return
|
|
247
|
+
if (typeof ref !== "string") return decodeToolJson(schema);
|
|
248
248
|
const defs = decodeJsonSchemaDefinitions(schema["$defs"]);
|
|
249
249
|
const key = ref.startsWith("#/$defs/") ? JsonPointer.unescapeToken(ref.slice(8)) : void 0;
|
|
250
250
|
const resolved = key !== void 0 && Object.hasOwn(defs, key) ? defs[key] : void 0;
|
|
251
|
-
return
|
|
251
|
+
return decodeToolJson(resolved ?? schema);
|
|
252
252
|
};
|
|
253
253
|
const fetchDocumentOutputSchema = flattenTopLevelRef(Tool.getJsonSchemaFromSchema(FetchDocument.successSchema));
|
|
254
254
|
const discoveredFetchDocument = McpSchema.Tool.make({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocsResearcher.mjs","names":[],"sources":["../src/fixtures/docs-researcher/definition.ts","../src/fixtures/docs-researcher/mcp.ts","../src/fixtures/docs-researcher/harness.ts"],"sourcesContent":["import { Context, Effect, Schema } from \"effect\";\nimport * as Agent from \"effect-agent/agent\";\nimport { AgentPolicy } from \"effect-agent/agent-policy\";\nimport { type RuntimeBinding } from \"effect-agent/agent-runtime\";\nimport * as Subagent from \"effect-agent/subagent\";\nimport { SubagentPolicy } from \"effect-agent/subagent\";\nimport { Tool, Toolkit } from \"effect/unstable/ai\";\n\n// ---------------------------------------------------------------------------\n// Docs Researcher (P7 internal agent #3, plan §6): a coordinator that\n// delegates per-document summarization to a doc-summarizer child through the\n// S2 durable delegation surface, with the child's content tools served —\n// and validated — through the MCP connector against a scripted MCP fixture.\n// The corpus, tools, and both Agent Definitions are deterministic fixtures in\n// the travel-planner style so DN tests (and any later DC assembly) reuse them.\n// ---------------------------------------------------------------------------\n\nexport const ResearchDocumentId = Schema.NonEmptyString.check(Schema.isMaxLength(64)).pipe(\n Schema.brand(\"@effect-agent/testing/docs-researcher/ResearchDocumentId\"),\n);\n\nexport type ResearchDocumentId = typeof ResearchDocumentId.Type;\n\nconst BoundedTitle = Schema.NonEmptyString.check(Schema.isMaxLength(120));\nconst BoundedBody = Schema.NonEmptyString.check(Schema.isMaxLength(16 * 1024));\n\n/** Bounded summary text: the ONLY child-derived text that may cross to the parent. */\nexport const BoundedSummary = Schema.NonEmptyString.check(Schema.isMaxLength(240));\n\nexport class DocumentQuery extends Schema.Class<DocumentQuery>(\"DocumentQuery\")({\n documentId: ResearchDocumentId,\n}) {}\n\n/** One bounded research document as the MCP content server exposes it. */\nexport class ResearchDocument extends Schema.Class<ResearchDocument>(\"ResearchDocument\")({\n documentId: ResearchDocumentId,\n title: BoundedTitle,\n body: BoundedBody,\n}) {}\n\nexport class DocumentUnavailable extends Schema.TaggedError<DocumentUnavailable>()(\n \"DocumentUnavailable\",\n {\n documentId: ResearchDocumentId,\n message: Schema.String,\n },\n) {}\n\n/** The content store behind the scripted MCP server. */\nexport class DocumentLibrary extends Context.Service<\n DocumentLibrary,\n {\n readonly fetch: (query: DocumentQuery) => Effect.Effect<ResearchDocument, DocumentUnavailable>;\n }\n>()(\"@effect-agent/testing/docs-researcher/DocumentLibrary\") {}\n\n/**\n * The one content tool the doc-summarizer child uses. Its authored JSON\n * schema is what MCP discovery must serve byte-for-byte: the scripted MCP\n * fixture derives its discovery entry from `Tool.getJsonSchema(FetchDocument)`\n * and `validateMcpDiscovery` re-derives and digests both sides (CAP-009).\n */\nexport const FetchDocument = Tool.make(\"fetch_document\", {\n description: \"Fetch one bounded research document by its identifier.\",\n parameters: DocumentQuery,\n success: ResearchDocument,\n failure: DocumentUnavailable,\n failureMode: \"error\",\n dependencies: [DocumentLibrary],\n});\n\nexport const DocContentToolkit = Toolkit.make(FetchDocument);\n\nexport const docContentToolkitLayer = DocContentToolkit.toLayer({\n fetch_document: (query) => Effect.flatMap(DocumentLibrary, (library) => library.fetch(query)),\n});\n\n// ---------------------------------------------------------------------------\n// Deterministic corpus. Every body deliberately embeds BOTH a secret marker\n// and a distinctive body phrase: the tests assert that neither ever reaches\n// the parent Thread, the parent prompts, or a redacted preview — only\n// the bounded summary crosses the delegation boundary (SUB-015, SEC-008).\n// ---------------------------------------------------------------------------\n\n/** Never allowed outside a child Thread or an unredacted fixture value. */\nexport const docsDocumentBodySecret = \"docs-vault-secret-771\";\n\nconst decodeDocumentId = Schema.decodeSync(ResearchDocumentId);\n\ninterface CorpusEntry {\n readonly document: ResearchDocument;\n readonly bodyPhrase: string;\n readonly summary: string;\n}\n\nconst corpusEntries = new Map<string, CorpusEntry>(\n [\n {\n documentId: \"durability-notes\",\n title: \"Durability protocol notes\",\n bodyPhrase: \"amber-ledger-passage\",\n summary:\n \"Settlement results are recorded exactly once while external side effects stay at-least-once.\",\n },\n {\n documentId: \"subagent-notes\",\n title: \"Subagent join notes\",\n bodyPhrase: \"cobalt-join-corridor\",\n summary: \"A parent joins only the verified settlement of its own established child.\",\n },\n ].map((entry) => [\n entry.documentId,\n {\n document: ResearchDocument.make({\n documentId: decodeDocumentId(entry.documentId),\n title: entry.title,\n body: `${entry.bodyPhrase}: internal working notes. ${docsDocumentBodySecret}. ${entry.summary} Raw notes stay inside the child Thread.`,\n }),\n bodyPhrase: entry.bodyPhrase,\n summary: entry.summary,\n },\n ]),\n);\n\n/** The corpus document ids in canonical fixture order. */\nexport const researchCorpusDocumentIds: ReadonlyArray<ResearchDocumentId> = [\n decodeDocumentId(\"durability-notes\"),\n decodeDocumentId(\"subagent-notes\"),\n];\n\nconst requireCorpusEntry = (documentId: string): CorpusEntry => {\n const entry = corpusEntries.get(documentId);\n\n if (entry === undefined) {\n throw new Error(`No deterministic corpus entry exists for document ${documentId}`);\n }\n\n return entry;\n};\n\n/** Deterministic library lookup shared by the scripted MCP content handlers. */\nexport const researchDocumentLookup = (\n query: DocumentQuery,\n): Effect.Effect<ResearchDocument, DocumentUnavailable> => {\n const entry = corpusEntries.get(query.documentId);\n\n return entry === undefined\n ? Effect.fail(\n DocumentUnavailable.make({\n documentId: query.documentId,\n message: \"No deterministic corpus entry exists for this document.\",\n }),\n )\n : Effect.succeed(entry.document);\n};\n\n/** The full fixture document (body includes the secret marker — child-side only). */\nexport const researchDocumentFor = (documentId: string): ResearchDocument =>\n requireCorpusEntry(documentId).document;\n\n/** The distinctive body phrase used by context-isolation assertions. */\nexport const documentBodyPhrase = (documentId: string): string =>\n requireCorpusEntry(documentId).bodyPhrase;\n\n// ---------------------------------------------------------------------------\n// Doc Summarizer: the child Agent Definition. Its toolkit is the authored\n// `DocContentToolkit`; the harness registers its worker Binding only after\n// MCP discovery validates that exact toolkit (mcp.ts).\n// ---------------------------------------------------------------------------\n\nexport class SummaryBrief extends Schema.Class<SummaryBrief>(\"SummaryBrief\")({\n documentId: ResearchDocumentId,\n focus: Schema.NonEmptyString,\n}) {}\n\nexport class DocumentSummary extends Schema.Class<DocumentSummary>(\"DocumentSummary\")({\n documentId: ResearchDocumentId,\n summary: BoundedSummary,\n}) {}\n\n/** The summary the scripted child writes after fetching the document. */\nexport const documentSummaryFor = (documentId: string): DocumentSummary =>\n DocumentSummary.make({\n documentId: requireCorpusEntry(documentId).document.documentId,\n summary: requireCorpusEntry(documentId).summary,\n });\n\nexport const encodedDocumentSummary = (documentId: string): string =>\n JSON.stringify(Schema.encodeSync(DocumentSummary)(documentSummaryFor(documentId)));\n\nexport const DocSummarizer = Agent.make(\"doc-summarizer\", {\n input: SummaryBrief,\n output: DocumentSummary,\n instructions:\n \"Fetch the briefed document with fetch_document exactly once, then return only a JSON document summary. Never copy raw notes or secrets into the summary.\",\n toolkit: DocContentToolkit,\n policy: AgentPolicy.make({\n maxTurns: 2,\n maxToolCalls: 1,\n maxDuration: \"30 seconds\",\n toolConcurrency: 1,\n }),\n description: \"Summarize one bounded research document fetched through MCP content tools.\",\n metadata: { deploymentClass: \"DN\", phase: \"P7\" },\n});\n\n// ---------------------------------------------------------------------------\n// Delegation Definition: the coordinator sees exactly one Tool with explicit\n// projections and finite bounds. `projectResult` is the declassification\n// boundary (SUB-015): only the bounded summary crosses; the fetched body —\n// secret marker included — stays in the child Thread.\n// ---------------------------------------------------------------------------\n\nexport class SummaryRequest extends Schema.Class<SummaryRequest>(\"SummaryRequest\")({\n documentId: ResearchDocumentId,\n}) {}\n\nexport class SummaryFinding extends Schema.Class<SummaryFinding>(\"SummaryFinding\")({\n documentId: ResearchDocumentId,\n summary: BoundedSummary,\n}) {}\n\nexport class DocumentSummaryFailed extends Schema.TaggedError<DocumentSummaryFailed>()(\n \"DocumentSummaryFailed\",\n {\n childErrorTag: Schema.NonEmptyString,\n },\n) {}\n\n/** Finite per-invocation bounds (SUB-009): one fetch per child, two children per Run. */\nexport const documentSummaryPolicy = SubagentPolicy.make({\n maxChildren: 2,\n maxConcurrency: 2,\n maxTurns: 2,\n maxToolCalls: 1,\n maxDuration: \"10 seconds\",\n});\n\nexport const delegateDocumentSummary = Subagent.define(\"delegate_document_summary\", {\n description:\n \"Summarize one research document through the doc-summarizer child and return a bounded finding.\",\n target: DocSummarizer,\n parameters: SummaryRequest,\n success: SummaryFinding,\n failure: DocumentSummaryFailed,\n prepareInput: (request) =>\n Effect.succeed(\n SummaryBrief.make({\n documentId: request.documentId,\n focus: \"summarize:durability-claims\",\n }),\n ),\n projectResult: (summary) =>\n Effect.succeed(\n SummaryFinding.make({\n documentId: summary.documentId,\n summary: summary.summary,\n }),\n ),\n policy: documentSummaryPolicy,\n});\n\n/** Total mapping from every expected child Run failure to the declared Tool failure (SUB-028). */\nexport const mapSummaryChildFailure = (failure: { readonly _tag: string }): DocumentSummaryFailed =>\n DocumentSummaryFailed.make({ childErrorTag: failure._tag });\n\n/** The exact digest strings the durable declaration AND host registration must share (SUB-023). */\nexport const docsSummarizerDigestStrings = {\n agent: \"50\".repeat(32),\n model: \"51\".repeat(32),\n tools: \"52\".repeat(32),\n} as const;\n\n/** Runtime wiring: the immutable delegation plus one explicit child Binding (S2 declaration). */\nexport const docsSummaryHandlersLayer = <Provider, ModelProvides, ModelRequires>(\n childBinding: RuntimeBinding<\n typeof SummaryBrief,\n typeof DocumentSummary,\n string,\n Toolkit.Tools<typeof DocContentToolkit>,\n Provider,\n ModelProvides,\n ModelRequires\n >,\n) =>\n Subagent.layer(delegateDocumentSummary, childBinding, {\n mapChildFailure: mapSummaryChildFailure,\n durable: { targetDigests: docsSummarizerDigestStrings },\n });\n\n// ---------------------------------------------------------------------------\n// Docs Researcher: the parent Agent Definition.\n// ---------------------------------------------------------------------------\n\nexport class ResearchRequest extends Schema.Class<ResearchRequest>(\"ResearchRequest\")({\n question: Schema.NonEmptyString,\n documentIds: Schema.Array(ResearchDocumentId).check(Schema.isMinLength(1)),\n}) {}\n\nexport class ResearchDigest extends Schema.Class<ResearchDigest>(\"ResearchDigest\")({\n findings: Schema.Array(SummaryFinding),\n nextAction: Schema.Literal(\"review\"),\n}) {}\n\n/** Parent-only transcript markers proving child context isolation (SUB-006/SUB-015). */\nexport const docsCoordinatorConfidentialMarker = \"docs-coordinator-vault-19x\";\nexport const docsMissionConfidentialMarker = \"docs-mission-dossier-42f\";\n\nexport const DocsResearcherToolkit = Toolkit.make(delegateDocumentSummary.tool);\n\nexport const DocsResearcher = Agent.make(\"docs-researcher\", {\n input: ResearchRequest,\n output: ResearchDigest,\n instructions: [\n \"You are the Effect Agent P7 docs-researcher coordinator.\",\n `Coordinator-only context: ${docsCoordinatorConfidentialMarker}.`,\n \"Call delegate_document_summary once per requested document in one Tool batch.\",\n \"Return only a JSON digest built from the delegated findings. This is read-only research.\",\n ].join(\"\\n\"),\n toolkit: DocsResearcherToolkit,\n policy: AgentPolicy.make({\n maxTurns: 2,\n maxToolCalls: 2,\n maxDuration: \"30 seconds\",\n toolConcurrency: 2,\n }),\n description: \"Coordinate per-document summarization through one declared delegation Tool.\",\n metadata: { deploymentClass: \"DN\", phase: \"P7\" },\n});\n\n/** The default two-document research mission. */\nexport const researchMissionRequest = ResearchRequest.make({\n question: `Summarize the durability and subagent notes; keep ${docsMissionConfidentialMarker} inside the coordinator thread.`,\n documentIds: researchCorpusDocumentIds,\n});\n\n/** The coordinator's expected final digest for the given documents. */\nexport const expectedResearchDigest = (\n documentIds: ReadonlyArray<string> = researchCorpusDocumentIds,\n): ResearchDigest =>\n ResearchDigest.make({\n findings: documentIds.map((documentId) => {\n const summary = documentSummaryFor(documentId);\n\n return SummaryFinding.make({\n documentId: summary.documentId,\n summary: summary.summary,\n });\n }),\n nextAction: \"review\",\n });\n","import type { JsonSchema } from \"effect\";\nimport { Effect, JsonPointer, Layer, Schema } from \"effect\";\nimport {\n McpConnectionRequest,\n McpConnector,\n McpServerIdentity,\n McpToolkitMismatch,\n type McpConnection,\n} from \"effect-agent/mcp\";\nimport { Tool } from \"effect/unstable/ai\";\nimport * as McpSchema from \"effect/unstable/ai/McpSchema\";\n\nimport { DocContentToolkit, FetchDocument } from \"./definition.ts\";\n\n// ---------------------------------------------------------------------------\n// Scripted MCP fixture: a deterministic `McpConnector` adapter that serves the\n// doc-summarizer's content tool. Discovery entries are DERIVED from the\n// authored Tool (`Tool.getJsonSchema`), so `validateMcpDiscovery` digesting\n// both sides is a real check, not a tautology; the mismatch and over-limit\n// connectors below serve deliberately wrong contracts so tests can pin the\n// fail-closed paths (CAP-009, SEC-013).\n// ---------------------------------------------------------------------------\n\n/** Framework-side hard bounds one docs-researcher assembly requests. */\nexport const docsMcpRequest = McpConnectionRequest.make({\n serverId: \"docs-content-mcp\",\n maxToolCount: 4,\n maxToolDescriptionBytes: 256,\n maxDiscoveryBytes: 16_384,\n connectTimeoutMillis: 1_000,\n});\n\nexport const docsMcpIdentity = McpServerIdentity.make({\n serverId: docsMcpRequest.serverId,\n implementation: McpSchema.Implementation.make({\n name: \"docs-researcher-content-fixture\",\n version: \"1.0.0\",\n }),\n});\n\n/**\n * `Tool.getJsonSchema` produces a `$ref`/`$defs`-shaped schema for\n * `FetchDocument`'s named, refined parameters type, but `McpSchema.Tool`'s\n * `inputSchema` requires a flat `{ type: \"object\", ... }` root — the shape a\n * real MCP server advertises on the wire. This inlines the single top-level\n * `$ref` so the derivation described above still holds byte-for-byte.\n */\nconst JsonSchemaDefinitions = Schema.Record(\n Schema.String,\n Schema.Record(Schema.String, Schema.Unknown),\n);\n\nconst decodeJsonSchemaDefinitions = Schema.decodeUnknownSync(JsonSchemaDefinitions);\nconst decodeToolJsonSchema = Schema.decodeUnknownSync(McpSchema.ToolJsonSchema);\n\nconst flattenTopLevelRef = (schema: JsonSchema.JsonSchema): McpSchema.ToolJsonSchema => {\n const ref = schema[\"$ref\"];\n\n if (typeof ref !== \"string\") {\n return decodeToolJsonSchema(schema);\n }\n\n const defs = decodeJsonSchemaDefinitions(schema[\"$defs\"]);\n\n const key = ref.startsWith(\"#/$defs/\")\n ? JsonPointer.unescapeToken(ref.slice(\"#/$defs/\".length))\n : undefined;\n\n const resolved = key !== undefined && Object.hasOwn(defs, key) ? defs[key] : undefined;\n\n return decodeToolJsonSchema(resolved ?? schema);\n};\n\nconst fetchDocumentOutputSchema = flattenTopLevelRef(\n Tool.getJsonSchemaFromSchema(FetchDocument.successSchema),\n);\n\nconst discoveredFetchDocument = McpSchema.Tool.make({\n name: FetchDocument.name,\n description: \"Fetch one bounded research document by its identifier.\",\n inputSchema: flattenTopLevelRef(Tool.getJsonSchema(FetchDocument)),\n // `validateMcpDiscovery` only compares an `outputSchema` derived down to an\n // object type; mirror that so this fixture stays a real round-trip check.\n ...(fetchDocumentOutputSchema.type === \"object\"\n ? { outputSchema: fetchDocumentOutputSchema }\n : {}),\n});\n\nconst scriptedConnector = (tools: ReadonlyArray<McpSchema.Tool>): Layer.Layer<McpConnector> =>\n Layer.succeed(McpConnector)({\n connect: () =>\n Effect.acquireRelease(\n Effect.succeed({\n identity: docsMcpIdentity,\n capabilities: McpSchema.ServerCapabilities.make({}),\n tools,\n toolkit: DocContentToolkit,\n }),\n () => Effect.void,\n ),\n });\n\n/** The well-behaved scripted content server. */\nexport const docsMcpConnectorLayer: Layer.Layer<McpConnector> = scriptedConnector([\n discoveredFetchDocument,\n]);\n\n/** Serves a tool description exceeding `maxToolDescriptionBytes` (SEC-013 bound). */\nexport const docsMcpOversizedConnectorLayer: Layer.Layer<McpConnector> = scriptedConnector([\n McpSchema.Tool.make({\n name: discoveredFetchDocument.name,\n description: \"x\".repeat(1_024),\n inputSchema: discoveredFetchDocument.inputSchema,\n }),\n]);\n\n/** Serves a discovery schema that disagrees with the authored toolkit (drift fails closed). */\nexport const docsMcpMismatchedConnectorLayer: Layer.Layer<McpConnector> = scriptedConnector([\n McpSchema.Tool.make({\n name: discoveredFetchDocument.name,\n description: discoveredFetchDocument.description,\n inputSchema: { type: \"object\", properties: { url: { type: \"string\" } } },\n }),\n]);\n\nconst isJsonEqual = (left: unknown, right: unknown): boolean =>\n JSON.stringify(left) === JSON.stringify(right);\n\n/**\n * Bind DISCOVERY to AUTHORING: `validateMcpDiscovery` (inside `connectMcp`)\n * already proved the served discovery matches the connection's own Toolkit;\n * this check additionally proves that Toolkit is the exact toolkit the\n * doc-summarizer was AUTHORED against — same tool names, same derived JSON\n * schemas — so a connector cannot substitute a look-alike toolkit. The\n * docs-researcher harness runs it before any worker Binding registration and\n * fails closed on any drift.\n */\nexport const assertDiscoveryMatchesAuthoredToolkit = Effect.fn(\n \"DocsResearcher.assertDiscoveryMatchesAuthoredToolkit\",\n)(function* (connection: McpConnection): Effect.fn.Return<void, McpToolkitMismatch> {\n const authored = Object.values(DocContentToolkit.tools)\n .map((tool) => ({ name: tool.name, inputSchema: Tool.getJsonSchema(tool) }))\n .sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));\n\n const discovered = Object.values(connection.toolkit.tools)\n .map((tool) => ({ name: tool.name, inputSchema: Tool.getJsonSchema(tool) }))\n .sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));\n\n const matches =\n authored.length === discovered.length &&\n authored.every(\n (tool, index) =>\n tool.name === discovered[index]?.name &&\n isJsonEqual(tool.inputSchema, discovered[index]?.inputSchema),\n );\n\n if (!matches) {\n return yield* McpToolkitMismatch.make({\n serverId: connection.discovery.identity.serverId,\n message:\n \"The MCP-discovered toolkit does not match the doc-summarizer's authored content toolkit\",\n });\n }\n});\n\n/** Round-trip guard for encoded discovery values persisted as fixture evidence. */\nexport const DocsMcpDiscoveryEvidence = Schema.Struct({\n serverId: Schema.NonEmptyString,\n toolCount: Schema.Natural,\n encodedBytes: Schema.Natural,\n toolkitSchemaDigest: Schema.String,\n});\n","import type { Crypto } from \"effect\";\nimport { Effect, Layer, Ref, Schema, Stream } from \"effect\";\nimport * as Agent from \"effect-agent/agent\";\nimport { DurableWorkerBinding, type ResolvedBinding } from \"effect-agent/agent-registration\";\nimport { type DurableSubmitOptions } from \"effect-agent/durable-agent-runtime\";\nimport { type ThreadId } from \"effect-agent/identifiers\";\nimport { connectMcp, type McpDiscovery } from \"effect-agent/mcp\";\nimport { DefinitionDigests, DeploymentId, Digest, ProducerId } from \"effect-agent/records\";\nimport { Redactor, type RedactedPreview, type RedactionError } from \"effect-agent/redaction\";\nimport { SubagentReservationsMemoryLive } from \"effect-agent/subagent-reservations\";\nimport { Principal, type IdempotencyKey } from \"effect-agent/submission-ledger\";\nimport { LanguageModel, Model, type Response } from \"effect/unstable/ai\";\n\nimport { DeterministicIdGeneratorLayer } from \"../travel-planner/deterministic-layers.ts\";\nimport {\n DocsResearcher,\n DocSummarizer,\n DocumentLibrary,\n docContentToolkitLayer,\n docsSummaryHandlersLayer,\n encodedDocumentSummary,\n expectedResearchDigest,\n ResearchDigest,\n ResearchDocument,\n researchCorpusDocumentIds,\n researchDocumentFor,\n researchDocumentLookup,\n} from \"./definition.ts\";\nimport {\n assertDiscoveryMatchesAuthoredToolkit,\n docsMcpConnectorLayer,\n docsMcpRequest,\n} from \"./mcp.ts\";\n\n// ---------------------------------------------------------------------------\n// DN durable harness for the docs-researcher (P7 plan §6 agent #3), following\n// `makeDurableResearchHarness` conventions: invocation counters and captured\n// prompts live OUTSIDE the Model Layers so they survive Layer rebuilds across\n// Attempts and separate runtime handles over the same SQLite file.\n// ---------------------------------------------------------------------------\n\nexport const docsResearcherDeploymentId = Schema.decodeSync(DeploymentId)(\n \"docs-researcher-p7-deployment\",\n);\n\nexport const docsResearcherProducerId = Schema.decodeSync(ProducerId)(\n \"docs-researcher-p7-producer\",\n);\n\nexport const docsResearcherPrincipal = Schema.decodeSync(Principal)(\"docs-researcher-p7-principal\");\n\nconst digestOf = (pair: string) => Schema.decodeSync(Digest)(pair.repeat(32));\n\n/** Redacted, deterministic coordinator definition digests for this fixture version. */\nexport const docsCoordinatorDigests = DefinitionDigests.make({\n agent: digestOf(\"40\"),\n model: digestOf(\"41\"),\n tools: digestOf(\"42\"),\n});\n\n/** The child registration digests — byte-equal to `docsSummarizerDigestStrings` (SUB-023). */\nexport const docsSummarizerDigests = DefinitionDigests.make({\n agent: digestOf(\"50\"),\n model: digestOf(\"51\"),\n tools: digestOf(\"52\"),\n});\n\n/** Durable admission options for one docs-researcher Submission on one mission lane. */\nexport const docsResearcherSubmitOptions = (\n threadId: ThreadId,\n idempotencyKey: IdempotencyKey,\n): DurableSubmitOptions => ({\n threadId,\n principal: docsResearcherPrincipal,\n idempotencyKey,\n definitions: docsCoordinatorDigests,\n});\n\n/** The structural submit slice of the coordinator Binding (`DurableAgentRuntime.submit`). */\nexport const docsResearcherSubmitAgent = {\n definition: { id: DocsResearcher.id, input: DocsResearcher.input },\n} as const;\n\n/** The deterministic delegation Tool Call identity for one document. */\nexport const summarizeCallId = (documentId: string): string => `summarize-${documentId}`;\n\n/** The child's own scripted fetch Tool Call identity for one document. */\nexport const fetchCallId = (documentId: string): string => `fetch-${documentId}`;\n\nconst scriptedUsage = { inputTokens: { total: 96 }, outputTokens: { total: 64 } };\n\nconst summaryDelegationParts = (\n documentIds: ReadonlyArray<string>,\n): ReadonlyArray<Response.StreamPartEncoded> => [\n ...documentIds.map((documentId): Response.StreamPartEncoded => ({\n type: \"tool-call\",\n id: summarizeCallId(documentId),\n name: \"delegate_document_summary\",\n params: { documentId },\n providerExecuted: false,\n })),\n { type: \"finish\", reason: \"tool-calls\", usage: scriptedUsage },\n];\n\nconst digestParts = (\n documentIds: ReadonlyArray<string>,\n): ReadonlyArray<Response.StreamPartEncoded> => [\n { type: \"text-start\", id: \"digest\" },\n {\n type: \"text-delta\",\n id: \"digest\",\n delta: JSON.stringify(Schema.encodeSync(ResearchDigest)(expectedResearchDigest(documentIds))),\n },\n { type: \"text-end\", id: \"digest\" },\n { type: \"finish\", reason: \"stop\", usage: scriptedUsage },\n];\n\nconst fetchParts = (documentId: string): ReadonlyArray<Response.StreamPartEncoded> => [\n {\n type: \"tool-call\",\n id: fetchCallId(documentId),\n name: \"fetch_document\",\n params: { documentId },\n providerExecuted: false,\n },\n { type: \"finish\", reason: \"tool-calls\", usage: scriptedUsage },\n];\n\nconst summaryParts = (documentId: string): ReadonlyArray<Response.StreamPartEncoded> => [\n { type: \"text-start\", id: \"document-summary\" },\n { type: \"text-delta\", id: \"document-summary\", delta: encodedDocumentSummary(documentId) },\n { type: \"text-end\", id: \"document-summary\" },\n { type: \"finish\", reason: \"stop\", usage: scriptedUsage },\n];\n\n/**\n * One prompt-aware scripted model with externally observable counters. A DN\n * Attempt may resume on a fresh Layer build, so responses derive from the\n * committed history in the prompt — never from an in-Layer turn counter.\n */\nconst makeCountingModel = (\n name: string,\n decide: (promptJson: string) => Effect.Effect<ReadonlyArray<Response.StreamPartEncoded>>,\n) =>\n Effect.gen(function* () {\n const calls = yield* Ref.make(0);\n const prompts = yield* Ref.make<ReadonlyArray<string>>([]);\n\n const model = Model.make(\n \"scripted\",\n name,\n Layer.effect(\n LanguageModel.LanguageModel,\n LanguageModel.make({\n generateText: () => Effect.succeed([]),\n streamText: (request) =>\n Stream.unwrap(\n Effect.gen(function* () {\n yield* Ref.update(calls, (value) => value + 1);\n const promptJson = JSON.stringify(request.prompt);\n\n yield* Ref.update(prompts, (previous) => [...previous, promptJson]);\n\n return Stream.fromIterable(yield* decide(promptJson));\n }),\n ),\n }),\n ),\n );\n\n return { model, calls: Ref.get(calls), prompts: Ref.get(prompts) };\n });\n\n/** Optional overrides for one docs-researcher harness. */\nexport interface DocsResearcherHarnessOptions {\n /** Documents to research; defaults to the full two-document corpus. */\n readonly documentIds?: ReadonlyArray<string> | undefined;\n}\n\n/** One durable coordinator/summarizer pair with observable counters and MCP evidence. */\nexport interface DocsResearcherHarness {\n /** Resolved registrations for the parent and child workers. */\n readonly bindings: ReadonlyArray<ResolvedBinding>;\n /** The validated MCP discovery the child toolkit registration was gated on. */\n readonly discovery: McpDiscovery;\n /** Total coordinator model invocations across every Attempt and runtime handle. */\n readonly parentModelCalls: Effect.Effect<number>;\n /** JSON-encoded coordinator prompts in request order. */\n readonly parentPrompts: Effect.Effect<ReadonlyArray<string>>;\n /** Total summarizer model invocations across every Attempt and runtime handle. */\n readonly childModelCalls: Effect.Effect<number>;\n /** JSON-encoded summarizer prompts in request order (context-isolation evidence). */\n readonly childPrompts: Effect.Effect<ReadonlyArray<string>>;\n /** MCP content-tool handler executions for one document (external side-effect record). */\n readonly fetchInvocations: (documentId: string) => Effect.Effect<number>;\n}\n\n/**\n * Build the docs-researcher harness. Order matters and is the point: the\n * child's content toolkit is only registered as a worker Binding AFTER the\n * MCP connector's bounded discovery validated the authored toolkit\n * byte-for-byte (`connectMcp` + `assertDiscoveryMatchesAuthoredToolkit`), so\n * \"the tools the summarizer runs are the tools discovery served\" is enforced\n * at assembly, not assumed. Content-tool execution then flows through the\n * counting `DocumentLibrary` — the scripted MCP server's content store.\n */\nexport const makeDocsResearcherHarness = (options?: DocsResearcherHarnessOptions) =>\n Effect.gen(function* () {\n const documentIds = options?.documentIds ?? researchCorpusDocumentIds;\n\n // MCP discovery gate (CAP-009): bounded, digest-verified, fail-closed.\n const discovery = yield* Effect.scoped(\n Effect.gen(function* () {\n const connection = yield* connectMcp(docsMcpRequest);\n\n yield* assertDiscoveryMatchesAuthoredToolkit(connection);\n\n return connection.discovery;\n }),\n ).pipe(Effect.provide(docsMcpConnectorLayer));\n\n const fetchCounts = yield* Ref.make<ReadonlyMap<string, number>>(new Map());\n\n const libraryLayer = Layer.succeed(\n DocumentLibrary,\n DocumentLibrary.of({\n fetch: (query) =>\n Ref.update(fetchCounts, (current) =>\n new Map(current).set(query.documentId, (current.get(query.documentId) ?? 0) + 1),\n ).pipe(Effect.andThen(researchDocumentLookup(query))),\n }),\n );\n\n const childToolkitLayer = docContentToolkitLayer.pipe(Layer.provideMerge(libraryLayer));\n\n const childModel = yield* makeCountingModel(\"doc-summarizer-p7\", (promptJson) =>\n Effect.suspend(() => {\n const documentId = documentIds.find((candidate) => promptJson.includes(candidate));\n\n if (documentId === undefined) {\n return Effect.die(new Error(\"The summarizer prompt names no corpus document\"));\n }\n\n return Effect.succeed(\n promptJson.includes(fetchCallId(documentId))\n ? summaryParts(documentId)\n : fetchParts(documentId),\n );\n }),\n );\n\n const childBinding = Agent.withModel(DocSummarizer, childModel.model);\n\n const firstCallId = summarizeCallId(documentIds[0] ?? \"durability-notes\");\n\n const parentModel = yield* makeCountingModel(\"docs-researcher-p7\", (promptJson) =>\n Effect.succeed(\n promptJson.includes(firstCallId)\n ? digestParts(documentIds)\n : summaryDelegationParts(documentIds),\n ),\n );\n\n const parentBinding = Agent.withModel(DocsResearcher, parentModel.model);\n\n const delegationLayer = docsSummaryHandlersLayer(childBinding).pipe(\n Layer.provide(\n Layer.mergeAll(\n childToolkitLayer,\n SubagentReservationsMemoryLive,\n DeterministicIdGeneratorLayer,\n ),\n ),\n );\n\n const parentResolved: ResolvedBinding = yield* DurableWorkerBinding.make(\n parentBinding,\n docsCoordinatorDigests,\n ).pipe(Effect.provide(delegationLayer));\n\n const childResolved: ResolvedBinding = yield* DurableWorkerBinding.make(\n childBinding,\n docsSummarizerDigests,\n ).pipe(Effect.provide(childToolkitLayer));\n\n const harness: DocsResearcherHarness = {\n bindings: [parentResolved, childResolved],\n discovery,\n parentModelCalls: parentModel.calls,\n parentPrompts: parentModel.prompts,\n childModelCalls: childModel.calls,\n childPrompts: childModel.prompts,\n fetchInvocations: (documentId) =>\n Ref.get(fetchCounts).pipe(Effect.map((current) => current.get(documentId) ?? 0)),\n };\n\n return harness;\n });\n\nconst encodeResearchDocument = Schema.encodeEffect(ResearchDocument);\n\n/**\n * The audit-surface preview of one fetched document: the raw document —\n * secret marker and all — passes through the configured structural `Redactor`\n * before anything may quote it outside the child Thread (SEC-008,\n * CAP-013). Tests assert the preview keeps shape but no scalar content.\n */\nexport const redactedDocumentPreview = Effect.fn(\"DocsResearcher.redactedDocumentPreview\")(\n function* (documentId: string): Effect.fn.Return<RedactedPreview, RedactionError, Redactor> {\n const redactor = yield* Redactor;\n\n const encoded = yield* encodeResearchDocument(researchDocumentFor(documentId)).pipe(\n Effect.orDie,\n );\n\n return yield* redactor.redact(encoded);\n },\n);\n\n// Crypto is deliberately in the harness requirements (`connectMcp` digests\n// discovery): callers provide a platform Crypto Layer, keeping this fixture\n// platform-neutral.\nexport type DocsResearcherHarnessRequirements = Crypto.Crypto;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DocsResearcher.mjs","names":[],"sources":["../src/fixtures/docs-researcher/definition.ts","../src/fixtures/docs-researcher/mcp.ts","../src/fixtures/docs-researcher/harness.ts"],"sourcesContent":["import { Context, Effect, Schema } from \"effect\";\nimport * as Agent from \"effect-agent/agent\";\nimport { AgentPolicy } from \"effect-agent/agent-policy\";\nimport { type RuntimeBinding } from \"effect-agent/agent-runtime\";\nimport * as Subagent from \"effect-agent/subagent\";\nimport { SubagentPolicy } from \"effect-agent/subagent\";\nimport { Tool, Toolkit } from \"effect/unstable/ai\";\n\n// ---------------------------------------------------------------------------\n// Docs Researcher (P7 internal agent #3, plan §6): a coordinator that\n// delegates per-document summarization to a doc-summarizer child through the\n// S2 durable delegation surface, with the child's content tools served —\n// and validated — through the MCP connector against a scripted MCP fixture.\n// The corpus, tools, and both Agent Definitions are deterministic fixtures in\n// the travel-planner style so DN tests (and any later DC assembly) reuse them.\n// ---------------------------------------------------------------------------\n\nexport const ResearchDocumentId = Schema.NonEmptyString.check(Schema.isMaxLength(64)).pipe(\n Schema.brand(\"@effect-agent/testing/docs-researcher/ResearchDocumentId\"),\n);\n\nexport type ResearchDocumentId = typeof ResearchDocumentId.Type;\n\nconst BoundedTitle = Schema.NonEmptyString.check(Schema.isMaxLength(120));\nconst BoundedBody = Schema.NonEmptyString.check(Schema.isMaxLength(16 * 1024));\n\n/** Bounded summary text: the ONLY child-derived text that may cross to the parent. */\nexport const BoundedSummary = Schema.NonEmptyString.check(Schema.isMaxLength(240));\n\nexport class DocumentQuery extends Schema.Class<DocumentQuery>(\"DocumentQuery\")({\n documentId: ResearchDocumentId,\n}) {}\n\n/** One bounded research document as the MCP content server exposes it. */\nexport class ResearchDocument extends Schema.Class<ResearchDocument>(\"ResearchDocument\")({\n documentId: ResearchDocumentId,\n title: BoundedTitle,\n body: BoundedBody,\n}) {}\n\nexport class DocumentUnavailable extends Schema.TaggedError<DocumentUnavailable>()(\n \"DocumentUnavailable\",\n {\n documentId: ResearchDocumentId,\n message: Schema.String,\n },\n) {}\n\n/** The content store behind the scripted MCP server. */\nexport class DocumentLibrary extends Context.Service<\n DocumentLibrary,\n {\n readonly fetch: (query: DocumentQuery) => Effect.Effect<ResearchDocument, DocumentUnavailable>;\n }\n>()(\"@effect-agent/testing/docs-researcher/DocumentLibrary\") {}\n\n/**\n * The one content tool the doc-summarizer child uses. Its authored JSON\n * schema is what MCP discovery must serve byte-for-byte: the scripted MCP\n * fixture derives its discovery entry from `Tool.getJsonSchema(FetchDocument)`\n * and `validateMcpDiscovery` re-derives and digests both sides (CAP-009).\n */\nexport const FetchDocument = Tool.make(\"fetch_document\", {\n description: \"Fetch one bounded research document by its identifier.\",\n parameters: DocumentQuery,\n success: ResearchDocument,\n failure: DocumentUnavailable,\n failureMode: \"error\",\n dependencies: [DocumentLibrary],\n});\n\nexport const DocContentToolkit = Toolkit.make(FetchDocument);\n\nexport const docContentToolkitLayer = DocContentToolkit.toLayer({\n fetch_document: (query) => Effect.flatMap(DocumentLibrary, (library) => library.fetch(query)),\n});\n\n// ---------------------------------------------------------------------------\n// Deterministic corpus. Every body deliberately embeds BOTH a secret marker\n// and a distinctive body phrase: the tests assert that neither ever reaches\n// the parent Thread, the parent prompts, or a redacted preview — only\n// the bounded summary crosses the delegation boundary (SUB-015, SEC-008).\n// ---------------------------------------------------------------------------\n\n/** Never allowed outside a child Thread or an unredacted fixture value. */\nexport const docsDocumentBodySecret = \"docs-vault-secret-771\";\n\nconst decodeDocumentId = Schema.decodeSync(ResearchDocumentId);\n\ninterface CorpusEntry {\n readonly document: ResearchDocument;\n readonly bodyPhrase: string;\n readonly summary: string;\n}\n\nconst corpusEntries = new Map<string, CorpusEntry>(\n [\n {\n documentId: \"durability-notes\",\n title: \"Durability protocol notes\",\n bodyPhrase: \"amber-ledger-passage\",\n summary:\n \"Settlement results are recorded exactly once while external side effects stay at-least-once.\",\n },\n {\n documentId: \"subagent-notes\",\n title: \"Subagent join notes\",\n bodyPhrase: \"cobalt-join-corridor\",\n summary: \"A parent joins only the verified settlement of its own established child.\",\n },\n ].map((entry) => [\n entry.documentId,\n {\n document: ResearchDocument.make({\n documentId: decodeDocumentId(entry.documentId),\n title: entry.title,\n body: `${entry.bodyPhrase}: internal working notes. ${docsDocumentBodySecret}. ${entry.summary} Raw notes stay inside the child Thread.`,\n }),\n bodyPhrase: entry.bodyPhrase,\n summary: entry.summary,\n },\n ]),\n);\n\n/** The corpus document ids in canonical fixture order. */\nexport const researchCorpusDocumentIds: ReadonlyArray<ResearchDocumentId> = [\n decodeDocumentId(\"durability-notes\"),\n decodeDocumentId(\"subagent-notes\"),\n];\n\nconst requireCorpusEntry = (documentId: string): CorpusEntry => {\n const entry = corpusEntries.get(documentId);\n\n if (entry === undefined) {\n throw new Error(`No deterministic corpus entry exists for document ${documentId}`);\n }\n\n return entry;\n};\n\n/** Deterministic library lookup shared by the scripted MCP content handlers. */\nexport const researchDocumentLookup = (\n query: DocumentQuery,\n): Effect.Effect<ResearchDocument, DocumentUnavailable> => {\n const entry = corpusEntries.get(query.documentId);\n\n return entry === undefined\n ? Effect.fail(\n DocumentUnavailable.make({\n documentId: query.documentId,\n message: \"No deterministic corpus entry exists for this document.\",\n }),\n )\n : Effect.succeed(entry.document);\n};\n\n/** The full fixture document (body includes the secret marker — child-side only). */\nexport const researchDocumentFor = (documentId: string): ResearchDocument =>\n requireCorpusEntry(documentId).document;\n\n/** The distinctive body phrase used by context-isolation assertions. */\nexport const documentBodyPhrase = (documentId: string): string =>\n requireCorpusEntry(documentId).bodyPhrase;\n\n// ---------------------------------------------------------------------------\n// Doc Summarizer: the child Agent Definition. Its toolkit is the authored\n// `DocContentToolkit`; the harness registers its worker Binding only after\n// MCP discovery validates that exact toolkit (mcp.ts).\n// ---------------------------------------------------------------------------\n\nexport class SummaryBrief extends Schema.Class<SummaryBrief>(\"SummaryBrief\")({\n documentId: ResearchDocumentId,\n focus: Schema.NonEmptyString,\n}) {}\n\nexport class DocumentSummary extends Schema.Class<DocumentSummary>(\"DocumentSummary\")({\n documentId: ResearchDocumentId,\n summary: BoundedSummary,\n}) {}\n\n/** The summary the scripted child writes after fetching the document. */\nexport const documentSummaryFor = (documentId: string): DocumentSummary =>\n DocumentSummary.make({\n documentId: requireCorpusEntry(documentId).document.documentId,\n summary: requireCorpusEntry(documentId).summary,\n });\n\nexport const encodedDocumentSummary = (documentId: string): string =>\n JSON.stringify(Schema.encodeSync(DocumentSummary)(documentSummaryFor(documentId)));\n\nexport const DocSummarizer = Agent.make(\"doc-summarizer\", {\n input: SummaryBrief,\n output: DocumentSummary,\n instructions:\n \"Fetch the briefed document with fetch_document exactly once, then return only a JSON document summary. Never copy raw notes or secrets into the summary.\",\n toolkit: DocContentToolkit,\n policy: AgentPolicy.make({\n maxTurns: 2,\n maxToolCalls: 1,\n maxDuration: \"30 seconds\",\n toolConcurrency: 1,\n }),\n description: \"Summarize one bounded research document fetched through MCP content tools.\",\n metadata: { deploymentClass: \"DN\", phase: \"P7\" },\n});\n\n// ---------------------------------------------------------------------------\n// Delegation Definition: the coordinator sees exactly one Tool with explicit\n// projections and finite bounds. `projectResult` is the declassification\n// boundary (SUB-015): only the bounded summary crosses; the fetched body —\n// secret marker included — stays in the child Thread.\n// ---------------------------------------------------------------------------\n\nexport class SummaryRequest extends Schema.Class<SummaryRequest>(\"SummaryRequest\")({\n documentId: ResearchDocumentId,\n}) {}\n\nexport class SummaryFinding extends Schema.Class<SummaryFinding>(\"SummaryFinding\")({\n documentId: ResearchDocumentId,\n summary: BoundedSummary,\n}) {}\n\nexport class DocumentSummaryFailed extends Schema.TaggedError<DocumentSummaryFailed>()(\n \"DocumentSummaryFailed\",\n {\n childErrorTag: Schema.NonEmptyString,\n },\n) {}\n\n/** Finite per-invocation bounds (SUB-009): one fetch per child, two children per Run. */\nexport const documentSummaryPolicy = SubagentPolicy.make({\n maxChildren: 2,\n maxConcurrency: 2,\n maxTurns: 2,\n maxToolCalls: 1,\n maxDuration: \"10 seconds\",\n});\n\nexport const delegateDocumentSummary = Subagent.define(\"delegate_document_summary\", {\n description:\n \"Summarize one research document through the doc-summarizer child and return a bounded finding.\",\n target: DocSummarizer,\n parameters: SummaryRequest,\n success: SummaryFinding,\n failure: DocumentSummaryFailed,\n prepareInput: (request) =>\n Effect.succeed(\n SummaryBrief.make({\n documentId: request.documentId,\n focus: \"summarize:durability-claims\",\n }),\n ),\n projectResult: (summary) =>\n Effect.succeed(\n SummaryFinding.make({\n documentId: summary.documentId,\n summary: summary.summary,\n }),\n ),\n policy: documentSummaryPolicy,\n});\n\n/** Total mapping from every expected child Run failure to the declared Tool failure (SUB-028). */\nexport const mapSummaryChildFailure = (failure: { readonly _tag: string }): DocumentSummaryFailed =>\n DocumentSummaryFailed.make({ childErrorTag: failure._tag });\n\n/** The exact digest strings the durable declaration AND host registration must share (SUB-023). */\nexport const docsSummarizerDigestStrings = {\n agent: \"50\".repeat(32),\n model: \"51\".repeat(32),\n tools: \"52\".repeat(32),\n} as const;\n\n/** Runtime wiring: the immutable delegation plus one explicit child Binding (S2 declaration). */\nexport const docsSummaryHandlersLayer = <Provider, ModelProvides, ModelRequires>(\n childBinding: RuntimeBinding<\n typeof SummaryBrief,\n typeof DocumentSummary,\n string,\n Toolkit.Tools<typeof DocContentToolkit>,\n Provider,\n ModelProvides,\n ModelRequires\n >,\n) =>\n Subagent.layer(delegateDocumentSummary, childBinding, {\n mapChildFailure: mapSummaryChildFailure,\n durable: { targetDigests: docsSummarizerDigestStrings },\n });\n\n// ---------------------------------------------------------------------------\n// Docs Researcher: the parent Agent Definition.\n// ---------------------------------------------------------------------------\n\nexport class ResearchRequest extends Schema.Class<ResearchRequest>(\"ResearchRequest\")({\n question: Schema.NonEmptyString,\n documentIds: Schema.Array(ResearchDocumentId).check(Schema.isMinLength(1)),\n}) {}\n\nexport class ResearchDigest extends Schema.Class<ResearchDigest>(\"ResearchDigest\")({\n findings: Schema.Array(SummaryFinding),\n nextAction: Schema.Literal(\"review\"),\n}) {}\n\n/** Parent-only transcript markers proving child context isolation (SUB-006/SUB-015). */\nexport const docsCoordinatorConfidentialMarker = \"docs-coordinator-vault-19x\";\nexport const docsMissionConfidentialMarker = \"docs-mission-dossier-42f\";\n\nexport const DocsResearcherToolkit = Toolkit.make(delegateDocumentSummary.tool);\n\nexport const DocsResearcher = Agent.make(\"docs-researcher\", {\n input: ResearchRequest,\n output: ResearchDigest,\n instructions: [\n \"You are the Effect Agent P7 docs-researcher coordinator.\",\n `Coordinator-only context: ${docsCoordinatorConfidentialMarker}.`,\n \"Call delegate_document_summary once per requested document in one Tool batch.\",\n \"Return only a JSON digest built from the delegated findings. This is read-only research.\",\n ].join(\"\\n\"),\n toolkit: DocsResearcherToolkit,\n policy: AgentPolicy.make({\n maxTurns: 2,\n maxToolCalls: 2,\n maxDuration: \"30 seconds\",\n toolConcurrency: 2,\n }),\n description: \"Coordinate per-document summarization through one declared delegation Tool.\",\n metadata: { deploymentClass: \"DN\", phase: \"P7\" },\n});\n\n/** The default two-document research mission. */\nexport const researchMissionRequest = ResearchRequest.make({\n question: `Summarize the durability and subagent notes; keep ${docsMissionConfidentialMarker} inside the coordinator thread.`,\n documentIds: researchCorpusDocumentIds,\n});\n\n/** The coordinator's expected final digest for the given documents. */\nexport const expectedResearchDigest = (\n documentIds: ReadonlyArray<string> = researchCorpusDocumentIds,\n): ResearchDigest =>\n ResearchDigest.make({\n findings: documentIds.map((documentId) => {\n const summary = documentSummaryFor(documentId);\n\n return SummaryFinding.make({\n documentId: summary.documentId,\n summary: summary.summary,\n });\n }),\n nextAction: \"review\",\n });\n","import type { JsonSchema } from \"effect\";\nimport { Effect, JsonPointer, Layer, Schema } from \"effect\";\nimport {\n McpConnectionRequest,\n McpConnector,\n McpServerIdentity,\n McpToolkitMismatch,\n type McpConnection,\n} from \"effect-agent/mcp\";\nimport { Tool } from \"effect/unstable/ai\";\nimport * as McpSchema from \"effect/unstable/ai/McpSchema\";\n\nimport { DocContentToolkit, FetchDocument } from \"./definition.ts\";\n\n// ---------------------------------------------------------------------------\n// Scripted MCP fixture: a deterministic `McpConnector` adapter that serves the\n// doc-summarizer's content tool. Discovery entries are DERIVED from the\n// authored Tool (`Tool.getJsonSchema`), so `validateMcpDiscovery` digesting\n// both sides is a real check, not a tautology; the mismatch and over-limit\n// connectors below serve deliberately wrong contracts so tests can pin the\n// fail-closed paths (CAP-009, SEC-013).\n// ---------------------------------------------------------------------------\n\n/** Framework-side hard bounds one docs-researcher assembly requests. */\nexport const docsMcpRequest = McpConnectionRequest.make({\n serverId: \"docs-content-mcp\",\n maxToolCount: 4,\n maxToolDescriptionBytes: 256,\n maxDiscoveryBytes: 16_384,\n connectTimeoutMillis: 1_000,\n});\n\nexport const docsMcpIdentity = McpServerIdentity.make({\n serverId: docsMcpRequest.serverId,\n implementation: McpSchema.Implementation.make({\n name: \"docs-researcher-content-fixture\",\n version: \"1.0.0\",\n }),\n});\n\n/**\n * `Tool.getJsonSchema` produces a `$ref`/`$defs`-shaped schema for\n * `FetchDocument`'s named, refined parameters type, but `McpSchema.Tool`'s\n * `inputSchema` requires a flat `{ type: \"object\", ... }` root — the shape a\n * real MCP server advertises on the wire. This inlines the single top-level\n * `$ref` so the derivation described above still holds byte-for-byte.\n */\nconst JsonSchemaDefinitions = Schema.Record(\n Schema.String,\n Schema.Record(Schema.String, Schema.Unknown),\n);\n\nconst decodeJsonSchemaDefinitions = Schema.decodeUnknownSync(JsonSchemaDefinitions);\nconst decodeToolJson = Schema.decodeUnknownSync(McpSchema.ToolJson);\n\nconst flattenTopLevelRef = (schema: JsonSchema.JsonSchema): McpSchema.ToolJson => {\n const ref = schema[\"$ref\"];\n\n if (typeof ref !== \"string\") {\n return decodeToolJson(schema);\n }\n\n const defs = decodeJsonSchemaDefinitions(schema[\"$defs\"]);\n\n const key = ref.startsWith(\"#/$defs/\")\n ? JsonPointer.unescapeToken(ref.slice(\"#/$defs/\".length))\n : undefined;\n\n const resolved = key !== undefined && Object.hasOwn(defs, key) ? defs[key] : undefined;\n\n return decodeToolJson(resolved ?? schema);\n};\n\nconst fetchDocumentOutputSchema = flattenTopLevelRef(\n Tool.getJsonSchemaFromSchema(FetchDocument.successSchema),\n);\n\nconst discoveredFetchDocument = McpSchema.Tool.make({\n name: FetchDocument.name,\n description: \"Fetch one bounded research document by its identifier.\",\n inputSchema: flattenTopLevelRef(Tool.getJsonSchema(FetchDocument)),\n // `validateMcpDiscovery` only compares an `outputSchema` derived down to an\n // object type; mirror that so this fixture stays a real round-trip check.\n ...(fetchDocumentOutputSchema.type === \"object\"\n ? { outputSchema: fetchDocumentOutputSchema }\n : {}),\n});\n\nconst scriptedConnector = (tools: ReadonlyArray<McpSchema.Tool>): Layer.Layer<McpConnector> =>\n Layer.succeed(McpConnector)({\n connect: () =>\n Effect.acquireRelease(\n Effect.succeed({\n identity: docsMcpIdentity,\n capabilities: McpSchema.ServerCapabilities.make({}),\n tools,\n toolkit: DocContentToolkit,\n }),\n () => Effect.void,\n ),\n });\n\n/** The well-behaved scripted content server. */\nexport const docsMcpConnectorLayer: Layer.Layer<McpConnector> = scriptedConnector([\n discoveredFetchDocument,\n]);\n\n/** Serves a tool description exceeding `maxToolDescriptionBytes` (SEC-013 bound). */\nexport const docsMcpOversizedConnectorLayer: Layer.Layer<McpConnector> = scriptedConnector([\n McpSchema.Tool.make({\n name: discoveredFetchDocument.name,\n description: \"x\".repeat(1_024),\n inputSchema: discoveredFetchDocument.inputSchema,\n }),\n]);\n\n/** Serves a discovery schema that disagrees with the authored toolkit (drift fails closed). */\nexport const docsMcpMismatchedConnectorLayer: Layer.Layer<McpConnector> = scriptedConnector([\n McpSchema.Tool.make({\n name: discoveredFetchDocument.name,\n description: discoveredFetchDocument.description,\n inputSchema: { type: \"object\", properties: { url: { type: \"string\" } } },\n }),\n]);\n\nconst isJsonEqual = (left: unknown, right: unknown): boolean =>\n JSON.stringify(left) === JSON.stringify(right);\n\n/**\n * Bind DISCOVERY to AUTHORING: `validateMcpDiscovery` (inside `connectMcp`)\n * already proved the served discovery matches the connection's own Toolkit;\n * this check additionally proves that Toolkit is the exact toolkit the\n * doc-summarizer was AUTHORED against — same tool names, same derived JSON\n * schemas — so a connector cannot substitute a look-alike toolkit. The\n * docs-researcher harness runs it before any worker Binding registration and\n * fails closed on any drift.\n */\nexport const assertDiscoveryMatchesAuthoredToolkit = Effect.fn(\n \"DocsResearcher.assertDiscoveryMatchesAuthoredToolkit\",\n)(function* (connection: McpConnection): Effect.fn.Return<void, McpToolkitMismatch> {\n const authored = Object.values(DocContentToolkit.tools)\n .map((tool) => ({ name: tool.name, inputSchema: Tool.getJsonSchema(tool) }))\n .sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));\n\n const discovered = Object.values(connection.toolkit.tools)\n .map((tool) => ({ name: tool.name, inputSchema: Tool.getJsonSchema(tool) }))\n .sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));\n\n const matches =\n authored.length === discovered.length &&\n authored.every(\n (tool, index) =>\n tool.name === discovered[index]?.name &&\n isJsonEqual(tool.inputSchema, discovered[index]?.inputSchema),\n );\n\n if (!matches) {\n return yield* McpToolkitMismatch.make({\n serverId: connection.discovery.identity.serverId,\n message:\n \"The MCP-discovered toolkit does not match the doc-summarizer's authored content toolkit\",\n });\n }\n});\n\n/** Round-trip guard for encoded discovery values persisted as fixture evidence. */\nexport const DocsMcpDiscoveryEvidence = Schema.Struct({\n serverId: Schema.NonEmptyString,\n toolCount: Schema.Natural,\n encodedBytes: Schema.Natural,\n toolkitSchemaDigest: Schema.String,\n});\n","import type { Crypto } from \"effect\";\nimport { Effect, Layer, Ref, Schema, Stream } from \"effect\";\nimport * as Agent from \"effect-agent/agent\";\nimport { DurableWorkerBinding, type ResolvedBinding } from \"effect-agent/agent-registration\";\nimport { type DurableSubmitOptions } from \"effect-agent/durable-agent-runtime\";\nimport { type ThreadId } from \"effect-agent/identifiers\";\nimport { connectMcp, type McpDiscovery } from \"effect-agent/mcp\";\nimport { DefinitionDigests, DeploymentId, Digest, ProducerId } from \"effect-agent/records\";\nimport { Redactor, type RedactedPreview, type RedactionError } from \"effect-agent/redaction\";\nimport { SubagentReservationsMemoryLive } from \"effect-agent/subagent-reservations\";\nimport { Principal, type IdempotencyKey } from \"effect-agent/submission-ledger\";\nimport { LanguageModel, Model, type Response } from \"effect/unstable/ai\";\n\nimport { DeterministicIdGeneratorLayer } from \"../travel-planner/deterministic-layers.ts\";\nimport {\n DocsResearcher,\n DocSummarizer,\n DocumentLibrary,\n docContentToolkitLayer,\n docsSummaryHandlersLayer,\n encodedDocumentSummary,\n expectedResearchDigest,\n ResearchDigest,\n ResearchDocument,\n researchCorpusDocumentIds,\n researchDocumentFor,\n researchDocumentLookup,\n} from \"./definition.ts\";\nimport {\n assertDiscoveryMatchesAuthoredToolkit,\n docsMcpConnectorLayer,\n docsMcpRequest,\n} from \"./mcp.ts\";\n\n// ---------------------------------------------------------------------------\n// DN durable harness for the docs-researcher (P7 plan §6 agent #3), following\n// `makeDurableResearchHarness` conventions: invocation counters and captured\n// prompts live OUTSIDE the Model Layers so they survive Layer rebuilds across\n// Attempts and separate runtime handles over the same SQLite file.\n// ---------------------------------------------------------------------------\n\nexport const docsResearcherDeploymentId = Schema.decodeSync(DeploymentId)(\n \"docs-researcher-p7-deployment\",\n);\n\nexport const docsResearcherProducerId = Schema.decodeSync(ProducerId)(\n \"docs-researcher-p7-producer\",\n);\n\nexport const docsResearcherPrincipal = Schema.decodeSync(Principal)(\"docs-researcher-p7-principal\");\n\nconst digestOf = (pair: string) => Schema.decodeSync(Digest)(pair.repeat(32));\n\n/** Redacted, deterministic coordinator definition digests for this fixture version. */\nexport const docsCoordinatorDigests = DefinitionDigests.make({\n agent: digestOf(\"40\"),\n model: digestOf(\"41\"),\n tools: digestOf(\"42\"),\n});\n\n/** The child registration digests — byte-equal to `docsSummarizerDigestStrings` (SUB-023). */\nexport const docsSummarizerDigests = DefinitionDigests.make({\n agent: digestOf(\"50\"),\n model: digestOf(\"51\"),\n tools: digestOf(\"52\"),\n});\n\n/** Durable admission options for one docs-researcher Submission on one mission lane. */\nexport const docsResearcherSubmitOptions = (\n threadId: ThreadId,\n idempotencyKey: IdempotencyKey,\n): DurableSubmitOptions => ({\n threadId,\n principal: docsResearcherPrincipal,\n idempotencyKey,\n definitions: docsCoordinatorDigests,\n});\n\n/** The structural submit slice of the coordinator Binding (`DurableAgentRuntime.submit`). */\nexport const docsResearcherSubmitAgent = {\n definition: { id: DocsResearcher.id, input: DocsResearcher.input },\n} as const;\n\n/** The deterministic delegation Tool Call identity for one document. */\nexport const summarizeCallId = (documentId: string): string => `summarize-${documentId}`;\n\n/** The child's own scripted fetch Tool Call identity for one document. */\nexport const fetchCallId = (documentId: string): string => `fetch-${documentId}`;\n\nconst scriptedUsage = { inputTokens: { total: 96 }, outputTokens: { total: 64 } };\n\nconst summaryDelegationParts = (\n documentIds: ReadonlyArray<string>,\n): ReadonlyArray<Response.StreamPartEncoded> => [\n ...documentIds.map((documentId): Response.StreamPartEncoded => ({\n type: \"tool-call\",\n id: summarizeCallId(documentId),\n name: \"delegate_document_summary\",\n params: { documentId },\n providerExecuted: false,\n })),\n { type: \"finish\", reason: \"tool-calls\", usage: scriptedUsage },\n];\n\nconst digestParts = (\n documentIds: ReadonlyArray<string>,\n): ReadonlyArray<Response.StreamPartEncoded> => [\n { type: \"text-start\", id: \"digest\" },\n {\n type: \"text-delta\",\n id: \"digest\",\n delta: JSON.stringify(Schema.encodeSync(ResearchDigest)(expectedResearchDigest(documentIds))),\n },\n { type: \"text-end\", id: \"digest\" },\n { type: \"finish\", reason: \"stop\", usage: scriptedUsage },\n];\n\nconst fetchParts = (documentId: string): ReadonlyArray<Response.StreamPartEncoded> => [\n {\n type: \"tool-call\",\n id: fetchCallId(documentId),\n name: \"fetch_document\",\n params: { documentId },\n providerExecuted: false,\n },\n { type: \"finish\", reason: \"tool-calls\", usage: scriptedUsage },\n];\n\nconst summaryParts = (documentId: string): ReadonlyArray<Response.StreamPartEncoded> => [\n { type: \"text-start\", id: \"document-summary\" },\n { type: \"text-delta\", id: \"document-summary\", delta: encodedDocumentSummary(documentId) },\n { type: \"text-end\", id: \"document-summary\" },\n { type: \"finish\", reason: \"stop\", usage: scriptedUsage },\n];\n\n/**\n * One prompt-aware scripted model with externally observable counters. A DN\n * Attempt may resume on a fresh Layer build, so responses derive from the\n * committed history in the prompt — never from an in-Layer turn counter.\n */\nconst makeCountingModel = (\n name: string,\n decide: (promptJson: string) => Effect.Effect<ReadonlyArray<Response.StreamPartEncoded>>,\n) =>\n Effect.gen(function* () {\n const calls = yield* Ref.make(0);\n const prompts = yield* Ref.make<ReadonlyArray<string>>([]);\n\n const model = Model.make(\n \"scripted\",\n name,\n Layer.effect(\n LanguageModel.LanguageModel,\n LanguageModel.make({\n generateText: () => Effect.succeed([]),\n streamText: (request) =>\n Stream.unwrap(\n Effect.gen(function* () {\n yield* Ref.update(calls, (value) => value + 1);\n const promptJson = JSON.stringify(request.prompt);\n\n yield* Ref.update(prompts, (previous) => [...previous, promptJson]);\n\n return Stream.fromIterable(yield* decide(promptJson));\n }),\n ),\n }),\n ),\n );\n\n return { model, calls: Ref.get(calls), prompts: Ref.get(prompts) };\n });\n\n/** Optional overrides for one docs-researcher harness. */\nexport interface DocsResearcherHarnessOptions {\n /** Documents to research; defaults to the full two-document corpus. */\n readonly documentIds?: ReadonlyArray<string> | undefined;\n}\n\n/** One durable coordinator/summarizer pair with observable counters and MCP evidence. */\nexport interface DocsResearcherHarness {\n /** Resolved registrations for the parent and child workers. */\n readonly bindings: ReadonlyArray<ResolvedBinding>;\n /** The validated MCP discovery the child toolkit registration was gated on. */\n readonly discovery: McpDiscovery;\n /** Total coordinator model invocations across every Attempt and runtime handle. */\n readonly parentModelCalls: Effect.Effect<number>;\n /** JSON-encoded coordinator prompts in request order. */\n readonly parentPrompts: Effect.Effect<ReadonlyArray<string>>;\n /** Total summarizer model invocations across every Attempt and runtime handle. */\n readonly childModelCalls: Effect.Effect<number>;\n /** JSON-encoded summarizer prompts in request order (context-isolation evidence). */\n readonly childPrompts: Effect.Effect<ReadonlyArray<string>>;\n /** MCP content-tool handler executions for one document (external side-effect record). */\n readonly fetchInvocations: (documentId: string) => Effect.Effect<number>;\n}\n\n/**\n * Build the docs-researcher harness. Order matters and is the point: the\n * child's content toolkit is only registered as a worker Binding AFTER the\n * MCP connector's bounded discovery validated the authored toolkit\n * byte-for-byte (`connectMcp` + `assertDiscoveryMatchesAuthoredToolkit`), so\n * \"the tools the summarizer runs are the tools discovery served\" is enforced\n * at assembly, not assumed. Content-tool execution then flows through the\n * counting `DocumentLibrary` — the scripted MCP server's content store.\n */\nexport const makeDocsResearcherHarness = (options?: DocsResearcherHarnessOptions) =>\n Effect.gen(function* () {\n const documentIds = options?.documentIds ?? researchCorpusDocumentIds;\n\n // MCP discovery gate (CAP-009): bounded, digest-verified, fail-closed.\n const discovery = yield* Effect.scoped(\n Effect.gen(function* () {\n const connection = yield* connectMcp(docsMcpRequest);\n\n yield* assertDiscoveryMatchesAuthoredToolkit(connection);\n\n return connection.discovery;\n }),\n ).pipe(Effect.provide(docsMcpConnectorLayer));\n\n const fetchCounts = yield* Ref.make<ReadonlyMap<string, number>>(new Map());\n\n const libraryLayer = Layer.succeed(\n DocumentLibrary,\n DocumentLibrary.of({\n fetch: (query) =>\n Ref.update(fetchCounts, (current) =>\n new Map(current).set(query.documentId, (current.get(query.documentId) ?? 0) + 1),\n ).pipe(Effect.andThen(researchDocumentLookup(query))),\n }),\n );\n\n const childToolkitLayer = docContentToolkitLayer.pipe(Layer.provideMerge(libraryLayer));\n\n const childModel = yield* makeCountingModel(\"doc-summarizer-p7\", (promptJson) =>\n Effect.suspend(() => {\n const documentId = documentIds.find((candidate) => promptJson.includes(candidate));\n\n if (documentId === undefined) {\n return Effect.die(new Error(\"The summarizer prompt names no corpus document\"));\n }\n\n return Effect.succeed(\n promptJson.includes(fetchCallId(documentId))\n ? summaryParts(documentId)\n : fetchParts(documentId),\n );\n }),\n );\n\n const childBinding = Agent.withModel(DocSummarizer, childModel.model);\n\n const firstCallId = summarizeCallId(documentIds[0] ?? \"durability-notes\");\n\n const parentModel = yield* makeCountingModel(\"docs-researcher-p7\", (promptJson) =>\n Effect.succeed(\n promptJson.includes(firstCallId)\n ? digestParts(documentIds)\n : summaryDelegationParts(documentIds),\n ),\n );\n\n const parentBinding = Agent.withModel(DocsResearcher, parentModel.model);\n\n const delegationLayer = docsSummaryHandlersLayer(childBinding).pipe(\n Layer.provide(\n Layer.mergeAll(\n childToolkitLayer,\n SubagentReservationsMemoryLive,\n DeterministicIdGeneratorLayer,\n ),\n ),\n );\n\n const parentResolved: ResolvedBinding = yield* DurableWorkerBinding.make(\n parentBinding,\n docsCoordinatorDigests,\n ).pipe(Effect.provide(delegationLayer));\n\n const childResolved: ResolvedBinding = yield* DurableWorkerBinding.make(\n childBinding,\n docsSummarizerDigests,\n ).pipe(Effect.provide(childToolkitLayer));\n\n const harness: DocsResearcherHarness = {\n bindings: [parentResolved, childResolved],\n discovery,\n parentModelCalls: parentModel.calls,\n parentPrompts: parentModel.prompts,\n childModelCalls: childModel.calls,\n childPrompts: childModel.prompts,\n fetchInvocations: (documentId) =>\n Ref.get(fetchCounts).pipe(Effect.map((current) => current.get(documentId) ?? 0)),\n };\n\n return harness;\n });\n\nconst encodeResearchDocument = Schema.encodeEffect(ResearchDocument);\n\n/**\n * The audit-surface preview of one fetched document: the raw document —\n * secret marker and all — passes through the configured structural `Redactor`\n * before anything may quote it outside the child Thread (SEC-008,\n * CAP-013). Tests assert the preview keeps shape but no scalar content.\n */\nexport const redactedDocumentPreview = Effect.fn(\"DocsResearcher.redactedDocumentPreview\")(\n function* (documentId: string): Effect.fn.Return<RedactedPreview, RedactionError, Redactor> {\n const redactor = yield* Redactor;\n\n const encoded = yield* encodeResearchDocument(researchDocumentFor(documentId)).pipe(\n Effect.orDie,\n );\n\n return yield* redactor.redact(encoded);\n },\n);\n\n// Crypto is deliberately in the harness requirements (`connectMcp` digests\n// discovery): callers provide a platform Crypto Layer, keeping this fixture\n// platform-neutral.\nexport type DocsResearcherHarnessRequirements = Crypto.Crypto;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@effect-agent/testing","version":"0.1.0-beta.
|
|
1
|
+
{"name":"@effect-agent/testing","version":"0.1.0-beta.112","dependencies":{"effect-agent":"0.1.0-beta.112"},"devDependencies":{"@effect-agent/ai-decision":"0.1.0-beta.112","@effect-agent/platform-node":"0.1.0-beta.112","@effect-agent/storage-memory":"0.1.0-beta.112","@effect-agent/storage-sqlite":"0.1.0-beta.112","@effect/platform-node":"4.0.0-rc.116","@effect/sql-sqlite-node":"4.0.0-rc.116","@effect/vitest":"4.0.0-rc.116","effect":"4.0.0-rc.116","typescript":"7.0.2","vite-plus":"0.3.2"},"peerDependencies":{"effect":"^4.0.0-rc.116"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./certification":{"types":"./dist/Certification.d.mts","default":"./dist/Certification.mjs"},"./chaos":{"types":"./dist/Chaos.d.mts","default":"./dist/Chaos.mjs"},"./code-executor-conformance":{"types":"./dist/CodeExecutorConformance.d.mts","default":"./dist/CodeExecutorConformance.mjs"},"./code-executor-substitute":{"types":"./dist/CodeExecutorSubstitute.d.mts","default":"./dist/CodeExecutorSubstitute.mjs"},"./docs-researcher":{"types":"./dist/DocsResearcher.d.mts","default":"./dist/DocsResearcher.mjs"},"./scripted-model":{"types":"./dist/ScriptedModel.d.mts","default":"./dist/ScriptedModel.mjs"},"./travel-planner":{"types":"./dist/TravelPlanner.d.mts","default":"./dist/TravelPlanner.mjs"}},"description":"Scripted models, deterministic fixtures, and adapter conformance kits for testing Effect Agent applications.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/testing"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests"}}
|
package/src/Certification.ts
CHANGED
|
@@ -729,11 +729,11 @@ const verifyLane = Effect.fn("Certification.verifyLane")(function* (
|
|
|
729
729
|
const exported = yield* store.export(ThreadExportRequest.make({ threadId: lane }));
|
|
730
730
|
const rows = new Map<SubmissionId, SubmissionSnapshot>();
|
|
731
731
|
const nonterminal = yield* Stream.runCollect(ledger.scanNonterminal);
|
|
732
|
+
const named = new Set<SubmissionId>();
|
|
732
733
|
|
|
733
734
|
for (const submission of nonterminal) {
|
|
734
|
-
if (submission.threadId === lane)
|
|
735
|
+
if (submission.threadId === lane) named.add(submission.submissionId);
|
|
735
736
|
}
|
|
736
|
-
const named = new Set<SubmissionId>();
|
|
737
737
|
|
|
738
738
|
for (const envelope of exported.records) {
|
|
739
739
|
const payload = envelope.record.payload;
|
|
@@ -885,7 +885,7 @@ const runSweepCell = Effect.fn("Certification.runSweepCell")(function* (
|
|
|
885
885
|
// Expire any lease a faulted Attempt left behind (D5): virtual time is the
|
|
886
886
|
// adapter-neutral reclaim lever — a live lease may block every new claim.
|
|
887
887
|
yield* TestClock.adjust(leaseAdvance);
|
|
888
|
-
yield* Effect.exit(runtime.runRecovery);
|
|
888
|
+
yield* Effect.exit(runtime.runRecovery());
|
|
889
889
|
for (const lane of lanes) {
|
|
890
890
|
yield* Effect.exit(driveLane(lane));
|
|
891
891
|
}
|
package/src/Chaos.ts
CHANGED
|
@@ -1141,7 +1141,7 @@ export const runChaosPlan = Effect.fn("Chaos.runChaosPlan")(function* (
|
|
|
1141
1141
|
yield* failpoints.clear;
|
|
1142
1142
|
if (options?.adapterFailpoints !== undefined) yield* options.adapterFailpoints.clear;
|
|
1143
1143
|
|
|
1144
|
-
yield* tolerateTyped(runtime.runRecovery);
|
|
1144
|
+
yield* tolerateTyped(runtime.runRecovery());
|
|
1145
1145
|
// Second, unarmed pass guarantees forward progress for newly marked Unknown lanes.
|
|
1146
1146
|
yield* resolutionPass(plan, states, desk);
|
|
1147
1147
|
|
|
@@ -1157,7 +1157,7 @@ export const runChaosPlan = Effect.fn("Chaos.runChaosPlan")(function* (
|
|
|
1157
1157
|
|
|
1158
1158
|
const detail = Option.isSome(nonterminal)
|
|
1159
1159
|
? Array.from(nonterminal.value)
|
|
1160
|
-
.map((row
|
|
1160
|
+
.map((row) => `${row.submissionId}(${row.state})`)
|
|
1161
1161
|
.join(", ")
|
|
1162
1162
|
: "ledger scan failed";
|
|
1163
1163
|
|
|
@@ -51,13 +51,13 @@ const JsonSchemaDefinitions = Schema.Record(
|
|
|
51
51
|
);
|
|
52
52
|
|
|
53
53
|
const decodeJsonSchemaDefinitions = Schema.decodeUnknownSync(JsonSchemaDefinitions);
|
|
54
|
-
const
|
|
54
|
+
const decodeToolJson = Schema.decodeUnknownSync(McpSchema.ToolJson);
|
|
55
55
|
|
|
56
|
-
const flattenTopLevelRef = (schema: JsonSchema.JsonSchema): McpSchema.
|
|
56
|
+
const flattenTopLevelRef = (schema: JsonSchema.JsonSchema): McpSchema.ToolJson => {
|
|
57
57
|
const ref = schema["$ref"];
|
|
58
58
|
|
|
59
59
|
if (typeof ref !== "string") {
|
|
60
|
-
return
|
|
60
|
+
return decodeToolJson(schema);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
const defs = decodeJsonSchemaDefinitions(schema["$defs"]);
|
|
@@ -68,7 +68,7 @@ const flattenTopLevelRef = (schema: JsonSchema.JsonSchema): McpSchema.ToolJsonSc
|
|
|
68
68
|
|
|
69
69
|
const resolved = key !== undefined && Object.hasOwn(defs, key) ? defs[key] : undefined;
|
|
70
70
|
|
|
71
|
-
return
|
|
71
|
+
return decodeToolJson(resolved ?? schema);
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
const fetchDocumentOutputSchema = flattenTopLevelRef(
|