session-orchestrator 5.2.0 → 5.4.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 (427) hide show
  1. package/.agents/skills/architecture/SKILL.md +3 -1
  2. package/.agents/skills/autopilot/SKILL.md +5 -1
  3. package/.agents/skills/autopilot/agents/openai.yaml +5 -0
  4. package/.agents/skills/bootstrap/SKILL.md +5 -1
  5. package/.agents/skills/bootstrap/agents/openai.yaml +5 -0
  6. package/.agents/skills/brainstorm/SKILL.md +5 -1
  7. package/.agents/skills/brainstorm/agents/openai.yaml +5 -0
  8. package/.agents/skills/claude-md-drift-check/SKILL.md +4 -2
  9. package/.agents/skills/close/SKILL.md +5 -1
  10. package/.agents/skills/close/agents/openai.yaml +5 -0
  11. package/.agents/skills/convergence-monitoring/SKILL.md +4 -2
  12. package/.agents/skills/debug/SKILL.md +5 -1
  13. package/.agents/skills/debug/agents/openai.yaml +5 -0
  14. package/.agents/skills/discovery/SKILL.md +5 -1
  15. package/.agents/skills/discovery/agents/openai.yaml +5 -0
  16. package/.agents/skills/dispatcher/SKILL.md +5 -1
  17. package/.agents/skills/dispatcher/agents/openai.yaml +5 -0
  18. package/.agents/skills/docs-orchestrator/SKILL.md +3 -1
  19. package/.agents/skills/ecosystem-health/SKILL.md +3 -1
  20. package/.agents/skills/eli5/SKILL.md +5 -1
  21. package/.agents/skills/eli5/agents/openai.yaml +5 -0
  22. package/.agents/skills/eval/SKILL.md +6 -2
  23. package/.agents/skills/eval/agents/openai.yaml +5 -0
  24. package/.agents/skills/evolve/SKILL.md +6 -2
  25. package/.agents/skills/evolve/agents/openai.yaml +5 -0
  26. package/.agents/skills/frontmatter-guard/SKILL.md +3 -1
  27. package/.agents/skills/gitlab-ops/SKILL.md +3 -1
  28. package/.agents/skills/gitlab-portfolio/SKILL.md +3 -1
  29. package/.agents/skills/go/SKILL.md +5 -1
  30. package/.agents/skills/go/agents/openai.yaml +5 -0
  31. package/.agents/skills/grill/SKILL.md +5 -1
  32. package/.agents/skills/grill/agents/openai.yaml +5 -0
  33. package/.agents/skills/harness-audit/SKILL.md +5 -1
  34. package/.agents/skills/harness-audit/agents/openai.yaml +5 -0
  35. package/.agents/skills/hook-development/SKILL.md +3 -1
  36. package/.agents/skills/mcp-builder/SKILL.md +3 -1
  37. package/.agents/skills/memory-cleanup/SKILL.md +5 -1
  38. package/.agents/skills/memory-cleanup/agents/openai.yaml +5 -0
  39. package/.agents/skills/mode-selector/SKILL.md +3 -1
  40. package/.agents/skills/navigator/SKILL.md +22 -0
  41. package/.agents/skills/navigator/agents/openai.yaml +5 -0
  42. package/.agents/skills/npm-publish/SKILL.md +4 -2
  43. package/.agents/skills/peekaboo-driver/SKILL.md +3 -1
  44. package/.agents/skills/persona-panel/SKILL.md +5 -1
  45. package/.agents/skills/persona-panel/agents/openai.yaml +5 -0
  46. package/.agents/skills/plan/SKILL.md +5 -1
  47. package/.agents/skills/plan/agents/openai.yaml +5 -0
  48. package/.agents/skills/playwright-driver/SKILL.md +3 -1
  49. package/.agents/skills/portfolio/SKILL.md +5 -1
  50. package/.agents/skills/portfolio/agents/openai.yaml +5 -0
  51. package/.agents/skills/quality-gates/SKILL.md +3 -1
  52. package/.agents/skills/reconcile/SKILL.md +5 -1
  53. package/.agents/skills/reconcile/agents/openai.yaml +5 -0
  54. package/.agents/skills/release/SKILL.md +5 -1
  55. package/.agents/skills/release/agents/openai.yaml +5 -0
  56. package/.agents/skills/remote-offload/SKILL.md +3 -1
  57. package/.agents/skills/repo-audit/SKILL.md +5 -1
  58. package/.agents/skills/repo-audit/agents/openai.yaml +5 -0
  59. package/.agents/skills/session/SKILL.md +21 -0
  60. package/.agents/skills/session/agents/openai.yaml +5 -0
  61. package/.agents/skills/session-end/SKILL.md +3 -1
  62. package/.agents/skills/session-plan/SKILL.md +3 -1
  63. package/.agents/skills/session-start/SKILL.md +3 -1
  64. package/.agents/skills/spinout/SKILL.md +5 -1
  65. package/.agents/skills/spinout/agents/openai.yaml +5 -0
  66. package/.agents/skills/sunset-review/SKILL.md +5 -1
  67. package/.agents/skills/sunset-review/agents/openai.yaml +5 -0
  68. package/.agents/skills/templates-ack/SKILL.md +21 -0
  69. package/.agents/skills/templates-ack/agents/openai.yaml +5 -0
  70. package/.agents/skills/test/SKILL.md +5 -1
  71. package/.agents/skills/test/agents/openai.yaml +5 -0
  72. package/.agents/skills/test-audit/SKILL.md +21 -0
  73. package/.agents/skills/test-audit/agents/openai.yaml +5 -0
  74. package/.agents/skills/test-runner/SKILL.md +3 -1
  75. package/.agents/skills/tmux-layout/SKILL.md +3 -1
  76. package/.agents/skills/using-orchestrator/SKILL.md +3 -1
  77. package/.agents/skills/ux-grill/SKILL.md +5 -1
  78. package/.agents/skills/ux-grill/agents/openai.yaml +5 -0
  79. package/.agents/skills/vault-mirror/SKILL.md +3 -1
  80. package/.agents/skills/vault-sync/SKILL.md +3 -1
  81. package/.agents/skills/wave-executor/SKILL.md +3 -1
  82. package/.agents/skills/write-executable-plan/SKILL.md +3 -1
  83. package/.claude-plugin/marketplace.json +1 -1
  84. package/.claude-plugin/plugin.json +1 -1
  85. package/.codex-plugin/plugin.json +4 -4
  86. package/.codex-plugin/skills/claude-md-drift-check/SKILL.md +1 -1
  87. package/.codex-plugin/skills/convergence-monitoring/SKILL.md +1 -3
  88. package/.codex-plugin/skills/eval/SKILL.md +1 -1
  89. package/.codex-plugin/skills/evolve/SKILL.md +1 -1
  90. package/.codex-plugin/skills/navigator/SKILL.md +22 -0
  91. package/.codex-plugin/skills/{convergence-monitoring → navigator}/agents/openai.yaml +2 -2
  92. package/.codex-plugin/skills/npm-publish/SKILL.md +1 -3
  93. package/.codex-plugin/skills/session/SKILL.md +1 -1
  94. package/.codex-plugin/skills/test-audit/SKILL.md +21 -0
  95. package/.codex-plugin/skills/{npm-publish → test-audit}/agents/openai.yaml +1 -1
  96. package/.cursor/commands/eval.md +1 -1
  97. package/.cursor/commands/navigator.md +15 -0
  98. package/.cursor/commands/session.md +1 -1
  99. package/.cursor/commands/test-audit.md +14 -0
  100. package/.cursor/rules/000-session-orchestrator.mdc +0 -2
  101. package/.cursor/rules/050-plan.mdc +1 -1
  102. package/.cursor/rules/060-evolve.mdc +27 -12
  103. package/.cursor/skills/claude-md-drift-check/SKILL.md +1 -1
  104. package/.cursor/skills/convergence-monitoring/SKILL.md +1 -0
  105. package/.cursor/skills/eval/SKILL.md +1 -1
  106. package/.cursor/skills/navigator/SKILL.md +13 -0
  107. package/.cursor/skills/npm-publish/SKILL.md +1 -0
  108. package/.cursor/skills/test-audit/SKILL.md +12 -0
  109. package/.cursor-plugin/plugin.json +1 -1
  110. package/.orchestrator/policy/blocked-commands.json +12 -3
  111. package/AGENTS.md +9 -30
  112. package/CHANGELOG.md +206 -0
  113. package/README.md +13 -9
  114. package/SECURITY.md +12 -0
  115. package/agents/dialectic-deriver.md +13 -10
  116. package/agents/eval-judge.md +67 -45
  117. package/agents/skill-applied-judge.md +34 -19
  118. package/commands/session.md +7 -3
  119. package/docs/agent-authoring.md +2 -2
  120. package/docs/baseline.md +22 -7
  121. package/docs/ci-setup.md +57 -4
  122. package/docs/codex-setup.md +14 -2
  123. package/docs/components.md +12 -10
  124. package/docs/events-schema.md +65 -15
  125. package/docs/persona-panel.md +5 -4
  126. package/docs/rule-authoring.md +84 -17
  127. package/docs/scope-collision-guard.md +26 -4
  128. package/docs/session-config-reference.md +154 -12
  129. package/docs/session-config-template.md +41 -3
  130. package/docs/telemetry.md +2 -0
  131. package/hooks/_lib/hook-import-set.json +87 -6
  132. package/hooks/_lib/subagent-transcript.mjs +582 -31
  133. package/hooks/config-protection.mjs +11 -3
  134. package/hooks/cwd-change-restore.mjs +11 -3
  135. package/hooks/enforce-commands.mjs +70 -23
  136. package/hooks/enforce-scope.mjs +143 -33
  137. package/hooks/hooks-codex.json +1 -1
  138. package/hooks/hooks-cursor.json +5 -0
  139. package/hooks/hooks-pi.json +5 -0
  140. package/hooks/hooks.json +6 -1
  141. package/hooks/loop-guard.mjs +11 -3
  142. package/hooks/on-session-end.mjs +58 -23
  143. package/hooks/on-session-start.mjs +101 -11
  144. package/hooks/on-stop.mjs +170 -22
  145. package/hooks/operator-steer.mjs +11 -3
  146. package/hooks/post-bash-issue-budget-refund.mjs +18 -8
  147. package/hooks/post-bash-write-verify.mjs +3 -2
  148. package/hooks/post-edit-import-probe.mjs +17 -9
  149. package/hooks/post-edit-validate.mjs +13 -5
  150. package/hooks/post-subagent-discovery-validator.mjs +98 -13
  151. package/hooks/post-tool-batch-wave-signal.mjs +202 -38
  152. package/hooks/post-tool-failure-corrective-context.mjs +11 -5
  153. package/hooks/post-tooluse-frontend-slop.mjs +10 -4
  154. package/hooks/pre-auq-clarity.mjs +15 -2
  155. package/hooks/pre-bash-destructive-guard.mjs +80 -9
  156. package/hooks/pre-bash-issue-budget.mjs +16 -11
  157. package/hooks/pre-bash-memory-propose-audit.mjs +137 -56
  158. package/hooks/pre-bash-sessions-ledger-guard.mjs +419 -22
  159. package/hooks/pre-bash-staging-fence.mjs +335 -31
  160. package/hooks/pre-bash-templates-first.mjs +19 -14
  161. package/hooks/pre-edit-sessions-ledger-guard.mjs +162 -0
  162. package/hooks/pre-task-scope-disjoint.mjs +792 -74
  163. package/hooks/subagent-telemetry.mjs +111 -38
  164. package/hooks/wave-scope-commit-guard.mjs +197 -100
  165. package/monitors/monitors.json +1 -1
  166. package/output-styles/wave-summary.md +1 -1
  167. package/package.json +3 -3
  168. package/pi/prompts/eval.md +1 -1
  169. package/pi/prompts/navigator.md +12 -0
  170. package/pi/prompts/session.md +1 -1
  171. package/pi/prompts/test-audit.md +12 -0
  172. package/rules/README.md +7 -2
  173. package/rules/_index.md +3 -3
  174. package/rules/always-on/bash-harness-pitfalls.md +7 -1
  175. package/rules/opt-in-domain/prompt-caching.md +6 -2
  176. package/rules/opt-in-stack/backend-data.md +10 -2
  177. package/rules/opt-in-stack/backend.md +10 -4
  178. package/rules/opt-in-stack/frontend.md +7 -2
  179. package/rules/opt-in-stack/security-web.md +10 -4
  180. package/rules/opt-in-stack/swift.md +6 -2
  181. package/scripts/apply-session-learnings.mjs +492 -0
  182. package/scripts/archive-closed-prds.mjs +2 -1
  183. package/scripts/autopilot.mjs +70 -53
  184. package/scripts/backfill-abandoned-sessions.mjs +118 -16
  185. package/scripts/baseline-archetypes.mjs +1 -1
  186. package/scripts/check-package-manager.mjs +62 -5
  187. package/scripts/check-sessions-integrity.mjs +300 -0
  188. package/scripts/cursor-install.mjs +1 -4
  189. package/scripts/dialectic-deriver.mjs +50 -13
  190. package/scripts/emit-session.mjs +371 -31
  191. package/scripts/eval-session.mjs +65 -3
  192. package/scripts/export-hw-learnings.mjs +22 -3
  193. package/scripts/fleet-checkin.mjs +147 -0
  194. package/scripts/generate-agents-skills.mjs +102 -29
  195. package/scripts/generate-cursor-adapter.mjs +61 -16
  196. package/scripts/lib/agent-frontmatter.mjs +3 -3
  197. package/scripts/lib/agent-status.mjs +2 -31
  198. package/scripts/lib/auq/clarity.mjs +10 -2
  199. package/scripts/lib/auq/parse.mjs +12 -31
  200. package/scripts/lib/auq/schema.mjs +56 -41
  201. package/scripts/lib/auto-dialectic.mjs +304 -15
  202. package/scripts/lib/auto-dream.mjs +7 -6
  203. package/scripts/lib/autopilot/flags.mjs +18 -2
  204. package/scripts/lib/autopilot/kill-switches.mjs +6 -3
  205. package/scripts/lib/autopilot/loop.mjs +19 -2
  206. package/scripts/lib/autopilot/stall-sampler.mjs +80 -23
  207. package/scripts/lib/baseline-archetypes.mjs +41 -22
  208. package/scripts/lib/ci-status-banner.mjs +376 -16
  209. package/scripts/lib/command-blocker.mjs +275 -28
  210. package/scripts/lib/config/dialectic.mjs +12 -3
  211. package/scripts/lib/config/gate.mjs +74 -0
  212. package/scripts/lib/config/host-paths.mjs +79 -0
  213. package/scripts/lib/config/persona-gate-wave.mjs +3 -3
  214. package/scripts/lib/config/reaper.mjs +163 -0
  215. package/scripts/lib/config-schema.mjs +13 -0
  216. package/scripts/lib/config.mjs +85 -10
  217. package/scripts/lib/convergence-monitor.mjs +74 -11
  218. package/scripts/lib/ecosystem-health.mjs +11 -0
  219. package/scripts/lib/eval/engine.mjs +421 -53
  220. package/scripts/lib/eval/judge.mjs +463 -40
  221. package/scripts/lib/eval/schema.mjs +10 -1
  222. package/scripts/lib/events-rotation.mjs +221 -25
  223. package/scripts/lib/events-schema.mjs +114 -0
  224. package/scripts/lib/events.mjs +545 -7
  225. package/scripts/lib/fleet-protocol.mjs +270 -0
  226. package/scripts/lib/frontmatter-guard.mjs +21 -10
  227. package/scripts/lib/gates/gate-baseline.mjs +40 -5
  228. package/scripts/lib/gates/gate-full.mjs +35 -5
  229. package/scripts/lib/gates/gate-helpers.mjs +336 -23
  230. package/scripts/lib/gates/gate-incremental.mjs +49 -23
  231. package/scripts/lib/gates/gate-per-file.mjs +42 -8
  232. package/scripts/lib/gitlab-portfolio/markdown-writer.mjs +6 -1
  233. package/scripts/lib/instruction-budget-guard.mjs +208 -8
  234. package/scripts/lib/io.mjs +42 -8
  235. package/scripts/lib/issue-close-strip-labels.mjs +207 -49
  236. package/scripts/lib/js-mask.mjs +197 -0
  237. package/scripts/lib/learnings/evolve-telemetry.mjs +11 -7
  238. package/scripts/lib/learnings/expiry-sweep.mjs +34 -3
  239. package/scripts/lib/learnings/io.mjs +154 -26
  240. package/scripts/lib/learnings/schema.mjs +163 -15
  241. package/scripts/lib/learnings/sizing-subject.mjs +2 -2
  242. package/scripts/lib/maintenance-due-banner.mjs +53 -88
  243. package/scripts/lib/memory-proposals/schema.mjs +11 -5
  244. package/scripts/lib/named-baseline-resolver.mjs +53 -28
  245. package/scripts/lib/named-vault-resolver.mjs +104 -5
  246. package/scripts/lib/orphan-reaper/defaults.mjs +41 -0
  247. package/scripts/lib/orphan-reaper/ps-snapshot.mjs +181 -0
  248. package/scripts/lib/orphan-reaper/reaper-audit.mjs +291 -0
  249. package/scripts/lib/orphan-reaper/reaper-decide.mjs +395 -0
  250. package/scripts/lib/orphan-reaper/scan-throttle.mjs +92 -0
  251. package/scripts/lib/orphan-reaper/scan.mjs +506 -0
  252. package/scripts/lib/orphan-reaper.mjs +316 -0
  253. package/scripts/lib/owner-yaml.mjs +104 -6
  254. package/scripts/lib/peer-cards/merger.mjs +48 -10
  255. package/scripts/lib/peer-cards/reader.mjs +78 -2
  256. package/scripts/lib/persona-panel/catalog-loader.mjs +1 -1
  257. package/scripts/lib/process-group.mjs +950 -0
  258. package/scripts/lib/project-hygiene.mjs +21 -1
  259. package/scripts/lib/quality-gate.mjs +152 -33
  260. package/scripts/lib/reconcile/backlog.mjs +368 -0
  261. package/scripts/lib/reconcile/engine.mjs +55 -188
  262. package/scripts/lib/reconcile/rule-expiry-sweep.mjs +302 -60
  263. package/scripts/lib/reconcile/sanitize.mjs +69 -3
  264. package/scripts/lib/reconcile-nudge-banner.mjs +138 -45
  265. package/scripts/lib/resource-probe/parsers.mjs +31 -0
  266. package/scripts/lib/resource-probe.mjs +1 -1
  267. package/scripts/lib/rule-loader.mjs +141 -74
  268. package/scripts/lib/rules-sync.mjs +27 -12
  269. package/scripts/lib/scope-baseline.mjs +3 -4
  270. package/scripts/lib/scope-echo.mjs +39 -2
  271. package/scripts/lib/scope-gate.mjs +605 -1
  272. package/scripts/lib/session-close-backfill.mjs +33 -6
  273. package/scripts/lib/session-id.mjs +9 -20
  274. package/scripts/lib/session-invocation.mjs +20 -0
  275. package/scripts/lib/session-record-repair.mjs +183 -26
  276. package/scripts/lib/session-registry.mjs +27 -2
  277. package/scripts/lib/session-schema/constants.mjs +56 -2
  278. package/scripts/lib/session-schema/normalizer.mjs +56 -4
  279. package/scripts/lib/session-schema/validator.mjs +28 -1
  280. package/scripts/lib/session-schema.mjs +8 -3
  281. package/scripts/lib/session-start-probes.mjs +95 -10
  282. package/scripts/lib/session-token-rollup.mjs +245 -52
  283. package/scripts/lib/sessions-canonical.mjs +118 -4
  284. package/scripts/lib/sessions-integrity-banner.mjs +7 -1
  285. package/scripts/lib/sessions-staleness-banner.mjs +193 -51
  286. package/scripts/lib/sh-quote.mjs +29 -0
  287. package/scripts/lib/skill-evidence-window.mjs +891 -0
  288. package/scripts/lib/skill-evolution/candidate-intake.mjs +133 -12
  289. package/scripts/lib/skill-evolution/engine.mjs +18 -9
  290. package/scripts/lib/skill-judge.mjs +45 -3
  291. package/scripts/lib/subagents-schema.mjs +30 -3
  292. package/scripts/lib/tail-window.mjs +56 -0
  293. package/scripts/lib/telemetry/pricing.mjs +118 -71
  294. package/scripts/lib/telemetry/schema.mjs +30 -0
  295. package/scripts/lib/telemetry/sync.mjs +61 -6
  296. package/scripts/lib/telemetry-flush-health-banner.mjs +4 -22
  297. package/scripts/lib/test-runner/issue-reconcile.mjs +48 -16
  298. package/scripts/lib/tests-src-ratio.mjs +140 -23
  299. package/scripts/lib/tmux-layout/layouts.mjs +1 -11
  300. package/scripts/lib/tmux-layout/telemetry-stats.mjs +72 -13
  301. package/scripts/lib/tmux-layout/tmux-shell.mjs +2 -11
  302. package/scripts/lib/user-invocable-skills.mjs +23 -3
  303. package/scripts/lib/ux-grill/reconcile.mjs +48 -22
  304. package/scripts/lib/validate/check-agents-skills.mjs +26 -15
  305. package/scripts/lib/validate/check-agents.mjs +1 -1
  306. package/scripts/lib/validate/check-cursor-adapter.mjs +1 -0
  307. package/scripts/lib/validate/check-entry-guard.mjs +13 -50
  308. package/scripts/lib/validate/check-hook-entry-guards.mjs +636 -0
  309. package/scripts/lib/validate/check-hooks-symmetry.mjs +5 -0
  310. package/scripts/lib/validate/check-learnings-shell-writes.mjs +214 -0
  311. package/scripts/lib/validate/check-pi-prompts.mjs +1 -0
  312. package/scripts/lib/validate/check-rules.mjs +7 -5
  313. package/scripts/lib/validate/check-skill-links.mjs +9 -1
  314. package/scripts/lib/validate/check-skill-script-paths.mjs +239 -27
  315. package/scripts/lib/validate/check-test-git-config-target.mjs +24 -34
  316. package/scripts/lib/validate/check-test-value-bans.mjs +87 -14
  317. package/scripts/lib/validate/check-unicode-safety.mjs +1 -0
  318. package/scripts/lib/validate/check-untracked-test-deps.mjs +7 -102
  319. package/scripts/lib/validate/check-unwired-features.mjs +130 -27
  320. package/scripts/lib/validate/check-validator-registration.mjs +34 -10
  321. package/scripts/lib/validate/confidential-names.mjs +10 -0
  322. package/scripts/lib/validate-vendored-rules.mjs +210 -84
  323. package/scripts/lib/vault-mirror/namespace.mjs +46 -8
  324. package/scripts/lib/vault-mirror/process.mjs +10 -3
  325. package/scripts/lib/vault-mirror/render-sessions.mjs +12 -2
  326. package/scripts/lib/vault-mirror/telemetry.mjs +8 -1
  327. package/scripts/lib/vault-status/board-writer.mjs +48 -11
  328. package/scripts/lib/vault-status/narrative-mirror.mjs +71 -16
  329. package/scripts/lib/vault-yaml.mjs +118 -0
  330. package/scripts/lib/wave-executor/dispatch-common.mjs +10 -18
  331. package/scripts/lib/wave-executor/foreign-dispatch.mjs +1 -1
  332. package/scripts/lib/wave-executor/remote-dispatch.mjs +1 -1
  333. package/scripts/lib/wave-resource-gate.mjs +34 -8
  334. package/scripts/lib/worktree/lifecycle.mjs +153 -1
  335. package/scripts/memory-propose.mjs +18 -5
  336. package/scripts/release-session-lock.mjs +306 -0
  337. package/scripts/release.mjs +40 -8
  338. package/scripts/repair-invalid-sessions.mjs +37 -4
  339. package/scripts/resolve-session-invocation.mjs +59 -0
  340. package/scripts/run-migrate-v2-cross-repo.mjs +158 -30
  341. package/scripts/run-quality-gate.mjs +357 -197
  342. package/scripts/site-numbers.mjs +163 -5
  343. package/scripts/sweep-expired-learnings.mjs +56 -5
  344. package/scripts/sweep-expired-rules.mjs +16 -4
  345. package/scripts/validate-plugin.mjs +19 -0
  346. package/scripts/validate-wave-scope.mjs +32 -105
  347. package/scripts/vault-integration-watcher.mjs +2 -1
  348. package/scripts/vault-mirror.mjs +81 -47
  349. package/scripts/wave-scope-binding.mjs +2 -1
  350. package/skills/_shared/config-reading.md +3 -3
  351. package/skills/_shared/fleet-protocol.md +131 -0
  352. package/skills/_shared/platform-tools.md +23 -11
  353. package/skills/_shared/state-ownership.md +5 -0
  354. package/skills/autopilot/SKILL.md +47 -18
  355. package/skills/bootstrap/SKILL.md +1 -1
  356. package/skills/bootstrap/_shared-template.md +1 -1
  357. package/skills/bootstrap/fast-template.md +1 -1
  358. package/skills/bootstrap/private-contract.md +2 -1
  359. package/skills/bootstrap/public-fallback.md +6 -3
  360. package/skills/bootstrap/references/bootstrap-retroactive-flow.md +2 -1
  361. package/skills/claude-md-drift-check/SKILL.md +10 -10
  362. package/skills/claude-md-drift-check/checker.mjs +26 -18
  363. package/skills/convergence-monitoring/README.md +8 -1
  364. package/skills/convergence-monitoring/SIGNALS.md +50 -6
  365. package/skills/convergence-monitoring/SKILL.md +15 -6
  366. package/skills/eval/SKILL.md +39 -24
  367. package/skills/eval/rubric-v1.md +1 -0
  368. package/skills/eval/rubric-v2.md +457 -0
  369. package/skills/evolve/SKILL.md +3 -3
  370. package/skills/evolve/references/evolve-analyze-mode.md +10 -6
  371. package/skills/evolve/references/evolve-dialectic-mode.md +42 -25
  372. package/skills/gitlab-ops/SKILL.md +3 -2
  373. package/skills/memory-cleanup/SKILL.md +1 -1
  374. package/skills/navigator/SKILL.md +193 -0
  375. package/skills/navigator/references/account-check.sh +87 -0
  376. package/skills/navigator/references/fleet-decisions.mjs +231 -0
  377. package/skills/navigator/references/slot-check.sh +114 -0
  378. package/skills/npm-publish/SKILL.md +1 -1
  379. package/skills/persona-panel/SKILL.md +2 -2
  380. package/skills/persona-panel/persona-format.md +2 -2
  381. package/skills/persona-panel/presets/designer-lens.md +1 -1
  382. package/skills/persona-panel/presets/engineer-lens.md +1 -1
  383. package/skills/persona-panel/presets/pm-lens.md +1 -1
  384. package/skills/plan/mode-retro.md +19 -4
  385. package/skills/quality-gates/SKILL.md +6 -4
  386. package/skills/reconcile/SKILL.md +11 -0
  387. package/skills/remote-offload/SKILL.md +4 -2
  388. package/skills/session-end/SKILL.md +13 -16
  389. package/skills/session-end/discovery-scan.md +1 -1
  390. package/skills/session-end/learning-patterns.md +22 -12
  391. package/skills/session-end/metrics-collection.md +5 -6
  392. package/skills/session-end/phase-3-6-tail.md +55 -9
  393. package/skills/session-end/references/phase-3-documentation-updates.md +2 -2
  394. package/skills/session-end/references/phase-4a-worktree-cleanup.md +2 -0
  395. package/skills/session-end/references/phase-5-issue-cleanup.md +9 -14
  396. package/skills/session-end/references/session-summary-template.md +1 -1
  397. package/skills/session-end/session-metrics-write.md +32 -60
  398. package/skills/session-plan/SKILL.md +17 -8
  399. package/skills/session-plan/references/session-plan-task-classification.md +2 -2
  400. package/skills/session-start/SKILL.md +6 -0
  401. package/skills/session-start/references/operations-contract.md +4 -0
  402. package/skills/session-start/references/phase-1-7-vault-status-board.md +1 -1
  403. package/skills/session-start/references/phase-4-ssot-environment-check.md +4 -3
  404. package/skills/test-audit/SKILL.md +152 -0
  405. package/skills/test-audit/references/campaign.md +111 -0
  406. package/skills/test-audit/references/mutate.sh +50 -0
  407. package/skills/ux-grill/SKILL.md +1 -1
  408. package/skills/wave-executor/SKILL.md +9 -5
  409. package/skills/wave-executor/circuit-breaker.md +2 -0
  410. package/skills/wave-executor/references/wave-executor-state-init.md +8 -3
  411. package/skills/wave-executor/references/wave-loop-dispatch.md +5 -2
  412. package/skills/wave-executor/references/wave-loop-review.md +3 -5
  413. package/templates/personas/README.md +5 -5
  414. package/templates/personas/accounting-compliance.v1.md +1 -1
  415. package/templates/personas/accounting-tax-advisor.v1.md +1 -1
  416. package/templates/personas/buyer-p1-cto.v1.md +1 -1
  417. package/templates/personas/buyer-p2-kanzlei.v1.md +1 -1
  418. package/templates/personas/buyer-p3-build.v1.md +1 -1
  419. package/templates/personas/buyer-p4-tech-veto.v1.md +1 -1
  420. package/templates/personas/buyer-p5-solo.v1.md +1 -1
  421. package/templates/personas/buyer-p6-ld.v1.md +1 -1
  422. package/templates/personas/klima-ai-expert.v1.md +1 -1
  423. package/templates/personas/klima-physicist.v1.md +1 -1
  424. package/.cursor/commands/convergence-monitoring.md +0 -13
  425. package/.cursor/commands/npm-publish.md +0 -13
  426. package/pi/prompts/convergence-monitoring.md +0 -11
  427. package/pi/prompts/npm-publish.md +0 -11
@@ -18,7 +18,7 @@
18
18
  * 2 — filesystem error
19
19
  *
20
20
  * Output: one JSON line per action on stdout:
21
- * {"action":"created|updated|skipped-noop|skipped-handwritten|skipped-collision-resolved|skipped-invalid|skipped-quality-low","path":"...","kind":"...","id":"..."}
21
+ * {"action":"created|updated|skipped-noop|skipped-handwritten|skipped-collision-resolved|skipped-invalid|skipped-quality-low|skipped-abandoned|skipped-duplicate-session","path":"...","kind":"...","id":"..."}
22
22
  *
23
23
  * Idempotency rules:
24
24
  * 1. File does not exist → create.
@@ -48,22 +48,27 @@
48
48
  * Part of session-orchestrator vault-mirror (Issue #14).
49
49
  */
50
50
 
51
- import { spawnSync } from 'node:child_process';
52
51
  import { existsSync } from 'node:fs';
53
- import { resolve } from 'node:path';
52
+ import { basename, resolve } from 'node:path';
54
53
  import { createInterface } from 'node:readline';
55
54
  import { createReadStream } from 'node:fs';
56
55
 
57
- import { processLearning, processSession, getMaskerStats } from './lib/vault-mirror/process.mjs';
56
+ import {
57
+ processLearning,
58
+ processSession,
59
+ getMaskerStats,
60
+ emitAction,
61
+ } from './lib/vault-mirror/process.mjs';
58
62
  import { emitMirrorEvent, emitMirrorRunEvent } from './lib/vault-mirror/telemetry.mjs';
59
63
  import { emitEvent } from './lib/events.mjs';
60
64
  import { autoCommitVaultMirror } from './lib/vault-mirror/auto-commit.mjs';
61
65
  import { parseColumnFlags, CliFlagError } from './lib/cli-flags.mjs';
62
66
  import { resolveRepoNamespace } from './lib/vault-mirror/namespace.mjs';
63
- import { resolveCanonicalSuffixes } from './lib/named-vault-resolver.mjs';
67
+ import { checkCanonicalVault, describeOriginForLog, normalizeRemote } from './lib/named-vault-resolver.mjs';
64
68
  import { loadOwnerConfig } from './lib/owner-yaml.mjs';
65
69
  import { canonicalizeSessions } from './lib/sessions-canonical.mjs';
66
70
  import { isMainModule } from './lib/is-main-module.mjs';
71
+ import { expandTilde } from './lib/common.mjs';
67
72
 
68
73
  // ── Canonical-vault helpers (#600 D2 / #607 D2) ────────────────────────────────
69
74
  // These are module-level (above the CLI bootstrap) so the module is import-safe
@@ -85,7 +90,7 @@ export function _resolveCanonicalSuffix(envValue) {
85
90
  return envValue && envValue.trim() ? envValue.trim() : '/agents/vault';
86
91
  }
87
92
 
88
- // Kept for documentation; the guard now uses resolveCanonicalSuffixes() which
93
+ // Kept for documentation; the guard now uses checkCanonicalVault() which
89
94
  // generalises this to N suffixes. The `_` prefix satisfies the no-unused-vars rule.
90
95
  const _CANONICAL_VAULT_SUFFIX = _resolveCanonicalSuffix(
91
96
  process.env.VAULT_MIRROR_CANONICAL_SUFFIX,
@@ -93,18 +98,14 @@ const _CANONICAL_VAULT_SUFFIX = _resolveCanonicalSuffix(
93
98
 
94
99
  /**
95
100
  * Normalize a git remote URL to a host/path tail for canonical-suffix matching
96
- * (#607 D2 — exported for unit tests). Strips `.git`, the `git@host:` / scheme
97
- * prefixes, and trailing slashes.
101
+ * (#607 D2 — exported for unit tests). Since #1450 the ONE implementation is
102
+ * `normalizeRemote` in lib/named-vault-resolver.mjs, shared with the board
103
+ * writer's guard; this name is kept for the existing test imports.
98
104
  * @param {string} url
99
105
  * @returns {string}
100
106
  */
101
107
  export function _normalizeRemote(url) {
102
- return String(url ?? '')
103
- .trim()
104
- .replace(/\.git$/, '')
105
- .replace(/^git@([^:]+):/, '$1/')
106
- .replace(/^[a-z]+:\/\//, '')
107
- .replace(/\/+$/, '');
108
+ return normalizeRemote(url);
108
109
  }
109
110
 
110
111
  // ── Mirror telemetry (#1116) ──────────────────────────────────────────────────
@@ -235,7 +236,11 @@ if (flagValues.help === true) {
235
236
  process.exit(0);
236
237
  }
237
238
 
238
- const vaultDir = flagValues['vault-dir'];
239
+ // Expand a leading `~` before anything touches the path: owner.yaml `vault-dirs:` /
240
+ // `paths.vault-dir` and the committed Session Config all accept `~/…`, and a quoted
241
+ // `--vault-dir "~/…"` reaches us literally. `resolve('~/x')` would yield `<cwd>/~/x`
242
+ // and the existsSync check below would abort with `missing-vault-dir` (agents/vault#319).
243
+ const vaultDir = expandTilde(flagValues['vault-dir']);
239
244
  const source = flagValues.source;
240
245
  const kind = flagValues.kind;
241
246
  const dryRun = flagValues['dry-run'] === true;
@@ -323,6 +328,21 @@ if (kind !== 'learning' && kind !== 'session') {
323
328
  // imports) so they are import-safe and unit-testable; see _resolveCanonicalSuffix
324
329
  // / _normalizeRemote there (#607 D2).
325
330
 
331
+ /**
332
+ * Render a CLI path flag for a stderr line as its basename only (#1479).
333
+ *
334
+ * This CLI's stderr lands in CI logs and session transcripts, and an absolute
335
+ * `--vault-dir` / `--source` carries the operator's home directory — the
336
+ * owner-leakage class `.claude/rules/security.md` § Owner-Privacy guards. The
337
+ * basename still says WHICH value was wrong; the caller passed the full path
338
+ * and already knows it.
339
+ * @param {string} p
340
+ * @returns {string}
341
+ */
342
+ function pathForLog(p) {
343
+ return `.../${basename(String(p ?? ''))}`;
344
+ }
345
+
326
346
  // ── Run-level accounting + run close-out (#1147) ──────────────────────────────
327
347
  //
328
348
  // Deliberately OUTSIDE main(): the run event's whole contract is that it is
@@ -430,32 +450,29 @@ async function main() {
430
450
  // are all `0`, and `aborted` is what makes that zero readable as "never
431
451
  // started" rather than "ran over an empty source".
432
452
  if (!existsSync(resolve(vaultDir))) {
433
- process.stderr.write(`vault-mirror: vault-dir not found: ${vaultDir}\n`);
453
+ process.stderr.write(`vault-mirror: vault-dir not found: ${pathForLog(vaultDir)}\n`);
434
454
  await finishRun('missing-vault-dir');
435
455
  process.exit(2);
436
456
  }
437
457
 
438
- if (process.env.VAULT_MIRROR_SKIP_CANONICAL_CHECK !== '1') {
439
- const res = spawnSync('git', ['-C', resolve(vaultDir), 'remote', 'get-url', 'origin'], {
440
- encoding: 'utf8',
441
- });
442
- const canonicalSuffixes = resolveCanonicalSuffixes({
443
- ownerConfig: loadOwnerConfig().config,
444
- env: process.env,
445
- });
446
- const ok = res.status === 0 && canonicalSuffixes.some((s) => _normalizeRemote(res.stdout).endsWith(s));
447
- if (!ok) {
448
- const got = res.status === 0 ? res.stdout.trim() : 'no git origin';
449
- process.stderr.write(
450
- `vault-mirror: refusing to mirror — "${vaultDir}" is not the canonical Meta-Vault (expected git origin ending in one of: ${canonicalSuffixes.join(', ')}; got ${got})\n`,
451
- );
452
- await finishRun('vault-not-canonical');
453
- process.exit(2);
454
- }
458
+ // The check itself — origin probe, suffix match, the SKIP_CANONICAL_CHECK
459
+ // escape hatch — is the shared `checkCanonicalVault` (#1450), the same one the
460
+ // board writer applies, so the two vault writers cannot drift apart again.
461
+ const canonical = checkCanonicalVault({
462
+ vaultDir: resolve(vaultDir),
463
+ ownerConfig: loadOwnerConfig().config,
464
+ env: process.env,
465
+ });
466
+ if (!canonical.ok) {
467
+ process.stderr.write(
468
+ `vault-mirror: refusing to mirror — vault is not the canonical Meta-Vault (expected git origin ending in one of: ${canonical.expected.join(', ')}; got ${describeOriginForLog(canonical.got) || 'no git origin'})\n`,
469
+ );
470
+ await finishRun('vault-not-canonical');
471
+ process.exit(2);
455
472
  }
456
473
 
457
474
  if (!existsSync(resolve(source))) {
458
- process.stderr.write(`vault-mirror: source file not found: ${source}\n`);
475
+ process.stderr.write(`vault-mirror: source file not found: ${pathForLog(source)}\n`);
459
476
  await finishRun('missing-source');
460
477
  process.exit(2);
461
478
  }
@@ -485,6 +502,10 @@ async function main() {
485
502
  kind,
486
503
  force,
487
504
  vaultName,
505
+ // #1389: the repo whose `.vault.yaml` declares the namespace slug. This CLI
506
+ // has no repo-root flag, so it is the invocation cwd — bound ONCE here and
507
+ // shared by every processor call and the auto-commit below.
508
+ repoRoot: process.cwd(),
488
509
  qualityMinNarrativeChars,
489
510
  qualityMinConfidence,
490
511
  };
@@ -650,18 +671,27 @@ async function main() {
650
671
  if (isIdentifiable(entry) && !survivors.has(entry)) {
651
672
  // A losing duplicate: an earlier line whose `session_id` a LATER line
652
673
  // in this same batch supersedes or overwrites (crash-recovery
653
- // re-append, #1068 stub/supersede pair). No dispatch, no stdout line,
654
- // no tally for it — the winning occurrence (dispatched below, at its
655
- // own position) already produces the ONE note this physical session
656
- // gets. BV-004 ceiling: `runState.total` still counts this raw line,
657
- // so `created+updated+skipped+failed` no longer partitions `total`
658
- // for a `--kind session` run that collapsed at least one duplicate —
659
- // no test pins that invariant for session kind (only for `learning`,
660
- // where duplicates are not collapsed), and a partially-written vault
661
- // from a batch that could not be fully deduped is the worse failure
662
- // mode. Revisit with a dedicated telemetry action if an operator ever
663
- // needs to name WHICH lines were collapsed, not just how many notes
664
- // were written.
674
+ // re-append, #1068 stub/supersede pair). Never dispatched — the winning
675
+ // occurrence (dispatched below, at its own position) produces the ONE
676
+ // note this physical session gets. It is still ACCOUNTED for (#1291):
677
+ // `skipped-duplicate-session` goes through the same per-entry path as
678
+ // every other skip (stdout line + per-entry ledger record, no `path`
679
+ // because no target file exists for it) and into the tally, so
680
+ // `created+updated+skipped+failed === total` partitions a `--kind
681
+ // session` run that collapsed duplicates, and the ledger names WHICH
682
+ // lines were collapsed, not just how many notes were written.
683
+ tally(
684
+ await emitAction({
685
+ action: 'skipped-duplicate-session',
686
+ path: null,
687
+ kind,
688
+ id: entry.session_id,
689
+ vaultDir: ctx.vaultDir,
690
+ meta: { line: sessionLineNums[i] },
691
+ line: sessionLineNums[i],
692
+ dryRun,
693
+ }),
694
+ );
665
695
  continue;
666
696
  }
667
697
  await dispatchEntry(entry, sessionLineNums[i]);
@@ -693,7 +723,11 @@ async function main() {
693
723
  // Opt-in: triggers only when --session-id is provided. Callers (session-end, evolve)
694
724
  // pass it explicitly; bare invocations stay quiet to preserve legacy behaviour.
695
725
  if (!dryRun && !noCommit && sessionIdArg) {
696
- autoCommitVaultMirror(resolve(vaultDir), sessionIdArg, resolveRepoNamespace({ vaultName }));
726
+ autoCommitVaultMirror(
727
+ resolve(vaultDir),
728
+ sessionIdArg,
729
+ resolveRepoNamespace({ vaultName, repoRoot: ctx.repoRoot }),
730
+ );
697
731
  }
698
732
  }
699
733
 
@@ -37,6 +37,7 @@
37
37
  */
38
38
 
39
39
  import { parseArgs } from 'node:util';
40
+ import path from 'node:path';
40
41
  import { attributionForRecord, emitEvent } from './lib/events.mjs';
41
42
  import { MANIFEST_SESSION_KEYS } from './lib/session-identity/own-session.mjs';
42
43
  import { isMainModule } from './lib/is-main-module.mjs';
@@ -109,7 +110,7 @@ async function main(argv) {
109
110
  return;
110
111
  }
111
112
 
112
- const repoRoot = parsed.values['repo-root'] ?? process.cwd();
113
+ const repoRoot = path.resolve(parsed.values['repo-root'] ?? process.cwd());
113
114
  const binding = resolveBinding(repoRoot);
114
115
 
115
116
  if (Object.keys(binding).length === 0) {
@@ -133,14 +133,14 @@ Learnings live exclusively in `.orchestrator/metrics/learnings.jsonl`. The pre-`
133
133
 
134
134
  The learning lifecycle states are:
135
135
 
136
- - **Created**: `confidence: 0.5`, `expires_at`: current date + `learning-expiry-days` (default: 30)
137
- - **Confirmed** (same type+subject seen again): `confidence += 0.15` (cap 1.0), `expires_at` reset
136
+ - **Created**: `confidence: 0.5`, `expires_at` = `created_at` + a per-TYPE TTL — `deriveExpiresAt(created_at, type)` with `LEARNING_TTL_DAYS[type] ?? LEARNING_TTL_DAYS.default` (`scripts/lib/learnings/schema.mjs`; 30–90 days per type, 60 for an unknown type). A caller-supplied `expires_at` is kept. `learning-expiry-days` does NOT set it: `scripts/lib/config.mjs` still parses that key (default 30), but no script or hook reads the parsed value — it survives only in skill prose (the `/evolve` Review-mode *Extend* action).
137
+ - **Confirmed** (same type+subject seen again): `confidence += 0.15` (cap 1.0), `expires_at` reset to `deriveExpiresAt(now, type)`
138
138
  - **Contradicted** (evidence against): `confidence -= 0.2` — do NOT reset `expires_at` (let the learning decay naturally if contradicted)
139
139
  - **Decayed** (untouched this session): `confidence -= learning-decay-rate` (from Session Config, default `0.05`). Applied at session-end after touched-set update, before prune. Clamped to 0.0. Does NOT reset `expires_at`.
140
140
  - **Expired**: `expires_at < current date` — removed on next write
141
141
  - **Dead**: `confidence <= 0.0` — removed on next write
142
142
 
143
- **Expiration check semantics:** Compare `expires_at` by date portion only (ignore time-of-day) to avoid intra-day jitter. When writing `expires_at`, set it to `<current_date>T00:00:00Z + learning-expiry-days` (midnight UTC).
143
+ **Expiration check semantics:** The code compares full timestamps, not dates: `pruneLearnings()` (`scripts/lib/learnings/expiry-sweep.mjs`) archives when `expires_at < now`; the time-driven sweep archives only after a 14-day grace window past `expires_at`. When writing `expires_at`, derive it with `deriveExpiresAt()` (full ISO timestamp, no midnight rounding) — never from `learning-expiry-days`.
144
144
 
145
145
  **Confidence bounds enforcement:** After EVERY increment or decrement, clamp confidence to [0.0, 1.0]. A learning at 0.95 confirmed becomes 1.0 (not 1.10). A learning at 0.1 contradicted becomes 0.0 and is pruned.
146
146
 
@@ -0,0 +1,131 @@
1
+ # Fleet Protocol v1 — Dateien statt Nachrichten (#1462, Epic #1461)
2
+
3
+ Shared reference for every session-orchestrator session (Claude Code, Codex, headless) that
4
+ runs beside a fleet coordinator ("navigator"). It is a reference, **not a rule**: nothing under
5
+ `.claude/rules/**` loads it, session-start Phase 7.6 and the operations-contract peer preflight
6
+ point here. The mechanics live in code — `scripts/lib/fleet-protocol.mjs` is the only place that
7
+ knows paths, fields, deadlines and lease validity; `scripts/fleet-checkin.mjs` writes the check-in.
8
+ This file describes them and never redefines them. Source: PRD
9
+ `docs/prd/2026-09-27-navigator-peer-protokoll.md` §§ 3.1–3.3, 3.7, Anhang A.2 (MR !53).
10
+
11
+ **Grundsatz (ADR-002, CSM-003).** Zustand liegt in Dateien; Nachrichten sind nur Hinweise auf eine
12
+ Datei. Der Navigator erteilt keine Freigaben — wörtlich: **„Freigaben erteile ich keine, maßgeblich
13
+ ist dein Owner-Auftrag"**. Eine Datei, die fehlt, heißt „nicht nachweisbar", nie „nicht vorhanden"
14
+ (ADR-004): eine fehlende Lease ist kein freies Feld, sondern ein Zustand ohne Beleg.
15
+
16
+ ## Verzeichnis und Dateiform
17
+
18
+ - Wurzel `~/.config/navigator/`, Override `NAVIGATOR_CONFIG_DIR` (getrimmt; leer oder nur
19
+ Whitespace zählt als nicht gesetzt) — dieselbe Variable wie die navigator-CLI, keine zweite.
20
+ Code: `navigatorDir()`. Ein Override zeigt nur auf ein eigenes Verzeichnis mit Modus 0700, nie
21
+ auf einen geteilten Ort: wer dort schreiben kann, kann eine „aktive" Lease vortäuschen.
22
+ - Verzeichnisse Modus `0700`, Dateien Modus `0600`. Schreiben immer atomar (tmp-Datei im
23
+ Zielverzeichnis, dann `rename`).
24
+ - Jede Datei trägt `zeit` aus `date -u +%FT%TZ` (Sekunden, `YYYY-MM-DDTHH:MM:SSZ`); nie geschätzt,
25
+ nie aus einer anderen Uhr. Code: `utcSecondsTimestamp()`.
26
+ - Dateinamen aus einer `session_id` sind pfadsicher: nur `[A-Za-z0-9._-]`, nicht `.` oder `..`,
27
+ kein `/`. Code: `isSafeSessionId()`; `checkinPath()` und `auflagenPath()` werfen sonst.
28
+ - Tests berühren das echte Verzeichnis nie: `tests/setup/navigator-dir-guard.mjs` setzt
29
+ `NAVIGATOR_CONFIG_DIR` je vitest-Worker auf ein tmp-Verzeichnis.
30
+
31
+ ## `leases/navigator.json` — genau ein aktiver Navigator (PRD 3.1)
32
+
33
+ | Feld | Inhalt |
34
+ |---|---|
35
+ | `session_id` | Registry-ID des Navigators (Pflicht; pfadsicher wie oben, höchstens 128 Zeichen) |
36
+ | `plattform` | `claude` \| `codex` \| `kopflos` (Pflicht) |
37
+ | `adresse` | `ListAgents`-Name, wenn Claude (`[A-Za-z0-9._:@-]`, 1–128 Zeichen); sonst `null` |
38
+ | `seit` | Zeit des Erwerbs, UTC mit `Z`, Sekunden oder Millisekunden (Pflicht) |
39
+ | `laeuft_ab` | UTC mit `Z`; Erneuerung je Ticker-Runde, Ablauf 30 min nach der letzten (Pflicht) |
40
+ | `uebergabe_an` | `null` oder Session-ID des Nachfolgers |
41
+
42
+ **„Aktiv" heißt ausschließlich: gültige Lease.** `readNavigatorLease()` liefert genau eines von
43
+ `active` (Datei lesbar, Pflichtfelder da, `laeuft_ab` in der Zukunft), `none` (Datei fehlt oder
44
+ `laeuft_ab` überschritten) oder `unreadable` (kaputtes JSON, fehlende Pflichtfelder, Lesefehler, oder ein Feld außerhalb der
45
+ Tabellenform: unbekannte `plattform`, Steuerzeichen in `session_id`/`adresse`, eine Zeit ohne `Z`
46
+ oder mit Offset — sie würde in lokaler Zeit gelesen und könnte die Lease verlängern).
47
+ Unlesbar oder abgelaufen ist **nie** aktiv (fail-closed). Registry-Heartbeat (`role: navigator`,
48
+ `scripts/lib/session-registry.mjs`) und `ListAgents` sind Zusatzsignale, keine Lebendbeweise.
49
+ Erwerb und Übergabe der Lease sind S4 (agents/navigator#36), nicht Teil dieses Repos.
50
+
51
+ ## `checkin/<session_id>.json` — Session an Navigator (PRD 3.2)
52
+
53
+ **Schreibend** heißt: Änderung an Repo-Inhalt oder VCS-Zustand (Datei im Arbeitsbaum außerhalb
54
+ `.orchestrator/` und `.claude/`, Commit, Branch, Push, MR, Issue, Kommentar). SO-eigener
55
+ Sitzungszustand zählt nicht: Phase 1.1 (CLAUDE.md-Migration, einmalig), 1.2 `session.lock`, 1.5
56
+ `STATE.md`, 1.6 Metriken, 1.7 Live-Status-Board. Phase 1.1 ist eine Repo-Datei und wird deshalb
57
+ als Ausnahme im Check-in genannt (`vorab_geschrieben`). (`CLAUDE.md` heißt auf Codex CLI `AGENTS.md`, siehe
58
+ `skills/_shared/instruction-file-resolution.md`.)
59
+
60
+ Der Check-in liegt **vor der ersten schreibenden Aktion** (Phase 7.6, oder der Peer-Preflight der
61
+ Operations-Route). Schreiber: `node scripts/fleet-checkin.mjs` liest das JSON von stdin, ergänzt
62
+ `zeit`, validiert (`validateCheckin()`), schreibt atomar mit Modus 0600 und emittiert
63
+ `orchestrator.fleet.checkin` (Payload `session`, `repo`, `modus`, `kandidaten`, `navigator_state`).
64
+ Exit 0 geschrieben, 2 ungültige Eingabe (Fehlerliste auf stderr, keine Datei), 1 Schreibfehler.
65
+
66
+ | Feld | Inhalt |
67
+ |---|---|
68
+ | `session`, `plattform` | Registry-ID (aus `.orchestrator/current-session.json`); `claude` / `codex` / `kopflos` |
69
+ | `repo`, `repo_id`, `worktree` | Name; `repo_id` aus `navigator identity` oder `null`; Worktree `true`/`false` |
70
+ | `modus` | `housekeeping` / `feature` / `deep` / `operations` |
71
+ | `auftrag_ref` | Pfad der Auftragsdatei oder „Owner-Chat <zeit>" mit Wortlaut in einem Satz |
72
+ | `konto_slot`, `quota` | `account_slot` als Nummer (`navigator identity`) oder `null`; Quota aus `navigator quota` oder `nicht messbar` |
73
+ | `stand` | Objekt: main-, origin/main-, Prod-SHA (sonst `nicht messbar`), offene MRs |
74
+ | `kandidaten`, `schreibbereich` | Issue-Nummern; Verzeichnisse/Dateien |
75
+ | `bedarf` | Objekt: geplante volle Pipelines, m5-remote-Jobs, prozessstartende Agents |
76
+ | `vorab_geschrieben`, `rueckfall` | Ausnahmen nach der Definition oben; Verhalten ohne Auflagen (unten) |
77
+ | `zeit` | von der CLI gesetzt |
78
+
79
+ Eine `SendMessage` an den Navigator ist optional und nur ein Hinweis auf die Datei: höchstens eine,
80
+ nur wenn die Lease aktiv ist und eine Peer-Adresse `navigator-*` erreichbar ist; nie eine Antwort
81
+ erwarten, nie darauf warten (CSM-004).
82
+
83
+ ## `auflagen/<session_id>.json` — Navigator an Session (PRD 3.3)
84
+
85
+ Felder: Caps (prozessstartende / lesende Agents nach freiem Speicher des lokalen Hosts), volle
86
+ Pipelines je Repo, m5-remote-Regel (`m5-ersatz`-Exit, was lokal erlaubt ist), Merge-Protokoll, Zeitregel,
87
+ Flottenpriorität, Besitzkonflikte, Pflichtsatz „Freigaben erteile ich keine, maßgeblich ist dein
88
+ Owner-Auftrag". Die Session **liest** die Datei; sie wartet auf keine Nachricht.
89
+
90
+ **Standard-Auflagen (konservative Stufe).** Sie gelten, wenn `CHECKIN_FALLBACK_MIN` = 10 Minuten
91
+ nach `checkin.zeit` keine Auflagen-Datei liegt — und sofort, wenn kein Navigator aktiv ist
92
+ (PRD Anhang A.2, v2-Wortlaut):
93
+
94
+ - Caps: 2 prozessstartende + 2 lesende Agents, solange der lokale Host ≥ 50 % Speicher frei hat
95
+ (`memory_pressure | tail -1`).
96
+ - Pipelines: ≤ 2 volle je Repo; Nachzug-Pushes vorher im Check-in (`bedarf`) benennen.
97
+ - Offload: Heavy-Rollen (test, build, lint, audit) nur auf `m5-remote`, und nur wenn
98
+ `navigator m5-ersatz --quiet` unmittelbar davor mit Exit 0 endet. Exit-Vertrag: 0 nutzbar,
99
+ 3 Ersatzregel, 5 überlastet, 6 nicht messbar; jeder Exit außer 0 (auch ein fehlender Befehl)
100
+ heißt: kein neues Offload-Gate. Schwelle und Hysterese leben allein in diesem Befehl — hier und
101
+ in den Skills steht bewusst keine Lastzahl. Lokal nur `vitest` bzw. `eslint` je Datei mit `timeout`.
102
+ - Zeiten nur aus `date`.
103
+ - Kein Merge ohne Befugnis nach PRD 3.5: `navigator authority query <repo> merge --exit-code` mit
104
+ Exit 0 **oder** ein ausdrücklicher Owner-Auftrag, der Merge für genau dieses Repo nennt
105
+ (`auftrag_ref`). Ohne navigator-CLI ist jeder Merge `einzeln`.
106
+
107
+ Lesende Arbeit und Schreiben im eigenen Worktree laufen währenddessen weiter; der Rückfall ist ein
108
+ Dateistand mit Frist, kein Warten auf eine Antwort.
109
+
110
+ ## Verhalten ohne Navigator (PRD 3.7)
111
+
112
+ Lease `none` oder `unreadable`: die Check-in-Datei wird **trotzdem** geschrieben (sie ist der
113
+ zählbare Beleg), die Standard-Auflagen gelten sofort, es geht keine Nachricht ab. Kopflose Läufe
114
+ sind per Nachricht nicht erreichbar und nutzen dieselben Dateien; ihr Brief verlangt, vor jeder
115
+ Welle und vor jedem MR `auflagen/` und `merge/` zu lesen.
116
+
117
+ ## Vorschau: `merge/<repo_id>/*` (S2, #1463 — hier keine Mechanik)
118
+
119
+ Ansage `ansage-<mr>.json` (MR, gepinnte Head-SHA, Pipeline-ID, Jobliste, Gate-Log-SHA, Review-Stand,
120
+ Migration, `laeuft_ab` +20 min), Lease `lease-<mr>.json` (Navigator, +15 min), Meldung
121
+ `done-<mr>.json` (Merge-SHA, main-Pipeline-ID, Prod-SHA). Verfall bei Ablauf, MR nicht mehr
122
+ `opened` oder geändertem Head. Nichts davon ist in diesem Repo implementiert; bis S2 gilt PRD 3.4
123
+ Punkt 3: selbst messen und nach 3.5 mergen, oder `navigator ask --aktion merge`.
124
+
125
+ ## See Also
126
+
127
+ `skills/session-start/SKILL.md` Phase 7.6 · `skills/session-start/references/operations-contract.md`
128
+ (Peer-Preflight) · `skills/_shared/state-ownership.md` § Session Identity and Lock Ownership (`role`) ·
129
+ `docs/events-schema.md` (`orchestrator.fleet.checkin`) · `.claude/rules/cross-session-messaging.md`
130
+ (CSM-003/004) · `scripts/lib/fleet-protocol.mjs` · `scripts/fleet-checkin.mjs` ·
131
+ `skills/navigator/SKILL.md` (`/session-orchestrator:navigator`)
@@ -8,15 +8,17 @@ The current platform is determined by the `scripts/lib/platform.mjs` library:
8
8
  - `$SO_PLATFORM` = `claude` | `codex` | `cursor` | `pi`
9
9
  - Environment: `$CLAUDE_PLUGIN_ROOT` (Claude Code), `$CODEX_PLUGIN_ROOT` (Codex CLI), `$CURSOR_RULES_DIR` (Cursor IDE), or `$PI_PLUGIN_ROOT` (Pi)
10
10
 
11
- ## Identical Tools (no mapping needed)
12
-
13
- These tools have the same name and behavior on all platforms. Cursor IDE uses equivalent built-in tools for file operations and terminal commands.
14
- - **Read** — read file contents
15
- - **Write** — create/overwrite files
16
- - **Edit** — string replacement in files
17
- - **Bash** — execute shell commands
18
- - **Glob** — file pattern matching
19
- - **Grep** — content search (ripgrep)
11
+ ## File and Shell Tool Adaptation
12
+
13
+ Skill bodies use Claude Code names as operations, not as a requirement that every
14
+ harness expose those exact tools. Use the current runtime's available tools.
15
+ Measured in Codex Desktop 0.153.4 on 2026-09-19: `exec_command` runs shell
16
+ commands (`cat`, `rg`, `rg --files` for Read/Grep/Glob); `apply_patch` performs
17
+ file edits. These may be exposed through a `functions.exec` tools namespace.
18
+ Never call an unavailable `Read`, `Bash`, or `Skill` tool by name. An instruction
19
+ to invoke `session-orchestrator:<name>` means read and follow the canonical
20
+ `skills/<name>/SKILL.md` relative to the plugin root when no Skill tool exists.
21
+ Keep the user's project as the working directory for project operations.
20
22
 
21
23
  ## Platform-Specific Tool Mapping
22
24
 
@@ -24,7 +26,7 @@ These tools have the same name and behavior on all platforms. Cursor IDE uses eq
24
26
 
25
27
  | Function | Claude Code | Codex CLI | Cursor IDE | Pi |
26
28
  |----------|------------|-----------|------------|----|
27
- | Present choices to user | `AskUserQuestion` tool with structured options | Numbered Markdown list as plain text, wait for user reply | Numbered Markdown list (same as Codex) | Numbered Markdown list v1; native UI adapter planned |
29
+ | Present choices to user | `AskUserQuestion` tool with structured options | Available native user-input tool, respecting its mode restrictions; plain-text fallback when unavailable | Available native choice tool or numbered Markdown list | Numbered Markdown list v1; native UI adapter planned |
28
30
  | Dispatch subagent | `Agent({ description, prompt, subagent_type })` | Native multi-agent collaboration namespace: `spawn_agent`, `list_agents`, `wait_agent`, `send_message`, `followup_task`, `interrupt_agent`, `close_agent`. Measured 2026-08-25 on `codex-cli 0.141.0` — `codex features list` → `multi_agent stable true`. | No native in-session Agent tool. Coordinator-side foreign dispatch via the headless `cursor-agent` CLI exists (`scripts/lib/wave-executor/foreign-dispatch.mjs`, #1150) — measured 2026-08-25 on `cursor-agent 2026.08.11-e8db854`. | Sequential execution v1. Do not assume native subagents until the Pi SDK dispatcher exists. |
29
31
  | Track tasks | `TaskCreate` / `TaskUpdate` / `TaskList` | Plain-text checklist in response context | Plain-text checklist (same as Codex) | Plain-text checklist (same as Codex) |
30
32
  | Enter plan mode | `EnterPlanMode` / `ExitPlanMode` tools | `/plan` slash command (prompt-level, not tool-based) | Instruction-based: "Focus on analysis and planning. Do not modify files until the user approves." | `/plan` prompt template; use instruction-based planning when tool mode is unavailable |
@@ -37,7 +39,13 @@ When a skill instructs "Use the AskUserQuestion tool", apply this pattern:
37
39
 
38
40
  **On Claude Code:** Use the AskUserQuestion tool with structured options as documented.
39
41
 
40
- **On Codex CLI / Cursor IDE / Pi:** Present the same choices as a numbered Markdown list and ask the user to respond:
42
+ **On Codex:** Prefer the available native user-input tool. In the measured Desktop
43
+ 0.153.4 runtime (2026-09-19), `request_user_input_async` allows a question while
44
+ independent work continues; `request_user_input` has mode restrictions. Follow
45
+ the live tool contract. Existing user authorization remains valid; do not ask
46
+ again merely because a workflow names `AskUserQuestion`.
47
+
48
+ **When no suitable native tool is available (including Cursor IDE / Pi):** Present the same choices as a numbered Markdown list and ask the user to respond:
41
49
  ```
42
50
  Choose one:
43
51
  1. Option A — description
@@ -85,6 +93,10 @@ No Session Orchestrator Pi subagent dispatcher exists in v1. Execute wave tasks
85
93
 
86
94
  Skills use `model-preference` (Claude), `model-preference-codex` (Codex), `model-preference-cursor` (Cursor), and active-model fallback on Pi in YAML frontmatter.
87
95
 
96
+ These are preferences, not authority to replace a user's selected model,
97
+ reasoning effort, or service tier. Preserve the current settings unless the user
98
+ requests a change; inherit them for native subagents.
99
+
88
100
  ## State Directory
89
101
 
90
102
  - **Claude Code:** `.claude/` (STATE.md, wave-scope.json)
@@ -104,6 +104,11 @@ layer.
104
104
  contract requires a trusted native resume identifier and remains a follow-up.
105
105
  In particular, a host rotation that changes both raw and semantic values has
106
106
  no guaranteed continuity.
107
+ - **Registry `role` (`'navigator'`) is display, never ownership.** The
108
+ authoritative claim is the navigator lease (`leases/navigator.json` under
109
+ `~/.config/navigator/`, see `skills/_shared/fleet-protocol.md`); `registerSelf()`
110
+ does not carry the field across a repeated SessionStart, so the `/navigator`
111
+ skill re-sets it each ticker round via `heartbeat(id, { role })` (#1462).
107
112
 
108
113
  The peer-discovery and issue-budget procedures below apply these rules at their
109
114
  narrow surfaces; neither creates a second ownership model.
@@ -39,11 +39,19 @@ the invocation surface only:
39
39
  Headless requirements:
40
40
 
41
41
  - Anthropic API key configured for `claude -p` (Claude Code CLI auth).
42
- - `scripts/autopilot.mjs` reads `sessions.jsonl` tail after each child exit to construct
43
- the `sessionRunner` return shape — the spawned session must complete cleanly and append
44
- its record (session-end Phase 3.7 handles this).
45
- - `AUTOPILOT_RUN_ID` env var is propagated to the child so session-end stamps it onto the
46
- per-iteration `sessions.jsonl` record.
42
+ - `scripts/autopilot.mjs` starts each child with `--session-id <fresh uuid>` and, after it
43
+ exits, reads the one canonical `sessions.jsonl` record whose `raw_session_id` is that uuid
44
+ to construct the `sessionRunner` return shape — the spawned session must complete cleanly
45
+ and append its record (session-end Phase 3.7 handles this). No such record, or more than
46
+ one, stops the loop with `failed-wave` instead of reading the ledger tail (#1457). So does
47
+ a unique record that is only a backfill stub (no waves/agents/token totals — the child never
48
+ closed): its token usage is unknown, not 0, so it is never counted as a healthy 0-token
49
+ iteration (#1457 F2).
50
+ - `AUTOPILOT_RUN_ID` env var is set in the child's env, but **nothing reads it yet**
51
+ (measured 2026-10-01: `rg -n "AUTOPILOT_RUN_ID" scripts hooks skills` finds only the writer
52
+ in `scripts/autopilot.mjs` and this line). CLI-driven iterations therefore carry no
53
+ `autopilot_run_id` on their `sessions.jsonl` record yet; join them to `autopilot.jsonl` via
54
+ the `sessions` list there, not via that field.
47
55
 
48
56
  Do NOT re-implement loop logic inline — this skill and `scripts/lib/autopilot.mjs` are
49
57
  authoritative. Kill-switches are enforced by `scripts/lib/autopilot.mjs`, not inline by
@@ -111,7 +119,7 @@ intent for THIS run, not a standing policy.
111
119
  ## Command Surface
112
120
 
113
121
  ```
114
- /autopilot [--max-sessions=N] [--max-hours=H] [--confidence-threshold=0.X] [--dry-run]
122
+ /autopilot [--max-sessions=N] [--max-hours=H] [--confidence-threshold=0.X] [--max-tokens=N] [--dry-run]
115
123
  ```
116
124
 
117
125
  | Flag | Default | Bounds | Meaning |
@@ -119,6 +127,7 @@ intent for THIS run, not a standing policy.
119
127
  | `--max-sessions` | `5` | 1..50 | Iteration cap (graceful exit when reached) |
120
128
  | `--max-hours` | `4.0` | 0.5..24.0 | Wall-clock budget for entire loop |
121
129
  | `--confidence-threshold` | `0.85` | 0.0..1.0 | Minimum `selectMode` confidence for auto-execute |
130
+ | `--max-tokens` | `0` (off) | 0..10000000 | Token budget for `token-budget-exceeded`. Unit: cumulative **subagent OUTPUT** tokens, summed from each `sessions.jsonl` record's `total_token_output` (falling back to `total_tokens`, which is subagent-only as well) — coordinator tokens are not counted. Off by default until calibrated: one measured deep session's subagents produced 450 499 output tokens, so a six-figure budget stops the loop after about one deep session |
122
131
  | `--dry-run` | `false` | — | Print planned iterations without executing |
123
132
 
124
133
  Out-of-range values silently clamp to bounds. `--dry-run` exits after printing — never
@@ -136,7 +145,7 @@ WHILE state.iterations_completed < max-sessions:
136
145
  kill_switch := 'max-sessions-reached'; break
137
146
  IF (now() - state.started_at) > max-hours:
138
147
  kill_switch := 'max-hours-exceeded'; break
139
- IF cumulative_tokens_used >= max-tokens:
148
+ IF max-tokens > 0 AND cumulative_tokens_used >= max-tokens:
140
149
  kill_switch := 'token-budget-exceeded'; break
141
150
  IF resource_verdict() == 'critical' AND peer_count() > autopilot-peer-abort:
142
151
  kill_switch := 'resource-overload'; break
@@ -222,7 +231,7 @@ session — drives `runLoop` between manual `/session` invocations. The headless
222
231
  | Field | Signature | Source |
223
232
  |---|---|---|
224
233
  | `modeSelector` | `() => Promise<{mode, confidence, rationale?}>` | wraps `selectMode(await buildLiveSignals())` |
225
- | `sessionRunner` | `({mode, autopilotRunId}) => Promise<{session_id, agent_summary?, effectiveness?}>` | wraps a `/session <mode>` invocation; reads `sessions.jsonl` tail to construct return value |
234
+ | `sessionRunner` | `({mode, autopilotRunId}) => Promise<{session_id, agent_summary?, effectiveness?}>` | wraps a `/session <mode>` invocation; reads the child's own record (matched on `raw_session_id`) to construct return value |
226
235
  | `resourceEvaluator` | `() => {verdict}` | calls `evaluate(cachedProbeSnapshot, thresholds)` from `resource-probe.mjs` over a snapshot `peerCounter` refreshed on the prior iteration — never calls `probe()` itself, which is what keeps it synchronous |
227
236
  | `peerCounter` | `() => Promise<number>` | returns `peers.length` from `detectPeers({ sessionId, freshnessMin: 15 })` (a SESSION count, not a process count — see `host-resources.md` HR-103) while refreshing the cached `probe()` snapshot `resourceEvaluator` reads |
228
237
 
@@ -235,6 +244,7 @@ import { runLoop, parseFlags } from '$PLUGIN_ROOT/scripts/lib/autopilot.mjs';
235
244
  import { buildLiveSignals } from '$PLUGIN_ROOT/scripts/lib/build-live-signals.mjs';
236
245
  import { selectMode } from '$PLUGIN_ROOT/scripts/lib/mode-selector.mjs';
237
246
  import { probe, evaluate } from '$PLUGIN_ROOT/scripts/lib/resource-probe.mjs';
247
+ import { detectPeers } from '$PLUGIN_ROOT/scripts/lib/session-registry.mjs';
238
248
 
239
249
  const flags = parseFlags(process.argv.slice(2));
240
250
 
@@ -250,20 +260,37 @@ const modeSelector = async () => {
250
260
  return selectMode(signals);
251
261
  };
252
262
 
263
+ let cachedProbeSnapshot = null; // written by peerCounter, read by resourceEvaluator
264
+
253
265
  const resourceEvaluator = () => {
254
- const snapshot = probeSync(); // or cached snapshot if probe is async
255
- return evaluate(snapshot, thresholds);
266
+ // Synchronous by contract: never calls probe() itself (it is async) — reads
267
+ // the snapshot peerCounter refreshed on the prior iteration.
268
+ if (cachedProbeSnapshot === null) {
269
+ return { verdict: 'warn', reasons: ['probe not yet available'], recommended_agents_per_wave_cap: null };
270
+ }
271
+ return evaluate(cachedProbeSnapshot, thresholds);
256
272
  };
257
273
 
258
- const peerCounter = () => {
259
- // Synchronous-friendly count from a recent probe snapshot.
260
- return latestSnapshot.claude_processes_count ?? 0;
274
+ const peerCounter = async () => {
275
+ // A SESSION count, not a process count (host-resources.md HR-103) —
276
+ // claude_processes_count runs ~6 processes per session. `ownSessionId` is
277
+ // this coordinator's registry id, so detectPeers() excludes it.
278
+ const [peers, snapshot] = await Promise.all([
279
+ detectPeers({ sessionId: ownSessionId, freshnessMin: 15 }),
280
+ probe(),
281
+ ]);
282
+ cachedProbeSnapshot = snapshot;
283
+ return peers.length;
261
284
  };
262
285
 
263
286
  const sessionRunner = async ({ mode, autopilotRunId }) => {
264
287
  // The coordinator (Claude) invokes /session <mode> manually here. After the
265
288
  // session completes (/close runs, sessions.jsonl appended), this function
266
289
  // reads the tail entry and projects it into the runLoop return-shape.
290
+ // CAUTION: a tail read has the peer-append error class — a parallel session
291
+ // that appends after this one supplies ITS record (and token usage). A real
292
+ // run should read its own record by raw session id, as scripts/autopilot.mjs
293
+ // does (readOwnSession → raw_session_id match, #1457).
267
294
  const tail = readSessionsJsonlTail(1); // last line, normalized
268
295
  return {
269
296
  session_id: tail.session_id,
@@ -289,8 +316,9 @@ The in-process driver has Claude (the coordinator) call `/session <mode>` betwee
289
316
  - **Pro:** zero new infra. Reuses canonical kill-switch logic. Validates `buildLiveSignals`
290
317
  against real Phase 7.5 swap before headless complexity. Each iteration carries
291
318
  inter-session memory through STATE.md / sessions.jsonl / learnings.
292
- - **Con:** not truly autonomous — Claude must stay in the chat. Doesn't deliver
293
- walk-away UX. That's Phase C-5's job.
319
+ - **Con:** not truly autonomous — Claude must stay in the chat. The in-process
320
+ driver does not deliver walk-away UX; that is the shipped headless driver
321
+ (`--headless`, `scripts/autopilot.mjs`, Phase C-5; see § Headless Driver Wiring).
294
322
 
295
323
  ### Headless Driver Wiring (Option A — `scripts/autopilot.mjs`)
296
324
 
@@ -299,9 +327,10 @@ four required `runLoop` dependencies (`modeSelector`, `sessionRunner`,
299
327
  `resourceEvaluator`, `peerCounter`) plus the optional `abortSignal` to production
300
328
  sources — distinct from, and more concrete than, the in-process skeleton above:
301
329
 
302
- - `sessionRunner` — spawns `claude -p '/session <mode>'` as a child process; after it
303
- exits cleanly, reads the `sessions.jsonl` tail to construct the return shape
304
- `{session_id, agent_summary?, effectiveness?}` (`scripts/autopilot.mjs` `sessionRunner`).
330
+ - `sessionRunner` — spawns `claude -p '/session <mode>' --session-id <uuid>` as a child
331
+ process; after it exits cleanly, reads the one canonical `sessions.jsonl` record whose
332
+ `raw_session_id` is that uuid to construct the return shape
333
+ `{session_id, agent_summary?, effectiveness?, usage?}` (`scripts/autopilot.mjs` `sessionRunner`).
305
334
  - `resourceEvaluator` — calls `evaluate(cachedProbeSnapshot, thresholds)` from
306
335
  `scripts/lib/resource-probe.mjs`, reading a snapshot refreshed by `peerCounter` on the
307
336
  prior iteration so the function itself stays synchronous, per the `runLoop` contract
@@ -94,7 +94,7 @@ Store `INVOCATION_MODE = transitive | direct`.
94
94
 
95
95
  - `private`: the existing host-local config resolution found a baseline directory and its reduced contract validated. Use `private-contract.md` for selection, templates, commands, CI and rules.
96
96
  - `public`: the resolved baseline is absent, empty, or points to a missing directory. Use plugin-bundled templates.
97
- - Existing but invalid configured baseline: abort before dispatch; report the reader's sanitized error reason.
97
+ - Existing but invalid configured baseline: abort before dispatch; report the reader's sanitized error reason; for `producer-missing` also surface the `message` and the migrate-or-unconfigure choice (see `public-fallback.md` § Step 1).
98
98
 
99
99
  Pass `PATH_TYPE` into Phase 1 and all subsequent phases. All tier templates (`fast-template.md`, `standard-template.md`, `deep-template.md`) must consult `public-fallback.md` for CLAUDE.md generation and archetype file sourcing when `PATH_TYPE = public`.
100
100
 
@@ -17,7 +17,7 @@ Vendor the canonical always-on rules from the plugin's `rules/` library into `$R
17
17
 
18
18
  Idempotency is handled by the writer itself:
19
19
  - Missing → create
20
- - Exists, plugin-owned (first line is the `<!-- source: session-orchestrator plugin ... -->` header) and byte-identical → skip silently
20
+ - Exists, plugin-owned (the `<!-- source: session-orchestrator plugin ... -->` header is on line 1, or is the first line after a line-1 frontmatter's closing `---` — `isPluginOwnedContent()`, #1449) and byte-identical → skip silently
21
21
  - Exists, plugin-owned and stale → overwrite (the plugin copy is canonical)
22
22
  - Exists WITHOUT that header → preserved untouched (a repo-private rule the operator authored)
23
23