{"version":3,"file":"conformance.mjs","names":[],"sources":["../../../src/batteries/orchestration/conformance.ts"],"sourcesContent":["/**\n * The shared conformance suite for {@link PlanStore} backends.\n *\n * A consumer who owns their own plan store imports {@link runPlanStoreConformance} and drives it\n * with a factory that mints a fresh store per case. Each case is a contract assertion written\n * against the {@link PlanStore} interface only — never against in-memory internals — so a passing\n * suite proves the backend honours the same contract the shipped reference implementation does.\n *\n * Public, deep-import-only (`@nhtio/adk/batteries/orchestration/conformance`). The suite has no\n * test-runner dependency: callers invoke and await it from any test framework.\n *\n * @module @nhtio/adk/batteries/orchestration/conformance\n */\n\nimport { foldOps } from './ops'\nimport { isObject } from '@nhtio/adk/guards'\nimport type { PlanStore, TransitionRequest } from './store'\nimport type {\n  ApprovalRecord,\n  ArtifactTable,\n  PlanOp,\n  PlanNode,\n  PendingFrame,\n  RunEvent,\n  SpooledArtifactLike,\n} from './types'\n\n/**\n * Drive a plan store through the shared contract suite.\n *\n * @param label - A human label for the store under test, used in the suite title.\n * @param makeStore - A factory returning a FRESH store for each case, so no case shares state with\n *   another. May be async.\n */\nconst equal = (actual: unknown, expected: unknown): boolean => {\n  if (actual === expected) return true\n  if (\n    actual === null ||\n    expected === null ||\n    typeof actual !== 'object' ||\n    typeof expected !== 'object'\n  )\n    return false\n  if (Array.isArray(actual) !== Array.isArray(expected)) return false\n  const keysA = Object.keys(actual)\n  const keysB = Object.keys(expected)\n  if (keysA.length !== keysB.length) return false\n  return keysA.every((k) => keysB.includes(k) && equal((actual as any)[k], (expected as any)[k]))\n}\nconst match = (actual: unknown, expected: unknown): boolean => {\n  if (expected === null || typeof expected !== 'object') return equal(actual, expected)\n  if (actual === null || typeof actual !== 'object') return false\n  return Object.entries(expected).every(([key, value]) =>\n    match((actual as Record<string, unknown>)[key], value)\n  )\n}\nconst expectValue = (actual: unknown) => ({\n  toBe: (expected: unknown) => assert(equal(actual, expected), 'values were not equal'),\n  toEqual: (expected: unknown) => assert(equal(actual, expected), 'values were not equal'),\n  toMatchObject: (expected: unknown) =>\n    assert(match(actual, expected), 'value did not match expected object'),\n  toBeDefined: () => assert(actual !== undefined, 'value was undefined'),\n  toBeUndefined: () => assert(actual === undefined, 'value was defined'),\n  toHaveLength: (length: number) =>\n    assert((actual as { length: number }).length === length, 'unexpected length'),\n  toBeGreaterThan: (value: number) =>\n    assert((actual as number) > value, 'value was not greater than expected'),\n  rejects: {\n    toThrow: async () => {\n      try {\n        await (actual as Promise<unknown>)\n      } catch {\n        return\n      }\n      throw new Error('expected promise to reject')\n    },\n  },\n})\nconst assert: (condition: boolean, message: string) => asserts condition = (condition, message) => {\n  if (!condition) throw new Error(message)\n}\n\n/**\n * Run the framework-free PlanStore conformance suite against a consumer implementation.\n *\n * Each check creates a fresh store through `makeStore`, and the returned promise rejects when any\n * contract assertion fails. Consumers can await this function from Vitest, node:test, Jest, Mocha,\n * or another runner without importing a test framework from the conformance module.\n *\n * @param label - Human-readable name used to identify the implementation under test.\n * @param makeStore - Factory returning a fresh PlanStore for each conformance check; it may be async.\n */\nexport const runPlanStoreConformance = async (\n  label: string,\n  makeStore: () => PlanStore | Promise<PlanStore>\n): Promise<void> => {\n  const pending: Array<() => Promise<void>> = []\n  const it = (_name: string, test: () => Promise<void>) => {\n    pending.push(test)\n  }\n  const describe = (_name: string, suite: () => void) => suite()\n  const expect = expectValue\n  describe(`PlanStore conformance: ${label}`, () => {\n    // ── helpers ────────────────────────────────────────────────────────────────\n    /** A minimal, well-shaped `entry` node for authoring ops. */\n    const entryNode = (id: string): PlanNode => ({\n      id,\n      kind: 'entry',\n      definition: { input: [] },\n    })\n\n    /** An `add_node` op for the given node, with a unique identity. */\n    const addNodeOp = (node: PlanNode, lamport: number): PlanOp => ({\n      op: 'add_node',\n      node,\n      opId: `op-${lamport}`,\n      actorId: 'conformance',\n      lamport,\n      at: '2024-01-01T00:00:00.000Z',\n    })\n\n    /** A valid approval record bound to a digest. */\n    const approvalFor = (planId: string, digest: string): ApprovalRecord => ({\n      planId,\n      digest,\n      authoritySet: [],\n      decidedBy: 'conformance',\n      decidedAt: '2024-01-01T00:00:00.000Z',\n      disposition: 'approved',\n    })\n\n    /** Append a single node and return the resulting digest, asserting the append succeeded. */\n    const appendNode = async (\n      store: PlanStore,\n      planId: string,\n      node: PlanNode,\n      lamport: number\n    ) => {\n      const result = await store.appendOps(planId, [addNodeOp(node, lamport)])\n      expect(result).toMatchObject({ ok: true })\n      return (result as { digest: string }).digest\n    }\n\n    /** Drive a plan to `executable` at the digest of a single authored node, and return that digest. */\n    const makeExecutable = async (store: PlanStore, planId: string) => {\n      const digest = await appendNode(store, planId, entryNode('entry'), 1)\n      await store.transition(planId, { from: 'editable', to: 'reviewable', expectedDigest: digest })\n      await store.transition(planId, {\n        from: 'reviewable',\n        to: 'executable',\n        expectedDigest: digest,\n        approval: approvalFor(planId, digest),\n      })\n      return digest\n    }\n\n    // ── 1. genesis ─────────────────────────────────────────────────────────────\n    it('createPlan mints editable at revision 0 with an empty op log and a non-empty digest', async () => {\n      const store = await makeStore()\n      const created = await store.createPlan('p1')\n      expect(created).toMatchObject({ ok: true, revision: 0 })\n      const state = await store.readState('p1')\n      expect(state.state).toBe('editable')\n      expect(state.revision).toBe(0)\n      expect(state.digest.length).toBeGreaterThan(0)\n      expect(await store.readOps('p1')).toEqual([])\n\n      const appended = await store.appendOps('p1', [addNodeOp(entryNode('entry'), 1)])\n      expect(appended).toMatchObject({ ok: true, revision: 1 })\n    })\n\n    // ── 2. duplicate id ────────────────────────────────────────────────────────\n    it('createPlan refuses a duplicate id with reason duplicate_id', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      const dup = await store.createPlan('p1')\n      expect(dup).toMatchObject({ ok: false, reason: 'duplicate_id' })\n    })\n\n    // ── 3. appendOps refused in reviewable ────────────────────────────────────\n    it('appendOps is refused in reviewable with reason not_editable and the real state', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      const d1 = await appendNode(store, 'p1', entryNode('entry'), 1)\n      await store.transition('p1', { from: 'editable', to: 'reviewable', expectedDigest: d1 })\n\n      const result = await store.appendOps('p1', [addNodeOp(entryNode('entry2'), 2)])\n      expect(result).toMatchObject({\n        ok: false,\n        reason: 'not_editable',\n        actual: { state: 'reviewable' },\n      })\n    })\n\n    // ── 4. appendOps refused in executable, digest unchanged ─────────────────\n    it('appendOps is refused in executable with not_editable and leaves the digest unchanged', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      const d1 = await makeExecutable(store, 'p1')\n\n      const result = await store.appendOps('p1', [addNodeOp(entryNode('entry2'), 2)])\n      expect(result).toMatchObject({\n        ok: false,\n        reason: 'not_editable',\n        actual: { state: 'executable' },\n      })\n      const state = await store.readState('p1')\n      expect(state.digest).toBe(d1)\n    })\n\n    // ── 5. stale expectedRevision ─────────────────────────────────────────────\n    it('appendOps with a stale expectedRevision returns revision_moved', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      await appendNode(store, 'p1', entryNode('entry'), 1)\n      const result = await store.appendOps('p1', [addNodeOp(entryNode('entry2'), 2)], 0)\n      expect(result).toMatchObject({ ok: false, reason: 'revision_moved' })\n    })\n\n    // ── 6. stale-approval interleaving ────────────────────────────────────────\n    it('a transition gated on a stale digest is refused with digest_mismatch and leaves the plan reviewable', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      const d1 = await appendNode(store, 'p1', entryNode('entry'), 1)\n      await store.transition('p1', { from: 'editable', to: 'reviewable', expectedDigest: d1 })\n\n      // Unfreeze, append, refreeze — the plan now sits at a NEW digest D2.\n      await store.transition('p1', { from: 'reviewable', to: 'editable', expectedDigest: d1 })\n      const d2 = await appendNode(store, 'p1', entryNode('entry2'), 2)\n      await store.transition('p1', { from: 'editable', to: 'reviewable', expectedDigest: d2 })\n\n      // Gate with the STALE digest D1 — must be refused, not silently approved.\n      const gate = await store.transition('p1', {\n        from: 'reviewable',\n        to: 'executable',\n        expectedDigest: d1,\n        approval: approvalFor('p1', d1),\n      })\n      expect(gate).toMatchObject({ ok: false, reason: 'digest_mismatch' })\n\n      const state = await store.readState('p1')\n      expect(state.state).toBe('reviewable')\n      expect(await store.readApproval('p1')).toBeUndefined()\n    })\n\n    // ── 7. approval persists in the same commit ───────────────────────────────\n    it('a successful gate persists the approval bound to the gated digest', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      const d1 = await appendNode(store, 'p1', entryNode('entry'), 1)\n      await store.transition('p1', { from: 'editable', to: 'reviewable', expectedDigest: d1 })\n      const gate = await store.transition('p1', {\n        from: 'reviewable',\n        to: 'executable',\n        expectedDigest: d1,\n        approval: approvalFor('p1', d1),\n      })\n      expect(gate).toMatchObject({ ok: true })\n      const approval = await store.readApproval('p1')\n      expect(approval?.digest).toBe(d1)\n    })\n\n    // ── 8. illegal transition pair ────────────────────────────────────────────\n    it('an illegal transition pair is answered with ok:false and reason illegal_transition, not thrown', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      await makeExecutable(store, 'p1')\n\n      // Pass the plan's REAL current digest so state and digest can never be the reason —\n      // only the illegal pair (executable -> editable) can be. This isolates the legality\n      // check from the store's state/digest-first ordering.\n      const { digest } = await store.readState('p1')\n\n      // A BYO store may receive a request the type system did not police (e.g. over a wire).\n      const request = {\n        from: 'executable',\n        to: 'editable',\n        expectedDigest: digest,\n      } as unknown as TransitionRequest\n      const result = await store.transition('p1', request)\n      expect(result).toMatchObject({ ok: false, reason: 'illegal_transition' })\n    })\n\n    // ── 8b. stale digest on a legal pair ───────────────────────────────────────\n    it('a well-formed pair with a stale digest is refused with digest_mismatch', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      // Drive the plan to `reviewable`, so that `reviewable -> executable` below is a LEGAL pair\n      // and the digest is the only thing wrong with the request.\n      const digest = await appendNode(store, 'p1', entryNode('entry'), 1)\n      await store.transition('p1', { from: 'editable', to: 'reviewable', expectedDigest: digest })\n\n      // A legal pair gated on a bogus digest must be refused with digest_mismatch — the check the\n      // store performs before it considers applying the pair.\n      const result = await store.transition('p1', {\n        from: 'reviewable',\n        to: 'executable',\n        expectedDigest: 'stale',\n        approval: approvalFor('p1', 'stale'),\n      })\n      expect(result).toMatchObject({ ok: false, reason: 'digest_mismatch' })\n\n      // The refusal left the plan untouched: still reviewable, still at its real digest.\n      const state = await store.readState('p1')\n      expect(state.state).toBe('reviewable')\n      expect(state.digest).toBe(digest)\n    })\n\n    // ── 9. claimRun exactly once ──────────────────────────────────────────────\n    it('claimRun succeeds exactly once under concurrent claimants', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      const d1 = await makeExecutable(store, 'p1')\n\n      const [a, b] = await Promise.all([store.claimRun('p1', d1), store.claimRun('p1', d1)])\n      const winners = [a, b].filter((r) => r.ok === true)\n      const losers = [a, b].filter((r) => r.ok === false)\n      expect(winners).toHaveLength(1)\n      expect(losers).toHaveLength(1)\n      expect(losers[0]).toMatchObject({ ok: false, reason: 'run_already_claimed' })\n      expect((losers[0] as { existingRunId?: string }).existingRunId).toBe(\n        (winners[0] as { runId: string }).runId\n      )\n    })\n\n    // ── 10. claimRun re-entry ─────────────────────────────────────────────────\n    it('claimRun re-enters a run with resumeRunId, and refuses unknown or settled runs', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      const d1 = await makeExecutable(store, 'p1')\n\n      const first = await store.claimRun('p1', d1)\n      expect(first).toMatchObject({ ok: true, resumed: false })\n      const runId = (first as { runId: string }).runId\n\n      const resumed = await store.claimRun('p1', d1, runId)\n      expect(resumed).toMatchObject({ ok: true, resumed: true })\n\n      const unknown = await store.claimRun('p1', d1, 'no-such-run')\n      expect(unknown).toMatchObject({ ok: false, reason: 'run_not_found' })\n\n      await store.appendRunEvents('p1', runId, [\n        { kind: 'run_settled', outcome: 'completed', at: '2024-01-01T00:00:00.000Z' },\n      ])\n      const settled = await store.claimRun('p1', d1, runId)\n      expect(settled).toMatchObject({ ok: false, reason: 'run_already_settled' })\n    })\n\n    it('claimRun re-enters after an ABORTED or HALTED run, but not after a completed one', async () => {\n      // `aborted` and `halted` are STOPPING POINTS, not endings. The interruption taxonomy\n      // classifies a turn abort as resumable with the frontier intact at the same digest, so a\n      // store that treats every `run_settled` as terminal makes `resumeRunId` unusable for\n      // exactly the cases it exists to serve — which is what the reference store did, and what\n      // this case would have caught.\n      for (const outcome of ['aborted', 'halted'] as const) {\n        const store = await makeStore()\n        await store.createPlan(`resumable-${outcome}`)\n        const digest = await makeExecutable(store, `resumable-${outcome}`)\n\n        const started = await store.claimRun(`resumable-${outcome}`, digest)\n        const runId = (started as { runId: string }).runId\n        await store.appendRunEvents(`resumable-${outcome}`, runId, [\n          {\n            kind: 'run_interrupted',\n            cause: { kind: 'turn_abort' },\n            at: '2024-01-01T00:00:00.000Z',\n          },\n          { kind: 'run_settled', outcome, at: '2024-01-01T00:00:00.000Z' },\n        ])\n\n        const again = await store.claimRun(`resumable-${outcome}`, digest, runId)\n        expect(again).toMatchObject({ ok: true, resumed: true })\n      }\n    })\n\n    it('a CLONED plan can be frozen — every state fold carries provenance', async () => {\n      // A clone carries `PlanProvenance`, and provenance is DIGESTED. So a store whose\n      // `transition`/`readState` folds omit it computes a different digest than `freezePlan`\n      // does, the `expectedDigest` check fails, and the clone can never leave `editable`.\n      //\n      // That breaks the documented recovery path outright: `clonePlan` is what you do after a\n      // halting failure, and a clone that cannot be frozen cannot be re-approved or re-run. The\n      // reference store had exactly this bug — five folds omitted `record.provenance` while\n      // `readProvenance` supplied it everywhere else.\n      const store = await makeStore()\n      await store.createPlan('conf-clone-src')\n      await store.appendOps('conf-clone-src', [addNodeOp(entryNode('entry'), 1)])\n\n      const cloned = await store.clonePlan('conf-clone-src', 'conf-clone-dst')\n      expect(cloned).toMatchObject({ ok: true })\n\n      const provenance = await store.readProvenance('conf-clone-dst')\n      expect(provenance).toBeDefined()\n\n      // The digest the store reports must be the one a provenance-aware fold produces — that is\n      // what `freezePlan` computes and passes as `expectedDigest`.\n      const ops = await store.readOps('conf-clone-dst')\n      const expected = foldOps('conf-clone-dst', ops, provenance).view.digest\n      const state = await store.readState('conf-clone-dst')\n      expect(state.digest).toBe(expected)\n\n      // And the transition must actually commit at that digest.\n      const moved = await store.transition('conf-clone-dst', {\n        from: 'editable',\n        to: 'reviewable',\n        expectedDigest: expected,\n      })\n      expect(moved).toMatchObject({ ok: true })\n    })\n\n    // ── 11. claimRun preconditions ────────────────────────────────────────────\n    it('claimRun is refused with not_executable when not executable and digest_mismatch when the digest moved', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      const d1 = await appendNode(store, 'p1', entryNode('entry'), 1)\n\n      const notExecutable = await store.claimRun('p1', d1)\n      expect(notExecutable).toMatchObject({ ok: false, reason: 'not_executable' })\n\n      await makeExecutable(store, 'p1')\n      const moved = await store.claimRun('p1', 'stale-digest')\n      expect(moved).toMatchObject({ ok: false, reason: 'digest_mismatch' })\n    })\n\n    // ── 12. appendRunEvents is one batch ─────────────────────────────────────\n    it('appendRunEvents commits its array as one batch so all three events are read back', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      const d1 = await makeExecutable(store, 'p1')\n      const claimed = await store.claimRun('p1', d1)\n      const runId = (claimed as { runId: string }).runId\n\n      // The commit protocol depends on node_settled + every edge_taken + the new\n      // frontier_snapshot landing in a SINGLE commit — a store that commits them one at a time\n      // and could interleave is non-conforming.\n      const batch: RunEvent[] = [\n        { kind: 'run_started', runId, digest: d1, at: '2024-01-01T00:00:00.000Z' },\n        {\n          kind: 'node_entered',\n          frame: {\n            nodeId: 'entry',\n            kind: 'entry',\n            branchId: { segments: [] },\n            viaEdgeId: undefined,\n          },\n          at: '2024-01-01T00:00:00.000Z',\n        },\n        {\n          kind: 'node_settled',\n          frame: {\n            nodeId: 'entry',\n            kind: 'entry',\n            branchId: { segments: [] },\n            viaEdgeId: undefined,\n          },\n          outcome: {\n            status: 'ok',\n            output: { items: [{ json: { ok: true } }], branchId: { segments: [] } },\n          },\n          at: '2024-01-01T00:00:00.000Z',\n        },\n      ]\n      await store.appendRunEvents('p1', runId, batch)\n      const events = await store.readRunEvents('p1', runId)\n      expect(events).toHaveLength(3)\n      expect(events.map((e) => e.kind)).toEqual(['run_started', 'node_entered', 'node_settled'])\n    })\n\n    // ── 13. readOps revision prefix ───────────────────────────────────────────\n    it('readOps throughRevision serves a revision prefix and rejects a revision the log never reached', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      await appendNode(store, 'p1', entryNode('entry'), 1)\n      await appendNode(store, 'p1', entryNode('entry2'), 2)\n\n      const prefix = await store.readOps('p1', { throughRevision: 1 })\n      expect(prefix).toHaveLength(1)\n      expect(prefix[0].opId).toBe('op-1')\n\n      await expect(store.readOps('p1', { throughRevision: 99 })).rejects.toThrow()\n    })\n\n    // ── 14. clonePlan ─────────────────────────────────────────────────────────\n    it('clonePlan yields an editable, unapproved, run-less clone with parent provenance', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      const d1 = await appendNode(store, 'p1', entryNode('entry'), 1)\n\n      const cloned = await store.clonePlan('p1', 'p2')\n      expect(cloned).toMatchObject({ ok: true })\n\n      const state = await store.readState('p2')\n      expect(state.state).toBe('editable')\n      expect(await store.readApproval('p2')).toBeUndefined()\n      await expect(store.readRunEvents('p2')).rejects.toThrow()\n\n      const provenance = await store.readProvenance('p2')\n      expect(provenance).toMatchObject({\n        kind: 'clone',\n        parent: 'p1',\n        parentDigest: d1,\n        parentRevision: 1,\n      })\n\n      const missing = await store.clonePlan('no-such', 'p3')\n      expect(missing).toMatchObject({ ok: false, reason: 'source_missing' })\n    })\n\n    // ── 15. frontier_snapshot artifact handles round-trip ────────────────────\n    it('a round-tripped frontier_snapshot preserves artifact handles', async () => {\n      const store = await makeStore()\n      await store.createPlan('p1')\n      const d1 = await makeExecutable(store, 'p1')\n      const claimed = await store.claimRun('p1', d1)\n      const runId = (claimed as { runId: string }).runId\n\n      // A handle is a pointer, never bytes — the encoding is the store's business, so we assert\n      // the PROPERTY (the entry survives the round-trip) rather than any representation.\n      const artifact: SpooledArtifactLike = {\n        constructor: { toolMethods: [] },\n        marker: 'handle',\n      }\n      const artifacts: ArtifactTable = new Map([['entry:root', artifact]])\n      const frame: PendingFrame = {\n        frame: {\n          nodeId: 'entry',\n          kind: 'entry',\n          branchId: { segments: [] },\n          viaEdgeId: undefined,\n        },\n        outputs: new Map(),\n        artifacts,\n      }\n      const snapshot: RunEvent = {\n        kind: 'frontier_snapshot',\n        frames: [frame],\n        joins: [],\n        at: '2024-01-01T00:00:00.000Z',\n      }\n      await store.appendRunEvents('p1', runId, [snapshot])\n\n      const events = await store.readRunEvents('p1', runId)\n      const readBack = events.find((e) => e.kind === 'frontier_snapshot')\n      expect(readBack).toBeDefined()\n      const readFrame = (readBack as { frames: PendingFrame[] }).frames[0]\n      const entry = readFrame.artifacts.get('entry:root')\n      expect(entry).toBeDefined()\n      expect(isObject(entry)).toBe(true)\n    })\n  })\n  for (const fn of pending) {\n    await fn()\n  }\n}\n"],"mappings":"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"}