@xingular/harness 1.2.0 → 1.3.1-unstable.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +10 -5
  3. package/dist/cli.js +5560 -5056
  4. package/dist/sdk/agents/builtin.js +3 -3
  5. package/dist/sdk/agents/planResearch.d.ts +23 -1
  6. package/dist/sdk/agents/planResearch.js +71 -8
  7. package/dist/sdk/agents/profiles.d.ts +4 -1
  8. package/dist/sdk/agents/profiles.js +17 -6
  9. package/dist/sdk/capabilities/runSnapshot.js +10 -4
  10. package/dist/sdk/commands/registry.d.ts +11 -3
  11. package/dist/sdk/commands/registry.js +3 -2
  12. package/dist/sdk/core/shell.d.ts +20 -0
  13. package/dist/sdk/core/shell.js +73 -0
  14. package/dist/sdk/core/workspaceBashTool.d.ts +17 -1
  15. package/dist/sdk/core/workspaceBashTool.js +16 -2
  16. package/dist/sdk/core/workspaceSandbox.d.ts +10 -0
  17. package/dist/sdk/core/workspaceSandbox.js +52 -12
  18. package/dist/sdk/core/workspaceWriteOperations.d.ts +11 -0
  19. package/dist/sdk/core/workspaceWriteOperations.js +26 -8
  20. package/dist/sdk/doctor/checks.js +71 -12
  21. package/dist/sdk/hub/hub.js +5 -3
  22. package/dist/sdk/index.d.ts +2 -2
  23. package/dist/sdk/index.js +1 -1
  24. package/dist/sdk/plugins/builtin.js +3 -3
  25. package/dist/sdk/plugins/install.d.ts +6 -2
  26. package/dist/sdk/plugins/install.js +29 -5
  27. package/dist/sdk/plugins/inventory.js +2 -2
  28. package/dist/sdk/prompt/compile.d.ts +2 -2
  29. package/dist/sdk/prompt/compile.js +14 -16
  30. package/dist/sdk/server/methods.js +4 -2
  31. package/dist/sdk/sessions/compactionCheckpoint.d.ts +3 -3
  32. package/dist/sdk/sessions/compactionCheckpoint.js +12 -12
  33. package/dist/sdk/sessions/continuation.d.ts +4 -2
  34. package/dist/sdk/sessions/continuation.js +7 -6
  35. package/dist/sdk/sessions/contracts.d.ts +22 -4
  36. package/dist/sdk/sessions/contracts.js +12 -7
  37. package/dist/sdk/sessions/planMode.js +2 -2
  38. package/dist/sdk/sessions/runStore.js +3 -1
  39. package/dist/sdk/sessions/runner.js +2 -2
  40. package/dist/sdk/sessions/sessions.js +29 -11
  41. package/dist/sdk/sessions/subagentService.d.ts +15 -0
  42. package/dist/sdk/sessions/subagentService.js +194 -54
  43. package/dist/sdk/sessions/subagents.d.ts +10 -1
  44. package/dist/sdk/sessions/subagents.js +4 -0
  45. package/dist/sdk/sessions/workSlice.d.ts +8 -5
  46. package/dist/sdk/sessions/workSlice.js +77 -45
  47. package/dist/sdk/terminal/controller.d.ts +20 -0
  48. package/dist/sdk/terminal/controller.js +43 -18
  49. package/dist/sdk/terminal/opentui/ansi.d.ts +25 -0
  50. package/dist/sdk/terminal/opentui/ansi.js +192 -0
  51. package/dist/sdk/terminal/opentui/model.d.ts +163 -0
  52. package/dist/sdk/terminal/opentui/model.js +482 -0
  53. package/dist/sdk/terminal/opentui/subagentsWidget.d.ts +3 -3
  54. package/dist/sdk/terminal/opentui/subagentsWidget.js +7 -5
  55. package/dist/sdk/terminal/opentui/theme.js +1 -0
  56. package/dist/sdk/terminal/piExtension.js +28 -14
  57. package/dist/sdk/terminal/subagentMonitor.d.ts +17 -4
  58. package/dist/sdk/terminal/subagentMonitor.js +29 -8
  59. package/dist/sdk/terminal/terminals.d.ts +7 -0
  60. package/dist/sdk/terminal/terminals.js +86 -14
  61. package/dist/sdk/terminal/trajectory.d.ts +6 -1
  62. package/dist/sdk/terminal/trajectory.js +8 -0
  63. package/dist/sdk/terminal/tui/chrome.d.ts +4 -0
  64. package/dist/sdk/terminal/tui/chrome.js +13 -0
  65. package/dist/sdk/terminal/tui/commandPages.js +14 -4
  66. package/dist/sdk/terminal/tui/commands.d.ts +4 -0
  67. package/dist/sdk/terminal/tui/commands.js +8 -0
  68. package/dist/sdk/terminal/tui/pageOverlay.js +13 -6
  69. package/dist/sdk/terminal/tui/pages/browserPage.js +5 -4
  70. package/dist/sdk/terminal/tui/pages/hubPage.d.ts +14 -1
  71. package/dist/sdk/terminal/tui/pages/hubPage.js +192 -28
  72. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +8 -1
  73. package/dist/sdk/terminal/tui/pages/pluginsPage.js +197 -25
  74. package/dist/sdk/terminal/tui/pages/subagentsPage.js +8 -5
  75. package/dist/sdk/tools/sessionName.d.ts +2 -0
  76. package/dist/sdk/tools/sessionName.js +5 -3
  77. package/dist/sdk/tools/spawnSubagent.js +9 -7
  78. package/dist/sdk/tools/todo.d.ts +15 -0
  79. package/dist/sdk/tools/todo.js +64 -0
  80. package/dist/terminal-opentui.js +1416 -348
  81. package/dist/terminal-pi.js +315 -126
  82. package/docs/architecture/00-overview.md +1 -1
  83. package/docs/architecture/01-extension-points.md +1 -1
  84. package/docs/architecture/02-sessions-and-runs.md +65 -34
  85. package/docs/architecture/04-prompt.md +8 -6
  86. package/docs/architecture/06-plugins-and-capabilities.md +10 -6
  87. package/docs/architecture/07-tools-and-gate.md +31 -5
  88. package/docs/architecture/09-accounts-and-connectors.md +8 -2
  89. package/docs/architecture/10-server-protocol.md +16 -9
  90. package/docs/architecture/11-terminal.md +51 -26
  91. package/docs/architecture/14-surfaces-and-parity.md +4 -1
  92. package/docs/architecture/README.md +18 -17
  93. package/docs/architecture/proposals/PROP-0006-run-checklist.md +2 -0
  94. package/docs/architecture/proposals/PROP-0041-bounded-work-slices.md +32 -21
  95. package/docs/architecture/proposals/PROP-0044-work-slice-defaults.md +93 -0
  96. package/docs/architecture/proposals/PROP-0045-rename-checklist-to-todo.md +132 -0
  97. package/docs/architecture/proposals/PROP-0046-progress-aware-stall-guards.md +82 -0
  98. package/docs/architecture/proposals/PROP-0047-plugins-hub-separation.md +122 -0
  99. package/docs/architecture/proposals/README.md +10 -6
  100. package/docs/decisions/ADR-0039-progress-aware-stall-guards.md +39 -0
  101. package/docs/decisions/ADR-0040-architecture-change-workflow.md +31 -0
  102. package/docs/decisions/ADR-0041-plugins-hub-separation.md +41 -0
  103. package/docs/decisions/ADR-0042-windows-shell-without-sandbox.md +40 -0
  104. package/docs/decisions/ADR-0043-parents-continue-stopped-subagents.md +49 -0
  105. package/docs/doctor.md +14 -1
  106. package/docs/parity.md +9 -9
  107. package/docs/releases/1.3.0.md +21 -0
  108. package/docs/releases/README.md +2 -2
  109. package/docs/terminal-tui.md +85 -46
  110. package/package.json +1 -1
  111. package/dist/sdk/tools/checklist.d.ts +0 -9
  112. package/dist/sdk/tools/checklist.js +0 -55
@@ -134,7 +134,7 @@ Modules with no member of their own: `variant/` (functions over the variant stor
134
134
  | Letter | The harness owns |
135
135
  |---|---|
136
136
  | **E** Execution | Isolated account folders, the Pi session, the terminal launch spec |
137
- | **T** Tools | History, trajectory, Wiki notes, skill loading, `ask_user`, the run checklist, the connected-apps broker, the tool gate |
137
+ | **T** Tools | History, trajectory, Wiki notes, skill loading, `ask_user`, the run todo list, the connected-apps broker, the tool gate |
138
138
  | **C** Context | The compiler, stable prefix and updates, the versioned variant (c1–c8), skills, on-demand Wiki notes |
139
139
  | **L** Lifecycle | Run state, interrupt, recovery, approvals and questions, subagents, refinement |
140
140
  | **O** Observability | Validated run events saved per run; usage counters |
@@ -50,7 +50,7 @@ harness forwards to the policy and never reads.
50
50
  ## Invariants
51
51
 
52
52
  - **INV-EXT-1** There are seven extension points. Adding, removing or changing the shape of one is
53
- an architecture change (proposal required).
53
+ an architecture change; update this page and affected contracts in the same change.
54
54
  - **INV-EXT-2** Every extension point is optional. The harness runs with none of them supplied.
55
55
  - **INV-EXT-3** An extension point carries data or decisions the application owns. It never
56
56
  carries an application's name or a branch for one application (`INV-BND-3`).
@@ -13,7 +13,7 @@ records everything the run does as validated events.
13
13
  |---|---|---|
14
14
  | `Sessions` | `sessions/sessions.ts` | Starts a turn: `run(input: SessionRunInput)`, `provide(provider)`. Builds the gate. |
15
15
  | `runTurn`, `piSessionFactory`, `loadResources` | `sessions/runner.ts` | Opens the Pi session, loads resources in a fixed order, streams events, settles the run. |
16
- | compaction checkpoint | `sessions/compactionCheckpoint.ts` | Restores the active request's bounded goal, checklist and plan instructions to model context after compaction. |
16
+ | compaction checkpoint | `sessions/compactionCheckpoint.ts` | Restores the active request's bounded goal, todo list and plan instructions to model context after compaction. |
17
17
  | `RunRegistry`, `ActiveRun` | `sessions/registry.ts` | Live runs: `emit`, `requestApproval`, `requestAnswer(s)`, `onInterrupt`, `onSteer`, `finish`; `listen` for observers. |
18
18
  | run store functions | `sessions/runStore.ts` | `saveRun`, `updateRun`, `persistEvent`, `appendEvent`, `readEvents`, `markInterruptedRuns`, `runFamily`, `listRuns`. |
19
19
  | `RunRecord`, `RunEvent`, schemas | `sessions/contracts.ts` | The one contract every session shares. |
@@ -55,7 +55,7 @@ A session that cannot open ends its run as `failed` and returns `nativeSessionId
55
55
  `message.completed`, `message.steered`, `tool.started`, `tool.completed`, `retry.started`,
56
56
  `retry.ended`, `compaction.started`, `compaction.ended`, `approval.requested`,
57
57
  `approval.resolved`, `question.requested`, `question.answered`, `extension.notice`,
58
- `reaction.added`, `agent.message`, `checklist.updated`, `artifact.added`, `file.changed`, `usage.updated`,
58
+ `reaction.added`, `agent.message`, `todo.updated`, `artifact.added`, `file.changed`, `usage.updated`,
59
59
  `account.status`, `status.changed`, `failed`, `completed`. Each has a payload schema in
60
60
  `runEventPayloadSchemas`.
61
61
  - **Workspace root** (`RunRecord.workspaceRoot`) is the canonical root whose filesystem effects
@@ -76,9 +76,10 @@ A session that cannot open ends its run as `failed` and returns `nativeSessionId
76
76
  across alternatives; generation quality is guidance, not a schema guarantee. Old events remain
77
77
  valid without a data rewrite; readers with the old bounds must update before accepting larger
78
78
  sketches. `question.answered` and `QuestionAnswer` are unchanged.
79
- - **Checklist** (PROP-0006): `checklist.updated` carries the whole list the model last wrote with
80
- `checklist_write`, `{ items: { text, status: pending | in_progress | completed }[] }`, at most 50
81
- items. The latest event replaces every earlier one; `checklistOf(events)` reads it.
79
+ - **Todo list** (PROP-0006, renamed by PROP-0045): `todo.updated` carries the whole list the model
80
+ last wrote with `todo_write`, `{ items: { text, status: pending | in_progress | completed }[] }`, at
81
+ most 50 items. The latest event replaces every earlier one; `todoOf(events)` reads it. The
82
+ pre-rename `checklist.updated` is still read so old runs keep their list, and is never written.
82
83
  - **`RunRecord`** fields are listed in `sessions/contracts.ts`. `mode`, `harness`, `sessionType`,
83
84
  `worktreeId`, `attachmentCount`, `exitCode`, `handoffId` and `trigger` belong to the
84
85
  application: stored and returned, and only `mode` and `trigger` are read.
@@ -97,12 +98,22 @@ A session that cannot open ends its run as `failed` and returns `nativeSessionId
97
98
  `results` for the host (`sessions.spawnSubagent` is a compatibility alias). Child runs have
98
99
  `relation: 'subagent'` and `parentRunId`. Nesting defaults to 1, at most 3 (`subagentDepth`).
99
100
  The child's record carries `title`, the short name the parent gave it (PROP-0030).
101
+ `spawn_subagent { continue: <runId> }` (`subagents.spawn { continue }`) continues a child that
102
+ stopped before finishing as a new child run with `continueFrom`. It reopens the first link's
103
+ history folder and keeps the earlier child's session id, profile, title, account, variant version
104
+ and frozen capability set, which must still lie within the parent's; `agent` and `tools` are
105
+ refused with it, and the newest link of a chain is the one continued (ADR-0043). Children an
106
+ earlier reply left stopped are delivered before the next reply's first request, each with a
107
+ note that it can be continued; a stopped child that was continued is reported through its
108
+ continuation. Every run record carries the launch `model` and `effort`, superseded by the model
109
+ the session opened with.
100
110
  - **Agent profiles** (PROP-0029). `agent` names a profile: built-in (`worker`, `explorer`),
101
111
  `<data root>/agents/<name>.md`, `<project>/.xingular/agents/<name>.md`, or a c5 definition of
102
112
  the parent's variant, later sources winning (`agents/profiles.ts`). A profile narrows the
103
113
  child's tools and plugins (`agents/narrow.ts`), may choose its variant, model and effort, and
104
114
  frames it with a "Your role" section. The child's record carries `profile`; the spawn result
105
- carries `agent` and any `unavailableTools`. A run that may spawn lists every profile in its
115
+ carries `agent` and any `unavailableTools`. `main` is reserved for the main agent's row: no
116
+ profile file or variant definition may take it. A run that may spawn lists every profile in its
106
117
  `subagents` section.
107
118
  - **Plan mode** (`plan: true`). The stable system prompt is unchanged. An attended plan run may
108
119
  include `ask_user` and `spawn_subagent` / `wait_subagents`, subject to the caller's frozen
@@ -122,15 +133,15 @@ A session that cannot open ends its run as `failed` and returns `nativeSessionId
122
133
  The reply ends with one `<proposed_plan>` block.
123
134
  - **Compaction checkpoint** (PROP-0033, ADR-0032). After compaction, an active run's model context
124
135
  receives a bounded, ephemeral checkpoint with the current user request and the latest validated
125
- checklist or applicable plan instructions, when either is available to restore. It is re-added to
136
+ todo list or applicable plan instructions, when either is available to restore. It is re-added to
126
137
  each request while that run continues;
127
138
  its state is cleared when the run settles or the session branch changes. The message changes no
128
139
  tools, permissions, run events or native history. An interrupted run still uses the durable
129
- checklist and normal continuation path.
140
+ todo list and normal continuation path.
130
141
  - **Continuation** (PROP-0007). `continuationOf(root, runId, sessionDir?)` (`runs.continuation`)
131
142
  says whether a stopped run can be continued: `resumable`, a `reason` when not (`not_found`,
132
143
  `active`, `completed`, `no_history`, `history_missing`), the exact native history to reopen,
133
- the pinned account, variant version and capability set, the checklist, unanswered approvals and
144
+ the pinned account, variant version and capability set, the todo list, unanswered approvals and
134
145
  questions, the last tool and whether it finished, and subagents that did not finish.
135
146
  `SessionRunInput.continueFrom` starts a **new** run from it: it reopens that history, records
136
147
  `resumedFromRunId`, pins the same account, variant version and capability set (anything different
@@ -138,7 +149,8 @@ A session that cannot open ends its run as `failed` and returns `nativeSessionId
138
149
  `continuation_unavailable`). If the earlier snapshot includes `ask_user`, an automatic or
139
150
  refinement-triggered continuation fails with `continuation_mismatch` rather than narrowing it.
140
151
  Empty text defaults to "Continue from where you stopped.", and the new run adds
141
- a dynamic `continuation` section (order 26) saying where the earlier run stopped. The next run
152
+ a dynamic `continuation` section (order 26) saying where the earlier run stopped and that its
153
+ unfinished subagents can be continued with `spawn_subagent { continue }`. The next run
142
154
  without `continueFrom` withdraws it. `Recovery.interruptedRunIds` lists the runs `open` marked
143
155
  interrupted.
144
156
  - **Worktrees** (PROP-0016). When `run.worktreeId` names a worktree in the Harness registry
@@ -203,7 +215,9 @@ is approved but remains in progress; no completed cross-surface catalog is impli
203
215
  and never applied or relayed.
204
216
  - **INV-RUN-4** A restarted harness never restarts model work. On `open`, runs left active are
205
217
  marked `interrupted` unless another live process owns them (`owner.json`). Recovery of a
206
- subagent needs the same account, caller, working folder and history branch. Continuing is always
218
+ subagent needs the same account, caller, working folder and history branch; the history branch
219
+ (owner marker and native history id), not the host's session id, ties a parent to an earlier
220
+ one. A stopped subagent is continued only by its parent, through `spawn_subagent { continue }`. Continuing is always
207
221
  a new run with `continueFrom`; it pins the earlier run's account, variant version and capability
208
222
  set, and the earlier run's record is never reopened. The application asks for it, or the earlier
209
223
  run's work-slice policy does when the reply stopped at its budget (PROP-0041); a run started
@@ -225,11 +239,15 @@ is approved but remains in progress; no completed cross-surface catalog is impli
225
239
  plan may include `ask_user`, `spawn_subagent` and `wait_subagents`, subject to the frozen caller
226
240
  capabilities; newly resolved normal, automatic, probe, improver and reflection runs omit
227
241
  `ask_user`. Plan-mode spawning requires a named profile whose effective explicit tool and plugin
228
- allowlists qualify for read-only research. The child inherits plan mode and is narrowed to the
229
- intersection of the parent's frozen capabilities, the profile and the plan research set; it has no
242
+ allowlists qualify for read-only research. The prompt lists only profiles whose intersection with
243
+ the parent's frozen tools and plugin contributions includes a research evidence tool. An omitted
244
+ `tools` override inherits that safe intersection; an explicit override can only narrow it. The
245
+ child inherits plan mode and is narrowed to the intersection of the parent's frozen capabilities,
246
+ the profile and the plan research set; it has no
230
247
  connectors, user questions, writes, commands or nested subagents. The plan run itself may run
231
- Bash only in the OS-enforced read-only scope (PROP-0043, ADR-0038). The gate refuses unsafe calls
232
- before approvals, and the service rechecks before launch. The terminal activates plan-eligible
248
+ Bash only in the OS-enforced read-only scope (PROP-0043, ADR-0038); research children cannot run
249
+ commands. Generic browser actions and connected-app calls remain unavailable in plan mode. The
250
+ gate refuses unsafe calls before approvals, and the service rechecks before launch. The terminal activates plan-eligible
233
251
  tools only for a plan request, then restores its normal set. Provider-cache effects of the tool-list
234
252
  difference are not assumed (page 04, `INV-PRM-8`).
235
253
  - **INV-RUN-9** Subagent results reach the parent at native turn boundaries, at most once
@@ -245,28 +263,39 @@ is approved but remains in progress; no completed cross-surface catalog is impli
245
263
  surface's visible transcript and selected references. It excludes hidden reasoning and attachment
246
264
  bytes, never reads the main native history, and never changes or steers the parent. Its own run
247
265
  record and events use the normal store contract (PROP-0019).
248
- - **INV-RUN-13** A reply is a bounded work slice (PROP-0041). The foundation defaults are 160 tool
249
- calls, 40 minutes and 320 000 new tokens, whichever comes first. The token count covers new input,
250
- cache writes and output, never the cached prefix: a few large reads pass any small cap before
251
- useful work, so the cap is a safety net, not the bound. At the limit the guard ends the slice and
252
- refuses the next tool call with a request for `checkpoint_write`; a handoff call is never refused,
253
- including when it is the first call past the limit, and another tool ends the reply. A reply that ends this way is `interrupted` with terminal reason `slice_complete`, and one
254
- the stall guard ends is `stalled`. The stall guard identifies a call by its name and every
255
- argument, names a repeated call once and ends the reply on the next repeat, and counts afresh in
256
- each reply, so a checklist a reply rewrites as its steps complete is not a repeat. A new run
257
- continues it only up to the policy's slice cap, only
258
- after a slice that changed a file, passed a check or recorded a finished item, and never after a
259
- checkpoint that is `blocked`. A run may turn the guard off with `workSlice.enabled: false`, and a
260
- launch may set `XINGULAR_WORK_SLICE=off` for every run in that process; with it off a reply has no
261
- boundary — no checkpoint, no continuation, no stall notes — and ends only when the model stops or a
262
- person interrupts.
266
+ - **INV-RUN-13** A reply is a bounded work slice (PROP-0041). The foundation defaults are 320 tool
267
+ calls and 60 minutes, whichever comes first, with no new-token limit (PROP-0044). A token cap is
268
+ available with `workSlice.maxNewTokens`, counted on new input, cache writes and output and never on
269
+ the cached prefix: a few large reads pass any small cap before useful work, so the tool calls and
270
+ the clock are the bound and the token count is only a ceiling for whoever asks for one. At the
271
+ limit the guard refuses the next tool call. When `checkpoint_write` is available, it requests a
272
+ checkpoint and leaves handoff calls callable; otherwise a plan-research child must stop with a
273
+ concise partial research report, and the runner derives a checkpoint from run evidence. A
274
+ non-handoff tool call after the refusal ends the reply. A budget-ended reply is `interrupted` with
275
+ terminal reason `slice_complete`; a reply ended by a stall guard is `stalled`.
276
+ The targeted stall guard identifies calls by name and every argument; three identical calls cause
277
+ one refusal, and a repeated trigger ends the reply. A Bash check that fails twice is a trigger. The
278
+ guard counts only successful native `edit`/`write` results (`isError === false`) with a path toward
279
+ the four-edit per-path churn limit; the next edit is refused, and a repeated trigger ends the
280
+ reply. Failed or blocked edits do not count. A successful edit/write clears failed-check counts,
281
+ identical Bash-check repeat counts and the pending nudge, but leaves edit counts and other
282
+ repeated-call counts intact. A passing check clears edit counts. The general 25-call file/check
283
+ no-progress trigger is removed. `todo_write` is bookkeeping: it is exempt from repeated-call
284
+ detection and does not reset loop state, but counts toward the tool-call budget. Third-compaction
285
+ thrash detection remains. Plan-research children without `checkpoint_write` receive the configured
286
+ bound without a new capability and do not auto-continue. A new run continues it only up to the
287
+ policy's slice cap, only after a slice that changed a file, passed a check or recorded a finished
288
+ item, and never after a checkpoint that is `blocked`. A run may turn the guard off with
289
+ `workSlice.enabled: false`, and a launch may set `XINGULAR_WORK_SLICE=off` for every run in that
290
+ process; with it off a reply has no boundary — no checkpoint, no continuation, no stall notes — and
291
+ ends only when the model stops or a person interrupts.
263
292
  - **INV-RUN-14** A run event stream carries `checkpoint` (the handoff `checkpoint_write` records or
264
293
  the harness derives from the run's own evidence when the model wrote none) and `heartbeat`
265
294
  (steps, elapsed time, last tool, compactions, slice, and the call budget). A heartbeat older than
266
295
  five minutes while the owner process lives marks the run `interrupted` with reason `stalled`; a
267
296
  run that never emitted one keeps the 30-minute silence rule. The watchdog never restarts work.
268
297
  - **INV-RUN-12** A post-compaction checkpoint is a bounded context projection of the active request,
269
- the latest validated checklist and applicable plan instructions. It is compiled by
298
+ the latest validated todo list and applicable plan instructions. It is compiled by
270
299
  `prompt/compile.ts`, supplied only to model requests in the active run, and never persists hidden
271
300
  reasoning or changes permissions, stable prompt text, native history or run-event schemas. Its
272
301
  in-memory state is cleared when the run settles or the active session branch changes
@@ -290,13 +319,15 @@ Decisions: [ADR-0002](../decisions/ADR-0002-native-subagent-lifecycle.md) (super
290
319
  [ADR-0022](../decisions/ADR-0022-plan-only-question-tools.md),
291
320
  [ADR-0023](../decisions/ADR-0023-contextual-side-question-runs.md),
292
321
  [ADR-0026](../decisions/ADR-0026-contextual-question-wireframes.md),
293
- [ADR-0033](../decisions/ADR-0033-plan-mode-research-delegation.md).
322
+ [ADR-0033](../decisions/ADR-0033-plan-mode-research-delegation.md),
323
+ [ADR-0039](../decisions/ADR-0039-progress-aware-stall-guards.md).
294
324
 
295
325
  ## Native session names (PROP-0010)
296
326
 
297
327
  `session_name({ name: string })` adds or revises the current Pi session's name in embedded
298
- and terminal execution. The agent names meaningful work early and revises it when the overall
299
- objective changes, including a manual name. Agent-submitted names are imperative sentences
328
+ and terminal execution. The agent calls it once before its first other tool call when a request
329
+ needs tools or changes state, and revises it only when the overall objective changes, including a
330
+ manual name. Agent-submitted names are imperative sentences
300
331
  of at most six whitespace-separated words; whitespace is normalized, and empty names,
301
332
  terminal escapes, non-whitespace controls and longer names fail without writing. Identical
302
333
  names are a no-op. Pi's native session-info history is the only storage; continuation and
@@ -16,7 +16,7 @@ keeps provider caching effective across turns.
16
16
  | `render(env, pack)` → `string` | One string for a session that takes a single prompt. |
17
17
  | `sessionLaunch(env, caller, launch, historyFile, variant)` → `{ system, update, pack }` | SDK sessions: stable prefix plus an update with only the dynamic sections that changed since the last delivered snapshot. |
18
18
  | `deliveredSnapshot(sessionFile)` | Reads the last delivered snapshot on the active history branch; a compaction forces a fresh one. |
19
- | `renderCompactionCheckpoint` | Compiles a bounded current-request, checklist and plan-state message for post-compaction model requests. |
19
+ | `renderCompactionCheckpoint` | Compiles a bounded current-request, todo list and plan-state message for post-compaction model requests. |
20
20
  | `saveForSession`, `copyToRun` | Terminal sessions keep the pack they started with and copy it to each run. |
21
21
  | `record`, `load`, `packPath` | The pack each run was given, at `runs/<id>/context.json`. |
22
22
  | `toolGroups`, `fit`, `clip` | The tool manifest by group; cutting text to a budget at a paragraph boundary. |
@@ -37,8 +37,9 @@ guidance in that section explains when delegation is worth its overhead, profile
37
37
  self-contained briefs, independent parallel work, and parent ownership of integration. Plan mode
38
38
  lists only effective profiles eligible for read-only research and requires a named profile; keeping
39
39
  this section dynamic leaves the stable system prompt unchanged across modes. The `tools`
40
- section has a Progress paragraph whenever `checklist_write` is available: it asks for a checklist
41
- early and kept current, then requests a final update before the reply. Only fully completed work is
40
+ section has a Progress paragraph whenever `todo_write` is available: it asks for `todo_write` before
41
+ the first other tool call when work has several steps, asks for the list to stay current, then
42
+ requests a final update before the reply. Only fully completed work is
42
43
  marked completed; unfinished or blocked steps remain accurate (PROP-0006).
43
44
 
44
45
  The fixed `harness-identity` section says `You are an AI agent running in <productName>.` and uses
@@ -81,7 +82,7 @@ compile ──► pack ──► stable sections ──► system prompt (+ "Con
81
82
  `references` is always resent when present, because it belongs to the current request.
82
83
  - After successful compaction, the foundation checkpoint extension detects the compacted context and
83
84
  uses `renderCompactionCheckpoint` to append one hidden, ephemeral context message to each model
84
- request while the active run continues, when a checklist or applicable plan instructions exist.
85
+ request while the active run continues, when a todo list or applicable plan instructions exist.
85
86
  It contains only the current request and available state. It is not written to native history, and its state is
86
87
  discarded when the run settles or the branch changes.
87
88
  - The session appends the update as a hidden custom message and saves its snapshot in the
@@ -154,7 +155,8 @@ sections), `src/sessions/planMode.ts` (`plan` section).
154
155
 
155
156
  ## Session naming guidance (PROP-0010)
156
157
 
157
- The Session tool group describes `session_name` when available: name meaningful work early
158
- with an imperative sentence of at most six words, and revise when the objective changes.
158
+ The Session tool group describes `session_name` when available: call it once before the first
159
+ other tool call when a request needs tools or changes state, with an imperative sentence of at
160
+ most six words, and revise only when the objective changes.
159
161
  This is fixed foundation guidance. The current name stays in native session metadata and
160
162
  the terminal snapshot; it is never interpolated into the stable system prompt.
@@ -134,13 +134,17 @@ metadata or availability:
134
134
  | Foundation | Accounts, sessions and run recording, prompt and variant validation, gate, plugin loading/trust/attachments, resource browser, server and terminal frameworks | Release-owned infrastructure and security contracts |
135
135
  | World | Web search/read tools, browser tools, page annotations | The isolated browser engine and network policy remain Foundation services |
136
136
  | Memory | Wiki, history and trajectory | Storage and run records remain Foundation-owned services |
137
- | Automation | Subagents, ask-user, checklist, lessons and refinement | Run lifecycle, capability narrowing and approval gate remain Foundation-owned |
137
+ | Automation | Subagents, ask-user, todo, lessons and refinement | Run lifecycle, capability narrowing and approval gate remain Foundation-owned |
138
138
  | Integrations | Connected apps/MCP and Hub | Connector credentials and plugin installation remain behind Foundation services |
139
139
  | Operations | Doctor, worktrees and usage | Diagnostics, repository operations and usage analytics remain Harness-managed services |
140
140
 
141
- ## Terminal resource inspection
141
+ ## Terminal plugin and resource inspection
142
142
 
143
- The unified browser joins saved plugin/contribution metadata with actual session skills and tool
144
- registration. A saved on/off state does not prove a resource loaded; origins and owners distinguish
145
- same-name resources. Protected install/remove, settings, attachment and trust actions call the
146
- existing services. No second discovery or enablement mechanism is introduced (PROP-0013).
143
+ The broad `/harness` browser joins saved plugin/contribution metadata with actual session skills and
144
+ tool registration. A saved on/off state does not prove a resource loaded; origins and owners
145
+ distinguish same-name resources. `/plugins` is a focused local manager with Plugins, Trust and
146
+ Packages tabs. It uses the existing plugin services for switching, trust, settings, package install,
147
+ update and removal. `/hub` is a distinct Community catalog surface; it does not load code or add a
148
+ second loader. Hub-owned package removal through `plugins.remove` delegates to Hub so the exact
149
+ receipt and its resources stay consistent. No second discovery or enablement mechanism is
150
+ introduced (PROP-0013, PROP-0047).
@@ -16,7 +16,7 @@ person without letting remembered per-tool grants widen that boundary.
16
16
  | `dispatch` | `tools/dispatch.ts` | One entry point for every History, Wiki and skill call, from a Pi tool, the server or a terminal. |
17
17
  | `harnessTools` | `tools/harnessTools.ts` | The definitions as `ToolSpec`s for one session. |
18
18
  | `askUserTool` (`ask_user`) | `tools/askUser.ts` | Stops an attended plan run and asks up to five related questions with choices and concise 1–2 word labels; absent from newly resolved normal runs. |
19
- | `checklistTool` (`checklist_write`) | `tools/checklist.ts` | Writes the run's whole checklist as a `checklist.updated` event (PROP-0006). Read-only for the gate, so plan mode allows it. Terminal sessions register the same tool; it reaches the run through the `checklist` telemetry call. The prompt's Progress group asks the model to keep it current and write one final update before replying; unfinished work is not automatically marked complete. |
19
+ | `todoTool` (`todo_write`) | `tools/todo.ts` | Writes the run's whole todo list as a `todo.updated` event (PROP-0006, renamed by PROP-0045). Read-only for the gate, so plan mode allows it. Terminal sessions register the same tool; it reaches the run through the `todo` telemetry call. The prompt's Progress group asks the model to call it before the first other tool call when work has several steps, keep it current, and write one final update before replying; unfinished work is not automatically marked complete. The pre-rename `checklist.updated` event is still read, never written. |
20
20
  | `subagentTools` | `tools/spawnSubagent.ts` | `spawn_subagent` (requires a short `title`, PROP-0030) and `wait_subagents`; normal-mode descriptions guide selective, bounded delegation, while plan-mode spawns require a named eligible read-only research profile. |
21
21
  | `annotationsPart` (`page_notes_list`, `page_notes_read`, `page_notes_mark_fixed`) | `annotations/part.ts` | World tools over the page notes a person shared with the session or agent (PROP-0017). `page_notes_mark_fixed` records the agent's claim that it fixed a note it was sent; it never resolves a note or changes grants (PROP-0018). |
22
22
  | `webTools` | `web/tools.ts` | `web_search` (Brave, key from the secret store), `web_fetch` (checked public reads). An application provides them as a provider. |
@@ -26,7 +26,7 @@ person without letting remembered per-tool grants widen that boundary.
26
26
  Harness tools: `get_capabilities` (read-only current-run discovery), `history_search`, `history_read`,
27
27
  `trajectory_search`, `trajectory_read`, `wiki_search`, `wiki_read`, `wiki_list`, `wiki_write`
28
28
  (not in the default set), `skill_load`, `ask_user` (attended plan runs and pinned continuations only),
29
- `checklist_write`. Broker:
29
+ `todo_write`. Broker:
30
30
  `mcp_list_tools`, `mcp_call_tool`. Native Pi tools: `read`, `grep`, `find`,
31
31
  `ls`, `edit`, `write`, `bash`.
32
32
 
@@ -76,6 +76,18 @@ never replayed after partial effects. Full Permission is the explicit eligible-r
76
76
  Unsupported or unavailable sandbox enforcement fails closed. A side-question run has an empty
77
77
  capability set and no tools (PROP-0019).
78
78
 
79
+ **Windows** has no write-boundary sandbox the harness can use, so the Bash tool treats every
80
+ command there as an outside request: a human-only one-call approval (or an eligible Full
81
+ Permission answer), then the command runs once without a sandbox. Plan-mode Bash is refused,
82
+ because a read-only scope cannot be enforced. Commands run in Git Bash when it is installed
83
+ (`%ProgramFiles%\Git\bin\bash.exe`, then `bash.exe` on `PATH`, never the WSL launcher in
84
+ `System32`), otherwise in PowerShell (`pwsh.exe`, then Windows PowerShell). The tool keeps the name
85
+ `bash`; its description names the shell. Native `edit` and `write` run their atomic helper with
86
+ Node directly, without an OS guard: the target is still canonicalized, authorized, revalidated and
87
+ replaced by rename, and outside targets still need their approval, but a junction or symlink swap
88
+ between the check and the rename is not prevented
89
+ ([ADR-0042](../decisions/ADR-0042-windows-shell-without-sandbox.md)).
90
+
79
91
  ## The gate, per call
80
92
 
81
93
  For native `edit` and `write`, the canonical target check is added to policy scope before approval;
@@ -96,6 +108,7 @@ policy.authorize(call) throws ─► refuse
96
108
  outside native file target ─► human-only one-call approval; eligible Full Permission may answer
97
109
  Bash workspace scope ─► hard-link scan, OS sandbox, run once
98
110
  Bash outside scope ─► pre-execution human-only approval, then run once unconfined
111
+ Bash on Windows (no sandbox) ─► as outside scope; plan-mode Bash refused
99
112
  trigger probe, improver, reflection or unattended ─► refuse anything requiring a person
100
113
  run.requestApproval(...) ─► standing approvals may answer where eligible, else the person
101
114
  denied ─► refuse; never replay a command
@@ -131,6 +144,8 @@ the switch and global tools.
131
144
  Full Permission switch can answer automatically under its existing restrictions. In plan mode, Bash
132
145
  runs only in the read-only scope (PROP-0043): no writes but a discarded temp folder, no network,
133
146
  no signals outside the sandbox, no macOS mach services; Full Permission and `outside` never apply.
147
+ On Windows, which has no sandbox, every Bash call takes the `outside` path and plan-mode Bash is
148
+ refused (ADR-0042).
134
149
  - **INV-GATE-4** Refinement runs (`probe`, `improver`) never ask a person; what would need one is
135
150
  refused, never queued (`INV-REF-4`).
136
151
  - **INV-GATE-5** SDK tools are registered only if their names are in the run's frozen capability
@@ -155,6 +170,7 @@ the switch and global tools.
155
170
  same choice as `!outside <command>`. Full Permission is the only standing boundary bypass and
156
171
  remains subject to host policy, authorization, read-only, plan, unattended, probe, improver and
157
172
  reflection restrictions. The rule does not protect against a peer process running as the same user.
173
+ On Windows the atomic replacement runs without an OS-enforced scope (ADR-0042).
158
174
 
159
175
  ## Data
160
176
 
@@ -164,14 +180,17 @@ the switch and global tools.
164
180
 
165
181
  `src/tools/*.ts`, `src/web/*.ts`, `src/sessions/sessions.ts`, `src/sessions/runner.ts`,
166
182
  `src/sessions/workspaceBoundary.ts`, `src/sessions/initialBash.ts`, `src/core/workspaceBashTool.ts`,
167
- `src/core/workspaceSandbox.ts`, `src/core/workspaceWriteOperations.ts`, `src/sessions/approvals.ts`,
168
- `src/sessions/policy.ts`. Decision: [ADR-0036](../decisions/ADR-0036-workspace-write-operation-boundary.md).
183
+ `src/core/shell.ts`, `src/core/workspaceSandbox.ts`, `src/core/workspaceWriteOperations.ts`,
184
+ `src/sessions/approvals.ts`, `src/sessions/policy.ts`. Decisions:
185
+ [ADR-0036](../decisions/ADR-0036-workspace-write-operation-boundary.md),
186
+ [ADR-0042](../decisions/ADR-0042-windows-shell-without-sandbox.md).
169
187
 
170
188
  ## Session naming (PROP-0010)
171
189
 
172
190
  `session_name` (`tools/sessionName.ts`) binds to the current native session. It maintains
173
191
  only Pi session metadata and is explicitly plan-safe, while still subject to capability
174
- selection and the host policy. The terminal registers the same definition through its Pi
192
+ selection and the host policy. The prompt asks for it once before the first other tool call when
193
+ a request needs tools or changes state. The terminal registers the same definition through its Pi
175
194
  bridge; standalone policy permits naming without approval. See page 02 for validation and
176
195
  persistence. It is a foundation tool, not mutable variant data.
177
196
 
@@ -181,3 +200,10 @@ persistence. It is a foundation tool, not mutable variant data.
181
200
  intersect current capabilities, and execute tool calls through the existing gate. Calls that
182
201
  require an additional per-call approval report blocked; batch diagnostic consent does not grant
183
202
  standing permission. No raw tool inputs, results, or screenshots enter diagnostic findings.
203
+
204
+ A live check may also run one command the harness wrote itself, when the capability it diagnoses is
205
+ a native Pi tool rather than a harness tool: the shell check runs `printf` through the same
206
+ workspace root, hard-link scan and write-boundary sandbox as a Bash call, and reports only the exit
207
+ status. It passes the gate first, and a diagnostic never widens the boundary — Full Permission,
208
+ an outside-workspace request and a host bypass are all refused for it — so a boundary that stops
209
+ the command before the shell starts is reported as blocked with the boundary's own reason.
@@ -38,7 +38,10 @@ skills, prompts, rules and Pi packages.
38
38
  - **`apps.expose(tools)`** offers the application's own tools through the broker, which is how a
39
39
  terminal session reaches them.
40
40
  - **Hub.** `hub.list`, `get`, `preview`, `install`, `uninstall`, `readDocument`. Pi packages need
41
- an exact npm version or a full Git commit. Documents are saved as inert JSON.
41
+ an exact npm version or a full Git commit. Documents are saved as inert JSON. The `/hub` Catalog
42
+ view filters Community entries for display; the service and other callers retain the full catalog.
43
+ Installed shows receipts from every channel. On page entry, cached/bundled content is shown before
44
+ a remote refresh, and origin, refresh time and failure status remain visible (PROP-0047).
42
45
 
43
46
  ## Invariants
44
47
 
@@ -62,7 +65,10 @@ skills, prompts, rules and Pi packages.
62
65
  nothing of it is stored.
63
66
  - **INV-MCP-4** Hub installation grants no attachment, trust, credential or permission. Writes
64
67
  are serialized; existing registry files are never overwritten; uninstall removes only the exact
65
- receipt's resources and revokes its attachment choices.
68
+ receipt's resources and revokes its attachment choices. Every removal route for a Hub-owned Pi
69
+ package, including `plugins.remove`, goes through Hub's receipt-owning uninstall operation. A
70
+ floating plugin-package update must not change a Hub-owned package; replacement uses an explicit
71
+ exact catalog version (PROP-0047).
66
72
 
67
73
  ## Data
68
74
 
@@ -40,7 +40,9 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
40
40
  `plugins.describe`.
41
41
  - `refine.start` takes `{ task, k?, mode?, improver?, executor?, baseVersion?, retainWorkspaces?, id? }`;
42
42
  `refine.candidates` returns each execution with `workspace: string | null` (page 05, PROP-0002, PROP-0003).
43
- - `runs.checklist { runId }` returns the run's latest checklist, `[]` when it wrote none (PROP-0006).
43
+ - `runs.todo { runId }` returns the run's latest todo list, `[]` when it wrote none (PROP-0006,
44
+ renamed by PROP-0045). `runs.checklist` is the deprecated pre-rename alias.
45
+ - `runs.continuation` returns `todo`; `checklist` remains a deprecated mirror of it for one release.
44
46
  - Run records include optional nullable `workspaceRoot`, the canonical root whose files a run may
45
47
  modify by default (page 02). New Harness runs set it; older records may omit it. Hosts must
46
48
  tolerate the additive field and must not nominate or widen the root.
@@ -49,15 +51,18 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
49
51
  and refuses an existing file; `agents.remove { cwd?, name, scope }` deletes a person's own file.
50
52
  `subagents.spawn` takes `agent` as a profile name and returns `agent` and `unavailableTools`
51
53
  (PROP-0029). It takes an optional `title` (at most six words); without one the child's title is
52
- the first line of its brief (PROP-0030).
54
+ the first line of its brief (PROP-0030). With `continue: <runId>` it continues a stopped child of
55
+ this conversation instead (no `agent` or `tools`; `brief` and `title` optional) and returns
56
+ `continued`, the run it continued (ADR-0043).
53
57
  - `runs.continuation { runId, sessionDir? }` returns a `Continuation` (its `checkpoint` is the last
54
58
  work-slice handoff), and `sessions.run` accepts `continueFrom` (page 02, PROP-0007) and `workSlice`
55
59
  (PROP-0041). `harness.status` reports `recovery.interruptedRunIds`.
56
60
  - `workSlice { enabled?, maxToolCalls?, maxMinutes?, maxNewTokens?, maxSlices?, continue? }` on
57
- `sessions.run` bounds that reply; absent uses 160 calls, 40 minutes, 320 000 new tokens, 8 slices and
58
- automatic continuation. A token cap counts new input, cache writes and output, never the cached
59
- prefix. `enabled: false` turns the guard off for that run; `XINGULAR_WORK_SLICE=off` in the
60
- launching process turns it off for every run in it, and nothing is persisted. The policy is
61
+ `sessions.run` bounds that reply; absent uses 320 calls, 60 minutes, no new-token cap, 8 slices and
62
+ automatic continuation. A token cap, when set, counts new input, cache writes and output, never the
63
+ cached prefix (PROP-0044). `enabled: false` turns the guard off for that run;
64
+ `XINGULAR_WORK_SLICE=off` in the launching process turns it off for every run in it, and nothing is
65
+ persisted. The policy is
61
66
  carried into the continuation. A value outside its range is refused with `invalid_request` before
62
67
  the run record is written.
63
68
  - The run-event stream adds `checkpoint` (the bounded handoff) and `heartbeat` (steps, elapsed time,
@@ -185,9 +190,11 @@ from preparation, never from the request.
185
190
  | `terminal.usage.summary\|limits` | `{ scope, period, timezoneOffsetMinutes }` / `{ refresh? }` | Existing usage service result, scoped to this terminal's account and project |
186
191
  | `terminal.usage.headers` | `{ provider, status, headers }` | `{}`; only limit-bearing headers, throttled, stored as an account limit reading |
187
192
 
188
- Protected `plugins.install { source }` and `plugins.remove { pluginId }` delegate to the package
189
- service. Optional matching callbacks extend `PluginControl`; hosts without them receive a clear
190
- unsupported-operation error. No protocol version or persisted schema changes.
193
+ Protected `plugins.install { source }`, `plugins.update { pluginId? }` and
194
+ `plugins.remove { pluginId }` delegate to the package service. Removing a Hub-owned package routes
195
+ through Hub's receipt-aware uninstall; a floating update refuses Hub-owned packages, while an
196
+ update-all skips them. Optional matching callbacks extend `PluginControl`; hosts without them
197
+ receive a clear unsupported-operation error. No protocol version or persisted schema changes.
191
198
 
192
199
  ## Worktrees (PROP-0016)
193
200
 
@@ -43,7 +43,7 @@ Screen: transcript above the composer, centred dialogs, full-screen resource bro
43
43
  per-tool grants do not widen it, and command output never triggers approval or replay.
44
44
  - The terminal compiles its prompt once (`compile` + `render`) and keeps that pack; each run
45
45
  records a copy (page 04). The shared compaction checkpoint extension reintroduces the active
46
- request and latest checklist into post-compaction model context until the run settles.
46
+ request and latest todo list into post-compaction model context until the run settles.
47
47
  - Normal mode keeps `ask_user` out of the active tool set. An attended plan request enables the
48
48
  shared tool alongside its read-only set and restores the normal set on success, failure or
49
49
  interruption. There is no terminal-only question alias (PROP-0040).
@@ -156,19 +156,29 @@ on close. No command text is sent to the conversation model. See [Doctor](../doc
156
156
 
157
157
  ## Resource browser (PROP-0013)
158
158
 
159
- `/harness` owns shared navigation for Foundation, Variant, Skills, Plugins, Connections, Tools
160
- and Library. `/skills`, `/plugins`, `/connections` (`/mcp`), `/tools`, `/hub` and `/components`
161
- are shortcuts into that browser. Current availability comes from the live resource loader and
162
- active tool registry, independently of saved configuration and the latest variant head.
159
+ `/harness` owns broad navigation for Foundation, Variant, Skills, Plugins, Connections, Tools and
160
+ Library. `/skills`, `/connections` (`/mcp`), `/tools` and `/components` are shortcuts into that
161
+ browser. `/plugins` opens the focused local plugin manager (Plugins, Trust and Packages tabs); `/hub`
162
+ opens the separate Community catalog (Catalog and Installed tabs). The Hub Catalog shows Community
163
+ entries across supported types; Installed retains receipts from every channel with its channel
164
+ visible. Registry/document entries offer bounded payload Preview; Pi packages do not. Current
165
+ availability in `/harness` comes from the live resource loader and active tool registry,
166
+ independently of saved configuration and the latest variant head.
163
167
 
164
168
  Every `terminal.browser.*` call requires the private control key, including bounded resource
165
- inspection, local imports, connection management and browser settings. Package install/remove use protected
166
- `plugins.install|remove`. These are adapters to the existing services, not another loader,
167
- attachment store, gate or secret store. Browsing neither executes plugin code nor connects MCP.
169
+ inspection, local imports, connection management and browser settings. Direct plugin package
170
+ install/update/remove and attachment/trust/settings actions use protected `plugins.*`; Hub catalog
171
+ list/install/uninstall use protected `hub.*`. Hub-owned package removal keeps the receipt and
172
+ resource ownership in the Hub service. These routes are adapters to the existing services, not
173
+ another loader, attachment store, gate or secret store. Browsing neither executes plugin code nor
174
+ connects MCP.
168
175
  The browser uses the full terminal with persistent section tabs (PROP-0014); wide screens keep
169
176
  inventory beside details, actions and content, while compact screens keep inline details under
170
- the same tabs. Other command pages remain centered except `/settings` and `/accounts`, which use
171
- full-screen page layouts. Accounts keeps Accounts/Pools tabs, search and account-service operations.
177
+ the same tabs. The separate `/plugins` and `/hub` pages also use full-screen layouts with persistent
178
+ section tabs, responsive inventory/details panes and their existing protected operations. Other
179
+ command pages remain centered except `/settings`, `/accounts`, `/plugins` and `/hub`, which use
180
+ full-screen page layouts.
181
+ Accounts keeps Accounts/Pools tabs, search and account-service operations.
172
182
  Wide terminals show selected-account details beside the list; Enter or a primary click opens grouped
173
183
  actions in that inspector. Compact terminals replace the list with a full-page account detail view
174
184
  and its grouped actions. Enter opens the selected account; Escape returns to the list while
@@ -262,20 +272,24 @@ The annotate pane (PROP-0018) is a full-screen page beside the window being insp
262
272
  - **Other keys:** `s` sends the queue as one run of this session, confirming notes that came from a page-world script first; `x` takes a note out of the queue; `t` picks a window.
263
273
  - **Routes:** `terminal.annotations.target|attach|windows|selectWindow|inspect|stopInspect|next|queue|dequeue|confirm|send` act only on this terminal's session and need the control key.
264
274
 
265
- ## Checklist (PROP-0006, PAR-001)
275
+ ## Todo list (PROP-0006, PROP-0045, PAR-001)
266
276
 
267
- Terminal sessions register the shared `checklist_write` tool. The extension validates each list
268
- with the same tool code and sends it as `checklist` telemetry; the controller emits it as
269
- `checklist.updated` on the active run, so `runs.checklist` and continuation read terminal runs too.
270
- The gate treats it as read-only, plan mode allows it, and terminal children inherit it. The
271
- transcript shows each write as a checklist block (`✓` done, `●` in progress (warning yellow), `○` pending) under a
272
- `Checklist · n of m done` header instead of a tool row; a failed or malformed call stays a tool row.
277
+ Terminal sessions register the shared `todo_write` tool. The extension validates each list with
278
+ the same tool code and sends it as `todo` telemetry; the controller emits it as `todo.updated` on the
279
+ active run, so `runs.todo` and continuation read terminal runs too. The gate treats it as read-only,
280
+ plan mode allows it, and terminal children inherit it. The transcript shows each write as a todo
281
+ block (`✓` done, `●` in progress (warning yellow), `○` pending) under a `Todo · n of m done` header
282
+ instead of a tool row; a failed or malformed call stays a tool row. `/todo` reads the latest
283
+ non-side-question run of this terminal's native session and appends the same card as a snapshot,
284
+ without a model request; an empty list is a one-line notice. `/checklist` remains its alias for one
285
+ release.
273
286
 
274
287
  ## Work-slice checkpoint (PROP-0041)
275
288
 
276
- Terminal replies carry the same work-slice guard as structured runs: 160 tool calls, 40 minutes or
277
- 320 000 new tokens, then a refusal that asks for `checkpoint_write`. The extension registers the shared
278
- tool and sends it as `checkpoint` telemetry, which the controller records as `checkpoint` on the
289
+ Terminal replies carry the same work-slice guard as structured runs: 320 tool calls or 60 minutes,
290
+ with no new-token limit by default (PROP-0044), then a refusal that asks for `checkpoint_write`. The
291
+ extension registers the shared tool and sends it as `checkpoint` telemetry, which the controller
292
+ records as `checkpoint` on the
279
293
  active run, so an App reading the same session sees the handoff. Terminal replies are not
280
294
  auto-continued: at the boundary the person decides, which is what the terminal's own turn model
281
295
  already does. The run record says `interrupted` with terminal reason `slice_complete` (or `stalled`
@@ -288,13 +302,13 @@ boundary at all; it is not persisted, so the next launch without it restores the
288
302
  During an active parent run, the terminal polls a private read-only monitor once per second. It
289
303
  projects the flat set of child and nested-child runs with task, status, elapsed time, the latest
290
304
  tool name, the child's agent profile (name and colour, PROP-0029), the title the parent gave it
291
- (PROP-0030), counts from the child's own checklist, the pinned account label, effective model and
305
+ (PROP-0030), counts from the child's own todo list, the pinned account label, effective model and
292
306
  effort, and cumulative usage totals. Model and effort come from the volatile launch selection; the
293
307
  latest provider-reported model supersedes the launch model when usage is available. Usage is an
294
308
  explicit projection of token, cache, cost, request-count and context-window totals. Per-request
295
309
  payloads and reasoning summaries do not enter the monitor. The child's own `session_name` is not
296
310
  projected; it names the child's session, not its row. Tool summaries, other arguments, output and
297
- checklist item text never enter the monitor. The latest completed tool name remains visible across
311
+ todo item text never enter the monitor. The latest completed tool name remains visible across
298
312
  one-second snapshots until new tool or response activity replaces it. The monitor exposes no
299
313
  controls to steer or stop children.
300
314
 
@@ -302,15 +316,26 @@ The live rows sit under the status line, after one blank row, with no heading. E
302
316
  order: the status mark (`○` queued, a running row that shows the working spinner's frame in the profile's colour (warning for a copy of the parent), `●` waiting in the accent,
303
317
  `✓` done, `✕` failed, `!` stopped), the profile name in its colour (`subagent`, muted, for a copy
304
318
  of the parent), the title the parent gave the child (PROP-0030), and `n of m tasks` when the child
305
- keeps a checklist. Active rows come first, at most three, then `+N more · /subagents`; a narrow
319
+ keeps a todo list. Active rows come first, at most three, then `+N more · /subagents`; a narrow
306
320
  terminal cuts the title first. `/subagents` opens the searchable full roster, with a colored
307
321
  profile and normal-color title on its first line, then muted account, model, effort and usage
308
322
  metadata on its second line. One blank row separates each two-line entry. Narrow rows truncate this
309
323
  lower-priority summary without hiding the title.
310
324
  At parent settlement, the terminal makes a final monitor read and keeps the latest parent's rows
311
- visible until the next parent run starts. The projection remains volatile and read-only, is scoped to
312
- the latest parent run in the terminal session, and is cleared on session replacement or terminal
313
- disposal. It is not a persisted event or public server method.
325
+ visible until the next parent run starts.
326
+
327
+ The monitor also projects the parent run itself as a `main` row (profile `main`, a reserved name,
328
+ in the theme's primary colour) with the same account, model, effort, usage, activity and todo
329
+ fields. The `/subagents` page pins it first and counts only children in its header; the rows under
330
+ the status line omit it, since the status line already describes the main agent.
331
+
332
+ Every turn marks its run on the native branch (`xingular-subagent-owner`), and `ready` sends those
333
+ owners. When a conversation opens or is switched to with no run active, the monitor is rebuilt from
334
+ the branch's latest top-level run in this folder and its descendants, by folding their saved events
335
+ with their final status. Runs a stopped process left active were already marked `interrupted`.
336
+ The rows show under the status line and on the page until the next parent run starts (ADR-0043).
337
+ The projection remains read-only and scoped to one parent run; a switch to a conversation with no
338
+ such run clears it, as does terminal disposal. It is not a persisted event or public server method.
314
339
 
315
340
  ## Agent profiles (PROP-0029)
316
341