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.
- package/.agents/skills/session-plan/SKILL.md +1 -1
- package/.agents/skills/session-start/SKILL.md +1 -1
- package/.agents/skills/ux-grill/SKILL.md +22 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +3 -2
- package/.codex-plugin/plugin.json +1 -1
- package/.codex-plugin/skills/session-plan/SKILL.md +1 -1
- package/.codex-plugin/skills/session-start/SKILL.md +1 -1
- package/.codex-plugin/skills/ux-grill/SKILL.md +21 -0
- package/.codex-plugin/skills/ux-grill/agents/openai.yaml +5 -0
- package/.cursor/commands/ux-grill.md +14 -0
- package/.cursor/skills/session-plan/SKILL.md +1 -1
- package/.cursor/skills/session-start/SKILL.md +1 -1
- package/.cursor/skills/ux-grill/SKILL.md +13 -0
- package/.cursor-plugin/plugin.json +1 -1
- package/AGENTS.md +2 -1
- package/CHANGELOG.md +128 -1
- package/README.md +98 -86
- package/agents/dialectic-deriver.md +11 -0
- package/agents/ux-evaluator.md +1 -1
- package/commands/close.md +3 -3
- package/commands/go.md +2 -0
- package/commands/memory-cleanup.md +4 -3
- package/commands/persona-panel.md +1 -1
- package/commands/session.md +3 -2
- package/commands/ux-grill.md +51 -0
- package/docs/README.md +4 -4
- package/docs/USER-GUIDE.md +117 -50
- package/docs/agent-authoring.md +2 -2
- package/docs/baseline.md +55 -1
- package/docs/ci-setup.md +1 -1
- package/docs/codex-setup.md +9 -0
- package/docs/components.md +9 -9
- package/docs/cursor-setup.md +1 -0
- package/docs/events-schema.md +13 -6
- package/docs/github-mirror-protection.md +61 -20
- package/docs/instruction-delivery.md +1 -1
- package/docs/memory-proposal-flow.md +3 -3
- package/docs/migration-v4.md +2 -2
- package/docs/migration-v5.md +62 -0
- package/docs/owner-config-schema.md +74 -90
- package/docs/persona-panel.md +4 -4
- package/docs/pi-setup.md +1 -0
- package/docs/rule-authoring.md +13 -6
- package/docs/scope-collision-guard.md +16 -0
- package/docs/session-config-reference.md +55 -22
- package/docs/session-config-template.md +9 -5
- package/docs/vault-docs-architecture.md +4 -2
- package/hooks/_lib/hook-import-set.json +70 -3
- package/hooks/_lib/lock-bootstrap.mjs +84 -1
- package/hooks/_lib/vcs-create-matcher.mjs +401 -16
- package/hooks/enforce-scope.mjs +201 -0
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks-cursor.json +5 -0
- package/hooks/hooks.json +7 -2
- package/hooks/on-session-start.mjs +171 -49
- package/hooks/post-bash-issue-budget-refund.mjs +375 -0
- package/hooks/pre-auq-clarity.mjs +70 -18
- package/hooks/pre-bash-issue-budget.mjs +170 -26
- package/hooks/subagent-telemetry.mjs +106 -20
- package/package.json +5 -4
- package/pi/prompts/ux-grill.md +12 -0
- package/scripts/baseline-archetypes.mjs +28 -0
- package/scripts/ci/assert-vitest-green.mjs +4 -2
- package/scripts/dialectic-deriver.mjs +32 -8
- package/scripts/emit-session.mjs +72 -1
- package/scripts/lib/agent-status.mjs +441 -9
- package/scripts/lib/auq/schema.mjs +10 -3
- package/scripts/lib/auto-dialectic.mjs +0 -68
- package/scripts/lib/baseline-archetypes.mjs +439 -0
- package/scripts/lib/build-live-signals.mjs +5 -6
- package/scripts/lib/ci-status-banner.mjs +29 -6
- package/scripts/lib/claude-md-budget-lint.mjs +52 -2
- package/scripts/lib/config/issue-budget.mjs +68 -8
- package/scripts/lib/config/private-config-dir.mjs +3 -2
- package/scripts/lib/config/remote-hosts.mjs +2 -2
- package/scripts/lib/config-schema.mjs +79 -0
- package/scripts/lib/config.mjs +12 -1
- package/scripts/lib/eval/engine.mjs +7 -1
- package/scripts/lib/file-lock.mjs +151 -8
- package/scripts/lib/git-porcelain.mjs +113 -0
- package/scripts/lib/instruction-budget-guard.mjs +415 -47
- package/scripts/lib/io.mjs +29 -4
- package/scripts/lib/issue-budget-reconcile.mjs +392 -0
- package/scripts/lib/issue-budget.mjs +412 -9
- package/scripts/lib/learnings/evolve-telemetry.mjs +1 -2
- package/scripts/lib/learnings/sizing-subject.mjs +44 -0
- package/scripts/lib/locks/staging-fence-lock.mjs +19 -38
- package/scripts/lib/locks/state-md-lock.mjs +19 -41
- package/scripts/lib/maintenance-due-banner.mjs +450 -0
- package/scripts/lib/owner-config.example.yaml +29 -46
- package/scripts/lib/owner-yaml.mjs +14 -13
- package/scripts/lib/peer-cards/merger.mjs +143 -0
- package/scripts/lib/pre-dispatch-check.mjs +20 -14
- package/scripts/lib/project-hygiene.mjs +81 -30
- package/scripts/lib/quality-gate.mjs +27 -71
- package/scripts/lib/reconcile/engine.mjs +19 -1
- package/scripts/lib/reconcile/writer.mjs +278 -11
- package/scripts/lib/resource-probe/evaluate.mjs +19 -21
- package/scripts/lib/rules-sync.mjs +34 -4
- package/scripts/lib/scope-echo.mjs +346 -0
- package/scripts/lib/session-close-backfill.mjs +182 -40
- package/scripts/lib/session-end/phase-skip.mjs +85 -86
- package/scripts/lib/session-end/tail-runner.mjs +178 -0
- package/scripts/lib/session-lock.mjs +62 -2
- package/scripts/lib/session-record-repair.mjs +91 -0
- package/scripts/lib/session-schema/constants.mjs +6 -0
- package/scripts/lib/session-schema/filters.mjs +26 -1
- package/scripts/lib/session-schema/validator.mjs +20 -0
- package/scripts/lib/session-shape.mjs +558 -0
- package/scripts/lib/session-start-probes.mjs +429 -56
- package/scripts/lib/session-token-rollup.mjs +95 -10
- package/scripts/lib/state-md/frontmatter-mutators.mjs +22 -34
- package/scripts/lib/state-md.mjs +1 -0
- package/scripts/lib/subagents-schema.mjs +77 -9
- package/scripts/lib/telemetry/pricing.mjs +197 -0
- package/scripts/lib/telemetry/sync.mjs +50 -1
- package/scripts/lib/test-runner/artifact-paths.mjs +30 -5
- package/scripts/lib/test-runner/issue-reconcile.mjs +45 -8
- package/scripts/lib/tmux-layout/layouts.mjs +62 -4
- package/scripts/lib/ux-grill/collect.mjs +1163 -0
- package/scripts/lib/ux-grill/compare.mjs +285 -0
- package/scripts/lib/ux-grill/manifest.mjs +618 -0
- package/scripts/lib/ux-grill/measures.mjs +431 -0
- package/scripts/lib/ux-grill/paths.mjs +224 -0
- package/scripts/lib/ux-grill/pencil-coverage.mjs +284 -0
- package/scripts/lib/ux-grill/reconcile.mjs +344 -0
- package/scripts/lib/ux-grill/run-record.mjs +316 -0
- package/scripts/lib/ux-grill/schema.mjs +321 -0
- package/scripts/lib/validate/check-skill-script-paths.mjs +33 -10
- package/scripts/lib/validate/check-untracked-test-deps.mjs +33 -19
- package/scripts/lib/validate/check-unwired-features.mjs +56 -27
- package/scripts/lib/vault-mirror/process.mjs +2 -1
- package/scripts/lib/vault-status/board-lock.mjs +18 -0
- package/scripts/lib/vault-status/board-writer.mjs +8 -0
- package/scripts/lib/vault-status/narrative-mirror.mjs +4 -4
- package/scripts/lib/wave-resource-gate.mjs +23 -27
- package/scripts/lib/wave-sizing.mjs +10 -3
- package/scripts/materialize-wave-scope.mjs +68 -14
- package/scripts/mcp-server.sh +16 -1
- package/scripts/print-applicable-rules.mjs +7 -6
- package/scripts/print-learnings-index.mjs +3 -2
- package/scripts/release.mjs +7 -2
- package/scripts/session-shape.mjs +266 -0
- package/skills/_shared/config-reading.md +15 -9
- package/skills/_shared/private-capability-context.md +89 -0
- package/skills/bootstrap/SKILL.md +60 -209
- package/skills/bootstrap/_shared-template.md +99 -14
- package/skills/bootstrap/deep-template.md +36 -26
- package/skills/bootstrap/fast-template.md +44 -8
- package/skills/bootstrap/intensity-heuristic.md +10 -4
- package/skills/bootstrap/private-contract.md +119 -0
- package/skills/bootstrap/public-fallback.md +30 -18
- package/skills/bootstrap/references/bootstrap-ecosystem-health-flow.md +48 -0
- package/skills/bootstrap/references/bootstrap-refresh-lock-flow.md +37 -0
- package/skills/bootstrap/references/bootstrap-retroactive-flow.md +108 -0
- package/skills/bootstrap/references/bootstrap-rules-fetch-bridge.md +64 -0
- package/skills/bootstrap/standard-template.md +39 -24
- package/skills/claude-md-drift-check/SKILL.md +9 -2
- package/skills/claude-md-drift-check/checker.mjs +213 -21
- package/skills/discovery/SKILL.md +6 -173
- package/skills/discovery/probes/vault-staleness.mjs +35 -5
- package/skills/discovery/probes-docs.md +8 -4
- package/skills/discovery/probes-supply-chain.md +4 -2
- package/skills/discovery/probes-ui.md +8 -4
- package/skills/discovery/probes-vault.md +12 -4
- package/skills/discovery/references/discovery-interactive-triage.md +139 -0
- package/skills/discovery/references/discovery-triage-state.md +54 -0
- package/skills/docs-orchestrator/audience-mapping.md +1 -1
- package/skills/eval/rubric-v1.md +13 -0
- package/skills/evolve/SKILL.md +2 -458
- package/skills/evolve/references/evolve-analyze-mode.md +360 -0
- package/skills/evolve/references/evolve-dialectic-mode.md +139 -0
- package/skills/gitlab-ops/SKILL.md +3 -3
- package/skills/grill/SKILL.md +1 -1
- package/skills/memory-cleanup/SKILL.md +2 -2
- package/skills/plan/mode-new.md +9 -0
- package/skills/plan/mode-retro.md +4 -3
- package/skills/reconcile/SKILL.md +11 -1
- package/skills/session-end/SKILL.md +3 -2
- package/skills/session-end/drift-operations.md +20 -5
- package/skills/session-end/metrics-collection.md +1 -0
- package/skills/session-end/phase-3-2-docs-verification.md +1 -1
- package/skills/session-end/phase-3-6-tail.md +27 -67
- package/skills/session-end/phase-3-7a-recommendations.md +2 -2
- package/skills/session-end/references/phase-2-quality-gate.md +3 -3
- package/skills/session-end/references/phase-3-documentation-updates.md +8 -6
- package/skills/session-end/references/phase-5-issue-cleanup.md +32 -1
- package/skills/session-end/session-metrics-write.md +33 -12
- package/skills/session-plan/SKILL.md +46 -180
- package/skills/session-plan/references/session-plan-task-classification.md +152 -0
- package/skills/session-plan/wave-template.md +8 -15
- package/skills/session-start/SKILL.md +41 -7
- package/skills/session-start/phase-2-5-docs-planning.md +1 -1
- package/skills/session-start/phase-8-5-express-path.md +12 -9
- package/skills/session-start/references/operations-contract.md +114 -0
- package/skills/session-start/references/phase-1-5-session-continuity.md +2 -0
- package/skills/session-start/references/phase-4-ssot-environment-check.md +42 -24
- package/skills/session-start/references/phase-6-7-memory-banner-telemetry-consent.md +3 -1
- package/skills/session-start/soul.md +2 -2
- package/skills/test-runner/SKILL.md +1 -1
- package/skills/test-runner/rubric-v1.md +2 -2
- package/skills/tmux-layout/SKILL.md +3 -1
- package/skills/ux-grill/SKILL.md +211 -0
- package/skills/ux-grill/rubric-v2.md +201 -0
- package/skills/ux-grill/soul.md +76 -0
- package/skills/wave-executor/SKILL.md +32 -127
- package/skills/wave-executor/circuit-breaker.md +3 -1
- package/skills/wave-executor/references/wave-executor-quality-gate.md +61 -0
- package/skills/wave-executor/references/wave-executor-state-init.md +86 -0
- package/skills/wave-executor/references/wave-loop-dispatch.md +12 -2
- package/skills/wave-executor/references/wave-loop-review.md +19 -6
- package/skills/wave-executor/references/wave-loop-scope-manifest.md +6 -2
- package/templates/_shared/ux-manifest.template.md +149 -0
- package/templates/nextjs-minimal/package.json +1 -1
- package/templates/node-minimal/package.json +1 -1
- package/scripts/lib/multi-provider-build/providers.mjs +0 -64
- package/scripts/lib/multi-provider-build/templating.mjs +0 -130
- package/scripts/lib/owner-config/coerce.mjs +0 -29
- package/scripts/lib/owner-config/constants.mjs +0 -21
- package/scripts/lib/owner-config/defaults.mjs +0 -50
- package/scripts/lib/owner-config/error.mjs +0 -19
- package/scripts/lib/owner-config/index.mjs +0 -13
- package/scripts/lib/owner-config/merge.mjs +0 -52
- package/scripts/lib/owner-config/validate.mjs +0 -259
- package/scripts/lib/owner-config-loader.mjs +0 -170
- package/scripts/lib/owner-config.mjs +0 -28
- package/scripts/lib/soul-resolve.mjs +0 -130
- package/scripts/lib/vault-mirror/render.mjs +0 -8
- 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 —
|
|
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 #
|
|
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
|
|
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` |
|
|
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-
|
|
3
|
-
"head": "
|
|
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-
|
|
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) {
|