session-orchestrator 5.3.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/.agents/skills/claude-md-drift-check/SKILL.md +1 -1
  2. package/.agents/skills/navigator/SKILL.md +22 -0
  3. package/.agents/skills/navigator/agents/openai.yaml +5 -0
  4. package/.agents/skills/test-audit/SKILL.md +21 -0
  5. package/.agents/skills/test-audit/agents/openai.yaml +5 -0
  6. package/.claude-plugin/marketplace.json +1 -1
  7. package/.claude-plugin/plugin.json +1 -1
  8. package/.codex-plugin/plugin.json +1 -1
  9. package/.codex-plugin/skills/claude-md-drift-check/SKILL.md +1 -1
  10. package/.codex-plugin/skills/navigator/SKILL.md +22 -0
  11. package/.codex-plugin/skills/navigator/agents/openai.yaml +5 -0
  12. package/.codex-plugin/skills/test-audit/SKILL.md +21 -0
  13. package/.codex-plugin/skills/test-audit/agents/openai.yaml +5 -0
  14. package/.cursor/commands/navigator.md +15 -0
  15. package/.cursor/commands/test-audit.md +14 -0
  16. package/.cursor/rules/060-evolve.mdc +27 -12
  17. package/.cursor/skills/claude-md-drift-check/SKILL.md +1 -1
  18. package/.cursor/skills/navigator/SKILL.md +13 -0
  19. package/.cursor/skills/test-audit/SKILL.md +12 -0
  20. package/.cursor-plugin/plugin.json +1 -1
  21. package/.orchestrator/policy/blocked-commands.json +1 -1
  22. package/AGENTS.md +9 -31
  23. package/CHANGELOG.md +70 -0
  24. package/README.md +14 -10
  25. package/docs/agent-authoring.md +2 -2
  26. package/docs/baseline.md +10 -1
  27. package/docs/ci-setup.md +57 -4
  28. package/docs/components.md +12 -12
  29. package/docs/events-schema.md +11 -8
  30. package/docs/persona-panel.md +5 -4
  31. package/docs/rule-authoring.md +27 -12
  32. package/docs/scope-collision-guard.md +26 -4
  33. package/docs/session-config-reference.md +55 -6
  34. package/docs/session-config-template.md +11 -2
  35. package/hooks/_lib/hook-import-set.json +27 -23
  36. package/hooks/hooks-codex.json +1 -1
  37. package/hooks/hooks-cursor.json +5 -0
  38. package/hooks/hooks-pi.json +5 -0
  39. package/hooks/hooks.json +6 -1
  40. package/hooks/on-session-start.mjs +53 -0
  41. package/hooks/on-stop.mjs +3 -1
  42. package/hooks/post-tool-batch-wave-signal.mjs +3 -1
  43. package/hooks/pre-bash-memory-propose-audit.mjs +52 -3
  44. package/hooks/pre-bash-sessions-ledger-guard.mjs +28 -2
  45. package/hooks/pre-edit-sessions-ledger-guard.mjs +162 -0
  46. package/hooks/pre-task-scope-disjoint.mjs +559 -72
  47. package/hooks/subagent-telemetry.mjs +96 -19
  48. package/package.json +3 -3
  49. package/pi/prompts/navigator.md +12 -0
  50. package/pi/prompts/test-audit.md +12 -0
  51. package/rules/README.md +6 -1
  52. package/rules/_index.md +3 -3
  53. package/rules/always-on/bash-harness-pitfalls.md +7 -1
  54. package/rules/opt-in-domain/prompt-caching.md +5 -1
  55. package/rules/opt-in-stack/backend-data.md +9 -1
  56. package/rules/opt-in-stack/backend.md +7 -1
  57. package/rules/opt-in-stack/frontend.md +6 -1
  58. package/rules/opt-in-stack/security-web.md +7 -1
  59. package/rules/opt-in-stack/swift.md +5 -1
  60. package/scripts/apply-session-learnings.mjs +492 -0
  61. package/scripts/archive-closed-prds.mjs +2 -1
  62. package/scripts/autopilot.mjs +49 -53
  63. package/scripts/backfill-abandoned-sessions.mjs +1 -1
  64. package/scripts/baseline-archetypes.mjs +1 -1
  65. package/scripts/check-package-manager.mjs +62 -5
  66. package/scripts/cursor-install.mjs +1 -4
  67. package/scripts/emit-session.mjs +296 -2
  68. package/scripts/export-hw-learnings.mjs +22 -3
  69. package/scripts/fleet-checkin.mjs +147 -0
  70. package/scripts/lib/agent-frontmatter.mjs +3 -3
  71. package/scripts/lib/auto-dream.mjs +7 -6
  72. package/scripts/lib/autopilot/flags.mjs +6 -1
  73. package/scripts/lib/autopilot/loop.mjs +10 -6
  74. package/scripts/lib/baseline-archetypes.mjs +41 -22
  75. package/scripts/lib/config/host-paths.mjs +79 -0
  76. package/scripts/lib/config/persona-gate-wave.mjs +3 -3
  77. package/scripts/lib/config/reaper.mjs +7 -6
  78. package/scripts/lib/config-schema.mjs +13 -0
  79. package/scripts/lib/config.mjs +71 -10
  80. package/scripts/lib/events.mjs +21 -2
  81. package/scripts/lib/fleet-protocol.mjs +270 -0
  82. package/scripts/lib/gates/gate-baseline.mjs +13 -3
  83. package/scripts/lib/gates/gate-full.mjs +7 -2
  84. package/scripts/lib/gates/gate-helpers.mjs +93 -2
  85. package/scripts/lib/gates/gate-incremental.mjs +23 -22
  86. package/scripts/lib/gates/gate-per-file.mjs +16 -7
  87. package/scripts/lib/instruction-budget-guard.mjs +69 -11
  88. package/scripts/lib/learnings/expiry-sweep.mjs +34 -3
  89. package/scripts/lib/learnings/io.mjs +154 -26
  90. package/scripts/lib/learnings/schema.mjs +163 -15
  91. package/scripts/lib/learnings/sizing-subject.mjs +2 -2
  92. package/scripts/lib/memory-proposals/schema.mjs +11 -5
  93. package/scripts/lib/named-baseline-resolver.mjs +53 -28
  94. package/scripts/lib/named-vault-resolver.mjs +104 -5
  95. package/scripts/lib/orphan-reaper/defaults.mjs +41 -0
  96. package/scripts/lib/orphan-reaper/ps-snapshot.mjs +181 -0
  97. package/scripts/lib/orphan-reaper/reaper-audit.mjs +291 -0
  98. package/scripts/lib/orphan-reaper/reaper-decide.mjs +395 -0
  99. package/scripts/lib/orphan-reaper/scan-throttle.mjs +92 -0
  100. package/scripts/lib/orphan-reaper/scan.mjs +506 -0
  101. package/scripts/lib/orphan-reaper.mjs +43 -1315
  102. package/scripts/lib/owner-yaml.mjs +104 -6
  103. package/scripts/lib/persona-panel/catalog-loader.mjs +1 -1
  104. package/scripts/lib/process-group.mjs +62 -11
  105. package/scripts/lib/project-hygiene.mjs +21 -1
  106. package/scripts/lib/quality-gate.mjs +45 -5
  107. package/scripts/lib/resource-probe.mjs +1 -1
  108. package/scripts/lib/rule-loader.mjs +100 -62
  109. package/scripts/lib/rules-sync.mjs +27 -12
  110. package/scripts/lib/scope-baseline.mjs +3 -4
  111. package/scripts/lib/session-record-repair.mjs +183 -26
  112. package/scripts/lib/session-registry.mjs +27 -2
  113. package/scripts/lib/session-schema/constants.mjs +30 -4
  114. package/scripts/lib/session-schema/validator.mjs +28 -1
  115. package/scripts/lib/session-token-rollup.mjs +245 -52
  116. package/scripts/lib/sessions-canonical.mjs +100 -9
  117. package/scripts/lib/sh-quote.mjs +29 -0
  118. package/scripts/lib/subagents-schema.mjs +30 -3
  119. package/scripts/lib/telemetry/pricing.mjs +118 -71
  120. package/scripts/lib/tests-src-ratio.mjs +140 -23
  121. package/scripts/lib/tmux-layout/layouts.mjs +1 -11
  122. package/scripts/lib/tmux-layout/tmux-shell.mjs +2 -11
  123. package/scripts/lib/ux-grill/reconcile.mjs +1 -1
  124. package/scripts/lib/validate/check-agents.mjs +1 -1
  125. package/scripts/lib/validate/check-hooks-symmetry.mjs +5 -0
  126. package/scripts/lib/validate/check-learnings-shell-writes.mjs +214 -0
  127. package/scripts/lib/validate/check-test-value-bans.mjs +87 -14
  128. package/scripts/lib/validate/check-unicode-safety.mjs +1 -0
  129. package/scripts/lib/validate/check-unwired-features.mjs +1 -1
  130. package/scripts/lib/validate-vendored-rules.mjs +206 -81
  131. package/scripts/lib/vault-mirror/telemetry.mjs +8 -1
  132. package/scripts/lib/vault-status/board-writer.mjs +48 -11
  133. package/scripts/lib/vault-status/narrative-mirror.mjs +40 -9
  134. package/scripts/lib/wave-executor/dispatch-common.mjs +10 -18
  135. package/scripts/lib/wave-executor/foreign-dispatch.mjs +1 -1
  136. package/scripts/lib/wave-executor/remote-dispatch.mjs +1 -1
  137. package/scripts/lib/wave-resource-gate.mjs +34 -8
  138. package/scripts/memory-propose.mjs +18 -5
  139. package/scripts/release-session-lock.mjs +2 -1
  140. package/scripts/release.mjs +10 -3
  141. package/scripts/repair-invalid-sessions.mjs +37 -4
  142. package/scripts/run-migrate-v2-cross-repo.mjs +158 -30
  143. package/scripts/run-quality-gate.mjs +323 -302
  144. package/scripts/site-numbers.mjs +163 -5
  145. package/scripts/sweep-expired-learnings.mjs +56 -5
  146. package/scripts/sweep-expired-rules.mjs +2 -1
  147. package/scripts/validate-plugin.mjs +7 -0
  148. package/scripts/vault-integration-watcher.mjs +2 -1
  149. package/scripts/vault-mirror.mjs +72 -46
  150. package/scripts/wave-scope-binding.mjs +2 -1
  151. package/skills/_shared/config-reading.md +3 -3
  152. package/skills/_shared/fleet-protocol.md +131 -0
  153. package/skills/_shared/state-ownership.md +5 -0
  154. package/skills/autopilot/SKILL.md +25 -11
  155. package/skills/bootstrap/SKILL.md +1 -1
  156. package/skills/bootstrap/_shared-template.md +1 -1
  157. package/skills/bootstrap/fast-template.md +1 -1
  158. package/skills/bootstrap/private-contract.md +2 -1
  159. package/skills/bootstrap/public-fallback.md +6 -3
  160. package/skills/bootstrap/references/bootstrap-retroactive-flow.md +2 -1
  161. package/skills/claude-md-drift-check/SKILL.md +10 -10
  162. package/skills/claude-md-drift-check/checker.mjs +26 -18
  163. package/skills/evolve/SKILL.md +2 -2
  164. package/skills/evolve/references/evolve-analyze-mode.md +10 -6
  165. package/skills/memory-cleanup/SKILL.md +1 -1
  166. package/skills/navigator/SKILL.md +193 -0
  167. package/skills/navigator/references/account-check.sh +87 -0
  168. package/skills/navigator/references/fleet-decisions.mjs +231 -0
  169. package/skills/navigator/references/slot-check.sh +114 -0
  170. package/skills/persona-panel/SKILL.md +2 -2
  171. package/skills/persona-panel/persona-format.md +2 -2
  172. package/skills/persona-panel/presets/designer-lens.md +1 -1
  173. package/skills/persona-panel/presets/engineer-lens.md +1 -1
  174. package/skills/persona-panel/presets/pm-lens.md +1 -1
  175. package/skills/plan/mode-retro.md +19 -4
  176. package/skills/quality-gates/SKILL.md +6 -4
  177. package/skills/remote-offload/SKILL.md +4 -2
  178. package/skills/session-end/learning-patterns.md +22 -12
  179. package/skills/session-end/metrics-collection.md +5 -6
  180. package/skills/session-end/references/phase-3-documentation-updates.md +2 -2
  181. package/skills/session-end/references/phase-4a-worktree-cleanup.md +2 -0
  182. package/skills/session-end/references/session-summary-template.md +1 -1
  183. package/skills/session-end/session-metrics-write.md +22 -60
  184. package/skills/session-plan/SKILL.md +0 -3
  185. package/skills/session-start/SKILL.md +6 -0
  186. package/skills/session-start/references/operations-contract.md +4 -0
  187. package/skills/session-start/references/phase-1-7-vault-status-board.md +1 -1
  188. package/skills/session-start/references/phase-4-ssot-environment-check.md +2 -2
  189. package/skills/test-audit/SKILL.md +152 -0
  190. package/skills/test-audit/references/campaign.md +111 -0
  191. package/skills/test-audit/references/mutate.sh +50 -0
  192. package/skills/wave-executor/SKILL.md +1 -1
  193. package/skills/wave-executor/references/wave-executor-state-init.md +3 -0
  194. package/skills/wave-executor/references/wave-loop-dispatch.md +3 -1
  195. package/skills/wave-executor/references/wave-loop-review.md +3 -5
  196. package/templates/personas/README.md +5 -5
  197. package/templates/personas/accounting-compliance.v1.md +1 -1
  198. package/templates/personas/accounting-tax-advisor.v1.md +1 -1
  199. package/templates/personas/buyer-p1-cto.v1.md +1 -1
  200. package/templates/personas/buyer-p2-kanzlei.v1.md +1 -1
  201. package/templates/personas/buyer-p3-build.v1.md +1 -1
  202. package/templates/personas/buyer-p4-tech-veto.v1.md +1 -1
  203. package/templates/personas/buyer-p5-solo.v1.md +1 -1
  204. package/templates/personas/buyer-p6-ld.v1.md +1 -1
  205. package/templates/personas/klima-ai-expert.v1.md +1 -1
  206. package/templates/personas/klima-physicist.v1.md +1 -1
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * pre-edit-sessions-ledger-guard.mjs — PreToolUse `Edit|Write|MultiEdit` hook:
4
+ * denies a TOOL write into the sessions ledger
5
+ * (`.orchestrator/metrics/sessions.jsonl`, plus rotated `sessions.jsonl.<N>`).
6
+ *
7
+ * The sibling `pre-bash-sessions-ledger-guard.mjs` covers shell writes only; the
8
+ * Edit/Write/MultiEdit tools were a second, unguarded route to the same file
9
+ * (GitLab #1443 item 4). Editing the ledger in place skips the validating writer
10
+ * (`scripts/emit-session.mjs`) and can silently rewrite records that are already
11
+ * there — the ledger is append-only by contract.
12
+ *
13
+ * ## Fleet safety — allow is the default, deny is the exception
14
+ *
15
+ * This hook runs on EVERY Edit/Write/MultiEdit in every session on the host, so
16
+ * it denies exactly one thing and allows everything else, including every
17
+ * internal failure: empty or unparsable stdin, a missing `tool_input`, an
18
+ * unknown `tool_name`, an absent `file_path`, or a repo module that fails to
19
+ * load all exit 0 with no decision (the harness proceeds). Only a positively
20
+ * identified ledger path is denied.
21
+ *
22
+ * ## Path scope — narrower than the Bash guard, on purpose
23
+ *
24
+ * The Bash guard matches on BASENAME (`sessions.jsonl` in any directory), because
25
+ * a shell `cd .orchestrator/metrics && echo … >> sessions.jsonl` leaves only the
26
+ * basename to see. The Edit/Write tools always carry the full target path, so
27
+ * here the path must END in `.orchestrator/metrics/sessions.jsonl` (optionally
28
+ * `.<digits>` for a rotated archive). Tmp-dir fixtures outside a
29
+ * `.orchestrator/metrics/` directory, `sessions.jsonl.bak`, `learnings.jsonl` and
30
+ * `events.jsonl` all allow. The comparison is case-insensitive because the
31
+ * default macOS filesystem is: `Sessions.JSONL` there IS the ledger.
32
+ *
33
+ * Not covered (by design — a guard against the accident, not a containment
34
+ * boundary): a symlink that points at the ledger under another name, and the
35
+ * `NotebookEdit` tool (not in the matcher; it cannot target a `.jsonl` file
36
+ * meaningfully).
37
+ *
38
+ * Named limits (measured 2026-09-25, security review of #1443):
39
+ *
40
+ * - The TRACKED fixture `tests/fixtures/harness-audit/clean-repo/.orchestrator/
41
+ * metrics/sessions.jsonl` matches the suffix and is DENIED (the Bash guard
42
+ * denies it too, by basename). No `tests/fixtures/` exemption on purpose: a
43
+ * path-prefix carve-out is a second hole, not a narrower guard. Editing that
44
+ * fixture is intentional maintenance — run with
45
+ * `SO_DISABLED_HOOKS=pre-edit-sessions-ledger-guard`.
46
+ * - A payload over 1 MB fails OPEN: `readStdin` (`scripts/lib/io.mjs`) rejects
47
+ * past 1,048,576 bytes and the catch below allows. A whole-ledger `Write`
48
+ * carries the file as `content`, so it bypasses the guard once the ledger
49
+ * nears that size. Largest ledger on the reference host: 481,543 bytes
50
+ * (`wc -c` over all 31 `.orchestrator/metrics/sessions.jsonl` under the
51
+ * projects root). Revisit when any ledger passes ~900 KB.
52
+ * - The case-insensitive match can DENY a distinct file on a case-sensitive
53
+ * filesystem (Linux): `.Orchestrator/METRICS/Sessions.JSONL` is not the
54
+ * ledger there, but is refused. Fails closed; same override as above.
55
+ *
56
+ * ## Platforms
57
+ *
58
+ * Cursor and Pi reach this hook through their bridges
59
+ * (`scripts/lib/cursor-hook-bridge.mjs`, `scripts/lib/pi-hook-bridge.mjs`), which
60
+ * rewrite native tool names to `Edit`/`Write`/`MultiEdit` and populate
61
+ * `tool_input.file_path`. Codex is a documented gap in
62
+ * `scripts/lib/validate/check-hooks-symmetry.mjs` (no Claude tool-name vocabulary).
63
+ *
64
+ * ## Override
65
+ *
66
+ * SO_DISABLED_HOOKS=pre-edit-sessions-ledger-guard (session-level)
67
+ * SO_HOOK_PROFILE=minimal|off
68
+ */
69
+
70
+ import path from 'node:path';
71
+
72
+ import { shouldRunHook } from './_lib/profile-gate.mjs';
73
+ import { isMainModule } from '../scripts/lib/is-main-module.mjs';
74
+
75
+ /** This hook's name — the `SO_DISABLED_HOOKS` key. */
76
+ const HOOK_NAME = 'pre-edit-sessions-ledger-guard';
77
+
78
+ /** The tools this hook judges. Anything else allows. */
79
+ const GUARDED_TOOLS = new Set(['Edit', 'Write', 'MultiEdit']);
80
+
81
+ /**
82
+ * The ledger, or a rotated archive of it, at the END of a normalized path.
83
+ * Anchored on a separator (or the start) so `x.orchestrator/metrics/…` does not match.
84
+ */
85
+ const LEDGER_PATH_RE = /(?:^|\/)\.orchestrator\/metrics\/sessions\.jsonl(?:\.\d+)?$/i;
86
+
87
+ /**
88
+ * Upper bound on the echoed target in the deny reason. `emitDeny` clamps the
89
+ * whole reason, so an unbounded path on line 1 would push the writer/reader
90
+ * instructions off the end (same reasoning as the Bash guard's TARGET_ECHO_MAX).
91
+ */
92
+ const TARGET_ECHO_MAX = 200;
93
+
94
+ /**
95
+ * Does this `file_path` name the sessions ledger (or a rotated archive)?
96
+ *
97
+ * Backslashes are normalized first so a Windows-spelled path is not read as one
98
+ * long filename (mirrors the Bash guard's `refersToLedger`), then
99
+ * `path.posix.normalize` folds `..` and `//` so `metrics/../metrics/sessions.jsonl`
100
+ * cannot sidestep the suffix match.
101
+ *
102
+ * @param {unknown} filePath
103
+ * @returns {boolean}
104
+ */
105
+ export function isLedgerPath(filePath) {
106
+ if (typeof filePath !== 'string' || filePath.length === 0) return false;
107
+ const normalized = path.posix.normalize(filePath.replace(/\\/g, '/'));
108
+ return LEDGER_PATH_RE.test(normalized);
109
+ }
110
+
111
+ /**
112
+ * Read the payload and decide. Every non-ledger outcome returns without output
113
+ * (exit 0 = no decision = allow).
114
+ *
115
+ * @returns {Promise<void>}
116
+ */
117
+ async function main() {
118
+ // Late-bound so a broken io.mjs lands in the fail-open catch below instead of
119
+ // an ESM link-time crash, and so the stdin reader is the repo's shared one.
120
+ const { readStdin, emitDeny } = await import('../scripts/lib/io.mjs');
121
+
122
+ let input;
123
+ try {
124
+ input = await readStdin();
125
+ } catch {
126
+ return; // unparsable / oversized / timed-out stdin → allow
127
+ }
128
+ if (!input || typeof input !== 'object') return;
129
+ if (!GUARDED_TOOLS.has(input.tool_name)) return;
130
+
131
+ const filePath = input.tool_input?.file_path;
132
+ if (!isLedgerPath(filePath)) return;
133
+
134
+ const shown = filePath.length > TARGET_ECHO_MAX ? `${filePath.slice(0, TARGET_ECHO_MAX)}…` : filePath;
135
+ emitDeny(
136
+ [
137
+ `${input.tool_name} on the sessions ledger blocked: '${shown}'`,
138
+ `The ledger is append-only through its validating writer:`,
139
+ ` node scripts/emit-session.mjs --entry '<json>' (or pipe the JSON on stdin)`,
140
+ `Read or verify it without writing:`,
141
+ ` node scripts/check-sessions-integrity.mjs`,
142
+ `Editing the file in place skips schema validation and can rewrite existing records.`,
143
+ `Override (intentional maintenance only): run the session with`,
144
+ `SO_DISABLED_HOOKS=${HOOK_NAME}`,
145
+ `See: GitLab #1443, skills/session-end/session-metrics-write.md`,
146
+ ].join('\n'),
147
+ );
148
+ }
149
+
150
+ // Entry guard (#1393): run only as the node script the harness execs — a bare
151
+ // `import()` must run no handler and must not exit the importing process.
152
+ if (isMainModule(import.meta.url)) {
153
+ if (!shouldRunHook(HOOK_NAME)) process.exit(0);
154
+
155
+ // Fail-OPEN on any internal error: exit 0 with no stdout is "no decision".
156
+ main()
157
+ .then(() => process.exit(0))
158
+ .catch((e) => {
159
+ process.stderr.write(`⚠ ${HOOK_NAME}: internal error — ${e?.message || e}\n`);
160
+ process.exit(0);
161
+ });
162
+ }