@jaggerxtrm/specialists 3.17.0 → 3.18.1

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 (255) hide show
  1. package/README.md +268 -134
  2. package/config/mandatory-rules/executor-delivery.md +4 -0
  3. package/config/mandatory-rules/json-only-final-output.md +13 -0
  4. package/config/mandatory-rules/service-skills-diff-scan-mandatory.md +26 -0
  5. package/config/mandatory-rules/service-skills-gitnexus-triage.md +5 -0
  6. package/config/mandatory-rules/test-runner-execution-scope.md +4 -0
  7. package/config/skills/setup-specialists/SKILL.md +556 -0
  8. package/config/skills/specialists-creator/SKILL.md +132 -4
  9. package/config/skills/specialists-creator/scripts/audit-spec-uniformity.mjs +1 -1
  10. package/config/skills/using-specialists-v3/SKILL.md +80 -20
  11. package/config/specialists/bare.specialist.json +3 -3
  12. package/config/specialists/changelog-drafter.specialist.json +5 -4
  13. package/config/specialists/changelog-keeper.specialist.json +7 -6
  14. package/config/specialists/debugger.specialist.json +2 -2
  15. package/config/specialists/executor.specialist.json +2 -2
  16. package/config/specialists/explorer.specialist.json +4 -4
  17. package/config/specialists/memory-processor.specialist.json +3 -3
  18. package/config/specialists/node-coordinator.specialist.json +3 -3
  19. package/config/specialists/obligations-scanner.specialist.json +67 -17
  20. package/config/specialists/overthinker.specialist.json +3 -3
  21. package/config/specialists/planner.specialist.json +4 -4
  22. package/config/specialists/quant-methodologist.specialist.json +145 -0
  23. package/config/specialists/quant-researcher.specialist.json +144 -0
  24. package/config/specialists/researcher.specialist.json +5 -5
  25. package/config/specialists/reviewer.specialist.json +1 -1
  26. package/config/specialists/seconder.specialist.json +2 -2
  27. package/config/specialists/security-auditor.specialist.json +2 -2
  28. package/config/specialists/service-skills-sync.specialist.json +90 -75
  29. package/config/specialists/specialists-creator.specialist.json +4 -4
  30. package/config/specialists/sync-docs.specialist.json +4 -4
  31. package/config/specialists/test-engineer.specialist.json +3 -3
  32. package/config/specialists/test-runner.specialist.json +7 -7
  33. package/config/specialists/transcriber.specialist.json +3 -3
  34. package/config/specialists/xt-merge.specialist.json +4 -4
  35. package/dist/asset-contract.json +22 -3
  36. package/dist/index.js +28711 -18517
  37. package/dist/lib.js +10020 -6150
  38. package/dist/types/cli/console/components.d.ts +83 -0
  39. package/dist/types/cli/console/components.d.ts.map +1 -0
  40. package/dist/types/cli/console/config-source.d.ts +58 -0
  41. package/dist/types/cli/console/config-source.d.ts.map +1 -0
  42. package/dist/types/cli/console/forensic.d.ts +11 -0
  43. package/dist/types/cli/console/forensic.d.ts.map +1 -0
  44. package/dist/types/cli/console/git.d.ts +28 -0
  45. package/dist/types/cli/console/git.d.ts.map +1 -0
  46. package/dist/types/cli/console/help.d.ts +2 -0
  47. package/dist/types/cli/console/help.d.ts.map +1 -0
  48. package/dist/types/cli/console/log.d.ts +13 -0
  49. package/dist/types/cli/console/log.d.ts.map +1 -0
  50. package/dist/types/cli/console/repo-config.d.ts +26 -0
  51. package/dist/types/cli/console/repo-config.d.ts.map +1 -0
  52. package/dist/types/cli/console/repo-discovery.d.ts +12 -0
  53. package/dist/types/cli/console/repo-discovery.d.ts.map +1 -0
  54. package/dist/types/cli/console/runtime.d.ts +12 -0
  55. package/dist/types/cli/console/runtime.d.ts.map +1 -0
  56. package/dist/types/cli/console/subscribe-prototype.d.ts +18 -0
  57. package/dist/types/cli/console/subscribe-prototype.d.ts.map +1 -0
  58. package/dist/types/cli/console/theme.d.ts +91 -0
  59. package/dist/types/cli/console/theme.d.ts.map +1 -0
  60. package/dist/types/cli/console/types.d.ts +231 -0
  61. package/dist/types/cli/console/types.d.ts.map +1 -0
  62. package/dist/types/cli/console/view-model.d.ts +252 -0
  63. package/dist/types/cli/console/view-model.d.ts.map +1 -0
  64. package/dist/types/cli/console.d.ts +2 -0
  65. package/dist/types/cli/console.d.ts.map +1 -0
  66. package/dist/types/cli/db.d.ts.map +1 -1
  67. package/dist/types/cli/doctor.d.ts.map +1 -1
  68. package/dist/types/cli/edit.d.ts.map +1 -1
  69. package/dist/types/cli/epic.d.ts.map +1 -1
  70. package/dist/types/cli/feed.d.ts.map +1 -1
  71. package/dist/types/cli/forensic.d.ts +2 -0
  72. package/dist/types/cli/forensic.d.ts.map +1 -0
  73. package/dist/types/cli/format-helpers.d.ts +4 -2
  74. package/dist/types/cli/format-helpers.d.ts.map +1 -1
  75. package/dist/types/cli/help.d.ts.map +1 -1
  76. package/dist/types/cli/init.d.ts +10 -0
  77. package/dist/types/cli/init.d.ts.map +1 -1
  78. package/dist/types/cli/list.d.ts.map +1 -1
  79. package/dist/types/cli/log.d.ts.map +1 -1
  80. package/dist/types/cli/merge.d.ts.map +1 -1
  81. package/dist/types/cli/metrics.d.ts +2 -0
  82. package/dist/types/cli/metrics.d.ts.map +1 -0
  83. package/dist/types/cli/ps.d.ts.map +1 -1
  84. package/dist/types/cli/result.d.ts.map +1 -1
  85. package/dist/types/cli/run.d.ts +20 -0
  86. package/dist/types/cli/run.d.ts.map +1 -1
  87. package/dist/types/cli/script.d.ts +3 -0
  88. package/dist/types/cli/script.d.ts.map +1 -1
  89. package/dist/types/cli/serve.d.ts.map +1 -1
  90. package/dist/types/cli/setup.d.ts +19 -1
  91. package/dist/types/cli/setup.d.ts.map +1 -1
  92. package/dist/types/cli/status.d.ts.map +1 -1
  93. package/dist/types/cli/version-check.d.ts +1 -0
  94. package/dist/types/cli/version-check.d.ts.map +1 -1
  95. package/dist/types/index.d.ts +1 -1
  96. package/dist/types/pi/session.d.ts +12 -1
  97. package/dist/types/pi/session.d.ts.map +1 -1
  98. package/dist/types/server.d.ts +15 -0
  99. package/dist/types/server.d.ts.map +1 -1
  100. package/dist/types/specialist/benchmarks.d.ts +37 -0
  101. package/dist/types/specialist/benchmarks.d.ts.map +1 -0
  102. package/dist/types/specialist/chain-identity.d.ts +7 -1
  103. package/dist/types/specialist/chain-identity.d.ts.map +1 -1
  104. package/dist/types/specialist/control.d.ts.map +1 -1
  105. package/dist/types/specialist/dead-job-audit.d.ts +20 -0
  106. package/dist/types/specialist/dead-job-audit.d.ts.map +1 -0
  107. package/dist/types/specialist/forensic-events.d.ts +138 -0
  108. package/dist/types/specialist/forensic-events.d.ts.map +1 -0
  109. package/dist/types/specialist/forensic-renderer.d.ts +34 -0
  110. package/dist/types/specialist/forensic-renderer.d.ts.map +1 -0
  111. package/dist/types/specialist/git-diff-evidence.d.ts +28 -0
  112. package/dist/types/specialist/git-diff-evidence.d.ts.map +1 -0
  113. package/dist/types/specialist/global-config.d.ts +389 -0
  114. package/dist/types/specialist/global-config.d.ts.map +1 -0
  115. package/dist/types/specialist/launch.d.ts +9 -0
  116. package/dist/types/specialist/launch.d.ts.map +1 -1
  117. package/dist/types/specialist/live-aggregates.d.ts +46 -0
  118. package/dist/types/specialist/live-aggregates.d.ts.map +1 -0
  119. package/dist/types/specialist/loader.d.ts +50 -1
  120. package/dist/types/specialist/loader.d.ts.map +1 -1
  121. package/dist/types/specialist/model-chain.d.ts +7 -0
  122. package/dist/types/specialist/model-chain.d.ts.map +1 -0
  123. package/dist/types/specialist/model-probes.d.ts +28 -0
  124. package/dist/types/specialist/model-probes.d.ts.map +1 -0
  125. package/dist/types/specialist/node-contract.d.ts +18 -18
  126. package/dist/types/specialist/node-supervisor.d.ts.map +1 -1
  127. package/dist/types/specialist/observability-db.d.ts +1 -1
  128. package/dist/types/specialist/observability-db.d.ts.map +1 -1
  129. package/dist/types/specialist/observability-sqlite.d.ts +101 -0
  130. package/dist/types/specialist/observability-sqlite.d.ts.map +1 -1
  131. package/dist/types/specialist/pr-drift-refresh.d.ts +17 -0
  132. package/dist/types/specialist/pr-drift-refresh.d.ts.map +1 -0
  133. package/dist/types/specialist/preset-resolver.d.ts +56 -0
  134. package/dist/types/specialist/preset-resolver.d.ts.map +1 -0
  135. package/dist/types/specialist/prometheus-projection.d.ts +25 -0
  136. package/dist/types/specialist/prometheus-projection.d.ts.map +1 -0
  137. package/dist/types/specialist/runner.d.ts +29 -1
  138. package/dist/types/specialist/runner.d.ts.map +1 -1
  139. package/dist/types/specialist/schema.d.ts +163 -54
  140. package/dist/types/specialist/schema.d.ts.map +1 -1
  141. package/dist/types/specialist/script-runner.d.ts +5 -1
  142. package/dist/types/specialist/script-runner.d.ts.map +1 -1
  143. package/dist/types/specialist/snapshot-diff.d.ts +8 -0
  144. package/dist/types/specialist/snapshot-diff.d.ts.map +1 -0
  145. package/dist/types/specialist/source-queue.d.ts +13 -0
  146. package/dist/types/specialist/source-queue.d.ts.map +1 -0
  147. package/dist/types/specialist/status-load.d.ts.map +1 -1
  148. package/dist/types/specialist/supervisor.d.ts +25 -1
  149. package/dist/types/specialist/supervisor.d.ts.map +1 -1
  150. package/dist/types/specialist/timeline-events.d.ts +70 -1
  151. package/dist/types/specialist/timeline-events.d.ts.map +1 -1
  152. package/dist/types/tools/specialist/resume_specialist.tool.d.ts +4 -4
  153. package/dist/types/tools/specialist/specialist_status.tool.d.ts +1 -1
  154. package/dist/types/tools/specialist/steer_specialist.tool.d.ts +4 -4
  155. package/dist/types/tools/specialist/use_specialist.tool.d.ts +16 -16
  156. package/docs/ARCHITECTURE.md +1176 -0
  157. package/docs/TODO.md +9 -0
  158. package/docs/architecture.md +11 -0
  159. package/docs/archive/2026-03-13-bd-decision-context-template-plan.md +96 -0
  160. package/docs/archive/AGENT-HANDOFF.md +351 -0
  161. package/docs/archive/PARITY-ANALYSIS.md +296 -0
  162. package/docs/archive/SPECIALISTS_REFACTOR.md.md +30 -0
  163. package/docs/archive/cc-programmatic.md +216 -0
  164. package/docs/archive/claude-agent-sdk.md +594 -0
  165. package/docs/archive/decision-specialist-directory.md +41 -0
  166. package/docs/archive/discoveries.md +148 -0
  167. package/docs/archive/executor-benchmark-protocol.md +198 -0
  168. package/docs/archive/future-features.md +66 -0
  169. package/docs/archive/gzrx-completion-critique.md +183 -0
  170. package/docs/archive/gzrx-research-notes.md +401 -0
  171. package/docs/archive/gzrx-tool-catalog.md +760 -0
  172. package/docs/archive/iron-review-hardening-qa-chain-substrate.md +322 -0
  173. package/docs/archive/iron-review-hardening.html +1004 -0
  174. package/docs/archive/issuetracking.md +312 -0
  175. package/docs/archive/qa-v3.0.2.md +220 -0
  176. package/docs/archive/restructure.md +231 -0
  177. package/docs/archive/script-specialists.md +1254 -0
  178. package/docs/archive/spec-v3.md +792 -0
  179. package/docs/archive/specialist-stats.md +127 -0
  180. package/docs/archive/specialists-friction-audit.md +1347 -0
  181. package/docs/archive/specialists-runtime-critique.md +170 -0
  182. package/docs/archive/specialists-service-evaluation.md +713 -0
  183. package/docs/archive/specialists-substrate-alignment.md +255 -0
  184. package/docs/archive/substrate-review.md +1288 -0
  185. package/docs/archive/test-writer-specialist.md +254 -0
  186. package/docs/archive/using-specialists-v3-improvements-2026-05-09.md +600 -0
  187. package/docs/archive/xtrm-specialists-analysis.md +314 -0
  188. package/docs/authoring.md +701 -0
  189. package/docs/background-jobs.md +203 -0
  190. package/docs/bare-specialists.md +83 -0
  191. package/docs/benchmarks/executor-benchmark-runner.md +66 -0
  192. package/docs/bootstrap.md +161 -0
  193. package/docs/cli-reference.md +1645 -0
  194. package/docs/deploying-alongside.md +155 -0
  195. package/docs/design/README.md +36 -0
  196. package/docs/design/darth-feedor-migration.md +290 -0
  197. package/docs/design/roadmap/README.md +32 -0
  198. package/docs/design/roadmap/chain-templates/README.md +146 -0
  199. package/docs/design/roadmap/chain-templates/code-quick.formula.json +27 -0
  200. package/docs/design/roadmap/chain-templates/code-standard.formula.json +126 -0
  201. package/docs/design/roadmap/chain-templates/code-with-advisors.formula.json +128 -0
  202. package/docs/design/roadmap/chain-templates/code-with-tests.formula.json +76 -0
  203. package/docs/design/roadmap/chain-templates/debug.formula.json +128 -0
  204. package/docs/design/roadmap/chain-templates/doc-sync.formula.json +28 -0
  205. package/docs/design/roadmap/chain-templates/memory-hygiene.formula.json +27 -0
  206. package/docs/design/roadmap/chain-templates/planning.formula.json +27 -0
  207. package/docs/design/roadmap/chain-templates/premortem.formula.json +26 -0
  208. package/docs/design/roadmap/chain-templates/release-prep.formula.json +36 -0
  209. package/docs/design/roadmap/chain-templates/research-only.formula.json +28 -0
  210. package/docs/design/roadmap/chain-templates/restitch.formula.json +125 -0
  211. package/docs/design/roadmap/chain-templates/security-deep.formula.json +161 -0
  212. package/docs/design/roadmap/chain-templates/test-only.formula.json +52 -0
  213. package/docs/design/roadmap/chain-templates/triage.formula.json +35 -0
  214. package/docs/design/roadmap/history/handoff-from-substrate-design.md +87 -0
  215. package/docs/design/roadmap/history/substrate-reconciliation.md +105 -0
  216. package/docs/design/roadmap/specialists-roadmap.md +1261 -0
  217. package/docs/design/sp-console-subscribe-via-materializer.md +231 -0
  218. package/docs/design/sp-console-tui-mock-v2.html +293 -0
  219. package/docs/design/sp-console-tui-mock.html +120 -0
  220. package/docs/design/sp-console-tui.md +340 -0
  221. package/docs/design/specialist-agentops-suite.md +323 -0
  222. package/docs/design/substrate/channels.md +14 -0
  223. package/docs/design/substrate/devops-platform-engineering-prd.md +446 -0
  224. package/docs/design/substrate/html-design-example.md +339 -0
  225. package/docs/design/xtrm-tiers-architecture.svg +132 -0
  226. package/docs/devops/dependency-verdict-materialization.md +46 -0
  227. package/docs/epic-readiness.md +75 -0
  228. package/docs/examples/mercury-atomic-summarizer.specialist.json +26 -0
  229. package/docs/examples/smoke-echo-text-expected-keys.specialist.json +25 -0
  230. package/docs/examples/smoke-echo.specialist.json +25 -0
  231. package/docs/features.md +1577 -0
  232. package/docs/hooks.md +81 -0
  233. package/docs/installation.md +142 -0
  234. package/docs/manifest.md +184 -0
  235. package/docs/mcp-servers.md +73 -0
  236. package/docs/mcp-tools.md +71 -0
  237. package/docs/nodes.md +231 -0
  238. package/docs/observability-metrics.md +152 -0
  239. package/docs/operator/sp-console-v2-walkthrough.md +410 -0
  240. package/docs/overrides-guide.md +306 -0
  241. package/docs/pi-rpc-boundary.md +118 -0
  242. package/docs/pi-session.md +195 -0
  243. package/docs/release.md +22 -0
  244. package/docs/skills.md +132 -0
  245. package/docs/specialists/handoff-schema.md +181 -0
  246. package/docs/specialists-catalog.md +99 -0
  247. package/docs/specialists-service-install.md +226 -0
  248. package/docs/specialists-service.md +363 -0
  249. package/docs/surface-ownership.md +138 -0
  250. package/docs/upgrade-notes/kan-90-global-user-config.md +114 -0
  251. package/docs/upgrade-notes/kan-91-expanded-overrides.md +261 -0
  252. package/docs/workflow.md +114 -0
  253. package/docs/worktree.md +71 -0
  254. package/docs/worktrees.md +309 -0
  255. package/package.json +7 -4
@@ -0,0 +1,170 @@
1
+ > **ARCHIVED 2026-05-27** — content superseded by:
2
+ > - `docs/design/substrate/specialists-roadmap-revised.md` (canonical specialists roadmap; absorbed this file in §0/§3.2/§12/§13)
3
+ > - `docs/design/substrate/substrate.md` rev10 (canonical substrate design)
4
+ > - `docs/design/chain-templates/` (13 evidence-backed bd formulas)
5
+ >
6
+ > Preserved for historical context. Do not edit. Do not cite as authoritative.
7
+
8
+ ---
9
+
10
+ # Specialists Runtime — Architectural Critique
11
+
12
+ > **⚠️ STATUS: SUPERSEDED — consolidated into `specialists-friction-audit.md` §1 (Architectural framing).**
13
+ >
14
+ > The content of this doc has been folded — distilled and integrated — into the canonical consolidated friction-audit. New work should reference the consolidated audit, not this file. This file is preserved for git-history continuity (it shows the reasoning step that produced the critique) but is no longer source-of-truth.
15
+ >
16
+ > **Canonical replacement:** `docs/design/specialists-friction-audit.md` §1.
17
+ >
18
+ > ---
19
+ >
20
+ > *Original purpose (historical):* Identify the architectural shape errors in the current `sp` runtime, distinct from the symptom-level catalog in `specialists-friction-audit.md`. The audit asks "what hurts and what bridge fixes it"; this doc asks "what is the runtime *shape* getting wrong, and why does the container model in substrate fix it by inversion." Prepared as context for the substrate revision 9 review so the specialists-side cleanup is grounded.
21
+ >
22
+ > **Method.** Code reading of `src/specialist/{chain-identity, supervisor, runner, control, worktree}.ts` + `src/cli/run.ts` cross-referenced against observed friction in `.xtrm/reports/` and against the substrate-review document.
23
+ >
24
+ > **Scope.** Six asymmetries. For each: what the code does today, why it hurts, how the container model inverts it. The fix is structural — bridges that preserve the asymmetry are wasted effort.
25
+
26
+ ---
27
+
28
+ ## The shape problem in one sentence
29
+
30
+ The current runtime treats *jobs* as first-class entities and *chains* as a derived projection over the job graph. Substrate's container model inverts this: containers are first-class, jobs (participants) are tenants of containers. Six concrete asymmetries fall out of the inversion.
31
+
32
+ ---
33
+
34
+ ## Asymmetry 1 — Executor is the privileged chain bootstrapper
35
+
36
+ **What the code does.** `chain-identity.ts:38-39`:
37
+
38
+ ```ts
39
+ const chainRootJobId = status.chain_root_job_id
40
+ ?? status.worktree_owner_job_id
41
+ ?? status.id;
42
+ const chainId = status.chain_id ?? chainRootJobId;
43
+ ```
44
+
45
+ The chain id defaults to the worktree-owner job id, which defaults to the job's own id. There is no `chain` row; the chain is computed by walking back to the worktree-owning job, which in practice is the first specialist dispatched with `--worktree`. By convention that is the executor.
46
+
47
+ The CLAUDE.md gotcha **"--worktree and --job are mutually exclusive"** is the operator-facing surface of this asymmetry: only the first dispatch may carry `--worktree`; everyone after must use `--job <first-job>` to enter the workspace.
48
+
49
+ **Why it hurts.**
50
+
51
+ - Executor is structurally the chain owner even when the chain is *conceptually* something else (a debug investigation, a planning seed, a documentation sweep). The role gets uniform privilege regardless of fit.
52
+ - Killing the executor's job (`sp stop`) implicitly destroys the chain — every other specialist that referenced `--job <exec>` loses its anchor.
53
+ - A debugger that wants to *open* a fresh investigation worktree must also use `--worktree`, which means debugger becomes "the new executor" for chain-identity purposes. The role names become misleading.
54
+ - The first-dispatched role's identity is permanent (the job id never changes), so a chain originated by a *temporary* role (e.g., a probe-explorer that you wanted to throw away) cannot be cleanly demoted to a member.
55
+
56
+ **How containers invert.** The container is opened *before* any participant is dispatched (`sb container open --workflow X --issue Y`). Container has its own id (`chain:7f3a`), independent of any participant. Participants are spawned *into* the container; none of them is privileged. Executor becomes a role with no special powers — it can be dispatched first or after other roles (e.g., explorer-first, then executor) without changing the chain identity. The "first-job creates chain" coupling is removed.
57
+
58
+ ---
59
+
60
+ ## Asymmetry 2 — Worktree is owned by a job, not by the chain
61
+
62
+ **What the code does.** The worktree is created during the first `sp run --worktree` dispatch. The owning job id is stamped on the worktree via `worktree_owner_job_id`. When the job ends, the worktree is *not* automatically destroyed — but it is no longer owned by any live entity. Future specialists join via `--job <owner>`, even after the owner's pi session has gone to `waiting` (keep-alive) — that's why keep-alive must hold the owner alive.
63
+
64
+ **Why it hurts.** Observed in `.xtrm/reports/`:
65
+
66
+ - **Orphan worktrees from prior sessions** (mercury 2026-05-25 §"6 pre-existing orphan worktrees"): worktrees survive their owning jobs' termination; nobody cleans them up because they're no longer attached to anything actionable.
67
+ - **Stale-base guard false-positives** (audit §B5, §8.2): the orphan worktrees' branches still exist; the guard sees them as "unmerged sibling chains" and refuses dispatches — operator normalizes to `--force-stale-base`, the guard loses signal.
68
+ - **Keep-alive must hold the executor's pi session** (audit §8.1): not because the LLM needs to stay loaded, but because the *workspace handle* (the `--job` target) is bound to a job. Lose the job, lose the handle.
69
+
70
+ **How containers invert.** The container owns the worktree for its whole lifetime. When the container moves to a terminal state (`closed:merged`, `closed:abandoned`, `closed:failed`), the worktree is reaped per the container-teardown handler (substrate.md §5.10 already specifies this). Jobs come and go; the worktree persists across them. Keep-alive holds *pi sessions* alive for resume convenience but is no longer load-bearing for workspace identity — that lives in the container.
71
+
72
+ ---
73
+
74
+ ## Asymmetry 3 — Chain has no first-class entity row
75
+
76
+ **What the code does.** No `chains` table. `chain_id` is a column on jobs (`chain_id`, `chain_root_job_id`, `chain_root_bead_id` per chain-identity.ts:9-11). The chain is reconstructed by aggregating jobs that share a `chain_id`. Queries like `listEpicChainsWithLatestJob` walk the job table and project chain views.
77
+
78
+ **Why it hurts.**
79
+
80
+ - No place to attach chain-level state: resolved workflow, chosen scrutiny, collision matrix, accumulated evidence index, budget consumed. Substrate-review §25 (workflow definition) needs `resolved_workflow_json` on the container — there is no analog in current runtime.
81
+ - Chain advancement is *implicit*. The "what step is next" decision has no row to consult — it lives in operator's head or in the SKILL.md prose. This is the orchestrator-laziness root cause (audit §B): the runtime has no model of "where is this chain in its workflow," so the operator has to carry it.
82
+ - Reporting and dashboards (substrate.md §12) need a chain-level row to render against. The current job-graph projection is OK for `sp ps` (time-ordered list) but cannot answer "what's the state of chain X end-to-end" without expensive walks. Audit §3.4 (`sp chain <bead>`) is exactly this gap.
83
+ - Re-running a chain (re-dispatch after a failure that abandoned the workspace) creates a *new* chain id because the worktree creator changes. The chain has no continuity of identity across reattempts.
84
+
85
+ **How containers invert.** Container is a row in `containers` with stable id. All chain-level state (workflow, scrutiny, collision strategy, budget, evidence index) attaches to it. Jobs reference `container_id` instead of synthesizing chain identity. `sb container ps --tree` is a primary-key lookup, not a graph walk.
86
+
87
+ ---
88
+
89
+ ## Asymmetry 4 — Keep-alive paradox: pi session held alive because workspace has no other persistence handle
90
+
91
+ **What the code does.** `--keep-alive` makes the first specialist's pi session stay in `waiting` after `agent_end` (supervisor.ts:1658, 1974). This is what lets later specialists `--job <owner>` into the same workspace.
92
+
93
+ **Why it hurts.**
94
+
95
+ - The pi session holds context, memory, tool state — all expensive — *only because the workspace identity is bound to its job id*. The keep-alive is paying for workspace handle, not for LLM-state reuse.
96
+ - A simple "review this diff" chain that doesn't need executor resumability still holds executor's pi session in memory until `sp finalize` releases it. Operator-forgets-finalize = resource leak (audit §8.1).
97
+ - Re-spawning the executor after a crash means re-creating the chain identity (Asymmetry 1) — so transient crashes destroy chains. No graceful "the executor died, here's a fresh one for the same chain."
98
+ - Pi has its own keep-alive semantics around `agent_end` (per `pi-rpc.md` and `--keep-alive`); substrate-review §19 maps this 1:1. But conflating *pi session keep-alive* with *chain workspace persistence* forces the two lifetimes to be the same, when they are conceptually independent.
99
+
100
+ **How containers invert.** Workspace persistence is a *container* property. Pi keep-alive is a *participant* property (useful when the operator wants to resume that specific LLM session). The two are decoupled. A reviewer chain can open a container with no pi session kept alive — the workspace is held by the container regardless. Substrate-review §19 already establishes that substrate aligns to pi turns; this asymmetry is the missing piece — the workspace handle moves out of the pi-session lifetime.
101
+
102
+ ---
103
+
104
+ ## Asymmetry 5 — `--bead` conflates work contract with chain key
105
+
106
+ **What the code does.** `sp run <role> --bead <id>` passes the bead in two roles simultaneously:
107
+ 1. **Contract**: what to do, success criteria, scope, validation — the prompt input.
108
+ 2. **Identity key**: `chain_root_bead_id` is set from this bead, and all subsequent jobs in the chain inherit it (or override via `--bead` to a different bead, e.g., reviewer's own tracking bead).
109
+
110
+ The reviewer/code-sanity discipline (SKILL Rule 7) is: reviewer uses its *own* tracking bead via `--bead`, but enters executor's workspace via `--job`. So we end up with two beads in play: the *target* bead (executor's bead, which is the chain root) and the *tracking* bead (reviewer's bead, which is purely for audit).
111
+
112
+ **Why it hurts.**
113
+
114
+ - Audit §R4: operator confuses tracking-bead with target — passes `--bead <reviewer-tracking-bead>` instead of `--bead <target>`. The conflation makes this a natural error.
115
+ - The "chain root bead" is determined by whichever bead the first specialist received. If the first dispatch happens to be a probe-explorer for a different bead than the eventual target, the chain inherits the probe's bead as root — confusing later attribution.
116
+ - Followup beads (`discovered_from`) cannot cleanly join a running chain: there's no "the chain is doing work *for* bead X" abstraction; you'd have to dispatch a new specialist with `--bead Y` and somehow link it, but the chain's `chain_root_bead_id` is already fixed.
117
+ - Workflow defaults derive from the bead (its `type` resolves to a workflow per substrate-review §25), but the chain-level "this is the resolved workflow" has no place to live (Asymmetry 3).
118
+
119
+ **How containers invert.** Container has its own id and explicitly references its target issue(s) via the issue-membership edges (substrate §6.7). The container is not "named after" any one issue — it's named after itself. The reviewer's tracking bead and the executor's target bead are both *issues that are members of the container*, with explicit roles (`role: validates`, `role: implements`). No conflation possible because the chain key is not a bead at all.
120
+
121
+ ---
122
+
123
+ ## Asymmetry 6 — Reviewer-as-parasite: cannot exist without executor
124
+
125
+ **What the code does.** Reviewer must be dispatched with `--job <exec-job>` to enter the executor's workspace. Without it, reviewer runs in a clean checkout and reviews against the contract only, with no diff visible (audit §R1). The runtime structurally encodes "reviewer is a follower of executor."
126
+
127
+ **Why it hurts.**
128
+
129
+ - A reviewer cannot review *anything but executor output*. Cannot review a manually-applied patch, a PR from outside the sp flow, a debugger's diff, a cherry-pick attempt. The role is locked to one input shape.
130
+ - The Iron-style pipeline (substrate-review §25, "code-standard" workflow) wants `executor → code-sanity → security-auditor → obligations-scanner → reviewer`. Code-sanity is supposed to gate before reviewer. But code-sanity also uses `--job <exec-job>` — it shares the executor-parasite shape. None of the gate specialists can exist as first-class workspace inhabitants.
131
+ - A "fresh review of pre-existing code" use case (`sb container open --workflow security-audit-only --no-executor`) has no place in the current model. Reviewer cannot bootstrap a container.
132
+
133
+ **How containers invert.** Any participant kind can be the first or only participant of a container. A `security-audit-only` container has a reviewer (or security-auditor) as its sole participant, working on a worktree the container created from a specified base. No executor required. This is the *unbound participant* concept of substrate-review §15 generalized — participants don't have implicit ordering hierarchy.
134
+
135
+ ---
136
+
137
+ ## What collapses cleanly under containers
138
+
139
+ Each asymmetry above maps to a substrate primitive that already removes it:
140
+
141
+ | Asymmetry | Removed by |
142
+ |---|---|
143
+ | 1 — Executor as chain bootstrapper | Container open is a substrate-level action (§4 container kinds); specialists are spawned into existing containers (§7.1 spawn-into-container) |
144
+ | 2 — Worktree owned by job | Worktree owned by container; reaped on container terminal state (§5.10 teardown) |
145
+ | 3 — Chain has no entity row | `containers` table is canonical (§13.3) with `resolved_workflow_json`, `collision_strategy_json`, evidence index |
146
+ | 4 — Keep-alive paradox | Container workspace lifetime independent of any pi session; pi keep-alive becomes purely about LLM-state convenience (§19) |
147
+ | 5 — `--bead` conflation | Container has its own id; issues are members via edges (§6.7); reviewer-tracking-bead and target-bead are both members with explicit roles |
148
+ | 6 — Reviewer-as-parasite | Any participant kind opens any container; no implicit ordering (review §15 unbound participants) |
149
+
150
+ ---
151
+
152
+ ## What this means for the rev-9 review
153
+
154
+ When substrate revision 9 arrives, the specialists-runtime refactor that comes with it should:
155
+
156
+ 1. **Stop adding bridges to the current asymmetries.** Each of the friction-audit §3/§7 patches (`sp chain`, post-dispatch hint, etc.) is fine *as long as* it does not entrench the executor-as-chain-root model. The proposed `sp chain <bead>` is at risk — it implicitly assumes one bead per chain, which is Asymmetry 5. Better surface eventually: `sb container ps <container-id>`.
157
+ 2. **Plan an order of operations.** Container model can't land all at once. Suggested staging (parallel to substrate.md §15 Sequencing):
158
+ - Stage A: introduce `containers` row (Asymmetry 3 fix) as additive — jobs still have `chain_id`, but it also points to a real container.
159
+ - Stage B: move worktree ownership from job → container (Asymmetry 2 + 4). Keep-alive becomes optional.
160
+ - Stage C: open containers explicitly before dispatch (Asymmetry 1 + 6). `sp run` becomes "spawn participant in container <id>" with `--container` flag.
161
+ - Stage D: issue membership edges replace `chain_root_bead_id` (Asymmetry 5). Existing `--bead` flag becomes a shortcut for "open container from this bead's contract."
162
+ 3. **Stop teaching the SKILL the workarounds.** Once Stage A lands, drop the "`--worktree` and `--job` are mutually exclusive" gotcha from CLAUDE.md — the workaround disappears with the asymmetry. Same for the keep-alive-must-be-on-first rule.
163
+ 4. **The friction audit's Layer 3a (Claude Code hook on `bd create`) is unaffected.** It operates one layer above runtime — it suggests chain shape from bead content, no matter how the runtime executes it. Land it independently.
164
+ 5. **The friction audit's Layer 3b (sp-runtime hints) needs re-targeting.** `sp run` post-dispatch hint currently says "next: code-sanity --job <this-job>." After Stage C it should say "next: code-sanity --container <id>" — the hint generator needs to know which world it's in. Plan for the migration in the hint template, not as an afterthought.
165
+
166
+ ---
167
+
168
+ ## Open question for the rev-9 author
169
+
170
+ The current runtime conflates *workspace identity* and *job identity* in subtle ways throughout (chain-identity.ts, branch naming `feature/<bead>-<role>`, the `--job` flag semantics). The rev-9 substrate design should make explicit: **is workspace identity exposed in the runtime API**, or is it strictly internal to substrate? If the former, the SDK gets a `workspace_id` first-class concept; if the latter, all operations are container-scoped and workspace is private. Either is defensible; the design should pick one and commit, because the half-and-half state (which is where we are now with `--job` as workspace handle) is what produced the six asymmetries above.