@jaggerxtrm/specialists 3.17.0 → 3.18.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 (246) hide show
  1. package/README.md +268 -134
  2. package/config/mandatory-rules/json-only-final-output.md +13 -0
  3. package/config/mandatory-rules/service-skills-diff-scan-mandatory.md +26 -0
  4. package/config/mandatory-rules/service-skills-gitnexus-triage.md +5 -0
  5. package/config/skills/setup-specialists/SKILL.md +556 -0
  6. package/config/skills/specialists-creator/SKILL.md +132 -4
  7. package/config/skills/specialists-creator/scripts/audit-spec-uniformity.mjs +1 -1
  8. package/config/specialists/bare.specialist.json +3 -3
  9. package/config/specialists/changelog-drafter.specialist.json +5 -4
  10. package/config/specialists/changelog-keeper.specialist.json +7 -6
  11. package/config/specialists/debugger.specialist.json +2 -2
  12. package/config/specialists/executor.specialist.json +2 -2
  13. package/config/specialists/explorer.specialist.json +4 -4
  14. package/config/specialists/memory-processor.specialist.json +3 -3
  15. package/config/specialists/node-coordinator.specialist.json +3 -3
  16. package/config/specialists/obligations-scanner.specialist.json +67 -17
  17. package/config/specialists/overthinker.specialist.json +3 -3
  18. package/config/specialists/planner.specialist.json +4 -4
  19. package/config/specialists/quant-methodologist.specialist.json +145 -0
  20. package/config/specialists/quant-researcher.specialist.json +144 -0
  21. package/config/specialists/researcher.specialist.json +5 -5
  22. package/config/specialists/reviewer.specialist.json +1 -1
  23. package/config/specialists/seconder.specialist.json +2 -2
  24. package/config/specialists/security-auditor.specialist.json +2 -2
  25. package/config/specialists/service-skills-sync.specialist.json +90 -75
  26. package/config/specialists/specialists-creator.specialist.json +4 -4
  27. package/config/specialists/sync-docs.specialist.json +4 -4
  28. package/config/specialists/test-engineer.specialist.json +3 -3
  29. package/config/specialists/test-runner.specialist.json +7 -7
  30. package/config/specialists/transcriber.specialist.json +3 -3
  31. package/config/specialists/xt-merge.specialist.json +4 -4
  32. package/dist/asset-contract.json +21 -2
  33. package/dist/index.js +25704 -16376
  34. package/dist/lib.js +9849 -6147
  35. package/dist/types/cli/console/components.d.ts +83 -0
  36. package/dist/types/cli/console/components.d.ts.map +1 -0
  37. package/dist/types/cli/console/config-source.d.ts +58 -0
  38. package/dist/types/cli/console/config-source.d.ts.map +1 -0
  39. package/dist/types/cli/console/forensic.d.ts +11 -0
  40. package/dist/types/cli/console/forensic.d.ts.map +1 -0
  41. package/dist/types/cli/console/git.d.ts +28 -0
  42. package/dist/types/cli/console/git.d.ts.map +1 -0
  43. package/dist/types/cli/console/help.d.ts +2 -0
  44. package/dist/types/cli/console/help.d.ts.map +1 -0
  45. package/dist/types/cli/console/log.d.ts +13 -0
  46. package/dist/types/cli/console/log.d.ts.map +1 -0
  47. package/dist/types/cli/console/repo-config.d.ts +26 -0
  48. package/dist/types/cli/console/repo-config.d.ts.map +1 -0
  49. package/dist/types/cli/console/repo-discovery.d.ts +12 -0
  50. package/dist/types/cli/console/repo-discovery.d.ts.map +1 -0
  51. package/dist/types/cli/console/runtime.d.ts +12 -0
  52. package/dist/types/cli/console/runtime.d.ts.map +1 -0
  53. package/dist/types/cli/console/subscribe-prototype.d.ts +18 -0
  54. package/dist/types/cli/console/subscribe-prototype.d.ts.map +1 -0
  55. package/dist/types/cli/console/theme.d.ts +91 -0
  56. package/dist/types/cli/console/theme.d.ts.map +1 -0
  57. package/dist/types/cli/console/types.d.ts +231 -0
  58. package/dist/types/cli/console/types.d.ts.map +1 -0
  59. package/dist/types/cli/console/view-model.d.ts +252 -0
  60. package/dist/types/cli/console/view-model.d.ts.map +1 -0
  61. package/dist/types/cli/console.d.ts +2 -0
  62. package/dist/types/cli/console.d.ts.map +1 -0
  63. package/dist/types/cli/db.d.ts.map +1 -1
  64. package/dist/types/cli/doctor.d.ts.map +1 -1
  65. package/dist/types/cli/edit.d.ts.map +1 -1
  66. package/dist/types/cli/epic.d.ts.map +1 -1
  67. package/dist/types/cli/feed.d.ts.map +1 -1
  68. package/dist/types/cli/forensic.d.ts +2 -0
  69. package/dist/types/cli/forensic.d.ts.map +1 -0
  70. package/dist/types/cli/format-helpers.d.ts +4 -2
  71. package/dist/types/cli/format-helpers.d.ts.map +1 -1
  72. package/dist/types/cli/help.d.ts.map +1 -1
  73. package/dist/types/cli/init.d.ts +10 -0
  74. package/dist/types/cli/init.d.ts.map +1 -1
  75. package/dist/types/cli/list.d.ts.map +1 -1
  76. package/dist/types/cli/log.d.ts.map +1 -1
  77. package/dist/types/cli/metrics.d.ts +2 -0
  78. package/dist/types/cli/metrics.d.ts.map +1 -0
  79. package/dist/types/cli/ps.d.ts.map +1 -1
  80. package/dist/types/cli/result.d.ts.map +1 -1
  81. package/dist/types/cli/run.d.ts +1 -0
  82. package/dist/types/cli/run.d.ts.map +1 -1
  83. package/dist/types/cli/script.d.ts +3 -0
  84. package/dist/types/cli/script.d.ts.map +1 -1
  85. package/dist/types/cli/serve.d.ts.map +1 -1
  86. package/dist/types/cli/setup.d.ts +19 -1
  87. package/dist/types/cli/setup.d.ts.map +1 -1
  88. package/dist/types/cli/status.d.ts.map +1 -1
  89. package/dist/types/cli/version-check.d.ts +1 -0
  90. package/dist/types/cli/version-check.d.ts.map +1 -1
  91. package/dist/types/index.d.ts +1 -1
  92. package/dist/types/pi/session.d.ts +11 -1
  93. package/dist/types/pi/session.d.ts.map +1 -1
  94. package/dist/types/server.d.ts +15 -0
  95. package/dist/types/server.d.ts.map +1 -1
  96. package/dist/types/specialist/benchmarks.d.ts +37 -0
  97. package/dist/types/specialist/benchmarks.d.ts.map +1 -0
  98. package/dist/types/specialist/chain-identity.d.ts +7 -1
  99. package/dist/types/specialist/chain-identity.d.ts.map +1 -1
  100. package/dist/types/specialist/control.d.ts.map +1 -1
  101. package/dist/types/specialist/forensic-events.d.ts +138 -0
  102. package/dist/types/specialist/forensic-events.d.ts.map +1 -0
  103. package/dist/types/specialist/forensic-renderer.d.ts +34 -0
  104. package/dist/types/specialist/forensic-renderer.d.ts.map +1 -0
  105. package/dist/types/specialist/git-diff-evidence.d.ts +28 -0
  106. package/dist/types/specialist/git-diff-evidence.d.ts.map +1 -0
  107. package/dist/types/specialist/global-config.d.ts +389 -0
  108. package/dist/types/specialist/global-config.d.ts.map +1 -0
  109. package/dist/types/specialist/launch.d.ts +1 -0
  110. package/dist/types/specialist/launch.d.ts.map +1 -1
  111. package/dist/types/specialist/live-aggregates.d.ts +46 -0
  112. package/dist/types/specialist/live-aggregates.d.ts.map +1 -0
  113. package/dist/types/specialist/loader.d.ts +50 -1
  114. package/dist/types/specialist/loader.d.ts.map +1 -1
  115. package/dist/types/specialist/model-chain.d.ts +7 -0
  116. package/dist/types/specialist/model-chain.d.ts.map +1 -0
  117. package/dist/types/specialist/model-probes.d.ts +28 -0
  118. package/dist/types/specialist/model-probes.d.ts.map +1 -0
  119. package/dist/types/specialist/node-contract.d.ts +18 -18
  120. package/dist/types/specialist/node-supervisor.d.ts.map +1 -1
  121. package/dist/types/specialist/observability-db.d.ts +1 -1
  122. package/dist/types/specialist/observability-db.d.ts.map +1 -1
  123. package/dist/types/specialist/observability-sqlite.d.ts +25 -0
  124. package/dist/types/specialist/observability-sqlite.d.ts.map +1 -1
  125. package/dist/types/specialist/preset-resolver.d.ts +56 -0
  126. package/dist/types/specialist/preset-resolver.d.ts.map +1 -0
  127. package/dist/types/specialist/prometheus-projection.d.ts +25 -0
  128. package/dist/types/specialist/prometheus-projection.d.ts.map +1 -0
  129. package/dist/types/specialist/runner.d.ts +26 -1
  130. package/dist/types/specialist/runner.d.ts.map +1 -1
  131. package/dist/types/specialist/schema.d.ts +163 -54
  132. package/dist/types/specialist/schema.d.ts.map +1 -1
  133. package/dist/types/specialist/script-runner.d.ts +5 -1
  134. package/dist/types/specialist/script-runner.d.ts.map +1 -1
  135. package/dist/types/specialist/snapshot-diff.d.ts +8 -0
  136. package/dist/types/specialist/snapshot-diff.d.ts.map +1 -0
  137. package/dist/types/specialist/source-queue.d.ts +13 -0
  138. package/dist/types/specialist/source-queue.d.ts.map +1 -0
  139. package/dist/types/specialist/supervisor.d.ts +15 -1
  140. package/dist/types/specialist/supervisor.d.ts.map +1 -1
  141. package/dist/types/specialist/timeline-events.d.ts +68 -1
  142. package/dist/types/specialist/timeline-events.d.ts.map +1 -1
  143. package/dist/types/tools/specialist/resume_specialist.tool.d.ts +4 -4
  144. package/dist/types/tools/specialist/specialist_status.tool.d.ts +1 -1
  145. package/dist/types/tools/specialist/steer_specialist.tool.d.ts +4 -4
  146. package/dist/types/tools/specialist/use_specialist.tool.d.ts +16 -16
  147. package/docs/ARCHITECTURE.md +1176 -0
  148. package/docs/TODO.md +9 -0
  149. package/docs/architecture.md +11 -0
  150. package/docs/archive/2026-03-13-bd-decision-context-template-plan.md +96 -0
  151. package/docs/archive/AGENT-HANDOFF.md +351 -0
  152. package/docs/archive/PARITY-ANALYSIS.md +296 -0
  153. package/docs/archive/SPECIALISTS_REFACTOR.md.md +30 -0
  154. package/docs/archive/cc-programmatic.md +216 -0
  155. package/docs/archive/claude-agent-sdk.md +594 -0
  156. package/docs/archive/decision-specialist-directory.md +41 -0
  157. package/docs/archive/discoveries.md +148 -0
  158. package/docs/archive/executor-benchmark-protocol.md +198 -0
  159. package/docs/archive/future-features.md +66 -0
  160. package/docs/archive/gzrx-completion-critique.md +183 -0
  161. package/docs/archive/gzrx-research-notes.md +401 -0
  162. package/docs/archive/gzrx-tool-catalog.md +760 -0
  163. package/docs/archive/iron-review-hardening-qa-chain-substrate.md +322 -0
  164. package/docs/archive/iron-review-hardening.html +1004 -0
  165. package/docs/archive/issuetracking.md +312 -0
  166. package/docs/archive/qa-v3.0.2.md +220 -0
  167. package/docs/archive/restructure.md +231 -0
  168. package/docs/archive/script-specialists.md +1254 -0
  169. package/docs/archive/spec-v3.md +792 -0
  170. package/docs/archive/specialist-stats.md +127 -0
  171. package/docs/archive/specialists-friction-audit.md +1347 -0
  172. package/docs/archive/specialists-runtime-critique.md +170 -0
  173. package/docs/archive/specialists-service-evaluation.md +713 -0
  174. package/docs/archive/specialists-substrate-alignment.md +255 -0
  175. package/docs/archive/substrate-review.md +1288 -0
  176. package/docs/archive/test-writer-specialist.md +254 -0
  177. package/docs/archive/using-specialists-v3-improvements-2026-05-09.md +600 -0
  178. package/docs/archive/xtrm-specialists-analysis.md +314 -0
  179. package/docs/authoring.md +701 -0
  180. package/docs/background-jobs.md +203 -0
  181. package/docs/bare-specialists.md +83 -0
  182. package/docs/benchmarks/executor-benchmark-runner.md +66 -0
  183. package/docs/bootstrap.md +161 -0
  184. package/docs/cli-reference.md +1645 -0
  185. package/docs/deploying-alongside.md +155 -0
  186. package/docs/design/README.md +36 -0
  187. package/docs/design/darth-feedor-migration.md +290 -0
  188. package/docs/design/roadmap/README.md +32 -0
  189. package/docs/design/roadmap/chain-templates/README.md +146 -0
  190. package/docs/design/roadmap/chain-templates/code-quick.formula.json +27 -0
  191. package/docs/design/roadmap/chain-templates/code-standard.formula.json +126 -0
  192. package/docs/design/roadmap/chain-templates/code-with-advisors.formula.json +128 -0
  193. package/docs/design/roadmap/chain-templates/code-with-tests.formula.json +76 -0
  194. package/docs/design/roadmap/chain-templates/debug.formula.json +128 -0
  195. package/docs/design/roadmap/chain-templates/doc-sync.formula.json +28 -0
  196. package/docs/design/roadmap/chain-templates/memory-hygiene.formula.json +27 -0
  197. package/docs/design/roadmap/chain-templates/planning.formula.json +27 -0
  198. package/docs/design/roadmap/chain-templates/premortem.formula.json +26 -0
  199. package/docs/design/roadmap/chain-templates/release-prep.formula.json +36 -0
  200. package/docs/design/roadmap/chain-templates/research-only.formula.json +28 -0
  201. package/docs/design/roadmap/chain-templates/restitch.formula.json +125 -0
  202. package/docs/design/roadmap/chain-templates/security-deep.formula.json +161 -0
  203. package/docs/design/roadmap/chain-templates/test-only.formula.json +52 -0
  204. package/docs/design/roadmap/chain-templates/triage.formula.json +35 -0
  205. package/docs/design/roadmap/history/handoff-from-substrate-design.md +87 -0
  206. package/docs/design/roadmap/history/substrate-reconciliation.md +105 -0
  207. package/docs/design/roadmap/specialists-roadmap.md +1193 -0
  208. package/docs/design/sp-console-subscribe-via-materializer.md +231 -0
  209. package/docs/design/sp-console-tui-mock-v2.html +293 -0
  210. package/docs/design/sp-console-tui-mock.html +120 -0
  211. package/docs/design/sp-console-tui.md +340 -0
  212. package/docs/design/specialist-agentops-suite.md +323 -0
  213. package/docs/design/substrate/channels.md +14 -0
  214. package/docs/design/substrate/devops-platform-engineering-prd.md +446 -0
  215. package/docs/design/substrate/html-design-example.md +339 -0
  216. package/docs/design/xtrm-tiers-architecture.svg +132 -0
  217. package/docs/devops/dependency-verdict-materialization.md +46 -0
  218. package/docs/epic-readiness.md +75 -0
  219. package/docs/examples/mercury-atomic-summarizer.specialist.json +26 -0
  220. package/docs/examples/smoke-echo-text-expected-keys.specialist.json +25 -0
  221. package/docs/examples/smoke-echo.specialist.json +25 -0
  222. package/docs/features.md +1577 -0
  223. package/docs/hooks.md +81 -0
  224. package/docs/installation.md +142 -0
  225. package/docs/manifest.md +184 -0
  226. package/docs/mcp-servers.md +73 -0
  227. package/docs/mcp-tools.md +71 -0
  228. package/docs/nodes.md +231 -0
  229. package/docs/observability-metrics.md +152 -0
  230. package/docs/operator/sp-console-v2-walkthrough.md +410 -0
  231. package/docs/overrides-guide.md +306 -0
  232. package/docs/pi-rpc-boundary.md +118 -0
  233. package/docs/pi-session.md +195 -0
  234. package/docs/release.md +22 -0
  235. package/docs/skills.md +132 -0
  236. package/docs/specialists/handoff-schema.md +181 -0
  237. package/docs/specialists-catalog.md +99 -0
  238. package/docs/specialists-service-install.md +226 -0
  239. package/docs/specialists-service.md +363 -0
  240. package/docs/surface-ownership.md +138 -0
  241. package/docs/upgrade-notes/kan-90-global-user-config.md +114 -0
  242. package/docs/upgrade-notes/kan-91-expanded-overrides.md +261 -0
  243. package/docs/workflow.md +114 -0
  244. package/docs/worktree.md +71 -0
  245. package/docs/worktrees.md +309 -0
  246. package/package.json +6 -3
@@ -0,0 +1,1577 @@
1
+ ---
2
+ title: Feature Guides
3
+ scope: runtime-features
4
+ category: guide
5
+ version: 2.5.0
6
+ updated: 2026-06-23
7
+ synced_at: bf6baf7a
8
+ description: Practical guides for structured output, job observation, bead-linked runs, keep-alive resume, worktree isolation, stuck detection, waiting state observability, auto gitnexus sync, specialist authoring, config presets, JSON-first configuration, context denormalization, and job lineage tracking.
9
+ source_of_truth_for:
10
+ - "src/cli/run.ts"
11
+ - "src/cli/feed.ts"
12
+ - "src/cli/result.ts"
13
+ - "src/cli/resume.ts"
14
+ - "src/specialist/supervisor.ts"
15
+ - "src/specialist/schema.ts"
16
+ - "src/specialist/job-root.ts"
17
+ - "src/specialist/worktree.ts"
18
+ - "src/specialist/worktree-gc.ts"
19
+ - "src/cli/edit.ts"
20
+ - "src/specialist/loader.ts"
21
+ - "src/cli/ps.ts"
22
+ - "src/cli/epic.ts"
23
+ - "src/cli/end.ts"
24
+ - "src/cli/merge.ts"
25
+ - "src/specialist/epic-lifecycle.ts"
26
+ - "src/specialist/chain-identity.ts"
27
+ ---
28
+
29
+ # Feature Guides
30
+
31
+ > `sp` is an alias for `specialists`.
32
+
33
+ ## 1) Structured run output modes (`human`, `--json`, `--raw`)
34
+
35
+ `specialists run` supports three foreground output modes.
36
+
37
+ ### Human mode (default)
38
+
39
+ ```bash
40
+ sp run executor --prompt "Investigate failing tests"
41
+ ```
42
+
43
+ - Shows formatted timeline events (debounced to reduce noise)
44
+ - Prints final assistant output when `run_complete` arrives
45
+ - Prints job footer to stderr with `job`, optional `bead`, elapsed time, model/backend
46
+
47
+ ### JSON mode (`--json`)
48
+
49
+ ```bash
50
+ sp run executor --prompt "Investigate failing tests" --json
51
+ ```
52
+
53
+ - Streams NDJSON, one event per line
54
+ - Each event envelope includes `jobId`, `specialist`, optional `beadId`, plus timeline event fields
55
+ - Model/backend banner still prints to stderr
56
+
57
+ ### Raw mode (`--raw`)
58
+
59
+ ```bash
60
+ sp run executor --prompt "Investigate failing tests" --raw
61
+ ```
62
+
63
+ - Legacy stream of raw progress deltas (`onProgress`) to stdout
64
+ - Useful for backward compatibility with older parsers
65
+ - Does not tail `events.jsonl` formatting
66
+
67
+ ### Mode selection rules
68
+
69
+ - Default is `human`
70
+ - `--json` switches to structured event stream
71
+ - `--raw` switches to legacy progress stream
72
+ - If both are passed, the last flag wins
73
+
74
+ ---
75
+
76
+ ## 2) Job observation: `feed`, `ps`, `result`
77
+
78
+ All observation reads DB-backed runtime state first. Legacy/operator mirrors under:
79
+
80
+ ```text
81
+ Legacy fallback artifacts (`observability.db` is primary runtime store):
82
+ .specialists/jobs/<job-id>/
83
+ status.json
84
+ events.jsonl
85
+ result.txt
86
+ ```
87
+
88
+ ### SQLite persistence (schema v4)
89
+
90
+ When SQLite is available, Supervisor uses it as the primary storage backend. File-based fallback is legacy/operator-only:
91
+
92
+ - **`specialist_jobs` table**: status, bead_id, node_id, worktree_path, branch, last_output, elapsed_ms
93
+ - **`specialist_events` table**: append-only timeline with event_json (JSON-first design)
94
+ - **Node tables** (schema v4): `node_runs`, `node_members`, `node_events`, `node_memory` for orchestrator tracking
95
+ - **Dual-write**: atomic transactions at job start/completion; mid-run writes are standalone for resilience
96
+ - **Backward compatible**: file-based storage remains available only for recovery/debug tooling when SQLite is unavailable
97
+
98
+ ### `feed` (timeline-first)
99
+
100
+ ```bash
101
+ sp feed <job-id>
102
+ sp feed <job-id> --follow
103
+ sp feed -f --forever
104
+ sp feed --json --since 5m --limit 200
105
+ ```
106
+
107
+ - Best for timeline/event visibility
108
+ - Snapshot mode: replay matching events
109
+ - Follow mode (`-f`): polls and appends new events in chronological order
110
+ - JSON mode outputs NDJSON envelopes with job metadata + event payload
111
+ - **Waiting state**: when a keep-alive job enters `waiting` status, feed displays a magenta `WAIT` banner with resume instructions
112
+ - **Text preview**: `TURN+` lines show 80-char preview of accumulated text content
113
+ - **Context warnings**: feed displays context utilization warnings at WARN/CRITICAL thresholds
114
+ - **Startup context lines**: on `run_start` events with `startup_snapshot`, emits dimmed `↳ startup` summary (job, specialist, bead, worktree, branch, vars, skills); on `meta` events with `memory_injection`, emits `↳ memory` token accounting line (static, dynamic, gitnexus, total)
115
+
116
+ ### `result` (final text)
117
+
118
+ ```bash
119
+ sp result <job-id>
120
+ sp result <job-id> --wait --timeout 120
121
+ ```
122
+
123
+ - Prints `result.txt`
124
+ - `--wait` polls until `done`/`error`
125
+ - `--timeout` applies only with `--wait`
126
+ - **Waiting state**: when status is `waiting`, result prints a footer with resume instructions
127
+ - **SQLite-backed**: reads from `specialist_jobs.last_output` column when available
128
+ - **Startup context block**: derives startup snapshot from `status.json.startup_context` merged with `run_start` event + `meta` memory_injection. Prepends `--- startup context ---` block in human mode; adds `startup_context` field in `--json` mode
129
+
130
+ Use `result` when you want final plain text; use `feed` when you want event history and incremental state.
131
+
132
+ ### Current tool staleness fix (April 2026)
133
+
134
+ `sp ps` exposes `current_tool` to show which tool a job is executing. Prior to April 2026, this field was stale because:
135
+
136
+ 1. `current_tool` was set on `tool_execution_start` but never cleared on `tool_execution_end`
137
+ 2. `sp ps` read from `status.json` snapshot, not the live event stream
138
+
139
+ **Fix (unitAI-66xn, unitAI-yke7):**
140
+
141
+ - **Read side**: `sp ps` now derives `current_tool` from `specialist_events` table, querying the latest tool event (start/update/end) instead of trusting `status.json`
142
+ - **Write side**: Supervisor clears `current_tool: undefined` in `onToolEndCallback` on every `tool_execution_end`
143
+
144
+ This prevents false-positive "hung job" diagnoses where `sp ps` showed a stale tool (e.g., `gitnexus_context`) while the model was actively streaming text.
145
+
146
+ ---
147
+
148
+ ## 2a) Console TUI (`sp console`)
149
+
150
+ `sp console` provides an interactive TUI for monitoring and controlling jobs across multiple repos.
151
+
152
+ ### ALL view (multi-repo overview)
153
+
154
+ The ALL view shows active jobs from all configured repos in a single scrollable list.
155
+
156
+ **Navigation:**
157
+ - `↑↓` or `j/k` — move cursor through selectable job rows (skips headers/spacers)
158
+ - `0` — reset cursor to top and switch to ALL view
159
+
160
+ **Actions (cursor on job row):**
161
+ - `↵` (Enter) — open feed for selected job
162
+ - `r` — open result for selected job
163
+ - `i` — inspect job details
164
+ - `b` — open bead view for the job's input bead
165
+ - `d` — open diff view for the job's worktree changes
166
+
167
+ **Repo selection:**
168
+ - `Tab` — cycle to next repo tab
169
+ - `1-9` — jump to repo by index
170
+
171
+ **Other keys:**
172
+ - `q` — quit console
173
+ - `g` — open global config view (from ps view)
174
+ - `R` — open repo config view (from ps view)
175
+ - `x` — stop selected job (from ps/all view)
176
+
177
+ The ALL view auto-scrolls to keep the cursor visible and auto-advances off non-selectable rows (headers/spacers) on first render.
178
+
179
+ ---
180
+
181
+ Use an existing bead as the run input source:
182
+
183
+ ```bash
184
+ sp run executor --bead unitAI-123
185
+ ```
186
+
187
+ Behavior:
188
+
189
+ - Reads bead content via `bd show --json`
190
+ - Builds full run prompt from bead context (`buildBeadContext(...)`)
191
+ - Injects variables:
192
+ - `$bead_context`
193
+ - `$bead_id`
194
+ - Adds `bead_id` to status and timeline (`run_start`, status footer)
195
+ - **Schema v2**: `bead_id` persisted as dedicated column in `specialist_jobs` table (backfilled from status_json)
196
+
197
+ ### Dependency context injection
198
+
199
+ By default, `--bead` injects completed blockers at depth 1.
200
+
201
+ ```bash
202
+ sp run executor --bead unitAI-123 --context-depth 2
203
+ sp run executor --bead unitAI-123 --context-depth 0 # disable blocker injection
204
+ ```
205
+
206
+ ### Tracking control
207
+
208
+ ```bash
209
+ sp run executor --bead unitAI-123 --no-beads
210
+ ```
211
+
212
+ - `--no-beads` disables bead tracking/updates
213
+ - Bead reading still works (run input still comes from `--bead`)
214
+
215
+ ### Prompt source exclusivity
216
+
217
+ `--prompt` and `--bead` are mutually exclusive.
218
+
219
+ ---
220
+
221
+ ## 4) Keep-alive + resume (`--keep-alive`, `--no-keep-alive`, `resume`)
222
+
223
+ Keep a session alive for multi-turn flows:
224
+
225
+ ```bash
226
+ sp run executor --prompt "Analyze this bug" --keep-alive
227
+ ```
228
+
229
+ Interactive specialists can enable this by default in YAML:
230
+
231
+ ```yaml
232
+ specialist:
233
+ execution:
234
+ interactive: true
235
+ ```
236
+
237
+ Default behavior and precedence:
238
+
239
+ 1. `--no-keep-alive` / `no_keep_alive` forces one-shot mode
240
+ 2. `--keep-alive` / `keep_alive` forces keep-alive
241
+ 3. Otherwise, runner uses merged `execution.interactive` (package spec → `~/.config/specialists/user.json` → repo override)
242
+ 4. If unset, default is one-shot (`false`)
243
+
244
+ Supervisor behavior in keep-alive mode:
245
+
246
+ - Creates FIFO: `.specialists/jobs/<job-id>/steer.pipe`
247
+ - On first turn completion, job status becomes `waiting`
248
+ - Emits `status_change` timeline event with `status: "waiting"` and `previous_status: "running"`
249
+ - Session stays alive with full conversation history retained
250
+
251
+ Resume with a next-turn task:
252
+
253
+ ```bash
254
+ sp resume <job-id> "Now implement the fix and add tests"
255
+ ```
256
+
257
+ Rules:
258
+
259
+ - `resume` is valid only when status is `waiting`
260
+ - If status is `running`, use `steer`/`steer_specialist` (mid-turn guidance)
261
+ - `resume` writes `{type:"resume", task:"..."}` to FIFO
262
+ - After resume turn finishes, status returns to `waiting` until closed
263
+
264
+ ### Waiting state observability
265
+
266
+ When a keep-alive job enters the `waiting` state, the system provides multiple observation signals:
267
+
268
+ **Timeline event** (`events.jsonl`):
269
+ ```json
270
+ {"t": 1743883200000, "type": "status_change", "status": "waiting", "previous_status": "running"}
271
+ ```
272
+
273
+ **Feed output** (`sp feed <job-id>`):
274
+ ```
275
+ WAIT executor (49adda) is waiting for input. Use: specialists resume 49adda "..."
276
+ ```
277
+ - Displayed in **magenta** to distinguish from running/done states
278
+ - Shows specialist name, job ID, and exact resume command
279
+
280
+ **Status output** (`sp status --job <job-id>`):
281
+ ```
282
+ status waiting
283
+ action specialists resume 49adda "..."
284
+ ```
285
+ - Status field rendered in magenta
286
+ - `action` row shows the resume command to use
287
+
288
+ **Result footer** (`sp result <job-id>`):
289
+ ```
290
+ --- Session is waiting for your input. Use: specialists resume 49adda "..." ---
291
+ ```
292
+ - Appended to result output when status is `waiting`
293
+ - Printed to stderr in dimmed text
294
+
295
+ Use `--no-keep-alive` for a one-off run even when the specialist is interactive:
296
+
297
+ ```bash
298
+ sp run executor --prompt "Quick check only" --no-keep-alive
299
+ ```
300
+
301
+ Observation loop for keep-alive runs:
302
+
303
+ ```bash
304
+ sp feed <job-id> --follow
305
+ ```
306
+
307
+ ---
308
+
309
+ ## 5) --job concurrency guard
310
+
311
+ When `--job <id>` reuses an existing job's worktree, MEDIUM/HIGH permission specialists are blocked from entering while the target job is still `starting` or `running`. This prevents concurrent file corruption.
312
+
313
+ ### Blocked statuses
314
+
315
+ | Status | Blocked for MEDIUM/HIGH | Allowed for READ_ONLY/LOW |
316
+ |--------|:-----------------------:|:------------------------:|
317
+ | `starting` | ✗ Blocked | ✓ Allowed |
318
+ | `running` | ✗ Blocked | ✓ Allowed |
319
+ | `waiting` | ✓ Allowed | ✓ Allowed |
320
+ | `done` | ✓ Allowed | ✓ Allowed |
321
+ | `error` | ✓ Allowed | ✓ Allowed |
322
+ | `cancelled` | ✓ Allowed | ✓ Allowed |
323
+ | Unknown | ✗ Blocked (conservative) | ✓ Allowed |
324
+
325
+ ### Bypass with --force-job
326
+
327
+ ```bash
328
+ sp run executor --job a1b2c3 --force-job --bead fix-123
329
+ ```
330
+
331
+ Use `--force-job` when:
332
+ - The target job's status is stale/unknown but the worktree is known to be safe
333
+ - Emergency fix entry when the original job is stalled but not terminal
334
+ - Caller explicitly accepts concurrent write risk
335
+
336
+ READ_ONLY and LOW specialists bypass the guard entirely — they cannot corrupt files.
337
+
338
+ ---
339
+
340
+ ## 6) Liveness checks for `sp list --live`
341
+
342
+ The `--live` mode in `sp list` filters out dead jobs by default. A job is **dead** when:
343
+ - Its PID no longer exists (`ps -p <pid>` fails)
344
+ - Its tmux session is gone (`tmux has-session -t <name>` fails or times out)
345
+
346
+ `is_dead` is a **computed field**, never persisted to `status.json`. This avoids stale state where a dead job is marked alive or vice versa.
347
+
348
+ ### `--show-dead` flag
349
+
350
+ ```bash
351
+ sp list --live --show-dead
352
+ ```
353
+
354
+ Shows dead jobs with a `dead` status indicator. Useful for debugging sessions that crashed or were killed externally.
355
+
356
+ ---
357
+
358
+ ## 7) Job status lifecycle
359
+
360
+ Supervisor tracks job status through a state machine:
361
+
362
+ ```
363
+ starting → running → waiting → (resume) → running → ... → done/error/cancelled
364
+ ↘ error
365
+ ```
366
+
367
+ **Terminal statuses**:
368
+ - `done` — job completed normally with `run_complete` event
369
+ - `error` — job failed (exception, timeout, crash)
370
+ - `cancelled` — job stopped intentionally without completion evidence
371
+
372
+ **`cancelled` status**:
373
+
374
+ Introduced to distinguish intentional stops from failures:
375
+ - Set by `sp stop` when job has no `run_complete` event
376
+ - Preserved in SQLite + legacy/operator file mirror `status.json`
377
+ - Rendered in `sp ps` and `sp status` (gray color)
378
+
379
+ ---
380
+
381
+ ## 8) Stuck detection configuration
382
+
383
+ There are two complementary mechanisms.
384
+
385
+ ### A) Session-level stall timeout (`execution.stall_timeout_ms`)
386
+
387
+ Defined in specialist YAML under `execution`.
388
+
389
+ ```yaml
390
+ specialist:
391
+ execution:
392
+ stall_timeout_ms: 120000
393
+ ```
394
+
395
+ - Passed to `PiAgentSession` as `stallTimeoutMs`
396
+ - If no RPC/protocol activity occurs within this window, the session is killed with `StallTimeoutError`
397
+ - Set `0`/unset to disable this watchdog
398
+
399
+ ### B) Supervisor-level stale detection (`stall_detection`)
400
+
401
+ Defined at top-level specialist config:
402
+
403
+ ```yaml
404
+ specialist:
405
+ stall_detection:
406
+ running_silence_warn_ms: 60000
407
+ running_silence_error_ms: 300000
408
+ waiting_stale_ms: 3600000
409
+ waiting_auto_close_ms: 0
410
+ tool_duration_warn_ms: 120000
411
+ ```
412
+
413
+ Defaults (if omitted):
414
+
415
+ - `running_silence_warn_ms`: 60s
416
+ - `running_silence_error_ms`: 300s
417
+ - `waiting_stale_ms`: 1h (3600s) — waiting jobs past this threshold emit `stale_warning` events
418
+ - `waiting_auto_close_ms`: disabled by default (`0` or `null`) — when set to a positive number, stale waiting jobs attempt graceful close first, then forced termination fallback if graceful close times out
419
+ - `tool_duration_warn_ms`: 120s
420
+
421
+ Supervisor outcomes:
422
+
423
+ - Emits `stale_warning` timeline events
424
+ - Can promote long-running silence to `status=error`
425
+ - Dead waiting jobs with no `run_complete` evidence transition to `error` (non-node only)
426
+ - Dead waiting jobs with `run_complete` evidence reconcile to `done`
427
+
428
+ ---
429
+
430
+ ## 9) Test-aware stall detection
431
+
432
+ PiAgentSession extends the stall timeout window when a bash tool command matches a test runner pattern:
433
+
434
+ - `vitest` (including `bun --bun vitest`)
435
+ - `bun test`
436
+ - `npm/pnpm/yarn test`
437
+ - `jest`
438
+ - `pytest`
439
+
440
+ During detected test commands, the effective timeout is `max(base_timeout, test_timeout)` where `test_timeout` defaults to 300s. This prevents the stall watchdog from killing test runners during tinypool worker initialization, which can take longer than the standard 30-120s stall window.
441
+
442
+ ### Extended window lifecycle
443
+
444
+ 1. `tool_execution_start` detected → pattern match on command string
445
+ 2. If test pattern matched → extend stall timeout for this tool call
446
+ 3. `tool_execution_end` → restore base stall timeout
447
+ 4. Stall watchdog still fires for actual hangs — no upper-bound removal
448
+
449
+ ### Known limitations
450
+
451
+ - Pattern-based detection may miss custom test wrappers
452
+ - Process-group isolation not implemented (deeper refactor needed)
453
+
454
+ ---
455
+
456
+ ## 10) Specialist authoring example (executor-style)
457
+
458
+ Example with structured-friendly settings and stall controls (JSON format):
459
+
460
+ ```json
461
+ {
462
+ "specialist": {
463
+ "metadata": {
464
+ "name": "executor",
465
+ "version": "1.0.0",
466
+ "description": "General-purpose execution specialist",
467
+ "category": "codegen"
468
+ },
469
+ "execution": {
470
+ "model": "openai-codex/gpt-5.3-codex",
471
+ "fallback_model": "google-gemini-cli/gemini-3.1-pro-preview",
472
+ "timeout_ms": 0,
473
+ "stall_timeout_ms": 120000,
474
+ "response_format": "text",
475
+ "permission_required": "HIGH",
476
+ "thinking_level": "medium"
477
+ },
478
+ "prompt": {
479
+ "system": "You are a production implementation specialist.",
480
+ "task_template": "$prompt\n\nWorking directory: $cwd"
481
+ },
482
+ "stall_detection": {
483
+ "running_silence_warn_ms": 60000,
484
+ "running_silence_error_ms": 300000,
485
+ "waiting_stale_ms": 3600000,
486
+ "tool_duration_warn_ms": 120000
487
+ }
488
+ }
489
+ }
490
+ ```
491
+
492
+ Authoring notes:
493
+
494
+ - **JSON-first**: Specialist configs use `.specialist.json` format (YAML deprecated but supported)
495
+ - `response_format` controls requested format (`text|json|markdown`) at specialist config level
496
+ - `stall_timeout_ms` handles session protocol silence
497
+ - `stall_detection` handles Supervisor state/timeline warnings and error promotion
498
+ - `permission_required` controls post-job GitNexus reindex (see below)
499
+ - For bead-driven specialists, rely on `$bead_context` / `$bead_id` in templates
500
+ - Bare specialists: see [bare-specialists.md](bare-specialists.md)
501
+ - Additional fields: `author`, `tags`, `created`, `output_type`, `max_retries`, `beads_write_notes`, `communication`
502
+
503
+
504
+ ---
505
+
506
+ ## 11) Configuration presets (`--preset`)
507
+
508
+ Presets provide one-shot configuration profiles for quick adaptation to different task types without editing specialist configs.
509
+
510
+ ### Available presets
511
+
512
+ Presets are defined in `config/presets.json`:
513
+
514
+ | Preset | Model | Thinking | Stall Timeout | Use Case |
515
+ |--------|-------|----------|---------------|----------|
516
+ | `cheap` | see `sp edit --list-presets` | `off` | 60s | Exploration, simple tasks, quick lookups |
517
+ | `medium` | see `sp edit --list-presets` | `low` | 120s | Balanced cost/quality — default for most tasks |
518
+ | `power` | see `sp edit --list-presets` | `high` | 300s | Complex implementation, deep reasoning |
519
+
520
+ Preset model values are operational defaults and may change between releases; inspect the live package with `sp edit --list-presets` or `config/presets.json`.
521
+
522
+ ### Usage
523
+
524
+ Apply a preset to a specialist config:
525
+
526
+ ```bash
527
+ sp edit executor --preset cheap
528
+ sp edit executor --preset medium
529
+ sp edit executor --preset power
530
+ ```
531
+
532
+ This mutates the specialist's JSON config in place, updating:
533
+ - `specialist.execution.model`
534
+ - `specialist.execution.thinking_level`
535
+ - `specialist.execution.stall_timeout_ms`
536
+
537
+ ### When to use
538
+
539
+ - **cheap**: Quick exploration, documentation lookups, simple refactors
540
+ - **medium**: Standard implementation work, bug fixes, feature development
541
+ - **power**: Complex architecture changes, multi-file refactors, difficult debugging
542
+
543
+ ---
544
+
545
+ ## 12) Configuration format: JSON-first with YAML fallback
546
+
547
+ Specialist configurations migrated from YAML to JSON in v2.1.15+.
548
+
549
+ ### File locations
550
+
551
+ Specialist configs and global overrides include:
552
+ - `config/specialists/<name>.specialist.json` (canonical)
553
+ - `.specialists/user/<name>.specialist.json` (repo user override fork, full spec)
554
+ - `~/.config/specialists/user.json` (global user override layer, sparse fields only, machine scope)
555
+
556
+ ### Loading precedence (KAN-90)
557
+
558
+ Override merge is strict 3-layer policy:
559
+
560
+ 1. **Package canonical** specialist from `config/specialists/<name>.specialist.json`
561
+ 2. **Global user** sparse overrides from `~/.config/specialists/user.json`
562
+ 3. **Repo user spec** from `.specialists/user/<name>.specialist.json`
563
+
564
+ Only allowed fields flow through global/repo override layers. Package canonical defines baseline behavior, then machine and repo layers may override safe fields (or append `skills.paths` values).
565
+
566
+ Blocked fields are still guarded:
567
+ - `execution.permission_required`
568
+ - `execution.auto_commit`
569
+ - `prompt.system`
570
+ - `prompt.output_schema`
571
+ - `skills.scripts`
572
+ - `mandatory_rules`
573
+ - `capabilities`
574
+
575
+ Allowed override fields include:
576
+ - `execution.model`, `execution.fallback_model`, `execution.timeout_ms`, `execution.stall_timeout_ms`, `execution.interactive`, `execution.thinking_level`, `execution.max_retries`, `execution.response_format`
577
+ - `execution.extensions.serena`, `execution.extensions.gitnexus`
578
+ - `specialist.stall_detection.waiting_auto_close_ms`
579
+ - `specialist.prompt.system_prompt_mode`
580
+
581
+ Global-layer blocked attempts are stripped at merge time; repo-layer blocked attempts are surfaced in `sp doctor --specialists`.
582
+
583
+ The loader keeps JSON-first with YAML fallback at each leaf source:
584
+
585
+ 1. Look for `<name>.specialist.json` — use if found
586
+ 2. Fall back to `<name>.specialist.yaml` — use if JSON missing (deprecated)
587
+ 3. Emit warning to stderr when YAML is used:
588
+ ```
589
+ [specialists] DEPRECATED: YAML specialist config detected at <path>. Please migrate to .specialist.json
590
+ ```
591
+
592
+ ### Migration from YAML
593
+
594
+ YAML configs remain functional but are deprecated. To migrate:
595
+
596
+ ```bash
597
+ # YAML (deprecated)
598
+ config/specialists/executor.specialist.yaml
599
+
600
+ # JSON (preferred)
601
+ config/specialists/executor.specialist.json
602
+ ```
603
+
604
+ JSON supports all YAML fields plus additional metadata:
605
+ - `author`: Config author
606
+ - `tags`: Array of categorization tags
607
+ - `created`: Creation date
608
+ - `output_type`: Expected output format
609
+ - `max_retries`: Retry count for transient failures
610
+ - `beads_write_notes`: Whether to write bead notes
611
+ - `communication`: Communication preferences
612
+
613
+ ### Schema validation
614
+
615
+ All configs are validated against `src/specialist/schema.ts` at load time. Invalid configs are skipped with an error message.
616
+
617
+ ---
618
+ ## 13) Auto GitNexus reindex after high-permission jobs
619
+
620
+ Supervisor automatically triggers a GitNexus reindex after jobs with elevated file access complete.
621
+ ### Trigger conditions
622
+
623
+ ```json
624
+ {
625
+ "specialist": {
626
+ "execution": {
627
+ "permission_required": "MEDIUM"
628
+ }
629
+ }
630
+ }
631
+ ```
632
+
633
+ When `permission_required` is `MEDIUM` or `HIGH`
634
+
635
+ When `permission_required` is `MEDIUM` or `HIGH`, the supervisor spawns a detached `npx gitnexus analyze` process after job completion.
636
+
637
+ ### Behavior
638
+
639
+ - **Detached execution**: reindex runs in background, does not block job completion
640
+ - **Working directory**: analyze runs in the job's worktree (if applicable) or main checkout
641
+ - **Timeline event**: emits a `meta` event with `model: "gitnexus_analyze_started"` or `model: "gitnexus_analyze_start_failed"`
642
+ - **Failure handling**: if spawn fails, error is logged to timeline but job still completes
643
+
644
+ ### Example timeline events
645
+
646
+ ```json
647
+ {"t": 1743883200000, "type": "meta", "model": "gitnexus_analyze_started", "backend": "supervisor"}
648
+ ```
649
+
650
+ ### Rationale
651
+
652
+ High-permission specialists (`MEDIUM`/`HIGH`) typically modify source code. Auto-reindex ensures the GitNexus knowledge graph stays current without requiring manual intervention or separate CI steps.
653
+
654
+ ### Disabling
655
+
656
+ To disable auto-reindex for a high-permission specialist, set `permission_required` to `LOW` or omit it (defaults to `LOW`).
657
+
658
+ ---
659
+
660
+ ## 14) Debugger v2.0 — Keep-alive iterative debugging
661
+
662
+ The `debugger` specialist was upgraded to v2.0 with enhanced capabilities for iterative debug-fix-verify cycles.
663
+
664
+ ### Configuration
665
+
666
+ ```json
667
+ {
668
+ "specialist": {
669
+ "metadata": {
670
+ "name": "debugger",
671
+ "version": "2.0.0",
672
+ "description": "Autonomous debugger: given any symptom, error, or stack trace, systematically traces call chains with GitNexus, identifies root cause at file:line precision, applies targeted fixes, and verifies the fix works. Keep-alive for iterative debug-fix-verify cycles."
673
+ },
674
+ "execution": {
675
+ "permission_required": "HIGH",
676
+ "interactive": true
677
+ }
678
+ }
679
+ }
680
+ ```
681
+
682
+ ### Key changes in v2.0
683
+
684
+ | Feature | v1.0 | v2.0 |
685
+ |---------|------|------|
686
+ | Permission level | MEDIUM | **HIGH** |
687
+ | Keep-alive | No | **Yes** (`interactive: true`) |
688
+ | Workflow | Single-pass | **Iterative cycles** |
689
+
690
+ ### Iterative workflow
691
+
692
+ 1. **Initial run**: `sp run debugger --bead bd-123`
693
+ - Investigates root cause using GitNexus
694
+ - Applies targeted fix
695
+ - Verifies fix works
696
+ - Enters `waiting` state
697
+
698
+ 2. **Resume if needed**: `sp resume <job-id> "Fix didn't work, error is now..."`
699
+ - Re-diagnoses with new evidence
700
+ - Applies corrected fix
701
+ - Re-verifies
702
+ - Returns to `waiting`
703
+
704
+ 3. **Repeat** until issue is resolved
705
+
706
+ ### When to use
707
+
708
+ - Complex bugs requiring multiple fix attempts
709
+ - Issues where the initial hypothesis may be wrong
710
+ - Debugging sessions that need human verification between attempts
711
+
712
+ ### Observation
713
+
714
+ Use standard observation commands:
715
+
716
+ ```bash
717
+ sp feed <job-id> --follow # Watch investigation progress
718
+ sp status --job <job-id> # Check waiting state
719
+ sp result <job-id> # Read bug report + resume footer
720
+ ```
721
+
722
+ ---
723
+
724
+ ## 15) Worktree isolation (`--worktree`, `--job`)
725
+
726
+ Each edit-permission specialist runs in an isolated git worktree (branch). This prevents concurrent file corruption when multiple executors modify overlapping paths, and produces a clean per-task branch that the orchestrator merges in dependency order.
727
+
728
+ ### CLI flags
729
+
730
+ ```bash
731
+ specialists run <name> [--worktree] [--job <id>]
732
+ ```
733
+
734
+ | Flag | Semantics | Creates worktree? |
735
+ |------|-----------|:-:|
736
+ | `--worktree` | Explicitly provision a new isolated workspace; requires `--bead` | Yes |
737
+ | `--job <id>` | Reuse the workspace of an existing job | No |
738
+
739
+ `--worktree` and `--job` are **mutually exclusive**.
740
+
741
+ ### Worktree guard (MEDIUM/HIGH permission specialists)
742
+
743
+ Specialists with `permission_required = MEDIUM` or `HIGH` and `requires_worktree: true` auto-provision an isolated worktree when `--bead` is provided and `--job` is not used. If no bead is supplied, the command exits with:
744
+
745
+ ```
746
+ Error: specialist '<name>' has permission_required=<MEDIUM|HIGH> and requires worktree isolation.
747
+ Provide --bead <id> for automatic worktree provisioning, or use --job <id> to reuse an existing worktree.
748
+ ```
749
+
750
+ ### `requires_worktree` config flag
751
+
752
+ Specialists can opt out of the worktree guard by setting:
753
+
754
+ ```json
755
+ {
756
+ "specialist": {
757
+ "execution": {
758
+ "requires_worktree": false
759
+ }
760
+ }
761
+ }
762
+ ```
763
+
764
+ When `requires_worktree: false`:
765
+ - Worktree guard is bypassed even for MEDIUM/HIGH permission
766
+ - Specialist can write directly to the main checkout
767
+ - Use for workflow specialists that manage shared state (e.g. memory-processor writes `.xtrm/memory.md`)
768
+
769
+ **Default**: `requires_worktree: true` — all edit-capable specialists are gated.
770
+
771
+ `READ_ONLY` specialists are never gated.
772
+
773
+ ### `--worktree` (new isolated workspace)
774
+
775
+ Requires `--bead <id>` — the bead id drives the deterministic branch name.
776
+
777
+ ```bash
778
+ sp run executor --worktree --bead hgpu.3
779
+ # stderr: [worktree created: /repo/.worktrees/hgpu.3/hgpu.3-executor branch: feature/hgpu.3-executor]
780
+ ```
781
+
782
+ If a worktree for that branch already exists (e.g. from a prior interrupted run) it is reused:
783
+
784
+ ```bash
785
+ # stderr: [worktree reused: /repo/.worktrees/hgpu.3/hgpu.3-executor branch: feature/hgpu.3-executor]
786
+ ```
787
+
788
+ ### `--job <id>` (reuse existing workspace)
789
+
790
+ Reads `worktree_path` from the target job's `status.json` and uses that directory as `cwd`. The **caller's** `--bead` remains authoritative — only the workspace is borrowed.
791
+
792
+ ```bash
793
+ sp run reviewer --job 49adda --bead hgpu.3-review
794
+ # stderr: [workspace reused from job 49adda: /repo/.worktrees/hgpu.3/hgpu.3-executor]
795
+ ```
796
+
797
+ Hard fail conditions:
798
+ - `status.json` missing or unreadable for the given job id
799
+ - `worktree_path` absent — the target job was not started with `--worktree`
800
+
801
+ ### Worktree GC
802
+
803
+ Clean up terminal job worktrees:
804
+
805
+ ```bash
806
+ sp clean # prunes job dirs AND terminal worktrees
807
+ sp clean --dry-run # preview removals without deleting
808
+ ```
809
+
810
+ GC candidates must satisfy all conditions:
811
+ 1. Job status is `done` or `error` (terminal)
812
+ 2. `worktree_path` is recorded in `status.json`
813
+ 3. The directory still exists on disk
814
+ 4. Job status is **not** `starting`, `running`, or `waiting`
815
+
816
+ For full technical details, see [worktrees.md](worktrees.md).
817
+
818
+ ---
819
+ ## 16) Context denormalization in `status.json`
820
+
821
+ Context utilization fields are denormalized directly into `status.json` on every `turn_summary` event, so any consumer reading `status.json` gets the latest context percentage without having to scan `events.jsonl`.
822
+
823
+ ### Fields
824
+
825
+ ```typescript
826
+ interface SupervisorStatus {
827
+ // ... existing fields ...
828
+ context_pct?: number; // context window utilization (0-100)
829
+ context_health?: 'OK' | 'MONITOR' | 'WARN' | 'CRITICAL';
830
+ }
831
+ ```
832
+
833
+ ### Health classification thresholds
834
+
835
+ | Range | Health |
836
+ |-------|--------|
837
+ | < 40% | `OK` |
838
+ | 40–65% | `MONITOR` |
839
+ | 65–80% | `WARN` |
840
+ | > 80% | `CRITICAL` |
841
+
842
+ ### Model context windows
843
+
844
+ | Model pattern | Window |
845
+ |---------------|--------|
846
+ | `gemini-3.1-pro` | 1M tokens |
847
+ | `qwen3.5` / `glm-5` | 128K tokens |
848
+ | `claude` | 200K tokens |
849
+
850
+ ### Where context is surfaced
851
+
852
+ - `sp status` / `sp status --job <id>` — renders `context_pct` and `context_health`
853
+ - `sp ps` — shows `ctx%` column on every job row (from `status.json` directly)
854
+ - `sp feed` — prints WARN/CRITICAL banners when thresholds are crossed
855
+ - `sp ps --json` — includes `context_pct` and `context_health` in `flat[]` array
856
+
857
+ ---
858
+
859
+ ## 17) Job lineage tracking (`reused_from_job_id`, `worktree_owner_job_id`)
860
+
861
+ When `--job <id>` is used, the new job records two lineage fields in its `status.json`. These enable `sp ps` to reconstruct worktree trees reliably without guessing from directory paths.
862
+
863
+ ### Fields
864
+
865
+ ```typescript
866
+ interface SupervisorStatus {
867
+ reused_from_job_id?: string; // the job whose workspace was borrowed via --job
868
+ worktree_owner_job_id?: string; // the root job that owns the worktree
869
+ }
870
+ ```
871
+
872
+ ### Semantics
873
+
874
+ | Field | Set when | Value |
875
+ |-------|----------|-------|
876
+ | `reused_from_job_id` | `--job <id>` is used | The explicit `--job` argument |
877
+ | `worktree_owner_job_id` | `--job <id>` is used | The transitive root owner of the worktree: resolves `worktree_owner_job_id` from the target status, falling back to the target job's `id` |
878
+
879
+ ### Example
880
+
881
+ ```bash
882
+ # Executor provisions the worktree (owner)
883
+ sp run executor --worktree --bead unitAI-55d
884
+ # → job a1b2c3, worktree_owner_job_id=a1b2c3
885
+
886
+ # Reviewer reuses the executor's workspace
887
+ sp run reviewer --job a1b2c3 --bead unitAI-55d-review
888
+ # → new job d4e5f6, reused_from_job_id=a1b2c3, worktree_owner_job_id=a1b2c3
889
+
890
+ # Second reviewer reuses the first reviewer's job (chained reuse)
891
+ sp run validator --job d4e5f6 --bead unitAI-55d-validate
892
+ # → new job g7h8i9, reused_from_job_id=d4e5f6, worktree_owner_job_id=a1b2c3 (resolved transitively)
893
+ ```
894
+
895
+ ### Tree reconstruction in `sp ps`
896
+
897
+ `sp ps` groups all jobs sharing the same `worktree_owner_job_id` into one worktree tree. Jobs are further arranged as a reuse forest: parent → child edges follow `reused_from_job_id` pointers.
898
+
899
+ ---
900
+
901
+ ## 18) `sp merge`: per-chain publication
902
+
903
+ `sp merge` publishes a single chain. The original "refuse if epic unresolved" inverted gate was removed in the chain-lifecycle redesign — per-chain merge is now allowed for any PASS chain regardless of sibling-epic state. Use `sp epic merge` only when batching all epic chains together.
904
+
905
+ ### When `sp merge` accepts a chain
906
+
907
+ - Chain has reviewer PASS verdict in its terminal state.
908
+ - All chain jobs are terminal (executor closed via auto-finalize-on-streaming-PASS or `sp finalize <any-chain-job-id>` cascade).
909
+ - Epic membership is allowed; the chain merges incrementally regardless of sibling state.
910
+ - Epic has not been explicitly `merged` or `abandoned` (those two are the only blocking terminal states).
911
+
912
+ ### Scope
913
+
914
+ **What it does**:
915
+ - Merge a single chain-root branch (one bead → one branch)
916
+ - Run TypeScript gate after merge
917
+ - Optional rebuild (`--rebuild`) after merge
918
+ - Optional PR mode (`--pr`)
919
+
920
+ **What it does NOT include**:
921
+ - Atomic batch publish across multiple chains (use `sp epic merge`)
922
+ - Topological dependency ordering across chains (use `sp epic merge`)
923
+ - Worktree cleanup after merge
924
+ - Conflict auto-resolution
925
+
926
+ ### Vocabulary
927
+
928
+ | Term | Definition |
929
+ |------|------------|
930
+ | **Epic** | Top merge-gated identity with state machine. Use `sp epic merge` for publication. |
931
+ | **Chain** | Worktree lineage (`chain_kind: 'chain'`), seeded by edit-capable specialist. |
932
+ | **Prep** | Standalone job without worktree lineage (`chain_kind: 'prep'`). |
933
+ | **Wave** | Stage/batch label — speech only, no code meaning. |
934
+ | **Job** | Atomic execution unit. Jobs belong to chains or are prep. |
935
+
936
+ ### Command
937
+
938
+ ```bash
939
+ sp merge <chain-root-bead-id> [--rebuild]
940
+ ```
941
+
942
+ - `<chain-root-bead-id>`: A **chain-root bead**. **Must NOT belong to an unresolved epic.**
943
+ - `--rebuild`: run `bun run build` after merge
944
+
945
+ ### Safety
946
+
947
+ - Non-terminal jobs block merge (`starting`, `running` statuses)
948
+ - Epic guard blocks if chain belongs to unresolved epic
949
+ - **Merge-preview worthiness guard** — blocks empty-delta and noise-only-delta branches (see [cli-reference.md#merge-preview-worthiness-guard](cli-reference.md#merge-preview-worthiness-guard))
950
+ - TypeScript gate after merge
951
+ - Uses `--no-ff` to preserve branch history
952
+
953
+ ### File listing
954
+
955
+ Merge output uses `git diff HEAD^1 HEAD` for accurate changed-file reporting (not `git diff-tree`).
956
+
957
+ ### Example
958
+
959
+ ```bash
960
+ # Standalone chain merge (epic guard must pass)
961
+ sp merge unitAI-55d
962
+ # → merges branch feature/unitAI-55d-executor
963
+
964
+ # PR mode
965
+ sp merge unitAI-55d --pr
966
+ # → creates PR instead of direct merge
967
+ ```
968
+
969
+ ### Implementation
970
+
971
+ Source: `src/cli/merge.ts`
972
+
973
+ Key functions:
974
+ - `resolveMergeTargets()` — resolve bead to chain
975
+ - `resolveChainEpicMembership()` — epic guard check
976
+ - `mergeBranch()` — git merge with conflict detection
977
+ - `runTypecheckGate()` — tsc validation
978
+
979
+ ---
980
+
981
+ ## 19) `sp epic merge`: canonical publication for wave-bound chains
982
+
983
+ `sp epic merge` is the canonical publication path for wave-bound chain groups.
984
+
985
+ ### Synopsis
986
+
987
+ ```bash
988
+ sp epic merge <epic-id> [--pr] [--rebuild] [--json]
989
+ ```
990
+
991
+ ### Behavior
992
+
993
+ 1. Reads epic record from observability SQLite (refuses only on `merged` / `abandoned`)
994
+ 2. Computes readiness live from chain state (no operator-driven `resolving → merge_ready` transition needed)
995
+ 3. Verifies all chains are terminal (executor finalized via auto-finalize-on-streaming-PASS or `sp finalize` cascade)
996
+ 4. Verifies latest reviewer verdict is PASS for each chain (matches plain or markdown-bold format)
997
+ 5. Topologically sorts chains by bead dependencies
998
+ 6. For each chain: `git merge <branch> --no-ff --no-edit`
999
+ 7. Runs `bunx tsc --noEmit` after each merge
1000
+ 8. Creates PRs if `--pr` is set
1001
+ 9. Persists `merged` on success; on transient failure (rebase conflict, dirty worktree) writes a soft `failed` marker that the next attempt clears automatically
1002
+
1003
+ ### Epic lifecycle (derived model)
1004
+
1005
+ ```
1006
+ chains in flight ──── derive ──── blocked / failed / merge_ready
1007
+
1008
+ ├── merged (persisted, terminal)
1009
+ └── abandoned (persisted, terminal)
1010
+ ```
1011
+
1012
+ Only `merged` and `abandoned` are persisted as terminal markers. `blocked`, `failed`, and `merge_ready` are recomputed live from chain readiness on every read. A persisted soft `failed` marker (from a transient publish failure) is recoverable — the next `sp epic merge` retries fresh.
1013
+
1014
+ See `docs/cli-reference.md` and `docs/ARCHITECTURE.md` §10 for the full derived-readiness rules.
1015
+
1016
+ ### Examples
1017
+
1018
+ ```bash
1019
+ # Check readiness first
1020
+ sp epic status unitAI-3f7b
1021
+
1022
+ # Publish all chains
1023
+ sp epic merge unitAI-3f7b
1024
+
1025
+ # PR mode
1026
+ sp epic merge unitAI-3f7b --pr
1027
+
1028
+ # Rebuild after merge
1029
+ sp epic merge unitAI-3f7b --rebuild
1030
+ ```
1031
+
1032
+ ---
1033
+
1034
+ ## 20) `sp end`: epic-aware session close
1035
+
1036
+ `sp end` integrates with epic lifecycle for publication.
1037
+
1038
+ ### Synopsis
1039
+
1040
+ ```bash
1041
+ sp end [--bead <id>|--epic <id>] [--pr] [--rebuild]
1042
+ ```
1043
+
1044
+ ### Behavior
1045
+
1046
+ 1. **Epic redirect**: If `--epic <id>` provided, delegates to `sp epic merge <id>`
1047
+ 2. **Epic guard**: If current chain belongs to unresolved epic, auto-redirects to `sp epic merge`
1048
+ 3. **Chain merge**: For standalone chains, publishes the branch
1049
+
1050
+ ### Example
1051
+
1052
+ ```bash
1053
+ # Epic publication
1054
+ sp end --epic unitAI-3f7b --pr
1055
+ # → delegates to: sp epic merge unitAI-3f7b --pr
1056
+
1057
+ # Chain in unresolved epic (auto-detect)
1058
+ sp end
1059
+ # Chain unitAI-impl belongs to unresolved epic unitAI-3f7b (resolving).
1060
+ # Redirecting to: sp epic merge unitAI-3f7b
1061
+ ```
1062
+
1063
+ ---
1064
+
1065
+ ## 21) Chain identity: chain vs prep jobs
1066
+
1067
+ Jobs are classified as `chain` or `prep` based on worktree lineage.
1068
+
1069
+ ### Kinds
1070
+
1071
+ | Kind | Definition | Has worktree? |
1072
+ |------|------------|:-------------:|
1073
+ | `chain` | Worktree lineage seeded by edit-capable specialist | Yes |
1074
+ | `prep` | Standalone job without worktree lineage | No |
1075
+
1076
+ ### Derivation
1077
+
1078
+ ```typescript
1079
+ // Automatic classification from status fields
1080
+ const isChainJob = Boolean(
1081
+ status.worktree_path || status.worktree_owner_job_id || status.chain_id
1082
+ );
1083
+ ```
1084
+
1085
+ ### Fields in status.json
1086
+
1087
+ - `chain_kind` — 'chain' or 'prep'
1088
+ - `chain_id` — unique identifier
1089
+ - `chain_root_job_id` — root worktree owner
1090
+ - `chain_root_bead_id` — seeding bead
1091
+
1092
+ ---
1093
+
1094
+ ## 22) Crash recovery for zombie jobs
1095
+
1096
+ `crashRecovery()` runs at Supervisor startup and reconciles orphaned job states:
1097
+
1098
+ **Dead running/starting jobs**:
1099
+ - Dead PID + non-node → status becomes `error` ("Process crashed or was killed")
1100
+ - Dead PID + node member → status becomes `waiting` ("recovery_pending") — preserved for NodeSupervisor
1101
+
1102
+ **Dead waiting jobs**:
1103
+ - Emits `stale_warning` event if idle past `waiting_stale_ms` threshold
1104
+ - If `waiting_auto_close_ms` is set, stale waiting jobs request graceful close first, then forced termination fallback if close hangs
1105
+ - Default remains recoverable waiting sessions when `waiting_auto_close_ms` is unset/0
1106
+ - Node members preserved for NodeSupervisor recovery
1107
+
1108
+ **`hasRunCompleteEvent()`**:
1109
+
1110
+ Used by `sp stop` to resolve terminal status:
1111
+ ```typescript
1112
+ // SQLite-first, then events.jsonl fallback
1113
+ export function hasRunCompleteEvent(jobId: string): boolean;
1114
+ ```
1115
+
1116
+ ---
1117
+
1118
+ ## 23) Epic chain membership auto-sync
1119
+
1120
+ Supervisor automatically syncs epic chain membership on job completion:
1121
+
1122
+ **Trigger**: Both success (`done`) and error paths
1123
+
1124
+ **Actions**:
1125
+ 1. `upsertEpicChainMembership()` — persist chain→epic linkage
1126
+ 2. `loadEpicReadinessSummary()` — recompute readiness state
1127
+ 3. `syncEpicStateFromReadiness()` — update epic state machine
1128
+
1129
+ This ensures epic readiness is always current without manual sync steps.
1130
+
1131
+ ---
1132
+
1133
+ ## 24) Worktree write-boundary enforcement
1134
+
1135
+ When a specialist runs with `--worktree`, the pi session enforces a **write-boundary** on tool calls. This prevents accidental modifications to files outside the isolated worktree.
1136
+
1137
+ ### Intercepted tools
1138
+
1139
+ | Tool | Intercepted? | Behavior on out-of-bounds absolute path |
1140
+ |------|:-------------:|------------------------------------------|
1141
+ | `edit` | ✓ Yes | Blocked with reason — tool call rejected |
1142
+ | `write` | ✓ Yes | Blocked with reason |
1143
+ | `multiEdit` | ✓ Yes | Blocked with reason |
1144
+ | `notebookEdit` | ✓ Yes | Blocked with reason |
1145
+ | `read` | ✗ No | Allowed (read-only, no corruption risk) |
1146
+ | `bash` | ✗ No | Allowed (command execution, not file write) |
1147
+
1148
+ ### Boundary semantics
1149
+
1150
+ - **Worktree root**: from `SPECIALISTS_WORKTREE_BOUNDARY` env var (set by the runner from `worktree_path` recorded in `status.json`)
1151
+ - **In-bounds path**: any path that resolves to a location under worktree root
1152
+ - **Out-of-bounds path**: any absolute path resolving outside worktree root
1153
+ - **Relative paths**: not intercepted — they resolve against the specialist's cwd, which is the worktree root
1154
+
1155
+ ### Block behavior
1156
+
1157
+ When a write tool is called with an out-of-bounds absolute path:
1158
+ 1. The tool call is **blocked** before reaching the file system.
1159
+ 2. The specialist receives a structured rejection: `{ block: true, reason: "Path '<X>' is outside worktree boundary ('<root>'). Use a relative path or a path within the worktree." }`.
1160
+ 3. No file is created, no tmp-fs redirect, no silent success.
1161
+ 4. The specialist sees the reason and is expected to retry with a worktree-relative path.
1162
+
1163
+ This design prevents:
1164
+ - Specialists accidentally modifying main checkout files
1165
+ - Parallel specialists racing on shared files
1166
+ - Escape via absolute paths (LLMs commonly generate these from context memory)
1167
+
1168
+ ### Why this matters
1169
+
1170
+ Without write-boundary enforcement, specialists in worktrees could:
1171
+ 1. Generate absolute paths from session context (e.g. `/home/user/project/src/file.ts`)
1172
+ 2. Modify files in the main repo, bypassing worktree isolation
1173
+ 3. Create race conditions with other specialists or the operator
1174
+
1175
+ This was observed in production (2026-04-09): sync-docs specialist in worktree `.worktrees/8we6/8we6-sync-docs/` emitted edit calls with absolute paths pointing to main repo. All 6 doc edits landed in main repo instead of the worktree — isolation was completely bypassed.
1176
+
1177
+ ### Implementation
1178
+
1179
+ Enforcement lives in pi session layer (not specialists code):
1180
+ - Commit: `da9ac9e3` (elhl/a2u7 Phase 1)
1181
+ - Applied at tool invocation boundary
1182
+ - Path resolution checks against declared `worktree_path`
1183
+
1184
+ ### Limitations
1185
+
1186
+ - `Bash` commands are not intercepted — a `bash` tool call invoking `cp`, `mv`, or shell redirection can still write outside the worktree.
1187
+ - Relative paths are not checked — they resolve against the specialist's cwd. Escape via `..` traversal is possible if the specialist explicitly does so; in practice the worktree boundary catches the absolute-path failure mode that motivated this enforcement.
1188
+ - Only `path` and `file_path` input fields are inspected; tools with non-standard input keys are not covered.
1189
+
1190
+ ---
1191
+
1192
+ ## 25) Memory injection at specialist spawn
1193
+
1194
+ Runner injects project context at specialist spawn using keyword-filtered memory retrieval from a local SQLite FTS cache. This replaced the previous full `bd prime` dump (~3000 tokens) with targeted retrieval (~600 tokens max).
1195
+
1196
+ ### Injection pipeline
1197
+
1198
+ | # | Source | Tokens | Condition | Purpose |
1199
+ |---|--------|--------|-----------|--------|
1200
+ | 0 | Caveman-micro output directive | ~80 | Always | Terse output style (+26pp accuracy, ~65% token savings) |
1201
+ | 1 | GitNexus workflow mandate | ~200 | `.gitnexus/meta.json` exists | Code intelligence usage rules |
1202
+ | — | `.xtrm/memory.md` | — | Injected by xtrm Pi extension, not runner | Saves ~800 tokens per spawn |
1203
+ | 2 | Static workflow rules | ~60 | Always | `STATIC_WORKFLOW_RULES_BLOCK` from `memory-retrieval.ts` |
1204
+ | 3 | Keyword-filtered memories | ~0-600 | `--bead <id>` provided | FTS query on bead title/description keywords |
1205
+ | 4 | GitNexus pre-query snapshot | ~0-200 | `.gitnexus/` exists + CamelCase tokens in bead title | Caller/callee summaries |
1206
+
1207
+ ### Keyword-filtered memory retrieval
1208
+
1209
+ `src/specialist/memory-retrieval.ts` provides `buildFilteredMemoryInjection()`:
1210
+
1211
+ 1. Extract keywords from bead title + description (max 6, stop-word filtered)
1212
+ 2. Query FTS cache (`specialist_memories_cache` SQLite table) for matching `bd memories`
1213
+ 3. Return top matches within 600-token budget
1214
+
1215
+ Key parameters:
1216
+ - `MAX_KEYWORDS = 6`
1217
+ - `MAX_MEMORIES = 10`
1218
+ - `MAX_MEMORY_TOKENS = 600`
1219
+ - `CACHE_MAX_AGE_MS = 3600000` (1 hour)
1220
+
1221
+ ### FTS cache sync triggers
1222
+
1223
+ | Trigger | Type |
1224
+ |---------|------|
1225
+ | `specialists init` | Full bootstrap sync |
1226
+ | `PostToolUse` hook (`specialists-memory-cache-sync.mjs`) | Incremental after memory mutations |
1227
+ | `sp memory sync [--force]` | Manual CLI sync |
1228
+ | `sp memory refresh` | Invalidate + full rebuild |
1229
+
1230
+ ### Extension opt-out
1231
+
1232
+ Specialists can disable specific npm extensions:
1233
+
1234
+ ```json
1235
+ {
1236
+ "execution": {
1237
+ "extensions": {
1238
+ "serena": false,
1239
+ "gitnexus": false
1240
+ }
1241
+ }
1242
+ }
1243
+ ```
1244
+
1245
+ ### `memory_injection` timeline event
1246
+
1247
+ Every spawn emits a `meta` event with `model: "memory_injection"` recording token accounting:
1248
+
1249
+ ```json
1250
+ {
1251
+ "memory_injection": {
1252
+ "static_tokens": 60,
1253
+ "memory_tokens": 400,
1254
+ "gitnexus_tokens": 150,
1255
+ "total_tokens": 610
1256
+ }
1257
+ }
1258
+ ```
1259
+
1260
+ ### Non-fatal behavior
1261
+
1262
+ All injection sources are non-fatal:
1263
+ - Missing FTS cache → no keyword-filtered memories (static rules still inject)
1264
+ - `.gitnexus/meta.json` missing → no GitNexus mandate or pre-query
1265
+ - GitNexus CLI unavailable → pre-query skipped silently
1266
+
1267
+ ---
1268
+
1269
+ ## 26) Edit gate bead-claim KV pattern
1270
+
1271
+ The edit gate hooks check two KV keys before allowing file edits:
1272
+
1273
+ ### Primary: session-scoped claim
1274
+
1275
+ ```bash
1276
+ bd kv set "claimed:<session-id>" "<bead-id>"
1277
+ ```
1278
+
1279
+ Set by Claude Code hooks when an agent claims a bead. Session-bound, cleared on session end.
1280
+
1281
+ ### Fallback: bead-claim
1282
+
1283
+ ```bash
1284
+ bd kv set "bead-claim:<bead-id>" "active"
1285
+ ```
1286
+
1287
+ Set by Runner **before spawning a specialist** when `--bead <id>` is provided. Enables worktree specialists to edit without requiring a session-scoped claim.
1288
+
1289
+ ### Lifecycle
1290
+
1291
+ ```typescript
1292
+ // Before specialist spawn (run.ts)
1293
+ if (args.beadId && workingDirectory) {
1294
+ execSync(`bd kv set "bead-claim:${args.beadId}" "active"`);
1295
+ }
1296
+
1297
+ // After specialist completes (success or error)
1298
+ if (args.beadId && workingDirectory) {
1299
+ execSync(`bd kv clear "bead-claim:${args.beadId}"`);
1300
+ }
1301
+ ```
1302
+
1303
+ **Why this matters**: Worktree specialists run in subprocesses without session context. The bead-claim pattern provides an edit gate entry that:
1304
+ 1. Is independent of session IDs
1305
+ 2. Is scoped to the specific bead being worked on
1306
+ 3. Is automatically cleaned up when the run completes
1307
+
1308
+ ---
1309
+
1310
+ ## 27) Auto-append bead notes for ALL specialists
1311
+
1312
+ Supervisor now auto-appends full specialist output to the **input bead** on every `run_complete` event. This applies to **all specialists**, not just READ_ONLY.
1313
+
1314
+ ### Behavior
1315
+
1316
+ For specialists with `--bead <id>`:
1317
+ - **First turn**: output appended with `[WAITING]` header if keep-alive and non-terminal
1318
+ - **Subsequent turns**: output appended after each resume turn completes
1319
+ - **Terminal completion**: output appended with `[DONE]` header
1320
+
1321
+ ### Format
1322
+
1323
+ ```markdown
1324
+ ### Specialist Output — executor (job 49adda) [WAITING]
1325
+
1326
+ <full assistant output>
1327
+
1328
+ ---
1329
+ timestamp=2026-04-13T10:30:00Z
1330
+ status=waiting
1331
+ prompt_hash=abc123
1332
+ git_sha=def456
1333
+ elapsed_ms=45678
1334
+ model=gpt-5.3-codex
1335
+ backend=openai-codex
1336
+ ```
1337
+
1338
+ Status labels:
1339
+ - `WAITING — more output may follow` — keep-alive session awaiting resume
1340
+ - `DONE` — terminal completion
1341
+ - `ERROR` — failed completion
1342
+
1343
+ ### Implementation
1344
+
1345
+ Commit: `428cd7f7`
1346
+ - `formatBeadNotes()` — enriched with specialist name, job ID, status label, timestamp
1347
+ - `appendResultToInputBead()` — called on every `run_complete` (not just terminal)
1348
+ - `BeadsClient.updateBeadNotes()` — returns `{ ok, error }` instead of void
1349
+
1350
+ ---
1351
+
1352
+ ## 28) Auto-commit worktree changes (checkpoint policy)
1353
+
1354
+ Specialists with `auto_commit: checkpoint_on_waiting` or `checkpoint_on_terminal` automatically commit substantive worktree changes at designated lifecycle points.
1355
+
1356
+ ### Policy options
1357
+
1358
+ | Policy | Trigger | Use case |
1359
+ |--------|---------|----------|
1360
+ | `never` | Never | Default — no auto-commit |
1361
+ | `checkpoint_on_waiting` | Each keep-alive turn entering `waiting` | Executors, debuggers — preserve partial work before review |
1362
+ | `checkpoint_on_terminal` | Terminal completion (`done`/`error`) | One-shot specialists — commit only at end |
1363
+
1364
+ ### Configuration
1365
+
1366
+ ```json
1367
+ {
1368
+ "specialist": {
1369
+ "execution": {
1370
+ "auto_commit": "checkpoint_on_waiting"
1371
+ }
1372
+ }
1373
+ }
1374
+ ```
1375
+
1376
+ Built-in defaults:
1377
+ - **executor**: `checkpoint_on_waiting`
1378
+ - **debugger**: `checkpoint_on_waiting`
1379
+
1380
+ ### Noise filtering
1381
+
1382
+ Auto-commit ignores paths matching:
1383
+ - `.xtrm/`
1384
+ - `.wolf/`
1385
+ - `.specialists/jobs/`
1386
+ - `.beads/`
1387
+
1388
+ Only **substantive files** (source, config, docs) are committed.
1389
+
1390
+ ### Commit message format
1391
+
1392
+ ```
1393
+ checkpoint(executor): unitAI-55d turn 1
1394
+ ```
1395
+
1396
+ ### Timeline events
1397
+
1398
+ ```json
1399
+ {"type": "auto_commit_success", "commit_sha": "abc123", "committed_files": ["src/cli/run.ts"]}
1400
+ {"type": "auto_commit_skipped", "reason": "no_substantive_changes"}
1401
+ {"type": "auto_commit_failed", "reason": "git commit failed"}
1402
+ ```
1403
+
1404
+ ### Status fields
1405
+
1406
+ ```typescript
1407
+ interface SupervisorStatus {
1408
+ auto_commit_count?: number; // cumulative checkpoints this run
1409
+ last_auto_commit_sha?: string; // SHA of most recent checkpoint
1410
+ last_auto_commit_at_ms?: number; // timestamp of most recent checkpoint
1411
+ }
1412
+ ```
1413
+
1414
+ ### Implementation
1415
+
1416
+ Commit: `11e9b016`
1417
+ - `runAutoCommitCheckpoint()` — substantive file detection, git add + commit, SHA capture
1418
+ - `applyAutoCommitCheckpoint()` — called after `run_complete` on waiting/terminal transitions
1419
+ - Timeline: `auto_commit_success/skipped/failed` events
1420
+ - Schema: `execution.auto_commit` field
1421
+
1422
+ ---
1423
+
1424
+ ## 29) Stale-base guard — rebase at merge + block at dispatch
1425
+
1426
+ Two-layer protection against parallel-chain divergence:
1427
+
1428
+ ### Layer 1: Dispatch-time guard
1429
+
1430
+ When `--worktree` provisions a new worktree, the stale-base guard checks for sibling chains with unmerged substantive commits:
1431
+
1432
+ ```
1433
+ Error: Epic 'unitAI-3f7b' has sibling chains with unmerged changes.
1434
+ - impl-a: 2 substantive commits on 'feature/unitAI-impl-a-executor'
1435
+ - impl-b: 3 substantive commits on 'feature/unitAI-impl-b-executor'
1436
+ Merge sibling chains first via 'sp epic merge unitAI-3f7b', or use --force-stale-base to bypass.
1437
+ ```
1438
+
1439
+ **Bypass**: `--force-stale-base` flag forces provisioning at caller's risk.
1440
+
1441
+ ### Layer 2: Merge-time rebase
1442
+
1443
+ Before merging each chain (via `sp merge` or `sp epic merge`), the branch is rebased onto master inside the worktree:
1444
+
1445
+ ```bash
1446
+ git rebase master # runs in worktree cwd
1447
+ ```
1448
+
1449
+ If rebase fails with conflicts:
1450
+
1451
+ ```
1452
+ Error: Rebase failed for 'feature/unitAI-impl-a-executor' onto 'master'.
1453
+ Conflicting files:
1454
+ - src/cli/run.ts
1455
+ - src/specialist/supervisor.ts
1456
+ Resolve conflicts manually in that worktree, then re-run merge.
1457
+ ```
1458
+
1459
+ Abort is automatic (`git rebase --abort`) — no partial rebase state remains.
1460
+
1461
+ ### Why this matters
1462
+
1463
+ Parallel chains branched from the same base diverge:
1464
+
1465
+ 1. Wave A branches from master at commit X
1466
+ 2. Wave B branches from master at commit X (same base)
1467
+ 3. Wave A merges → master now has Wave A changes
1468
+ 4. Wave B merges → its diff shows **reversions** of Wave A (branched before merge)
1469
+
1470
+ Rebase at merge-time resolves this by incorporating earlier waves' changes before publication.
1471
+
1472
+ ### Implementation
1473
+
1474
+ Commit: `4c3eeb36`
1475
+ - `assertNoStaleBaseSiblings()` — dispatch-time guard in run.ts
1476
+ - `rebaseBranchOntoMaster()` — merge-time rebase in merge.ts
1477
+ - `listEpicChainsWithLatestJob()` — SQLite query for sibling chain state
1478
+ - Schema: `ChainMergeTarget.worktreePath` field
1479
+
1480
+ ---
1481
+
1482
+ ## 30) Manifest-driven tool resolver
1483
+
1484
+ Each specialist's `--tools` argument is computed at session start by `resolvePermissionTools` from a JSON tool catalog plus an optional per-specialist override block. There are no hardcoded tier→tool arrays in source: the catalog is the only source of truth.
1485
+
1486
+ ### Inputs
1487
+
1488
+ 1. The specialist's tier from `execution.permission_required` (`READ_ONLY`/`LOW`/`MEDIUM`/`HIGH`)
1489
+ 2. The catalog index at `.specialists/catalog/index.json` (with `native.json` / `gitnexus.json` / `serena.json` siblings)
1490
+ 3. Live extension health probe of `pi-gitnexus` and `pi-serena-tools` in the global npm modules directory
1491
+ 4. Optional `permissions[<TIER>]` override block on the specialist JSON
1492
+
1493
+ ### Resolution layers (in order)
1494
+
1495
+ | Layer | Effect |
1496
+ |-------|--------|
1497
+ | `catalog` | Tier defaults from each catalog (native + gitnexus + serena) |
1498
+ | `specialist_override` | The specialist's `permissions[<TIER>]` block strips natives via `denied_natives_when_extension` |
1499
+ | `runtime_health` | Tools belonging to unhealthy extensions are dropped; if a hard-deny had stripped natives whose replacement extension is now unhealthy, those natives are restored automatically |
1500
+
1501
+ ### Deny modes
1502
+
1503
+ - `soft` (default): native tool stays in `--tools`; resolver emits a `preference signals` line as a hint
1504
+ - `hard`: native tool is removed when the replacement extension is healthy; restored when it isn't
1505
+
1506
+ ### Override example: explorer
1507
+
1508
+ `config/specialists/explorer.specialist.json` is the only specialist with an override today:
1509
+
1510
+ ```json
1511
+ "permissions": {
1512
+ "READ_ONLY": {
1513
+ "denied_natives_when_extension": ["grep", "find", "ls"],
1514
+ "denied_natives_mode": "hard"
1515
+ }
1516
+ }
1517
+ ```
1518
+
1519
+ Result at runtime when both extensions are healthy: explorer's `--tools` excludes native `grep`/`find`/`ls`, includes `gitnexus_query` + `search_for_pattern` + `find_file` + symbol-graph tools. If `pi-serena-tools` becomes unhealthy mid-run, the natives are restored.
1520
+
1521
+ ### Inspection
1522
+
1523
+ ```bash
1524
+ sp config show <name> --resolved
1525
+ ```
1526
+
1527
+ Prints layer attribution, extension health, denied natives, deny mode, downgrade reasons, and the final `--tools` string. See [manifest.md](manifest.md) for the full reference and [cli-reference.md](cli-reference.md#specialists-config) for the CLI surface.
1528
+
1529
+ ---
1530
+
1531
+ ## Quick reference flows
1532
+
1533
+ ### CLI async observation flow
1534
+
1535
+ ```bash
1536
+ sp run executor --prompt "Task" --json
1537
+ # capture job id from stderr
1538
+ sp feed <job-id> --follow
1539
+ sp result <job-id> --wait --timeout 120
1540
+ ```
1541
+
1542
+ ### Process dashboard flow
1543
+
1544
+ ```bash
1545
+ # Live view of all active jobs
1546
+ sp ps --follow
1547
+
1548
+ # Snapshot with context% and bead titles
1549
+ sp ps
1550
+
1551
+ # Include completed jobs
1552
+ sp ps --all
1553
+
1554
+ # Machine-readable for scripting
1555
+ sp ps --json | jq '.flat[] | select(.status == "waiting")'
1556
+ ```
1557
+
1558
+ ### Worktree isolation flow
1559
+
1560
+ ```bash
1561
+ # 1. Executor provisions worktree, runs implementation
1562
+ sp run executor --worktree --bead hgpu.3
1563
+ # → job id: 49adda
1564
+
1565
+ # 2. Reviewer reuses same workspace (read-only)
1566
+ sp run reviewer --job 49adda --bead hgpu.3-review
1567
+
1568
+ # 3. Clean up terminal worktrees after review complete
1569
+ sp clean --dry-run # preview
1570
+ sp clean # execute
1571
+ ```
1572
+
1573
+ ### MCP single-run flow
1574
+
1575
+ 1. `use_specialist` with `name` + `prompt`/`bead_id`
1576
+ 2. Read final output directly from MCP response
1577
+