| D-M2-51-1 |
2026-10-25 |
The recording of design note 1 is read from the files of the npm package of the platform of the pinned Claude Code 2.1.259 (no session, no login, no model call): task_started carries tool_use_id and task_type (values local_agent, local_bash, local_command, local_workflow), task_progress and task_notification carry tool_use_id and usage with total_tokens, tool_uses and duration_ms, tool_progress carries tool_use_id, tool_name, parent_tool_use_id and elapsed_time_seconds. The workflow type is local_workflow. The fixture tests/fixtures/recording/stream_fields_2.1.259.json keeps only types, subtypes and field names; the Fake-Claude fixture graph is constructed from them. |
A turn that really starts a subagent needs a login and a model call, which the brief forbids; the CLI's own emitting code names every field the mapping reads, and the level-one switch test holds them against the installed CLI. |
| D-M2-51-2 |
2026-10-25 |
No backfill of runs.last_progress_at: an active run without a value is never marked; it gets one with its next start or stored patch. |
A backfill from started_at would mark every long run of an old adapter at once, although nothing about its progress is known. |
| D-M2-51-3 |
2026-10-25 |
Summary steps are grouped by parent_step_id (the root as one group): the removal order stays the lowest ordinal of the run; a new summary step takes the parent and the lowest ordinal removed into it; a finished step whose only live child is its own summary step is a candidate, both go and their counts move into the summary of its parent. A summary step created in a patch and removed in the same patch with its parent is never stored or announced. The first stored summary step per parent is that parent's summary. |
09 5.3 addendum and R-DM-53; one rule for old root summaries and new ones; the normalized ops stay applicable to the base document. |
| D-M2-51-4 |
2026-10-25 |
The stall marking runs after the orphan verdicts of the same runs.stall_check round, one unit of work per run: lock the row, compare version with the version the round read and decide again (running, no notice, last_progress_at older than run.stall_after), then one UPDATE sets stall_warned_at and raises version; run.updated with base_version, version and add /stall_warned_at is published after the commit, without an actor. A run whose row changed in between is skipped until the next round. |
Design note 5; a patch, start or end stored between the read and the lock wins, and a run the orphan check ended in the same round is not marked. |
| D-M2-51-5 |
2026-10-25 |
run.stall_after is a server key of chapter 03 (default 10m, at least 1ms); runner.progress_patch_interval (default 2m) is a runner key. The runner counts its interval from the creation of the live box of a turn (the run was just started) and from every change it hands to the patcher, not from the server's store, which the runner cannot read. |
The patcher sends a handed change within agent.run_update_min_interval, far below the interval; the runner key must stay below the server key (README of the runner). |
| D-M2-51-6 |
2026-10-25 |
background_thread_ids are stored as focus entries with a background mark: they are in the thread index of run.updated and the live box snapshot, a foreground-only type (typing.started) skips them, and the presence view and gateway_presence leave them out. A thread in both lists is a foreground thread; the budget counts the distinct threads of both lists. |
04 6.2, 11.3 and R-SY-27 with one index and one re-check path (pruning, resume) for both lists. |
| D-M2-51-7 |
2026-10-25 |
The usage of a task becomes detail.usage on every task_progress and task_notification that carries it and changes it; the whole detail is replaced (a subagent keeps type). |
09 5.6 shows tokens of a running node too; the patcher throttles the replaces. |
| D-M2-51-8 |
2026-10-25 |
In role worker the runs module publishes run.updated through a gateway cluster publisher without a local hub: the event goes to the api nodes as the run signal of 02 11.6, and their cluster hands it to the live box of the connections that focus the thread (a snapshot at the window end). In roles api and all the gateway binds its own publisher as before. |
Red team of M2-51: runs.stall_check runs only in worker and all, so in a split of api and worker the stall marking published nothing; the same path already carries notification.created of the worker (D-M7-17-7). |