session-orchestrator 4.1.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/.agents/skills/session-plan/SKILL.md +1 -1
  2. package/.agents/skills/session-start/SKILL.md +1 -1
  3. package/.agents/skills/ux-grill/SKILL.md +22 -0
  4. package/.claude-plugin/marketplace.json +1 -1
  5. package/.claude-plugin/plugin.json +3 -2
  6. package/.codex-plugin/plugin.json +1 -1
  7. package/.codex-plugin/skills/session-plan/SKILL.md +1 -1
  8. package/.codex-plugin/skills/session-start/SKILL.md +1 -1
  9. package/.codex-plugin/skills/ux-grill/SKILL.md +21 -0
  10. package/.codex-plugin/skills/ux-grill/agents/openai.yaml +5 -0
  11. package/.cursor/commands/ux-grill.md +14 -0
  12. package/.cursor/skills/session-plan/SKILL.md +1 -1
  13. package/.cursor/skills/session-start/SKILL.md +1 -1
  14. package/.cursor/skills/ux-grill/SKILL.md +13 -0
  15. package/.cursor-plugin/plugin.json +1 -1
  16. package/AGENTS.md +2 -1
  17. package/CHANGELOG.md +128 -1
  18. package/README.md +98 -86
  19. package/agents/dialectic-deriver.md +11 -0
  20. package/agents/ux-evaluator.md +1 -1
  21. package/commands/close.md +3 -3
  22. package/commands/go.md +2 -0
  23. package/commands/memory-cleanup.md +4 -3
  24. package/commands/persona-panel.md +1 -1
  25. package/commands/session.md +3 -2
  26. package/commands/ux-grill.md +51 -0
  27. package/docs/README.md +4 -4
  28. package/docs/USER-GUIDE.md +117 -50
  29. package/docs/agent-authoring.md +2 -2
  30. package/docs/baseline.md +55 -1
  31. package/docs/ci-setup.md +1 -1
  32. package/docs/codex-setup.md +9 -0
  33. package/docs/components.md +9 -9
  34. package/docs/cursor-setup.md +1 -0
  35. package/docs/events-schema.md +13 -6
  36. package/docs/github-mirror-protection.md +61 -20
  37. package/docs/instruction-delivery.md +1 -1
  38. package/docs/memory-proposal-flow.md +3 -3
  39. package/docs/migration-v4.md +2 -2
  40. package/docs/migration-v5.md +62 -0
  41. package/docs/owner-config-schema.md +74 -90
  42. package/docs/persona-panel.md +4 -4
  43. package/docs/pi-setup.md +1 -0
  44. package/docs/rule-authoring.md +13 -6
  45. package/docs/scope-collision-guard.md +16 -0
  46. package/docs/session-config-reference.md +55 -22
  47. package/docs/session-config-template.md +9 -5
  48. package/docs/vault-docs-architecture.md +4 -2
  49. package/hooks/_lib/hook-import-set.json +70 -3
  50. package/hooks/_lib/lock-bootstrap.mjs +84 -1
  51. package/hooks/_lib/vcs-create-matcher.mjs +401 -16
  52. package/hooks/enforce-scope.mjs +201 -0
  53. package/hooks/hooks-codex.json +1 -1
  54. package/hooks/hooks-cursor.json +5 -0
  55. package/hooks/hooks.json +7 -2
  56. package/hooks/on-session-start.mjs +171 -49
  57. package/hooks/post-bash-issue-budget-refund.mjs +375 -0
  58. package/hooks/pre-auq-clarity.mjs +70 -18
  59. package/hooks/pre-bash-issue-budget.mjs +170 -26
  60. package/hooks/subagent-telemetry.mjs +106 -20
  61. package/package.json +5 -4
  62. package/pi/prompts/ux-grill.md +12 -0
  63. package/scripts/baseline-archetypes.mjs +28 -0
  64. package/scripts/ci/assert-vitest-green.mjs +4 -2
  65. package/scripts/dialectic-deriver.mjs +32 -8
  66. package/scripts/emit-session.mjs +72 -1
  67. package/scripts/lib/agent-status.mjs +441 -9
  68. package/scripts/lib/auq/schema.mjs +10 -3
  69. package/scripts/lib/auto-dialectic.mjs +0 -68
  70. package/scripts/lib/baseline-archetypes.mjs +439 -0
  71. package/scripts/lib/build-live-signals.mjs +5 -6
  72. package/scripts/lib/ci-status-banner.mjs +29 -6
  73. package/scripts/lib/claude-md-budget-lint.mjs +52 -2
  74. package/scripts/lib/config/issue-budget.mjs +68 -8
  75. package/scripts/lib/config/private-config-dir.mjs +3 -2
  76. package/scripts/lib/config/remote-hosts.mjs +2 -2
  77. package/scripts/lib/config-schema.mjs +79 -0
  78. package/scripts/lib/config.mjs +12 -1
  79. package/scripts/lib/eval/engine.mjs +7 -1
  80. package/scripts/lib/file-lock.mjs +151 -8
  81. package/scripts/lib/git-porcelain.mjs +113 -0
  82. package/scripts/lib/instruction-budget-guard.mjs +415 -47
  83. package/scripts/lib/io.mjs +29 -4
  84. package/scripts/lib/issue-budget-reconcile.mjs +392 -0
  85. package/scripts/lib/issue-budget.mjs +412 -9
  86. package/scripts/lib/learnings/evolve-telemetry.mjs +1 -2
  87. package/scripts/lib/learnings/sizing-subject.mjs +44 -0
  88. package/scripts/lib/locks/staging-fence-lock.mjs +19 -38
  89. package/scripts/lib/locks/state-md-lock.mjs +19 -41
  90. package/scripts/lib/maintenance-due-banner.mjs +450 -0
  91. package/scripts/lib/owner-config.example.yaml +29 -46
  92. package/scripts/lib/owner-yaml.mjs +14 -13
  93. package/scripts/lib/peer-cards/merger.mjs +143 -0
  94. package/scripts/lib/pre-dispatch-check.mjs +20 -14
  95. package/scripts/lib/project-hygiene.mjs +81 -30
  96. package/scripts/lib/quality-gate.mjs +27 -71
  97. package/scripts/lib/reconcile/engine.mjs +19 -1
  98. package/scripts/lib/reconcile/writer.mjs +278 -11
  99. package/scripts/lib/resource-probe/evaluate.mjs +19 -21
  100. package/scripts/lib/rules-sync.mjs +34 -4
  101. package/scripts/lib/scope-echo.mjs +346 -0
  102. package/scripts/lib/session-close-backfill.mjs +182 -40
  103. package/scripts/lib/session-end/phase-skip.mjs +85 -86
  104. package/scripts/lib/session-end/tail-runner.mjs +178 -0
  105. package/scripts/lib/session-lock.mjs +62 -2
  106. package/scripts/lib/session-record-repair.mjs +91 -0
  107. package/scripts/lib/session-schema/constants.mjs +6 -0
  108. package/scripts/lib/session-schema/filters.mjs +26 -1
  109. package/scripts/lib/session-schema/validator.mjs +20 -0
  110. package/scripts/lib/session-shape.mjs +558 -0
  111. package/scripts/lib/session-start-probes.mjs +429 -56
  112. package/scripts/lib/session-token-rollup.mjs +95 -10
  113. package/scripts/lib/state-md/frontmatter-mutators.mjs +22 -34
  114. package/scripts/lib/state-md.mjs +1 -0
  115. package/scripts/lib/subagents-schema.mjs +77 -9
  116. package/scripts/lib/telemetry/pricing.mjs +197 -0
  117. package/scripts/lib/telemetry/sync.mjs +50 -1
  118. package/scripts/lib/test-runner/artifact-paths.mjs +30 -5
  119. package/scripts/lib/test-runner/issue-reconcile.mjs +45 -8
  120. package/scripts/lib/tmux-layout/layouts.mjs +62 -4
  121. package/scripts/lib/ux-grill/collect.mjs +1163 -0
  122. package/scripts/lib/ux-grill/compare.mjs +285 -0
  123. package/scripts/lib/ux-grill/manifest.mjs +618 -0
  124. package/scripts/lib/ux-grill/measures.mjs +431 -0
  125. package/scripts/lib/ux-grill/paths.mjs +224 -0
  126. package/scripts/lib/ux-grill/pencil-coverage.mjs +284 -0
  127. package/scripts/lib/ux-grill/reconcile.mjs +344 -0
  128. package/scripts/lib/ux-grill/run-record.mjs +316 -0
  129. package/scripts/lib/ux-grill/schema.mjs +321 -0
  130. package/scripts/lib/validate/check-skill-script-paths.mjs +33 -10
  131. package/scripts/lib/validate/check-untracked-test-deps.mjs +33 -19
  132. package/scripts/lib/validate/check-unwired-features.mjs +56 -27
  133. package/scripts/lib/vault-mirror/process.mjs +2 -1
  134. package/scripts/lib/vault-status/board-lock.mjs +18 -0
  135. package/scripts/lib/vault-status/board-writer.mjs +8 -0
  136. package/scripts/lib/vault-status/narrative-mirror.mjs +4 -4
  137. package/scripts/lib/wave-resource-gate.mjs +23 -27
  138. package/scripts/lib/wave-sizing.mjs +10 -3
  139. package/scripts/materialize-wave-scope.mjs +68 -14
  140. package/scripts/mcp-server.sh +16 -1
  141. package/scripts/print-applicable-rules.mjs +7 -6
  142. package/scripts/print-learnings-index.mjs +3 -2
  143. package/scripts/release.mjs +7 -2
  144. package/scripts/session-shape.mjs +266 -0
  145. package/skills/_shared/config-reading.md +15 -9
  146. package/skills/_shared/private-capability-context.md +89 -0
  147. package/skills/bootstrap/SKILL.md +60 -209
  148. package/skills/bootstrap/_shared-template.md +99 -14
  149. package/skills/bootstrap/deep-template.md +36 -26
  150. package/skills/bootstrap/fast-template.md +44 -8
  151. package/skills/bootstrap/intensity-heuristic.md +10 -4
  152. package/skills/bootstrap/private-contract.md +119 -0
  153. package/skills/bootstrap/public-fallback.md +30 -18
  154. package/skills/bootstrap/references/bootstrap-ecosystem-health-flow.md +48 -0
  155. package/skills/bootstrap/references/bootstrap-refresh-lock-flow.md +37 -0
  156. package/skills/bootstrap/references/bootstrap-retroactive-flow.md +108 -0
  157. package/skills/bootstrap/references/bootstrap-rules-fetch-bridge.md +64 -0
  158. package/skills/bootstrap/standard-template.md +39 -24
  159. package/skills/claude-md-drift-check/SKILL.md +9 -2
  160. package/skills/claude-md-drift-check/checker.mjs +213 -21
  161. package/skills/discovery/SKILL.md +6 -173
  162. package/skills/discovery/probes/vault-staleness.mjs +35 -5
  163. package/skills/discovery/probes-docs.md +8 -4
  164. package/skills/discovery/probes-supply-chain.md +4 -2
  165. package/skills/discovery/probes-ui.md +8 -4
  166. package/skills/discovery/probes-vault.md +12 -4
  167. package/skills/discovery/references/discovery-interactive-triage.md +139 -0
  168. package/skills/discovery/references/discovery-triage-state.md +54 -0
  169. package/skills/docs-orchestrator/audience-mapping.md +1 -1
  170. package/skills/eval/rubric-v1.md +13 -0
  171. package/skills/evolve/SKILL.md +2 -458
  172. package/skills/evolve/references/evolve-analyze-mode.md +360 -0
  173. package/skills/evolve/references/evolve-dialectic-mode.md +139 -0
  174. package/skills/gitlab-ops/SKILL.md +3 -3
  175. package/skills/grill/SKILL.md +1 -1
  176. package/skills/memory-cleanup/SKILL.md +2 -2
  177. package/skills/plan/mode-new.md +9 -0
  178. package/skills/plan/mode-retro.md +4 -3
  179. package/skills/reconcile/SKILL.md +11 -1
  180. package/skills/session-end/SKILL.md +3 -2
  181. package/skills/session-end/drift-operations.md +20 -5
  182. package/skills/session-end/metrics-collection.md +1 -0
  183. package/skills/session-end/phase-3-2-docs-verification.md +1 -1
  184. package/skills/session-end/phase-3-6-tail.md +27 -67
  185. package/skills/session-end/phase-3-7a-recommendations.md +2 -2
  186. package/skills/session-end/references/phase-2-quality-gate.md +3 -3
  187. package/skills/session-end/references/phase-3-documentation-updates.md +8 -6
  188. package/skills/session-end/references/phase-5-issue-cleanup.md +32 -1
  189. package/skills/session-end/session-metrics-write.md +33 -12
  190. package/skills/session-plan/SKILL.md +46 -180
  191. package/skills/session-plan/references/session-plan-task-classification.md +152 -0
  192. package/skills/session-plan/wave-template.md +8 -15
  193. package/skills/session-start/SKILL.md +41 -7
  194. package/skills/session-start/phase-2-5-docs-planning.md +1 -1
  195. package/skills/session-start/phase-8-5-express-path.md +12 -9
  196. package/skills/session-start/references/operations-contract.md +114 -0
  197. package/skills/session-start/references/phase-1-5-session-continuity.md +2 -0
  198. package/skills/session-start/references/phase-4-ssot-environment-check.md +42 -24
  199. package/skills/session-start/references/phase-6-7-memory-banner-telemetry-consent.md +3 -1
  200. package/skills/session-start/soul.md +2 -2
  201. package/skills/test-runner/SKILL.md +1 -1
  202. package/skills/test-runner/rubric-v1.md +2 -2
  203. package/skills/tmux-layout/SKILL.md +3 -1
  204. package/skills/ux-grill/SKILL.md +211 -0
  205. package/skills/ux-grill/rubric-v2.md +201 -0
  206. package/skills/ux-grill/soul.md +76 -0
  207. package/skills/wave-executor/SKILL.md +32 -127
  208. package/skills/wave-executor/circuit-breaker.md +3 -1
  209. package/skills/wave-executor/references/wave-executor-quality-gate.md +61 -0
  210. package/skills/wave-executor/references/wave-executor-state-init.md +86 -0
  211. package/skills/wave-executor/references/wave-loop-dispatch.md +12 -2
  212. package/skills/wave-executor/references/wave-loop-review.md +19 -6
  213. package/skills/wave-executor/references/wave-loop-scope-manifest.md +6 -2
  214. package/templates/_shared/ux-manifest.template.md +149 -0
  215. package/templates/nextjs-minimal/package.json +1 -1
  216. package/templates/node-minimal/package.json +1 -1
  217. package/scripts/lib/multi-provider-build/providers.mjs +0 -64
  218. package/scripts/lib/multi-provider-build/templating.mjs +0 -130
  219. package/scripts/lib/owner-config/coerce.mjs +0 -29
  220. package/scripts/lib/owner-config/constants.mjs +0 -21
  221. package/scripts/lib/owner-config/defaults.mjs +0 -50
  222. package/scripts/lib/owner-config/error.mjs +0 -19
  223. package/scripts/lib/owner-config/index.mjs +0 -13
  224. package/scripts/lib/owner-config/merge.mjs +0 -52
  225. package/scripts/lib/owner-config/validate.mjs +0 -259
  226. package/scripts/lib/owner-config-loader.mjs +0 -170
  227. package/scripts/lib/owner-config.mjs +0 -28
  228. package/scripts/lib/soul-resolve.mjs +0 -130
  229. package/scripts/lib/vault-mirror/render.mjs +0 -8
  230. package/templates/_shared/journey-manifest.md +0 -114
@@ -36,8 +36,8 @@ These seven fields are enforced by `scripts/lib/config-schema.mjs`. Validation i
36
36
  test-command: npm test # non-empty string — quality-gate test runner
37
37
  typecheck-command: npm run typecheck # non-empty string — canonical typecheck runner
38
38
  lint-command: npm run lint # non-empty string — Full Gate lint runner
39
- agents-per-wave: 6 # integer ≥ 2 (or { default: 6, deep: 18 })
40
- waves: 5 # integer ≥ 3 — execution wave count
39
+ agents-per-wave: 6 # integer ≥ 2 (or { default: 6, deep: 18 }) — see § Session Structure
40
+ waves: 5 # integer ≥ 3 — base count; actual wave count is resolved per session type by `scripts/session-shape.mjs`
41
41
  persistence: true # boolean — STATE.md + memory file resumption
42
42
  enforcement: warn # strict | warn | off — hook strictness AND validator gate
43
43
  ```
@@ -50,13 +50,15 @@ Controls wave count, parallelism, and freeform per-repo notes the orchestrator m
50
50
 
51
51
  ```yaml
52
52
  agents-per-wave: 6 # integer or "6 (deep: 18)" override syntax
53
- waves: 5 # integer ≥ 3
53
+ waves: 5 # integer ≥ 3 — base count only; resolved shape may ignore it (see below)
54
54
  recent-commits: 20 # how many commits to display at session-start
55
55
  special: "any repo-specific instructions" # freeform — orchestrator reads + obeys
56
56
  ```
57
57
 
58
58
  Read by: `skills/session-start/SKILL.md` (Phase 4.5), `skills/session-plan/SKILL.md`, `skills/wave-executor/wave-loop.md`.
59
59
 
60
+ **Wave count, roles and per-wave agent caps are resolved by `scripts/session-shape.mjs`, not derived from `waves` by hand.** Housekeeping is always 1 coordinator-direct maintenance-loop wave; feature is 3 waves (Impl-Core / Impl-Polish+Quality / Finalization); deep is 5 waves (4 when the scope is already known — Discovery is dropped); the `ultradeep` profile is a fixed 7-wave shape that IGNORES `waves` entirely (`wavesConfigHonored: false`). `agents-per-wave` resolves via `resolveAgentCap()` in the same module. Full table: [`session-config-reference.md` § Session Shapes](./session-config-reference.md#session-shapes).
61
+
60
62
  **The override key set is open.** `_coerceInteger` (`scripts/lib/config/coercers.mjs`) parses whatever keys stand inside the parentheses, so `agents-per-wave: 6 (deep: 18, ultradeep: 18)` is valid today with no code change — it yields `{"default": 6, "deep": 18, "ultradeep": 18}`.
61
63
 
62
64
  **`session-profile` is NOT a Session Config key — do not add one here.** The wave-shape profile (`ultradeep`) lives in STATE.md frontmatter, written per session by the `/session ultradeep` argument alias, and is absent by default. `parseSessionConfig()` emits no such key, so writing one into a repo's `## Session Config` block is inert prose — the same trap as `session-type:`. Full contract: [`session-config-reference.md` § Session Profile](./session-config-reference.md). The PRD's `ultradeep.max-*` budget block is deliberately NOT implemented and no key of that name is read anywhere (deferred until measured, HR-105).
@@ -151,7 +153,7 @@ reasoning-output: false # opt-in STATE:/PLAN: agent transparency
151
153
  grounding-check: true # session-end Phase 1.1a planned-vs-touched diff
152
154
  grounding-injection-max-files: 3 # 0 disables (#85)
153
155
  isolation: auto # worktree | none | auto (graduated default #194)
154
- max-turns: auto # housekeeping=8, feature=15, deep=25
156
+ max-turns: auto # per session shape (scripts/lib/session-shape.mjs): 8/15/25; ultradeep is per-wave 40/25/15
155
157
  auto-commit-per-wave: false # opt-in: commit after each wave's Quality-Lite PASS (default false; V3.6 plumbing)
156
158
  ```
157
159
 
@@ -482,7 +484,9 @@ Read by: `scripts/lib/config/dialectic.mjs`, `scripts/lib/auto-dialectic.mjs`, `
482
484
 
483
485
  ## Eval (#803)
484
486
 
485
- Opt-in configuration for the Standard v1 evaluation harness and the forthcoming `/eval` skill (Session-Prozess-Eval PRD `docs/prd/2026-07-16-aiat-llm-eval.md` §S6, follow-up wave of Epic #803). This section documents the config surface only; the skill consumer lands in a later wave.
487
+ Opt-in configuration for the Standard v1 evaluation harness and `/eval` (Session-Prozess-Eval); see `skills/eval/SKILL.md` for the current workflow.
488
+
489
+ The original config proposal is in the archived PRD `docs/prd/2026-07-16-aiat-llm-eval.md` §S6 (Epic #803). <!-- path-check: historical -->
486
490
 
487
491
  ```yaml
488
492
  eval:
@@ -123,11 +123,13 @@ Data flow within a single `/session feature → /go → /close` cycle:
123
123
  | `vault-staleness` probes | `skills/discovery/probes-vault.md` + `skills/discovery/probes/vault-staleness.mjs` | `/discovery vault` (on-demand) and session-end Phase 2.3 (opt-in close-time gate) | `VAULT_DIR/01-projects/*/` `_overview.md` + narrative files | JSONL findings under `.orchestrator/metrics/vault-staleness.jsonl` and `vault-narrative-staleness.jsonl` | Vault/Ops (telemetry) |
124
124
  | `docs-orchestrator` | `skills/docs-orchestrator/SKILL.md` | session-start Phase 2.5, session-plan Step 1.5/1.8, session-end Phase 3.2 (all gated on `enabled: true`) | Session scope + Session Config audience list | `docs-tasks` block in STATE.md (write side); `### Documentation Coverage` block in final report (verify side) | All three (User / Dev / Vault) |
125
125
  | `docs-writer` agent | `agents/docs-writer.md` | Dispatched by `wave-executor` for each `Docs`-classified task | `diff`, `git-log`, `session-memory`, `affected-files` | Audience-targeted Markdown writes (Edit/Write); `[docs-orchestrator] Docs task complete` report line | All three (per task) |
126
- | `narrative-mirror` | `scripts/lib/vault-status/narrative-mirror.mjs` (`mirrorNarrative`) | session-end Phase 3.7, gated on `vault-integration.enabled` | `.claude/STATE.md` narrative sections + the session record | `<vault>/01-projects/<repo-slug>/_session-narrative.md` (generator-marked) | Vault/Ops (durable per-repo narrative) |
126
+ | `narrative-mirror` | `scripts/lib/vault-status/narrative-mirror.mjs` (`mirrorNarrative`) | session-end Phase 3.7, gated on `vault-integration.enabled` | Generated session-state narrative sections (see input note below) + the session record | `<vault>/01-projects/<repo-slug>/_session-narrative.md` (generator-marked) | Vault/Ops (durable per-repo narrative) |
127
127
  | `board-writer` | `scripts/lib/vault-status/board-writer.mjs` (`sweepBoard` / `mirrorBoard`) | session-start Phase 1.7 (`in-progress`) and session-end Phase 3.7c (`closed`), gated on `vault-integration.enabled` | live session registry + this repo's root | `<vault>/01-projects/_active-sessions.md` — one row per repo (generator-marked, idempotent, never touches `_overview.md`) | Vault/Ops (cross-repo occupancy board) |
128
128
  | `vault-mirror` | `skills/vault-mirror/SKILL.md` + `scripts/vault-mirror.mjs` | session-end Phase 3.7 (sessions); evolve Phase 3.5 (learnings) | `.orchestrator/metrics/sessions.jsonl`, `.orchestrator/metrics/learnings.jsonl` | `<vault>/50-sessions/<id>.md`, `<vault>/40-learnings/<slug>.md` (`_generator` marker `session-orchestrator-vault-mirror@1`) | Vault/Ops (telemetry → Markdown) |
129
129
  | `vault-backfill` CLI | `scripts/vault-backfill.mjs` | Manual, also surfaced via `/plan retro vault-backfill` sub-mode | `vault-integration.gitlab-groups` config + GitLab API | `.vault.yaml` per repo + Vault stub directories | Vault/Ops (one-shot migration) |
130
130
 
131
+ The narrative mirror reads narrative sections from the generated `.claude/STATE.md` input, together with the session record. <!-- path-check: example -->
132
+
131
133
  ---
132
134
 
133
135
  ## 4. Audience Model
@@ -138,7 +140,7 @@ table), which is the **single source of truth** for which files belong to
138
140
  which audience. Never inline this table elsewhere — always cross-link.
139
141
 
140
142
  - **User** — external/internal users of the repo. Targets: `README.md`,
141
- `docs/user/**/*.md`, `docs/getting-started.md`, `examples/**/*.md`. Source:
143
+ `docs/user/**/*.md`, `docs/getting-started.md`, `examples/**/*.md`. Source: <!-- path-check: example -->
142
144
  `skills/docs-orchestrator/audience-mapping.md` § Audiences & File Patterns.
143
145
  - **Dev** — contributors to the repo, including future Claude sessions.
144
146
  Targets: `CLAUDE.md`, `docs/dev/**/*.md`, `docs/adr/**/*.md`. Source: same.
@@ -1,6 +1,6 @@
1
1
  {
2
- "generated_at": "2026-09-07T18:36:32.142Z",
3
- "head": "a244b8707aa5bb650673fce2e6cf548564b43e58",
2
+ "generated_at": "2026-09-13T09:10:50.839Z",
3
+ "head": "ff1ed19177795b743186eebfc387319de0e90c31",
4
4
  "entries": [
5
5
  {
6
6
  "file": "hooks/_lib/atomic-json.mjs",
@@ -46,6 +46,7 @@
46
46
  "on-session-start.mjs",
47
47
  "on-stop.mjs",
48
48
  "operator-steer.mjs",
49
+ "post-bash-issue-budget-refund.mjs",
49
50
  "post-bash-write-verify.mjs",
50
51
  "post-edit-import-probe.mjs",
51
52
  "post-edit-validate.mjs",
@@ -68,6 +69,7 @@
68
69
  {
69
70
  "file": "hooks/_lib/subagent-paths.mjs",
70
71
  "reachable_from": [
72
+ "enforce-scope.mjs",
71
73
  "on-stop.mjs",
72
74
  "post-subagent-discovery-validator.mjs",
73
75
  "subagent-telemetry.mjs"
@@ -88,6 +90,7 @@
88
90
  {
89
91
  "file": "hooks/_lib/vcs-create-matcher.mjs",
90
92
  "reachable_from": [
93
+ "post-bash-issue-budget-refund.mjs",
91
94
  "pre-bash-issue-budget.mjs",
92
95
  "pre-bash-templates-first.mjs"
93
96
  ]
@@ -146,6 +149,12 @@
146
149
  "operator-steer.mjs"
147
150
  ]
148
151
  },
152
+ {
153
+ "file": "hooks/post-bash-issue-budget-refund.mjs",
154
+ "reachable_from": [
155
+ "post-bash-issue-budget-refund.mjs"
156
+ ]
157
+ },
149
158
  {
150
159
  "file": "hooks/post-bash-write-verify.mjs",
151
160
  "reachable_from": [
@@ -291,6 +300,7 @@
291
300
  {
292
301
  "file": "scripts/lib/command-blocker.mjs",
293
302
  "reachable_from": [
303
+ "post-bash-issue-budget-refund.mjs",
294
304
  "post-bash-write-verify.mjs",
295
305
  "post-edit-validate.mjs",
296
306
  "post-tool-batch-wave-signal.mjs",
@@ -305,6 +315,7 @@
305
315
  "on-session-end.mjs",
306
316
  "on-session-start.mjs",
307
317
  "on-stop.mjs",
318
+ "post-bash-issue-budget-refund.mjs",
308
319
  "post-edit-validate.mjs",
309
320
  "post-subagent-discovery-validator.mjs",
310
321
  "pre-bash-issue-budget.mjs",
@@ -337,6 +348,7 @@
337
348
  "on-session-end.mjs",
338
349
  "on-session-start.mjs",
339
350
  "on-stop.mjs",
351
+ "post-bash-issue-budget-refund.mjs",
340
352
  "post-bash-write-verify.mjs",
341
353
  "post-edit-import-probe.mjs",
342
354
  "post-edit-validate.mjs",
@@ -359,6 +371,7 @@
359
371
  "on-session-end.mjs",
360
372
  "on-session-start.mjs",
361
373
  "on-stop.mjs",
374
+ "post-bash-issue-budget-refund.mjs",
362
375
  "post-bash-write-verify.mjs",
363
376
  "post-edit-import-probe.mjs",
364
377
  "post-edit-validate.mjs",
@@ -384,7 +397,9 @@
384
397
  "reachable_from": [
385
398
  "on-session-end.mjs",
386
399
  "on-session-start.mjs",
387
- "post-edit-validate.mjs"
400
+ "post-bash-issue-budget-refund.mjs",
401
+ "post-edit-validate.mjs",
402
+ "pre-bash-issue-budget.mjs"
388
403
  ]
389
404
  },
390
405
  {
@@ -549,6 +564,7 @@
549
564
  "reachable_from": [
550
565
  "on-session-end.mjs",
551
566
  "on-session-start.mjs",
567
+ "post-bash-issue-budget-refund.mjs",
552
568
  "post-edit-validate.mjs",
553
569
  "pre-bash-issue-budget.mjs"
554
570
  ]
@@ -593,6 +609,7 @@
593
609
  "on-session-end.mjs",
594
610
  "on-session-start.mjs",
595
611
  "on-stop.mjs",
612
+ "post-bash-issue-budget-refund.mjs",
596
613
  "post-bash-write-verify.mjs",
597
614
  "post-edit-import-probe.mjs",
598
615
  "post-edit-validate.mjs",
@@ -600,6 +617,7 @@
600
617
  "post-tool-batch-wave-signal.mjs",
601
618
  "post-tooluse-frontend-slop.mjs",
602
619
  "pre-auq-clarity.mjs",
620
+ "pre-bash-issue-budget.mjs",
603
621
  "pre-bash-memory-propose-audit.mjs",
604
622
  "pre-bash-staging-fence.mjs",
605
623
  "pre-task-scope-disjoint.mjs",
@@ -632,6 +650,7 @@
632
650
  "on-session-end.mjs",
633
651
  "on-session-start.mjs",
634
652
  "on-stop.mjs",
653
+ "post-bash-issue-budget-refund.mjs",
635
654
  "post-bash-write-verify.mjs",
636
655
  "post-edit-import-probe.mjs",
637
656
  "post-edit-validate.mjs",
@@ -670,6 +689,7 @@
670
689
  "on-session-end.mjs",
671
690
  "on-session-start.mjs",
672
691
  "on-stop.mjs",
692
+ "post-bash-issue-budget-refund.mjs",
673
693
  "post-bash-write-verify.mjs",
674
694
  "post-edit-import-probe.mjs",
675
695
  "post-edit-validate.mjs",
@@ -677,6 +697,7 @@
677
697
  "post-tool-batch-wave-signal.mjs",
678
698
  "post-tooluse-frontend-slop.mjs",
679
699
  "pre-auq-clarity.mjs",
700
+ "pre-bash-issue-budget.mjs",
680
701
  "pre-bash-memory-propose-audit.mjs",
681
702
  "skill-invocation-telemetry.mjs"
682
703
  ]
@@ -763,6 +784,7 @@
763
784
  "on-session-end.mjs",
764
785
  "on-session-start.mjs",
765
786
  "on-stop.mjs",
787
+ "post-bash-issue-budget-refund.mjs",
766
788
  "post-bash-write-verify.mjs",
767
789
  "post-edit-import-probe.mjs",
768
790
  "post-edit-validate.mjs",
@@ -808,6 +830,7 @@
808
830
  "on-session-end.mjs",
809
831
  "on-session-start.mjs",
810
832
  "on-stop.mjs",
833
+ "post-bash-issue-budget-refund.mjs",
811
834
  "post-bash-write-verify.mjs",
812
835
  "post-edit-import-probe.mjs",
813
836
  "post-edit-validate.mjs",
@@ -828,6 +851,7 @@
828
851
  "on-session-end.mjs",
829
852
  "on-session-start.mjs",
830
853
  "on-stop.mjs",
854
+ "post-bash-issue-budget-refund.mjs",
831
855
  "post-bash-write-verify.mjs",
832
856
  "post-edit-import-probe.mjs",
833
857
  "post-edit-validate.mjs",
@@ -848,6 +872,7 @@
848
872
  "on-session-end.mjs",
849
873
  "on-session-start.mjs",
850
874
  "on-stop.mjs",
875
+ "post-bash-issue-budget-refund.mjs",
851
876
  "post-bash-write-verify.mjs",
852
877
  "post-edit-import-probe.mjs",
853
878
  "post-edit-validate.mjs",
@@ -855,6 +880,7 @@
855
880
  "post-tool-batch-wave-signal.mjs",
856
881
  "post-tooluse-frontend-slop.mjs",
857
882
  "pre-auq-clarity.mjs",
883
+ "pre-bash-issue-budget.mjs",
858
884
  "pre-bash-memory-propose-audit.mjs",
859
885
  "skill-invocation-telemetry.mjs"
860
886
  ]
@@ -877,6 +903,7 @@
877
903
  "on-session-end.mjs",
878
904
  "on-session-start.mjs",
879
905
  "on-stop.mjs",
906
+ "post-bash-issue-budget-refund.mjs",
880
907
  "post-bash-write-verify.mjs",
881
908
  "post-edit-import-probe.mjs",
882
909
  "post-edit-validate.mjs",
@@ -884,6 +911,7 @@
884
911
  "post-tool-batch-wave-signal.mjs",
885
912
  "post-tooluse-frontend-slop.mjs",
886
913
  "pre-auq-clarity.mjs",
914
+ "pre-bash-issue-budget.mjs",
887
915
  "pre-bash-memory-propose-audit.mjs",
888
916
  "pre-task-scope-disjoint.mjs",
889
917
  "skill-invocation-telemetry.mjs"
@@ -919,6 +947,7 @@
919
947
  "on-session-end.mjs",
920
948
  "on-session-start.mjs",
921
949
  "on-stop.mjs",
950
+ "post-bash-issue-budget-refund.mjs",
922
951
  "post-bash-write-verify.mjs",
923
952
  "post-edit-import-probe.mjs",
924
953
  "post-edit-validate.mjs",
@@ -926,6 +955,7 @@
926
955
  "post-tool-batch-wave-signal.mjs",
927
956
  "post-tooluse-frontend-slop.mjs",
928
957
  "pre-auq-clarity.mjs",
958
+ "pre-bash-issue-budget.mjs",
929
959
  "pre-bash-memory-propose-audit.mjs",
930
960
  "pre-bash-staging-fence.mjs",
931
961
  "pre-task-scope-disjoint.mjs",
@@ -942,6 +972,7 @@
942
972
  "on-session-end.mjs",
943
973
  "on-session-start.mjs",
944
974
  "on-stop.mjs",
975
+ "post-bash-issue-budget-refund.mjs",
945
976
  "post-bash-write-verify.mjs",
946
977
  "post-edit-import-probe.mjs",
947
978
  "post-edit-validate.mjs",
@@ -962,6 +993,7 @@
962
993
  {
963
994
  "file": "scripts/lib/issue-budget.mjs",
964
995
  "reachable_from": [
996
+ "post-bash-issue-budget-refund.mjs",
965
997
  "pre-bash-issue-budget.mjs"
966
998
  ]
967
999
  },
@@ -982,6 +1014,7 @@
982
1014
  "on-session-end.mjs",
983
1015
  "on-session-start.mjs",
984
1016
  "on-stop.mjs",
1017
+ "post-bash-issue-budget-refund.mjs",
985
1018
  "post-bash-write-verify.mjs",
986
1019
  "post-edit-import-probe.mjs",
987
1020
  "post-edit-validate.mjs",
@@ -989,6 +1022,7 @@
989
1022
  "post-tool-batch-wave-signal.mjs",
990
1023
  "post-tooluse-frontend-slop.mjs",
991
1024
  "pre-auq-clarity.mjs",
1025
+ "pre-bash-issue-budget.mjs",
992
1026
  "pre-bash-memory-propose-audit.mjs",
993
1027
  "skill-invocation-telemetry.mjs"
994
1028
  ]
@@ -1003,6 +1037,7 @@
1003
1037
  "on-session-end.mjs",
1004
1038
  "on-session-start.mjs",
1005
1039
  "on-stop.mjs",
1040
+ "post-bash-issue-budget-refund.mjs",
1006
1041
  "post-bash-write-verify.mjs",
1007
1042
  "post-edit-import-probe.mjs",
1008
1043
  "post-edit-validate.mjs",
@@ -1010,6 +1045,7 @@
1010
1045
  "post-tool-batch-wave-signal.mjs",
1011
1046
  "post-tooluse-frontend-slop.mjs",
1012
1047
  "pre-auq-clarity.mjs",
1048
+ "pre-bash-issue-budget.mjs",
1013
1049
  "pre-bash-memory-propose-audit.mjs",
1014
1050
  "skill-invocation-telemetry.mjs"
1015
1051
  ]
@@ -1024,6 +1060,7 @@
1024
1060
  "on-session-end.mjs",
1025
1061
  "on-session-start.mjs",
1026
1062
  "on-stop.mjs",
1063
+ "post-bash-issue-budget-refund.mjs",
1027
1064
  "post-bash-write-verify.mjs",
1028
1065
  "post-edit-import-probe.mjs",
1029
1066
  "post-edit-validate.mjs",
@@ -1031,6 +1068,7 @@
1031
1068
  "post-tool-batch-wave-signal.mjs",
1032
1069
  "post-tooluse-frontend-slop.mjs",
1033
1070
  "pre-auq-clarity.mjs",
1071
+ "pre-bash-issue-budget.mjs",
1034
1072
  "pre-bash-memory-propose-audit.mjs",
1035
1073
  "skill-invocation-telemetry.mjs"
1036
1074
  ]
@@ -1080,6 +1118,7 @@
1080
1118
  "on-session-start.mjs",
1081
1119
  "on-stop.mjs",
1082
1120
  "operator-steer.mjs",
1121
+ "post-bash-issue-budget-refund.mjs",
1083
1122
  "post-bash-write-verify.mjs",
1084
1123
  "post-edit-import-probe.mjs",
1085
1124
  "post-edit-validate.mjs",
@@ -1109,6 +1148,7 @@
1109
1148
  "on-session-start.mjs",
1110
1149
  "on-stop.mjs",
1111
1150
  "operator-steer.mjs",
1151
+ "post-bash-issue-budget-refund.mjs",
1112
1152
  "post-bash-write-verify.mjs",
1113
1153
  "post-edit-import-probe.mjs",
1114
1154
  "post-edit-validate.mjs",
@@ -1196,6 +1236,7 @@
1196
1236
  "on-session-end.mjs",
1197
1237
  "on-session-start.mjs",
1198
1238
  "on-stop.mjs",
1239
+ "post-bash-issue-budget-refund.mjs",
1199
1240
  "post-bash-write-verify.mjs",
1200
1241
  "post-edit-import-probe.mjs",
1201
1242
  "post-edit-validate.mjs",
@@ -1216,6 +1257,7 @@
1216
1257
  "on-session-end.mjs",
1217
1258
  "on-session-start.mjs",
1218
1259
  "on-stop.mjs",
1260
+ "post-bash-issue-budget-refund.mjs",
1219
1261
  "post-bash-write-verify.mjs",
1220
1262
  "post-edit-import-probe.mjs",
1221
1263
  "post-edit-validate.mjs",
@@ -1223,6 +1265,7 @@
1223
1265
  "post-tool-batch-wave-signal.mjs",
1224
1266
  "post-tooluse-frontend-slop.mjs",
1225
1267
  "pre-auq-clarity.mjs",
1268
+ "pre-bash-issue-budget.mjs",
1226
1269
  "pre-bash-memory-propose-audit.mjs",
1227
1270
  "skill-invocation-telemetry.mjs"
1228
1271
  ]
@@ -1237,6 +1280,7 @@
1237
1280
  "on-session-end.mjs",
1238
1281
  "on-session-start.mjs",
1239
1282
  "on-stop.mjs",
1283
+ "post-bash-issue-budget-refund.mjs",
1240
1284
  "post-bash-write-verify.mjs",
1241
1285
  "post-edit-import-probe.mjs",
1242
1286
  "post-edit-validate.mjs",
@@ -1244,6 +1288,7 @@
1244
1288
  "post-tool-batch-wave-signal.mjs",
1245
1289
  "post-tooluse-frontend-slop.mjs",
1246
1290
  "pre-auq-clarity.mjs",
1291
+ "pre-bash-issue-budget.mjs",
1247
1292
  "pre-bash-memory-propose-audit.mjs",
1248
1293
  "skill-invocation-telemetry.mjs"
1249
1294
  ]
@@ -1313,6 +1358,12 @@
1313
1358
  "on-session-start.mjs"
1314
1359
  ]
1315
1360
  },
1361
+ {
1362
+ "file": "scripts/lib/session-shape.mjs",
1363
+ "reachable_from": [
1364
+ "on-session-start.mjs"
1365
+ ]
1366
+ },
1316
1367
  {
1317
1368
  "file": "scripts/lib/session-start-probes.mjs",
1318
1369
  "reachable_from": [
@@ -1370,6 +1421,7 @@
1370
1421
  "on-session-end.mjs",
1371
1422
  "on-session-start.mjs",
1372
1423
  "on-stop.mjs",
1424
+ "post-bash-issue-budget-refund.mjs",
1373
1425
  "post-bash-write-verify.mjs",
1374
1426
  "post-edit-import-probe.mjs",
1375
1427
  "post-edit-validate.mjs",
@@ -1377,6 +1429,7 @@
1377
1429
  "post-tool-batch-wave-signal.mjs",
1378
1430
  "post-tooluse-frontend-slop.mjs",
1379
1431
  "pre-auq-clarity.mjs",
1432
+ "pre-bash-issue-budget.mjs",
1380
1433
  "pre-bash-memory-propose-audit.mjs",
1381
1434
  "skill-invocation-telemetry.mjs"
1382
1435
  ]
@@ -1399,6 +1452,7 @@
1399
1452
  "on-session-end.mjs",
1400
1453
  "on-session-start.mjs",
1401
1454
  "on-stop.mjs",
1455
+ "post-bash-issue-budget-refund.mjs",
1402
1456
  "post-bash-write-verify.mjs",
1403
1457
  "post-edit-import-probe.mjs",
1404
1458
  "post-edit-validate.mjs",
@@ -1406,6 +1460,7 @@
1406
1460
  "post-tool-batch-wave-signal.mjs",
1407
1461
  "post-tooluse-frontend-slop.mjs",
1408
1462
  "pre-auq-clarity.mjs",
1463
+ "pre-bash-issue-budget.mjs",
1409
1464
  "pre-bash-memory-propose-audit.mjs",
1410
1465
  "skill-invocation-telemetry.mjs"
1411
1466
  ]
@@ -1478,6 +1533,18 @@
1478
1533
  "pre-bash-staging-fence.mjs"
1479
1534
  ]
1480
1535
  },
1536
+ {
1537
+ "file": "scripts/lib/wave-sizing.mjs",
1538
+ "reachable_from": [
1539
+ "on-session-start.mjs"
1540
+ ]
1541
+ },
1542
+ {
1543
+ "file": "scripts/lib/wave-transcript-tail.mjs",
1544
+ "reachable_from": [
1545
+ "enforce-scope.mjs"
1546
+ ]
1547
+ },
1481
1548
  {
1482
1549
  "file": "scripts/lib/worktree/listing.mjs",
1483
1550
  "reachable_from": [
@@ -38,6 +38,23 @@ import fs from 'node:fs';
38
38
  import path from 'node:path';
39
39
  import { writeJsonAtomicSync } from '../../scripts/lib/io.mjs';
40
40
 
41
+ /**
42
+ * Native SessionStart `source` values that are a RE-ENTRY into the same logical
43
+ * session rather than a new one (#1091).
44
+ *
45
+ * SSOT for both consumers — the SessionStart hook's high-water-mark
46
+ * preservation and the force-refresh gate below — so a later widening
47
+ * ("`fork` is a re-entry too") can never reach one side only. It lives HERE,
48
+ * in the leaf module, because the hook already imports this file while the
49
+ * reverse direction would pull the whole hook's closure into a helper.
50
+ *
51
+ * `startup` is deliberately absent: a fresh process start must never inherit a
52
+ * predecessor's markers or take over its lock.
53
+ *
54
+ * @type {ReadonlySet<string>}
55
+ */
56
+ export const SAME_LOGICAL_SESSION_SOURCES = new Set(['resume', 'clear', 'compact']);
57
+
41
58
  /**
42
59
  * Bootstrap the session.lock for this hook invocation.
43
60
  *
@@ -55,6 +72,16 @@ import { writeJsonAtomicSync } from '../../scripts/lib/io.mjs';
55
72
  * field is populated by mirroring sessionId for backward-compatible display only.
56
73
  * @param {string} opts.mode — session mode (e.g. "deep", "feature").
57
74
  * @param {number} [opts.ttlHours=4] — lock TTL in hours.
75
+ * @param {string|null} [opts.nativeSource=null] — the native SessionStart
76
+ * `source` (`startup`|`resume`|`clear`|`compact`), when the harness sent one.
77
+ * Only consulted for the same-logical-session force-refresh below; every
78
+ * existing caller that omits it keeps its pre-#1091 behaviour exactly.
79
+ * @param {string|null} [opts.predecessorSessionId=null] — the raw `session_id`
80
+ * recorded in `.orchestrator/current-session.json` by our OWN previous run of
81
+ * this hook. It is the third, load-bearing conjunct of the re-entry
82
+ * force-refresh below: without it a same-host semantic-label collision (#1066)
83
+ * lets one session take over a live peer's lock. Omitting it (the default)
84
+ * disables the re-entry force-refresh entirely — fail-closed.
58
85
  * @param {Function} [opts._acquireImpl] — DI for tests (defaults to importing acquire from session-lock.mjs).
59
86
  * @param {Function} [opts._forceAcquireImpl] — DI for tests (defaults to importing forceAcquire from session-lock.mjs).
60
87
  * @param {Function} [opts._emitEventImpl] — DI for tests (defaults to importing emitEvent from events.mjs).
@@ -66,6 +93,8 @@ export async function bootstrapLock({
66
93
  semanticSessionId,
67
94
  mode,
68
95
  ttlHours = 4,
96
+ nativeSource = null,
97
+ predecessorSessionId = null,
69
98
  _acquireImpl,
70
99
  _forceAcquireImpl,
71
100
  _emitEventImpl,
@@ -106,6 +135,53 @@ export async function bootstrapLock({
106
135
 
107
136
  if (!acquireResult || typeof acquireResult !== 'object') return null;
108
137
 
138
+ // #1091 F2 — a same-logical-session re-entry whose RAW id the harness did not
139
+ // preserve. `resume` entered the SessionStart matcher in #1091, so this hook
140
+ // now runs on re-entry: if Claude Code mints a fresh raw `session_id` there,
141
+ // `acquire()` returns `reason:'active'` with THIS SESSION'S OWN predecessor
142
+ // lock as `existingLock` (its heartbeat is fresh, so it is live by
143
+ // definition), `shouldForce` is false, and the hook bails — leaving the
144
+ // session running for up to the 4 h TTL without owning its own lock, while
145
+ // `recordConflictSignal()` below names the session's own former self as a
146
+ // foreign conflict.
147
+ //
148
+ // THREE conjuncts gate the force, and all three are load-bearing:
149
+ // (a) `SAME_LOGICAL_SESSION_SOURCES.has(nativeSource)` — the harness itself
150
+ // says this is a re-entry rather than a fresh start;
151
+ // (b) `existingLock.semantic_session_id === semanticSessionId` — the lock's
152
+ // label is written by this same bootstrap, so an equal label means the
153
+ // predecessor was minted from the same (branch, date, mode, n) tuple;
154
+ // (c) `existingLock.session_id === predecessorSessionId` — the RAW id our
155
+ // own previous hook run recorded in current-session.json is the raw id
156
+ // the live lock carries.
157
+ //
158
+ // (a)+(b) alone are NOT enough (security review, #1066): semantic labels are
159
+ // measurably collidable on one host — two sessions minted the SAME label when
160
+ // the host-wide registry contributed nothing to the n-increment — so a
161
+ // `/clear` in session B would take over session A's LIVE lock. (c) is the only
162
+ // conjunct tied to a witness WE wrote about OURSELVES; it is deliberately not
163
+ // `resumeLinkage === 'raw-id'`, which is true exactly when the raw id was
164
+ // PRESERVED — the complement of the fresh-raw-id case this branch exists for.
165
+ //
166
+ // NOT gated on process liveness, deliberately: `pid` on a session.lock is the
167
+ // ephemeral hook subprocess that WROTE it, so `isPidAliveOnHost(lock.pid)`
168
+ // reports "dead" for essentially every lock including live heartbeating ones
169
+ // (7/7 measured, #1137) — a vacuous predicate that would widen this branch to
170
+ // every source, not narrow it. `isLockLive()` is no help either: under
171
+ // `reason:'active'` acquire() has already established it is true
172
+ // (session-lock.mjs `classifyExisting`).
173
+ //
174
+ // Ceiling (BV-004), named rather than claimed closed: the residual is a peer
175
+ // that wrote `current-session.json` LAST with our semantic label — that peer's
176
+ // raw id is what we read as `predecessorSessionId`, so if it also owns the
177
+ // live lock, conjunct (c) holds for the wrong session. `current-session.json`
178
+ // carries no session field of its own (see
179
+ // `.claude/rules/identity-and-locks.md` § shared repo artefacts), which is
180
+ // exactly why this is a ceiling and not a proof. Revisit when the lock or
181
+ // current-session.json carries a durable logical-session id of its own.
182
+ const isSameLogicalReentry =
183
+ typeof nativeSource === 'string' && SAME_LOGICAL_SESSION_SOURCES.has(nativeSource);
184
+
109
185
  const shouldForce =
110
186
  acquireResult.ok !== true && (
111
187
  // #1137: 'stale-heartbeat' replaced the former 'stale-pid-dead' /
@@ -115,7 +191,14 @@ export async function bootstrapLock({
115
191
  acquireResult.reason === 'stale-heartbeat' ||
116
192
  (acquireResult.reason === 'active' &&
117
193
  acquireResult.existingLock &&
118
- acquireResult.existingLock.session_id === sessionId)
194
+ (acquireResult.existingLock.session_id === sessionId ||
195
+ (isSameLogicalReentry &&
196
+ typeof semanticSessionId === 'string' &&
197
+ semanticSessionId.length > 0 &&
198
+ acquireResult.existingLock.semantic_session_id === semanticSessionId &&
199
+ typeof predecessorSessionId === 'string' &&
200
+ predecessorSessionId.length > 0 &&
201
+ acquireResult.existingLock.session_id === predecessorSessionId)))
119
202
  );
120
203
 
121
204
  if (!acquireResult.ok && shouldForce) {