feat(runtime): reconstruct replayable agent graph timeline - #1549
Conversation
|
The overall direction looks right: reconstructing this as a read projection over the existing SQLite control plane and Runtime ledgers is preferable to introducing another trace authority. I found two blockers before this can satisfy the stable/replayable timeline contract. Blocker 1: mutable snapshot events invalidate pagination cursors
Cursor resume then requires the exact old I reproduced this with a minimal two-state admission fixture. The existing test covers an earlier immutable event being discovered, but not a current snapshot changing between page reads. This conflicts with the stable-cursor acceptance criterion. Making only the entity ID stable is not sufficient because the mutable snapshot can also move in chronological order. Pagination needs to bind to a frozen reconstruction/snapshot version, or mutable current-state snapshots should live outside the pageable historical stream. Persisting append-only transitions would also solve this later. Blocker 2: an existing activation is invisible until its first committed RuntimeEvent
As a result, a valid claimed/executing child AgentRun that already exists but has not committed its first RuntimeEvent produces only: There is no The timeline should match each claim's I do not consider the lack of a cross-store atomic transaction itself a blocker for this query-time projection; the cursor/snapshot contract is the part that needs to remain coherent across pages. |
* feat(runtime): reconcile graph supervisor schedules * fix(runtime): close graph stop admission races * fix(runtime): gate graph admission inside pending turns * fix(runtime): stop pending turns with cached backend * feat(runtime): bootstrap dynamic graph operators (#1474) * feat(runtime): bootstrap dynamic graph operators * fix(storage): close graph provision crash gaps * feat(runtime): host-manage agent graph invocations (#1480) * feat(runtime): host-manage agent graph invocations * fix(runtime): fence graph host lifecycle * feat(runtime): add agent graph client read model (#1483) * feat(runtime): add agent graph client read model * fix(runtime): materialize bounded graph client views * fix(runtime): fence graph projection updates * fix(runtime): isolate graph client projection * fix(runtime): repair dirty graph projections * feat(desktop): add playable Graph Mode (#1513) * feat(desktop): add playable graph mode * fix(desktop): resume graph supervisor at quiescence * fix(desktop): make graph wakes durably retryable * fix(desktop): converge graph wake lifecycle * fix(desktop): settle parked graph wakes * feat(runtime): reconstruct replayable agent graph timeline (#1549) * feat(runtime): reconstruct agent graph timeline * docs: explain agent graph architecture (#1550) * fix(runtime): stabilize graph timeline cursors * docs: clarify graph timeline current state * style: format graph integration merge
Summary
AgentGraphCoordinator.getTimeline()currentStateWhy this shape
This is the first implementation slice of #1529. It deliberately uses a query-time join over existing authorities instead of introducing a second trace authority or changing scheduler/runtime semantics.
The existing SQLite schema stores the current admission and wake state but not every overwritten transition, and reconcile passes are not durable facts yet. Mutable admission/wake snapshots therefore live outside the pageable historical stream so their state changes cannot invalidate an issued cursor. The response also reports the missing transition history through
coverage.limitations:admission_transition_history_not_persistedsupervisor_wake_transition_history_not_persistedreconcile_history_not_persistedThat makes the v1 trace useful and honest while leaving an append-only transition ledger and Desktop timeline UI as follow-up slices.
Result
A completed Graph run can now reconstruct:
root turn → schedule commit → operator/child Session → intent → durable AgentRun activation → runtime records → child terminal → supervisor wake/attempt → later root turn → selected result → schedule finishThe cursor is based on durable event identity/time rather than the page index, so it remains valid when an earlier event is discovered later.
sequenceis documented as deterministic reconstruction order, not a cross-ledger commit sequence.activation_startedcomes from the claimed child AgentRun's durablecreatedAt, including the live window before its first RuntimeEvent. Terminal activation remains RuntimeEvent-authoritative.Validation
npm run typechecknpm run build --workspace @maka/corenpm run build --workspace @maka/storagenpm run build --workspace @maka/runtimenode --test packages/runtime/dist/__tests__/agent-graph-timeline.test.js packages/runtime/dist/__tests__/stream-graph-projection.test.js packages/runtime/dist/__tests__/stream-graph-coordinator.test.jsThe full runtime suite completed with 2 unrelated local macOS/Homebrew sandbox failures out of 2,551 tests: the sandbox could not load ripgrep's
/opt/homebrew/opt/pcre2dylib, and an executable-root assertion expected/usr/local. The new timeline tests pass.Part of #1529.
中文说明
本 PR 做了什么
currentState,状态变化不会让旧 cursor 失效。为什么不是新建一套 trace authority
这是 #1529 的第一个实现切片。首版直接复用现有权威 stores,不增加新的 scheduler/runtime 语义,也不引入第二套事实源。
当前 SQLite 表只保留 admission/wake 的最新状态,不保留所有被覆盖的中间 transition;reconcile pass 目前也没有 durable ledger。因此 mutable current state 不进入分页历史流,同时 API 通过
coverage.limitations明确报告这些边界,而不是假装已经拥有完整历史。activation_started直接来自 claim 所关联 child AgentRun 的 durablecreatedAt,即便还没有第一条 RuntimeEvent 也可见;terminal 仍以 RuntimeEvent 为权威。后续可以单独增加 append-only transition ledger,再接 Desktop timeline UI。