Repository navigation
[EPIC-D][LOU-D45.1] Agent Forge time-travel API: checkpoint history, fork from a step, compare trajectories - #112
Merged
Merged
Conversation
…pare routes (LOU-D45.1)
- FileCheckpointStore keeps the bounded per-session history() ring with
the same semantics as LocalStorageCheckpointStore (historyLimit,
delete({ keepHistory })); the SDK's history contract suite moves to a
shared fixture and runs against it too.
- RunManager.history/fork/compare and the routes GET /runs/:id/history,
POST /runs/:id/fork (validated { fromStep, patch? }, started through the
registry's run lifecycle and WS stream) and GET /runs/compare?a=&b=.
- Fix: chatReconcile compiles against multimodal Message.content (LOU-V11)
by flattening it with textOf(); server tsconfig adds the DOM lib like the
SDK's own, since server tests now type-check SDK sources.
- docs/agent-forge.md "Time travel", CHANGELOG, llms files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bY29ibQgv3MDdjAbUT4YR
…ws CheckpointStore.history (LOU-D45.1) parseForkRequest() checks each patch field from a Map of validators, which keeps it under fallow's complexity threshold, and CheckpointStore.history joins save/load/delete as an interface member fallow treats as used (FileCheckpointStore.history is only called through the interface). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bY29ibQgv3MDdjAbUT4YR
4 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
First half of LOU-D45 (Agent Forge time travel). It is split to stay within the ~200-line budget. The whole ticket is about 390 code lines, not counting comments. This PR has the server and store half, at 192 code lines. The client half (History tab) is ready on
lou-d45.2-forge-history-panel, stacked on this branch, and will be opened once this merges.FileCheckpointStorenow implementshistory(). It is a bounded per-session ring with the same helpers and semantics asLocalStorageCheckpointStore:historyLimit(default 50,0keeps none) anddelete({ keepHistory }). The ring is stored at.loushy/agents/<agentId>/checkpoint-history/<sessionId>.json. This closes the Forge part of LOU-D43.2.CheckpointStore.historycontract suite moves intosrc/execution/__fixtures__/checkpointHistoryContract.tsasdescribeCheckpointHistoryContract(name, factory). The SDK test runs it for its 3 stores, unchanged with 33 tests, and Forge runs it againstFileCheckpointStore. This is test-only code undersrc/; no SDK source changed.RunManager):history(runId)returns one row per step of the latest execution: the newest checkpoint of each step, with status, savedAt, finish reason, tool calls with results, and the tokens and cost of that step's model call.fork(runId, fromStep, patch)callsAgentExecutor.fork()and then starts the fork through the registry's ownlaunch(), using the source run's spec. The fork therefore gets the same lifecycle, status, WS stream, chat and approvals as any run.compare(a, b)runscompareTrajectories()on the two latest checkpoints.GET /runs/:id/history: 404 when the run has no history.POST /runs/:id/forkwith body{ fromStep, patch?: { toolResult?, appendInput?, businessState? } }: validated (400 for bad input, including unknown patch keys). An unknown tool call id returns 400, and an unknown run or step returns 404. Success is 202{ runId, fromStep, status }.GET /runs/compare?a=&b=: 400 for invalid ids, 404 when a run has no checkpoint./runs/:iduses the same path-traversal id guard as/agents/:id, and the SPA fallback leaves/runsalone.shared/wireTypes.ts:RunHistoryStep,RunHistoryPayload,ForkRunRequest,ForkRunResponse,RunComparisonPayload.typecheck:serverwas failing onmainsince LOU-V11, becauseChatMessage.contentis a string andMessage.contentcan now hold parts.chatReconcile.tsnow flattens content withtextOf().DOMlib, as the SDK's own tsconfig has. Server tests now type-check SDK sources through the shared contract..fallowrc.jsonlistshistoryas a usedCheckpointStoremember. It is only called through the interface.Why
Third differentiator in AUDIT.md section 7 (Agent Forge time-travel). D43 (history) and D44 (fork,
compareTrajectories) gave the SDK the primitives. Forge's file store kept no history, so a Forge run could not be forked, and the server had no API for it.Acceptance criteria
FileCheckpointStoreimplementshistory()with the same bounded ring semantics asLocalStorageCheckpointStore, checked by the shared SDK contract suite.GET /runs/:id/historyreturns steps with status, savedAt, tokens and cost per step when known, plus finish reason and tool calls.POST /runs/:id/forktakes body{ fromStep, patch?: { toolResult?, appendInput?, businessState? } }, validates it, returns the new run id and starts the fork through the registry's run lifecycle and WS events.GET /runs/compare?a=&b=returnscompareTrajectories, with validated input.server/__tests__/timeTravel.test.ts: appendInput fork, toolResult fork of a run paused for approval, validation and error mapping), and the store contract is reused (server/__tests__/checkpointStore.test.ts).src/execution/__fixtures__, the contract test and.fallowrc.jsonchanged.lou-d45.2-forge-history-panel): the client History panel, edit-and-replay, the side-by-side view and its client test..github/workflows/e2e-studio.ymlinstalls Chromium (npx playwright install --with-deps chromium), so the suite does not run here without a browser install.How verified
🤖 Generated with Claude Code
https://claude.ai/code/session_016bY29ibQgv3MDdjAbUT4YR
Generated by Claude Code