session-orchestrator 5.0.0 → 5.2.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 (298) hide show
  1. package/.agents/skills/autopilot/SKILL.md +1 -0
  2. package/.agents/skills/bootstrap/SKILL.md +2 -0
  3. package/.agents/skills/brainstorm/SKILL.md +3 -0
  4. package/.agents/skills/close/SKILL.md +17 -0
  5. package/.agents/skills/debug/SKILL.md +2 -0
  6. package/.agents/skills/discovery/SKILL.md +2 -1
  7. package/.agents/skills/dispatcher/SKILL.md +2 -0
  8. package/.agents/skills/eli5/SKILL.md +2 -0
  9. package/.agents/skills/eval/SKILL.md +1 -0
  10. package/.agents/skills/evolve/SKILL.md +2 -1
  11. package/.agents/skills/go/SKILL.md +18 -0
  12. package/.agents/skills/grill/SKILL.md +2 -0
  13. package/.agents/skills/harness-audit/SKILL.md +16 -0
  14. package/.agents/skills/memory-cleanup/SKILL.md +1 -0
  15. package/.agents/skills/persona-panel/SKILL.md +1 -0
  16. package/.agents/skills/plan/SKILL.md +3 -1
  17. package/.agents/skills/portfolio/SKILL.md +17 -0
  18. package/.agents/skills/reconcile/SKILL.md +1 -0
  19. package/.agents/skills/release/SKILL.md +18 -0
  20. package/.agents/skills/repo-audit/SKILL.md +1 -0
  21. package/.agents/skills/spinout/SKILL.md +1 -0
  22. package/.agents/skills/sunset-review/SKILL.md +2 -0
  23. package/.agents/skills/test/SKILL.md +17 -0
  24. package/.agents/skills/ux-grill/SKILL.md +2 -0
  25. package/.claude-plugin/marketplace.json +3 -3
  26. package/.claude-plugin/plugin.json +2 -2
  27. package/.codex-plugin/plugin.json +2 -2
  28. package/.codex-plugin/skills/autopilot/SKILL.md +5 -4
  29. package/.codex-plugin/skills/bootstrap/SKILL.md +8 -4
  30. package/.codex-plugin/skills/brainstorm/SKILL.md +11 -4
  31. package/.codex-plugin/skills/close/SKILL.md +3 -3
  32. package/.codex-plugin/skills/convergence-monitoring/SKILL.md +2 -0
  33. package/.codex-plugin/skills/convergence-monitoring/agents/openai.yaml +5 -0
  34. package/.codex-plugin/skills/debug/SKILL.md +11 -4
  35. package/.codex-plugin/skills/discovery/SKILL.md +8 -4
  36. package/.codex-plugin/skills/dispatcher/SKILL.md +4 -4
  37. package/.codex-plugin/skills/eli5/SKILL.md +9 -4
  38. package/.codex-plugin/skills/eval/SKILL.md +9 -4
  39. package/.codex-plugin/skills/evolve/SKILL.md +9 -4
  40. package/.codex-plugin/skills/go/SKILL.md +3 -3
  41. package/.codex-plugin/skills/grill/SKILL.md +11 -4
  42. package/.codex-plugin/skills/harness-audit/SKILL.md +4 -3
  43. package/.codex-plugin/skills/memory-cleanup/SKILL.md +9 -4
  44. package/.codex-plugin/skills/npm-publish/SKILL.md +2 -0
  45. package/.codex-plugin/skills/npm-publish/agents/openai.yaml +5 -0
  46. package/.codex-plugin/skills/persona-panel/SKILL.md +5 -5
  47. package/.codex-plugin/skills/plan/SKILL.md +8 -4
  48. package/.codex-plugin/skills/portfolio/SKILL.md +3 -3
  49. package/.codex-plugin/skills/reconcile/SKILL.md +9 -4
  50. package/.codex-plugin/skills/release/SKILL.md +3 -3
  51. package/.codex-plugin/skills/repo-audit/SKILL.md +6 -4
  52. package/.codex-plugin/skills/spinout/SKILL.md +4 -4
  53. package/.codex-plugin/skills/sunset-review/SKILL.md +5 -4
  54. package/.codex-plugin/skills/test/SKILL.md +3 -3
  55. package/.codex-plugin/skills/ux-grill/SKILL.md +11 -4
  56. package/.cursor/commands/autopilot.md +4 -4
  57. package/.cursor/commands/bootstrap.md +5 -4
  58. package/.cursor/commands/brainstorm.md +5 -4
  59. package/.cursor/commands/close.md +4 -3
  60. package/.cursor/commands/convergence-monitoring.md +13 -0
  61. package/.cursor/commands/debug.md +4 -4
  62. package/.cursor/commands/discovery.md +4 -4
  63. package/.cursor/commands/dispatcher.md +4 -4
  64. package/.cursor/commands/eli5.md +4 -4
  65. package/.cursor/commands/eval.md +4 -4
  66. package/.cursor/commands/evolve.md +4 -4
  67. package/.cursor/commands/go.md +4 -3
  68. package/.cursor/commands/grill.md +4 -4
  69. package/.cursor/commands/harness-audit.md +3 -3
  70. package/.cursor/commands/memory-cleanup.md +4 -4
  71. package/.cursor/commands/npm-publish.md +13 -0
  72. package/.cursor/commands/persona-panel.md +4 -4
  73. package/.cursor/commands/plan.md +5 -4
  74. package/.cursor/commands/portfolio.md +3 -3
  75. package/.cursor/commands/reconcile.md +4 -4
  76. package/.cursor/commands/release.md +4 -3
  77. package/.cursor/commands/repo-audit.md +4 -4
  78. package/.cursor/commands/spinout.md +4 -4
  79. package/.cursor/commands/sunset-review.md +4 -4
  80. package/.cursor/commands/test.md +3 -3
  81. package/.cursor/commands/ux-grill.md +4 -4
  82. package/.cursor/rules/010-session-workflow.mdc +2 -2
  83. package/.cursor/skills/bootstrap/SKILL.md +1 -0
  84. package/.cursor/skills/close/SKILL.md +13 -0
  85. package/.cursor/skills/debug/SKILL.md +0 -1
  86. package/.cursor/skills/discovery/SKILL.md +0 -1
  87. package/.cursor/skills/dispatcher/SKILL.md +0 -1
  88. package/.cursor/skills/eli5/SKILL.md +0 -1
  89. package/.cursor/skills/evolve/SKILL.md +0 -1
  90. package/.cursor/skills/go/SKILL.md +13 -0
  91. package/.cursor/skills/grill/SKILL.md +0 -1
  92. package/.cursor/skills/harness-audit/SKILL.md +12 -0
  93. package/.cursor/skills/portfolio/SKILL.md +12 -0
  94. package/.cursor/skills/release/SKILL.md +13 -0
  95. package/.cursor/skills/repo-audit/SKILL.md +0 -1
  96. package/.cursor/skills/sunset-review/SKILL.md +0 -1
  97. package/.cursor/skills/test/SKILL.md +12 -0
  98. package/.cursor/skills/ux-grill/SKILL.md +0 -1
  99. package/.cursor-plugin/plugin.json +2 -2
  100. package/.orchestrator/policy/blocked-commands.json +10 -0
  101. package/AGENTS.md +1 -1
  102. package/CHANGELOG.md +80 -0
  103. package/README.md +74 -235
  104. package/commands/session.md +10 -0
  105. package/docs/USER-GUIDE.md +24 -0
  106. package/docs/ci-setup.md +53 -0
  107. package/docs/codex-setup.md +1 -1
  108. package/docs/components.md +12 -5
  109. package/docs/events-schema.md +5 -1
  110. package/docs/install.md +128 -0
  111. package/docs/persona-panel.md +1 -1
  112. package/docs/pi-setup.md +1 -1
  113. package/docs/rule-authoring.md +83 -14
  114. package/docs/scope-collision-guard.md +2 -0
  115. package/docs/session-config-reference.md +6 -4
  116. package/docs/session-config-template.md +38 -0
  117. package/docs/telemetry.md +15 -0
  118. package/hooks/_lib/hook-import-set.json +46 -6
  119. package/hooks/_lib/subagent-paths.mjs +15 -0
  120. package/hooks/_lib/vcs-create-matcher.mjs +217 -62
  121. package/hooks/enforce-scope.mjs +42 -1
  122. package/hooks/hooks-codex.json +1 -1
  123. package/hooks/hooks.json +1 -1
  124. package/hooks/on-session-end.mjs +14 -2
  125. package/hooks/on-stop.mjs +43 -1
  126. package/hooks/post-bash-write-verify.mjs +3 -0
  127. package/hooks/pre-auq-clarity.mjs +3 -0
  128. package/hooks/pre-bash-issue-budget.mjs +103 -17
  129. package/hooks/pre-task-scope-disjoint.mjs +152 -3
  130. package/hooks/skill-invocation-telemetry.mjs +2 -1
  131. package/package.json +3 -2
  132. package/pi/prompts/autopilot.md +3 -3
  133. package/pi/prompts/bootstrap.md +3 -3
  134. package/pi/prompts/brainstorm.md +3 -3
  135. package/pi/prompts/close.md +2 -2
  136. package/pi/prompts/convergence-monitoring.md +11 -0
  137. package/pi/prompts/debug.md +3 -3
  138. package/pi/prompts/discovery.md +3 -3
  139. package/pi/prompts/dispatcher.md +3 -3
  140. package/pi/prompts/eli5.md +3 -3
  141. package/pi/prompts/eval.md +3 -3
  142. package/pi/prompts/evolve.md +3 -3
  143. package/pi/prompts/go.md +2 -2
  144. package/pi/prompts/grill.md +3 -3
  145. package/pi/prompts/harness-audit.md +2 -3
  146. package/pi/prompts/memory-cleanup.md +3 -3
  147. package/pi/prompts/npm-publish.md +11 -0
  148. package/pi/prompts/persona-panel.md +3 -3
  149. package/pi/prompts/plan.md +3 -3
  150. package/pi/prompts/portfolio.md +2 -2
  151. package/pi/prompts/reconcile.md +3 -3
  152. package/pi/prompts/release.md +3 -3
  153. package/pi/prompts/repo-audit.md +3 -4
  154. package/pi/prompts/session.md +1 -1
  155. package/pi/prompts/spinout.md +3 -3
  156. package/pi/prompts/sunset-review.md +3 -3
  157. package/pi/prompts/templates-ack.md +1 -1
  158. package/pi/prompts/test.md +3 -3
  159. package/pi/prompts/ux-grill.md +3 -3
  160. package/scripts/archive-closed-prds.mjs +2 -2
  161. package/scripts/auq-audit.mjs +2 -3
  162. package/scripts/backfill-abandoned-sessions.mjs +57 -3
  163. package/scripts/backfill-evidence-digest.mjs +2 -1
  164. package/scripts/backfill-learnings-from-vault.mjs +2 -2
  165. package/scripts/check-package-manager.mjs +2 -2
  166. package/scripts/ci/assert-vitest-green.mjs +2 -1
  167. package/scripts/emit-session.mjs +2 -3
  168. package/scripts/export-hw-learnings.mjs +2 -1
  169. package/scripts/express-path.mjs +1 -1
  170. package/scripts/gc-stale-worktrees.mjs +2 -1
  171. package/scripts/generate-codex-skills.mjs +48 -4
  172. package/scripts/generate-cursor-adapter.mjs +173 -9
  173. package/scripts/generate-hook-import-set.mjs +12 -27
  174. package/scripts/generate-pi-prompts.mjs +183 -13
  175. package/scripts/github-protection-audit.mjs +2 -3
  176. package/scripts/lib/agent-frontmatter.mjs +23 -1
  177. package/scripts/lib/claude-md-budget-lint.mjs +2 -5
  178. package/scripts/lib/command-blocker.mjs +209 -9
  179. package/scripts/lib/config/drift-check.mjs +19 -0
  180. package/scripts/lib/convergence-monitor.mjs +2 -2
  181. package/scripts/lib/cursor-hook-bridge.mjs +2 -2
  182. package/scripts/lib/description-surface.mjs +2 -5
  183. package/scripts/lib/dispatcher/cli.mjs +2 -1
  184. package/scripts/lib/ecosystem-wizard.mjs +2 -1
  185. package/scripts/lib/fetch-baseline.mjs +3 -8
  186. package/scripts/lib/gitlab-ops/stale-mr-sweep.mjs +2 -1
  187. package/scripts/lib/gitlab-portfolio/cli.mjs +2 -1
  188. package/scripts/lib/instruction-budget-guard.mjs +186 -46
  189. package/scripts/lib/is-main-module.mjs +82 -0
  190. package/scripts/lib/locks/index.mjs +32 -25
  191. package/scripts/lib/maintenance-due-banner.mjs +69 -3
  192. package/scripts/lib/peer-discovery.mjs +2 -5
  193. package/scripts/lib/playwright-driver/runner.mjs +63 -2
  194. package/scripts/lib/reconcile/rule-expiry-sweep.mjs +642 -0
  195. package/scripts/lib/rules-sync.mjs +2 -5
  196. package/scripts/lib/scope-echo.mjs +392 -7
  197. package/scripts/lib/session-close-backfill.mjs +58 -6
  198. package/scripts/lib/state-md.mjs +84 -3
  199. package/scripts/lib/sunset/walker.mjs +31 -4
  200. package/scripts/lib/tests-src-ratio.mjs +2 -6
  201. package/scripts/lib/tmux-layout/telemetry-stats.mjs +2 -1
  202. package/scripts/lib/user-invocable-skills.mjs +185 -0
  203. package/scripts/lib/validate/check-banner-parity.mjs +2 -2
  204. package/scripts/lib/validate/check-cursor-adapter.mjs +2 -2
  205. package/scripts/lib/validate/check-dead-bridge.mjs +2 -2
  206. package/scripts/lib/validate/check-doc-cli-commands.mjs +2 -2
  207. package/scripts/lib/validate/check-entry-guard.mjs +366 -0
  208. package/scripts/lib/validate/check-guard-requires-parity.mjs +2 -2
  209. package/scripts/lib/validate/check-hooks-emit-event-guard.mjs +2 -2
  210. package/scripts/lib/validate/check-learning-provenance.mjs +2 -2
  211. package/scripts/lib/validate/check-skill-links.mjs +27 -6
  212. package/scripts/lib/validate/check-skill-script-paths.mjs +2 -2
  213. package/scripts/lib/validate/check-test-git-config-target.mjs +2 -2
  214. package/scripts/lib/validate/check-unicode-safety.mjs +2 -2
  215. package/scripts/lib/validate/check-untracked-test-deps.mjs +2 -2
  216. package/scripts/lib/validate/check-unwired-features.mjs +266 -11
  217. package/scripts/lib/validate/check-validator-registration.mjs +2 -2
  218. package/scripts/lib/validate/check-vcs-repo-flag.mjs +2 -2
  219. package/scripts/lib/validate-vendored-rules.mjs +35 -9
  220. package/scripts/lib/wave-transcript-tail.mjs +2 -2
  221. package/scripts/lock-reaper.mjs +2 -1
  222. package/scripts/materialize-wave-scope.mjs +87 -4
  223. package/scripts/migrate-sessions-jsonl.mjs +2 -1
  224. package/scripts/migrate-vault-paths.mjs +2 -3
  225. package/scripts/release.mjs +124 -35
  226. package/scripts/relocate-vault-corpus.mjs +2 -3
  227. package/scripts/repair-invalid-sessions.mjs +2 -2
  228. package/scripts/session-shape.mjs +2 -2
  229. package/scripts/site-numbers.mjs +35 -11
  230. package/scripts/sweep-expired-rules.mjs +216 -0
  231. package/scripts/validate-plugin.mjs +9 -0
  232. package/scripts/vault-consolidate.mjs +2 -2
  233. package/scripts/vault-mirror.mjs +2 -3
  234. package/scripts/wave-scope-binding.mjs +2 -3
  235. package/skills/_shared/bootstrap-gate.md +1 -1
  236. package/skills/_shared/monitor-patterns.md +1 -1
  237. package/skills/_shared/research-evidence.md +53 -0
  238. package/skills/_shared/state-ownership.md +3 -0
  239. package/skills/autopilot/SKILL.md +58 -4
  240. package/skills/bootstrap/SKILL.md +51 -1
  241. package/skills/brainstorm/SKILL.md +16 -0
  242. package/skills/claude-md-drift-check/checker.mjs +49 -11
  243. package/{commands/close.md → skills/close/SKILL.md} +9 -3
  244. package/skills/debug/SKILL.md +10 -0
  245. package/skills/discovery/SKILL.md +24 -1
  246. package/skills/discovery/probes-session.md +2 -2
  247. package/skills/dispatcher/SKILL.md +38 -7
  248. package/skills/eli5/SKILL.md +11 -0
  249. package/skills/eval/SKILL.md +14 -0
  250. package/skills/evolve/SKILL.md +8 -1
  251. package/skills/evolve/references/evolve-dialectic-mode.md +6 -2
  252. package/{commands/go.md → skills/go/SKILL.md} +9 -1
  253. package/skills/grill/SKILL.md +19 -0
  254. package/{commands/harness-audit.md → skills/harness-audit/SKILL.md} +7 -2
  255. package/skills/hook-development/SKILL.md +46 -41
  256. package/skills/memory-cleanup/SKILL.md +7 -0
  257. package/skills/npm-publish/SKILL.md +1 -1
  258. package/skills/persona-panel/SKILL.md +56 -1
  259. package/skills/persona-panel/persona-format.md +1 -1
  260. package/skills/plan/SKILL.md +28 -1
  261. package/skills/playwright-driver/SKILL.md +7 -10
  262. package/{commands/portfolio.md → skills/portfolio/SKILL.md} +8 -2
  263. package/skills/reconcile/SKILL.md +10 -0
  264. package/{commands/release.md → skills/release/SKILL.md} +16 -2
  265. package/skills/repo-audit/SKILL.md +7 -0
  266. package/skills/session-end/plan-verification.md +2 -2
  267. package/skills/session-plan/SKILL.md +1 -1
  268. package/skills/session-start/SKILL.md +5 -4
  269. package/skills/session-start/phase-8-5-express-path.md +6 -6
  270. package/skills/session-start/references/phase-1-5-session-continuity.md +1 -1
  271. package/skills/session-start/references/phase-2-7-portfolio-snapshot.md +1 -1
  272. package/skills/session-start/references/phase-4-ssot-environment-check.md +4 -3
  273. package/skills/spinout/SKILL.md +12 -1
  274. package/skills/sunset-review/SKILL.md +13 -0
  275. package/{commands/test.md → skills/test/SKILL.md} +10 -4
  276. package/skills/ux-grill/SKILL.md +19 -1
  277. package/skills/wave-executor/SKILL.md +7 -4
  278. package/skills/wave-executor/references/wave-executor-state-init.md +13 -1
  279. package/skills/wave-executor/references/wave-loop-dispatch.md +3 -1
  280. package/skills/wave-executor/references/wave-loop-review.md +17 -1
  281. package/commands/autopilot.md +0 -80
  282. package/commands/bootstrap.md +0 -56
  283. package/commands/brainstorm.md +0 -48
  284. package/commands/debug.md +0 -36
  285. package/commands/discovery.md +0 -32
  286. package/commands/dispatcher.md +0 -59
  287. package/commands/eli5.md +0 -33
  288. package/commands/eval.md +0 -28
  289. package/commands/evolve.md +0 -10
  290. package/commands/grill.md +0 -45
  291. package/commands/memory-cleanup.md +0 -26
  292. package/commands/persona-panel.md +0 -121
  293. package/commands/plan.md +0 -15
  294. package/commands/reconcile.md +0 -23
  295. package/commands/repo-audit.md +0 -24
  296. package/commands/spinout.md +0 -15
  297. package/commands/sunset-review.md +0 -27
  298. package/commands/ux-grill.md +0 -51
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * sweep-expired-rules.mjs — CLI for the generated-rule expiry sweep (#1377).
4
+ *
5
+ * The sibling of `scripts/sweep-expired-learnings.mjs`, one corpus over:
6
+ * that one moves expired LEARNINGS out of `learnings.jsonl`, this one removes
7
+ * expired ENTRIES from the consolidated `.claude/rules/*.md` files that were
8
+ * generated from them. `scripts/lib/rule-loader.mjs` already refuses to inject
9
+ * an expired generated rule; nothing until now removed one from disk.
10
+ *
11
+ * All planning and writing logic lives in
12
+ * `scripts/lib/reconcile/rule-expiry-sweep.mjs`
13
+ * (`planRuleExpirySweep` / `applyRuleExpirySweep`). This file is argv parsing,
14
+ * output formatting, the event emit, and exit codes — nothing else.
15
+ *
16
+ * SAFETY: `--dry-run` is the DEFAULT and writes nothing. `--apply` is the only
17
+ * write path, and it rewrites or deletes TRACKED files under `.claude/rules/`.
18
+ *
19
+ * Usage:
20
+ * node scripts/sweep-expired-rules.mjs [--dry-run|--apply] [--json]
21
+ * [--grace-days N] [--now ISO] [--repo-root PATH] [--learnings PATH]
22
+ *
23
+ * Exit codes (the same contract as the learnings sweep CLI, deliberately —
24
+ * two sibling commands with inverted codes is a trap for the operator who
25
+ * learns one of them):
26
+ * 0 Success, including the no-op when nothing is expired
27
+ * 1 Usage/invocation error (bad flag or value)
28
+ * 2 Sweep error (an I/O or validation failure inside the lib, or any
29
+ * per-file error on the `--apply` path)
30
+ */
31
+
32
+ import { emitEvent } from './lib/events.mjs';
33
+ import { isMainModule } from './lib/is-main-module.mjs';
34
+ import {
35
+ RULE_EXPIRY_SWEEP_EVENT,
36
+ applyRuleExpirySweep,
37
+ planRuleExpirySweep,
38
+ } from './lib/reconcile/rule-expiry-sweep.mjs';
39
+
40
+ const DEFAULT_GRACE_DAYS = 0;
41
+
42
+ function printHelp() {
43
+ process.stdout.write(
44
+ `Usage: node scripts/sweep-expired-rules.mjs [--dry-run|--apply] [--json] [--grace-days N] [--now ISO] [--repo-root PATH] [--learnings PATH]
45
+
46
+ Removes EXPIRED entries from the consolidated machine-generated rule files in
47
+ .claude/rules/. An expired entry's prose block is deleted; its "## Provenance"
48
+ pair is KEPT as a "markers only" bullet, because /reconcile dedupes on those
49
+ markers and dropping one re-proposes the learning. A file is deleted only when
50
+ every substantive entry expired, and every provenance key is stamped terminal
51
+ before the unlink.
52
+
53
+ Options:
54
+ --dry-run Preview the plan; write nothing (DEFAULT)
55
+ --apply Perform the rewrites/deletes and emit the ledger event
56
+ --json Emit a single machine-parseable JSON summary line
57
+ --grace-days N Days past expiry before an entry is swept (default: ${DEFAULT_GRACE_DAYS})
58
+ --now ISO Injected clock (testing / what-if planning)
59
+ --repo-root PATH Repo root (default: process.cwd())
60
+ --learnings PATH Learnings store, repo-relative (default: the metrics store)
61
+
62
+ Exit codes: 0 success 1 usage/invocation error 2 sweep error
63
+ `,
64
+ );
65
+ }
66
+
67
+ /** Exit 1 with a diagnostic on stderr (usage/invocation errors). */
68
+ function usageError(message) {
69
+ process.stderr.write(`sweep-expired-rules: ${message}\n`);
70
+ process.exit(1);
71
+ }
72
+
73
+ export function parseArgs(argv) {
74
+ const args = {
75
+ dryRun: true,
76
+ json: false,
77
+ graceDays: DEFAULT_GRACE_DAYS,
78
+ now: null,
79
+ repoRoot: process.cwd(),
80
+ learnings: null,
81
+ };
82
+ for (let i = 0; i < argv.length; i += 1) {
83
+ const a = argv[i];
84
+ if (a === '--apply') args.dryRun = false;
85
+ else if (a === '--dry-run') args.dryRun = true;
86
+ else if (a === '--json') args.json = true;
87
+ else if (a === '--grace-days') {
88
+ const raw = argv[++i];
89
+ const v = Number(raw);
90
+ if (!Number.isFinite(v) || v < 0) {
91
+ usageError(`--grace-days requires a non-negative number, got: ${raw}`);
92
+ }
93
+ args.graceDays = v;
94
+ } else if (a === '--now') {
95
+ const raw = argv[++i];
96
+ if (typeof raw !== 'string' || !Number.isFinite(Date.parse(raw))) {
97
+ usageError(`--now requires an ISO timestamp, got: ${raw}`);
98
+ }
99
+ args.now = raw;
100
+ } else if (a === '--repo-root') {
101
+ const raw = argv[++i];
102
+ if (typeof raw !== 'string' || raw.length === 0) usageError('--repo-root requires a path');
103
+ args.repoRoot = raw;
104
+ } else if (a === '--learnings') {
105
+ const raw = argv[++i];
106
+ if (typeof raw !== 'string' || raw.length === 0) usageError('--learnings requires a path');
107
+ args.learnings = raw;
108
+ } else if (a === '--help' || a === '-h') {
109
+ printHelp();
110
+ process.exit(0);
111
+ } else {
112
+ usageError(`unknown argument: ${a}`);
113
+ }
114
+ }
115
+ return args;
116
+ }
117
+
118
+ /** Roll the plan up into the summary both output modes render. */
119
+ function summarize(plan, args, applied) {
120
+ const counts = { rewrite: 0, delete: 0, keep: 0 };
121
+ for (const p of plan.plans) counts[p.action] = (counts[p.action] ?? 0) + 1;
122
+ return {
123
+ dry_run: args.dryRun,
124
+ grace_days: args.graceDays,
125
+ files_scanned: plan.plans.length,
126
+ rewrites: counts.rewrite,
127
+ deletes: counts.delete,
128
+ keeps: counts.keep,
129
+ expired_entries: plan.plans.reduce((n, p) => n + p.expiredPairIds.length, 0),
130
+ unresolved_pairs: plan.plans.reduce((n, p) => n + p.unresolvedPairIds.length, 0),
131
+ malformed_lines: plan.malformedLines,
132
+ rules_dir_readable: plan.ok,
133
+ skipped: plan.skipped,
134
+ plans: plan.plans.map(({ nextContent: _nextContent, ...rest }) => rest),
135
+ ...(applied ? { applied } : {}),
136
+ };
137
+ }
138
+
139
+ async function main(argv) {
140
+ const args = parseArgs(argv);
141
+
142
+ let plan;
143
+ try {
144
+ plan = await planRuleExpirySweep({
145
+ repoRoot: args.repoRoot,
146
+ now: args.now ?? undefined,
147
+ graceDays: args.graceDays,
148
+ learningsPath: args.learnings ?? undefined,
149
+ });
150
+ } catch (err) {
151
+ process.stderr.write(`sweep-expired-rules: planning failed: ${err?.message ?? err}\n`);
152
+ process.exit(2);
153
+ }
154
+
155
+ let applied = null;
156
+ if (!args.dryRun) {
157
+ applied = applyRuleExpirySweep(plan, { repoRoot: args.repoRoot, now: args.now ?? undefined });
158
+ }
159
+
160
+ const summary = summarize(plan, args, applied);
161
+
162
+ if (args.json) process.stdout.write(`${JSON.stringify(summary)}\n`);
163
+ else {
164
+ process.stdout.write(
165
+ `sweep-expired-rules: ${args.dryRun ? 'dry-run' : 'applied'} — ` +
166
+ `${summary.files_scanned} generated rule file(s), ${summary.rewrites} rewrite(s), ` +
167
+ `${summary.deletes} delete(s), ${summary.expired_entries} expired entr(ies), ` +
168
+ `${summary.unresolved_pairs} unresolved pair(s), ${summary.skipped.length} skipped, ` +
169
+ `${summary.malformed_lines} malformed learnings line(s)\n`,
170
+ );
171
+ for (const s of plan.skipped) process.stdout.write(` skipped ${s.file}: ${s.reason}\n`);
172
+ for (const p of plan.plans) {
173
+ if (p.advisory) process.stdout.write(` advisory ${p.file}: ${p.advisory}\n`);
174
+ }
175
+ }
176
+
177
+ if (applied) {
178
+ for (const e of applied.errors) {
179
+ process.stderr.write(`sweep-expired-rules: ${e.file}: ${e.error}\n`);
180
+ }
181
+ // Emitted on apply ONLY, and AFTER the writes: a record's presence is proof
182
+ // that `.claude/rules/` was actually changed, never that a preview ran.
183
+ // Wrapped because `emitEvent` THROWS `EventValidationError` — a telemetry
184
+ // failure must not turn a completed sweep into a non-zero exit.
185
+ try {
186
+ await emitEvent(
187
+ RULE_EXPIRY_SWEEP_EVENT,
188
+ {
189
+ rewritten: applied.rewritten.length,
190
+ deleted: applied.deleted.length,
191
+ stamped: applied.stamped,
192
+ write_errors: applied.errors.length,
193
+ expired_entries: summary.expired_entries,
194
+ files_scanned: summary.files_scanned,
195
+ source: 'sweep-expired-rules-cli',
196
+ },
197
+ { repoRoot: args.repoRoot },
198
+ );
199
+ } catch (err) {
200
+ process.stderr.write(`sweep-expired-rules: event emit failed: ${err?.message ?? err}\n`);
201
+ }
202
+ if (applied.errors.length > 0) process.exit(2);
203
+ }
204
+
205
+ if (!plan.ok) {
206
+ process.stderr.write(
207
+ 'sweep-expired-rules: .claude/rules/ exists but could not be enumerated — ' +
208
+ 'the plan above is INCOMPLETE, not clean.\n',
209
+ );
210
+ process.exit(2);
211
+ }
212
+ }
213
+
214
+ if (isMainModule(import.meta.url)) {
215
+ await main(process.argv.slice(2));
216
+ }
@@ -424,6 +424,15 @@ if (runCheck('check-unicode-safety.mjs') !== 0) checkFailed = 1;
424
424
  process.stdout.write('\n');
425
425
  if (runCheck('check-dead-bridge.mjs') !== 0) checkFailed = 1;
426
426
 
427
+ // BLOCKING (#1371): a hand-written `process.argv[1] === import.meta.url` entry
428
+ // guard is false under any symlinked invocation, so main() never runs and the
429
+ // process still exits 0 — the caller reads silence as success. This can block
430
+ // honestly because the backlog was drained to zero in the same change: the check
431
+ // is not red on arrival for work nobody intends to do (contrast the WARN-only
432
+ // censuses below, each of which had a standing backlog when it landed).
433
+ process.stdout.write('\n');
434
+ if (runCheck('check-entry-guard.mjs') !== 0) checkFailed = 1;
435
+
427
436
  // FAIL-capable, unlike the WARN-only censuses below: R2+R4 were measured at
428
437
  // 1 hit / 1 TP / 0 FP each against the full test corpus, so this check cannot be
429
438
  // red on arrival for anything but a real instance of the class. The alternatives
@@ -84,7 +84,6 @@
84
84
 
85
85
  import { promises as fs } from 'node:fs';
86
86
  import path from 'node:path';
87
- import { pathToFileURL } from 'node:url';
88
87
 
89
88
  import { die, utcTimestamp, expandTilde } from './lib/common.mjs';
90
89
  import { parseColumnFlags, CliFlagError } from './lib/cli-flags.mjs';
@@ -96,6 +95,7 @@ import {
96
95
  stageBackup,
97
96
  compressAndCleanupBackup,
98
97
  } from './lib/vault-consolidate-fs.mjs';
98
+ import { isMainModule } from './lib/is-main-module.mjs';
99
99
 
100
100
  const DEFAULT_SOURCE = '~/Projects/vault';
101
101
  const DEFAULT_CANONICAL = '~/Projects/Bernhard/vault';
@@ -580,7 +580,7 @@ async function main() {
580
580
  // `process.argv[1]` is undefined when the module is loaded via `node -e
581
581
  // "import(...)"` (no script path in argv), so guard against it before calling
582
582
  // pathToFileURL — otherwise the import itself throws ERR_INVALID_ARG_TYPE.
583
- if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
583
+ if (isMainModule(import.meta.url)) {
584
584
  main().catch((e) => {
585
585
  console.error(e);
586
586
  process.exit(1);
@@ -53,7 +53,6 @@ import { existsSync } from 'node:fs';
53
53
  import { resolve } from 'node:path';
54
54
  import { createInterface } from 'node:readline';
55
55
  import { createReadStream } from 'node:fs';
56
- import { pathToFileURL } from 'node:url';
57
56
 
58
57
  import { processLearning, processSession, getMaskerStats } from './lib/vault-mirror/process.mjs';
59
58
  import { emitMirrorEvent, emitMirrorRunEvent } from './lib/vault-mirror/telemetry.mjs';
@@ -64,6 +63,7 @@ import { resolveRepoNamespace } from './lib/vault-mirror/namespace.mjs';
64
63
  import { resolveCanonicalSuffixes } from './lib/named-vault-resolver.mjs';
65
64
  import { loadOwnerConfig } from './lib/owner-yaml.mjs';
66
65
  import { canonicalizeSessions } from './lib/sessions-canonical.mjs';
66
+ import { isMainModule } from './lib/is-main-module.mjs';
67
67
 
68
68
  // ── Canonical-vault helpers (#600 D2 / #607 D2) ────────────────────────────────
69
69
  // These are module-level (above the CLI bootstrap) so the module is import-safe
@@ -166,8 +166,7 @@ export function _normalizeRemote(url) {
166
166
  // (`node vault-mirror.mjs ...`). When imported from a unit test, argv belongs to
167
167
  // the test runner — parsing it would spuriously process.exit. The exported
168
168
  // helpers above are unaffected by this guard.
169
- const _isDirectInvocation =
170
- Boolean(process.argv[1]) && import.meta.url === pathToFileURL(process.argv[1]).href;
169
+ const _isDirectInvocation =isMainModule(import.meta.url);
171
170
 
172
171
  if (_isDirectInvocation) {
173
172
  let parsedFlags;
@@ -37,10 +37,9 @@
37
37
  */
38
38
 
39
39
  import { parseArgs } from 'node:util';
40
- import { resolve as resolvePath } from 'node:path';
41
- import { fileURLToPath } from 'node:url';
42
40
  import { attributionForRecord, emitEvent } from './lib/events.mjs';
43
41
  import { MANIFEST_SESSION_KEYS } from './lib/session-identity/own-session.mjs';
42
+ import { isMainModule } from './lib/is-main-module.mjs';
44
43
 
45
44
  const HELP = `Usage: node scripts/wave-scope-binding.mjs [--merge] [--wave N] [--role R] [--repo-root DIR]
46
45
 
@@ -210,6 +209,6 @@ function readStdin() {
210
209
 
211
210
  // `import.meta.main` is not available on every supported Node — compare argv[1]
212
211
  // instead, so importing this module from a test never runs the CLI.
213
- if (process.argv[1] && fileURLToPath(import.meta.url) === resolvePath(process.argv[1])) {
212
+ if (isMainModule(import.meta.url)) {
214
213
  await main(process.argv.slice(2));
215
214
  }
@@ -102,7 +102,7 @@ source: projects-baseline | plugin-template | claude-init
102
102
 
103
103
  A repo that has already been bootstrapped passes the gate on every subsequent invocation with zero overhead. The gate check reads three files and performs two grep operations — negligible cost.
104
104
 
105
- `/bootstrap --retroactive` exists for repos that predate the gate (have `CLAUDE.md` + Session Config but no `bootstrap.lock`). It writes the lock without re-scaffolding. Documented in `commands/bootstrap.md`.
105
+ `/bootstrap --retroactive` exists for repos that predate the gate (have `CLAUDE.md` + Session Config but no `bootstrap.lock`). It writes the lock without re-scaffolding. Documented in `skills/bootstrap/SKILL.md`.
106
106
 
107
107
  ## Auto-Skill Dispatch (opt-in, default: off)
108
108
 
@@ -23,7 +23,7 @@ coverage check.
23
23
 
24
24
  ## Pattern 1 — GitLab pipeline + GitHub mirror sync (post-push)
25
25
 
26
- **When.** After `git push origin main` from `commands/close.md` Phase 6.
26
+ **When.** After `git push origin main` from `skills/close/SKILL.md` Phase 6.
27
27
  Watches the GitLab pipeline through to a terminal status, then prints
28
28
  the GitHub mirror's main-branch SHA so the operator can confirm parity.
29
29
 
@@ -0,0 +1,53 @@
1
+ # Research Evidence Contract
2
+
3
+ Use this contract when research informs a plan, audit, recommendation, or
4
+ research-agent handoff. Scale it to the decision: a trivial local lookup may be
5
+ one sentence; a comparison with several sources needs one record per material
6
+ claim. It does not require external research when repository evidence is enough.
7
+
8
+ ## Record
9
+
10
+ For each finding that changes the recommendation, retain:
11
+
12
+ - **Source:** stable reference plus source revision or publication/update date.
13
+ For repository evidence, prefer `SHA:path:line`; for changing external facts,
14
+ include the observation date.
15
+ - **Basis:** label the finding `observed` for a measurement or source-code
16
+ inspection (name which), `documented` for a source's claim, or `inference`
17
+ when it follows from other evidence. A test found in source is not an
18
+ executed test. Never present one class as another. Counts, percentages and
19
+ distributions additionally require PSA-006's executed-command transcript
20
+ (`.claude/rules/parallel-sessions.md` § PSA-006) — command, file scope,
21
+ result, measurement time.
22
+ - **Local equivalent:** name the existing repository feature, dependency, rule,
23
+ or workflow that already covers the need; use `none found` only after a search
24
+ proportionate to the task.
25
+ - **Disposition:** `adopt`, `adapt`, `experiment`, `reject`, or
26
+ `already stronger`, with one short reason. `Adopt` still means implement
27
+ through the current repository's conventions; it does not authorize copying,
28
+ installing, publishing, or another external mutation.
29
+ - **Next check:** state one falsifiable next step when uncertainty remains: what
30
+ result would confirm or overturn the disposition.
31
+
32
+ Keep quoted text minimal. Record limitations that materially constrain the
33
+ claim. A source revision proves which artifact was inspected; it does not prove
34
+ that its documented behavior works.
35
+
36
+ ## Private sources
37
+
38
+ Treat private/internal sources as evidence for an authorized private audience
39
+ only. Follow [Private capability context](private-capability-context.md) for
40
+ lookup and retention. Do not copy private identities, paths, excerpts, or
41
+ derived implementation details into a public plan or handoff. Re-establish a
42
+ public claim from an authorized public source, or omit it. Source access never
43
+ expands the task's implementation or external-action authority.
44
+
45
+ ## Compact example
46
+
47
+ ```text
48
+ Source: vendor guide, rev 3.2, observed 2026-09-15
49
+ Basis: documented — retries use exponential backoff; runtime behavior untested
50
+ Local equivalent: src/retry.mjs already provides capped linear retries
51
+ Disposition: experiment — compare failure recovery before changing the default
52
+ Next check: 100 replayed failures; reject if success rate does not improve
53
+ ```
@@ -18,6 +18,7 @@ total-waves: <N>
18
18
  # Optional fields (schema-version 1, additive for backward-compat):
19
19
  updated: <ISO 8601 UTC> # last write timestamp, touched by any writer
20
20
  session: <session-label> # attribution/history label; normally semantic since #573, legacy UUID-v4 remains readable; never a lock/registry ownership key
21
+ session-id: <raw id> # the RAW/native harness session id from session.lock (#1368); omit when absent; never a lock/registry ownership key
21
22
  session-start-ref: <sha> # git ref at session start
22
23
  ---
23
24
  ```
@@ -25,6 +26,8 @@ session-start-ref: <sha> # git ref at session start
25
26
  ### Required vs. optional fields
26
27
 
27
28
  - `schema-version`, `session-type`, `branch`, `issues`, `started_at`, `status`, `current-wave`, `total-waves` — **required** in every session-owned STATE.md.
29
+ - `session-id` — **optional**, additive under `schema-version: 1` (#1368). The RAW/native harness session id, taken from `.orchestrator/session.lock` via `resolveSessionIds()` (`scripts/lib/state-md.mjs`). Writers OMIT the key when the lock yields none; readers MUST tolerate its absence. It exists so `/close`'s #429 pre-check can join STATE.md to sessions.jsonl on a NATIVE identity (`findRecordedSession`'s UUID fast path) instead of falling through to the semantic label. Like `session`, it grants no lock or registry ownership.
30
+ - `started_at` is SOURCED from the same lock (`resolveSessionStartedAt()`), never from the writer's clock — see `skills/wave-executor/references/wave-executor-state-init.md` § Pre-Wave 1b for the template and the 48-minute drift that motivated it (#1368). On the READ side `started_at` is a CORROBORATING signal, never an identity key: `findRecordedSession()` (`scripts/lib/session-close-backfill.mjs`) joins STATE.md to `sessions.jsonl` on the native `session-id` FIRST and never consults `started_at` on that path — only the legacy-LABEL path compares the two timestamps, and it tolerates up to `STARTED_AT_DRIFT_TOLERANCE_MS` = **6 h** of drift (`session-close-backfill.mjs:559`, the single definition) before vetoing a label match: wider than any plausible write-lag (the 48 minutes above), narrower than the day the label's own date component already distinguishes.
28
31
  - `updated`, `session`, `session-start-ref` — **optional**. Added by #184. STATE.md files without these fields remain valid and should be treated as `updated: null` / `session: null`. Writers SHOULD populate these fields but readers MUST tolerate their absence. `session` is an attribution/history label, normally `<branch>-<YYYY-MM-DD>-<mode>-<n>` since #573 (Epic #568 Parallel-Aware Sessions P2.2); pre-#573 files may contain a UUID-v4 — both formats are read via `parseSessionId()` from `scripts/lib/session-id.mjs` per PRD §3 P2 row 3 (backward-compat). Neither form grants lock or registry ownership.
29
32
 
30
33
  The `session-type: none` + `status: idle` combination is used only for bootstrap-scaffolded placeholder files (no active session).
@@ -9,12 +9,47 @@ description: >
9
9
  record per loop run. Phase C scaffold (issue #277); implementation lives in
10
10
  scripts/lib/autopilot.mjs (Phase C-1 follow-up).
11
11
  user-invocable: true
12
+ argument-hint: "[--headless] [--verbose] [--max-sessions=N] [--max-hours=H] [--confidence-threshold=0.X] [--dry-run]"
12
13
  tags: [phase-c, autopilot, autonomous, loop]
13
14
  model: sonnet
14
15
  ---
15
16
 
16
17
  # Autopilot Skill
17
18
 
19
+ ## Invocation
20
+
21
+ The user invokes `/autopilot` with arguments: **$ARGUMENTS**. This is autonomous
22
+ session-orchestration mode — a top-level invocation only, never from inside a running
23
+ session.
24
+
25
+ Parse `$ARGUMENTS` before anything else. Unrecognized flags are ignored; out-of-range
26
+ values silently clamp to bounds. Use `parseFlags` from `scripts/lib/autopilot.mjs` for
27
+ canonical parsing — never re-implement clamping inline. The loop flags
28
+ (`--max-sessions`, `--max-hours`, `--confidence-threshold`, `--dry-run`) and their
29
+ defaults/bounds are tabled once in § Command Surface below. Two further flags belong to
30
+ the invocation surface only:
31
+
32
+ | Flag | Default | Meaning |
33
+ |------|---------|---------|
34
+ | `--headless` | `false` | Run via the standalone driver `scripts/autopilot.mjs`, which spawns `claude -p '/session <mode>'` as a child process per iteration. Required for unattended walk-away mode. Without it, `/autopilot` runs the in-process driver inside the current chat session (see § Production Wiring). |
35
+ | `--verbose` | `false` | Verbose driver output. |
36
+
37
+ ### Headless (`claude -p`)
38
+
39
+ Headless requirements:
40
+
41
+ - Anthropic API key configured for `claude -p` (Claude Code CLI auth).
42
+ - `scripts/autopilot.mjs` reads `sessions.jsonl` tail after each child exit to construct
43
+ the `sessionRunner` return shape — the spawned session must complete cleanly and append
44
+ its record (session-end Phase 3.7 handles this).
45
+ - `AUTOPILOT_RUN_ID` env var is propagated to the child so session-end stamps it onto the
46
+ per-iteration `sessions.jsonl` record.
47
+
48
+ Do NOT re-implement loop logic inline — this skill and `scripts/lib/autopilot.mjs` are
49
+ authoritative. Kill-switches are enforced by `scripts/lib/autopilot.mjs`, not inline by
50
+ Claude. The runtime writes ONE record to `.orchestrator/metrics/autopilot.jsonl` per
51
+ invocation via atomic tmp+rename; no other code path appends to that file.
52
+
18
53
  ## Phase 0.5: Parallel-Aware Preamble
19
54
 
20
55
  > Skip silently when `persistence: false` in Session Config.
@@ -177,7 +212,8 @@ Phase C-1 ships `runLoop` as a pure controller. Phase C-1.c ships `buildLiveSign
177
212
  the canonical signals-assembly helper. This section documents the **in-process driver
178
213
  protocol** (Option B from #301): how Claude — running as the coordinator in a chat
179
214
  session — drives `runLoop` between manual `/session` invocations. The headless wrapper
180
- (Option A, `scripts/autopilot.mjs` CLI spawning `claude -p`) is reserved for Phase C-5.
215
+ (Option A, `scripts/autopilot.mjs` CLI spawning `claude -p`) is selected with `--headless`
216
+ — see § Invocation.
181
217
 
182
218
  ### Dependency-Injection Contract
183
219
 
@@ -187,8 +223,8 @@ session — drives `runLoop` between manual `/session` invocations. The headless
187
223
  |---|---|---|
188
224
  | `modeSelector` | `() => Promise<{mode, confidence, rationale?}>` | wraps `selectMode(await buildLiveSignals())` |
189
225
  | `sessionRunner` | `({mode, autopilotRunId}) => Promise<{session_id, agent_summary?, effectiveness?}>` | wraps a `/session <mode>` invocation; reads `sessions.jsonl` tail to construct return value |
190
- | `resourceEvaluator` | `() => {verdict}` | wraps `evaluate(await probe(), thresholds)` from `resource-probe.mjs` |
191
- | `peerCounter` | `() => number` | reads `claude_processes_count` from a fresh `probe()` snapshot |
226
+ | `resourceEvaluator` | `() => {verdict}` | calls `evaluate(cachedProbeSnapshot, thresholds)` from `resource-probe.mjs` over a snapshot `peerCounter` refreshed on the prior iteration — never calls `probe()` itself, which is what keeps it synchronous |
227
+ | `peerCounter` | `() => Promise<number>` | returns `peers.length` from `detectPeers({ sessionId, freshnessMin: 15 })` (a SESSION count, not a process count — see `host-resources.md` HR-103) while refreshing the cached `probe()` snapshot `resourceEvaluator` reads |
192
228
 
193
229
  `abortSignal` is optional (Ctrl+C / Esc → `user-abort` kill-switch).
194
230
 
@@ -256,6 +292,25 @@ The in-process driver has Claude (the coordinator) call `/session <mode>` betwee
256
292
  - **Con:** not truly autonomous — Claude must stay in the chat. Doesn't deliver
257
293
  walk-away UX. That's Phase C-5's job.
258
294
 
295
+ ### Headless Driver Wiring (Option A — `scripts/autopilot.mjs`)
296
+
297
+ The standalone headless driver invoked via `--headless` (see § Invocation) wires all
298
+ four required `runLoop` dependencies (`modeSelector`, `sessionRunner`,
299
+ `resourceEvaluator`, `peerCounter`) plus the optional `abortSignal` to production
300
+ sources — distinct from, and more concrete than, the in-process skeleton above:
301
+
302
+ - `sessionRunner` — spawns `claude -p '/session <mode>'` as a child process; after it
303
+ exits cleanly, reads the `sessions.jsonl` tail to construct the return shape
304
+ `{session_id, agent_summary?, effectiveness?}` (`scripts/autopilot.mjs` `sessionRunner`).
305
+ - `resourceEvaluator` — calls `evaluate(cachedProbeSnapshot, thresholds)` from
306
+ `scripts/lib/resource-probe.mjs`, reading a snapshot refreshed by `peerCounter` on the
307
+ prior iteration so the function itself stays synchronous, per the `runLoop` contract
308
+ (`scripts/autopilot.mjs` `resourceEvaluator`).
309
+ - `peerCounter` — calls `detectPeers({ sessionId: autopilotRunId, freshnessMin: 15 })` from
310
+ `scripts/lib/session-registry.mjs` AND refreshes the cached `probe()` snapshot in the
311
+ same call, returning `peers.length` (`scripts/autopilot.mjs` `makePeerCounter`).
312
+ - `abortSignal` — an `AbortController` aborted on the process's `SIGINT` handler.
313
+
259
314
  ### `autopilot_run_id` Propagation
260
315
 
261
316
  When `runLoop` invokes `sessionRunner({mode, autopilotRunId})`, the per-iteration
@@ -387,7 +442,6 @@ Single-story `/autopilot` takes no Session Config block. Multi-story
387
442
  - PRD: "Autopilot Loop" (#277; archived in the private Meta-Vault)
388
443
  - Implementation (Phase C-1 + C-1.b): `scripts/lib/autopilot.mjs` — exports `runLoop`, `parseFlags`, `writeAutopilotJsonl`, `KILL_SWITCHES`, `FLAG_BOUNDS`, `SCHEMA_VERSION`, `DEFAULT_PEER_ABORT_THRESHOLD`, `DEFAULT_JSONL_PATH`, `DEFAULT_CARRYOVER_THRESHOLD`
389
444
  - Tests (Phase C-1 + C-1.b): `tests/lib/autopilot.test.mjs`
390
- - Command file: `commands/autopilot.md`
391
445
  - Mode-Selector contract: `skills/mode-selector/SKILL.md`
392
446
  - Resource probe: `scripts/lib/resource-probe.mjs`
393
447
  - Session registry: `scripts/lib/session-registry.mjs`
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: bootstrap
3
3
  user-invocable: true
4
+ disable-model-invocation: true
5
+ argument-hint: "[--upgrade <tier>]"
4
6
  tags: [bootstrap, setup, scaffold, init]
5
7
  model: sonnet
6
8
  model-preference: sonnet
@@ -15,6 +17,54 @@ description: >
15
17
 
16
18
  # Bootstrap Skill
17
19
 
20
+ ## Invocation
21
+
22
+ The user invokes `/bootstrap` with arguments: **$ARGUMENTS**. Direct invocation runs with
23
+ `INVOCATION_MODE = direct` (see § Invocation Context) and is standalone: after bootstrap
24
+ completes, report the files created and the git commit hash, and do NOT automatically
25
+ continue into any other skill.
26
+
27
+ **TL;DR — for first-time users:** Run `/bootstrap` with no flags. The skill auto-detects the right tier (fast/standard/deep) from your repo, recommends one with a one-line reason, then walks a **fixed questionnaire** — tier/stack (1–2 prompts), owner persona (5), dispatcher autonomy (1); **7–9 prompts** on a first-run full bootstrap. Bestätigen → fertig. Keine weiteren Schritte.
28
+
29
+ The flags below cover special cases (re-adopting an existing repo, upgrading a tier, syncing rules). If you don't recognize the case in the description, you don't need the flag.
30
+
31
+ > **Instruction file alias:** Bootstrap creates and reads `CLAUDE.md` (or `AGENTS.md` on Codex CLI). The two are transparent aliases — pick one, never both. Resolution rule: see `skills/_shared/instruction-file-resolution.md`.
32
+
33
+ ### Standard usage (no flags)
34
+
35
+ This is the path 95 % of users want.
36
+
37
+ | Invocation | Behavior |
38
+ |------------|----------|
39
+ | `/bootstrap` | Auto-detect tier (fast / standard / deep) from repo context. Present recommendation via `AskUserQuestion` with options to confirm or override. Tier/stack: 1–2 questions; first-run full bootstrap adds owner interview (5, `owner-interview.mjs`) + dispatcher-autonomy capture (1). Then scaffold files + commit. |
40
+
41
+ What the user sees:
42
+
43
+ ```
44
+ Skill: "Repo leer. Empfehle 'standard' weil <reason>. Passt das?"
45
+ User: [Enter on "standard (Empfohlen)"]
46
+ Skill: <writes files, commits, prints summary>
47
+ ```
48
+
49
+ ### Flag reference (special cases)
50
+
51
+ Only use a flag if you have one of the situations described. Parsed flags decide the mode
52
+ dispatch in § Invocation Context — `--fast` / `--standard` / `--deep` skip the tier
53
+ confirmation question, while `--retroactive`, `--refresh-lock`, `--sync-rules` and
54
+ `--ecosystem-health` are standalone short-circuit flows that run to completion in this
55
+ skill without dispatching to a tier template.
56
+
57
+ | Flag | When to use it |
58
+ |------|----------------|
59
+ | `--upgrade <tier>` | You bootstrapped `fast` earlier and now need `standard` or `deep`. Idempotent — writes only the delta. Refuses downgrade. Valid: `fast → standard`, `fast → deep`, `standard → deep`. |
60
+ | `--retroactive` | The repo already has `CLAUDE.md` (or `AGENTS.md` on Codex CLI) + `## Session Config` but no `bootstrap.lock` (manually bootstrapped before the gate existed). Writes the lock based on file inventory; **makes no scaffolding changes**. Commit: `chore: bootstrap lock (retroactive)`. |
61
+ | `--refresh-lock` | Your `bootstrap.lock` already has valid `version`/`tier` fields but the freshness probe flags it as stale or plugin-version-drifted — `--retroactive` is a no-op here. Acknowledges the current plugin version and resets the freshness clock (`refreshed-at` + `refreshed-plugin-version`) without touching the lock's original bootstrap provenance. No scaffolding, no auto-commit. |
62
+ | `--sync-rules` | Pull canonical rules from the plugin's `rules/` library into `.claude/rules/`. Preserves local rules (files without the plugin source header). Standalone — does not touch `bootstrap.lock`. |
63
+ | `--ecosystem-health` | Run the ecosystem-health wizard: detects CI provider + package manager, prompts for health endpoints, pipelines, and critical issue labels. Writes the config block + `.orchestrator/policy/ecosystem.json`. No scaffolding, no auto-commit. |
64
+ | `--fast` / `--standard` / `--deep` | Skip the tier confirmation question (e.g., for scripted runs). Equivalent to running `/bootstrap` and selecting that option. |
65
+
66
+ All flag-driven flows are idempotent — running twice with no upstream change is a no-op.
67
+
18
68
  ## Overview
19
69
 
20
70
  This skill runs when the Bootstrap Gate is closed (missing CLAUDE.md, Session Config, or `.orchestrator/bootstrap.lock`) or when the user invokes `/bootstrap` directly. It scaffolds the minimum structure required by all session-orchestrator skills, commits it, and writes the lock file that opens the gate for all future invocations.
@@ -26,7 +76,7 @@ This skill runs when the Bootstrap Gate is closed (missing CLAUDE.md, Session Co
26
76
  Before starting, determine how this skill was invoked:
27
77
 
28
78
  - **Transitive (gate-closed):** Invoked from another skill's Phase 0. The user's original intent (their first prompt) is available in context. After bootstrap completes, execution must return to the original skill's Phase 1.
29
- - **Direct (`/bootstrap`):** User invoked manually. Parse `$ARGUMENTS` for flags: `--fast`, `--standard`, `--deep`, `--upgrade <tier>`, `--retroactive`. See `commands/bootstrap.md` for flag semantics.
79
+ - **Direct (`/bootstrap`):** User invoked manually. Parse `$ARGUMENTS` for flags: `--fast`, `--standard`, `--deep`, `--upgrade <tier>`, `--retroactive`. See § Invocation above for flag semantics.
30
80
 
31
81
  Store `INVOCATION_MODE = transitive | direct`.
32
82
 
@@ -3,6 +3,9 @@ name: brainstorm
3
3
  description: Use when you have a feature idea but the scope or UX is still ambiguous — runs a lightweight Socratic design dialogue (3-5 AUQ rounds) and writes a spec markdown file. Use BEFORE /plan feature when product intent needs validation; skip to /plan feature when scope is already clear. HARD-GATE prevents any code work until the design is user-approved.
4
4
  model: inherit
5
5
  color: cyan
6
+ user-invocable: true
7
+ disable-model-invocation: true
8
+ argument-hint: "[topic-or-feature-slug]"
6
9
  tools: Read, Grep, Glob, Bash, Write
7
10
  ---
8
11
 
@@ -10,6 +13,19 @@ tools: Read, Grep, Glob, Bash, Write
10
13
 
11
14
  > Lightweight Socratic design dialogue for per-feature exploration. Sibling to `/plan feature`, not a replacement. Produces `docs/specs/YYYY-MM-DD-<slug>-design.md` after the user approves an approach.
12
15
 
16
+ ## Invocation
17
+
18
+ The user invokes `/brainstorm` with arguments: **$ARGUMENTS**.
19
+
20
+ The optional argument is a topic or feature slug used in the spec filename (lowercase, hyphens, no special characters). If absent, the skill derives a slug from the user's Phase 1 answer.
21
+
22
+ Examples:
23
+ - `/brainstorm` — no slug; skill prompts for the problem in Phase 1
24
+ - `/brainstorm export-to-csv` — slug pre-set to `export-to-csv`
25
+ - `/brainstorm "user notification system"` — normalize to `user-notification-system`
26
+
27
+ The HARD-GATE in Phase 0 below prevents any Edit, Write (code), or Bash (implementation) call until the user approves the design in Phase 6 — the only Write permitted before approval is the spec file itself in Phase 4.
28
+
13
29
  ## Soul Reference
14
30
 
15
31
  Read `soul.md` in this skill directory before anything else. It defines WHO you are — a Design Facilitator who shapes vague ideas into approved designs through Socratic questioning. Every interaction in this skill should reflect that identity.