Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 29 additions & 52 deletions typescript/examples/checkpoint_continuation/README.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,53 @@
# Checkpoint continuation
# State persistence

Restoring a saved checkpoint changes whether a fresh host process can resume
and apply a pending itinerary change. This example shows checkpoint
continuation in a generic TypeScript travel-booking flow.
Persisting authoritative compiler state lets a fresh host process recover the
same premise and policy decisions without recreating them from model output or
conversation history. This example shows state persistence in a deterministic
TypeScript travel-booking flow.

## Domain

The domain is a small travel-booking change flow.

The user requests a change from the current itinerary to a new itinerary.
That change requires confirmation before the host applies it.
The host starts with a booking on `boston_trip`. The user selects
`chicago_trip`, Context Compiler records that selection in authoritative state,
and the host later applies the booking change from a restored engine.

## Runtime

This is a generic TypeScript example.

It does not call an LLM.

It does not use directive drafter.
This example does not call an LLM or use Directive Drafter.

## What Context Compiler owns

Context Compiler owns:

- authoritative policy state
- the pending confirmation continuation state
- the checkpoint that captures both

In this example, the pending checkpoint state is what makes the resumed
confirmation meaningful.

Restoring authoritative state alone is not enough to resume the pending change.
- authoritative policy state;
- serialization through `export_json()`;
- restoration through `import_json()`.

## What the host owns

The host owns:

- the booking record
- checkpoint persistence
- request/process boundaries
- the runtime behavior that actually applies the itinerary change

The host reads authoritative Context Compiler state after confirmation and
decides whether to apply the booking change.

## Why this is not prompt reinjection
- the booking record;
- persisted state storage;
- the process boundary;
- runtime behavior that applies the itinerary change.

This example does not re-send hidden instructions to a model.

The observable behavior change is host-side: the booking record changes only
after a restored engine resumes the pending confirmation and authoritative
state changes.
The host reads restored authoritative policy state before applying the booking
change. Context Compiler remains the sole authority over premise and policy
state.

## Example behavior

1. The host starts with a booking on `boston_trip`.
2. The user initiates a switch to `chicago_trip`.
3. Context Compiler enters a pending confirmation state.
4. The host exports and persists the checkpoint.
5. A fresh host process restores that checkpoint into a new engine.
6. If the user confirms, the host applies the itinerary change.
7. If the user rejects or sends unrelated text, the booking remains unchanged.
1. The host submits `use chicago_trip`.
2. Context Compiler updates authoritative state.
3. The host persists that state JSON.
4. A fresh engine restores the saved JSON.
5. The host reads the restored `use` policy and applies the booking change from
`boston_trip` to `chicago_trip`.

This example does not implement pending clarification, confirmation,
continuation, or resume semantics. The observable effect comes directly from
restored authoritative state.

## Install

Expand All @@ -77,13 +64,3 @@ npm run build
npm run typecheck
npm test
```

## Related integrations

The generic example teaches checkpoint continuation without requiring a
framework.

Related runtime surfaces:

- [typescript/starter_apps/node/README.md](../../starter_apps/node/README.md)
- [typescript/starter_apps/nextjs/README.md](../../starter_apps/nextjs/README.md)
8 changes: 4 additions & 4 deletions typescript/examples/checkpoint_continuation/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion typescript/examples/checkpoint_continuation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"example": "node dist/src/index.js"
},
"dependencies": {
"@rlippmann/context-compiler": "^0.8.2"
"@rlippmann/context-compiler": "0.9.0-dev.0"
},
"devDependencies": {
"@types/node": "^24.10.0",
Expand Down
35 changes: 35 additions & 0 deletions typescript/examples/checkpoint_continuation/src/compiler-state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Engine, type Decision } from "@rlippmann/context-compiler";

export type CompilerState = {
premise: string | null;
policies: Record<string, "use" | "prohibit">;
version: 2;
};

export function snapshotState(engine: Engine): CompilerState {
return { premise: engine.premise, policies: engine.policies, version: 2 };
}

export function policyItems(
state: CompilerState,
policy?: "use" | "prohibit"
): string[] {
return Object.entries(state.policies)
.filter(([, value]) => policy === undefined || value === policy)
.map(([item]) => item)
.sort();
}

export function premiseValue(state: CompilerState): string | null {
return state.premise;
}

export function engineFromState(state: CompilerState): Engine {
const engine = new Engine();
engine.import_json(JSON.stringify(state));
return engine;
}

export function decisionMessage(decision: Decision): string | null {
return decision.kind === "error" ? decision.message : null;
}
Loading