session-orchestrator 3.22.0 → 3.24.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 (316) 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/commands/autopilot-multi.md +14 -0
  5. package/.cursor/commands/autopilot.md +14 -0
  6. package/.cursor/commands/bootstrap.md +14 -0
  7. package/.cursor/commands/brainstorm.md +14 -0
  8. package/.cursor/commands/close.md +13 -0
  9. package/.cursor/commands/contract-version-bump.md +14 -0
  10. package/.cursor/commands/debug.md +14 -0
  11. package/.cursor/commands/discovery.md +14 -0
  12. package/.cursor/commands/dispatcher.md +14 -0
  13. package/.cursor/commands/eli5.md +14 -0
  14. package/.cursor/commands/eval.md +14 -0
  15. package/.cursor/commands/evolve.md +14 -0
  16. package/.cursor/commands/go.md +14 -0
  17. package/.cursor/commands/grill.md +14 -0
  18. package/.cursor/commands/harness-audit.md +13 -0
  19. package/.cursor/commands/journey-audit.md +14 -0
  20. package/.cursor/commands/memory-cleanup.md +14 -0
  21. package/.cursor/commands/persona-panel.md +14 -0
  22. package/.cursor/commands/plan.md +14 -0
  23. package/.cursor/commands/portfolio.md +14 -0
  24. package/.cursor/commands/reconcile.md +14 -0
  25. package/.cursor/commands/release.md +14 -0
  26. package/.cursor/commands/repo-audit.md +13 -0
  27. package/.cursor/commands/session.md +14 -0
  28. package/.cursor/commands/spinout.md +14 -0
  29. package/.cursor/commands/sunset-review.md +14 -0
  30. package/.cursor/commands/templates-ack.md +14 -0
  31. package/.cursor/commands/test.md +14 -0
  32. package/.cursor/hooks.json +60 -0
  33. package/.cursor/rules/000-session-orchestrator.mdc +8 -0
  34. package/.cursor/rules/010-session-workflow.mdc +9 -1
  35. package/.cursor/rules/020-quality-gates.mdc +1 -1
  36. package/.cursor/rules/030-wave-execution.mdc +1 -1
  37. package/.cursor/rules/050-plan.mdc +2 -2
  38. package/.cursor/rules/070-gitlab-ops.mdc +73 -57
  39. package/.cursor/rules/080-ecosystem-health.mdc +7 -7
  40. package/.cursor/skills/architecture/SKILL.md +13 -0
  41. package/.cursor/skills/autopilot/SKILL.md +12 -0
  42. package/.cursor/skills/bootstrap/SKILL.md +12 -0
  43. package/.cursor/skills/brainstorm/SKILL.md +13 -0
  44. package/.cursor/skills/claude-md-drift-check/SKILL.md +13 -0
  45. package/.cursor/skills/contract-version-bump/SKILL.md +12 -0
  46. package/.cursor/skills/convergence-monitoring/SKILL.md +12 -0
  47. package/.cursor/skills/daily/SKILL.md +12 -0
  48. package/.cursor/skills/debug/SKILL.md +13 -0
  49. package/.cursor/skills/discovery/SKILL.md +13 -0
  50. package/.cursor/skills/dispatcher/SKILL.md +13 -0
  51. package/.cursor/skills/docs-orchestrator/SKILL.md +13 -0
  52. package/.cursor/skills/domain-model/SKILL.md +13 -0
  53. package/.cursor/skills/ecosystem-health/SKILL.md +13 -0
  54. package/.cursor/skills/eli5/SKILL.md +13 -0
  55. package/.cursor/skills/eval/SKILL.md +12 -0
  56. package/.cursor/skills/evolve/SKILL.md +13 -0
  57. package/.cursor/skills/frontmatter-guard/SKILL.md +13 -0
  58. package/.cursor/skills/gitlab-ops/SKILL.md +13 -0
  59. package/.cursor/skills/gitlab-portfolio/SKILL.md +13 -0
  60. package/.cursor/skills/grill/SKILL.md +13 -0
  61. package/.cursor/skills/hook-development/SKILL.md +13 -0
  62. package/.cursor/skills/journey-audit/SKILL.md +13 -0
  63. package/.cursor/skills/mcp-builder/SKILL.md +13 -0
  64. package/.cursor/skills/memory-cleanup/SKILL.md +12 -0
  65. package/.cursor/skills/mode-selector/SKILL.md +13 -0
  66. package/.cursor/skills/npm-publish/SKILL.md +12 -0
  67. package/.cursor/skills/peekaboo-driver/SKILL.md +13 -0
  68. package/.cursor/skills/persona-panel/SKILL.md +12 -0
  69. package/.cursor/skills/plan/SKILL.md +13 -0
  70. package/.cursor/skills/playwright-driver/SKILL.md +13 -0
  71. package/.cursor/skills/quality-gates/SKILL.md +13 -0
  72. package/.cursor/skills/reconcile/SKILL.md +12 -0
  73. package/.cursor/skills/remote-offload/SKILL.md +13 -0
  74. package/.cursor/skills/repo-audit/SKILL.md +13 -0
  75. package/.cursor/skills/session-end/SKILL.md +13 -0
  76. package/.cursor/skills/session-plan/SKILL.md +13 -0
  77. package/.cursor/skills/session-start/SKILL.md +13 -0
  78. package/.cursor/skills/skill-creator/SKILL.md +13 -0
  79. package/.cursor/skills/spinout/SKILL.md +12 -0
  80. package/.cursor/skills/sunset-review/SKILL.md +13 -0
  81. package/.cursor/skills/test-runner/SKILL.md +13 -0
  82. package/.cursor/skills/tmux-layout/SKILL.md +13 -0
  83. package/.cursor/skills/ubiquitous-language/SKILL.md +13 -0
  84. package/.cursor/skills/using-orchestrator/SKILL.md +13 -0
  85. package/.cursor/skills/vault-mirror/SKILL.md +13 -0
  86. package/.cursor/skills/vault-sync/SKILL.md +13 -0
  87. package/.cursor/skills/wave-executor/SKILL.md +13 -0
  88. package/.cursor/skills/write-executable-plan/SKILL.md +13 -0
  89. package/.mcp.json +4 -1
  90. package/CHANGELOG.md +446 -0
  91. package/README.md +22 -17
  92. package/agents/AGENTS.md +23 -4
  93. package/agents/code-implementer.md +2 -1
  94. package/agents/db-specialist.md +2 -2
  95. package/agents/docs-writer.md +3 -1
  96. package/agents/eval-judge.md +1 -1
  97. package/agents/session-reviewer.md +7 -1
  98. package/agents/test-writer.md +2 -1
  99. package/agents/ui-developer.md +2 -1
  100. package/commands/bootstrap.md +2 -2
  101. package/commands/close.md +3 -1
  102. package/commands/go.md +1 -1
  103. package/commands/journey-audit.md +43 -0
  104. package/docs/USER-GUIDE.md +2 -2
  105. package/docs/ci-setup.md +194 -25
  106. package/docs/codex-setup.md +64 -0
  107. package/docs/components.md +7 -7
  108. package/docs/cursor-setup.md +26 -47
  109. package/docs/events-schema.md +120 -10
  110. package/docs/github-mirror-protection.md +197 -0
  111. package/docs/pi-setup.md +2 -0
  112. package/docs/rule-authoring.md +3 -1
  113. package/docs/scope-collision-guard.md +49 -2
  114. package/docs/session-config-reference.md +89 -9
  115. package/docs/session-config-template.md +38 -7
  116. package/docs/telemetry/telemetry-claims.md +11 -10
  117. package/docs/telemetry.md +52 -1
  118. package/hooks/_lib/atomic-json.mjs +111 -0
  119. package/hooks/_lib/lock-bootstrap.mjs +8 -4
  120. package/hooks/_lib/subagent-paths.mjs +143 -0
  121. package/hooks/_lib/vcs-create-matcher.mjs +397 -38
  122. package/hooks/cwd-change-restore.mjs +9 -29
  123. package/hooks/enforce-scope.mjs +93 -0
  124. package/hooks/hooks-codex.json +1 -1
  125. package/hooks/hooks-cursor.json +201 -20
  126. package/hooks/hooks-pi.json +1 -1
  127. package/hooks/hooks.json +2 -2
  128. package/hooks/on-session-end.mjs +486 -19
  129. package/hooks/on-session-start.mjs +263 -12
  130. package/hooks/on-stop.mjs +392 -24
  131. package/hooks/post-bash-write-verify.mjs +104 -4
  132. package/hooks/post-subagent-discovery-validator.mjs +182 -21
  133. package/hooks/post-tool-batch-wave-signal.mjs +165 -42
  134. package/hooks/post-tool-failure-corrective-context.mjs +9 -32
  135. package/hooks/pre-bash-issue-budget.mjs +117 -4
  136. package/hooks/pre-bash-memory-propose-audit.mjs +13 -7
  137. package/hooks/pre-bash-sessions-ledger-guard.mjs +159 -0
  138. package/hooks/pre-bash-staging-fence.mjs +4 -0
  139. package/hooks/pre-task-scope-disjoint.mjs +368 -35
  140. package/hooks/skill-invocation-telemetry.mjs +21 -10
  141. package/hooks/subagent-telemetry.mjs +11 -26
  142. package/monitors/monitors.json +6 -0
  143. package/package.json +1 -1
  144. package/pi/prompts/journey-audit.md +12 -0
  145. package/rules/_index.md +9 -1
  146. package/rules/always-on/ask-via-tool.md +62 -0
  147. package/rules/always-on/bash-harness-pitfalls.md +168 -0
  148. package/rules/always-on/build-value.md +47 -0
  149. package/rules/always-on/cross-session-messaging.md +59 -0
  150. package/rules/always-on/loop-and-monitor.md +221 -0
  151. package/rules/always-on/parallel-sessions.md +142 -12
  152. package/rules/always-on/receiving-review.md +108 -0
  153. package/rules/always-on/test-value.md +40 -0
  154. package/rules/always-on/verification-before-completion.md +77 -0
  155. package/scripts/archive-closed-prds.mjs +258 -18
  156. package/scripts/autopilot.mjs +31 -12
  157. package/scripts/backfill-abandoned-sessions.mjs +80 -11
  158. package/scripts/backfill-evidence-digest.mjs +376 -0
  159. package/scripts/cursor-install.mjs +89 -48
  160. package/scripts/emit-event.mjs +10 -2
  161. package/scripts/export-hw-learnings.mjs +143 -2
  162. package/scripts/express-path.mjs +299 -0
  163. package/scripts/generate-cursor-adapter.mjs +253 -0
  164. package/scripts/github-protection-audit.mjs +358 -0
  165. package/scripts/lib/auq/parse.mjs +5 -29
  166. package/scripts/lib/auto-dialectic.mjs +68 -0
  167. package/scripts/lib/autopilot/worktree-pipeline.mjs +318 -18
  168. package/scripts/lib/build-live-signals.mjs +49 -27
  169. package/scripts/lib/ci-status-banner.mjs +158 -11
  170. package/scripts/lib/cold-start-detector.mjs +23 -14
  171. package/scripts/lib/command-blocker.mjs +70 -0
  172. package/scripts/lib/config/block-header.mjs +55 -0
  173. package/scripts/lib/config/discovery-validator.mjs +7 -2
  174. package/scripts/lib/config/health-endpoints.mjs +383 -0
  175. package/scripts/lib/config/reconcile.mjs +79 -4
  176. package/scripts/lib/config/remote-hosts.mjs +233 -0
  177. package/scripts/lib/config/section-extractor.mjs +235 -36
  178. package/scripts/lib/config-schema.mjs +9 -1
  179. package/scripts/lib/config.mjs +87 -8
  180. package/scripts/lib/convergence-monitor.mjs +13 -2
  181. package/scripts/lib/cursor-hook-bridge.mjs +443 -0
  182. package/scripts/lib/dispatcher/cli.mjs +2 -2
  183. package/scripts/lib/dispatcher/enumerate.mjs +2 -17
  184. package/scripts/lib/events-schema.mjs +48 -0
  185. package/scripts/lib/events.mjs +238 -5
  186. package/scripts/lib/evolve/autonomy-verdict.mjs +9 -4
  187. package/scripts/lib/evolve/autopilot-effectiveness.mjs +18 -1
  188. package/scripts/lib/express-path.mjs +327 -0
  189. package/scripts/lib/file-lock.mjs +22 -4
  190. package/scripts/lib/gates/gate-full.mjs +81 -8
  191. package/scripts/lib/gates/gate-helpers.mjs +76 -15
  192. package/scripts/lib/git-config-drift.mjs +134 -5
  193. package/scripts/lib/gitlab-portfolio/cli.mjs +3 -15
  194. package/scripts/lib/harness-audit/categories/category1.mjs +17 -6
  195. package/scripts/lib/host-identity.mjs +247 -2
  196. package/scripts/lib/instruction-budget-guard.mjs +31 -1
  197. package/scripts/lib/issue-budget.mjs +229 -30
  198. package/scripts/lib/learnings/io.mjs +55 -10
  199. package/scripts/lib/learnings/schema.mjs +95 -28
  200. package/scripts/lib/lock-reaper.mjs +7 -1
  201. package/scripts/lib/locks/staging-fence-lock.mjs +5 -1
  202. package/scripts/lib/locks/state-md-lock.mjs +8 -1
  203. package/scripts/lib/memory-banner.mjs +25 -10
  204. package/scripts/lib/memory-paths.mjs +15 -6
  205. package/scripts/lib/mode-selector/scoring.mjs +53 -6
  206. package/scripts/lib/peer-discovery.mjs +20 -2
  207. package/scripts/lib/platform.mjs +72 -9
  208. package/scripts/lib/plugin-root.mjs +143 -19
  209. package/scripts/lib/project-hygiene.mjs +43 -3
  210. package/scripts/lib/quality-gate.mjs +271 -13
  211. package/scripts/lib/reconcile/emitter.mjs +87 -19
  212. package/scripts/lib/reconcile/engine.mjs +517 -18
  213. package/scripts/lib/reconcile/idempotency.mjs +102 -1
  214. package/scripts/lib/reconcile/renderer.mjs +148 -3
  215. package/scripts/lib/reconcile/sanitize.mjs +40 -17
  216. package/scripts/lib/reconcile/writer.mjs +415 -84
  217. package/scripts/lib/rule-loader.mjs +37 -2
  218. package/scripts/lib/rules-sync.mjs +51 -8
  219. package/scripts/lib/scope-gate.mjs +126 -0
  220. package/scripts/lib/session-close-backfill.mjs +427 -37
  221. package/scripts/lib/session-discovery.mjs +69 -5
  222. package/scripts/lib/session-end/phase-skip.mjs +38 -5
  223. package/scripts/lib/session-end/worktree-cleanup.mjs +154 -7
  224. package/scripts/lib/session-id.mjs +30 -14
  225. package/scripts/lib/session-identity/own-session.mjs +220 -0
  226. package/scripts/lib/session-lock.mjs +85 -30
  227. package/scripts/lib/session-schema/normalizer.mjs +70 -3
  228. package/scripts/lib/session-schema/validator.mjs +40 -0
  229. package/scripts/lib/session-start-probes.mjs +608 -0
  230. package/scripts/lib/session-transition.mjs +277 -0
  231. package/scripts/lib/sessions-canonical.mjs +446 -0
  232. package/scripts/lib/sessions-staleness-banner.mjs +124 -57
  233. package/scripts/lib/spiral-carryover.mjs +90 -9
  234. package/scripts/lib/state-md/frontmatter-mutators.mjs +41 -8
  235. package/scripts/lib/state-md/mission-status.mjs +350 -52
  236. package/scripts/lib/state-md/yaml-parser.mjs +145 -16
  237. package/scripts/lib/state-md.mjs +12 -2
  238. package/scripts/lib/telemetry/schema.mjs +74 -8
  239. package/scripts/lib/telemetry/sync.mjs +91 -16
  240. package/scripts/lib/tmux-layout/telemetry.mjs +14 -2
  241. package/scripts/lib/validate/check-agents.mjs +66 -0
  242. package/scripts/lib/validate/check-cursor-adapter.mjs +102 -0
  243. package/scripts/lib/validate/check-dead-bridge.mjs +24 -2
  244. package/scripts/lib/validate/check-doc-cli-commands.mjs +25 -65
  245. package/scripts/lib/validate/check-hooks-emit-event-guard.mjs +370 -0
  246. package/scripts/lib/validate/check-hooks-symmetry.mjs +29 -63
  247. package/scripts/lib/validate/check-playwright-mcp-canary.mjs +13 -22
  248. package/scripts/lib/validate/check-plugin-monitors.mjs +10 -4
  249. package/scripts/lib/validate/check-skill-script-paths.mjs +436 -0
  250. package/scripts/lib/validate/check-test-value-bans.mjs +165 -17
  251. package/scripts/lib/validate/check-untracked-test-deps.mjs +10 -0
  252. package/scripts/lib/validate/check-unwired-features.mjs +333 -32
  253. package/scripts/lib/validate/check-validator-registration.mjs +248 -0
  254. package/scripts/lib/validate/check-vcs-repo-flag.mjs +6 -28
  255. package/scripts/lib/validate/markdown-fences.mjs +196 -0
  256. package/scripts/lib/validate/repo-files.mjs +275 -0
  257. package/scripts/lib/validate-vendored-rules.mjs +229 -7
  258. package/scripts/lib/vault-mirror/process.mjs +99 -43
  259. package/scripts/lib/vault-mirror/telemetry.mjs +210 -0
  260. package/scripts/lib/vault-staleness-banner.mjs +76 -6
  261. package/scripts/lib/vault-status/board-lock.mjs +185 -0
  262. package/scripts/lib/vault-status/board-writer.mjs +381 -141
  263. package/scripts/lib/vault-status/narrative-mirror.mjs +190 -27
  264. package/scripts/lib/wave-executor/foreign-dispatch.mjs +832 -0
  265. package/scripts/lib/wave-executor/remote-dispatch.mjs +504 -0
  266. package/scripts/lib/wave-resource-gate.mjs +127 -7
  267. package/scripts/lib/wave-transcript-tail.mjs +889 -0
  268. package/scripts/materialize-wave-scope.mjs +228 -15
  269. package/scripts/mcp-server.sh +11 -2
  270. package/scripts/memory-propose.mjs +132 -8
  271. package/scripts/parse-config.mjs +65 -0
  272. package/scripts/promote-vault-strict.mjs +4 -15
  273. package/scripts/site-numbers.mjs +36 -4
  274. package/scripts/token-audit.sh +9 -2
  275. package/scripts/validate-plugin.mjs +29 -0
  276. package/scripts/validate-wave-scope.mjs +67 -0
  277. package/scripts/vault-consolidate.mjs +3 -11
  278. package/scripts/vault-integration-watcher.mjs +2 -4
  279. package/scripts/vault-mirror.mjs +305 -51
  280. package/skills/_shared/monitor-patterns.md +31 -5
  281. package/skills/_shared/parallel-aware-auq.md +31 -2
  282. package/skills/_shared/parallel-aware-preamble.md +19 -4
  283. package/skills/_shared/platform-tools.md +11 -5
  284. package/skills/_shared/state-ownership.md +29 -2
  285. package/skills/autopilot/SKILL.md +5 -1
  286. package/skills/bootstrap/SKILL.md +3 -3
  287. package/skills/bootstrap/_shared-template.md +18 -10
  288. package/skills/bootstrap/deep-template.md +10 -6
  289. package/skills/bootstrap/fast-template.md +15 -8
  290. package/skills/bootstrap/standard-template.md +10 -6
  291. package/skills/claude-md-drift-check/checker.mjs +39 -11
  292. package/skills/contract-version-bump/SKILL.md +1 -1
  293. package/skills/dispatcher/SKILL.md +1 -1
  294. package/skills/ecosystem-health/SKILL.md +4 -1
  295. package/skills/ecosystem-health/wizard.md +5 -0
  296. package/skills/evolve/SKILL.md +38 -1
  297. package/skills/journey-audit/SKILL.md +270 -0
  298. package/skills/peekaboo-driver/SKILL.md +15 -3
  299. package/skills/persona-panel/SKILL.md +1 -1
  300. package/skills/reconcile/SKILL.md +46 -3
  301. package/skills/remote-offload/SKILL.md +89 -0
  302. package/skills/session-end/SKILL.md +17 -4
  303. package/skills/session-end/metrics-collection.md +7 -4
  304. package/skills/session-end/phase-3-6-tail.md +20 -9
  305. package/skills/session-end/phase-3-7a-recommendations.md +16 -2
  306. package/skills/session-plan/SKILL.md +6 -1
  307. package/skills/session-plan/wave-template.md +1 -0
  308. package/skills/session-start/SKILL.md +54 -17
  309. package/skills/session-start/phase-7-5-mode-selector.md +15 -3
  310. package/skills/session-start/phase-8-5-express-path.md +77 -12
  311. package/skills/vault-sync/validator.mjs +31 -0
  312. package/skills/wave-executor/SKILL.md +5 -3
  313. package/skills/wave-executor/circuit-breaker.md +34 -9
  314. package/skills/wave-executor/wave-loop.md +143 -22
  315. package/templates/_shared/journey-manifest.md +110 -0
  316. package/templates/_shared/rules/parallel-sessions.md +0 -77
@@ -9,6 +9,12 @@
9
9
  * G1 tool filter — only Edit/Write/MultiEdit are gated
10
10
  * G2 file_path present + string
11
11
  * G3 wave-scope.json exists
12
+ * G3b (#1123, #1194) the manifest belongs to THIS session — a manifest that
13
+ * PROVABLY names another live session in this shared working copy is not
14
+ * ours to enforce; allow + emit one event. Runs AFTER the parse so a
15
+ * corrupt manifest still fails closed. Identity is PROCESS-LOCAL only
16
+ * (hook payload + CLAUDE_CODE_SESSION_ID), never the repo-global
17
+ * `session.lock` — see the gate's own block for why.
12
18
  * G4 path-guard gate enabled
13
19
  * G5 enforcement != "off"
14
20
  * G5b (#792) allowlist-first: an EXPLICIT absolute allowedPaths entry that
@@ -98,6 +104,11 @@ let readJson;
98
104
  let classifyEmptyScope;
99
105
  let suggestForEmptyScope;
100
106
  let sessionStartedAtMs;
107
+ // #1123 — "is this manifest even mine?" (G3b). Process-local identity only
108
+ // (#1194): the repo-global `session.lock` tier is shared by every session in the
109
+ // checkout and would classify a peer's manifest as ours.
110
+ let readProcessLocalSessionIds;
111
+ let classifyManifestSession;
101
112
 
102
113
  const PLUGIN_ROOT = path.resolve(import.meta.dirname, '..');
103
114
 
@@ -154,6 +165,10 @@ async function bootstrap() {
154
165
  // `scope-gate` transitively, so this adds no new failure mode — a broken
155
166
  // scope-gate already banners GUARD INACTIVE through that edge.
156
167
  scopeGate: { specifier: lib('scope-gate.mjs') },
168
+ // #1123. Bound through the same loader as every other repo dependency, so
169
+ // a SyntaxError in the identity module banners GUARD INACTIVE instead of
170
+ // link-crashing the hook into a silent fail-open (#993).
171
+ sessionIdentity: { specifier: lib('session-identity/own-session.mjs') },
157
172
  },
158
173
  {
159
174
  hookName: HOOK_NAME,
@@ -169,6 +184,7 @@ async function bootstrap() {
169
184
  ({ findScopeFile, pathMatchesPattern, suggestForScopeViolation } = modules.hardening);
170
185
  ({ readJson } = modules.common);
171
186
  ({ classifyEmptyScope, suggestForEmptyScope, sessionStartedAtMs } = modules.scopeGate);
187
+ ({ readProcessLocalSessionIds, classifyManifestSession } = modules.sessionIdentity);
172
188
  }
173
189
 
174
190
  async function main() {
@@ -220,6 +236,83 @@ async function main() {
220
236
  scope = {};
221
237
  }
222
238
 
239
+ // -------------------------------------------------------------------------
240
+ // Gate 3b (#1123) — is this manifest even MINE?
241
+ //
242
+ // `wave-scope.json` lives in the WORKING COPY, not in the session. Two live
243
+ // sessions sharing one checkout read the same file, so session A's manifest
244
+ // enforced session B's writes: measured 2026-08-22 (#1082), where a Discovery
245
+ // wave's `allowedPaths: []` — which `wave-loop.md` prescribes for EVERY
246
+ // Discovery wave — denied every write of an unrelated parallel session, with
247
+ // a deny reason that could only tell it to fix a wave plan it does not own.
248
+ //
249
+ // Deliberately runs AFTER the parse block: a corrupt manifest yields `{}`,
250
+ // hence no ids, hence `'unknown'` — and keeps failing closed. A gate that
251
+ // peeked at the raw bytes instead would let a truncated manifest disarm the
252
+ // guard.
253
+ //
254
+ // `'own'` and `'unknown'` fall through completely unchanged. A legacy manifest
255
+ // without a `session` field is `'unknown'` and stays enforced: only what is
256
+ // PROVABLY foreign is treated as foreign.
257
+ //
258
+ // IDENTITY TIER (#1194): `readProcessLocalSessionIds` — the hook payload and
259
+ // `CLAUDE_CODE_SESSION_ID` — and deliberately NOT `readOwnSessionIds`, whose
260
+ // third tier is the repo-global `session.lock`. That lock is ONE file shared
261
+ // by every session in the checkout, so unioning it made a peer's manifest
262
+ // match a peer-written lock id and classify as `'own'`: Gate 7 then denied the
263
+ // second session's legitimate writes — the exact lockout G3b exists to end.
264
+ // A better signal REPLACES a worse one (`host-resources.md` § HR-102).
265
+ //
266
+ // The trade this buys, accepted rather than hidden: a session that wrote a
267
+ // PEER's id into its OWN manifest (it lost the `bootstrapLock()` race, so
268
+ // `sessionAttribution()` handed it the peer's lock id) now reads `'foreign'`
269
+ // and its own guard stands down. The defense is on the WRITER side — the
270
+ // manifest writer must omit the `session` keys when the lock does not name it
271
+ // (`skills/wave-executor/wave-loop.md` § Scope Manifest, "Verify the binding
272
+ // names YOU before you write it") — not on this reader.
273
+ //
274
+ // CEILING (BV-004): on a harness that exports no session env var and puts no
275
+ // `session_id` in the hook payload (Codex CLI, Cursor today), both tiers are
276
+ // empty, so G3b is permanently `'unknown'` = enforce = pre-#1123 behaviour
277
+ // there. Revisit when Codex/Cursor hook payloads carry a session id.
278
+ //
279
+ // ACCEPTED RESIDUAL, named rather than hidden: `session` is a plain field in a
280
+ // file any process in this working copy can write, so writing a foreign id
281
+ // into it switches this guard off for that manifest. That is the SAME power
282
+ // `enforcement: "off"` already grants in the same file — this gate adds no new
283
+ // authority, and the manifest is the coordinator's own artefact either way.
284
+ {
285
+ // `new Set(...)` is load-bearing: `readProcessLocalSessionIds` returns a
286
+ // string[], and `classifyManifestSession` does `ownIds instanceof Set ?
287
+ // ownIds : new Set()` — a bare array would silently become EMPTY, making
288
+ // every manifest read `unknown`.
289
+ const ownIds = new Set(readProcessLocalSessionIds({ hookInput: input }));
290
+ const { verdict, manifestIds } = classifyManifestSession(scope, ownIds);
291
+ if (verdict === 'foreign') {
292
+ // Observability only, and deliberately NOT emitWarn: this branch is hit on
293
+ // every single Edit of the non-owning session, so a stderr line per write
294
+ // would be noise the operator learns to ignore. One event per decision
295
+ // point, awaited before emitAllow() — emitAllow() calls process.exit(),
296
+ // which would discard a pending append.
297
+ try {
298
+ const { emitEvent } = await import('../scripts/lib/events.mjs');
299
+ await emitEvent(
300
+ 'orchestrator.scope.foreign_session_ignored',
301
+ {
302
+ hook: HOOK_NAME,
303
+ manifest: scopePath,
304
+ manifest_session: manifestIds,
305
+ own_session: [...ownIds],
306
+ wave: scope.wave,
307
+ file_path: filePath,
308
+ },
309
+ { repoRoot: projectRoot },
310
+ );
311
+ } catch { /* observability is best-effort — never blocks the decision */ }
312
+ return emitAllow();
313
+ }
314
+ }
315
+
223
316
  const enforcement = scope.enforcement ?? 'strict';
224
317
  const allowedPaths = Array.isArray(scope.allowedPaths) ? scope.allowedPaths : [];
225
318
  // A PRESENT-but-non-array `allowedPaths` (#558: null / string / object) is a
@@ -7,7 +7,7 @@
7
7
  "hooks": [
8
8
  {
9
9
  "type": "command",
10
- "command": "echo '🎯 Session Orchestrator v3.22.0 — /session [housekeeping|feature|deep] | /plan [new|feature|retro] | /discovery [scope] | /evolve [analyze|review|list]'",
10
+ "command": "echo '🎯 Session Orchestrator v3.24.0 — /session [housekeeping|feature|deep] | /plan [new|feature|retro] | /discovery [scope] | /evolve [analyze|review|list]'",
11
11
  "async": false
12
12
  },
13
13
  {
@@ -1,24 +1,205 @@
1
1
  {
2
- "_comment": "Cursor IDE hook mapping reference. Configure hooks in Cursor Settings > Hooks.",
3
- "_note": "Cursor hooks fire at different lifecycle points than Claude Code. See docs/cursor-setup.md for details.",
4
- "_limitation": "SessionStart greeting (session-start skill) is NOT available on Cursor. Cursor has no conversation-start lifecycle event equivalent to Claude Code's UserPromptSubmit hook. Session initialisation must be triggered manually.",
5
- "_enforcement": "reference-only",
6
- "_enforcement_note": "MACHINE-READABLE STATUS (#919): every entry below is an intended mapping, NOT live enforcement. No Cursor payload adapter exists (Pi has scripts/lib/pi-hook-bridge.mjs; Cursor has nothing), so each handler short-circuits on a Cursor-shaped payload and writes 0 bytes with exit 0. Operator decision 2026-07-31: gap registered, not closed. The machine-readable counterpart of this key is DOCUMENTED_ASYMMETRIES.handlerAsymmetries.cursor in scripts/lib/validate/check-hooks-symmetry.mjs, which Check 6 counts per event; the projection that makes that comparison non-vacuous is DOCUMENTED_ASYMMETRIES.cursorEventMap.",
7
- "_issues": ["#919", "#946"],
2
+ "_comment": "Cursor IDE hook mapping. Event names are Cursor-native; commands receive Claude/Codex-compatible hook JSON on stdin after scripts/lib/cursor-hook-bridge.mjs normalises the payload. CURSOR_PLUGIN_ROOT is set by the bridge; CURSOR_RULES_DIR is the compatibility alias used by plugin-root resolution.",
3
+ "_enforcement": "live",
4
+ "_enforcement_note": "LIVE via scripts/lib/cursor-hook-bridge.mjs and .cursor/hooks.json. The bridge maps Cursor stdin onto tool_name / tool_input and maps emitDeny envelopes onto Cursor { permission }. afterFileEdit remains post-hoc (cannot prevent an edit already written).",
5
+ "_issues": ["#919"],
8
6
  "hooks": {
9
- "afterFileEdit": {
10
- "script": "hooks/enforce-scope.mjs",
11
- "enforcement": "none",
12
- "issue": "#919",
13
- "mapsToClaudeEvent": "PostToolUse",
14
- "note": "Post-hoc scope warning — Cursor fires AFTER the edit (not before), so this maps onto PostToolUse, never PreToolUse. Cannot prevent out-of-scope edits, only warn — and today not even that: on a Cursor afterFileEdit payload enforce-scope.mjs writes 0 bytes to stdout AND stderr with exit 0 (measured 2026-07-31), because it reads Claude Code's PreToolUse field names."
15
- },
16
- "beforeShellExecution": {
17
- "script": "hooks/enforce-commands.mjs",
18
- "enforcement": "none",
19
- "issue": "#919",
20
- "mapsToClaudeEvent": "PreToolUse",
21
- "note": "NOT WIRED (#919) — silent no-op on a Cursor payload, NOT a block. The handler reads Claude Code's PreToolUse field names (tool_name === 'Bash', tool_input.command) and emits a Claude Code PreToolUse envelope (hookSpecificOutput.permissionDecision). Fed a Cursor beforeShellExecution payload it short-circuits at gate G1 and writes 0 bytes to stdout AND stderr with exit 0 — the harness sees no decision, so the command runs. Cursor needs an input/output adapter like scripts/lib/pi-hook-bridge.mjs; none exists. Treat this entry as the intended mapping, not as live enforcement."
22
- }
7
+ "sessionStart": [
8
+ {
9
+ "matcher": "",
10
+ "hooks": [
11
+ {
12
+ "type": "command",
13
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/on-session-start.mjs\"",
14
+ "timeout": 5
15
+ }
16
+ ]
17
+ }
18
+ ],
19
+ "sessionEnd": [
20
+ {
21
+ "matcher": "",
22
+ "hooks": [
23
+ {
24
+ "type": "command",
25
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/on-session-end.mjs\"",
26
+ "timeout": 5
27
+ }
28
+ ]
29
+ }
30
+ ],
31
+ "beforeShellExecution": [
32
+ {
33
+ "matcher": "*",
34
+ "hooks": [
35
+ {
36
+ "type": "command",
37
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/pre-bash-destructive-guard.mjs\"",
38
+ "timeout": 5
39
+ },
40
+ {
41
+ "type": "command",
42
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/pre-bash-staging-fence.mjs\"",
43
+ "timeout": 5
44
+ },
45
+ {
46
+ "type": "command",
47
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/pre-bash-memory-propose-audit.mjs\"",
48
+ "timeout": 5
49
+ },
50
+ {
51
+ "type": "command",
52
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/pre-bash-sessions-ledger-guard.mjs\"",
53
+ "timeout": 5
54
+ },
55
+ {
56
+ "type": "command",
57
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/pre-bash-templates-first.mjs\"",
58
+ "timeout": 5
59
+ },
60
+ {
61
+ "type": "command",
62
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/pre-bash-issue-budget.mjs\"",
63
+ "timeout": 5
64
+ },
65
+ {
66
+ "type": "command",
67
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/enforce-commands.mjs\"",
68
+ "timeout": 5
69
+ }
70
+ ]
71
+ }
72
+ ],
73
+ "preToolUse": [
74
+ {
75
+ "matcher": "Write|StrReplace|TabWrite|Edit|MultiEdit",
76
+ "hooks": [
77
+ {
78
+ "type": "command",
79
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/enforce-scope.mjs\"",
80
+ "timeout": 5
81
+ },
82
+ {
83
+ "type": "command",
84
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/config-protection.mjs\"",
85
+ "timeout": 5
86
+ }
87
+ ]
88
+ }
89
+ ],
90
+ "afterShellExecution": [
91
+ {
92
+ "matcher": "*",
93
+ "hooks": [
94
+ {
95
+ "type": "command",
96
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/post-bash-write-verify.mjs\"",
97
+ "timeout": 5
98
+ }
99
+ ]
100
+ }
101
+ ],
102
+ "postToolUse": [
103
+ {
104
+ "matcher": "Write|StrReplace|TabWrite|Edit|MultiEdit",
105
+ "hooks": [
106
+ {
107
+ "type": "command",
108
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/post-edit-validate.mjs\"",
109
+ "timeout": 5
110
+ },
111
+ {
112
+ "type": "command",
113
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/post-tooluse-frontend-slop.mjs\"",
114
+ "timeout": 5
115
+ }
116
+ ]
117
+ },
118
+ {
119
+ "matcher": "*",
120
+ "hooks": [
121
+ {
122
+ "type": "command",
123
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/loop-guard.mjs\"",
124
+ "timeout": 5
125
+ }
126
+ ]
127
+ }
128
+ ],
129
+ "afterFileEdit": [
130
+ {
131
+ "matcher": "*",
132
+ "hooks": [
133
+ {
134
+ "type": "command",
135
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/post-edit-validate.mjs\"",
136
+ "timeout": 5
137
+ },
138
+ {
139
+ "type": "command",
140
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/post-tooluse-frontend-slop.mjs\"",
141
+ "timeout": 5
142
+ }
143
+ ]
144
+ }
145
+ ],
146
+ "postToolUseFailure": [
147
+ {
148
+ "matcher": "",
149
+ "hooks": [
150
+ {
151
+ "type": "command",
152
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/post-tool-failure-corrective-context.mjs\"",
153
+ "timeout": 5
154
+ }
155
+ ]
156
+ }
157
+ ],
158
+ "stop": [
159
+ {
160
+ "matcher": "",
161
+ "hooks": [
162
+ {
163
+ "type": "command",
164
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/on-stop.mjs\"",
165
+ "timeout": 5
166
+ }
167
+ ]
168
+ }
169
+ ],
170
+ "subagentStart": [
171
+ {
172
+ "matcher": "",
173
+ "hooks": [
174
+ {
175
+ "type": "command",
176
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/subagent-telemetry.mjs\"",
177
+ "timeout": 5
178
+ }
179
+ ]
180
+ }
181
+ ],
182
+ "subagentStop": [
183
+ {
184
+ "matcher": "",
185
+ "hooks": [
186
+ {
187
+ "type": "command",
188
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/on-stop.mjs\"",
189
+ "timeout": 5
190
+ },
191
+ {
192
+ "type": "command",
193
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/subagent-telemetry.mjs\"",
194
+ "timeout": 5
195
+ },
196
+ {
197
+ "type": "command",
198
+ "command": "sh \"$CURSOR_PLUGIN_ROOT/hooks/run-node.sh\" \"$CURSOR_PLUGIN_ROOT/hooks/post-subagent-discovery-validator.mjs\"",
199
+ "timeout": 5
200
+ }
201
+ ]
202
+ }
203
+ ]
23
204
  }
24
205
  }
@@ -20,7 +20,7 @@
20
20
  {
21
21
  "type": "command",
22
22
  "command": "sh \"$PI_PLUGIN_ROOT/hooks/run-node.sh\" \"$PI_PLUGIN_ROOT/hooks/on-session-end.mjs\"",
23
- "timeout": 5
23
+ "timeout": 10
24
24
  }
25
25
  ]
26
26
  }
package/hooks/hooks.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "hooks": [
7
7
  {
8
8
  "type": "command",
9
- "command": "echo '🎯 Session Orchestrator v3.22.0 — /session [housekeeping|feature|deep] | /plan [new|feature|retro] | /discovery [scope] | /evolve [analyze|review|list]'",
9
+ "command": "echo '🎯 Session Orchestrator v3.24.0 — /session [housekeeping|feature|deep] | /plan [new|feature|retro] | /discovery [scope] | /evolve [analyze|review|list]'",
10
10
  "async": false
11
11
  },
12
12
  {
@@ -25,7 +25,7 @@
25
25
  {
26
26
  "type": "command",
27
27
  "command": "sh \"$CLAUDE_PLUGIN_ROOT/hooks/run-node.sh\" \"$CLAUDE_PLUGIN_ROOT/hooks/on-session-end.mjs\"",
28
- "timeout": 5
28
+ "timeout": 10
29
29
  }
30
30
  ]
31
31
  }