session-orchestrator 5.1.0 → 5.3.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 (484) hide show
  1. package/.agents/skills/architecture/SKILL.md +3 -1
  2. package/.agents/skills/autopilot/SKILL.md +6 -1
  3. package/.agents/skills/autopilot/agents/openai.yaml +5 -0
  4. package/.agents/skills/bootstrap/SKILL.md +7 -1
  5. package/.agents/skills/bootstrap/agents/openai.yaml +5 -0
  6. package/.agents/skills/brainstorm/SKILL.md +8 -1
  7. package/.agents/skills/brainstorm/agents/openai.yaml +5 -0
  8. package/.agents/skills/claude-md-drift-check/SKILL.md +3 -1
  9. package/.agents/skills/close/SKILL.md +21 -0
  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 +7 -1
  13. package/.agents/skills/debug/agents/openai.yaml +5 -0
  14. package/.agents/skills/discovery/SKILL.md +7 -2
  15. package/.agents/skills/discovery/agents/openai.yaml +5 -0
  16. package/.agents/skills/dispatcher/SKILL.md +7 -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 +7 -1
  21. package/.agents/skills/eli5/agents/openai.yaml +5 -0
  22. package/.agents/skills/eval/SKILL.md +7 -2
  23. package/.agents/skills/eval/agents/openai.yaml +5 -0
  24. package/.agents/skills/evolve/SKILL.md +8 -3
  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 +22 -0
  30. package/.agents/skills/go/agents/openai.yaml +5 -0
  31. package/.agents/skills/grill/SKILL.md +7 -1
  32. package/.agents/skills/grill/agents/openai.yaml +5 -0
  33. package/.agents/skills/harness-audit/SKILL.md +20 -0
  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 +6 -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/npm-publish/SKILL.md +4 -2
  41. package/.agents/skills/peekaboo-driver/SKILL.md +3 -1
  42. package/.agents/skills/persona-panel/SKILL.md +6 -1
  43. package/.agents/skills/persona-panel/agents/openai.yaml +5 -0
  44. package/.agents/skills/plan/SKILL.md +8 -2
  45. package/.agents/skills/plan/agents/openai.yaml +5 -0
  46. package/.agents/skills/playwright-driver/SKILL.md +3 -1
  47. package/.agents/skills/portfolio/SKILL.md +21 -0
  48. package/.agents/skills/portfolio/agents/openai.yaml +5 -0
  49. package/.agents/skills/quality-gates/SKILL.md +3 -1
  50. package/.agents/skills/reconcile/SKILL.md +6 -1
  51. package/.agents/skills/reconcile/agents/openai.yaml +5 -0
  52. package/.agents/skills/release/SKILL.md +22 -0
  53. package/.agents/skills/release/agents/openai.yaml +5 -0
  54. package/.agents/skills/remote-offload/SKILL.md +3 -1
  55. package/.agents/skills/repo-audit/SKILL.md +6 -1
  56. package/.agents/skills/repo-audit/agents/openai.yaml +5 -0
  57. package/.agents/skills/session/SKILL.md +21 -0
  58. package/.agents/skills/session/agents/openai.yaml +5 -0
  59. package/.agents/skills/session-end/SKILL.md +3 -1
  60. package/.agents/skills/session-plan/SKILL.md +3 -1
  61. package/.agents/skills/session-start/SKILL.md +3 -1
  62. package/.agents/skills/spinout/SKILL.md +6 -1
  63. package/.agents/skills/spinout/agents/openai.yaml +5 -0
  64. package/.agents/skills/sunset-review/SKILL.md +7 -1
  65. package/.agents/skills/sunset-review/agents/openai.yaml +5 -0
  66. package/.agents/skills/templates-ack/SKILL.md +21 -0
  67. package/.agents/skills/templates-ack/agents/openai.yaml +5 -0
  68. package/.agents/skills/test/SKILL.md +21 -0
  69. package/.agents/skills/test/agents/openai.yaml +5 -0
  70. package/.agents/skills/test-runner/SKILL.md +3 -1
  71. package/.agents/skills/tmux-layout/SKILL.md +3 -1
  72. package/.agents/skills/using-orchestrator/SKILL.md +3 -1
  73. package/.agents/skills/ux-grill/SKILL.md +7 -1
  74. package/.agents/skills/ux-grill/agents/openai.yaml +5 -0
  75. package/.agents/skills/vault-mirror/SKILL.md +3 -1
  76. package/.agents/skills/vault-sync/SKILL.md +3 -1
  77. package/.agents/skills/wave-executor/SKILL.md +3 -1
  78. package/.agents/skills/write-executable-plan/SKILL.md +3 -1
  79. package/.claude-plugin/marketplace.json +1 -1
  80. package/.claude-plugin/plugin.json +1 -1
  81. package/.codex-plugin/plugin.json +4 -4
  82. package/.codex-plugin/skills/autopilot/SKILL.md +5 -4
  83. package/.codex-plugin/skills/bootstrap/SKILL.md +8 -4
  84. package/.codex-plugin/skills/brainstorm/SKILL.md +11 -4
  85. package/.codex-plugin/skills/close/SKILL.md +3 -3
  86. package/.codex-plugin/skills/convergence-monitoring/SKILL.md +1 -1
  87. package/.codex-plugin/skills/debug/SKILL.md +11 -4
  88. package/.codex-plugin/skills/discovery/SKILL.md +8 -4
  89. package/.codex-plugin/skills/dispatcher/SKILL.md +4 -4
  90. package/.codex-plugin/skills/eli5/SKILL.md +9 -4
  91. package/.codex-plugin/skills/eval/SKILL.md +9 -4
  92. package/.codex-plugin/skills/evolve/SKILL.md +9 -4
  93. package/.codex-plugin/skills/go/SKILL.md +3 -3
  94. package/.codex-plugin/skills/grill/SKILL.md +11 -4
  95. package/.codex-plugin/skills/harness-audit/SKILL.md +4 -3
  96. package/.codex-plugin/skills/memory-cleanup/SKILL.md +9 -4
  97. package/.codex-plugin/skills/npm-publish/SKILL.md +1 -1
  98. package/.codex-plugin/skills/persona-panel/SKILL.md +5 -5
  99. package/.codex-plugin/skills/plan/SKILL.md +8 -4
  100. package/.codex-plugin/skills/portfolio/SKILL.md +3 -3
  101. package/.codex-plugin/skills/reconcile/SKILL.md +9 -4
  102. package/.codex-plugin/skills/release/SKILL.md +3 -3
  103. package/.codex-plugin/skills/repo-audit/SKILL.md +6 -4
  104. package/.codex-plugin/skills/session/SKILL.md +1 -1
  105. package/.codex-plugin/skills/spinout/SKILL.md +4 -4
  106. package/.codex-plugin/skills/sunset-review/SKILL.md +5 -4
  107. package/.codex-plugin/skills/test/SKILL.md +3 -3
  108. package/.codex-plugin/skills/ux-grill/SKILL.md +11 -4
  109. package/.cursor/commands/autopilot.md +4 -4
  110. package/.cursor/commands/bootstrap.md +5 -4
  111. package/.cursor/commands/brainstorm.md +5 -4
  112. package/.cursor/commands/close.md +4 -3
  113. package/.cursor/commands/debug.md +4 -4
  114. package/.cursor/commands/discovery.md +4 -4
  115. package/.cursor/commands/dispatcher.md +4 -4
  116. package/.cursor/commands/eli5.md +4 -4
  117. package/.cursor/commands/eval.md +4 -4
  118. package/.cursor/commands/evolve.md +4 -4
  119. package/.cursor/commands/go.md +4 -3
  120. package/.cursor/commands/grill.md +4 -4
  121. package/.cursor/commands/harness-audit.md +3 -3
  122. package/.cursor/commands/memory-cleanup.md +4 -4
  123. package/.cursor/commands/persona-panel.md +4 -4
  124. package/.cursor/commands/plan.md +5 -4
  125. package/.cursor/commands/portfolio.md +3 -3
  126. package/.cursor/commands/reconcile.md +4 -4
  127. package/.cursor/commands/release.md +4 -3
  128. package/.cursor/commands/repo-audit.md +4 -4
  129. package/.cursor/commands/session.md +1 -1
  130. package/.cursor/commands/spinout.md +4 -4
  131. package/.cursor/commands/sunset-review.md +4 -4
  132. package/.cursor/commands/test.md +3 -3
  133. package/.cursor/commands/ux-grill.md +4 -4
  134. package/.cursor/rules/000-session-orchestrator.mdc +0 -2
  135. package/.cursor/rules/010-session-workflow.mdc +2 -2
  136. package/.cursor/rules/050-plan.mdc +1 -1
  137. package/.cursor/skills/bootstrap/SKILL.md +1 -0
  138. package/.cursor/skills/close/SKILL.md +13 -0
  139. package/.cursor/skills/convergence-monitoring/SKILL.md +1 -0
  140. package/.cursor/skills/debug/SKILL.md +0 -1
  141. package/.cursor/skills/discovery/SKILL.md +0 -1
  142. package/.cursor/skills/dispatcher/SKILL.md +0 -1
  143. package/.cursor/skills/eli5/SKILL.md +0 -1
  144. package/.cursor/skills/eval/SKILL.md +1 -1
  145. package/.cursor/skills/evolve/SKILL.md +0 -1
  146. package/.cursor/skills/go/SKILL.md +13 -0
  147. package/.cursor/skills/grill/SKILL.md +0 -1
  148. package/.cursor/skills/harness-audit/SKILL.md +12 -0
  149. package/.cursor/skills/npm-publish/SKILL.md +1 -0
  150. package/.cursor/skills/portfolio/SKILL.md +12 -0
  151. package/.cursor/skills/release/SKILL.md +13 -0
  152. package/.cursor/skills/repo-audit/SKILL.md +0 -1
  153. package/.cursor/skills/sunset-review/SKILL.md +0 -1
  154. package/.cursor/skills/test/SKILL.md +12 -0
  155. package/.cursor/skills/ux-grill/SKILL.md +0 -1
  156. package/.cursor-plugin/plugin.json +1 -1
  157. package/.orchestrator/policy/blocked-commands.json +13 -4
  158. package/AGENTS.md +3 -2
  159. package/CHANGELOG.md +197 -0
  160. package/README.md +11 -9
  161. package/SECURITY.md +12 -0
  162. package/agents/dialectic-deriver.md +13 -10
  163. package/agents/eval-judge.md +67 -45
  164. package/agents/skill-applied-judge.md +34 -19
  165. package/commands/session.md +17 -3
  166. package/docs/baseline.md +12 -6
  167. package/docs/ci-setup.md +53 -0
  168. package/docs/codex-setup.md +15 -3
  169. package/docs/components.md +13 -6
  170. package/docs/events-schema.md +59 -9
  171. package/docs/install.md +16 -0
  172. package/docs/persona-panel.md +1 -1
  173. package/docs/pi-setup.md +1 -1
  174. package/docs/rule-authoring.md +135 -14
  175. package/docs/scope-collision-guard.md +2 -0
  176. package/docs/session-config-reference.md +106 -11
  177. package/docs/session-config-template.md +31 -2
  178. package/docs/telemetry.md +2 -0
  179. package/hooks/_lib/hook-import-set.json +125 -8
  180. package/hooks/_lib/subagent-paths.mjs +15 -0
  181. package/hooks/_lib/subagent-transcript.mjs +582 -31
  182. package/hooks/_lib/vcs-create-matcher.mjs +217 -62
  183. package/hooks/config-protection.mjs +11 -3
  184. package/hooks/cwd-change-restore.mjs +11 -3
  185. package/hooks/enforce-commands.mjs +70 -23
  186. package/hooks/enforce-scope.mjs +143 -33
  187. package/hooks/hooks-codex.json +1 -1
  188. package/hooks/hooks.json +1 -1
  189. package/hooks/loop-guard.mjs +11 -3
  190. package/hooks/on-session-end.mjs +72 -25
  191. package/hooks/on-session-start.mjs +48 -11
  192. package/hooks/on-stop.mjs +211 -23
  193. package/hooks/operator-steer.mjs +11 -3
  194. package/hooks/post-bash-issue-budget-refund.mjs +18 -8
  195. package/hooks/post-bash-write-verify.mjs +6 -2
  196. package/hooks/post-edit-import-probe.mjs +17 -9
  197. package/hooks/post-edit-validate.mjs +13 -5
  198. package/hooks/post-subagent-discovery-validator.mjs +98 -13
  199. package/hooks/post-tool-batch-wave-signal.mjs +200 -38
  200. package/hooks/post-tool-failure-corrective-context.mjs +11 -5
  201. package/hooks/post-tooluse-frontend-slop.mjs +10 -4
  202. package/hooks/pre-auq-clarity.mjs +18 -2
  203. package/hooks/pre-bash-destructive-guard.mjs +80 -9
  204. package/hooks/pre-bash-issue-budget.mjs +119 -28
  205. package/hooks/pre-bash-memory-propose-audit.mjs +86 -54
  206. package/hooks/pre-bash-sessions-ledger-guard.mjs +391 -20
  207. package/hooks/pre-bash-staging-fence.mjs +335 -31
  208. package/hooks/pre-bash-templates-first.mjs +19 -14
  209. package/hooks/pre-task-scope-disjoint.mjs +385 -5
  210. package/hooks/skill-invocation-telemetry.mjs +2 -1
  211. package/hooks/subagent-telemetry.mjs +15 -19
  212. package/hooks/wave-scope-commit-guard.mjs +197 -100
  213. package/monitors/monitors.json +1 -1
  214. package/output-styles/wave-summary.md +1 -1
  215. package/package.json +2 -1
  216. package/pi/prompts/autopilot.md +3 -3
  217. package/pi/prompts/bootstrap.md +3 -3
  218. package/pi/prompts/brainstorm.md +3 -3
  219. package/pi/prompts/close.md +2 -2
  220. package/pi/prompts/debug.md +3 -3
  221. package/pi/prompts/discovery.md +3 -3
  222. package/pi/prompts/dispatcher.md +3 -3
  223. package/pi/prompts/eli5.md +3 -3
  224. package/pi/prompts/eval.md +3 -3
  225. package/pi/prompts/evolve.md +3 -3
  226. package/pi/prompts/go.md +2 -2
  227. package/pi/prompts/grill.md +3 -3
  228. package/pi/prompts/harness-audit.md +2 -3
  229. package/pi/prompts/memory-cleanup.md +3 -3
  230. package/pi/prompts/persona-panel.md +3 -3
  231. package/pi/prompts/plan.md +3 -3
  232. package/pi/prompts/portfolio.md +2 -2
  233. package/pi/prompts/reconcile.md +3 -3
  234. package/pi/prompts/release.md +3 -3
  235. package/pi/prompts/repo-audit.md +3 -4
  236. package/pi/prompts/session.md +2 -2
  237. package/pi/prompts/spinout.md +3 -3
  238. package/pi/prompts/sunset-review.md +3 -3
  239. package/pi/prompts/templates-ack.md +1 -1
  240. package/pi/prompts/test.md +3 -3
  241. package/pi/prompts/ux-grill.md +3 -3
  242. package/rules/README.md +1 -1
  243. package/rules/opt-in-domain/prompt-caching.md +1 -1
  244. package/rules/opt-in-stack/backend-data.md +1 -1
  245. package/rules/opt-in-stack/backend.md +3 -3
  246. package/rules/opt-in-stack/frontend.md +1 -1
  247. package/rules/opt-in-stack/security-web.md +3 -3
  248. package/rules/opt-in-stack/swift.md +1 -1
  249. package/scripts/archive-closed-prds.mjs +2 -2
  250. package/scripts/auq-audit.mjs +2 -3
  251. package/scripts/autopilot.mjs +23 -2
  252. package/scripts/backfill-abandoned-sessions.mjs +171 -15
  253. package/scripts/backfill-evidence-digest.mjs +2 -1
  254. package/scripts/backfill-learnings-from-vault.mjs +2 -2
  255. package/scripts/check-package-manager.mjs +2 -2
  256. package/scripts/check-sessions-integrity.mjs +300 -0
  257. package/scripts/ci/assert-vitest-green.mjs +2 -1
  258. package/scripts/dialectic-deriver.mjs +50 -13
  259. package/scripts/emit-session.mjs +77 -32
  260. package/scripts/eval-session.mjs +65 -3
  261. package/scripts/export-hw-learnings.mjs +2 -1
  262. package/scripts/express-path.mjs +1 -1
  263. package/scripts/gc-stale-worktrees.mjs +2 -1
  264. package/scripts/generate-agents-skills.mjs +102 -29
  265. package/scripts/generate-codex-skills.mjs +48 -4
  266. package/scripts/generate-cursor-adapter.mjs +220 -11
  267. package/scripts/generate-hook-import-set.mjs +12 -27
  268. package/scripts/generate-pi-prompts.mjs +183 -13
  269. package/scripts/github-protection-audit.mjs +2 -3
  270. package/scripts/lib/agent-frontmatter.mjs +23 -1
  271. package/scripts/lib/agent-status.mjs +2 -31
  272. package/scripts/lib/auq/clarity.mjs +10 -2
  273. package/scripts/lib/auq/parse.mjs +12 -31
  274. package/scripts/lib/auq/schema.mjs +56 -41
  275. package/scripts/lib/auto-dialectic.mjs +304 -15
  276. package/scripts/lib/autopilot/flags.mjs +12 -1
  277. package/scripts/lib/autopilot/kill-switches.mjs +6 -3
  278. package/scripts/lib/autopilot/loop.mjs +14 -1
  279. package/scripts/lib/autopilot/stall-sampler.mjs +80 -23
  280. package/scripts/lib/ci-status-banner.mjs +376 -16
  281. package/scripts/lib/claude-md-budget-lint.mjs +2 -5
  282. package/scripts/lib/command-blocker.mjs +408 -33
  283. package/scripts/lib/config/dialectic.mjs +12 -3
  284. package/scripts/lib/config/drift-check.mjs +19 -0
  285. package/scripts/lib/config/gate.mjs +74 -0
  286. package/scripts/lib/config/reaper.mjs +162 -0
  287. package/scripts/lib/config.mjs +14 -0
  288. package/scripts/lib/convergence-monitor.mjs +76 -13
  289. package/scripts/lib/cursor-hook-bridge.mjs +2 -2
  290. package/scripts/lib/description-surface.mjs +2 -5
  291. package/scripts/lib/dispatcher/cli.mjs +2 -1
  292. package/scripts/lib/ecosystem-health.mjs +11 -0
  293. package/scripts/lib/ecosystem-wizard.mjs +2 -1
  294. package/scripts/lib/eval/engine.mjs +421 -53
  295. package/scripts/lib/eval/judge.mjs +463 -40
  296. package/scripts/lib/eval/schema.mjs +10 -1
  297. package/scripts/lib/events-rotation.mjs +221 -25
  298. package/scripts/lib/events-schema.mjs +114 -0
  299. package/scripts/lib/events.mjs +524 -5
  300. package/scripts/lib/fetch-baseline.mjs +3 -8
  301. package/scripts/lib/frontmatter-guard.mjs +21 -10
  302. package/scripts/lib/gates/gate-baseline.mjs +27 -2
  303. package/scripts/lib/gates/gate-full.mjs +28 -3
  304. package/scripts/lib/gates/gate-helpers.mjs +243 -21
  305. package/scripts/lib/gates/gate-incremental.mjs +28 -3
  306. package/scripts/lib/gates/gate-per-file.mjs +27 -2
  307. package/scripts/lib/gitlab-ops/stale-mr-sweep.mjs +2 -1
  308. package/scripts/lib/gitlab-portfolio/cli.mjs +2 -1
  309. package/scripts/lib/gitlab-portfolio/markdown-writer.mjs +6 -1
  310. package/scripts/lib/instruction-budget-guard.mjs +332 -50
  311. package/scripts/lib/io.mjs +42 -8
  312. package/scripts/lib/is-main-module.mjs +82 -0
  313. package/scripts/lib/issue-close-strip-labels.mjs +207 -49
  314. package/scripts/lib/js-mask.mjs +197 -0
  315. package/scripts/lib/learnings/evolve-telemetry.mjs +11 -7
  316. package/scripts/lib/locks/index.mjs +32 -25
  317. package/scripts/lib/maintenance-due-banner.mjs +122 -91
  318. package/scripts/lib/orphan-reaper.mjs +1588 -0
  319. package/scripts/lib/peer-cards/merger.mjs +48 -10
  320. package/scripts/lib/peer-cards/reader.mjs +78 -2
  321. package/scripts/lib/peer-discovery.mjs +2 -5
  322. package/scripts/lib/playwright-driver/runner.mjs +2 -1
  323. package/scripts/lib/process-group.mjs +899 -0
  324. package/scripts/lib/quality-gate.mjs +107 -28
  325. package/scripts/lib/reconcile/backlog.mjs +368 -0
  326. package/scripts/lib/reconcile/engine.mjs +55 -188
  327. package/scripts/lib/reconcile/rule-expiry-sweep.mjs +884 -0
  328. package/scripts/lib/reconcile/sanitize.mjs +69 -3
  329. package/scripts/lib/reconcile-nudge-banner.mjs +138 -45
  330. package/scripts/lib/resource-probe/parsers.mjs +31 -0
  331. package/scripts/lib/rule-loader.mjs +41 -12
  332. package/scripts/lib/rules-sync.mjs +2 -5
  333. package/scripts/lib/scope-echo.mjs +429 -7
  334. package/scripts/lib/scope-gate.mjs +605 -1
  335. package/scripts/lib/session-close-backfill.mjs +91 -12
  336. package/scripts/lib/session-id.mjs +9 -20
  337. package/scripts/lib/session-invocation.mjs +20 -0
  338. package/scripts/lib/session-schema/constants.mjs +30 -2
  339. package/scripts/lib/session-schema/normalizer.mjs +56 -4
  340. package/scripts/lib/session-schema.mjs +8 -3
  341. package/scripts/lib/session-start-probes.mjs +95 -10
  342. package/scripts/lib/sessions-canonical.mjs +23 -0
  343. package/scripts/lib/sessions-integrity-banner.mjs +7 -1
  344. package/scripts/lib/sessions-staleness-banner.mjs +193 -51
  345. package/scripts/lib/skill-evidence-window.mjs +891 -0
  346. package/scripts/lib/skill-evolution/candidate-intake.mjs +133 -12
  347. package/scripts/lib/skill-evolution/engine.mjs +18 -9
  348. package/scripts/lib/skill-judge.mjs +45 -3
  349. package/scripts/lib/state-md.mjs +84 -3
  350. package/scripts/lib/sunset/walker.mjs +31 -4
  351. package/scripts/lib/tail-window.mjs +56 -0
  352. package/scripts/lib/telemetry/schema.mjs +30 -0
  353. package/scripts/lib/telemetry/sync.mjs +61 -6
  354. package/scripts/lib/telemetry-flush-health-banner.mjs +4 -22
  355. package/scripts/lib/test-runner/issue-reconcile.mjs +48 -16
  356. package/scripts/lib/tests-src-ratio.mjs +2 -6
  357. package/scripts/lib/tmux-layout/telemetry-stats.mjs +74 -14
  358. package/scripts/lib/user-invocable-skills.mjs +205 -0
  359. package/scripts/lib/ux-grill/reconcile.mjs +48 -22
  360. package/scripts/lib/validate/check-agents-skills.mjs +26 -15
  361. package/scripts/lib/validate/check-banner-parity.mjs +2 -2
  362. package/scripts/lib/validate/check-cursor-adapter.mjs +3 -2
  363. package/scripts/lib/validate/check-dead-bridge.mjs +2 -2
  364. package/scripts/lib/validate/check-doc-cli-commands.mjs +2 -2
  365. package/scripts/lib/validate/check-entry-guard.mjs +329 -0
  366. package/scripts/lib/validate/check-guard-requires-parity.mjs +2 -2
  367. package/scripts/lib/validate/check-hook-entry-guards.mjs +636 -0
  368. package/scripts/lib/validate/check-hooks-emit-event-guard.mjs +2 -2
  369. package/scripts/lib/validate/check-learning-provenance.mjs +2 -2
  370. package/scripts/lib/validate/check-pi-prompts.mjs +1 -0
  371. package/scripts/lib/validate/check-rules.mjs +7 -5
  372. package/scripts/lib/validate/check-skill-links.mjs +35 -6
  373. package/scripts/lib/validate/check-skill-script-paths.mjs +241 -29
  374. package/scripts/lib/validate/check-test-git-config-target.mjs +26 -36
  375. package/scripts/lib/validate/check-unicode-safety.mjs +2 -2
  376. package/scripts/lib/validate/check-untracked-test-deps.mjs +9 -104
  377. package/scripts/lib/validate/check-unwired-features.mjs +220 -33
  378. package/scripts/lib/validate/check-validator-registration.mjs +36 -12
  379. package/scripts/lib/validate/check-vcs-repo-flag.mjs +2 -2
  380. package/scripts/lib/validate/confidential-names.mjs +10 -0
  381. package/scripts/lib/validate-vendored-rules.mjs +39 -12
  382. package/scripts/lib/vault-mirror/namespace.mjs +46 -8
  383. package/scripts/lib/vault-mirror/process.mjs +10 -3
  384. package/scripts/lib/vault-mirror/render-sessions.mjs +12 -2
  385. package/scripts/lib/vault-status/narrative-mirror.mjs +31 -7
  386. package/scripts/lib/vault-yaml.mjs +118 -0
  387. package/scripts/lib/wave-transcript-tail.mjs +2 -2
  388. package/scripts/lib/worktree/lifecycle.mjs +153 -1
  389. package/scripts/lock-reaper.mjs +2 -1
  390. package/scripts/materialize-wave-scope.mjs +87 -4
  391. package/scripts/migrate-sessions-jsonl.mjs +2 -1
  392. package/scripts/migrate-vault-paths.mjs +2 -3
  393. package/scripts/release-session-lock.mjs +305 -0
  394. package/scripts/release.mjs +109 -39
  395. package/scripts/relocate-vault-corpus.mjs +2 -3
  396. package/scripts/repair-invalid-sessions.mjs +2 -2
  397. package/scripts/resolve-session-invocation.mjs +59 -0
  398. package/scripts/run-quality-gate.mjs +156 -17
  399. package/scripts/session-shape.mjs +2 -2
  400. package/scripts/site-numbers.mjs +35 -11
  401. package/scripts/sweep-expired-rules.mjs +227 -0
  402. package/scripts/validate-plugin.mjs +21 -0
  403. package/scripts/validate-wave-scope.mjs +32 -105
  404. package/scripts/vault-consolidate.mjs +2 -2
  405. package/scripts/vault-mirror.mjs +11 -4
  406. package/scripts/wave-scope-binding.mjs +2 -3
  407. package/skills/_shared/bootstrap-gate.md +1 -1
  408. package/skills/_shared/monitor-patterns.md +1 -1
  409. package/skills/_shared/platform-tools.md +23 -11
  410. package/skills/_shared/research-evidence.md +53 -0
  411. package/skills/_shared/state-ownership.md +3 -0
  412. package/skills/autopilot/SKILL.md +80 -11
  413. package/skills/bootstrap/SKILL.md +51 -1
  414. package/skills/brainstorm/SKILL.md +16 -0
  415. package/skills/claude-md-drift-check/SKILL.md +1 -1
  416. package/skills/claude-md-drift-check/checker.mjs +49 -11
  417. package/{commands/close.md → skills/close/SKILL.md} +9 -3
  418. package/skills/convergence-monitoring/README.md +8 -1
  419. package/skills/convergence-monitoring/SIGNALS.md +50 -6
  420. package/skills/convergence-monitoring/SKILL.md +15 -6
  421. package/skills/debug/SKILL.md +10 -0
  422. package/skills/discovery/SKILL.md +24 -1
  423. package/skills/discovery/probes-session.md +2 -2
  424. package/skills/dispatcher/SKILL.md +38 -7
  425. package/skills/eli5/SKILL.md +11 -0
  426. package/skills/eval/SKILL.md +52 -23
  427. package/skills/eval/rubric-v1.md +1 -0
  428. package/skills/eval/rubric-v2.md +457 -0
  429. package/skills/evolve/SKILL.md +9 -2
  430. package/skills/evolve/references/evolve-dialectic-mode.md +46 -25
  431. package/skills/gitlab-ops/SKILL.md +3 -2
  432. package/{commands/go.md → skills/go/SKILL.md} +9 -1
  433. package/skills/grill/SKILL.md +19 -0
  434. package/{commands/harness-audit.md → skills/harness-audit/SKILL.md} +7 -2
  435. package/skills/hook-development/SKILL.md +46 -41
  436. package/skills/memory-cleanup/SKILL.md +7 -0
  437. package/skills/npm-publish/SKILL.md +2 -2
  438. package/skills/persona-panel/SKILL.md +56 -1
  439. package/skills/persona-panel/persona-format.md +1 -1
  440. package/skills/plan/SKILL.md +28 -1
  441. package/{commands/portfolio.md → skills/portfolio/SKILL.md} +8 -2
  442. package/skills/reconcile/SKILL.md +21 -0
  443. package/{commands/release.md → skills/release/SKILL.md} +16 -2
  444. package/skills/repo-audit/SKILL.md +7 -0
  445. package/skills/session-end/SKILL.md +13 -16
  446. package/skills/session-end/discovery-scan.md +1 -1
  447. package/skills/session-end/phase-3-6-tail.md +55 -9
  448. package/skills/session-end/plan-verification.md +2 -2
  449. package/skills/session-end/references/phase-5-issue-cleanup.md +9 -14
  450. package/skills/session-end/session-metrics-write.md +10 -0
  451. package/skills/session-plan/SKILL.md +18 -6
  452. package/skills/session-plan/references/session-plan-task-classification.md +2 -2
  453. package/skills/session-start/SKILL.md +5 -4
  454. package/skills/session-start/phase-8-5-express-path.md +6 -6
  455. package/skills/session-start/references/phase-1-5-session-continuity.md +1 -1
  456. package/skills/session-start/references/phase-2-7-portfolio-snapshot.md +1 -1
  457. package/skills/session-start/references/phase-4-ssot-environment-check.md +6 -4
  458. package/skills/spinout/SKILL.md +12 -1
  459. package/skills/sunset-review/SKILL.md +13 -0
  460. package/{commands/test.md → skills/test/SKILL.md} +10 -4
  461. package/skills/ux-grill/SKILL.md +20 -2
  462. package/skills/wave-executor/SKILL.md +14 -7
  463. package/skills/wave-executor/circuit-breaker.md +2 -0
  464. package/skills/wave-executor/references/wave-executor-state-init.md +18 -4
  465. package/skills/wave-executor/references/wave-loop-dispatch.md +5 -2
  466. package/skills/wave-executor/references/wave-loop-review.md +17 -1
  467. package/commands/autopilot.md +0 -80
  468. package/commands/bootstrap.md +0 -56
  469. package/commands/brainstorm.md +0 -48
  470. package/commands/debug.md +0 -36
  471. package/commands/discovery.md +0 -32
  472. package/commands/dispatcher.md +0 -59
  473. package/commands/eli5.md +0 -33
  474. package/commands/eval.md +0 -28
  475. package/commands/evolve.md +0 -10
  476. package/commands/grill.md +0 -45
  477. package/commands/memory-cleanup.md +0 -26
  478. package/commands/persona-panel.md +0 -121
  479. package/commands/plan.md +0 -15
  480. package/commands/reconcile.md +0 -23
  481. package/commands/repo-audit.md +0 -24
  482. package/commands/spinout.md +0 -15
  483. package/commands/sunset-review.md +0 -27
  484. package/commands/ux-grill.md +0 -51
@@ -200,6 +200,15 @@ down session-start.
200
200
  | `stale-branch-days` | integer | `7` | Days of inactivity before a branch is flagged as stale. |
201
201
  | `stale-issue-days` | integer | `30` | Days without progress before an issue is flagged for triage. |
202
202
 
203
+ **`cross-repo.projects` block form (#469, #478).** Not to be confused with the flat `cross-repos` list above. The dotted name is only how `parseSessionConfig()` returns it (`scripts/lib/config.mjs:446`); in the config file it is a `projects:` sub-key under a top-level `cross-repo:` block:
204
+
205
+ ```yaml
206
+ cross-repo:
207
+ projects: [~/Projects/my-app, ~/Projects/another-app] # INLINE list only
208
+ ```
209
+
210
+ Parsed by `_parseCrossRepo()` (`scripts/lib/config/cross-repo.mjs:50-84`). Only the inline form on the `projects:` line is read — a block list of `- ` items under `projects:` yields `[]` without a warning (measured 2026-09-18). An entry containing anything outside `[A-Za-z0-9._~/-]` (a shell metacharacter, a space) is dropped with one stderr line `cross-repo: rejected project entry with shell metacharacter: …`. Absent, empty, `none` or `null` → `[]`. Readers additionally drop entries resolving outside `~/Projects/` (confinement root, `getConfinementRoot()`). Read by `scripts/run-migrate-v2-cross-repo.mjs`, `scripts/vault-integration-watcher.mjs`, `scripts/promote-vault-strict.mjs`, and — as a secondary repo source after the filesystem scan — `scripts/lib/dispatcher/enumerate.mjs:303`.
211
+
203
212
  ## Auto-Skill Dispatch (#337)
204
213
 
205
214
  Opt-in phrase-match meta-skill (`skills/using-orchestrator/SKILL.md`) that inspects the user's first message for implicit slash-command intent (e.g. "plane neues Projekt", "run discovery on the backlog") and dispatches to the highest-confidence matching entry-point skill via the `Skill` tool — before that skill's own Phase 1 — once the bootstrap gate is open. Off by default; when `false` (or absent) the meta-skill returns immediately with zero reads, zero logging, zero side effects, and every calling skill behaves exactly as if it was never invoked.
@@ -332,7 +341,7 @@ slopcheck:
332
341
  | `memory-cleanup-threshold` | integer | `5` | Recommend `/memory-cleanup` after N accumulated session memory files. |
333
342
  | `memory-cleanup-soft-limit` | integer | `180` | Hard ceiling on accumulated memory files before the cleanup nudge escalates from a soft suggestion to a strong recommendation. PRD F2.2 / issue #502. Used by `scripts/lib/auto-dream.mjs`. |
334
343
 
335
- **Nudge retirement (2026-09-09, #1246-adjacent).** The two session-end nudges that used to read these thresholds — Phase 3.6.5 Auto-Dream and Phase 3.6.7 Auto-Dialectic — are RETIRED as standalone close-time prompts: measured across consumer repos, the auto-dialectic nudge recorded `decided: true` while nobody ever ran it, and memory-cleanup had run in only 1 of 3 repos, because both fired at the moment the operator is closing down, not the moment they can act. `shouldDispatchAutoDream()` and `shouldDispatchAutoDialectic()` are unchanged as pure signal functions and still consult these two keys — but they are now called from the session-START `maintenance-due` probe (`scripts/lib/maintenance-due-banner.mjs`, see § Reconcile below), which reads them as two of its six signals and reports a single `⚠ maintenance due: N of 6 …` banner at the one moment the operator can actually run `/session housekeeping`.
344
+ **Nudge retirement (2026-09-09, #1246-adjacent).** The two session-end nudges that used to read these thresholds — Phase 3.6.5 Auto-Dream and Phase 3.6.7 Auto-Dialectic — are RETIRED as standalone close-time prompts: measured across consumer repos, the auto-dialectic nudge recorded `decided: true` while nobody ever ran it, and memory-cleanup had run in only 1 of 3 repos, because both fired at the moment the operator is closing down, not the moment they can act. `shouldDispatchAutoDream()` and `shouldDispatchAutoDialectic()` are unchanged as pure signal functions and still consult these two keys — but they are now called from the session-START `maintenance-due` probe (`scripts/lib/maintenance-due-banner.mjs`, see § Reconcile below), which reads them as two of its seven signals and reports a single `⚠ maintenance due: N of 7 …` banner at the one moment the operator can actually run `/session housekeeping`.
336
345
  | `learning-expiry-days` | integer | `30` | Legacy/default expiry window used by review/extend flows. New analyzer learnings preserve a candidate-supplied `expires_at` or derive expiry from `LEARNING_TTL_DAYS[type]` (for example, `autonomy-verdict` is 90 days). |
337
346
  | `learnings-surface-top-n` | integer | `15` | Cap on how many learnings the session-start Phase 5.6 and session-plan Step 0.5 sections surface, ranked by confidence descending. `0` = do not surface any learnings. Applies to Project Intelligence output. |
338
347
  | `learning-decay-rate` | float (0.0 ≤ x < 1.0) | `0.05` | Confidence decay applied to every untouched learning at session-end (after touched-set update, before prune). `0.0` = disable decay. A learning starting at `0.5` confidence survives ~10 untouched sessions with default decay. |
@@ -343,6 +352,7 @@ slopcheck:
343
352
  | `grounding-check` | boolean | `true` | Enable file-level grounding verification in session-end Phase 1.1a (planned vs touched files). When true, session-end compares each agent's declared file scope against `git diff --name-only $SESSION_START_REF..HEAD` and reports scope creep + incomplete coverage. Informational — does not block session close. |
344
353
  | `grounding-injection-max-files` | integer | `3` | Max files with recent `edit-format-friction` stagnation history to inject as line-numbered GROUNDING blocks into each agent's prompt before dispatch (wave-executor pre-dispatch step). Per-agent scope; selects top N by recency. `0` disables the feature. Gated on `persistence: true`. (#85) |
345
354
  | `isolation` | string | `auto` | Agent isolation mode: `worktree`, `none`, or `auto`. `auto` resolves per-wave via the graduated default (#194): ≤2 agents → `none`, 3–4 agents on feature/deep → `worktree`, ≥5 agents → `worktree`, housekeeping 3–4 → `none`. Explicit `worktree` or `none` overrides the graduation. The resolved value surfaces per wave as `waves[].isolation` in the session shape's JSON output (`scripts/session-shape.mjs`) — a coordinator-direct or read-only wave resolves `none` without consulting the graduation at all. See [isolation graduation](#isolation-graduation) below. |
355
+ | `worktree-exclude` | list | `[node_modules, dist, build, .next, .nuxt, coverage, .cache, .turbo, .vercel, out]` | Top-level directory names deleted (recursive `fs.rm`) from a freshly created worktree, to cut disk and RAM on constrained hosts (#192). Parsed as a flat list by `scripts/lib/config.mjs:237-241`; read by `createWorktree()` (`scripts/lib/worktree/lifecycle.mjs:155-181`) and applied by `applyWorktreeExcludes()` (`scripts/lib/worktree/listing.mjs`). Names only, no globs, no nested paths; a name absent from the worktree is skipped silently. `null` / `none` / `[]` disable all excludes. **Scope limit (measured 2026-09-18):** `createWorktree()` has no production caller — `grep -rn "createWorktree(" scripts hooks skills` finds only a comment in `scripts/lib/wave-executor/foreign-dispatch.mjs`, which creates its own detached worktree with `git worktree add`. Wave dispatch under `isolation: worktree` uses the harness's native Agent worktree and never reads this key, so setting it changes nothing in a wave today. |
346
356
  | `max-turns` | integer or string | `auto` | Maximum agent turns before PARTIAL. Auto expands PER SESSION TYPE inside the resolved shape (`scripts/lib/session-shape.mjs` `MAX_TURNS_DEFAULT`, § Session Shapes above): housekeeping=8, feature=15, deep=25 (`maxTurnsDefault` in the shape JSON, applied to every wave). The `ultradeep` profile does **not** use one flat number — it sets `max-turns` PER WAVE: 40 for the Research+Code-Discovery wave, 25 for Impl-Core/Impl-Polish/Quality, 15 for Release/Finalization (the Synthesis-Gate wave is coordinator-direct and carries no `max-turns` at all). |
347
357
  | `auto-commit-per-wave` | boolean | `false` | Automatically commit each wave's work after the Quality-Lite gate passes. Checkpoint commits per wave reduce the risk of data loss from `git stash` collisions in parallel sessions (V3.3 RESCUE incident — see GitLab #214). When `false`, all work is committed at session-end via `/close`. Requires `persistence: true`; the flag is silently ignored when `persistence: false`. Trade-off: each wave produces an additional commit; git log shows N+1 commits instead of 1. Use `/simplify` or `git rebase -i --autosquash` before final close to squash if a clean history is desired. **Implementation note:** the procedural commit sequence (`scripts/lib/auto-commit.mjs`) is deferred to V3.6. Until then, setting this flag to `true` triggers a session-start warning that auto-commits are not yet active — the flag is a no-op but is validated so projects can opt in early. <!-- path-check: historical --> |
348
358
 
@@ -1003,14 +1013,14 @@ All fields live under a top-level `dialectic` object in your Session Config (CLA
1003
1013
  dialectic:
1004
1014
  cadence: 5 # integer ≥ 0; 0 = kill-switch
1005
1015
  model: haiku # haiku | sonnet | opus
1006
- budget-tokens: 8000 # input token budget per call
1016
+ budget-tokens: 32000 # input token ceiling per call
1007
1017
  ```
1008
1018
 
1009
1019
  | Field | Type | Default | Description |
1010
1020
  |-------|------|---------|-------------|
1011
- | `dialectic.cadence` | integer | `5` | Number of sessions between auto-dialectic dispatches. Set to `0` to disable all dispatches (kill-switch). Non-integer and negative values silently fall back to default. **The dispatch moment moved (2026-09-09):** `shouldDispatchAutoDialectic()` is still the decision function this key feeds, but session-end Phase 3.6.7's own auto-trigger nudge is gone — retired as a standalone close-time prompt, and its recording wrapper (with the `orchestrator.dialectic.nudge_decided` event) removed in #1288 — see § Persistence & Safety above "Nudge retirement". The session-start `maintenance-due` probe now calls it as one of six signals, so a due dialectic surfaces where the operator can act on it (session start), not where they are closing down. |
1021
+ | `dialectic.cadence` | integer | `5` | Number of sessions between auto-dialectic dispatches. Set to `0` to disable all dispatches (kill-switch). Non-integer and negative values silently fall back to default. **The dispatch moment moved (2026-09-09):** `shouldDispatchAutoDialectic()` is still the decision function this key feeds, but session-end Phase 3.6.7's own auto-trigger nudge is gone — retired as a standalone close-time prompt, and its recording wrapper (with the `orchestrator.dialectic.nudge_decided` event) removed in #1288 — see § Persistence & Safety above "Nudge retirement". The session-start `maintenance-due` probe now calls it as one of seven signals, so a due dialectic surfaces where the operator can act on it (session start), not where they are closing down. |
1012
1022
  | `dialectic.model` | string | `haiku` | Model tier for the critique call. Must be one of `haiku`, `sonnet`, `opus`. **Fail-fast**: unknown values cause parse-config.mjs to exit 1 at startup — NOT silently ignored. |
1013
- | `dialectic.budget-tokens` | integer | `8000` | Input token budget per call. Output budget is fixed at 4000 (per #506). Non-integer and negative values fall back to default. |
1023
+ | `dialectic.budget-tokens` | integer | `32000` | Input token ceiling per call (`DEFAULT_BUDGET_TOKENS`, `scripts/lib/config/dialectic.mjs:24`). `32000` — card bodies + steering alone estimated ~12k tokens in this repo, a consumer repo measured 30,262 (2026-09-18); the value is a ceiling, the pre-dispatch estimate aborts above it (`checkBudget()`, `scripts/dialectic-deriver.mjs:125`, status `budget-exceeded` — never a truncation). Output budget is fixed at 4000 (per #506). Non-integer and negative values fall back to default. |
1014
1024
 
1015
1025
  **Used by:** `skills/evolve/SKILL.md` Phase 6, `scripts/dialectic-deriver.mjs`, `scripts/lib/auto-dialectic.mjs`, and the session-start `maintenance-due` probe (`scripts/lib/maintenance-due-banner.mjs`). Session-end Phase 3.6.7 no longer reads it (retired 2026-09-09).
1016
1026
 
@@ -1018,9 +1028,9 @@ dialectic:
1018
1028
 
1019
1029
  **Trigger behavior:** When `cadence > 0` AND sessions-since-last-dialectic ≥ cadence AND (≥1 new session OR ≥1 new learning since last run), `shouldDispatchAutoDialectic()` returns `trigger: true` and the session-start `maintenance-due` probe reports it; the housekeeping session then runs the deriver in dry-run mode (session-end Phase 3.6.7 is retired — it dispatches nothing). The diff sidecar lands at `.orchestrator/dialectic-pending.md` (gitignored, vault-mirror-excluded). When `cadence: 0`, the signal never fires; manual `/evolve --dialectic` always works. <!-- path-check: example -->
1020
1030
 
1021
- **Token cost:** With defaults (cadence: 5, budget-tokens: 8000, output 4000, model haiku), ~12k tokens every 5 sessions. At haiku pricing this is ~$0.02/run. Surfaced in Final Report.
1031
+ **Token cost:** `budget-tokens` is a ceiling, not a spend — a run costs its actual input plus at most 4000 output tokens, once every 5 sessions with the default cadence (model haiku). Surfaced in Final Report.
1022
1032
 
1023
- **Empirical note (2026-07-04 session-3) the parser default of `8000` proved structurally unreachable for this repo's own peer-card/steering corpus.** Fixed overhead (Peer-Cards + Steering + scaffold) alone runs ≈13k tokens, and a full input set (top-50 learnings + last-10 sessions) runs ≈28.4k tokens both already exceed the `8000` default before any call is made. This repo's own committed Session Config therefore sets `budget-tokens: 32000`, not the documented default. If your repo accumulates a similarly large peer-card/steering corpus over time, raise `budget-tokens` accordingly rather than leaving the low default in place — a too-low budget silently truncates the dialectic critique input rather than erroring.
1033
+ **Empirical note — why the default is `32000` (#1380).** The former parser default of `8000` proved structurally unreachable: in this repo (2026-07-04 session-3) the fixed overhead (Peer-Cards + Steering + scaffold) alone ran ≈13k tokens and a full input set (top-50 learnings + last-10 sessions) ≈28.4k tokens; a consumer repo measured 30,262 (2026-09-18). Because the budget gate aborts BEFORE dispatch instead of truncating (`scripts/dialectic-deriver.mjs:604-612`), a corpus of that size can never run under `8000` it ends `budget-exceeded` every time. If your peer-card/steering corpus outgrows `32000`, raise `budget-tokens` — a too-low ceiling aborts the run, it never shortens the input.
1024
1034
 
1025
1035
  ## Eval (#803)
1026
1036
 
@@ -1049,6 +1059,10 @@ eval:
1049
1059
 
1050
1060
  **Parser gotcha (learning confidence 0.9 — mirrors `custom-phases:` and every other block-shaped key):** the `eval:` key-line itself MUST NOT carry an inline comment. The block-open scan uses the shared `matchBlockHeader(line, 'eval')` (`scripts/lib/config/block-header.mjs`) — it tolerates the bold-bullet `- **eval:**` rendering (#830) but a trailing `# comment` on the header line still fails the match, so the parser never enters the block and ALL fields silently fall back to their defaults — no error, no warning surfaces anywhere. Sub-key lines (`enabled:`, `mode:`, …) tolerate inline comments without issue. See § Parser Gotcha: No-Inline-Comment Block Headers (top of this file) for the general contract this key shares with 36 other block-shaped keys.
1051
1061
 
1062
+ **Rubric version is NOT a Session Config key (#1037).** No key here selects the check set. The engine pins it as a constant — `RUBRIC_VERSION` in `scripts/lib/eval/engine.mjs` — because the rubric is *pre-registered*: a changed check mints a new version and a new file, it is never a per-repo dial. Current value: **`rubric-v2`** (`skills/eval/rubric-v2.md`, 2026-09-19), which supersedes `rubric-v1` (2026-07-16) for every newly written record. The two changes: `process-safety` no longer fails on `destructive_guard.blocked` (measured 2026-09-19 @ `d92c2ca4`: 32 of 40 records `fail`, all 32 solely from `blocked`, spiral `0` in all 40 — `.claude/rules/host-resources.md` HR-101), and the guard counts moved to a new reported-only `guard-friction` dimension. Stored records keep the `rubric_version` they were scored under and stay readable: neither `scripts/lib/eval/schema.mjs` nor `scripts/lib/eval/report.mjs` enumerates a fixed dimension set. `--verify` in `scripts/eval-session.mjs` used to re-score every stored record with the current engine and therefore reported `DRIFT` on all 40 `rubric-v1` records (measured 2026-09-19); since #1400 it compares only at matching `rubric_version` and otherwise returns its own verdict `version-mismatch` with exit code **3** — a planned rubric change is no longer indistinguishable from a forged record.
1063
+
1064
+ Neither `eval.enabled` nor `eval.judge` changed in v2 — the harness runs exactly where it ran before.
1065
+
1052
1066
  **Used by:** `scripts/lib/config/eval.mjs` (`_parseEval`), `scripts/lib/config.mjs`. Skill consumer (`skills/eval/SKILL.md`) is a follow-up wave of Epic #803 — not yet implemented as of this parser.
1053
1067
 
1054
1068
  ## Vault Staleness
@@ -1205,9 +1219,38 @@ docs-orchestrator:
1205
1219
  - `skills/session-end/SKILL.md` — Phase 3.2 gap-reporting step (activated when `enabled: true`)
1206
1220
  - `agents/docs-writer.md` — agent dispatched for documentation generation
1207
1221
 
1222
+ ## GitLab Portfolio (GH #41)
1223
+
1224
+ Opt-in cross-repo health dashboard for the `gitlab-portfolio` skill (`/portfolio`): discovers repos from `<vault>/01-projects/*/_overview.md`, aggregates open issues, MRs, critical labels and stale signals, and writes `_PORTFOLIO.md` into the vault. It needs `vault-integration.vault-dir` — the CLI exits 2 without it (`scripts/lib/gitlab-portfolio/cli.mjs`).
1225
+
1226
+ All fields live under a top-level `gitlab-portfolio` object in your Session Config host file (`CLAUDE.md` or `AGENTS.md`):
1227
+
1228
+ ```yaml
1229
+ gitlab-portfolio:
1230
+ enabled: false # opt-in
1231
+ mode: warn # warn | strict | off
1232
+ stale-days: 30 # integer ≥ 1
1233
+ critical-labels: # BLOCK list only — see the row below
1234
+ - priority::critical
1235
+ - priority::high
1236
+ ```
1237
+
1238
+ | Field | Type | Default | Allowed values | Description |
1239
+ |-------|------|---------|----------------|-------------|
1240
+ | `gitlab-portfolio.enabled` | boolean | `false` | `true` / `false` | Only the literal `true` enables it. When false, `/portfolio` prints `disabled` and exits 0 (`cli.mjs:192-199`), and session-start Phase 2.7 skips its dry-run banner (`skills/session-start/SKILL.md` § Phase 2.7). |
1241
+ | `gitlab-portfolio.mode` | string | `warn` | `warn` / `strict` / `off` | `strict` makes the CLI exit 2 when any repo failed to fetch (`cli.mjs:375`). `warn` and `off` both exit 0 in the CLI; `off` additionally suppresses the session-start banner. An unknown value falls back to `warn`. |
1242
+ | `gitlab-portfolio.stale-days` | integer | `30` | integer ≥ 1 | An open issue whose `updated_at` is older than this counts as stale (`scripts/lib/gitlab-portfolio/aggregator.mjs`). An invalid value falls back to `30`. |
1243
+ | `gitlab-portfolio.critical-labels` | array of string | `[priority::critical, priority::high]` | non-empty strings | Labels that count an issue as critical; matching is scope-tolerant (`priority:critical` also matches). **Block list only:** items need their own `- ` lines indented at least 3 spaces. The inline form `critical-labels: [a, b]` is NOT read — the parser silently keeps the default (measured 2026-09-18 via `_parseGitlabPortfolio`). |
1244
+
1245
+ Parsing is tolerant: `_parseGitlabPortfolio()` (`scripts/lib/config/gitlab-portfolio.mjs`, called at `scripts/lib/config.mjs:443`) drops unknown sub-keys and replaces invalid values with the defaults above, never throwing. The strict check lives separately in `validateGitlabPortfolio()` (`scripts/lib/config-schema.mjs:369-405`, wired at `:104-106`), which reports wrong types and unknown sub-keys as schema errors under `enforcement`.
1246
+
1247
+ **Used by:** `scripts/lib/gitlab-portfolio/cli.mjs` (`/portfolio`, and session-start Phase 2.7 via `--dry-run`), `skills/gitlab-portfolio/SKILL.md`.
1248
+
1208
1249
  ## Events Rotation
1209
1250
 
1210
- Size-based rotation for `.orchestrator/metrics/events.jsonl` (#251). Rotation fires at **session-start only** — per-append overhead is rejected design given typical growth of ~6 KiB/day. When the active log exceeds `max-size-mb`, it is renamed to `events.jsonl.1`, older backups shift down (`.1` `.2`, …, `.N-1` `.N`), and the oldest backup (`events.jsonl.{max-backups}`) is deleted. Rotation failure never blocks session-start; errors are logged to stderr and swallowed.
1251
+ Size-based rotation for `.orchestrator/metrics/events.jsonl` (#251). Rotation fires at **session-start only** — per-append overhead is rejected design given typical growth of ~6 KiB/day. When the active log exceeds `max-size-mb`, it is renamed into `.orchestrator/metrics/_archive/events-<firstTs>_<lastTs>.jsonl` (each stamp `YYYYMMDDTHHMMSSZ`, derived from the archived content; `unknown` for the first when no timestamp parsed, plus a `-<n>` suffix on a name collision), archives beyond `max-backups` are pruned oldest-first, and an `orchestrator.events.rotated` record naming the archive, its byte size, line count, timestamp range and any pruned files is appended as the **first line of the new active file**. That record is what lets a reader tell a rotation from a deletion. Rotation failure never blocks session-start; errors are logged to stderr and swallowed.
1252
+
1253
+ **Reading across a rotation:** use `readEventsWithRotations(repoRoot, opts)` from `scripts/lib/events.mjs` — active file plus every archive in time order, `malformed_lines` counted, and a rotation whose `archived_as` target is missing reported in `gaps` with `complete: false`. It also still reads a legacy `events.jsonl.1`..`.N` ring left on disk by pre-#1401 versions; the writer never creates, shifts or prunes one any more. The ring was replaced because its shift step renamed every surviving backup on each rotation, which would have made the `archived_as` pointer stale one rotation after it was written.
1211
1254
 
1212
1255
  All fields live under a top-level `events-rotation` object in your Session Config host file (`CLAUDE.md` or `AGENTS.md`), for example:
1213
1256
 
@@ -1222,9 +1265,9 @@ events-rotation:
1222
1265
  |-------|------|---------|-------------|
1223
1266
  | `events-rotation.enabled` | boolean | `true` | If false, rotation is skipped entirely and `events.jsonl` grows unbounded. |
1224
1267
  | `events-rotation.max-size-mb` | integer | `10` | Size threshold in MiB. When `events.jsonl` exceeds this, it is rotated at the next session-start. Bounds: `1..1024`; out-of-range values silently fall back to the default. |
1225
- | `events-rotation.max-backups` | integer | `5` | Number of retained backup files (`events.jsonl.1` `events.jsonl.N`). The oldest is deleted before shifting. Bounds: `1..20`; out-of-range values silently fall back to the default. |
1268
+ | `events-rotation.max-backups` | integer | `5` | Number of retained archives in `.orchestrator/metrics/_archive/`. After each rotation the excess is deleted oldest-first (by the leading timestamp in the filename) and the deletions are listed in the rotation record's `pruned` field. Only files matching the archive naming contract are eligible, so a hand-placed file in `_archive/` is never pruned. Bounds: `1..20`; out-of-range values silently fall back to the default. |
1226
1269
 
1227
- **Rename safety (POSIX):** Atomic rename is safe with in-flight writers. Open file descriptors continue writing to the original inode (now `events.jsonl.1`); new writers open the new file on next append. Maximum observed line size is 220 bytes, well under the 4096-byte PIPE_BUF atomicity guarantee.
1270
+ **Rename safety (POSIX):** Atomic rename is safe with in-flight writers. Open file descriptors continue writing to the original inode (now the archive); new writers open the new file on next append. Maximum observed line size is 220 bytes, well under the 4096-byte PIPE_BUF atomicity guarantee.
1228
1271
 
1229
1272
  ## Test
1230
1273
 
@@ -1343,7 +1386,9 @@ Read by: `scripts/lib/config/evolve.mjs` (parser), `skills/evolve/SKILL.md` Step
1343
1386
 
1344
1387
  Opt-in configuration for the learning→conditional-rule reconciliation engine (Epic #693). When enabled, the reconciliation engine runs at session-end Phase 3.6.8 and proposes new `.claude/rules/` entries derived from accumulated learnings. The proposal is always operator-AUQ-gated — rules are **never** auto-applied. FA3 (#696) delivers proposals via `AskUserQuestion`; FA4 (#697) adds the guardrail config block documented here. When `enabled: false` (the default), Phase 3.6.8 is a silent no-op and the engine never runs.
1345
1388
 
1346
- **The former `reconcile-nudge` session-start probe is SUBSUMED (2026-09-09), not replaced 1:1.** `reconcile-nudge-banner.mjs`'s `computeReconcileNudge()` function is unchanged and still the reconcile-specific signal — but it is no longer surfaced as its own standalone banner. `scripts/lib/maintenance-due-banner.mjs` now calls it wholesale as one of six ANDed maintenance signals (`reconcile: computeReconcileNudge().nudge === true`) behind the single session-start `maintenance-due` probe, alongside `evolve`, `sweep`, `dialectic`, `memory-cleanup` and `pending-sidecar`. The reconcile signal is therefore not lost — it is reported as `⚠ maintenance due: N of 6 (…) — run /session housekeeping.` rather than as its own line, with a 7-day cooldown after any housekeeping session (`HOUSEKEEPING_COOLDOWN_DAYS`) so a repo that just ran the loop stays silent instead of re-nagging.
1389
+ **The former `reconcile-nudge` session-start probe is SUBSUMED (2026-09-09), not replaced 1:1.** `reconcile-nudge-banner.mjs`'s `computeReconcileNudge()` function is unchanged and still the reconcile-specific signal — but it is no longer surfaced as its own standalone banner. `scripts/lib/maintenance-due-banner.mjs` now calls it wholesale as one of seven ANDed maintenance signals (`reconcile: computeReconcileNudge().nudge === true`) behind the single session-start `maintenance-due` probe, alongside `evolve`, `sweep`, `dialectic`, `memory-cleanup`, `pending-sidecar` and `generated-rules-expiring`. The reconcile signal is therefore not lost — it is reported as `⚠ maintenance due: N of 7 (…) — run /session housekeeping.` rather than as its own line, with a 7-day cooldown after any housekeeping session (`HOUSEKEEPING_COOLDOWN_DAYS`) so a repo that just ran the loop stays silent instead of re-nagging.
1390
+
1391
+ **`generated-rules-expiring` (7th signal, 2026-09-16, #1372 follow-up).** Due when a machine-generated rule under `.claude/rules/` is expired or expires within `GENERATED_RULE_EXPIRY_HORIZON_DAYS` (7, a module constant — **no Session Config key**, same posture as every other threshold in this probe). Population and predicate come from `scripts/lib/instruction-budget-guard.mjs` (`listMachineGeneratedRules` / `daysUntilGeneratedRuleExpiry`), the same set its generated byte ceiling judges. The row names the files and their dates, because the repair is per-file: consolidate the content into a live thematic rule, move the `- learning-key:` / `- learning-id:` pairs with it, then delete. `rule-loader.mjs` filters an expired rule at READ time but nothing deletes it, so it keeps costing bytes and is still loaded verbatim by Claude Code (#1372). This alarm deliberately does NOT live in the test suite: an assertion against today's date turns `npm test` red on a calendar date with nothing committed, blocking unrelated work, and no test run can perform the consolidation.
1347
1392
 
1348
1393
  All fields live under a top-level `reconcile` object in your Session Config host file (`CLAUDE.md` or `AGENTS.md`), for example:
1349
1394
 
@@ -1501,6 +1546,56 @@ loop-guard:
1501
1546
 
1502
1547
  **Used by:** `hooks/loop-guard.mjs`, `scripts/lib/config/loop-guard.mjs` (`_parseLoopGuard`). Issue #619.
1503
1548
 
1549
+ ## Orphan Reaper (#1425 / #1432)
1550
+
1551
+ Watchdog against orphaned descendants of quality-gate commands. On **2026-09-20** four orphaned `tsgo --noEmit` processes from another repo on the same host — two with PPID 1, 86–588 % CPU, up to 8.0 GB RSS each — drove the machine to 13 % free memory and a 67.4 load average. Part A of the PRD stops them at the source (process-group kill in the gate); this block configures part B, the net that catches what still escapes.
1552
+
1553
+ The scan itself lives in `scripts/lib/orphan-reaper.mjs`. Two hooks TRIGGER it — `hooks/post-tool-batch-wave-signal.mjs` (PostToolBatch, the only hook with measurably high frequency *during* a wave) and `hooks/on-stop.mjs` (Stop + SubagentStop, which lands exactly when gate children have just finished). Neither runs the scan inline: one `ps` round-trip out of Node was measured at ~47 ms, which alone would exceed `max-hook-latency-ms`. The hook does one config read plus one `stat` of the throttle marker (`.orchestrator/tmp/reaper-last-scan`, shared by both hooks and gitignored), then hands the work to a DETACHED, `unref()`-ed child that owns the kill, the audit and the event.
1554
+
1555
+ **Default OFF, and deliberately so.** Unlike `loop-guard`, this signal can send signals to processes, so it ships inert. `.claude/rules/host-resources.md` HR-101 binds it: a warning class above ~10 % is a broken instrument to be re-aimed, not obeyed — measure the firing rate over `false-alarm-window` decisions in the JSONL audit BEFORE arming `mode: kill`. HR-105 binds the other half: a rate nothing records is unfalsifiable, which is why every decision (including a withdrawn one) is appended to `.orchestrator/metrics/reaper-audit.jsonl`.
1556
+
1557
+ ```yaml
1558
+ reaper:
1559
+ enabled: false # default OFF; only an explicit `true` arms the watchdog
1560
+ mode: report # report (decide + audit only) | kill (send signals)
1561
+ min-age-seconds: 300
1562
+ min-scan-interval-seconds: 30
1563
+ kill-grace-ms: 10000
1564
+ verify-wait-ms: 500
1565
+ max-hook-latency-ms: 50
1566
+ false-alarm-window: 50
1567
+ ```
1568
+
1569
+ | Field | Type | Default | Provenance / Description |
1570
+ |-------|------|---------|--------------------------|
1571
+ | `reaper.enabled` | boolean | `false` | Master toggle. Only an explicit `enabled: true` arms it; `false` means the hooks do no `stat` and no spawn at all. |
1572
+ | `reaper.mode` | `report` \| `kill` | `report` | `report` runs the scan in dry-run (decide + audit, no signal); `kill` arms the signal path (PRD Stufe 2, after calibration). An unrecognised value falls back to `report` — never to `kill`. |
1573
+ | `reaper.min-age-seconds` | integer (≥ 0) | `300` | DevWatchdog's hard limit for `tsgo`; the 2026-09-20 orphans were 7–17 min old, well above it. Self-healing clamp: a value below `min-scan-interval-seconds` is widened to it, because a process younger than one scan period can be born and reaped between two scans. |
1574
+ | `reaper.min-scan-interval-seconds` | integer (≥ 1) | `30` | DevWatchdog's normal scan cadence. The throttle that keeps a `PostToolBatch` storm from taxing every tool call. |
1575
+ | `reaper.kill-grace-ms` | integer (≥ 0) | `10000` | `DEFAULT_KILL_GRACE_MS` from `dispatch-common.mjs:61` — repo convention, not newly invented. SIGTERM → grace → SIGKILL. |
1576
+ | `reaper.verify-wait-ms` | integer (≥ 0) | `500` | Wait before reading the effect back. Without it the 2026-09-20 check falsely reported "still alive" measuring immediately after `kill -9` (PRD B6: a sent signal proves nothing). |
1577
+ | `reaper.max-hook-latency-ms` | integer (≥ 1) | `50` | Ceiling the TRIGGER may delay a hook by — the config read, the marker `stat` and the detached spawn, measured with `performance.now()` in `maybeTriggerOrphanScan()`. Overrunning it writes ONE stderr WARN line and nothing else: no event (a `PostToolBatch`-class hook emitting per fire is the always-on signal HR-101 calls a broken instrument) and no abort (the child is already detached by then). The scan itself is not covered — that is the point of spawning detached. |
1578
+ | `reaper.false-alarm-window` | integer (≥ 1) | `50` | Rolling window of audit decisions the HR-101 10 % false-alarm rate is judged over — a window in DECISIONS, not calendar time, so the rate has a population on quiet hosts too. Reaches the scan as `--false-alarm-window` on the detached child's argv and becomes `runOrphanScan`'s `falseAlarmWindow`; the CLI refuses `0`, which `falseAlarmRate()` would read as “every firing ever recorded” rather than as a window. |
1579
+
1580
+ **Used by:** `hooks/post-tool-batch-wave-signal.mjs`, `hooks/on-stop.mjs` (both via `maybeTriggerOrphanScan()`), `scripts/lib/orphan-reaper.mjs`, `scripts/lib/config/reaper.mjs` (`_parseReaper`). PRD `docs/prd/2026-09-20-prozessgruppen-kill-und-waisen-waechter.md`, Epic #1425, issue #1432.
1581
+
1582
+ ## Gate Timeout — Path B (#1425 A3)
1583
+
1584
+ The quality gate has two execution paths. Path A (`scripts/lib/quality-gate.mjs`) has always had a 900 000 ms cap. Path B — `scripts/run-quality-gate.mjs` → `scripts/lib/gates/gate-{baseline,incremental,full,per-file}.mjs` — had **no timeout at all**, which is how a wedged `tsgo` two levels down could run unbounded and be reparented to PPID 1. This block sets the committed ceiling for path B so both paths may run equally long.
1585
+
1586
+ ```yaml
1587
+ gate:
1588
+ timeout-path-b-ms: 900000 # 15 min; same cap as GATE_TIMEOUT_MS on path A
1589
+ ```
1590
+
1591
+ | Field | Type | Default | Description |
1592
+ |-------|------|---------|-------------|
1593
+ | `gate.timeout-path-b-ms` | integer (> 0) | `900000` | Per-command wall-clock ceiling for gate path B. A zero or negative value falls back to the default rather than being honoured — an instant-kill ceiling is worse than the uncapped state this key exists to fix. |
1594
+
1595
+ **Precedence, highest first:** `SO_GATE_TIMEOUT_MS` (operator override, per run) > `gate.timeout-path-b-ms` (committed) > `900000`. `run-quality-gate.mjs` resolves the three and publishes the ANSWER to the gate sub-script as the distinct env var `GATE_TIMEOUT_MS` — writing it back into `SO_GATE_TIMEOUT_MS` would make a committed default indistinguishable from an operator decision for every process further down the tree. The gate's own outer wrapper ceiling is derived from the same resolved number plus a 60 s reserve, so the inner per-command kill always fires first and the gate can still print its JSON envelope.
1596
+
1597
+ **Used by:** `scripts/run-quality-gate.mjs`, `scripts/lib/gates/gate-{baseline,incremental,full,per-file}.mjs`, `scripts/lib/config/gate.mjs` (`_parseGate`). PRD §4 A3, Epic #1425, issue #1432.
1598
+
1504
1599
  ## Config Protection (#622)
1505
1600
 
1506
1601
  `PreToolUse` `Edit`/`Write` guard that intercepts edits to a small allow-list of quality-gate config files (eslint, vitest, tsconfig, prettier, commitlint, gitleaks) and warns — or, in `strict` mode, blocks — when an edit LOOSENS a gate (a threshold lowered, a disable/ignore directive added, a rule removed, a gitleaks allowlist widened, tsconfig strictness relaxed). The edit-tool analogue of the test-the-mock gate-cheating anti-pattern (see `.claude/rules/testing.md`). First-time file creation, tightening edits, and neutral edits are always allowed regardless of mode.
@@ -1770,7 +1865,7 @@ Leave disabled (default) when:
1770
1865
  - The wave's deliverable is server-side / backend-only and persona evaluation would be noise.
1771
1866
 
1772
1867
  **Related skills and files:**
1773
- - `commands/persona-panel.md` — standalone `/persona-panel` command for ad-hoc panel runs (not gated on `persona-gate-wave.enabled`).
1868
+ - `skills/persona-panel/SKILL.md` — standalone `/persona-panel` command for ad-hoc panel runs (not gated on `persona-gate-wave.enabled`).
1774
1869
  - `skills/persona-panel/SKILL.md` — full skill spec (catalog format, consolidation modes, sidecar shape).
1775
1870
  - `skills/wave-executor/wave-loop.md` § 3b — the wave-executor hook contract.
1776
1871
  - `agents/schemas/persona-panel-sidecar.schema.json` — sidecar JSON Schema enforced before write.
@@ -477,9 +477,11 @@ Opt-in mode for `/evolve --dialectic` and session-end Phase 3.6.7 auto-trigger.
477
477
  dialectic:
478
478
  cadence: 5 # integer ≥ 0; 0 = kill-switch (no critique dispatches)
479
479
  model: haiku # haiku | sonnet | opus — fail-fast on unknown value
480
- budget-tokens: 8000 # integer ≥ 0 — input token budget per critique call
480
+ budget-tokens: 32000 # integer ≥ 0 — input token CEILING per critique call; the pre-dispatch estimate aborts above it
481
481
  ```
482
482
 
483
+ `32000` — card bodies + steering alone estimated ~12k tokens in this repo, a consumer repo measured 30,262 (2026-09-18); the value is a ceiling, the pre-dispatch estimate aborts above it.
484
+
483
485
  Read by: `scripts/lib/config/dialectic.mjs`, `scripts/lib/auto-dialectic.mjs`, `skills/session-end/SKILL.md` Phase 3.6.7, `skills/evolve/SKILL.md` Phase 6.
484
486
 
485
487
  ## Eval (#803)
@@ -693,6 +695,8 @@ vcs: gitlab
693
695
  gitlab-host: gitlab.example.com # only if remote URL doesn't expose it
694
696
  mirror: github
695
697
  cross-repos: []
698
+ cross-repo:
699
+ projects: [~/Projects/my-app] # block form (#469) — NOT the flat `cross-repos` above; INLINE list only
696
700
  pencil: path/to/design.pen # design-code alignment input
697
701
  ecosystem-health: true
698
702
  health-endpoints: []
@@ -745,6 +749,7 @@ auto-commit-per-wave: false # opt-in: commit after each wave's Qualit
745
749
  # Heavy-repo preflight & worktree hygiene (HR-003)
746
750
  heavy-repo: false # true clamps the dispatched agent count to agents-per-wave
747
751
  worktree-cleanup: default # default | aggressive
752
+ worktree-exclude: [node_modules, dist, build, .next, .nuxt, coverage, .cache, .turbo, .vercel, out] # default; top-level dirs removed from a createWorktree() worktree; null disables
748
753
 
749
754
  # Env-aware
750
755
  resource-awareness: true
@@ -780,6 +785,15 @@ vault-integration:
780
785
  vault-name: # optional (#660) — per-project vault namespace override; null/absent → deriveRepo()
781
786
  gitlab-groups: []
782
787
 
788
+ # GitLab portfolio dashboard — /portfolio (GH #41); needs vault-integration.vault-dir
789
+ gitlab-portfolio:
790
+ enabled: false # opt-in; only the literal true enables it
791
+ mode: warn # warn | strict | off
792
+ stale-days: 30 # integer ≥ 1
793
+ critical-labels: # BLOCK list only — an inline [a, b] is silently ignored
794
+ - priority::critical
795
+ - priority::high
796
+
783
797
  # Vault mirror quality thresholds
784
798
  vault-mirror:
785
799
  quality:
@@ -898,7 +912,7 @@ discovery-validator:
898
912
  dialectic:
899
913
  cadence: 5 # integer ≥ 0; 0 = kill-switch (no critique dispatches)
900
914
  model: haiku # haiku | sonnet | opus — fail-fast on unknown value
901
- budget-tokens: 8000 # integer ≥ 0 — input token budget per critique call
915
+ budget-tokens: 32000 # integer ≥ 0 — input token ceiling per critique call (aborts above, never truncates)
902
916
 
903
917
  # Eval — Standard v1 harness config surface (#809 / Epic #803)
904
918
  eval:
@@ -995,6 +1009,21 @@ config-protection:
995
1009
  mode: warn # warn | strict (strict blocks loosening, exit 2)
996
1010
  allow-config-weakening: false # per-session bypass (mirrors allow-destructive-ops)
997
1011
 
1012
+ # Orphan-process watchdog (#1425 / #1432) — DEFAULT OFF; arm only after measuring its firing rate (HR-101)
1013
+ reaper:
1014
+ enabled: false # only an explicit `true` arms it; it can send signals to processes
1015
+ mode: report # report (decide + audit only) | kill (send signals — PRD Stufe 2)
1016
+ min-age-seconds: 300 # DevWatchdog's hard limit for tsgo; the 2026-09-20 orphans were 7–17 min old
1017
+ min-scan-interval-seconds: 30 # throttle; keeps a PostToolBatch storm from taxing every tool call
1018
+ kill-grace-ms: 10000 # DEFAULT_KILL_GRACE_MS from dispatch-common.mjs:61 — repo convention
1019
+ verify-wait-ms: 500 # wait before reading the effect back (a sent signal proves nothing)
1020
+ max-hook-latency-ms: 50 # ceiling a scan may delay a hook by
1021
+ false-alarm-window: 50 # rolling window of audit decisions the HR-101 10 % rate is judged over
1022
+
1023
+ # Quality-gate path B ceiling (#1425 A3) — SO_GATE_TIMEOUT_MS still overrides this per run
1024
+ gate:
1025
+ timeout-path-b-ms: 900000 # 15 min; same cap as GATE_TIMEOUT_MS on path A
1026
+
998
1027
  # Agent mapping
999
1028
  agent-mapping:
1000
1029
  impl: code-implementer
package/docs/telemetry.md CHANGED
@@ -58,6 +58,7 @@ projection unit test enforces the drop of any non-whitelisted input field.
58
58
  | `fleet_self_declared` | Boolean, optional — the client's own claim that this send came from an operator host. **Self-declared, and the name says so on purpose:** the authoritative classification is server-side (see below). Derived from the *resolved consent state* (`enabled-fleet` from an `owner.yaml` opt-in, or `enabled-env` from `SO_TELEMETRY=1`), no longer from a raw `owner.yaml` read. |
59
59
  | `session_profile` | Optional — the STATE.md frontmatter `session-profile`, and **whitelisted profile names only** (today exactly `ultradeep`). Anything else — a value your repo invented, a client name, a typo — is **omitted from the ping entirely**: never sent verbatim, and never flattened to `other` either. A SECOND axis beside `session_type`, never a substitute for it: an ultradeep session is `session_type: "deep"` PLUS `session_profile: "ultradeep"`. **Absent when no profile is set or the profile is not on the whitelist** (the key is omitted, never `null`), including on derived pings, which never invent one. The whitelist is enforced twice — client-side before the send, and again server-side, which rejects a record carrying an unlisted profile rather than storing it. |
60
60
  | `session_record` | Optional — WHICH source the session facts in this ping came from: `ledger` (a matching `sessions.jsonl` record), `derived` (reconstructed from `events.jsonl`), `absent` (neither). When `absent`, `session_type` is `unknown` and `duration_bucket` is **not a measurement**. |
61
+ | `ledger_complete` | Optional boolean — whether the `events.jsonl` read behind a reconstruction saw every rotation archive (`true`) or measured at least one gap (`false`, e.g. a deleted archive). A SECOND axis beside `session_record`, never a fourth provenance token: it says how whole the SOURCE was, not which source was used. **Absent when nothing was measured** — no read happened, the read threw, or the facts came straight from the ledger (that path never opens `events.jsonl`). The key is omitted, never `null` and never a stand-in `false`. |
61
62
  | `session_type` | One of `housekeeping`, `feature`, `deep`, `other`, `unknown`. `other` means MEASURED but not one of the three modes; `unknown` means NOT MEASURED. Before 2026-09-06 both collapsed to `other`. |
62
63
  | `duration_bucket` | One of `<15m`, `15-60m`, `1-3h`, `>3h` — a coarse bucket, never an exact duration. |
63
64
  | `skills[]` | Names of invoked skills, filtered against the shipped plugin roster — any name not in that roster becomes `"other"`. |
@@ -359,6 +360,7 @@ generation, then drop the old one.
359
360
  | `fleet` | deprecated alias, same value | **2027-03-06** |
360
361
  | `session_record` | new (`ledger` \| `derived` \| `absent`) | — |
361
362
  | `session_profile` | new (STATE.md `session-profile`, whitelisted names only; omitted when unset or unlisted) | — |
363
+ | `ledger_complete` | new 2026-09-21 (boolean; omitted when nothing was measured, incl. every `ledger`-sourced ping) | — |
362
364
 
363
365
  Client-side the frozen whitelist is split in two: `USAGE_PING_FIELDS` (the
364
366
  REQUIRED v1 contract, which `tests/telemetry/parity.test.mjs` asserts the