session-orchestrator 3.23.0 → 4.0.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 (393) hide show
  1. package/.agents/skills/architecture/SKILL.md +18 -0
  2. package/.agents/skills/autopilot/SKILL.md +17 -0
  3. package/.agents/skills/bootstrap/SKILL.md +20 -0
  4. package/.agents/skills/brainstorm/SKILL.md +22 -0
  5. package/.agents/skills/claude-md-drift-check/SKILL.md +15 -0
  6. package/.agents/skills/convergence-monitoring/SKILL.md +22 -0
  7. package/.agents/skills/debug/SKILL.md +22 -0
  8. package/.agents/skills/discovery/SKILL.md +20 -0
  9. package/.agents/skills/dispatcher/SKILL.md +15 -0
  10. package/.agents/skills/docs-orchestrator/SKILL.md +18 -0
  11. package/.agents/skills/ecosystem-health/SKILL.md +20 -0
  12. package/.agents/skills/eli5/SKILL.md +20 -0
  13. package/.agents/skills/eval/SKILL.md +21 -0
  14. package/.agents/skills/evolve/SKILL.md +21 -0
  15. package/.agents/skills/frontmatter-guard/SKILL.md +15 -0
  16. package/.agents/skills/gitlab-ops/SKILL.md +20 -0
  17. package/.agents/skills/gitlab-portfolio/SKILL.md +15 -0
  18. package/.agents/skills/grill/SKILL.md +22 -0
  19. package/.agents/skills/hook-development/SKILL.md +15 -0
  20. package/.agents/skills/mcp-builder/SKILL.md +15 -0
  21. package/.agents/skills/memory-cleanup/SKILL.md +21 -0
  22. package/.agents/skills/mode-selector/SKILL.md +17 -0
  23. package/.agents/skills/npm-publish/SKILL.md +16 -0
  24. package/.agents/skills/peekaboo-driver/SKILL.md +18 -0
  25. package/.agents/skills/persona-panel/SKILL.md +17 -0
  26. package/.agents/skills/plan/SKILL.md +20 -0
  27. package/.agents/skills/playwright-driver/SKILL.md +20 -0
  28. package/.agents/skills/quality-gates/SKILL.md +20 -0
  29. package/.agents/skills/reconcile/SKILL.md +21 -0
  30. package/.agents/skills/remote-offload/SKILL.md +20 -0
  31. package/.agents/skills/repo-audit/SKILL.md +16 -0
  32. package/.agents/skills/session-end/SKILL.md +20 -0
  33. package/.agents/skills/session-plan/SKILL.md +20 -0
  34. package/.agents/skills/session-start/SKILL.md +20 -0
  35. package/.agents/skills/spinout/SKILL.md +16 -0
  36. package/.agents/skills/sunset-review/SKILL.md +16 -0
  37. package/.agents/skills/test-runner/SKILL.md +20 -0
  38. package/.agents/skills/tmux-layout/SKILL.md +21 -0
  39. package/.agents/skills/using-orchestrator/SKILL.md +17 -0
  40. package/.agents/skills/vault-mirror/SKILL.md +15 -0
  41. package/.agents/skills/vault-sync/SKILL.md +15 -0
  42. package/.agents/skills/wave-executor/SKILL.md +20 -0
  43. package/.agents/skills/write-executable-plan/SKILL.md +22 -0
  44. package/.claude-plugin/marketplace.json +1 -1
  45. package/.claude-plugin/plugin.json +1 -1
  46. package/.codex-plugin/plugin.json +1 -1
  47. package/.cursor/commands/autopilot.md +2 -2
  48. package/.cursor/commands/bootstrap.md +1 -1
  49. package/.cursor/commands/brainstorm.md +1 -1
  50. package/.cursor/commands/debug.md +1 -1
  51. package/.cursor/commands/discovery.md +1 -1
  52. package/.cursor/commands/dispatcher.md +2 -2
  53. package/.cursor/commands/eli5.md +2 -2
  54. package/.cursor/commands/eval.md +2 -2
  55. package/.cursor/commands/evolve.md +1 -1
  56. package/.cursor/commands/go.md +1 -1
  57. package/.cursor/commands/grill.md +2 -2
  58. package/.cursor/commands/memory-cleanup.md +2 -2
  59. package/.cursor/commands/persona-panel.md +1 -1
  60. package/.cursor/commands/plan.md +1 -1
  61. package/.cursor/commands/portfolio.md +1 -1
  62. package/.cursor/commands/reconcile.md +2 -2
  63. package/.cursor/commands/release.md +2 -2
  64. package/.cursor/commands/session.md +2 -2
  65. package/.cursor/commands/spinout.md +2 -2
  66. package/.cursor/commands/sunset-review.md +2 -2
  67. package/.cursor/commands/templates-ack.md +2 -2
  68. package/.cursor/commands/test.md +2 -2
  69. package/.cursor/skills/brainstorm/SKILL.md +1 -1
  70. package/.cursor/skills/eval/SKILL.md +1 -1
  71. package/.cursor/skills/quality-gates/SKILL.md +1 -1
  72. package/.cursor/skills/remote-offload/SKILL.md +13 -0
  73. package/.orchestrator/policy/blocked-commands.json +121 -0
  74. package/.orchestrator/policy/ecosystem.schema.json +66 -0
  75. package/.orchestrator/policy/quality-gates.example.json +16 -0
  76. package/.orchestrator/policy/quality-gates.schema.json +38 -0
  77. package/.orchestrator/policy/templates-policy.json +27 -0
  78. package/.orchestrator/policy/test-profiles.json +47 -0
  79. package/AGENTS.md +225 -0
  80. package/CHANGELOG.md +1401 -0
  81. package/NOTICE +11 -6
  82. package/README.md +127 -92
  83. package/agents/db-specialist.md +0 -1
  84. package/agents/eval-judge.md +1 -1
  85. package/agents/skill-applied-judge.md +1 -1
  86. package/assets/wave-lifecycle.svg +98 -0
  87. package/commands/release.md +6 -3
  88. package/commands/session.md +18 -3
  89. package/docs/README.md +4 -0
  90. package/{agents/AGENTS.md → docs/agent-authoring.md} +19 -26
  91. package/docs/baseline.md +67 -0
  92. package/docs/ci-setup.md +249 -48
  93. package/docs/codex-setup.md +66 -22
  94. package/docs/components.md +37 -16
  95. package/docs/cursor-setup.md +6 -2
  96. package/docs/events-schema.md +51 -10
  97. package/docs/instruction-delivery.md +62 -0
  98. package/{agents/memory-proposal-collector.md → docs/memory-proposal-flow.md} +1 -8
  99. package/docs/migration-v4.md +341 -0
  100. package/docs/pi-setup.md +6 -1
  101. package/docs/plugin-architecture-v3.md +1 -1
  102. package/docs/rule-authoring.md +85 -19
  103. package/docs/scope-collision-guard.md +8 -8
  104. package/docs/session-config-reference.md +120 -61
  105. package/docs/session-config-template.md +40 -33
  106. package/docs/telemetry/telemetry-claims.md +11 -10
  107. package/docs/telemetry.md +187 -4
  108. package/docs/vault-docs-architecture.md +50 -11
  109. package/hooks/_lib/atomic-json.mjs +111 -0
  110. package/hooks/_lib/hook-import-set.json +1487 -0
  111. package/hooks/_lib/subagent-paths.mjs +143 -0
  112. package/hooks/_lib/subagent-transcript.mjs +562 -0
  113. package/hooks/config-protection.mjs +2 -2
  114. package/hooks/cwd-change-restore.mjs +11 -31
  115. package/hooks/enforce-commands.mjs +69 -0
  116. package/hooks/enforce-scope.mjs +35 -6
  117. package/hooks/hooks-codex.json +1 -1
  118. package/hooks/hooks-cursor.json +10 -0
  119. package/hooks/hooks-pi.json +5 -0
  120. package/hooks/hooks.json +6 -1
  121. package/hooks/loop-guard.mjs +3 -3
  122. package/hooks/on-session-end.mjs +280 -14
  123. package/hooks/on-session-start.mjs +153 -4
  124. package/hooks/on-stop.mjs +371 -17
  125. package/hooks/operator-steer.mjs +2 -2
  126. package/hooks/post-bash-write-verify.mjs +189 -4
  127. package/hooks/post-edit-import-probe.mjs +344 -0
  128. package/hooks/post-subagent-discovery-validator.mjs +278 -392
  129. package/hooks/post-tool-batch-wave-signal.mjs +272 -44
  130. package/hooks/post-tool-failure-corrective-context.mjs +11 -34
  131. package/hooks/post-tooluse-frontend-slop.mjs +3 -3
  132. package/hooks/pre-bash-destructive-guard.mjs +39 -13
  133. package/hooks/pre-bash-memory-propose-audit.mjs +13 -7
  134. package/hooks/skill-invocation-telemetry.mjs +17 -5
  135. package/hooks/subagent-telemetry.mjs +24 -30
  136. package/monitors/monitors.json +3 -3
  137. package/package.json +9 -1
  138. package/pi/prompts/session.md +2 -2
  139. package/plugin.json +27 -0
  140. package/scripts/autopilot.mjs +26 -12
  141. package/scripts/backfill-abandoned-sessions.mjs +130 -15
  142. package/scripts/backfill-learnings-from-vault.mjs +9 -3
  143. package/scripts/dialectic-deriver.mjs +73 -8
  144. package/scripts/emit-event.mjs +10 -2
  145. package/scripts/export-hw-learnings.mjs +113 -1
  146. package/scripts/generate-agents-skills.mjs +378 -0
  147. package/scripts/generate-cursor-adapter.mjs +45 -8
  148. package/scripts/generate-hook-import-set.mjs +249 -0
  149. package/scripts/lib/agent-status.mjs +13 -2
  150. package/scripts/lib/auq/parse.mjs +5 -29
  151. package/scripts/lib/auto-dialectic.mjs +68 -0
  152. package/scripts/lib/auto-dream.mjs +38 -36
  153. package/scripts/lib/autonomy/suitability.mjs +6 -0
  154. package/scripts/lib/autopilot/loop.mjs +2 -2
  155. package/scripts/lib/autopilot/worktree-pipeline.mjs +82 -6
  156. package/scripts/lib/build-live-signals.mjs +25 -22
  157. package/scripts/lib/ci-status-banner.mjs +220 -75
  158. package/scripts/lib/codex/plugin-contract.mjs +82 -6
  159. package/scripts/lib/cold-start-detector.mjs +23 -14
  160. package/scripts/lib/config/auto-dream.mjs +2 -1
  161. package/scripts/lib/config/block-header.mjs +63 -0
  162. package/scripts/lib/config/block-preprocess.mjs +177 -0
  163. package/scripts/lib/config/broken-window.mjs +2 -1
  164. package/scripts/lib/config/cold-start.mjs +2 -1
  165. package/scripts/lib/config/config-protection.mjs +22 -2
  166. package/scripts/lib/config/context-coverage.mjs +2 -1
  167. package/scripts/lib/config/cross-repo.mjs +2 -1
  168. package/scripts/lib/config/custom-phases.mjs +2 -1
  169. package/scripts/lib/config/dialectic.mjs +2 -1
  170. package/scripts/lib/config/discovery-validator.mjs +9 -3
  171. package/scripts/lib/config/dispatcher-autonomy-capture.mjs +24 -1
  172. package/scripts/lib/config/dispatcher-autonomy.mjs +2 -1
  173. package/scripts/lib/config/docs-orchestrator.mjs +2 -1
  174. package/scripts/lib/config/docs-staleness.mjs +2 -1
  175. package/scripts/lib/config/drift-check.mjs +2 -1
  176. package/scripts/lib/config/eval.mjs +2 -1
  177. package/scripts/lib/config/events-rotation.mjs +2 -1
  178. package/scripts/lib/config/evolve.mjs +8 -2
  179. package/scripts/lib/config/frontend-slop-hook.mjs +7 -3
  180. package/scripts/lib/config/gitlab-portfolio.mjs +2 -1
  181. package/scripts/lib/config/handover-gate.mjs +2 -1
  182. package/scripts/lib/config/health-endpoints.mjs +388 -0
  183. package/scripts/lib/config/issue-budget.mjs +2 -1
  184. package/scripts/lib/config/loop-guard.mjs +2 -1
  185. package/scripts/lib/config/memory.mjs +2 -1
  186. package/scripts/lib/config/moc-staleness.mjs +2 -1
  187. package/scripts/lib/config/persona-gate-wave.mjs +2 -1
  188. package/scripts/lib/config/private-config-dir.mjs +67 -0
  189. package/scripts/lib/config/reconcile.mjs +2 -1
  190. package/scripts/lib/config/remote-hosts.mjs +234 -0
  191. package/scripts/lib/config/section-extractor.mjs +7 -1
  192. package/scripts/lib/config/skill-evolution.mjs +2 -1
  193. package/scripts/lib/config/slopcheck.mjs +2 -1
  194. package/scripts/lib/config/state-md-lock.mjs +2 -1
  195. package/scripts/lib/config/templates-first.mjs +2 -1
  196. package/scripts/lib/config/test.mjs +2 -1
  197. package/scripts/lib/config/vault-integration.mjs +7 -1
  198. package/scripts/lib/config/vault-mirror-quality.mjs +2 -1
  199. package/scripts/lib/config/vault-staleness.mjs +2 -1
  200. package/scripts/lib/config/vault-sync.mjs +2 -1
  201. package/scripts/lib/config/verification-auto-fix.mjs +2 -1
  202. package/scripts/lib/config/wave-reviewers.mjs +2 -1
  203. package/scripts/lib/config/worktree-orphans.mjs +2 -1
  204. package/scripts/lib/config.mjs +31 -3
  205. package/scripts/lib/convergence-monitor.mjs +82 -16
  206. package/scripts/lib/dispatcher/enumerate.mjs +2 -17
  207. package/scripts/lib/dispatcher/rank.mjs +124 -48
  208. package/scripts/lib/ecosystem-health.mjs +16 -2
  209. package/scripts/lib/eval/engine.mjs +9 -1
  210. package/scripts/lib/eval/session-resolve.mjs +23 -4
  211. package/scripts/lib/events-schema.mjs +48 -0
  212. package/scripts/lib/events.mjs +256 -7
  213. package/scripts/lib/evolve/autonomy-verdict.mjs +9 -4
  214. package/scripts/lib/evolve/autopilot-effectiveness.mjs +18 -1
  215. package/scripts/lib/frontmatter-guard.mjs +131 -13
  216. package/scripts/lib/gates/gate-full.mjs +26 -0
  217. package/scripts/lib/gates/gate-helpers.mjs +76 -0
  218. package/scripts/lib/gitlab-portfolio/cli.mjs +3 -15
  219. package/scripts/lib/hardware-pattern-detector.mjs +18 -1
  220. package/scripts/lib/harness-audit/categories/category1.mjs +17 -6
  221. package/scripts/lib/harness-audit/categories/category4.mjs +31 -11
  222. package/scripts/lib/host-identity.mjs +50 -11
  223. package/scripts/lib/instruction-budget-guard.mjs +171 -5
  224. package/scripts/lib/learnings/evolve-telemetry.mjs +178 -0
  225. package/scripts/lib/learnings/io.mjs +60 -6
  226. package/scripts/lib/memory-banner.mjs +20 -8
  227. package/scripts/lib/memory-proposals/store.mjs +30 -22
  228. package/scripts/lib/owner-config-banner.mjs +43 -6
  229. package/scripts/lib/owner-config-loader.mjs +21 -10
  230. package/scripts/lib/owner-interview.mjs +3 -3
  231. package/scripts/lib/owner-yaml.mjs +207 -14
  232. package/scripts/lib/peer-discovery.mjs +20 -2
  233. package/scripts/lib/platform.mjs +108 -15
  234. package/scripts/lib/plugin-update-banner.mjs +406 -0
  235. package/scripts/lib/project-hygiene.mjs +38 -2
  236. package/scripts/lib/qg-command-drift-banner.mjs +50 -12
  237. package/scripts/lib/quality-gate.mjs +133 -44
  238. package/scripts/lib/reconcile/emitter.mjs +68 -6
  239. package/scripts/lib/reconcile/engine.mjs +249 -9
  240. package/scripts/lib/reconcile/idempotency.mjs +37 -4
  241. package/scripts/lib/reconcile/writer.mjs +40 -18
  242. package/scripts/lib/scope-gate.mjs +36 -0
  243. package/scripts/lib/session-close-backfill.mjs +125 -18
  244. package/scripts/lib/session-discovery.mjs +57 -3
  245. package/scripts/lib/session-end/phase-skip.mjs +2 -2
  246. package/scripts/lib/session-id.mjs +12 -23
  247. package/scripts/lib/session-identity/own-session.mjs +187 -11
  248. package/scripts/lib/session-lock-shape.mjs +43 -0
  249. package/scripts/lib/session-lock.mjs +5 -10
  250. package/scripts/lib/session-registry.mjs +25 -9
  251. package/scripts/lib/session-schema/constants.mjs +36 -2
  252. package/scripts/lib/session-schema/validator.mjs +38 -4
  253. package/scripts/lib/session-start-probes.mjs +18 -1
  254. package/scripts/lib/session-transition.mjs +1 -1
  255. package/scripts/lib/sessions-canonical.mjs +446 -0
  256. package/scripts/lib/sessions-staleness-banner.mjs +18 -11
  257. package/scripts/lib/skill-health/join.mjs +17 -4
  258. package/scripts/lib/state-md.mjs +78 -0
  259. package/scripts/lib/sunset/walker.mjs +6 -0
  260. package/scripts/lib/telemetry/schema.mjs +255 -17
  261. package/scripts/lib/telemetry/sync.mjs +417 -24
  262. package/scripts/lib/tmux-layout/telemetry.mjs +14 -2
  263. package/scripts/lib/validate/check-agents-skills.mjs +327 -0
  264. package/scripts/lib/validate/check-agents.mjs +3 -3
  265. package/scripts/lib/validate/check-cursor-adapter.mjs +234 -72
  266. package/scripts/lib/validate/check-doc-cli-commands.mjs +9 -33
  267. package/scripts/lib/validate/check-hooks-emit-event-guard.mjs +370 -0
  268. package/scripts/lib/validate/check-hooks-symmetry.mjs +45 -16
  269. package/scripts/lib/validate/check-owner-leakage.mjs +281 -20
  270. package/scripts/lib/validate/check-skill-links.mjs +163 -0
  271. package/scripts/lib/validate/check-skill-script-paths.mjs +455 -0
  272. package/scripts/lib/validate/check-untracked-test-deps.mjs +10 -0
  273. package/scripts/lib/validate/check-unwired-features.mjs +0 -9
  274. package/scripts/lib/validate/check-validator-registration.mjs +254 -0
  275. package/scripts/lib/validate/check-vcs-repo-flag.mjs +6 -28
  276. package/scripts/lib/validate/enumerate-repo-files.mjs +317 -0
  277. package/scripts/lib/validate/markdown-fences.mjs +196 -0
  278. package/scripts/lib/vault-backfill/template.mjs +63 -6
  279. package/scripts/lib/vault-mirror/process.mjs +165 -42
  280. package/scripts/lib/vault-mirror/telemetry.mjs +2 -2
  281. package/scripts/lib/vault-status/board-lock.mjs +185 -0
  282. package/scripts/lib/vault-status/board-writer.mjs +174 -135
  283. package/scripts/lib/vault-status/narrative-mirror.mjs +129 -37
  284. package/scripts/lib/wave-executor/dispatch-common.mjs +164 -0
  285. package/scripts/lib/wave-executor/foreign-dispatch.mjs +7 -142
  286. package/scripts/lib/wave-executor/remote-dispatch.mjs +502 -0
  287. package/scripts/lib/wave-resource-gate.mjs +133 -7
  288. package/scripts/lib/wave-sizing.mjs +4 -1
  289. package/scripts/lib/wave-transcript-tail.mjs +142 -8
  290. package/scripts/materialize-wave-scope.mjs +32 -9
  291. package/scripts/memory-propose.mjs +146 -8
  292. package/scripts/migrate-cold-start-seed.mjs +4 -1
  293. package/scripts/parse-config.mjs +60 -3
  294. package/scripts/promote-vault-strict.mjs +4 -15
  295. package/scripts/release.mjs +337 -29
  296. package/scripts/repair-invalid-sessions.mjs +3 -3
  297. package/scripts/run-quality-gate.mjs +128 -11
  298. package/scripts/site-numbers.mjs +36 -4
  299. package/scripts/sweep-expired-learnings.mjs +90 -0
  300. package/scripts/sync-vault-schema.mjs +3 -1
  301. package/scripts/telemetry.mjs +2 -2
  302. package/scripts/validate-plugin.mjs +187 -0
  303. package/scripts/validate-wave-scope.mjs +28 -8
  304. package/scripts/vault-consolidate.mjs +3 -11
  305. package/scripts/vault-integration-watcher.mjs +2 -4
  306. package/scripts/vault-mirror.mjs +111 -26
  307. package/scripts/wave-scope-binding.mjs +215 -0
  308. package/skills/_shared/instruction-file-resolution.md +10 -0
  309. package/skills/_shared/parallel-aware-auq.md +31 -2
  310. package/skills/_shared/parallel-aware-preamble.md +18 -4
  311. package/skills/_shared/platform-tools.md +1 -1
  312. package/skills/_shared/state-ownership.md +1 -1
  313. package/skills/architecture/SKILL.md +7 -5
  314. package/skills/{domain-model/SKILL.md → architecture/references/domain-model.md} +9 -9
  315. package/skills/autopilot/SKILL.md +4 -18
  316. package/skills/claude-md-drift-check/SKILL.md +5 -1
  317. package/skills/claude-md-drift-check/checker.mjs +62 -2
  318. package/skills/convergence-monitoring/SIGNALS.md +55 -0
  319. package/skills/discovery/probes/vault-staleness.mjs +37 -13
  320. package/skills/discovery/probes-arch.md +20 -18
  321. package/skills/dispatcher/SKILL.md +3 -2
  322. package/skills/ecosystem-health/SKILL.md +4 -1
  323. package/skills/ecosystem-health/wizard.md +5 -0
  324. package/skills/evolve/SKILL.md +87 -11
  325. package/skills/frontmatter-guard/SKILL.md +11 -5
  326. package/skills/npm-publish/SKILL.md +1 -1
  327. package/skills/reconcile/SKILL.md +38 -2
  328. package/skills/remote-offload/SKILL.md +89 -0
  329. package/skills/session-end/SKILL.md +18 -905
  330. package/skills/session-end/phase-3-6-tail.md +19 -9
  331. package/skills/session-end/plan-verification.md +221 -155
  332. package/skills/session-end/references/phase-2-quality-gate.md +93 -0
  333. package/skills/session-end/references/phase-3-documentation-updates.md +229 -0
  334. package/skills/session-end/references/phase-4a-worktree-cleanup.md +120 -0
  335. package/skills/session-end/references/phase-4b-worktree-orphan-sweep.md +58 -0
  336. package/skills/session-end/references/phase-5-issue-cleanup.md +104 -0
  337. package/skills/session-end/references/session-summary-template.md +62 -0
  338. package/skills/session-plan/SKILL.md +49 -0
  339. package/skills/session-start/SKILL.md +41 -900
  340. package/skills/session-start/phase-8-5-express-path.md +1 -1
  341. package/skills/session-start/references/phase-1-1-dispatcher-autonomy-capture.md +55 -0
  342. package/skills/session-start/references/phase-1-2-session-lock.md +140 -0
  343. package/skills/session-start/references/phase-1-5-session-continuity.md +254 -0
  344. package/skills/session-start/references/phase-1-7-vault-status-board.md +53 -0
  345. package/skills/session-start/references/phase-2-7-portfolio-snapshot.md +75 -0
  346. package/skills/session-start/references/phase-4-ssot-environment-check.md +155 -0
  347. package/skills/session-start/references/phase-6-5-forced-reads.md +75 -0
  348. package/skills/session-start/references/phase-6-6-project-intelligence.md +81 -0
  349. package/skills/session-start/references/phase-6-7-memory-banner-telemetry-consent.md +103 -0
  350. package/skills/vault-sync/validator.mjs +21 -27
  351. package/skills/wave-executor/SKILL.md +16 -2
  352. package/skills/wave-executor/references/wave-loop-dispatch.md +612 -0
  353. package/skills/wave-executor/references/wave-loop-review.md +570 -0
  354. package/skills/wave-executor/references/wave-loop-scope-manifest.md +162 -0
  355. package/skills/wave-executor/wave-loop.md +14 -1271
  356. package/templates/_shared/journey-manifest.md +10 -6
  357. package/.cursor/commands/autopilot-multi.md +0 -14
  358. package/.cursor/commands/contract-version-bump.md +0 -14
  359. package/.cursor/commands/journey-audit.md +0 -14
  360. package/.cursor/skills/contract-version-bump/SKILL.md +0 -12
  361. package/.cursor/skills/daily/SKILL.md +0 -12
  362. package/.cursor/skills/domain-model/SKILL.md +0 -13
  363. package/.cursor/skills/journey-audit/SKILL.md +0 -13
  364. package/.cursor/skills/skill-creator/SKILL.md +0 -13
  365. package/.cursor/skills/ubiquitous-language/SKILL.md +0 -13
  366. package/commands/autopilot-multi.md +0 -74
  367. package/commands/contract-version-bump.md +0 -28
  368. package/commands/journey-audit.md +0 -43
  369. package/pi/prompts/autopilot-multi.md +0 -12
  370. package/pi/prompts/contract-version-bump.md +0 -12
  371. package/pi/prompts/journey-audit.md +0 -12
  372. package/scripts/autopilot-multi.mjs +0 -885
  373. package/scripts/backfill-learnings-expires.mjs +0 -196
  374. package/scripts/backfill-learnings.mjs +0 -203
  375. package/scripts/fleet-instruction-scan.mjs +0 -141
  376. package/scripts/lib/autopilot/dep-graph.mjs +0 -417
  377. package/scripts/lib/autopilot/multi-killswitch.mjs +0 -184
  378. package/scripts/lib/webhook-url.mjs +0 -105
  379. package/scripts/lifecycle-sim-v6.mjs +0 -347
  380. package/scripts/migrate-learnings-jsonl.mjs +0 -189
  381. package/scripts/migrate-subagents-jsonl.mjs +0 -196
  382. package/scripts/upload-social-preview.mjs +0 -316
  383. package/skills/_shared/model-selection.md +0 -64
  384. package/skills/contract-version-bump/SKILL.md +0 -219
  385. package/skills/daily/SKILL.md +0 -222
  386. package/skills/daily/generate.sh +0 -92
  387. package/skills/daily/templates/daily.md.tpl +0 -36
  388. package/skills/journey-audit/SKILL.md +0 -269
  389. package/skills/skill-creator/SKILL.md +0 -168
  390. package/skills/ubiquitous-language/SKILL.md +0 -97
  391. package/skills/vault-sync/package-lock.json +0 -40
  392. /package/skills/{domain-model → architecture/references}/ADR-FORMAT.md +0 -0
  393. /package/skills/{domain-model → architecture/references}/CONTEXT-FORMAT.md +0 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
- description: Start a development session (housekeeping, feature, deep)
3
- argument-hint: "[housekeeping|feature|deep]"
2
+ description: Start a development session (housekeeping, feature, deep; ultradeep = deep + profile)
3
+ argument-hint: "[housekeeping|feature|deep|ultradeep]"
4
4
  ---
5
5
 
6
6
  # Session Start
@@ -9,7 +9,22 @@ You are beginning a new development session. The user has invoked `/session` wit
9
9
 
10
10
  **Default rationale (measured, not assumed):** `deep` is the default because it is what operators actually run — 77.3 % of 489 recorded sessions across 5 repos, and 115 of 228 (50.4 %) in this repo's own `.orchestrator/metrics/sessions.jsonl`. The former `feature` default made the majority case the one that had to be typed out every time. A `deep` default costs a downgrade keystroke in the minority case; a `feature` default cost an upgrade keystroke in the majority case.
11
11
 
12
- **Argument validation:** Valid session types are `housekeeping`, `feature`, and `deep`. An explicit `$ARGUMENTS` value ALWAYS wins over the default — `/session housekeeping` and `/session feature` behave exactly as before. If `$ARGUMENTS` is not empty and does not match any valid type, inform the user: "Invalid session type '$ARGUMENTS'. Valid types: housekeeping, feature, deep." Then fall back to `deep`.
12
+ **Argument validation:** Valid session types are `housekeeping`, `feature`, and `deep`. An explicit `$ARGUMENTS` value ALWAYS wins over the default — `/session housekeeping` and `/session feature` behave exactly as before. `ultradeep` is additionally accepted as an ARGUMENT ALIAS (see below); it is not a fourth type. If `$ARGUMENTS` is not empty and does not match any valid type or the alias, inform the user: "Invalid session type '$ARGUMENTS'. Valid types: housekeeping, feature, deep (alias: ultradeep)." Then fall back to `deep`.
13
+
14
+ ### Argument alias: `ultradeep` (PRD `docs/prd/2026-09-06-ultradeep-session-profile.md`)
15
+
16
+ `/session ultradeep` is an alias, NOT a fourth `session_type`. Resolve it to TWO STATE.md frontmatter values and then continue exactly as a `deep` session would:
17
+
18
+ ```yaml
19
+ session-type: deep # what every downstream consumer sees
20
+ session-profile: ultradeep # the only place the alias survives
21
+ ```
22
+
23
+ - **`session-type` NEVER becomes `ultradeep`.** The value is a closed set in `scripts/lib/session-schema/constants.mjs` (`VALID_SESSION_TYPES`) and in `scripts/lib/wave-sizing.mjs`; a fourth member would degrade silently in two places (`scripts/lib/telemetry/schema.mjs` maps an unknown type to `"other"`, `scripts/lib/session-close-backfill.mjs` labels it `housekeeping`). The alias exists so that no closed set has to change.
24
+ - **`session-profile` is optional and absent by default.** A plain `/session deep` writes NO `session-profile` key. Absent means "no profile" — never write an empty string, `none`, or `null` to mean absence. Read/write helpers: `readSessionProfile` / `setSessionProfile` in `scripts/lib/state-md.mjs`.
25
+ - **What the profile changes** is the WAVE SHAPE, not the session type: 7 waves with a coordinator-direct Synthesis-Gate at wave 2. See `skills/session-plan/SKILL.md` § Role-to-Wave Mapping and `skills/wave-executor/SKILL.md` § Ultradeep Profile.
26
+ - **Precondition.** The profile needs 7 waves. If Session Config sets `waves` below 7, do NOT silently plan 5 waves under an ultradeep label — name the conflict to the user and let them raise `waves` or drop the alias.
27
+ - **Budgets are deliberately not implemented yet** (PRD § 7): no `ultradeep.max-*` key is read anywhere. Do not invent one; the PRD defers thresholds until three runs have been measured.
13
28
 
14
29
  > **Not read from Session Config.** There is deliberately no `session-type:` (or equivalent) key in the `## Session Config` block — `scripts/lib/config.mjs` `parseSessionConfig()` does not emit one, so any such key in a repo's CLAUDE.md (or its Codex CLI equivalent AGENTS.md) is inert prose. The `session-type:` scalar that IS live lives in STATE.md frontmatter (read by `scripts/print-applicable-rules.mjs` for rule mode-gating) and is written per session, not configured per repo. Do not reintroduce a Session Config key here without wiring it into the parser first.
15
30
 
package/docs/README.md CHANGED
@@ -98,6 +98,10 @@ Two things worth knowing about this split:
98
98
  | `docs/plans/` | Active work document | `/write-executable-plan` artifacts for in-progress work. May not exist when nothing is mid-plan. |
99
99
  | `docs/_private/`, `docs/specs/` | Local-only (gitignored) | Operator scratch space; never tracked, out of scope for this classification. |
100
100
 
101
+ ### Superseded design notes
102
+
103
+ Because `docs/specs/` is gitignored, a correction written INTO a spec can never be committed — so the correction lives here instead. `docs/specs/2026-05-26-parallel-aware-sessions-design.md` (parallel-aware sessions) specifies PID-based lock liveness (`stale-pid-dead`). That is **superseded**: liveness is heartbeat-age based since #1137 (`isLockLive`; `acquire()` knows only `stale-heartbeat`), and the recorded PID is consulted nowhere since #1151 — it was the PID of the short-lived subprocess that wrote the lock, dead within a second. Read the local spec only with that correction applied.
104
+
101
105
  ## See Also
102
106
 
103
107
  - `docs/prd/2026-07-08-docs-public-split.md` — the epic that established this split (S1–S8, issues #775–#782).
@@ -1,37 +1,30 @@
1
- ---
2
- name: agents-authoring-spec
3
- description: NOT A DISPATCHABLE AGENT — never select this. It is the authoring specification that the agent definitions in this directory must follow, loaded as a nested instruction file. Claude Code's plugin loader registers every agents/*.md as an agent by directory convention, and the manifest's `agents` key is additive-only, so it cannot exclude a path. Without this frontmatter the file registered as an unnamed agent with FULL tool access; the minimal `tools` line below is what bounds that. If you need agent-authoring rules, read this file — do not dispatch it.
4
- tools: Read
5
- ---
1
+ <!-- Moved in v4.0.0 from `agents/AGENTS.md` (audit 2026-09-06 § 5A). It never was an agent: Claude Code's plugin loader registers every `agents/*.md` by directory convention and the manifest's `agents` key is additive-only, so no manifest entry could exclude it — only pseudo-frontmatter (`name: agents-authoring-spec`, `tools: Read`) kept the false registration bounded. Living under `docs/` removes the registration instead of bounding it. -->
6
2
 
7
- # `agents/` — Sub-Agent Authoring Conventions
3
+ # Sub-Agent Authoring Conventions (`agents/**`)
8
4
 
9
- > Nested instruction file for the `agents/` subtree. Claude Code / Cursor IDE
10
- > and Codex CLI both load this additively when working on files in this
11
- > directory (root `CLAUDE.md` for the big picture, this file for local
12
- > conventions). Resolution rule:
5
+ > Authoring spec for the sub-agent definitions in `agents/`. Read it together
6
+ > with the root `CLAUDE.md` (big picture) and, when working under `agents/`,
7
+ > whatever nested instruction file that subtree carries. Resolution rule:
13
8
  > [`../skills/_shared/instruction-file-resolution.md`](../skills/_shared/instruction-file-resolution.md).
14
9
  >
15
- > This is **not** an agent definition it is the authoring spec the agent
16
- > `*.md` definitions in this directory must follow. The plugin validator
17
- > (`scripts/lib/validate/check-agents.mjs`) excludes `AGENTS.md` / `CLAUDE.md`
18
- > from agent-frontmatter validation by name, and `measureDescriptionSurface`
19
- > excludes them from its walked corpus (#878).
20
- >
21
- > **Claude Code's plugin loader makes no such exception.** It registers every
22
- > `agents/*.md` as a dispatchable agent by directory convention, and the
23
- > manifest's `agents` key is documented as *additive* ("in addition to those in
24
- > the `agents/` directory"), so it cannot exclude a path. With no frontmatter
25
- > this file therefore registered as an agent named `AGENTS` with **full tool
26
- > access**. The frontmatter above is the containment: it names the file for what
27
- > it is, states in the `description` that it must never be dispatched, and caps
28
- > `tools` at `Read`. Do not remove it — and if you add another non-agent doc to
29
- > this directory, give it the same treatment.
10
+ > **This spec lives in `docs/`, not in `agents/`, on purpose.** Claude Code's
11
+ > plugin loader registers every `agents/*.md` as a dispatchable agent by
12
+ > directory convention, and the manifest's `agents` key is documented as
13
+ > *additive* ("in addition to those in the `agents/` directory"), so it cannot
14
+ > exclude a path. As `agents/AGENTS.md` this file was therefore a registered
15
+ > agent — first an unnamed one with **full tool access**, later a contained one
16
+ > whose pseudo-frontmatter capped `tools` at `Read`. Moving it out of the
17
+ > directory removes the registration rather than bounding it. The same applies
18
+ > to any future non-agent doc: put it under `docs/`, never in `agents/`.
19
+ > (`scripts/lib/validate/check-agents.mjs` still excludes `AGENTS.md` /
20
+ > `CLAUDE.md` by name, and `measureDescriptionSurface` still excludes them from
21
+ > its walked corpus (#878) both now vacuous for this file, and the safety net
22
+ > for anyone who reintroduces one.)
30
23
  >
31
24
  > Sibling spec: for `.claude/rules/*.md` frontmatter (conditional loading via
32
25
  > globs/mode/host-class/expiry, plus the never-always-on invariant for
33
26
  > auto-generated rules), see the canonical authoring spec
34
- > [`docs/rule-authoring.md`](../docs/rule-authoring.md).
27
+ > [`docs/rule-authoring.md`](./rule-authoring.md).
35
28
 
36
29
  ## Local Validation Commands
37
30
 
@@ -0,0 +1,67 @@
1
+ # The projects-baseline Relationship
2
+
3
+ **One line:** `projects-baseline` is a **private, optional** companion repository that
4
+ holds the operator's canonical rule and schema corpus. session-orchestrator reads
5
+ from it when it is present and degrades to a documented fallback when it is not.
6
+ Nothing in this plugin requires it, and no public consumer needs to obtain it.
7
+
8
+ ## What it is
9
+
10
+ A separate git repository (not vendored, not a submodule, not on npm) carrying:
11
+
12
+ - `packages/zod-schemas/src/vault-frontmatter.ts` — the canonical Zod schema for
13
+ Obsidian vault note frontmatter.
14
+ - `templates/shared/.vault.yaml.template` — the canonical `.vault.yaml` template.
15
+ - A `.claude/rules/` corpus. Measured: **26 rule files, all using `paths:`
16
+ frontmatter, 0 using `globs:`** (`scripts/lib/rule-loader.mjs` module doc;
17
+ restated in `scripts/lib/validate/check-rules.mjs`). That corpus is the reason
18
+ `paths:` exists as a same-shape alias for `globs:` at all (#795) — the fleet's
19
+ rules are read **from the baseline**, not from this plugin, so the plugin had to
20
+ learn the baseline's frontmatter convention rather than the other way round.
21
+
22
+ ## How the plugin finds it
23
+
24
+ Never by a hardcoded path. Resolution is host-local, most specific first:
25
+
26
+ 1. `SO_BASELINE_PATH` environment variable
27
+ 2. `owner.yaml` `paths.baseline-path` (`~/.config/session-orchestrator/owner.yaml`,
28
+ host-local, never committed — see `docs/owner-config-schema.md`)
29
+ 3. a sibling checkout at `<repoRoot>/../projects-baseline`
30
+ 4. `~/Projects/projects-baseline` (legacy default)
31
+
32
+ Tiers 1–2 go through `resolveHostPath('baseline-path', …)` in
33
+ `scripts/lib/config/host-paths.mjs`. `scripts/lib/vault-backfill/template.mjs`
34
+ additionally honours `PROJECTS_BASELINE_DIR` above all four, for back-compat.
35
+
36
+ ## The four hard-runtime touchpoints, and what each degrades to
37
+
38
+ | Touchpoint | Reads / writes | Without a baseline |
39
+ |---|---|---|
40
+ | `scripts/lib/frontmatter-guard.mjs` | the canonical vault-frontmatter Zod schema | `readVaultSchema()` → `null`; `generateFrontmatterSnippet()` falls back to an in-module enum set mirroring `skills/vault-sync/validator.mjs` and warns ONCE on stderr; `computeSchemaHash()` → `null` (never the empty-string hash) |
41
+ | `scripts/lib/vault-backfill/template.mjs` | `.vault.yaml.template` | `loadTemplate()` calls `dieFn(2, …)` with a message naming `owner.yaml paths.baseline-path`, `SO_BASELINE_PATH`, `PROJECTS_BASELINE_DIR`, and the sibling-checkout convention. Only `scripts/vault-backfill.mjs` is affected; nothing else aborts |
42
+ | `scripts/sync-vault-schema.mjs` | `--check` drift guard against the canonical schema | exits 2 (missing file). It is a maintenance script, never on a session path |
43
+ | `scripts/lib/reconcile/writer.mjs` + `scripts/lib/session-end/phase-skip.mjs` | writes rule proposals into the baseline (`reconcile.targets` containing `baseline`) | `baselineRoot` absent ⇒ the `baseline` target is a **no-op**; `repo-local` (the default target) is unaffected |
44
+
45
+ `scripts/promote-vault-strict.mjs` also uses a baseline template and already ships
46
+ an explicit `--no-baseline` opt-out.
47
+
48
+ ## The public fallback
49
+
50
+ A repository bootstrapped without the baseline is a normal, supported outcome —
51
+ `skills/bootstrap/public-fallback.md` owns that path. `bootstrap.lock` records
52
+ which source produced the scaffold in its `source:` field:
53
+
54
+ - `claude-init` — `claude init` ran successfully (Claude Code fast path)
55
+ - `plugin-template` — the plugin's own template was copied (every other case)
56
+ - `projects-baseline` — the private baseline was present and used
57
+
58
+ The first two are the **public** values. A consumer repo that shows either is
59
+ fully bootstrapped; the baseline adds the operator's private corpus on top, it
60
+ does not gate the scaffold.
61
+
62
+ ## See also
63
+
64
+ - `docs/owner-config-schema.md` — `owner.yaml` schema, including `paths.baseline-path`
65
+ - `docs/rule-authoring.md` — `paths:` / `globs:` frontmatter
66
+ - `skills/bootstrap/public-fallback.md` — the no-baseline bootstrap path
67
+ - `skills/frontmatter-guard/SKILL.md` — the schema-source resolution table
package/docs/ci-setup.md CHANGED
@@ -14,25 +14,124 @@ project-level Job Token allowlists are explicitly configured — an admin action
14
14
  in the foreign project that cannot be scripted from here. The fix is a deploy
15
15
  token or PAT stored as the masked CI variable `SCHEMA_DRIFT_TOKEN`.
16
16
 
17
- > **Current decision (2026-08-28, #1062): amber is the accepted normal state.**
18
- > `glab variable list` on this project returns zero CI variables — no
19
- > `SCHEMA_DRIFT_TOKEN` is set so every pipeline runs the job to exit 3
20
- > (`NOT VERIFIED`) and `pipeline-gate` prints the amber line. This is a
21
- > deliberate operator choice, not a defect: the job is correctly fail-loud
22
- > (exit taxonomy below), the vendored schema is compared manually at each
23
- > baseline refresh (#1100), and no token is rotated for a check that runs
24
- > against a private project of our own. Session-start's CI banner keeps
25
- > reporting the soft failure on purpose (`allow_failure` jobs are invisible
26
- > at pipeline level, which is what that banner exists to surface). Revisit
27
- > trigger: the first time a vendored-schema drift ships unnoticed, or when
28
- > the baseline gains a public mirror then set the token (Option A below)
29
- > and flip `SCHEMA_DRIFT_OPTIONAL` at both sites.
17
+ > **Armed (2026-09-03, #1175): the hard gate is live.** #531 landed upstream
18
+ > `infrastructure/projects-baseline` commit `cb9ec97` adds `peer-card`,
19
+ > `board`, and `source-repo` to the canonical schema (the issue's AC named
20
+ > only `peer-card`; the close comment widened scope to all three values
21
+ > already vendored ahead here). That closed the vendored-schema divergence
22
+ > which had blocked activation since 2026-09-02; `skills/vault-sync/
23
+ > validator.mjs` was regenerated and `node scripts/sync-vault-schema.mjs
24
+ > --check` now exits 0. The Project Access Token was re-minted (id 53, see
25
+ > § Activation status below), the masked `SCHEMA_DRIFT_TOKEN` CI variable is
26
+ > set on this project, and `SCHEMA_DRIFT_OPTIONAL` is `"false"` at both
27
+ > sites in `.gitlab-ci.yml` a missing or expired token now hard-fails the
28
+ > pipeline (exit 4) instead of printing the amber `NOT VERIFIED` line that
29
+ > was the accepted state under the prior (2026-08-28, #1062) decision. Both
30
+ > directions were proven before the flip — see below. Revisit trigger for
31
+ > the token itself: expiry (2027-09-01) or a scope/rotation need — see
32
+ > § Rotation / re-arm sequence.
33
+
34
+ ### Activation status (token re-minted 2026-09-03, id 53)
35
+
36
+ The Project Access Token was revoked on 2026-09-02 once a control run had
37
+ answered the question it was minted for — an unused credential is a
38
+ liability per SEC-005's secrets-lifecycle discipline. That control run had
39
+ also surfaced the real reason activation was still blocked:
40
+ `skills/vault-sync/validator.mjs`'s `vaultNoteTypeSchema` enum carried
41
+ `peer-card` and `board`, and `vaultFrontmatterSchema` carried
42
+ `source-repo: z.string().optional()`, none of which the canonical
43
+ `infrastructure/projects-baseline` source had yet — the documented
44
+ vendor-ahead state (`scripts/sync-vault-schema.mjs` header, "Vendor-ahead
45
+ state (2026-05-23, #503, I5)"), tracked as upstream-sync-debt in issue #531
46
+ (#503 itself was already closed).
47
+
48
+ **#531 landed upstream** as commit `cb9ec97`: `vaultNoteTypeSchema` gained
49
+ `peer-card` and `board`; `vaultFrontmatterSchema` gained `source-repo:
50
+ z.string().optional()`. With the canonical source caught up,
51
+ `node scripts/sync-vault-schema.mjs --check` exits 0 — no drift.
52
+
53
+ **Token, re-minted:**
54
+
55
+ - **Name:** `session-orchestrator-ci-schema-drift`
56
+ - **Project:** `infrastructure/projects-baseline` (id 52) — the TARGET repo,
57
+ not this one
58
+ - **Token id:** 53
59
+ - **Scopes:** `read_repository`
60
+ - **Access level:** Reporter (20)
61
+ - **Expires:** 2027-09-01
62
+
63
+ The masked `SCHEMA_DRIFT_TOKEN` CI variable is set on this project (id 74),
64
+ **not** Protected — same reasoning as Option A step 3 below.
65
+
66
+ **Proof pipelines, both directions, run before the flip:**
67
+
68
+ - **GREEN** — pipeline 8358 @ `dc9522dd` (branch
69
+ `proof/1175-schema-drift-green`): job `schema-drift-check` #84625 ran with
70
+ the token, cloned the baseline, and printed `RESULT: IN-SYNC (exit 0)`;
71
+ `pipeline-gate` succeeded.
72
+ - **RED** — pipelines 8355–8357 @ `bca78dae` (branch
73
+ `proof/1175-schema-drift-red`, a deliberately bogus enum value injected
74
+ into the vendored copy): `sync-vault-schema.mjs` reported drift, the job
75
+ failed with exit 1 — outside `allow_failure.exit_codes: [3]` — and
76
+ `pipeline-gate` never ran.
77
+
78
+ With both proofs recorded, `SCHEMA_DRIFT_OPTIONAL` is `"false"` at both
79
+ sites in `.gitlab-ci.yml` — `schema-drift-check` and `pipeline-gate`.
80
+ `tests/ci/schema-drift-check.test.mjs` pins the committed value on both
81
+ jobs, so a half-revert or a template refresh flipping one site back to
82
+ `"true"` fails the suite locally, not silently in a pipeline.
83
+
84
+ **Rotation / re-arm sequence** (token expiry or replacement):
85
+
86
+ 0. **Re-mint the token.** Run the same `glab api --method POST … --input -`
87
+ recipe as Option A step 1, against the TARGET project (id 52), and copy
88
+ the response's `token` field immediately — it is shown exactly once.
89
+ 1. `read -rs TOKEN` at the prompt (no echo), then pipe it into `glab variable
90
+ set` rather than passing it as a `--value` argument — a value passed on the
91
+ command line is visible to any other process on the host via `ps`, while
92
+ stdin is not:
93
+
94
+ ```bash
95
+ read -rs TOKEN
96
+ printf '%s' "$TOKEN" | glab variable set SCHEMA_DRIFT_TOKEN \
97
+ -R infrastructure/session-orchestrator --masked
98
+ ```
99
+
100
+ **Not** `--protected`: `.gate-rules` (`.gitlab-ci.yml:74`) runs the job
101
+ on every branch and every MR pipeline, and a protected-only variable would
102
+ silently reproduce the exit-5 `UNAVAILABLE` failure on every unprotected
103
+ branch. (`glab variable set --help` documents stdin piping directly —
104
+ `cat file.txt | glab variable set SERVER_TOKEN` — but no `-`/dash value
105
+ for `--value`; the flag only accepts a literal string, so omitting it
106
+ entirely and piping the value is the only way to keep the token off argv.)
107
+ 2. Push an ordinary commit and read the `schema-drift-check` job log for
108
+ `RESULT: IN-SYNC` — and confirm the job DURATION is well over 20 seconds
109
+ (see the pipeline-6815 warning above). A fast "success" is the exit-3
110
+ soft-skip in disguise, not a real run.
111
+ 3. `SCHEMA_DRIFT_OPTIONAL` stays `"false"` at **both** sites —
112
+ `schema-drift-check` and `pipeline-gate`. A rotation replaces only the
113
+ credential, never the flag; if the flag was ever reverted for an
114
+ emergency, flip it back to `"false"` at both sites in one commit —
115
+ `tests/ci/schema-drift-check.test.mjs` pins the committed value on both
116
+ jobs, so a half-flip fails the suite locally.
117
+ 4. Local counter-probe before trusting the pipeline: clone
118
+ `infrastructure/projects-baseline` with the token, make a throwaway copy of
119
+ `packages/zod-schemas/src/vault-frontmatter.ts` with one field
120
+ deliberately edited, then run
121
+ `node scripts/sync-vault-schema.mjs --check --canonical <path-to-edited-copy>`
122
+ — expect exit 1 with a diff naming the edited field. That confirms the
123
+ check diffs real content rather than passing on a broken comparison.
124
+
125
+ Per `.claude/rules/security.md` § SEC-005, this token's lifecycle belongs in
126
+ `.claude/docs/SECRETS-INVENTORY.md` once one exists — that file is not present
127
+ in this repo (measured 2026-09-02: no `.claude/docs/` directory tracked), so
128
+ the inventory is not adopted here and this section remains the sole record.
30
129
 
31
130
  ### Required CI variable
32
131
 
33
132
  | Variable | Type | Mask | Protect | Value |
34
133
  |---|---|---|---|---|
35
- | `SCHEMA_DRIFT_TOKEN` | Variable | Yes | Optional | deploy token or PAT (see below) |
134
+ | `SCHEMA_DRIFT_TOKEN` | Variable | Yes | No | Project Access Token or PAT see Option A/B below |
36
135
 
37
136
  If `SCHEMA_DRIFT_TOKEN` is **not set**, the job prints a `NOT VERIFIED` notice
38
137
  and exits **3** — which `allow_failure.exit_codes` renders as an amber *warning*,
@@ -53,11 +152,12 @@ let alone diff a schema against it. Issue #933.
53
152
 
54
153
  ```yaml
55
154
  variables:
56
- SCHEMA_DRIFT_OPTIONAL: "true"
155
+ SCHEMA_DRIFT_OPTIONAL: "false"
57
156
  ```
58
157
 
59
- It is the review-visible declaration that "no token" is *currently* an accepted
60
- state. The behaviour matrix:
158
+ It is the review-visible declaration that "no token" is *no longer* an
159
+ accepted state armed 2026-09-03 (#1175, see § Activation status above).
160
+ The behaviour matrix:
61
161
 
62
162
  | `SCHEMA_DRIFT_TOKEN` | `SCHEMA_DRIFT_OPTIONAL` | Exit | State | Pipeline effect |
63
163
  |---|---|---|---|---|
@@ -76,14 +176,53 @@ a schema diff that does not exist. Only 3 is listed in
76
176
  outcome also prints its own `[schema-drift] RESULT: <STATE>` line, so the job log
77
177
  answers "what happened" without the reader having to know this table.
78
178
 
79
- **After completing the token setup below, change `SCHEMA_DRIFT_OPTIONAL` to
80
- `"false"` in `.gitlab-ci.yml`** in **both** places: the `schema-drift-check`
179
+ **Caveat a second, narrower exit-3 collision (do not change the YAML for
180
+ it).** `scripts/sync-vault-schema.mjs` has its own exit 3, for a different
181
+ condition: malformed sentinel comments in `validator.mjs` (only one of
182
+ `begin`/`end` present). If `--check` ever hit that branch, it would return
183
+ exit 3 from the tool itself — and `allow_failure.exit_codes: [3]` reads the
184
+ shell's final exit code, not which tool produced it, so a genuine tooling
185
+ defect (broken sentinels) would render as the same amber "no token, declared
186
+ optional" warning that the missing-token guard produces. This is a caveat to
187
+ note, not a blocker: the sentinels are intact today, and the fix — if it is
188
+ ever needed — is giving `sync-vault-schema.mjs`'s malformed-sentinel case a
189
+ distinct exit code, not a change here.
190
+
191
+ **This is what the armed state looks like.** `SCHEMA_DRIFT_OPTIONAL` is
192
+ `"false"` in `.gitlab-ci.yml` at **both** places: the `schema-drift-check`
81
193
  job and `pipeline-gate`. One flag, two enforcement points;
82
- `tests/ci/schema-drift-check.test.mjs` asserts the mirroring, so a half-flip
83
- fails the suite locally rather than silently leaving one point advisory. The
84
- flip is what converts a missing token from a tolerated warning into a hard red,
85
- and it is the whole point of the flag: the opt-out is a line in a reviewed file,
86
- not the accidental side effect of an unset CI variable.
194
+ `tests/ci/schema-drift-check.test.mjs` asserts the mirroring AND pins the
195
+ literal `"false"` value on both jobs, so a half-flip or a full revert —
196
+ fails the suite locally rather than silently leaving one point advisory. A
197
+ missing or expired token now hard-fails the pipeline (exit 4) instead of the
198
+ tolerated amber warning — that is the whole point of the flag: the opt-out is
199
+ a line in a reviewed file, not the accidental side effect of an unset CI
200
+ variable.
201
+
202
+ **To switch it back to amber temporarily** (a token rotation window, or
203
+ taking the check offline for an emergency): set `SCHEMA_DRIFT_OPTIONAL` to
204
+ `"true"` at **both** sites, in one commit — the same mirrored-pair discipline
205
+ applies in reverse, and the same test catches a half-revert. Re-arm by
206
+ flipping both sites back to `"false"` once the reason for the amber window is
207
+ resolved; see § Rotation / re-arm sequence above for the token side of that
208
+ operation.
209
+
210
+ **Fork / external-contributor MR caveat.** `.gate-rules` (`.gitlab-ci.yml:74`)
211
+ includes `if: $CI_PIPELINE_SOURCE == "merge_request_event"`, so a merge
212
+ request pipeline runs `schema-drift-check` regardless of who opened it — but
213
+ GitLab does not pass the target project's masked CI/CD variables to a
214
+ pipeline running a **forked** project's code, by design, so that an untrusted
215
+ fork cannot exfiltrate a secret. A fork/contributor MR therefore cannot read
216
+ `SCHEMA_DRIFT_TOKEN` even though the variable is set and unprotected on this
217
+ project, and with `SCHEMA_DRIFT_OPTIONAL: "false"` that reads as a genuinely
218
+ missing token: exit **4** (`MISCONFIGURED`), a hard pipeline failure — not the
219
+ amber `SKIPPED` a same-project branch would get. The accepted mitigation is
220
+ either of: a maintainer re-runs the pipeline from within this project (e.g.
221
+ pushing the same commit to a branch here, where the variable IS available),
222
+ or a maintainer temporarily sets `SCHEMA_DRIFT_OPTIONAL: "true"` on that one
223
+ MR/branch for the duration of review. Do not weaken the committed default in
224
+ `.gitlab-ci.yml` for this — it stays `"false"` at both sites per the armed
225
+ state above.
87
226
 
88
227
  > **Before you flip it, run ONE pipeline with the token present while
89
228
  > `SCHEMA_DRIFT_OPTIONAL` is still `"true"`, and check the job's DURATION.**
@@ -98,35 +237,93 @@ not the accidental side effect of an unset CI variable.
98
237
  > exactly this failure — pipeline 6815 reported SUCCESS in 17 s having checked
99
238
  > nothing (issue #933).
100
239
 
101
- ### Option A — Deploy Token (recommended, least-privilege)
102
-
103
- 1. Open `infrastructure/projects-baseline` on your GitLab instance.
104
- 2. Go to **Settings Repository Deploy tokens**.
105
- 3. Click **Add token**:
106
- - **Name:** `session-orchestrator-ci-schema-drift`
107
- - **Expires at:** set a reminder (e.g. 1 year); rotate before expiry
108
- - **Scopes:** check `read_repository` only
109
- 4. Copy the generated token value (shown once).
110
- 5. Open `session-orchestrator` on GitLab.
111
- 6. Go to **Settings CI/CD Variables Add variable**:
112
- - **Key:** `SCHEMA_DRIFT_TOKEN`
113
- - **Value:** paste the deploy token
114
- - **Type:** Variable
115
- - **Masked:** Yes
116
- - **Protected:** Optional (enable if you only need it on protected branches)
117
- 7. Save.
240
+ ### Option A — Project Access Token (recommended — works with the current clone URL)
241
+
242
+ GitLab resolves a **deploy token** by its own fixed username
243
+ (`gitlab+deploy-token-<n>`, or a custom username if one was set at creation).
244
+ The job's clone step hardcodes the login as `oauth2:${SCHEMA_DRIFT_TOKEN}`
245
+ (`.gitlab-ci.yml` ~:652) `oauth2` is the username GitLab expects for a
246
+ Personal or Project Access Token, not for a deploy token. A deploy token's
247
+ value paired with that hardcoded username fails authentication at clone time
248
+ and surfaces as exit 5 `UNAVAILABLE`, which reads as a network/credential
249
+ problem rather than "wrong username" (see the demoted Deploy Token option
250
+ below). Tokens with **PAT semantics** GitLab accepts any username alongside
251
+ the token value — authenticate correctly with this clone URL: a Personal
252
+ Access Token, or, least-privilege, a **Project Access Token** scoped to the
253
+ TARGET project (`infrastructure/projects-baseline`). A Project Access Token
254
+ is preferred over a personal PAT for the same reason the deploy token used to
255
+ be recommended: it belongs to the project, not a person, and survives staff
256
+ changes.
257
+
258
+ 1. Create the token via API against the TARGET project (id 52) — GitLab has
259
+ no path to create a Project Access Token FOR a project from outside that
260
+ project's own Settings UI, so use `glab api`:
261
+
262
+ ```bash
263
+ glab api --hostname "$GITLAB_HOST" -X POST "projects/52/access_tokens" \
264
+ -H 'Content-Type: application/json' --input - <<'JSON'
265
+ {"name":"session-orchestrator-ci-schema-drift","scopes":["read_repository"],"access_level":20,"expires_at":"2027-09-01"}
266
+ JSON
267
+ ```
268
+
269
+ `--input -` plus the explicit `Content-Type: application/json` header is
270
+ required because the payload has a nested type (`scopes` is a JSON array),
271
+ which `glab api`'s `-f`/`-F` flag form cannot express. `access_level: 20`
272
+ is Reporter — the lowest access level that can read repository content.
273
+ `expires_at` is an operator choice, not a fixed value; the token created
274
+ for this document's own dry run (2026-09-02) was set 1 year out
275
+ (`2027-09-01`) — rotate before expiry.
276
+
277
+ 2. The response's `token` field holds the token value and is **shown exactly
278
+ once** — copy it immediately; GitLab will not display it again.
279
+
280
+ 3. Store it in `session-orchestrator` CI/CD variables as `SCHEMA_DRIFT_TOKEN`.
281
+ Prefer stdin over `--value` — a value passed as a command-line argument is
282
+ visible to other processes on the host (`ps`), while stdin is not:
283
+
284
+ ```bash
285
+ read -rs TOKEN
286
+ printf '%s' "$TOKEN" | glab variable set SCHEMA_DRIFT_TOKEN \
287
+ -R infrastructure/session-orchestrator --masked
288
+ ```
289
+
290
+ **Masked:** Yes. **Not** `--protected` — `.gate-rules` (`.gitlab-ci.yml:74`)
291
+ runs the job on every branch and every MR pipeline, so a protected-only
292
+ variable would silently be absent everywhere the job actually needs it.
118
293
 
119
294
  ### Option B — Personal Access Token (fallback)
120
295
 
121
- Use this if a deploy token is not available for the target project.
296
+ The same PAT-semantics reasoning from Option A applies: a personal PAT
297
+ authenticates under any username, so it works with the hardcoded `oauth2:`
298
+ clone login. Use this only if you cannot create a Project Access Token on
299
+ `infrastructure/projects-baseline` (e.g. you lack Owner/Maintainer there).
122
300
 
123
301
  1. Go to your GitLab profile → **Access Tokens**.
124
302
  2. Create a token with scope `read_repository` and a reasonable expiry.
125
303
  3. Store it in `session-orchestrator` CI/CD variables as `SCHEMA_DRIFT_TOKEN`
126
- (Masked: Yes)same steps 5–7 above.
127
-
128
- Note: a PAT is scoped to the creating user's access; prefer a deploy token so
129
- the CI credential survives staff changes.
304
+ (Masked: Yes, **not** Protected see Option A step 3 above).
305
+
306
+ A personal PAT is tied to the creating user's account and access; prefer the
307
+ Project Access Token in Option A so the CI credential survives staff changes.
308
+
309
+ ### Deploy Token — does not work with the current clone URL
310
+
311
+ This was the previously recommended option; it is demoted here because, as
312
+ the job is written today, it does not authenticate. GitLab deploy tokens
313
+ authenticate under their OWN username (`gitlab+deploy-token-<n>`, or a custom
314
+ username set at creation) — never as `oauth2`. The job's clone step hardcodes
315
+ `oauth2:${SCHEMA_DRIFT_TOKEN}` (`.gitlab-ci.yml` ~:652), so a deploy token's
316
+ value paired with the wrong username fails authentication at clone time. This
317
+ job reports that as exit 5 `UNAVAILABLE` — read as a network/credential-scope
318
+ problem, when the actual cause is the username mismatch.
319
+
320
+ To use a deploy token instead of Option A, `.gitlab-ci.yml`'s clone step would
321
+ need to stop hardcoding `oauth2` — either read the deploy token's own username
322
+ from a second CI variable and interpolate it into the clone URL, or create the
323
+ deploy token with a custom username of `oauth2` if the GitLab instance allows
324
+ choosing one. Neither change is made in this repo; that edit is out of this
325
+ document's scope. Option A avoids needing it at all, by using a token whose
326
+ username requirement (any username) already matches the hardcoded login.
130
327
 
131
328
  ### Verification path
132
329
 
@@ -162,8 +359,12 @@ Documenting it here for completeness:
162
359
  `infrastructure/session-orchestrator`.
163
360
  - Once the allowlist entry is saved, the job can use `CI_JOB_TOKEN` directly
164
361
  and `SCHEMA_DRIFT_TOKEN` is not needed.
165
- - Issue #279 chose the deploy-token path because it requires no admin action
166
- in the foreign project and works immediately after variable creation.
362
+ - Issue #279 chose the token-variable path over this allowlist because it
363
+ requires no admin action in the foreign project and works immediately after
364
+ variable creation. The original choice was a deploy token; as documented in
365
+ Option A above, a deploy token does not actually authenticate with this
366
+ job's hardcoded `oauth2:` clone login, so a Project Access Token (or PAT)
367
+ is the variant that delivers on that original reasoning.
167
368
 
168
369
  ## `pipeline-gate` — the fan-in job
169
370