{"version":3,"file":"in_memory.mjs","names":["#plans"],"sources":["../../../src/batteries/orchestration/in_memory.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/orchestration/in_memory\n */\n\nimport { foldOps } from './ops'\nimport type {\n  PlanStore,\n  CreateResult,\n  AppendResult,\n  TransitionRequest,\n  TransitionResult,\n  ClaimRunResult,\n} from './store'\nimport type {\n  PlanOp,\n  PlanState,\n  PlanSummary,\n  PlanProvenance,\n  InstantiatedFrom,\n  ApprovalRecord,\n  RunEvent,\n} from './types'\n\n/**\n * A plan held entirely in memory.\n *\n * The op log is the single source of truth for content: revision and digest are always derived\n * from it by folding, never stored alongside it, so they cannot drift from what the log actually\n * contains. Lifecycle state, approval, provenance and the run are the parts that are not `PlanOp`s\n * and therefore cannot be folded, so they live here as first-class fields.\n */\ninterface PlanRecord {\n  /** The ordered authoring log. */\n  ops: PlanOp[]\n  /** The lifecycle state of the plan. */\n  state: PlanState\n  /** The approval record, present only once the plan has been approved. */\n  approval?: ApprovalRecord\n  /** Provenance, present only for plans that were cloned or instantiated. */\n  provenance?: PlanProvenance\n  /** A human label for the plan. */\n  label?: string\n  /** The last time the plan was touched, as an ISO timestamp. */\n  updatedAt: string\n  /** The run bound to this plan, if one has ever been claimed. */\n  run?: {\n    runId: string\n    events: RunEvent[]\n    settled: boolean\n  }\n}\n\n/**\n * The reference in-memory implementation of the {@link PlanStore} contract.\n *\n * Every operation is asynchronous and returns a structured result rather than throwing for the\n * expected, precondition-style failures the contract names — so a caller can branch on the\n * outcome without exception handling. Lifecycle transitions and run claiming are atomic with\n * respect to the single-threaded event loop: a plan is mutated only through these methods, so no\n * interleaving can observe a half-applied change.\n *\n * The store commits; it does not validate. Deciding whether a plan is well-formed, whether an\n * evaluator is wired, or whether a tool is on the allowlist is battery knowledge this class has\n * no access to, so those checks live upstream and this class only records the outcome.\n */\nexport class InMemoryPlanStore implements PlanStore {\n  readonly #plans = new Map<string, PlanRecord>()\n\n  /**\n   * Mint a new plan in the `editable` state at revision 0.\n   *\n   * The op log is genuinely empty: revision 0 is the fold seed, not an implied op, so `readOps`\n   * returns `[]` and the first authoring op produces revision 1. Instantiation lineage is\n   * persisted when supplied.\n   *\n   * @param planId - The id of the new plan.\n   * @param meta - Optional label and instantiation lineage to attach.\n   * @returns A success result carrying the new plan's revision and digest, or `duplicate_id` if\n   *   the id is already taken.\n   */\n  async createPlan(\n    planId: string,\n    meta?: { label?: string; provenance?: InstantiatedFrom }\n  ): Promise<CreateResult> {\n    if (this.#plans.has(planId)) {\n      return { ok: false, reason: 'duplicate_id' }\n    }\n    const provenance: PlanProvenance | undefined = meta?.provenance\n      ? { kind: 'template', ...meta.provenance }\n      : undefined\n    this.#plans.set(planId, {\n      ops: [],\n      state: 'editable',\n      label: meta?.label,\n      provenance,\n      updatedAt: new Date().toISOString(),\n    })\n    return {\n      ok: true,\n      planId,\n      revision: 0,\n      digest: foldOps(planId, []).view.digest,\n    }\n  }\n\n  /**\n   * Clone an existing plan into a new id, seeded with the source's folded state at a given\n   * revision.\n   *\n   * The clone is minted in `editable` and inherits no approval and no run — it is cold by\n   * construction. Its provenance records the parent, the parent's digest, the parent's revision,\n   * and the node ids that had settled `ok` when the clone was taken (or `[]` if the source never\n   * ran). The operation is atomic: either the clone exists complete or not at all.\n   *\n   * @param sourcePlanId - The plan to clone from.\n   * @param newPlanId - The id for the new plan.\n   * @param atRevision - The source revision to clone at; defaults to the source's current\n   *   revision.\n   * @returns A success result carrying the clone's revision and digest, or `source_missing` /\n   *   `revision_missing` / `duplicate_id`.\n   */\n  async clonePlan(\n    sourcePlanId: string,\n    newPlanId: string,\n    atRevision?: number\n  ): Promise<CreateResult> {\n    const source = this.#plans.get(sourcePlanId)\n    if (!source) {\n      return { ok: false, reason: 'source_missing' }\n    }\n    if (this.#plans.has(newPlanId)) {\n      return { ok: false, reason: 'duplicate_id' }\n    }\n    const targetRevision = atRevision ?? source.ops.length\n    if (targetRevision < 0 || targetRevision > source.ops.length) {\n      return { ok: false, reason: 'revision_missing' }\n    }\n    const prefix = source.ops.slice(0, targetRevision)\n    const completedAtClone: string[] = []\n    if (source.run) {\n      for (const event of source.run.events) {\n        if (event.kind === 'node_settled' && event.outcome.status === 'ok') {\n          completedAtClone.push(event.frame.nodeId)\n        }\n      }\n    }\n    const provenance: PlanProvenance = {\n      kind: 'clone',\n      parent: sourcePlanId,\n      parentDigest: foldOps(sourcePlanId, prefix).view.digest,\n      parentRevision: targetRevision,\n      completedAtClone,\n    }\n    this.#plans.set(newPlanId, {\n      ops: prefix,\n      state: 'editable',\n      provenance,\n      label: source.label,\n      updatedAt: new Date().toISOString(),\n    })\n    return {\n      ok: true,\n      planId: newPlanId,\n      revision: targetRevision,\n      digest: foldOps(newPlanId, prefix).view.digest,\n    }\n  }\n\n  /**\n   * Append ops to a plan's log.\n   *\n   * The plan must be `editable`; this is checked in the same operation as the append, which is\n   * what keeps `reviewable` and `executable` plans frozen at the only boundary that can enforce\n   * it. Without the check, ops could change a frozen plan's content and digest while its stored\n   * state stayed frozen, and an executable plan's approval would remain bound to a prior digest —\n   * a plan executable with content nobody approved.\n   *\n   * @param planId - The plan to append to.\n   * @param ops - The ops to append.\n   * @param expectedRevision - If given, the log must still be at this revision (optimistic\n   *   concurrency for a single author); omit it for the multi-writer CRDT case.\n   * @returns A success result carrying the new revision and digest, or `not_editable` /\n   *   `revision_moved` with the actual state.\n   */\n  async appendOps(planId: string, ops: PlanOp[], expectedRevision?: number): Promise<AppendResult> {\n    const record = this.#plans.get(planId)\n    if (!record) {\n      throw new Error(`appendOps: no plan \"${planId}\"`)\n    }\n    if (record.state !== 'editable') {\n      return {\n        ok: false,\n        reason: 'not_editable',\n        actual: { state: record.state, revision: record.ops.length },\n      }\n    }\n    if (expectedRevision !== undefined && record.ops.length !== expectedRevision) {\n      return {\n        ok: false,\n        reason: 'revision_moved',\n        actual: { state: record.state, revision: record.ops.length },\n      }\n    }\n    record.ops.push(...ops)\n    record.updatedAt = new Date().toISOString()\n    return {\n      ok: true,\n      revision: record.ops.length,\n      digest: foldOps(planId, record.ops, record.provenance).view.digest,\n    }\n  }\n\n  /**\n   * Read the ops of a plan's log.\n   *\n   * `sinceLamport` filters by clock; `throughRevision` bounds the result to a revision prefix\n   * (the first N ops in sorted order), which is what a historical view needs. A revision the log\n   * never reached is rejected rather than silently returning everything.\n   *\n   * @param planId - The plan to read from.\n   * @param opts - Optional filtering options.\n   * @returns The matching ops.\n   */\n  async readOps(\n    planId: string,\n    opts?: { sinceLamport?: number; throughRevision?: number }\n  ): Promise<PlanOp[]> {\n    const record = this.#plans.get(planId)\n    if (!record) {\n      throw new Error(`readOps: no plan \"${planId}\"`)\n    }\n    if (opts?.throughRevision !== undefined) {\n      if (opts.throughRevision < 0 || opts.throughRevision > record.ops.length) {\n        throw new Error(`readOps: plan \"${planId}\" never reached revision ${opts.throughRevision}`)\n      }\n    }\n    let ops = record.ops\n    if (opts?.throughRevision !== undefined) {\n      ops = ops.slice(0, opts.throughRevision)\n    }\n    if (opts?.sinceLamport !== undefined) {\n      ops = ops.filter((op) => op.lamport > (opts.sinceLamport as number))\n    }\n    return ops\n  }\n\n  /**\n   * Read the provenance of a plan.\n   *\n   * @param planId - The plan to read from.\n   * @returns The provenance, or `undefined` for a plan that is not a clone or was not\n   *   instantiated.\n   */\n  async readProvenance(planId: string): Promise<PlanProvenance | undefined> {\n    return this.#plans.get(planId)?.provenance\n  }\n\n  /**\n   * Read the current lifecycle state, digest, and revision of a plan.\n   *\n   * @param planId - The plan to read from.\n   * @returns The state, digest, and revision.\n   */\n  async readState(planId: string): Promise<{ state: PlanState; digest: string; revision: number }> {\n    const record = this.#plans.get(planId)\n    if (!record) {\n      throw new Error(`readState: no plan \"${planId}\"`)\n    }\n    return {\n      state: record.state,\n      digest: foldOps(planId, record.ops, record.provenance).view.digest,\n      revision: record.ops.length,\n    }\n  }\n\n  /**\n   * Read the approval record bound to a plan's current digest.\n   *\n   * @param planId - The plan to read from.\n   * @returns The approval, or `undefined` if the plan has not been approved.\n   */\n  async readApproval(planId: string): Promise<ApprovalRecord | undefined> {\n    return this.#plans.get(planId)?.approval\n  }\n\n  /**\n   * List plans, optionally filtered by lifecycle state.\n   *\n   * @param filter - Optional state filter.\n   * @returns A summary of each matching plan.\n   */\n  async list(filter?: { state?: PlanState }): Promise<PlanSummary[]> {\n    const summaries: PlanSummary[] = []\n    for (const [planId, record] of this.#plans) {\n      if (filter?.state && record.state !== filter.state) {\n        continue\n      }\n      const folded = foldOps(planId, record.ops, record.provenance).view\n      summaries.push({\n        planId,\n        state: record.state,\n        digest: folded.digest,\n        revision: record.ops.length,\n        nodeCount: folded.nodes.length,\n        label: record.label,\n        provenance: record.provenance,\n        updatedAt: record.updatedAt,\n      })\n    }\n    return summaries\n  }\n\n  /**\n   * Perform the single atomic lifecycle transition.\n   *\n   * The plan must be in the state `t.from` implies and at `t.expectedDigest`; the pair must be a\n   * legal transition. For `reviewable` → `executable`, the approval is persisted in the same\n   * operation. No policy is evaluated here — the battery validates, the store commits.\n   *\n   * @param planId - The plan to transition.\n   * @param t - The transition request.\n   * @returns A success result carrying the new revision, or `state_mismatch` / `digest_mismatch`\n   *   with the actual state and digest, or `illegal_transition` for a request the type system did\n   *   not police.\n   */\n  async transition(planId: string, t: TransitionRequest): Promise<TransitionResult> {\n    const record = this.#plans.get(planId)\n    if (!record) {\n      throw new Error(`transition: no plan \"${planId}\"`)\n    }\n    const folded = foldOps(planId, record.ops, record.provenance).view\n    if (record.state !== t.from) {\n      return {\n        ok: false,\n        reason: 'state_mismatch',\n        actual: { state: record.state, digest: folded.digest },\n      }\n    }\n    if (folded.digest !== t.expectedDigest) {\n      return {\n        ok: false,\n        reason: 'digest_mismatch',\n        actual: { state: record.state, digest: folded.digest },\n      }\n    }\n    if (!isLegalTransition(t.from, t.to)) {\n      return { ok: false, reason: 'illegal_transition', from: t.from, to: t.to }\n    }\n    record.state = t.to\n    if (t.from === 'reviewable' && t.to === 'executable') {\n      record.approval = t.approval\n    }\n    record.updatedAt = new Date().toISOString()\n    return { ok: true, revision: record.ops.length }\n  }\n\n  /**\n   * Claim a run for a plan.\n   *\n   * The plan must be `executable` at `expectedDigest`. Without a resume id, a run is started only\n   * if none was ever claimed; with a resume id, that specific run is re-entered only if it exists\n   * and is not settled. This is what enforces one plan, at most one run, ever.\n   *\n   * @param planId - The plan to run.\n   * @param expectedDigest - The digest the plan must be at.\n   * @param resumeRunId - Optional id of a run to resume.\n   * @returns A success result carrying the run id and whether it was resumed, or a structured\n   *   failure.\n   */\n  async claimRun(\n    planId: string,\n    expectedDigest: string,\n    resumeRunId?: string\n  ): Promise<ClaimRunResult> {\n    const record = this.#plans.get(planId)\n    if (!record) {\n      throw new Error(`claimRun: no plan \"${planId}\"`)\n    }\n    const folded = foldOps(planId, record.ops, record.provenance).view\n    if (record.state !== 'executable') {\n      return { ok: false, reason: 'not_executable' }\n    }\n    if (folded.digest !== expectedDigest) {\n      return { ok: false, reason: 'digest_mismatch' }\n    }\n    if (resumeRunId === undefined) {\n      if (record.run) {\n        return { ok: false, reason: 'run_already_claimed', existingRunId: record.run.runId }\n      }\n      const runId = crypto.randomUUID()\n      record.run = { runId, events: [], settled: false }\n      record.updatedAt = new Date().toISOString()\n      return { ok: true, runId, resumed: false }\n    }\n    if (!record.run || record.run.runId !== resumeRunId) {\n      return { ok: false, reason: 'run_not_found' }\n    }\n    if (record.run.settled) {\n      return { ok: false, reason: 'run_already_settled' }\n    }\n    record.updatedAt = new Date().toISOString()\n    return { ok: true, runId: resumeRunId, resumed: true }\n  }\n\n  /**\n   * Append a batch of run events atomically.\n   *\n   * The whole array is committed as one batch, so the commit protocol can land `node_settled`,\n   * every `edge_taken`, and the new `frontier_snapshot` in a single commit.\n   *\n   * A run is marked TERMINALLY settled only by `run_settled{outcome: 'completed'}`. `aborted` and\n   * `halted` are STOPPING POINTS, not endings: the interruption taxonomy classifies a turn abort\n   * as resumable with the frontier intact and the same digest, and a halted run is resumable once\n   * whatever halted it is addressed. Marking those terminal made `claimRun(resumeRunId)` answer\n   * `run_already_settled` and `resumeRunId` unusable for the exact cases it exists to serve.\n   *\n   * A run that later resumes and completes is settled then, which is the point at which no\n   * further work can follow.\n   *\n   * @param planId - The plan the run belongs to.\n   * @param runId - The run to append to.\n   * @param events - The events to append.\n   */\n  async appendRunEvents(planId: string, runId: string, events: RunEvent[]): Promise<void> {\n    const record = this.#plans.get(planId)\n    if (!record) {\n      throw new Error(`appendRunEvents: no plan \"${planId}\"`)\n    }\n    if (!record.run || record.run.runId !== runId) {\n      throw new Error(`appendRunEvents: no run \"${runId}\" on plan \"${planId}\"`)\n    }\n    record.run.events.push(...events)\n    if (events.some((e) => e.kind === 'run_settled' && e.outcome === 'completed')) {\n      record.run.settled = true\n    }\n    record.updatedAt = new Date().toISOString()\n  }\n\n  /**\n   * Read the events of a run.\n   *\n   * @param planId - The plan the run belongs to.\n   * @param runId - The run to read; omitted reads the plan's only run.\n   * @returns The events.\n   */\n  async readRunEvents(planId: string, runId?: string): Promise<RunEvent[]> {\n    const record = this.#plans.get(planId)\n    if (!record) {\n      throw new Error(`readRunEvents: no plan \"${planId}\"`)\n    }\n    if (!record.run) {\n      throw new Error(`readRunEvents: no run on plan \"${planId}\"`)\n    }\n    if (runId !== undefined && record.run.runId !== runId) {\n      throw new Error(`readRunEvents: no run \"${runId}\" on plan \"${planId}\"`)\n    }\n    return record.run.events\n  }\n}\n\n/**\n * Whether a lifecycle transition is legal.\n *\n * @param from - The current state.\n * @param to - The requested state.\n * @returns True if the pair is a legal transition.\n */\nfunction isLegalTransition(from: PlanState, to: PlanState): boolean {\n  switch (from) {\n    case 'editable':\n      return to === 'reviewable'\n    case 'reviewable':\n      return to === 'executable' || to === 'editable'\n    case 'executable':\n      return to === 'reviewable'\n    default:\n      return false\n  }\n}\n"],"mappings":"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"}