---
url: >-
  https://adk.nht.io/api/@nhtio/adk/batteries/orchestration/in_memory/classes/InMemoryPlanStore.md
description: 'The reference in-memory implementation of the [`PlanStore`](https://adk.nht.io/api/@nhtio/adk/batteries/orchestration/interfaces/PlanStore) contract.'
---

# Class: InMemoryPlanStore

Defined in: [src/batteries/orchestration/in\_memory.ts:66](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L66)

The reference in-memory implementation of the [PlanStore](../../interfaces/PlanStore.md) contract.

Every operation is asynchronous and returns a structured result rather than throwing for the
expected, precondition-style failures the contract names — so a caller can branch on the
outcome without exception handling. Lifecycle transitions and run claiming are atomic with
respect to the single-threaded event loop: a plan is mutated only through these methods, so no
interleaving can observe a half-applied change.

The store commits; it does not validate. Deciding whether a plan is well-formed, whether an
evaluator is wired, or whether a tool is on the allowlist is battery knowledge this class has
no access to, so those checks live upstream and this class only records the outcome.

## Implements

* [`PlanStore`](../../interfaces/PlanStore.md)

## Constructors

### Constructor

```ts
new InMemoryPlanStore(): InMemoryPlanStore;
```

#### Returns

`InMemoryPlanStore`

## Methods

### appendOps()

```ts
appendOps(
   planId: string,
   ops: PlanOp[],
expectedRevision?: number): Promise<AppendResult>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:185](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L185)

Append ops to a plan's log.

The plan must be `editable`; this is checked in the same operation as the append, which is
what keeps `reviewable` and `executable` plans frozen at the only boundary that can enforce
it. Without the check, ops could change a frozen plan's content and digest while its stored
state stayed frozen, and an executable plan's approval would remain bound to a prior digest —
a plan executable with content nobody approved.

#### Parameters

| Parameter           | Type                                             | Description                                                                                                                            |
| ------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| `planId`            | `string`                                         | The plan to append to.                                                                                                                 |
| `ops`               | [`PlanOp`](../../types/type-aliases/PlanOp.md)\[] | The ops to append.                                                                                                                     |
| `expectedRevision?` | `number`                                         | If given, the log must still be at this revision (optimistic concurrency for a single author); omit it for the multi-writer CRDT case. |

#### Returns

`Promise`<[`AppendResult`](../../type-aliases/AppendResult.md)>

A success result carrying the new revision and digest, or `not_editable` /
`revision_moved` with the actual state.

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`appendOps`](../../interfaces/PlanStore.md#appendops)

***

### appendRunEvents()

```ts
appendRunEvents(
   planId: string,
   runId: string,
events: RunEvent[]): Promise<void>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:424](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L424)

Append a batch of run events atomically.

The whole array is committed as one batch, so the commit protocol can land `node_settled`,
every `edge_taken`, and the new `frontier_snapshot` in a single commit.

A run is marked TERMINALLY settled only by `run_settled{outcome: 'completed'}`. `aborted` and
`halted` are STOPPING POINTS, not endings: the interruption taxonomy classifies a turn abort
as resumable with the frontier intact and the same digest, and a halted run is resumable once
whatever halted it is addressed. Marking those terminal made `claimRun(resumeRunId)` answer
`run_already_settled` and `resumeRunId` unusable for the exact cases it exists to serve.

A run that later resumes and completes is settled then, which is the point at which no
further work can follow.

#### Parameters

| Parameter | Type                                                 | Description                  |
| --------- | ---------------------------------------------------- | ---------------------------- |
| `planId`  | `string`                                             | The plan the run belongs to. |
| `runId`   | `string`                                             | The run to append to.        |
| `events`  | [`RunEvent`](../../types/type-aliases/RunEvent.md)\[] | The events to append.        |

#### Returns

`Promise`<`void`>

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`appendRunEvents`](../../interfaces/PlanStore.md#appendrunevents)

***

### claimRun()

```ts
claimRun(
   planId: string,
   expectedDigest: string,
resumeRunId?: string): Promise<ClaimRunResult>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:370](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L370)

Claim a run for a plan.

The plan must be `executable` at `expectedDigest`. Without a resume id, a run is started only
if none was ever claimed; with a resume id, that specific run is re-entered only if it exists
and is not settled. This is what enforces one plan, at most one run, ever.

#### Parameters

| Parameter        | Type     | Description                     |
| ---------------- | -------- | ------------------------------- |
| `planId`         | `string` | The plan to run.                |
| `expectedDigest` | `string` | The digest the plan must be at. |
| `resumeRunId?`   | `string` | Optional id of a run to resume. |

#### Returns

`Promise`<[`ClaimRunResult`](../../type-aliases/ClaimRunResult.md)>

A success result carrying the run id and whether it was resumed, or a structured
failure.

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`claimRun`](../../interfaces/PlanStore.md#claimrun)

***

### clonePlan()

```ts
clonePlan(
   sourcePlanId: string,
   newPlanId: string,
atRevision?: number): Promise<CreateResult>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:122](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L122)

Clone an existing plan into a new id, seeded with the source's folded state at a given
revision.

The clone is minted in `editable` and inherits no approval and no run — it is cold by
construction. Its provenance records the parent, the parent's digest, the parent's revision,
and the node ids that had settled `ok` when the clone was taken (or `[]` if the source never
ran). The operation is atomic: either the clone exists complete or not at all.

#### Parameters

| Parameter      | Type     | Description                                                                 |
| -------------- | -------- | --------------------------------------------------------------------------- |
| `sourcePlanId` | `string` | The plan to clone from.                                                     |
| `newPlanId`    | `string` | The id for the new plan.                                                    |
| `atRevision?`  | `number` | The source revision to clone at; defaults to the source's current revision. |

#### Returns

`Promise`<[`CreateResult`](../../type-aliases/CreateResult.md)>

A success result carrying the clone's revision and digest, or `source_missing` /
`revision_missing` / `duplicate_id`.

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`clonePlan`](../../interfaces/PlanStore.md#cloneplan)

***

### createPlan()

```ts
createPlan(planId: string, meta?: {
  label?: string;
  provenance?: InstantiatedFrom;
}): Promise<CreateResult>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:81](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L81)

Mint a new plan in the `editable` state at revision 0.

The op log is genuinely empty: revision 0 is the fold seed, not an implied op, so `readOps`
returns `[]` and the first authoring op produces revision 1. Instantiation lineage is
persisted when supplied.

#### Parameters

| Parameter          | Type                                                                                                       | Description                                         |
| ------------------ | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| `planId`           | `string`                                                                                                   | The id of the new plan.                             |
| `meta?`            | { `label?`: `string`; `provenance?`: [`InstantiatedFrom`](../../types/interfaces/InstantiatedFrom.md); } | Optional label and instantiation lineage to attach. |
| `meta.label?`      | `string`                                                                                                   | -                                                   |
| `meta.provenance?` | [`InstantiatedFrom`](../../types/interfaces/InstantiatedFrom.md)                                           | -                                                   |

#### Returns

`Promise`<[`CreateResult`](../../type-aliases/CreateResult.md)>

A success result carrying the new plan's revision and digest, or `duplicate_id` if
the id is already taken.

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`createPlan`](../../interfaces/PlanStore.md#createplan)

***

### list()

```ts
list(filter?: {
  state?: PlanState;
}): Promise<PlanSummary[]>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:292](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L292)

List plans, optionally filtered by lifecycle state.

#### Parameters

| Parameter       | Type                                                                  | Description            |
| --------------- | --------------------------------------------------------------------- | ---------------------- |
| `filter?`       | { `state?`: [`PlanState`](../../types/type-aliases/PlanState.md); } | Optional state filter. |
| `filter.state?` | [`PlanState`](../../types/type-aliases/PlanState.md)                  | -                      |

#### Returns

`Promise`<[`PlanSummary`](../../types/interfaces/PlanSummary.md)\[]>

A summary of each matching plan.

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`list`](../../interfaces/PlanStore.md#list)

***

### readApproval()

```ts
readApproval(planId: string): Promise<
  | ApprovalRecord
| undefined>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:282](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L282)

Read the approval record bound to a plan's current digest.

#### Parameters

| Parameter | Type     | Description            |
| --------- | -------- | ---------------------- |
| `planId`  | `string` | The plan to read from. |

#### Returns

`Promise`<
| [`ApprovalRecord`](../../types/interfaces/ApprovalRecord.md)
| `undefined`>

The approval, or `undefined` if the plan has not been approved.

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`readApproval`](../../interfaces/PlanStore.md#readapproval)

***

### readOps()

```ts
readOps(planId: string, opts?: {
  sinceLamport?: number;
  throughRevision?: number;
}): Promise<PlanOp[]>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:224](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L224)

Read the ops of a plan's log.

`sinceLamport` filters by clock; `throughRevision` bounds the result to a revision prefix
(the first N ops in sorted order), which is what a historical view needs. A revision the log
never reached is rejected rather than silently returning everything.

#### Parameters

| Parameter               | Type                                                           | Description                 |
| ----------------------- | -------------------------------------------------------------- | --------------------------- |
| `planId`                | `string`                                                       | The plan to read from.      |
| `opts?`                 | { `sinceLamport?`: `number`; `throughRevision?`: `number`; } | Optional filtering options. |
| `opts.sinceLamport?`    | `number`                                                       | -                           |
| `opts.throughRevision?` | `number`                                                       | -                           |

#### Returns

`Promise`<[`PlanOp`](../../types/type-aliases/PlanOp.md)\[]>

The matching ops.

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`readOps`](../../interfaces/PlanStore.md#readops)

***

### readProvenance()

```ts
readProvenance(planId: string): Promise<
  | PlanProvenance
| undefined>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:254](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L254)

Read the provenance of a plan.

#### Parameters

| Parameter | Type     | Description            |
| --------- | -------- | ---------------------- |
| `planId`  | `string` | The plan to read from. |

#### Returns

`Promise`<
| [`PlanProvenance`](../../types/type-aliases/PlanProvenance.md)
| `undefined`>

The provenance, or `undefined` for a plan that is not a clone or was not
instantiated.

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`readProvenance`](../../interfaces/PlanStore.md#readprovenance)

***

### readRunEvents()

```ts
readRunEvents(planId: string, runId?: string): Promise<RunEvent[]>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:446](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L446)

Read the events of a run.

#### Parameters

| Parameter | Type     | Description                                         |
| --------- | -------- | --------------------------------------------------- |
| `planId`  | `string` | The plan the run belongs to.                        |
| `runId?`  | `string` | The run to read; omitted reads the plan's only run. |

#### Returns

`Promise`<[`RunEvent`](../../types/type-aliases/RunEvent.md)\[]>

The events.

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`readRunEvents`](../../interfaces/PlanStore.md#readrunevents)

***

### readState()

```ts
readState(planId: string): Promise<{
  digest: string;
  revision: number;
  state: PlanState;
}>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:264](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L264)

Read the current lifecycle state, digest, and revision of a plan.

#### Parameters

| Parameter | Type     | Description            |
| --------- | -------- | ---------------------- |
| `planId`  | `string` | The plan to read from. |

#### Returns

`Promise`<{
`digest`: `string`;
`revision`: `number`;
`state`: [`PlanState`](../../types/type-aliases/PlanState.md);
}>

The state, digest, and revision.

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`readState`](../../interfaces/PlanStore.md#readstate)

***

### transition()

```ts
transition(planId: string, t: TransitionRequest): Promise<TransitionResult>;
```

Defined in: [src/batteries/orchestration/in\_memory.ts:326](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/in_memory.ts#L326)

Perform the single atomic lifecycle transition.

The plan must be in the state `t.from` implies and at `t.expectedDigest`; the pair must be a
legal transition. For `reviewable` → `executable`, the approval is persisted in the same
operation. No policy is evaluated here — the battery validates, the store commits.

#### Parameters

| Parameter | Type                                                           | Description             |
| --------- | -------------------------------------------------------------- | ----------------------- |
| `planId`  | `string`                                                       | The plan to transition. |
| `t`       | [`TransitionRequest`](../../type-aliases/TransitionRequest.md) | The transition request. |

#### Returns

`Promise`<[`TransitionResult`](../../type-aliases/TransitionResult.md)>

A success result carrying the new revision, or `state_mismatch` / `digest_mismatch`
with the actual state and digest, or `illegal_transition` for a request the type system did
not police.

#### Implementation of

[`PlanStore`](../../interfaces/PlanStore.md).[`transition`](../../interfaces/PlanStore.md#transition)
