@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,363 @@
1
+ ---
2
+ title: Specialists Service
3
+ scope: specialists-service
4
+ category: architecture
5
+ version: 3.1.2
6
+ updated: 2026-06-24
7
+ synced_at: bf6baf7a
8
+ description: Human SSOT for sp serve, sp script, script-class authoring, trust/readiness/hot-reload, and image release.
9
+ source_of_truth_for:
10
+ - src/cli/script.ts
11
+ - src/cli/serve.ts
12
+ - src/specialist/script-runner.ts
13
+ - Dockerfile
14
+ - .github/workflows/pi-compat.yml
15
+ domain:
16
+ - specialists
17
+ - service
18
+ - release
19
+ ---
20
+
21
+ <!-- INDEX: auto-generated by validate_doc.py — do not edit manually -->
22
+ | Section | Summary |
23
+ |---|---|
24
+ | [Shape](#shape) | - `sp serve` = HTTP sidecar for script-class specialists |
25
+ | [HTTP contract](#http-contract) | `POST /v1/generate` |
26
+ | [`sp serve`](#sp-serve) | Defaults: |
27
+ | [`sp script`](#sp-script) | One-shot CLI on same runtime path as `sp serve` |
28
+ | [Script-class authoring](#script-class-authoring) | Script-class specialists are JSON specialists with one-shot runtime constraints |
29
+ | [Observability](#observability) | Every call writes one row to ` |
30
+ | [Deployment](#deployment) | Sidecar-per-consumer |
31
+ | [Image release runbook](#image-release-runbook) | Current state: |
32
+ | [Merged legacy content](#merged-legacy-content) | - old architecture intent absorbed here as transport/runtime split |
33
+ | [Dropped on purpose](#dropped-on-purpose) | - Python/qwen architecture |
34
+ | [Operator summary](#operator-summary) | If you need one page for current service behavior, use this doc |
35
+ <!-- END INDEX -->
36
+
37
+ # Specialists Service
38
+
39
+ Single SSOT for `sp serve` and `sp script`. This doc covers service contract, script-class specialist authoring, trust and readiness gates, hot reload, and image release flow.
40
+
41
+ ## Shape
42
+
43
+ - `sp serve` = HTTP sidecar for script-class specialists.
44
+ - `sp script` = one-shot CLI for same runtime path.
45
+ - Both reuse `script-runner.ts` and `SpecialistLoader`.
46
+ - Both write observability rows into project `.specialists/db/observability.db` unless trace disabled.
47
+ - Both reject interactive / worktree / keep-alive / orchestration use cases. Use `sp run` for those.
48
+
49
+ ## HTTP contract
50
+
51
+ ### Endpoint
52
+
53
+ `POST /v1/generate`
54
+
55
+ ### Request
56
+
57
+ ```json
58
+ {
59
+ "specialist": "kebab-case-name",
60
+ "variables": {"key": "value"},
61
+ "template": "task_template",
62
+ "template_field": "task_template",
63
+ "model_override": "anthropic/...",
64
+ "timeout_ms": 60000,
65
+ "trace": true
66
+ }
67
+ ```
68
+
69
+ ### Response
70
+
71
+ ```json
72
+ {
73
+ "success": true,
74
+ "output": "final assistant text",
75
+ "parsed_json": {},
76
+ "meta": {
77
+ "specialist": "name",
78
+ "model": "resolved-model",
79
+ "duration_ms": 1234,
80
+ "trace_id": "uuid"
81
+ }
82
+ }
83
+ ```
84
+
85
+ Failure response stays `200` with `success: false`. Closed `error_type` taxonomy:
86
+
87
+ - `specialist_not_found`
88
+ - `specialist_load_error`
89
+ - `template_variable_missing`
90
+ - `template_field_misuse` — `input.template` was the literal name of a key on `spec.prompt` (e.g. `"task_template"`, `"normalize_template"`). Pass template body inline, or use `template_field` for named prompt field; do not pass key name.
91
+ - `auth`
92
+ - `quota`
93
+ - `timeout`
94
+ - `network`
95
+ - `invalid_json`
96
+ - `prompt_too_large`
97
+ - `output_too_large`
98
+ - `internal`
99
+
100
+ `400` only for malformed request JSON, missing `specialist`, or unknown template name.
101
+
102
+ ### Reference clients
103
+
104
+ A stdlib-only Python client lives at [`clients/python/`](../clients/python/). It mirrors the closed `error_type` taxonomy 1:1 and adds a single caller-side `transport` value for HTTP/socket failures. Import as `from specialists_client import SpecialistsClient, SpecialistErrorType`.
105
+
106
+ ## `sp serve`
107
+
108
+ ### CLI
109
+
110
+ ```bash
111
+ sp serve \
112
+ --port <n> \
113
+ --user-dir <path> \
114
+ --concurrency <n> \
115
+ --request-timeout-ms <n> \
116
+ --audit-failure-threshold <n> \
117
+ --allow-skills \
118
+ --allow-skills-roots <p1>:<p2> \
119
+ --reload-poll-ms <n> \
120
+ --readiness-canary off|warn|require \
121
+ --readiness-required-pi-flag <flag> \
122
+ --readiness-canary-specialist <name>
123
+ ```
124
+
125
+ Defaults:
126
+
127
+ - port `8000`
128
+ - user dir `./.specialists/user`
129
+ - concurrency `4`
130
+ - request timeout `120000`
131
+
132
+ ### Runtime
133
+
134
+ - One Node process, one HTTP listener, one `pi` subprocess per in-flight request.
135
+ - `pi` is spawned in `options.projectDir ?? process.cwd()` and gets current one-shot runner contract: `--mode json --no-session --no-extensions --no-tools --offline --no-context-files --no-prompt-templates --no-themes --model <resolved> [--thinking <level>] [--system-prompt <text>] [--skill <path> ... | --no-skills]`; rendered prompt is written to stdin, not argv.
136
+ - Credentials stay inside `pi`; service never handles API keys.
137
+ - Excess load waits behind semaphore, then returns `429`.
138
+
139
+ ### `/healthz`
140
+
141
+ - `200 { ok: true }`
142
+ - Liveness only.
143
+
144
+ ### `/readyz`
145
+
146
+ Readiness gate with explicit reason strings. Failure order:
147
+
148
+ 1. `draining`
149
+ 2. `degraded:audit`
150
+ 3. `pi_config_unreadable`
151
+ 4. `db_not_writable`
152
+ 5. optional Pi canary: `pi_binary_missing`, `pi_flag_missing`, `pi_smoke_failed`
153
+ 6. `empty_user_dir`
154
+ 7. `invalid_spec_in_user_dir`
155
+
156
+ Notes:
157
+
158
+ - `/readyz` uses same state as serve loop.
159
+ - audit failure window is sliding 60s.
160
+ - `SIGTERM` flips service into draining.
161
+ - `evaluateReadiness()` is pure async and testable.
162
+ - Pi canary defaults to `off`; use `--readiness-canary warn` in Docker/Podman rollout to surface `warning` without failing readiness, then `--readiness-canary require` when deployments should block on Pi compatibility.
163
+ - `--readiness-required-pi-flag <flag>` may be repeated; without explicit flags the canary checks the script-runner isolation flags.
164
+ - `--readiness-canary-specialist <name>` adds a minimal smoke generation through a script-class specialist; keep its prompt non-secret and deterministic.
165
+
166
+ ### Trust flags
167
+
168
+ Default-reject. Nothing from user dir runs unless explicitly allowed.
169
+
170
+ Flags:
171
+
172
+ - `--allow-skills`
173
+ - allows `skills.paths` and `prompt.skill_inherit`
174
+ - `--allow-skills-roots <p1>:<p2>`
175
+ - prefix allowlist for `skills.paths` and `prompt.skill_inherit`
176
+ - only active when `--allow-skills` on
177
+ - `--allow-local-scripts` is not supported. `skills.scripts` are always rejected in service/script mode until a separate sandboxed script-execution design exists.
178
+
179
+ Audit behavior:
180
+
181
+ - when `--allow-skills` on, each resolved skill source gets `{ path, sha256 }` in status audit data
182
+ - unreadable file records `sha256: "unreadable"`
183
+ - compat guard still blocks interactive, worktree, and all `skills.scripts` cases
184
+
185
+ ### Hot reload
186
+
187
+ - default watcher: native `fs.watch`
188
+ - fallback: `--reload-poll-ms <n>` polling mode for platforms where native watch is weak
189
+ - debounce: `300ms`
190
+ - change action: `loader.invalidateCache(name)` per touched specialist name
191
+ - reload path stays request-safe: request captures current spec at entry
192
+
193
+ ## `sp script`
194
+
195
+ One-shot CLI on same runtime path as `sp serve`.
196
+
197
+ ### Shape
198
+
199
+ ```bash
200
+ sp script <name> \
201
+ [--vars k=v ...] \
202
+ [--template <text>] \
203
+ [--template-field <name>] \
204
+ [--model <override>] \
205
+ [--thinking <level>] \
206
+ [--project-dir <path>] \
207
+ [--db-path <path>] \
208
+ [--timeout-ms <n>] \
209
+ [--json] \
210
+ [--single-instance <lockpath>] \
211
+ [--no-trace] \
212
+ [--allow-local-scripts] \
213
+ [--allow-write-capable]
214
+ ```
215
+
216
+ Notes:
217
+
218
+ - `--project-dir` resolves specs from `<project-dir>/.specialists/user/` and also becomes `pi` child cwd
219
+ - `--user-dir` still accepted as deprecated alias
220
+ - `--db-path` is an exact SQLite file path for script observability; default remains `<git-root>/.specialists/db/observability.db`
221
+ - rendered prompt is streamed to `pi` stdin; no positional prompt arg anymore
222
+ - default output = assistant text on stdout
223
+ - `--json` returns full response payload
224
+ - `--single-instance` uses `flock`; contention exits `75`
225
+ - trusted local mode only on `sp script`: `--allow-local-scripts` enables `skills.scripts`; `--allow-write-capable` permits non-`READ_ONLY` specialists
226
+
227
+ ### Exit codes
228
+
229
+ | Code | Meaning |
230
+ |---|---|
231
+ | `0` | success |
232
+ | `1` | internal / unknown |
233
+ | `2` | `specialist_not_found` or `specialist_load_error` |
234
+ | `3` | `template_variable_missing` |
235
+ | `4` | `auth` or `quota` |
236
+ | `5` | `timeout` or `network` |
237
+ | `6` | `invalid_json` |
238
+ | `7` | `output_too_large` |
239
+ | `75` | `--single-instance` lock contention |
240
+
241
+ ## Script-class authoring
242
+
243
+ Script-class specialists are JSON specialists with one-shot runtime constraints.
244
+
245
+ Reference schema and examples: [`docs/authoring.md`](authoring.md)
246
+
247
+ ### Required shape
248
+
249
+ - `execution.interactive` must be `false`
250
+ - `execution.requires_worktree` must be `false`
251
+ - `execution.permission_required` must be `READ_ONLY`
252
+ - `skills.scripts` must be empty
253
+ - `prompt.task_template` must exist
254
+ - template variables must all resolve at run time
255
+
256
+ ### Behavior
257
+
258
+ - same model resolution as `sp run`
259
+ - same fallback-model behavior
260
+ - same thinking-level forwarding
261
+ - `prompt.system` becomes `--system-prompt` on `pi` (full override, not append)
262
+ - trusted `skills.paths` and `prompt.skill_inherit` are forwarded as `--skill`; if none are allowed, child gets `--no-skills`
263
+ - same output-schema validation behavior
264
+ - stdout cap defaults to 32MB; override with `SPECIALISTS_SCRIPT_STDOUT_LIMIT_BYTES` or `execution.stdout_limit_bytes`
265
+ - `template_variable_missing` if template references missing `$var`
266
+
267
+ ### What this doc does not cover
268
+
269
+ - full authoring schema details
270
+ - older YAML shape
271
+ - legacy Python/qwen runtime
272
+
273
+ Use [`docs/authoring.md`](authoring.md) for full field reference.
274
+
275
+ ## Observability
276
+
277
+ Every call writes one row to `.specialists/db/observability.db` unless `trace: false` or `--no-trace`.
278
+
279
+ Same observability table, same trace shape, same writer as `sp run`.
280
+
281
+ ## Deployment
282
+
283
+ Sidecar-per-consumer.
284
+
285
+ ```yaml
286
+ services:
287
+ specialists:
288
+ image: specialists-service:local
289
+ command: [sp, serve, --port=8000]
290
+ user: "${UID:-1000}:${GID:-1000}"
291
+ environment:
292
+ HOME: /pi-home
293
+ volumes:
294
+ - ./.specialists:/work/.specialists
295
+ - ${HOME}/.pi:/pi-home/.pi:ro
296
+ working_dir: /work
297
+ networks: [app]
298
+ restart: unless-stopped
299
+ ```
300
+
301
+ Rules:
302
+
303
+ - mount `.specialists/` directory, not only DB file
304
+ - keep local filesystem, not NFS/SMB
305
+ - align container UID/GID with host files
306
+ - keep `pi` auth inside mounted home
307
+
308
+ ## Image release runbook
309
+
310
+ Current state:
311
+
312
+ - build from repo
313
+ - image build keeps `config/` and `scripts/generate-asset-contract.mjs` in context for asset-contract generation
314
+ - publish to registry deferred
315
+ - `Dockerfile` keeps `ARG PI_VERSION=latest`
316
+ - CI canary lives in [`.github/workflows/pi-compat.yml`](../.github/workflows/pi-compat.yml)
317
+
318
+ ### Build
319
+
320
+ ```bash
321
+ docker build -t specialists-service:local .
322
+ ```
323
+
324
+ ### Release intent
325
+
326
+ - root `Dockerfile` is source of runtime image truth
327
+ - pin `@earendil-works/pi-coding-agent` only in release pipeline if needed
328
+ - keep canary green before bumping runtime dependency
329
+ - registry publishing stays future work until release path lands
330
+
331
+ ### Compatibility canary
332
+
333
+ `pi-compat.yml` checks:
334
+
335
+ - required `pi` spawn flags still exist
336
+ - stdin prompt handling still works
337
+ - image boots with latest `pi`
338
+
339
+ ## Merged legacy content
340
+
341
+ ### From `docs/script-specialists.md`
342
+
343
+ - old architecture intent absorbed here as transport/runtime split
344
+ - service-side authoring constraints copied into script-class authoring section
345
+ - old Python/qwen implementation details dropped
346
+ - old YAML-first wording dropped
347
+
348
+ ### From retired image-release notes
349
+
350
+ - build / push intent folded into image release runbook
351
+ - current publish state recorded as deferred
352
+ - CI canary and `PI_VERSION=latest` preserved
353
+
354
+ ## Dropped on purpose
355
+
356
+ - Python/qwen architecture
357
+ - legacy `specialists/**/*.specialist.yaml` framing
358
+ - service claims about being tied to old gateway runtime
359
+ - obsolete image push instructions as active maintainer path
360
+
361
+ ## Operator summary
362
+
363
+ If you need one page for current service behavior, use this doc. If you need field-level authoring schema, use [`docs/authoring.md`](authoring.md).
@@ -0,0 +1,138 @@
1
+ # Surface Ownership and Precedence
2
+
3
+ > Canonical ownership map for specialist assets after layered refactor.
4
+
5
+ ## Four-layer model
6
+
7
+ 1. **Upstream source (package, read-only at runtime)**
8
+ - `config/specialists/*.specialist.json`
9
+ - `config/mandatory-rules/*`
10
+ - `config/nodes/*.node.json`
11
+ 2. **Optional managed/pinned mirror (repo, compatibility/pin layer)**
12
+ - `.specialists/default/*.specialist.json`
13
+ - `.specialists/default/mandatory-rules/*`
14
+ - `.specialists/default/nodes/*.node.json`
15
+ - Empty by default in fresh package-canonical installs; populated only for intentional pins or compatibility snapshots
16
+ 3. **Repo authoring / custom layer (repo-owned)**
17
+ - `.specialists/user/*.specialist.json`
18
+ - `config/nodes/*.node.json` (repo node overrides)
19
+ 4. **Runtime / generated state (never hand-author)**
20
+ - `.specialists/jobs/`
21
+ - `.specialists/ready/`
22
+ - `.specialists/db/`
23
+
24
+ ## Ownership boundaries
25
+
26
+ - `config/*` in package = canonical upstream source.
27
+ - `.specialists/default/*` = optional pin / compatibility snapshot. Prefer package-canonical fallback; prune stale defaults with `sp prune-stale-defaults`.
28
+ - `.specialists/user/*` = repo custom specialists. Safe place for overrides/forks.
29
+ - `.specialists/{jobs,ready,db}` = runtime state. Do not treat as config surface.
30
+
31
+ ## Precedence ladders
32
+
33
+ ### Specialists
34
+
35
+ Runtime loader order (first match wins):
36
+
37
+ 1. `.specialists/user/`
38
+ 2. `.specialists/default/`
39
+ 3. `config/specialists/` (package fallback)
40
+ 4. legacy paths (migration compatibility only)
41
+
42
+ Meaning:
43
+ - Same filename in `.specialists/user/` overrides mirror/package.
44
+ - New filename in `.specialists/user/` extends catalog.
45
+ - `.specialists/default/` can override package fallback for same name.
46
+
47
+ ### Mandatory rules
48
+
49
+ Four-tier index resolution. Loader reads and union-merges all that exist (dedup by set id):
50
+
51
+ 1. `.specialists/user/mandatory-rules/index.json` — repo-owned user overlay, highest priority
52
+ 2. `config/mandatory-rules/index.json` — upstream source, ships with package
53
+ 3. `.specialists/default/mandatory-rules/index.json` — optional pin / compatibility snapshot, pruned by `sp prune-stale-defaults` unless intentionally retained
54
+ 4. `.specialists/mandatory-rules/index.json` — repo overlay, wins on set-id conflict
55
+
56
+ Set-file lookup (`<set-id>.md`) probes the same four paths in reverse precedence:
57
+ `.specialists/user/mandatory-rules/` first, then `.specialists/mandatory-rules/`, then `.specialists/default/mandatory-rules/`, then `config/mandatory-rules/`.
58
+
59
+ Injection merge order (within the resolved index):
60
+
61
+ 1. required sets (union of all tiers)
62
+ 2. default sets (union of all tiers)
63
+ 3. specialist `mandatory_rules.template_sets`
64
+ 4. specialist `mandatory_rules.inline_rules`
65
+
66
+ Global workflow block injected unless `mandatory_rules.disable_default_globals=true`.
67
+
68
+ Full authoring guide: [`config/mandatory-rules/README.md`](../config/mandatory-rules/README.md).
69
+
70
+ ### Nodes
71
+
72
+ Node resolution order:
73
+
74
+ 1. explicit path (`specialists node run ./path/to/file.node.json`)
75
+ 2. `config/nodes/` (repo-owned override layer)
76
+ 3. `.specialists/default/nodes/` (managed mirror fallback)
77
+
78
+ `specialists node list` discovery follows same repo-first then mirror order.
79
+
80
+ ## Repo fork flow (`specialists edit`)
81
+
82
+ ### Same-name override
83
+
84
+ Use when customizing existing specialist without new catalog name.
85
+
86
+ - Create/edit `.specialists/user/<name>.specialist.json`
87
+ - Name unchanged
88
+ - Loader picks user file first
89
+
90
+ ### New-name fork
91
+
92
+ Use when creating variant specialist.
93
+
94
+ - `specialists edit <new-name> --fork-from <base-name>`
95
+ - Writes `.specialists/user/<new-name>.specialist.json`
96
+ - New specialist appears alongside base
97
+
98
+ ## Init, prune, and sync behavior
99
+
100
+ `specialists init` always:
101
+ - ensures `.specialists/user`, `.specialists/jobs`, `.specialists/ready`, `.specialists/db`
102
+ - wires hooks, MCP, skill symlinks
103
+
104
+ Package-canonical runtime assets are read from the installed package when no repo override exists. Fresh repos should normally leave `.specialists/default/` empty.
105
+
106
+ `specialists init --sync-defaults` still exists for compatibility, but it is deprecated because it creates default snapshots that drift. Use it only when an operator deliberately wants a repo-local pin/compatibility mirror.
107
+
108
+ Preferred cleanup:
109
+ - `sp doctor --check-drift` — report stale Category A defaults
110
+ - `sp prune-stale-defaults --dry-run` — preview removals
111
+ - `sp prune-stale-defaults` — remove stale defaults, including diverged defaults by default
112
+ - `sp prune-stale-defaults --keep-diverged` — preserve intentionally diverged defaults
113
+
114
+ ## Migration notes
115
+
116
+ Legacy layouts still recognized for compatibility:
117
+ - `.specialists/user/specialists/*.specialist.json`
118
+ - `.specialists/default/specialists/*.specialist.json`
119
+
120
+ Migration target:
121
+ - `.specialists/user/*.specialist.json`
122
+ - `.specialists/default/*.specialist.json`
123
+
124
+ Operator rule:
125
+ - do not hand-edit `.specialists/default/*`
126
+ - edit in `.specialists/user/*` for repo custom behavior
127
+ - run `sp doctor --check-drift` and `sp prune-stale-defaults` to reconcile default mirror drift
128
+
129
+ ## Explicit non-goal: backlog-clean isolation
130
+
131
+ This ownership/precedence migration does **not** change backlog-clean surfaces.
132
+
133
+ Untouched by this contract:
134
+ - backlog-clean command behavior
135
+ - backlog-clean data model
136
+ - backlog-clean runtime hooks/automation
137
+
138
+ Keep backlog-clean work isolated in dedicated issues/tasks.
@@ -0,0 +1,114 @@
1
+ # KAN-90 / unitAI-1gtou — Upgrading to the global user-config layer
2
+
3
+ This release moves model selection out of the shipped specialist files and into a
4
+ single per-user config file. Before this change every specialist in
5
+ `config/specialists/*.specialist.json` shipped with a hard-coded
6
+ `execution.model` and `execution.fallback_model`. That was a user-environment
7
+ detail (each user has their own provider keys in `pi`), not something the
8
+ package should ship.
9
+
10
+ ## What changed
11
+
12
+ - Every `config/specialists/*.specialist.json` ships with
13
+ `execution.model = null` and `execution.fallback_model = null`.
14
+ - The `SpecialistLoader` resolves each specialist via a 3-layer field-merge:
15
+
16
+ ```
17
+ package canonical (base)
18
+ ⇡ ~/.config/specialists/user.json (your model + per-spec tuning)
19
+ ⇡ .specialists/user/<name> (repo authoring layer)
20
+ ```
21
+
22
+ The repo-managed `.specialists/default/<name>` mirror was retired by commit
23
+ `31a6421c` and is no longer walked by the loader. Stale entries left on disk
24
+ are detected by `drift-detector` and removed by `sp prune-stale-defaults`.
25
+
26
+ - If `execution.model` is still `null` after the full merge, the loader throws
27
+ a `SpecialistMissingModelError` pointing you at `sp edit --global`.
28
+ - `sp init --global` generates the global user config; `sp edit --global` reads
29
+ / writes individual fields; `sp doctor --specialists` reports coverage and
30
+ flags blocked-field attempts.
31
+
32
+ ## Upgrade procedure
33
+
34
+ Run this **once** after upgrading:
35
+
36
+ ```bash
37
+ # 1. Generate ~/.config/specialists/user.json (or $XDG_CONFIG_HOME/...).
38
+ # Idempotent: it is safe to re-run later.
39
+ sp init --global
40
+
41
+ # 2. Pick a default model for any specialist you actually use:
42
+ sp edit --global executor.execution.model anthropic/claude-sonnet-4-6
43
+ sp edit --global executor.execution.fallback_model openai-codex/gpt-5.4-mini
44
+ # ... repeat for any specialist you dispatch
45
+
46
+ # 3. Verify coverage:
47
+ sp doctor --specialists
48
+ ```
49
+
50
+ The `sp doctor` output will list every specialist that still has no model and
51
+ suggest the exact `sp edit --global` command to fix it. Specialists you never
52
+ dispatch can be left alone — the missing-model error only fires at dispatch
53
+ time, never during `specialists list` or `sp doctor`.
54
+
55
+ ## What you can override (per-specialist) in the global config
56
+
57
+ Allowed in `~/.config/specialists/user.json`:
58
+
59
+ - `execution.model`
60
+ - `execution.fallback_model`
61
+ - `execution.timeout_ms`
62
+ - `execution.stall_timeout_ms`
63
+ - `execution.thinking_level`
64
+ - `execution.max_retries`
65
+ - `beads_write_notes`
66
+ - `skills.paths` (append + dedup against the base)
67
+
68
+ Anything else in `user.json` is a blocked field. The loader strips it during
69
+ merge and `sp doctor --specialists` surfaces a `STRIPPED` warning:
70
+
71
+ - `execution.permission_required` — identity field; the package decides what
72
+ tools each role can call.
73
+ - `execution.auto_commit`
74
+ - `prompt.system`
75
+ - `prompt.output_schema`
76
+ - `skills.scripts` — pre/post hooks are part of the role contract.
77
+ - `mandatory_rules`
78
+ - `capabilities`
79
+
80
+ Repo-level overrides (`.specialists/user/<name>`) keep the existing whole-file
81
+ replacement behaviour: blocked fields are applied but `sp doctor --specialists`
82
+ flags them as a `warn`-severity finding so the divergence is visible.
83
+
84
+ ## Path resolution
85
+
86
+ The loader checks in this order:
87
+
88
+ 1. `$XDG_CONFIG_HOME/specialists/user.json` (if `XDG_CONFIG_HOME` is set)
89
+ 2. `~/.config/specialists/user.json`
90
+ 3. `~/.specialists/user.json` (legacy, read-only fallback)
91
+
92
+ `sp init --global` always writes to slot 1 or 2 (the XDG-compliant target).
93
+
94
+ ## Why a single file
95
+
96
+ Earlier sketches considered `~/.specialists/defaults.json` plus per-specialist
97
+ sparse files. The single-file shape (`unitAI-o328h`) was picked because:
98
+
99
+ - One file is the canonical place to look at and edit.
100
+ - No drift between defaults and per-specialist overrides.
101
+ - `sp init --global` only has to manage one file.
102
+ - Removing a specialist from a future release still leaves its block in the
103
+ user's file (with a `removed` notice in `sp init --global` output) so the
104
+ user keeps the history.
105
+
106
+ ## Cross-references
107
+
108
+ - Jira: [KAN-90](https://xtrmxt.atlassian.net/browse/KAN-90)
109
+ - Design decision: bd `unitAI-o328h`
110
+ - Implementation epic: bd `unitAI-1gtou`
111
+ - C1 (loader): `unitAI-1gtou.12` (commit `6604c144`)
112
+ - C2 (CLI): `unitAI-1gtou.13` (commit `5f8d725e`)
113
+ - C3 (doctor): `unitAI-1gtou.14` (commit `6b69a6fe`)
114
+ - C4 (config strip + this doc): `unitAI-1gtou.15`