session-orchestrator 3.20.0 → 3.22.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 (202) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.cursor/rules/000-session-orchestrator.mdc +3 -2
  5. package/.cursor/rules/030-wave-execution.mdc +10 -8
  6. package/.cursor/rules/040-discovery.mdc +6 -6
  7. package/.cursor/rules/050-plan.mdc +8 -8
  8. package/CHANGELOG.md +515 -0
  9. package/README.md +16 -11
  10. package/agents/analyst.md +1 -1
  11. package/agents/architect-reviewer.md +1 -1
  12. package/agents/code-implementer.md +4 -2
  13. package/agents/db-specialist.md +1 -1
  14. package/agents/dialectic-deriver.md +1 -1
  15. package/agents/docs-writer.md +1 -1
  16. package/agents/memory-proposal-collector.md +7 -5
  17. package/agents/qa-strategist.md +1 -1
  18. package/agents/security-reviewer.md +1 -1
  19. package/agents/session-reviewer.md +42 -1
  20. package/agents/skill-applied-judge.md +1 -1
  21. package/agents/test-writer.md +1 -1
  22. package/agents/ui-developer.md +1 -1
  23. package/agents/ux-evaluator.md +1 -1
  24. package/commands/eli5.md +33 -0
  25. package/commands/release.md +62 -0
  26. package/commands/test.md +2 -2
  27. package/docs/components.md +6 -5
  28. package/docs/migration-v3.md +9 -6
  29. package/docs/persona-panel.md +3 -1
  30. package/docs/scope-collision-guard.md +167 -0
  31. package/docs/session-config-reference.md +31 -8
  32. package/hooks/_lib/lock-bootstrap.mjs +19 -13
  33. package/hooks/enforce-scope.mjs +103 -3
  34. package/hooks/hooks-codex.json +1 -1
  35. package/hooks/hooks.json +21 -1
  36. package/hooks/on-session-end.mjs +76 -97
  37. package/hooks/on-session-start.mjs +195 -104
  38. package/hooks/on-stop.mjs +127 -12
  39. package/hooks/post-bash-write-verify.mjs +8 -32
  40. package/hooks/pre-auq-clarity.mjs +787 -0
  41. package/hooks/pre-bash-issue-budget.mjs +17 -18
  42. package/hooks/pre-task-scope-disjoint.mjs +1042 -0
  43. package/package.json +3 -1
  44. package/pi/prompts/eli5.md +12 -0
  45. package/pi/prompts/release.md +12 -0
  46. package/scripts/auq-audit.mjs +825 -0
  47. package/scripts/autopilot.mjs +10 -9
  48. package/scripts/emit-session.mjs +42 -0
  49. package/scripts/export-hw-learnings.mjs +61 -2
  50. package/scripts/lib/auq/clarity.mjs +1314 -0
  51. package/scripts/lib/auq/parse.mjs +1006 -0
  52. package/scripts/lib/auq/schema.mjs +1457 -0
  53. package/scripts/lib/autopilot/worktree-pipeline.mjs +5 -5
  54. package/scripts/lib/backlog-scan.mjs +106 -15
  55. package/scripts/lib/build-live-signals.mjs +7 -3
  56. package/scripts/lib/ci-status-banner.mjs +267 -77
  57. package/scripts/lib/config/dispatcher-autonomy-capture.mjs +32 -9
  58. package/scripts/lib/config/vault-integration.mjs +12 -1
  59. package/scripts/lib/dispatcher/rank.mjs +4 -7
  60. package/scripts/lib/gates/gate-full.mjs +3 -3
  61. package/scripts/lib/gates/gate-helpers.mjs +17 -6
  62. package/scripts/lib/git-config-drift.mjs +471 -0
  63. package/scripts/lib/harness-audit/categories/category6.mjs +65 -12
  64. package/scripts/lib/io.mjs +432 -7
  65. package/scripts/lib/issue-budget.mjs +63 -9
  66. package/scripts/lib/learnings/select.mjs +157 -3
  67. package/scripts/lib/memory-cleanup-stamp.mjs +132 -8
  68. package/scripts/lib/mirror-issues-banner.mjs +266 -0
  69. package/scripts/lib/named-vault-resolver.mjs +105 -16
  70. package/scripts/lib/owner-interview.mjs +78 -32
  71. package/scripts/lib/peer-cards/schema.mjs +6 -2
  72. package/scripts/lib/peer-discovery.mjs +73 -22
  73. package/scripts/lib/project-hygiene.mjs +64 -4
  74. package/scripts/lib/reconcile/renderer.mjs +17 -4
  75. package/scripts/lib/reconcile/writer.mjs +69 -30
  76. package/scripts/lib/redact-spans.mjs +89 -0
  77. package/scripts/lib/resource-probe/evaluate.mjs +330 -149
  78. package/scripts/lib/resource-probe/probe-platform.mjs +35 -0
  79. package/scripts/lib/resource-probe.mjs +18 -2
  80. package/scripts/lib/scope-baseline.mjs +77 -17
  81. package/scripts/lib/scope-gate.mjs +658 -0
  82. package/scripts/lib/secret-masker.mjs +262 -0
  83. package/scripts/lib/session-lock.mjs +34 -10
  84. package/scripts/lib/session-registry.mjs +9 -1
  85. package/scripts/lib/spiral-carryover.mjs +23 -2
  86. package/scripts/lib/state-md/mission-status.mjs +164 -58
  87. package/scripts/lib/tmux-layout/vcs-detector.mjs +108 -4
  88. package/scripts/lib/validate/check-agents.mjs +77 -5
  89. package/scripts/lib/validate/check-auq-clarity.mjs +274 -0
  90. package/scripts/lib/validate/check-commands.mjs +2 -20
  91. package/scripts/lib/validate/check-doc-cli-commands.mjs +514 -0
  92. package/scripts/lib/validate/check-hooks-symmetry.mjs +48 -0
  93. package/scripts/lib/validate/check-owner-leakage.mjs +185 -17
  94. package/scripts/lib/validate/check-rules.mjs +153 -9
  95. package/scripts/lib/validate/check-skills.mjs +191 -0
  96. package/scripts/lib/validate/check-test-git-config-target.mjs +665 -0
  97. package/scripts/lib/validate/check-unicode-safety.mjs +22 -2
  98. package/scripts/lib/validate/check-untracked-test-deps.mjs +925 -0
  99. package/scripts/lib/validate/check-unwired-features.mjs +219 -11
  100. package/scripts/lib/validate/check-vcs-repo-flag.mjs +965 -0
  101. package/scripts/lib/validate/frontmatter-block.mjs +61 -0
  102. package/scripts/lib/validate/tier-inference.mjs +46 -8
  103. package/scripts/lib/vault-backfill/glab.mjs +91 -58
  104. package/scripts/lib/vault-backfill/manifest.mjs +28 -8
  105. package/scripts/lib/vault-mirror/namespace.mjs +146 -1
  106. package/scripts/lib/vault-mirror/process.mjs +264 -31
  107. package/scripts/lib/vault-mirror/render-sessions.mjs +115 -4
  108. package/scripts/lib/vault-status/board-writer.mjs +300 -56
  109. package/scripts/lib/vault-status/narrative-mirror.mjs +119 -5
  110. package/scripts/lib/vcs-repo-spec.mjs +680 -30
  111. package/scripts/lib/wave-resource-gate.mjs +67 -73
  112. package/scripts/materialize-wave-scope.mjs +281 -0
  113. package/scripts/print-learnings-index.mjs +30 -3
  114. package/scripts/release.mjs +983 -107
  115. package/scripts/run-quality-gate.mjs +14 -0
  116. package/scripts/site-numbers.mjs +1049 -0
  117. package/scripts/validate-plugin.mjs +64 -0
  118. package/scripts/validate-wave-scope.mjs +286 -12
  119. package/scripts/vault-backfill.mjs +32 -5
  120. package/scripts/vault-mirror.mjs +26 -1
  121. package/skills/_shared/monitor-patterns.md +24 -4
  122. package/skills/_shared/parallel-aware-auq.md +30 -24
  123. package/skills/_shared/parallel-aware-preamble.md +31 -2
  124. package/skills/_shared/state-ownership.md +49 -6
  125. package/skills/bootstrap/SKILL.md +2 -1
  126. package/skills/brainstorm/SKILL.md +18 -18
  127. package/skills/brainstorm/soul.md +12 -0
  128. package/skills/claude-md-drift-check/SKILL.md +9 -1
  129. package/skills/debug/SKILL.md +4 -1
  130. package/skills/discovery/SKILL.md +28 -24
  131. package/skills/discovery/issue-templates.md +4 -4
  132. package/skills/discovery/probes-code.md +2 -2
  133. package/skills/discovery/probes-feature.md +6 -6
  134. package/skills/discovery/probes-infra.md +2 -2
  135. package/skills/discovery/probes-session.md +5 -5
  136. package/skills/dispatcher/SKILL.md +10 -1
  137. package/skills/eli5/SKILL.md +43 -0
  138. package/skills/evolve/SKILL.md +8 -9
  139. package/skills/frontmatter-guard/SKILL.md +9 -1
  140. package/skills/gitlab-ops/SKILL.md +73 -59
  141. package/skills/gitlab-portfolio/SKILL.md +10 -1
  142. package/skills/grill/SKILL.md +6 -6
  143. package/skills/grill/soul.md +16 -0
  144. package/skills/memory-cleanup/SKILL.md +20 -7
  145. package/skills/npm-publish/SKILL.md +23 -51
  146. package/skills/peekaboo-driver/SKILL.md +3 -3
  147. package/skills/persona-panel/SKILL.md +3 -1
  148. package/skills/plan/SKILL.md +18 -16
  149. package/skills/plan/mode-feature.md +1 -1
  150. package/skills/plan/mode-new.md +42 -12
  151. package/skills/plan/soul.md +12 -0
  152. package/skills/reconcile/SKILL.md +3 -3
  153. package/skills/repo-audit/SKILL.md +10 -1
  154. package/skills/session-end/SKILL.md +97 -22
  155. package/skills/session-end/metrics-collection.md +1 -1
  156. package/skills/session-end/phase-3-6-tail.md +37 -2
  157. package/skills/session-end/session-metrics-write.md +4 -10
  158. package/skills/session-plan/SKILL.md +2 -2
  159. package/skills/session-plan/wave-template.md +1 -1
  160. package/skills/session-start/SKILL.md +82 -36
  161. package/skills/session-start/phase-2-5-docs-planning.md +8 -8
  162. package/skills/session-start/phase-4-5-resource-health.md +82 -19
  163. package/skills/session-start/soul.md +110 -0
  164. package/skills/spinout/SKILL.md +5 -1
  165. package/skills/sunset-review/SKILL.md +11 -1
  166. package/skills/test-runner/SKILL.md +2 -2
  167. package/skills/tmux-layout/SKILL.md +7 -2
  168. package/skills/using-orchestrator/SKILL.md +1 -1
  169. package/skills/vault-mirror/SKILL.md +10 -1
  170. package/skills/vault-sync/SKILL.md +10 -1
  171. package/skills/vault-sync/validator.mjs +55 -6
  172. package/skills/wave-executor/wave-loop.md +64 -12
  173. package/skills/write-executable-plan/SKILL.md +6 -6
  174. package/scripts/lib/mission-status-schema.mjs +0 -114
  175. package/scripts/tests/fixtures/fetch-baseline/sample-rule.md +0 -8
  176. package/skills/vault-sync/tests/fixtures/archive-test-vault/90-archive/bad-archived.md +0 -8
  177. package/skills/vault-sync/tests/fixtures/archive-test-vault/_meta/.gitkeep +0 -0
  178. package/skills/vault-sync/tests/fixtures/archive-test-vault/live-note.md +0 -8
  179. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/_meta/.gitkeep +0 -0
  180. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/bad-type.md +0 -8
  181. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/good-note.md +0 -8
  182. package/skills/vault-sync/tests/fixtures/clean-vault/.obsidian/config.md +0 -8
  183. package/skills/vault-sync/tests/fixtures/clean-vault/01-projects/foo/projects-baseline.md +0 -10
  184. package/skills/vault-sync/tests/fixtures/clean-vault/03-daily/daily-2026-04-13.md +0 -8
  185. package/skills/vault-sync/tests/fixtures/clean-vault/README.md +0 -3
  186. package/skills/vault-sync/tests/fixtures/clean-vault/hello-world.md +0 -11
  187. package/skills/vault-sync/tests/fixtures/dangling-link-vault/_meta/.gitkeep +0 -0
  188. package/skills/vault-sync/tests/fixtures/dangling-link-vault/has-dangling.md +0 -9
  189. package/skills/vault-sync/tests/fixtures/dangling-link-vault/real-target.md +0 -8
  190. package/skills/vault-sync/tests/fixtures/empty-vault/_meta/.gitkeep +0 -0
  191. package/skills/vault-sync/tests/fixtures/missing-field-vault/_meta/.gitkeep +0 -0
  192. package/skills/vault-sync/tests/fixtures/missing-field-vault/missing-id.md +0 -7
  193. package/skills/vault-sync/tests/fixtures/nested-tag-vault/03-daily/daily-2026-04-13.md +0 -9
  194. package/skills/vault-sync/tests/fixtures/nested-tag-vault/_meta/.gitkeep +0 -0
  195. package/skills/vault-sync/tests/fixtures/nested-tag-vault/nested-tags-note.md +0 -11
  196. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/README.md +0 -3
  197. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_MOC.md +0 -3
  198. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_meta/.gitkeep +0 -0
  199. package/skills/vault-sync/tests/fixtures/with-moc-vault/_MOC.md +0 -11
  200. package/skills/vault-sync/tests/fixtures/with-moc-vault/_meta/.gitkeep +0 -0
  201. package/skills/vault-sync/tests/fixtures/with-moc-vault/hello-world.md +0 -11
  202. package/skills/vault-sync/tests/schema-drift.test.mjs +0 -133
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env node
2
+ // check-skills.mjs — Validate the frontmatter contract of every skills/<name>/SKILL.md.
3
+ // Usage: check-skills.mjs <plugin-root>
4
+ // Outputs lines of the form " PASS: ..." / " FAIL: ..."
5
+ // Exit 0 = all checks passed; exit 1 = at least one failure.
6
+ //
7
+ // WHY A REAL PARSER: the sibling check-agents.mjs validates agent frontmatter with
8
+ // line-oriented regexes. That is exactly why 12 of 46 SKILL.md frontmatter blocks
9
+ // could sit unparseable in the tree unnoticed — an unquoted single-line
10
+ // `description:` containing a `: ` (e.g. "Iron Law: NO FIXES") is not YAML, but a
11
+ // regex that only looks for `^description:` sees nothing wrong. Claude Code's own
12
+ // loader is lenient, so the defect was latent rather than visible. This check
13
+ // follows check-commands.mjs instead: a real js-yaml CORE_SCHEMA parse (R8) is the
14
+ // rule the other five hang off, because none of the field rules can be evaluated
15
+ // on a block that does not parse.
16
+ //
17
+ // DELIBERATELY NOT IMPLEMENTED — see the report for #<wave>:
18
+ // * A block-scalar ban. check-agents.mjs bans `description: >` for agents/*.md
19
+ // because the agent loader cannot read it. For SKILL.md the sign is REVERSED:
20
+ // the folded block scalar is the only form that makes the `: ` collision above
21
+ // structurally impossible, 23 of 46 files already use it, and the 12 repairs
22
+ // that made this check green all landed on it. Porting the agent rule here
23
+ // would red 35 of 46 files and forbid the fix.
24
+ // * Length ceilings on `name` / `description`. No spec vendored in this repo
25
+ // states one, and an invented requirement is worse than none. (Measured
26
+ // 2026-08-15 at the repairing commit: longest name 22 chars, longest
27
+ // description 1012 chars — a hypothetical 1024 ceiling would sit 12 chars
28
+ // above the live corpus and go red on the next sentence added.)
29
+
30
+ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
31
+ import { join } from 'node:path';
32
+ import yaml from 'js-yaml';
33
+
34
+ import { extractInitialFrontmatter } from './frontmatter-block.mjs';
35
+
36
+ const [, , pluginRoot] = process.argv;
37
+
38
+ if (!pluginRoot) {
39
+ console.error('Usage: check-skills.mjs <plugin-root>');
40
+ process.exit(1);
41
+ }
42
+
43
+ const SKILLS_DIR_NAME = 'skills';
44
+ const SKILL_FILE = 'SKILL.md';
45
+ const KEBAB_CASE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
46
+
47
+ let passed = 0;
48
+ let failed = 0;
49
+
50
+ function pass(msg) {
51
+ console.log(` PASS: ${msg}`);
52
+ passed++;
53
+ }
54
+
55
+ function fail(msg) {
56
+ console.log(` FAIL: ${msg}`);
57
+ failed++;
58
+ }
59
+
60
+ /**
61
+ * Enumerate `skills/<dir>/SKILL.md` one level below the skills root.
62
+ *
63
+ * Depth is capped at one level on purpose: R5 (name === directory name) is only
64
+ * meaningful for a skill that owns its immediate directory. Measured 2026-08-15:
65
+ * `find skills -mindepth 3 -name SKILL.md` returns 0, so the cap loses nothing
66
+ * today. Revisit if nested skill packages ever land.
67
+ *
68
+ * @param {string} skillsDir - absolute path to the skills root
69
+ * @returns {Array<{ dirName: string, relPath: string, absPath: string }>} sorted by directory name
70
+ */
71
+ function collectSkillFiles(skillsDir) {
72
+ const found = [];
73
+ for (const dirName of readdirSync(skillsDir).sort()) {
74
+ const dirPath = join(skillsDir, dirName);
75
+ let isDir;
76
+ try {
77
+ isDir = statSync(dirPath).isDirectory();
78
+ } catch {
79
+ isDir = false;
80
+ }
81
+ if (!isDir) continue;
82
+
83
+ const absPath = join(dirPath, SKILL_FILE);
84
+ if (!existsSync(absPath)) continue;
85
+
86
+ found.push({ dirName, relPath: `${SKILLS_DIR_NAME}/${dirName}/${SKILL_FILE}`, absPath });
87
+ }
88
+ return found;
89
+ }
90
+
91
+ /**
92
+ * Apply the frontmatter contract to one SKILL.md.
93
+ *
94
+ * Rules: R1 frontmatter block present · R8 block parses as a YAML mapping ·
95
+ * R2 `name` present · R3 `name` is kebab-case · R5 `name` === directory name ·
96
+ * R6 `description` present and non-empty.
97
+ *
98
+ * @param {{ dirName: string, relPath: string, absPath: string }} skill
99
+ * @returns {boolean} true when every rule holds
100
+ */
101
+ function validateSkillFrontmatter(skill) {
102
+ const before = failed;
103
+ const content = readFileSync(skill.absPath, 'utf8');
104
+
105
+ // R1 — frontmatter block present.
106
+ const extracted = extractInitialFrontmatter(content);
107
+ if (!extracted.ok) {
108
+ fail(`${skill.relPath}: ${extracted.diagnostic}`);
109
+ return false;
110
+ }
111
+
112
+ // R8 — the block is valid YAML. Everything below depends on this holding.
113
+ let frontmatter;
114
+ try {
115
+ frontmatter = yaml.load(extracted.yamlText, { schema: yaml.CORE_SCHEMA });
116
+ } catch (error) {
117
+ const reason = error?.reason ?? error?.message ?? String(error);
118
+ const location = error?.mark
119
+ ? ` at frontmatter line ${error.mark.line + 1}, column ${error.mark.column + 1}`
120
+ : '';
121
+ fail(`${skill.relPath}: invalid YAML frontmatter: ${reason}${location}`);
122
+ return false;
123
+ }
124
+
125
+ if (frontmatter === null || typeof frontmatter !== 'object' || Array.isArray(frontmatter)) {
126
+ fail(`${skill.relPath}: YAML frontmatter must be a non-null mapping/object`);
127
+ return false;
128
+ }
129
+
130
+ // R2 — name present.
131
+ const name = frontmatter.name;
132
+ if (typeof name !== 'string' || name.trim() === '') {
133
+ fail(`${skill.relPath}: missing or empty required frontmatter field: name`);
134
+ } else {
135
+ // R3 — name is kebab-case.
136
+ if (!KEBAB_CASE.test(name)) {
137
+ fail(`${skill.relPath}: name must be kebab-case (^[a-z0-9]+(-[a-z0-9]+)*$), got: '${name}'`);
138
+ }
139
+ // R5 — name matches the directory that owns the skill.
140
+ if (name !== skill.dirName) {
141
+ fail(`${skill.relPath}: name '${name}' does not match its directory '${skill.dirName}'`);
142
+ }
143
+ }
144
+
145
+ // R6 — description present and non-empty.
146
+ const description = frontmatter.description;
147
+ if (typeof description !== 'string' || description.trim() === '') {
148
+ fail(`${skill.relPath}: missing or empty required frontmatter field: description`);
149
+ }
150
+
151
+ return failed === before;
152
+ }
153
+
154
+ // ============================================================================
155
+ // Check: skill frontmatter (SKILL.md)
156
+ // ============================================================================
157
+ console.log('--- Check: skill frontmatter (SKILL.md) ---');
158
+
159
+ const skillsDir = join(pluginRoot, SKILLS_DIR_NAME);
160
+
161
+ if (!existsSync(skillsDir)) {
162
+ fail(`skills directory not found at conventional location: ./${SKILLS_DIR_NAME}`);
163
+ } else {
164
+ let skills;
165
+ try {
166
+ skills = collectSkillFiles(skillsDir);
167
+ } catch (error) {
168
+ skills = [];
169
+ fail(`skills directory is unreadable: ${error?.message ?? String(error)}`);
170
+ }
171
+
172
+ if (skills.length === 0) {
173
+ fail(`skills directory contains no ${SKILL_FILE} files`);
174
+ } else {
175
+ pass(`skills directory contains ${skills.length} ${SKILL_FILE} files`);
176
+
177
+ let valid = 0;
178
+ for (const skill of skills) {
179
+ if (validateSkillFrontmatter(skill)) valid++;
180
+ }
181
+
182
+ if (valid === skills.length) {
183
+ pass(`all ${skills.length} ${SKILL_FILE} frontmatter blocks parse as YAML and carry a kebab-case name matching their directory plus a non-empty description`);
184
+ }
185
+ }
186
+ }
187
+
188
+ console.log('');
189
+ console.log(`Results: ${passed} passed, ${failed} failed`);
190
+
191
+ process.exit(failed > 0 ? 1 : 0);