session-orchestrator 5.3.0 → 5.5.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/claude-md-drift-check/SKILL.md +1 -1
- package/.agents/skills/test-audit/SKILL.md +21 -0
- package/.agents/skills/test-audit/agents/openai.yaml +5 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.codex-plugin/skills/claude-md-drift-check/SKILL.md +1 -1
- package/.codex-plugin/skills/test-audit/SKILL.md +21 -0
- package/.codex-plugin/skills/test-audit/agents/openai.yaml +5 -0
- package/.cursor/commands/test-audit.md +14 -0
- package/.cursor/rules/060-evolve.mdc +28 -13
- package/.cursor/skills/claude-md-drift-check/SKILL.md +1 -1
- package/.cursor/skills/test-audit/SKILL.md +12 -0
- package/.cursor-plugin/plugin.json +1 -1
- package/.orchestrator/policy/blocked-commands.json +1 -1
- package/AGENTS.md +9 -31
- package/CHANGELOG.md +162 -0
- package/README.md +14 -10
- package/docs/agent-authoring.md +2 -2
- package/docs/baseline.md +10 -1
- package/docs/ci-setup.md +154 -4
- package/docs/components.md +11 -11
- package/docs/events-schema.md +25 -19
- package/docs/install.md +14 -2
- package/docs/migration-v4.md +24 -17
- package/docs/persona-panel.md +5 -4
- package/docs/plugin-architecture-v3.md +1 -1
- package/docs/rule-authoring.md +27 -12
- package/docs/scope-collision-guard.md +40 -16
- package/docs/session-config-reference.md +61 -12
- package/docs/session-config-template.md +11 -2
- package/docs/vault-docs-architecture.md +8 -4
- package/hooks/_lib/hook-import-set.json +42 -29
- package/hooks/_lib/lock-bootstrap.mjs +118 -26
- package/hooks/config-protection.mjs +1 -1
- package/hooks/enforce-commands.mjs +28 -13
- package/hooks/enforce-scope.mjs +201 -23
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks-cursor.json +5 -0
- package/hooks/hooks-pi.json +5 -0
- package/hooks/hooks.json +6 -1
- package/hooks/on-session-start.mjs +57 -2
- package/hooks/on-stop.mjs +70 -168
- package/hooks/post-bash-write-verify.mjs +98 -17
- package/hooks/post-edit-validate.mjs +15 -5
- package/hooks/post-tool-batch-wave-signal.mjs +32 -152
- package/hooks/pre-bash-memory-propose-audit.mjs +71 -10
- package/hooks/pre-bash-sessions-ledger-guard.mjs +28 -2
- package/hooks/pre-bash-staging-fence.mjs +29 -8
- package/hooks/pre-edit-sessions-ledger-guard.mjs +162 -0
- package/hooks/pre-task-scope-disjoint.mjs +1143 -279
- package/hooks/subagent-telemetry.mjs +96 -19
- package/hooks/wave-scope-commit-guard.mjs +168 -72
- package/package.json +2 -6
- package/pi/prompts/test-audit.md +12 -0
- package/rules/README.md +6 -1
- package/rules/_index.md +3 -3
- package/rules/always-on/bash-harness-pitfalls.md +7 -1
- package/rules/opt-in-domain/prompt-caching.md +5 -1
- package/rules/opt-in-stack/backend-data.md +9 -1
- package/rules/opt-in-stack/backend.md +7 -1
- package/rules/opt-in-stack/frontend.md +6 -1
- package/rules/opt-in-stack/security-web.md +7 -1
- package/rules/opt-in-stack/swift.md +5 -1
- package/scripts/apply-session-learnings.mjs +513 -0
- package/scripts/archive-closed-prds.mjs +40 -12
- package/scripts/autopilot.mjs +57 -54
- package/scripts/backfill-abandoned-sessions.mjs +81 -6
- package/scripts/backfill-learnings-from-vault.mjs +49 -22
- package/scripts/baseline-archetypes.mjs +1 -1
- package/scripts/check-package-manager.mjs +62 -5
- package/scripts/codex-install.mjs +3 -0
- package/scripts/cursor-install.mjs +47 -6
- package/scripts/emit-session.mjs +298 -2
- package/scripts/export-hw-learnings.mjs +40 -10
- package/scripts/fleet-checkin.mjs +170 -0
- package/scripts/lib/agent-frontmatter.mjs +3 -3
- package/scripts/lib/auto-dream.mjs +7 -6
- package/scripts/lib/autopilot/flags.mjs +6 -1
- package/scripts/lib/autopilot/loop.mjs +32 -13
- package/scripts/lib/autopilot/stall-sampler.mjs +13 -9
- package/scripts/lib/baseline-archetypes.mjs +41 -22
- package/scripts/lib/blocked-commands-policy.mjs +40 -0
- package/scripts/lib/common.mjs +41 -0
- package/scripts/lib/config/host-paths.mjs +79 -0
- package/scripts/lib/config/persona-gate-wave.mjs +3 -3
- package/scripts/lib/config/reaper.mjs +7 -6
- package/scripts/lib/config/vault-integration.mjs +151 -16
- package/scripts/lib/config-schema.mjs +13 -0
- package/scripts/lib/config.mjs +75 -10
- package/scripts/lib/eval/engine.mjs +13 -0
- package/scripts/lib/events-retention-banner.mjs +393 -0
- package/scripts/lib/events-rotation.mjs +21 -6
- package/scripts/lib/events.mjs +72 -5
- package/scripts/lib/fleet-protocol.mjs +288 -0
- package/scripts/lib/gates/gate-baseline.mjs +13 -3
- package/scripts/lib/gates/gate-full.mjs +7 -2
- package/scripts/lib/gates/gate-helpers.mjs +93 -2
- package/scripts/lib/gates/gate-incremental.mjs +23 -22
- package/scripts/lib/gates/gate-per-file.mjs +16 -7
- package/scripts/lib/hardening.mjs +1 -0
- package/scripts/lib/harness-audit/categories/category4.mjs +8 -6
- package/scripts/lib/instruction-budget-guard.mjs +77 -11
- package/scripts/lib/learnings/expiry-sweep.mjs +420 -22
- package/scripts/lib/learnings/io.mjs +274 -37
- package/scripts/lib/learnings/schema.mjs +163 -15
- package/scripts/lib/learnings/sizing-subject.mjs +2 -2
- package/scripts/lib/lock-reaper.mjs +38 -14
- package/scripts/lib/maintenance-due-banner.mjs +23 -8
- package/scripts/lib/memory-proposals/schema.mjs +11 -5
- package/scripts/lib/named-baseline-resolver.mjs +53 -28
- package/scripts/lib/named-vault-resolver.mjs +147 -5
- package/scripts/lib/orphan-reaper/defaults.mjs +41 -0
- package/scripts/lib/orphan-reaper/no-follow-append.mjs +87 -0
- package/scripts/lib/orphan-reaper/ps-snapshot.mjs +181 -0
- package/scripts/lib/orphan-reaper/reaper-audit.mjs +323 -0
- package/scripts/lib/orphan-reaper/reaper-decide.mjs +395 -0
- package/scripts/lib/orphan-reaper/scan-throttle.mjs +144 -0
- package/scripts/lib/orphan-reaper/scan.mjs +510 -0
- package/scripts/lib/orphan-reaper/trigger.mjs +173 -0
- package/scripts/lib/orphan-reaper.mjs +47 -1315
- package/scripts/lib/owner-yaml.mjs +104 -6
- package/scripts/lib/persona-panel/catalog-loader.mjs +1 -1
- package/scripts/lib/platform.mjs +206 -2
- package/scripts/lib/plugin-update-banner.mjs +3 -1
- package/scripts/lib/process-group.mjs +134 -22
- package/scripts/lib/project-hygiene.mjs +21 -1
- package/scripts/lib/quality-gate.mjs +45 -5
- package/scripts/lib/resource-probe.mjs +1 -1
- package/scripts/lib/rule-loader.mjs +100 -62
- package/scripts/lib/rules-sync.mjs +27 -12
- package/scripts/lib/scope-baseline.mjs +119 -29
- package/scripts/lib/scope-echo.mjs +7 -0
- package/scripts/lib/scope-gate.mjs +194 -27
- package/scripts/lib/session-close-backfill.mjs +129 -4
- package/scripts/lib/session-end/tail-runner.mjs +10 -5
- package/scripts/lib/session-lock-shape.mjs +6 -3
- package/scripts/lib/session-lock.mjs +320 -67
- package/scripts/lib/session-record-repair.mjs +183 -26
- package/scripts/lib/session-registry.mjs +67 -17
- package/scripts/lib/session-schema/constants.mjs +30 -4
- package/scripts/lib/session-schema/validator.mjs +28 -1
- package/scripts/lib/session-start-probes.mjs +242 -68
- package/scripts/lib/session-token-rollup.mjs +252 -54
- package/scripts/lib/sessions-canonical.mjs +100 -9
- package/scripts/lib/sessions-staleness-banner.mjs +3 -1
- package/scripts/lib/sh-quote.mjs +29 -0
- package/scripts/lib/subagents-schema.mjs +30 -3
- package/scripts/lib/tail-window.mjs +27 -3
- package/scripts/lib/telemetry/pricing.mjs +121 -71
- package/scripts/lib/telemetry/sync.mjs +17 -0
- package/scripts/lib/tests-src-ratio.mjs +215 -23
- package/scripts/lib/tmux-layout/layouts.mjs +1 -11
- package/scripts/lib/tmux-layout/telemetry-stats.mjs +12 -0
- package/scripts/lib/tmux-layout/tmux-shell.mjs +2 -11
- package/scripts/lib/ux-grill/reconcile.mjs +1 -1
- package/scripts/lib/validate/check-agents.mjs +1 -1
- package/scripts/lib/validate/check-hooks-symmetry.mjs +5 -0
- package/scripts/lib/validate/check-learnings-shell-writes.mjs +214 -0
- package/scripts/lib/validate/check-test-value-bans.mjs +388 -27
- package/scripts/lib/validate/check-unicode-safety.mjs +1 -0
- package/scripts/lib/validate/check-unwired-features.mjs +1 -1
- package/scripts/lib/validate/check-vcs-repo-flag.mjs +1 -1
- package/scripts/lib/validate-vendored-rules.mjs +206 -81
- package/scripts/lib/vault-mirror/auto-commit.mjs +5 -3
- package/scripts/lib/vault-mirror/namespace.mjs +47 -26
- package/scripts/lib/vault-mirror/process.mjs +350 -62
- package/scripts/lib/vault-mirror/pseudonym-map.mjs +14 -5
- package/scripts/lib/vault-mirror/render-learnings.mjs +66 -3
- package/scripts/lib/vault-mirror/render-sessions.mjs +28 -4
- package/scripts/lib/vault-mirror/telemetry.mjs +25 -11
- package/scripts/lib/vault-status/board-writer.mjs +53 -12
- package/scripts/lib/vault-status/narrative-mirror.mjs +40 -9
- package/scripts/lib/vcs-repo-spec.mjs +8 -0
- package/scripts/lib/wave-executor/dispatch-common.mjs +10 -18
- package/scripts/lib/wave-executor/foreign-dispatch.mjs +1 -1
- package/scripts/lib/wave-executor/remote-dispatch.mjs +1 -1
- package/scripts/lib/wave-resource-gate.mjs +34 -8
- package/scripts/materialize-wave-scope.mjs +7 -4
- package/scripts/memory-propose.mjs +18 -5
- package/scripts/release-session-lock.mjs +2 -1
- package/scripts/release.mjs +11 -3
- package/scripts/repair-invalid-sessions.mjs +37 -4
- package/scripts/run-migrate-v2-cross-repo.mjs +171 -31
- package/scripts/run-quality-gate.mjs +331 -307
- package/scripts/self-update.mjs +229 -0
- package/scripts/site-numbers.mjs +163 -5
- package/scripts/sweep-expired-learnings.mjs +603 -20
- package/scripts/sweep-expired-rules.mjs +2 -1
- package/scripts/validate-plugin.mjs +7 -0
- package/scripts/validate-wave-scope.mjs +21 -2
- package/scripts/vault-backfill.mjs +50 -37
- package/scripts/vault-integration-watcher.mjs +2 -1
- package/scripts/vault-mirror.mjs +238 -75
- package/scripts/wave-scope-binding.mjs +2 -1
- package/skills/_shared/config-reading.md +3 -3
- package/skills/_shared/fleet-protocol.md +134 -0
- package/skills/_shared/state-ownership.md +41 -12
- package/skills/autopilot/SKILL.md +25 -11
- package/skills/bootstrap/SKILL.md +6 -4
- package/skills/bootstrap/_shared-template.md +97 -2
- package/skills/bootstrap/fast-template.md +4 -1
- package/skills/bootstrap/private-contract.md +2 -1
- package/skills/bootstrap/public-fallback.md +6 -3
- package/skills/bootstrap/references/bootstrap-refresh-lock-flow.md +5 -3
- package/skills/bootstrap/references/bootstrap-retroactive-flow.md +2 -1
- package/skills/bootstrap/standard-template.md +2 -0
- package/skills/claude-md-drift-check/SKILL.md +10 -10
- package/skills/claude-md-drift-check/checker.mjs +26 -18
- package/skills/discovery/probes/ssot-code-diff.mjs +12 -6
- package/skills/discovery/probes/vault-narrative-staleness.mjs +6 -2
- package/skills/discovery/probes/vault-staleness.mjs +9 -3
- package/skills/docs-orchestrator/SKILL.md +12 -5
- package/skills/docs-orchestrator/audience-mapping.md +5 -3
- package/skills/evolve/SKILL.md +13 -4
- package/skills/evolve/references/evolve-analyze-mode.md +42 -18
- package/skills/memory-cleanup/SKILL.md +1 -1
- package/skills/persona-panel/SKILL.md +2 -2
- package/skills/persona-panel/persona-format.md +2 -2
- package/skills/persona-panel/presets/designer-lens.md +1 -1
- package/skills/persona-panel/presets/engineer-lens.md +1 -1
- package/skills/persona-panel/presets/pm-lens.md +1 -1
- package/skills/plan/mode-retro.md +19 -4
- package/skills/quality-gates/SKILL.md +6 -4
- package/skills/remote-offload/SKILL.md +4 -2
- package/skills/session-end/learning-patterns.md +23 -13
- package/skills/session-end/metrics-collection.md +6 -7
- package/skills/session-end/phase-3-2-docs-verification.md +7 -6
- package/skills/session-end/plan-verification.md +25 -9
- package/skills/session-end/references/phase-3-documentation-updates.md +13 -3
- package/skills/session-end/references/phase-4a-worktree-cleanup.md +2 -0
- package/skills/session-end/references/session-summary-template.md +1 -1
- package/skills/session-end/session-metrics-write.md +65 -68
- package/skills/session-plan/SKILL.md +0 -3
- package/skills/session-start/SKILL.md +8 -2
- package/skills/session-start/references/operations-contract.md +6 -0
- package/skills/session-start/references/phase-1-2-session-lock.md +32 -7
- package/skills/session-start/references/phase-1-7-vault-status-board.md +1 -1
- package/skills/session-start/references/phase-4-ssot-environment-check.md +10 -3
- package/skills/test-audit/SKILL.md +152 -0
- package/skills/test-audit/references/campaign.md +111 -0
- package/skills/test-audit/references/mutate.sh +50 -0
- package/skills/vault-mirror/SKILL.md +21 -11
- package/skills/wave-executor/SKILL.md +2 -2
- package/skills/wave-executor/circuit-breaker.md +1 -1
- package/skills/wave-executor/references/wave-executor-state-init.md +3 -0
- package/skills/wave-executor/references/wave-loop-dispatch.md +11 -1
- package/skills/wave-executor/references/wave-loop-review.md +4 -6
- package/skills/wave-executor/references/wave-loop-scope-manifest.md +13 -5
- package/templates/personas/README.md +5 -5
- package/templates/personas/accounting-compliance.v1.md +1 -1
- package/templates/personas/accounting-tax-advisor.v1.md +1 -1
- package/templates/personas/buyer-p1-cto.v1.md +1 -1
- package/templates/personas/buyer-p2-kanzlei.v1.md +1 -1
- package/templates/personas/buyer-p3-build.v1.md +1 -1
- package/templates/personas/buyer-p4-tech-veto.v1.md +1 -1
- package/templates/personas/buyer-p5-solo.v1.md +1 -1
- package/templates/personas/buyer-p6-ld.v1.md +1 -1
- package/templates/personas/klima-ai-expert.v1.md +1 -1
- package/templates/personas/klima-physicist.v1.md +1 -1
|
@@ -356,6 +356,11 @@ slopcheck:
|
|
|
356
356
|
| `max-turns` | integer or string | `auto` | Maximum agent turns before PARTIAL. Auto expands PER SESSION TYPE inside the resolved shape (`scripts/lib/session-shape.mjs` `MAX_TURNS_DEFAULT`, § Session Shapes above): housekeeping=8, feature=15, deep=25 (`maxTurnsDefault` in the shape JSON, applied to every wave). The `ultradeep` profile does **not** use one flat number — it sets `max-turns` PER WAVE: 40 for the Research+Code-Discovery wave, 25 for Impl-Core/Impl-Polish/Quality, 15 for Release/Finalization (the Synthesis-Gate wave is coordinator-direct and carries no `max-turns` at all). |
|
|
357
357
|
| `auto-commit-per-wave` | boolean | `false` | Automatically commit each wave's work after the Quality-Lite gate passes. Checkpoint commits per wave reduce the risk of data loss from `git stash` collisions in parallel sessions (V3.3 RESCUE incident — see GitLab #214). When `false`, all work is committed at session-end via `/close`. Requires `persistence: true`; the flag is silently ignored when `persistence: false`. Trade-off: each wave produces an additional commit; git log shows N+1 commits instead of 1. Use `/simplify` or `git rebase -i --autosquash` before final close to squash if a clean history is desired. **Implementation note:** the procedural commit sequence (`scripts/lib/auto-commit.mjs`) is deferred to V3.6. Until then, setting this flag to `true` triggers a session-start warning that auto-commits are not yet active — the flag is a no-op but is validated so projects can opt in early. <!-- path-check: historical --> |
|
|
358
358
|
|
|
359
|
+
**Guard coverage (moved from CLAUDE.md Critical Gotchas, 2026-09-25).** **Destructive-Command Guard is active in main + subagent waves on harnesses with a compatible command hook.** On Claude Code, and through the supported Cursor and Pi bridges, `hooks/pre-bash-destructive-guard.mjs` applies `.orchestrator/policy/blocked-commands.json`:
|
|
360
|
+
**12 of its 16 rules are `severity: block`, the other 4 only warn** (measured 2026-09-19: `jq '[.rules[].severity]|group_by(.)|map({(.[0]):length})|add' .orchestrator/policy/blocked-commands.json`).
|
|
361
|
+
The 16th is `ledger-delete-protected` (#1401): `rm`/`mv`/`unlink` on `.orchestrator/metrics/**` — added after a wave agent deleted a rotated 53.896-line ledger archive that no rule covered, because `rm` existed only as the pattern `rm -rf` and the redirect denylist's `*.jsonl` did not match `events.jsonl.1`.
|
|
362
|
+
On Codex, the destructive-command rules are instructions only because no compatible `PreToolUse` command handler is wired. Rule source of truth: [`.claude/rules/parallel-sessions.md`](../.claude/rules/parallel-sessions.md) (PSA-003). Per-session bypass via Session Config: `allow-destructive-ops: true` (intentional maintenance only).
|
|
363
|
+
|
|
359
364
|
### enforcement-gates: the five gate keys (#800/#915)
|
|
360
365
|
|
|
361
366
|
`enforcement-gates` is surfaced to the hook layer as `gates` inside the wave's
|
|
@@ -775,7 +780,25 @@ vault-integration:
|
|
|
775
780
|
vault-name: # optional (#660) — per-project vault namespace override
|
|
776
781
|
```
|
|
777
782
|
|
|
778
|
-
> **Host-local override (#653; extended #819).** `vault-dir` resolves host-locally with precedence: env-var (`SO_VAULT_DIR`) > `owner.yaml` `paths.vault-dir` > the committed default. `plan-baseline-path` resolves
|
|
783
|
+
> **Host-local override (#653; extended #819, agents/vault#319, #1448).** `vault-dir` resolves host-locally with precedence: env-var (`SO_VAULT_DIR`) > `owner.yaml` `vault-dirs:` directory-prefix match against cwd > `owner.yaml` `paths.vault-dir` > the committed default. `plan-baseline-path` resolves the same way: `SO_BASELINE_PATH` env > `owner.yaml` `baselines:` directory-prefix match against cwd > `owner.yaml` `paths.baseline-path` (legacy scalar) > the committed default. The match tier exists because one host-wide `paths.vault-dir` otherwise redirects EVERY repo on the host into one vault, including a repo whose own vault lives elsewhere on that host. First match wins, so list the more specific prefix first:
|
|
784
|
+
>
|
|
785
|
+
> ```yaml
|
|
786
|
+
> # ~/.config/session-orchestrator/owner.yaml
|
|
787
|
+
> paths:
|
|
788
|
+
> vault-dir: ~/Projects/work/vault # host-wide default
|
|
789
|
+
> vault-dirs:
|
|
790
|
+
> - path: ~/Projects/private-world/vault # used for any cwd under the prefix
|
|
791
|
+
> match: { path-prefix: ~/Projects/private-world/ }
|
|
792
|
+
> ```
|
|
793
|
+
>
|
|
794
|
+
> A leading `~` is expanded to the home directory: `path-prefix` when matching, and the `path` / `paths.vault-dir` value the two owner.yaml tiers return (`match`, `owner`). The `env` and `committed` tiers pass through unexpanded; `scripts/vault-mirror.mjs` expands its `--vault-dir` at entry, so a `~/…` from any tier reaches the vault rather than `<cwd>/~/…`.
|
|
795
|
+
>
|
|
796
|
+
> The parsed config reports which tier won as `vault-integration.vault-dir-source` (`env`, `match`, `owner`, `committed`). This keeps maintainer-specific absolute paths out of version control. Resolvers: `scripts/lib/config.mjs` (`resolveVaultDir`, exported; `scripts/vault-backfill.mjs` resolves its stub root through it, #1094), `scripts/lib/config/host-paths.mjs` (`resolveHostPath`, used for `plan-baseline-path`) and `scripts/lib/named-baseline-resolver.mjs` (the `baselines:` / `vault-dirs:` match tier).
|
|
797
|
+
>
|
|
798
|
+
> **Fake-repoRoot trap (moved from CLAUDE.md Critical Gotchas, 2026-09-25).** A throwaway invocation of a vault writer (`mirrorNarrative()`, `vault-mirror.mjs`, the board writer) with a synthetic `repoRoot` does **not** land in a sandbox — the fake repo path only fakes the SOURCE, never the DESTINATION. A reviewer in this repo walked into exactly that.
|
|
799
|
+
> Export `SO_VAULT_DIR=<tmpdir>` before ANY manual invocation of vault-writing code. <!-- consistency:exempt:runtime-only -->
|
|
800
|
+
>
|
|
801
|
+
> **Host-local switch (#1448).** A host can switch the integration off or soften it without touching the committed file, e.g. a host with no vault clone, where `vault-mirror.mjs` would otherwise exit 2 (`missing-vault-dir`) and a `strict` repo would block `/close`. Precedence: env `SO_VAULT_INTEGRATION=off|warn|strict` > `owner.yaml` `vault-integration: { enabled: false }` or `vault-integration: { mode: off|warn|strict }` > the committed block. The host may only LOWER the committed level (`strict` → `warn` → `off`); `enabled: true` or a stronger mode is ignored, so a host can never mirror a repo that did not opt in. An invalid `owner.yaml` `vault-integration:` section is dropped on its own (the rest of `owner.yaml` stays in force). When the host lowered the level, `vault-integration.host-override` names the tier (`env:SO_VAULT_INTEGRATION` or `owner.yaml`), otherwise it is `null`; session-end then prints `vault-mirror: bewusst aus auf diesem Host (<tier>)` instead of failing.
|
|
779
802
|
|
|
780
803
|
> **`SO_CONFIG_HOME` — the host-private config directory itself.** A sibling override, one layer below `owner.yaml`'s own contents rather than a key inside it: `scripts/lib/config/private-config-dir.mjs` (`resolvePrivateConfigDir()`) is THE resolver (#1223) for the directory holding `owner.yaml`, `host-private.json`, and the host-alias ledger (`SO_HOST_ALIASES_FILE`) — `scripts/lib/host-identity.mjs`'s `_privateDir()` delegates to it — with precedence env-var (`SO_CONFIG_HOME`, names the private dir ITSELF) > `XDG_CONFIG_HOME` (names its PARENT) > the homedir default `~/.config/session-orchestrator`. Both env vars are read with `.trim() || fallback`, not a bare `||` (`.claude/rules/development.md` § Error Handling env-var-fallback-whitespace trap).
|
|
781
804
|
|
|
@@ -784,10 +807,10 @@ vault-integration:
|
|
|
784
807
|
| Field | Type | Default | Description |
|
|
785
808
|
|-------|------|---------|-------------|
|
|
786
809
|
| `vault-integration.enabled` | boolean | `false` | If true, session-end and evolve skills invoke `vault-mirror.mjs` to sync learnings and sessions into the vault. When false (or missing), mirroring is skipped silently. |
|
|
787
|
-
| `vault-integration.vault-dir` | string or null | `null` | Absolute path to the vault repository.
|
|
810
|
+
| `vault-integration.vault-dir` | string or null | `null` | Absolute path to the vault repository. Host-local tiers override it (see the note above). If it is still empty after them, only the bash snippet in session-end and evolve falls back to the `$VAULT_DIR` env variable. Required when `enabled` is true. |
|
|
788
811
|
| `vault-integration.mode` | string | `warn` | Mirror error handling. `strict` blocks session close if the mirror exits non-zero. `warn` reports errors but does not block. `off` bypasses mirror invocation entirely (useful when transitioning). |
|
|
789
812
|
| `vault-integration.vault-name` | string or null | `null` | Optional override for the per-project vault namespace segment (#660). When set (or via CLI `--vault-name`), vault writes go to `40-learnings/<vault-name>/` and `50-sessions/<vault-name>/`, sanitised to a kebab slug. When null/absent, the namespace is derived from the git origin via `deriveRepo()`. Owner-privacy leaks (personal home path / private slug / personal name) are redacted to `redacted-repo`. NOT a filesystem path → NOT host-path-resolved. **Coverage gap:** portfolio board rows are NOT yet namespace-aware — the override only reaches `40-learnings/`, `50-sessions/`, and the per-repo narrative mirror (`narrative-mirror.mjs`, #832 item 2); tracked separately in #832. Resolver: `scripts/lib/vault-mirror/namespace.mjs` (`resolveRepoNamespace`). |
|
|
790
|
-
| `vault-integration.gitlab-groups` | string[] or null | `null` | List of GitLab group paths to scan for repos missing `.vault.yaml`.
|
|
813
|
+
| `vault-integration.gitlab-groups` | string[] or null | `null` | List of GitLab group paths to scan for repos missing `.vault.yaml`. Parsed by `_parseVaultIntegration` (`scripts/lib/config/vault-integration.mjs`) and consumed by `scripts/vault-backfill.mjs`. Accepts a comma string, `[a, b]`, or a YAML block list; in the inline-object form more than one group needs `[a, b]`; an empty list is `null`. YAML semantics: `null`, `~` and an empty value mean unset (as a list element too, where they are dropped), and each element loses one pair of matching quotes — `["a"]` is the group `a`, and only a quoted `"null"` element is a group named `null`. Also consumed by the `/plan retro` vault-backfill sub-mode (`skills/plan/mode-retro.md` Phase 1.6 Step 1). When null/unset and neither `--groups` nor `--yes` is passed, the backfill CLI exits 1 with `no GitLab groups specified — pass --groups <CSV> or set vault-integration.gitlab-groups in CLAUDE.md`. |
|
|
791
814
|
|
|
792
815
|
### Environment override: `VAULT_MIRROR_CANONICAL_SUFFIX`
|
|
793
816
|
|
|
@@ -843,7 +866,7 @@ Opt-out configuration for the agent-writable memory tool. During a wave, an agen
|
|
|
843
866
|
|
|
844
867
|
This is a Hermes-style memory-write API **without** Hermes' overwrites-manual-edits critique: the operator confirmation is mandatory and there is no silent overwrite path. Three safety layers keep the surface conservative:
|
|
845
868
|
|
|
846
|
-
1. **Quota per wave** — `quota-per-wave` (default `5`) caps how many proposals
|
|
869
|
+
1. **Quota per wave** — `quota-per-wave` (default `5`) caps how many proposals ONE WAVE may queue, all of its agents together — not each agent: the store counts a wave's records by `wave_id` only (`scripts/lib/memory-proposals/store.mjs`). In a wave of N agents the 6th proposal of the wave exits `1` regardless of which agent sends it, so one agent that proposes five times uses up the quota for every sibling. Excess proposals exit `1` and the call-site logs the rejection.
|
|
847
870
|
2. **Confidence floor** — `confidence-floor` (default `0.5`) rejects low-confidence proposals before they reach the operator (exit `2`). Tuned so a learning is only proposed when the agent is at least 50% sure of the insight.
|
|
848
871
|
3. **AUQ confirm-or-discard** — the session-end phase never auto-persists. Every proposal is `AskUserQuestion`-gated; the operator can accept, reject, or edit before commit.
|
|
849
872
|
|
|
@@ -853,14 +876,14 @@ All fields live under the top-level `memory` object in your Session Config host
|
|
|
853
876
|
memory:
|
|
854
877
|
proposals:
|
|
855
878
|
enabled: true # default true; opt-out master toggle for the memory.propose feature
|
|
856
|
-
quota-per-wave: 5 # max proposals
|
|
879
|
+
quota-per-wave: 5 # max proposals per wave, all agents together (exit 1 on overflow)
|
|
857
880
|
confidence-floor: 0.5 # proposals below this confidence are rejected (exit 2)
|
|
858
881
|
```
|
|
859
882
|
|
|
860
883
|
| Field | Type | Default | Description |
|
|
861
884
|
|-------|------|---------|-------------|
|
|
862
885
|
| `memory.proposals.enabled` | boolean | `true` | Master toggle for the entire memory-proposals feature. When `false`, the `memory.propose` CLI exits `3` (rejected-wrong-context) for every call and session-end Phase 3.6.3 is skipped. When `true`, agents may queue proposals during waves and the coordinator surfaces them at session-end. PRD F2.1 / issue #501. |
|
|
863
|
-
| `memory.proposals.quota-per-wave` | integer | `5` | Maximum number of proposals
|
|
886
|
+
| `memory.proposals.quota-per-wave` | integer | `5` | Maximum number of proposals a wave can queue, counted across ALL of its agents (the store counts records by `wave_id` only). The 6th proposal of a wave exits `1` (quota-exceeded) whichever agent sends it — in a wave of N agents, the first five proposals of the wave win. Bounds: integer ≥ 0. Set to `0` to disable proposals from agents without disabling the feature entirely (operator can still propose). |
|
|
864
887
|
| `memory.proposals.confidence-floor` | float | `0.5` | Minimum confidence (0.0..1.0) required for a proposal to be queued. Proposals with `--confidence < confidence-floor` exit `2` (rejected-low-confidence) before reaching the operator. Bounds: `0.0 ≤ value ≤ 1.0`. Set to `0.0` to accept any confidence (operator filters at AUQ time). |
|
|
865
888
|
|
|
866
889
|
### Agent CLI invocation
|
|
@@ -900,7 +923,7 @@ A successful dry-run exits `0` with stdout status `dry-run-ok` (see updated exit
|
|
|
900
923
|
|-----------|-----------------|---------|--------------|
|
|
901
924
|
| `0` | `queued` | Queued | Proposal accepted into the per-wave staging directory; awaits operator confirmation at session-end Phase 3.6.3. |
|
|
902
925
|
| `0` | `dry-run-ok` | Validated, not written | `--dry-run` was passed and the proposal (argv + schema) validated successfully. No write to `proposals.jsonl` occurs; the wrong-context gates are bypassed under this flag (#741.3). |
|
|
903
|
-
| `1` | `quota-exceeded` | Rejected — quota exceeded | This
|
|
926
|
+
| `1` | `quota-exceeded` | Rejected — quota exceeded | This wave has already queued `quota-per-wave` proposals, from any of its agents. Every further call in this wave fails, whichever agent makes it, until the next wave. Not applicable under `--dry-run` (gate bypassed). |
|
|
904
927
|
| `2` | `rejected-low-confidence` | Rejected — low confidence | `--confidence` argument is below `confidence-floor`. Tighten the insight or raise the confidence (operator can still tune the floor). |
|
|
905
928
|
| `3` | `rejected-wrong-context` | Rejected — wrong context | Feature disabled (`enabled: false`), STATE.md not active, or `SO_WAVE_AGENT != "1"` (call originated outside a wave-executor agent context). Not applicable under `--dry-run` (gate bypassed). |
|
|
906
929
|
| `4` | `error` | Arg error | Missing or malformed flag — invalid `--type`, empty `--subject`, non-numeric `--confidence`. The CLI prints a one-line usage message on stderr. |
|
|
@@ -1350,7 +1373,7 @@ remote-hosts:
|
|
|
1350
1373
|
|
|
1351
1374
|
**Two enums, never conflated.** `roles-allowed` holds `agent-mapping` roles (`test`, `ui`, `perf`) — NOT wave roles (`Impl-Core`, `Quality`, …). The wave→role translation is `OFFLOADABLE_WAVE_ROLES` in `scripts/lib/wave-resource-gate.mjs`; a wave role absent from that map is local-only by default.
|
|
1352
1375
|
|
|
1353
|
-
**Placement contract.** The gate applies its offload arm only after the HR-004 heavy-repo cap, and only when the resource verdict was `reduce` or `coordinator-direct
|
|
1376
|
+
**Placement contract.** The gate applies its offload arm only after the HR-004 heavy-repo cap, and only when the resource verdict was `reduce` or `coordinator-direct` — or, with `offload-first: true`, on `proceed` as well (see § `offload-first` below). It does NOT probe the network: the coordinator supplies a readiness witness (`remoteReady: { m5: true }`, or an async `probeFn`). With no witness, no host counts as ready and the decision stays local — the gate fails toward local, never toward an unverified host. A role in `NEVER_FOREIGN_ROLES` (`scripts/lib/wave-executor/dispatch-common.mjs`) is never offloaded regardless.
|
|
1354
1377
|
|
|
1355
1378
|
**agent-mapping interaction.** A declared alias is what an `agent-mapping` value of the form `<role>: ssh:<alias>` validates against; naming an undeclared host throws at parse time, naming the `ssh` channel with no target throws as for any other channel.
|
|
1356
1379
|
|
|
@@ -1358,6 +1381,32 @@ Read by: `scripts/lib/config/remote-hosts.mjs` (parser), `scripts/lib/config.mjs
|
|
|
1358
1381
|
|
|
1359
1382
|
See `skills/remote-offload/SKILL.md` for the wave-executor-side decision rule, the three offload channels, and how a declared alias here is what an `agent-mapping` `ssh:<alias>` value validates against.
|
|
1360
1383
|
|
|
1384
|
+
### `offload-first` (#1465)
|
|
1385
|
+
|
|
1386
|
+
Opt-in switch that makes placement the FIRST choice for an offloadable wave role, not only the answer to local pressure. Scalar key, so a trailing `# comment` on its line is fine (the block-header gotcha above does not apply).
|
|
1387
|
+
|
|
1388
|
+
```yaml
|
|
1389
|
+
offload-first: false # true = offloadable roles go to a witnessed-ready remote host even on `proceed`
|
|
1390
|
+
```
|
|
1391
|
+
|
|
1392
|
+
| Field | Type | Default | Description |
|
|
1393
|
+
|-------|------|---------|-------------|
|
|
1394
|
+
| `offload-first` | boolean | `false` | When `true`, the gate's offload arm fires on a `proceed` verdict too, not only on `reduce` / `coordinator-direct`. `false` (or absent) changes nothing. |
|
|
1395
|
+
|
|
1396
|
+
**Behaviour with `offload-first: true`.**
|
|
1397
|
+
|
|
1398
|
+
- Only roles in `OFFLOADABLE_WAVE_ROLES` (`scripts/lib/wave-resource-gate.mjs`) move: wave roles `quality` / `test` → `test`, `ui` → `ui`, `perf` → `perf`. The table is NOT extended by this switch — build, lint and audit work is covered by the Quality wave's `test` role. `impl-core`, `security-review`, `migration`, `release`, `secrets`, `incident` and `refactor-crosscut` never leave the local host.
|
|
1399
|
+
- The target is the FIRST declared `remote-hosts` entry whose `roles-allowed` carries the mapped role AND that is witnessed ready (`remoteReady: { m5: true }` or an async `probeFn`). The gate still never probes the network itself, so the witness is mandatory for the switch to have any effect: without one, nothing offloads even with the switch on.
|
|
1400
|
+
- The HR-004 heavy-repo cap still binds the offloaded agent count.
|
|
1401
|
+
- No ready host for the role → the verdict is unchanged (`proceed`, or the `reduce`/`coordinator-direct` the resource rules computed) and `reasons` carries `offload-first: no ready host for '<role>' — staying local`.
|
|
1402
|
+
- Switch on but no `remote-hosts` declared → the verdict is unchanged and `reasons` carries `offload-first: true but no remote-hosts declared — staying local`. `validateSessionConfig()` (`scripts/lib/config-schema.mjs`) additionally emits a warn-level cross-field finding `offload-first-cross-field` for that combination; it never flips `ok`.
|
|
1403
|
+
- `resource-awareness: false` remains a FULL opt-out (no probe, no HR-004 cap, no placement), as documented in § Environment Awareness — the switch does not change that.
|
|
1404
|
+
- On the `probe failed (ignored)` path placement DOES apply when the switch is on, because placement needs no measurement; the `probe failed (ignored)` reason is kept.
|
|
1405
|
+
|
|
1406
|
+
**Committed-only.** There is no host-local precedence (env > `owner.yaml` > committed) for this key: the existing `resolveDispatcherAutonomy` resolver is enum-specific and `owner.yaml` freezes its allowed sections, so reusing it would need a schema change for a need nobody has raised yet (BV-001) — the value in the committed Session Config is the value that applies.
|
|
1407
|
+
|
|
1408
|
+
Read by: `scripts/lib/config.mjs` (parser), `scripts/lib/config-schema.mjs` (cross-field warning), `scripts/lib/wave-resource-gate.mjs` (placement).
|
|
1409
|
+
|
|
1361
1410
|
## Evolve Extra Sources (#638)
|
|
1362
1411
|
|
|
1363
1412
|
Opt-in EXTRA learning sources for `/evolve`. A domain measurement (e.g. an eval-learn regression harness) runs OUT-OF-BAND and writes a sidecar JSON of regression flags; `/evolve` then READS each declared sidecar and emits a `domain-regression` learning candidate per flag that has persisted across ≥2 consecutive sessions. This is a strict **read-only consumption contract**: `/evolve` never runs the domain measurement — it only consumes the sidecar output. Absent/empty ⇒ `[]` ⇒ no extra sources are read; existing `/evolve` runs are unaffected.
|
|
@@ -1572,12 +1621,12 @@ reaper:
|
|
|
1572
1621
|
| `reaper.mode` | `report` \| `kill` | `report` | `report` runs the scan in dry-run (decide + audit, no signal); `kill` arms the signal path (PRD Stufe 2, after calibration). An unrecognised value falls back to `report` — never to `kill`. |
|
|
1573
1622
|
| `reaper.min-age-seconds` | integer (≥ 0) | `300` | DevWatchdog's hard limit for `tsgo`; the 2026-09-20 orphans were 7–17 min old, well above it. Self-healing clamp: a value below `min-scan-interval-seconds` is widened to it, because a process younger than one scan period can be born and reaped between two scans. |
|
|
1574
1623
|
| `reaper.min-scan-interval-seconds` | integer (≥ 1) | `30` | DevWatchdog's normal scan cadence. The throttle that keeps a `PostToolBatch` storm from taxing every tool call. |
|
|
1575
|
-
| `reaper.kill-grace-ms` | integer (≥ 0) | `10000` | `DEFAULT_KILL_GRACE_MS` from `
|
|
1624
|
+
| `reaper.kill-grace-ms` | integer (≥ 0) | `10000` | `DEFAULT_KILL_GRACE_MS` from `process-group.mjs:52` — repo convention, not newly invented. SIGTERM → grace → SIGKILL. |
|
|
1576
1625
|
| `reaper.verify-wait-ms` | integer (≥ 0) | `500` | Wait before reading the effect back. Without it the 2026-09-20 check falsely reported "still alive" measuring immediately after `kill -9` (PRD B6: a sent signal proves nothing). |
|
|
1577
1626
|
| `reaper.max-hook-latency-ms` | integer (≥ 1) | `50` | Ceiling the TRIGGER may delay a hook by — the config read, the marker `stat` and the detached spawn, measured with `performance.now()` in `maybeTriggerOrphanScan()`. Overrunning it writes ONE stderr WARN line and nothing else: no event (a `PostToolBatch`-class hook emitting per fire is the always-on signal HR-101 calls a broken instrument) and no abort (the child is already detached by then). The scan itself is not covered — that is the point of spawning detached. |
|
|
1578
1627
|
| `reaper.false-alarm-window` | integer (≥ 1) | `50` | Rolling window of audit decisions the HR-101 10 % false-alarm rate is judged over — a window in DECISIONS, not calendar time, so the rate has a population on quiet hosts too. Reaches the scan as `--false-alarm-window` on the detached child's argv and becomes `runOrphanScan`'s `falseAlarmWindow`; the CLI refuses `0`, which `falseAlarmRate()` would read as “every firing ever recorded” rather than as a window. |
|
|
1579
1628
|
|
|
1580
|
-
**Used by:** `hooks/post-tool-batch-wave-signal.mjs`, `hooks/on-stop.mjs` (both via `maybeTriggerOrphanScan()`), `scripts/lib/orphan-reaper.mjs`, `scripts/lib/config/reaper.mjs` (`_parseReaper`). PRD `docs/prd/2026-09-20-prozessgruppen-kill-und-waisen-waechter.md`, Epic #1425, issue #1432.
|
|
1629
|
+
**Used by:** `hooks/post-tool-batch-wave-signal.mjs`, `hooks/on-stop.mjs` (both via `maybeTriggerOrphanScan()` from `scripts/lib/orphan-reaper/trigger.mjs`), `scripts/lib/orphan-reaper.mjs`, `scripts/lib/config/reaper.mjs` (`_parseReaper`). PRD `docs/prd/2026-09-20-prozessgruppen-kill-und-waisen-waechter.md`, Epic #1425, issue #1432.
|
|
1581
1630
|
|
|
1582
1631
|
## Gate Timeout — Path B (#1425 A3)
|
|
1583
1632
|
|
|
@@ -1834,7 +1883,7 @@ persona-gate-wave:
|
|
|
1834
1883
|
after: quality # quality | impl-polish — wave name after which to fire
|
|
1835
1884
|
threshold: "all" # "M-of-N" | "all" | "N-of-N" — passed to parseThreshold
|
|
1836
1885
|
personas: [] # list of persona names from .claude/personas/; empty = all catalog
|
|
1837
|
-
dispatch-model:
|
|
1886
|
+
dispatch-model: opus # alias or full model ID — default 'opus'
|
|
1838
1887
|
mode: off # off | warn | strict
|
|
1839
1888
|
```
|
|
1840
1889
|
|
|
@@ -1844,7 +1893,7 @@ persona-gate-wave:
|
|
|
1844
1893
|
| `persona-gate-wave.after` | string (`quality` \| `impl-polish`) | `quality` | The wave role after which the hook fires. The hook runs once per session, immediately after the named wave's STATE.md update. |
|
|
1845
1894
|
| `persona-gate-wave.threshold` | string | `"all"` | Voting threshold passed to `parseThreshold()` from `scripts/lib/persona-panel/threshold.mjs`. Accepts `"all"`, `"any"`, or `"M-of-N"` where `1 ≤ M ≤ N ≤ 20`. Example: `"6-of-6"` requires every persona to vote PASS; `"4-of-6"` allows two dissenters. |
|
|
1846
1895
|
| `persona-gate-wave.personas` | string[] | `[]` | Roster of persona names to dispatch. Each entry must match `^[a-z0-9-]{1,64}$` and refer to a persona file under `.claude/personas/<name>.md`. When the list is empty (default), every persona in the catalog is dispatched. |
|
|
1847
|
-
| `persona-gate-wave.dispatch-model` | string | `
|
|
1896
|
+
| `persona-gate-wave.dispatch-model` | string | `opus` | Model used for each persona agent dispatch. Accepts the same shape as agent frontmatter `model:` — one of `inherit` \| `sonnet` \| `opus` \| `haiku` \| `fable`, or a full model ID like `claude-opus-5-5`. Default is the alias `opus`, which tracks the current Opus; pin a full ID only for a named reproducibility need. |
|
|
1848
1897
|
| `persona-gate-wave.mode` | string (`off` \| `warn` \| `strict`) | `off` | Behaviour on consolidator result. `off` skips dispatch entirely even when `enabled: true` (silent no-op). `warn` consolidates and logs findings under a `Persona-gate:` bullet in the wave progress update without blocking. `strict` consolidates and on any non-PROCEED verdict prompts the operator via `AskUserQuestion` to proceed-as-is, revise remaining waves, or abort. |
|
|
1849
1898
|
|
|
1850
1899
|
**Validation:**
|
|
@@ -410,6 +410,14 @@ The gate never probes the network. Without a readiness witness no host counts as
|
|
|
410
410
|
|
|
411
411
|
Read by: `scripts/lib/config/remote-hosts.mjs`, `scripts/lib/wave-resource-gate.mjs`.
|
|
412
412
|
|
|
413
|
+
`offload-first` (#1465) makes placement the first choice instead of the answer to pressure: with `true`, an offloadable role (`test` / `ui` / `perf`) goes to the first witnessed-ready declared host even when the gate verdict is `proceed`. It needs both a `remote-hosts` entry and a readiness witness to act; without them the wave stays local and the gate names the reason.
|
|
414
|
+
|
|
415
|
+
```yaml
|
|
416
|
+
offload-first: false # true = offloadable roles go to a witnessed-ready remote host even on `proceed`
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Read by: `scripts/lib/config.mjs`, `scripts/lib/config-schema.mjs`, `scripts/lib/wave-resource-gate.mjs`.
|
|
420
|
+
|
|
413
421
|
## Evolve Extra Sources (#638)
|
|
414
422
|
|
|
415
423
|
Opt-in EXTRA learning sources for `/evolve`. A `domain-regression` measurement (e.g. an eval-learn harness) runs OUT-OF-BAND and writes a sidecar JSON; `/evolve` then READS each declared sidecar and emits a `domain-regression` learning candidate per persistent regression flag. `/evolve` NEVER runs the measurement itself — this is a strict read-only consumption contract. Absent/empty ⇒ `[]` ⇒ no extra sources are read.
|
|
@@ -856,7 +864,7 @@ persona-gate-wave:
|
|
|
856
864
|
after: quality # quality | impl-polish
|
|
857
865
|
threshold: all # all | any | <m>-of-<n>
|
|
858
866
|
personas: [] # persona slugs the panel dispatches
|
|
859
|
-
dispatch-model:
|
|
867
|
+
dispatch-model: opus # alias or full model ID — default 'opus'
|
|
860
868
|
mode: off # off | warn | strict — enabled: true with mode: off never fires
|
|
861
869
|
|
|
862
870
|
# Agentic test orchestrator (/test) — run profiles and artifact retention
|
|
@@ -886,6 +894,7 @@ remote-hosts:
|
|
|
886
894
|
roles-allowed: [test, ui, perf] # subset of test|ui|perf (default: all three)
|
|
887
895
|
repo-path: ~/Projects/Alice # optional SAFE path (default: null)
|
|
888
896
|
claude-path: ~/.local/bin/claude # optional SAFE path (default: null)
|
|
897
|
+
offload-first: false # #1465: true = offloadable roles go to a witnessed-ready remote host even on `proceed`
|
|
889
898
|
|
|
890
899
|
# Evolve extra-sources — opt-in EXTRA /evolve learning sources (#638)
|
|
891
900
|
evolve:
|
|
@@ -1015,7 +1024,7 @@ reaper:
|
|
|
1015
1024
|
mode: report # report (decide + audit only) | kill (send signals — PRD Stufe 2)
|
|
1016
1025
|
min-age-seconds: 300 # DevWatchdog's hard limit for tsgo; the 2026-09-20 orphans were 7–17 min old
|
|
1017
1026
|
min-scan-interval-seconds: 30 # throttle; keeps a PostToolBatch storm from taxing every tool call
|
|
1018
|
-
kill-grace-ms: 10000 # DEFAULT_KILL_GRACE_MS from
|
|
1027
|
+
kill-grace-ms: 10000 # DEFAULT_KILL_GRACE_MS from process-group.mjs:52 — repo convention
|
|
1019
1028
|
verify-wait-ms: 500 # wait before reading the effect back (a sent signal proves nothing)
|
|
1020
1029
|
max-hook-latency-ms: 50 # ceiling a scan may delay a hook by
|
|
1021
1030
|
false-alarm-window: 50 # rolling window of audit decisions the HR-101 10 % rate is judged over
|
|
@@ -169,10 +169,14 @@ entirely. Source: `docs/session-config-reference.md` § Docs Orchestrator.
|
|
|
169
169
|
The `docs-writer` agent operates under a **hallucination ban**: every
|
|
170
170
|
substantive paragraph must trace to one of the canonical four sources, or
|
|
171
171
|
carry an inline `<!-- REVIEW: source needed -->` marker. The four sources are
|
|
172
|
-
defined once and reused everywhere
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
172
|
+
defined once — in `skills/docs-orchestrator/SKILL.md` — and reused everywhere.
|
|
173
|
+
Diffs take `"$SESSION_RANGE"`, ONE complete range (the pinned SHA's
|
|
174
|
+
`<sha>..HEAD`, else the resolved `<base>...HEAD` from the accessor in
|
|
175
|
+
`skills/session-end/plan-verification.md`); only the log keeps the two-dot
|
|
176
|
+
`$SESSION_START_REF..HEAD`. An empty range or ref is a skip, never "no changes":
|
|
177
|
+
|
|
178
|
+
1. **diff** — `git diff "$SESSION_RANGE"`
|
|
179
|
+
2. **git-log** — `git log "$SESSION_START_REF..HEAD" --format="%H %s%n%b"`
|
|
176
180
|
3. **session-memory** — `~/.claude/projects/<project>/memory/session-*.md` and
|
|
177
181
|
`.orchestrator/` outputs
|
|
178
182
|
4. **affected-files** — files in the wave-scope `allowedPaths` block
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generated_at": "2026-
|
|
3
|
-
"head": "
|
|
2
|
+
"generated_at": "2026-10-03T07:30:53.188Z",
|
|
3
|
+
"head": "0cfbaa2c4fad16d825b94b8000ca8aea3dc9af68",
|
|
4
4
|
"entries": [
|
|
5
5
|
{
|
|
6
6
|
"file": "hooks/_lib/atomic-json.mjs",
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
"pre-bash-sessions-ledger-guard.mjs",
|
|
62
62
|
"pre-bash-staging-fence.mjs",
|
|
63
63
|
"pre-bash-templates-first.mjs",
|
|
64
|
+
"pre-edit-sessions-ledger-guard.mjs",
|
|
64
65
|
"pre-task-scope-disjoint.mjs",
|
|
65
66
|
"skill-invocation-telemetry.mjs",
|
|
66
67
|
"subagent-telemetry.mjs"
|
|
@@ -239,6 +240,12 @@
|
|
|
239
240
|
"pre-bash-templates-first.mjs"
|
|
240
241
|
]
|
|
241
242
|
},
|
|
243
|
+
{
|
|
244
|
+
"file": "hooks/pre-edit-sessions-ledger-guard.mjs",
|
|
245
|
+
"reachable_from": [
|
|
246
|
+
"pre-edit-sessions-ledger-guard.mjs"
|
|
247
|
+
]
|
|
248
|
+
},
|
|
242
249
|
{
|
|
243
250
|
"file": "hooks/pre-task-scope-disjoint.mjs",
|
|
244
251
|
"reachable_from": [
|
|
@@ -301,6 +308,7 @@
|
|
|
301
308
|
{
|
|
302
309
|
"file": "scripts/lib/command-blocker.mjs",
|
|
303
310
|
"reachable_from": [
|
|
311
|
+
"on-stop.mjs",
|
|
304
312
|
"post-bash-issue-budget-refund.mjs",
|
|
305
313
|
"post-bash-write-verify.mjs",
|
|
306
314
|
"post-edit-validate.mjs",
|
|
@@ -308,7 +316,8 @@
|
|
|
308
316
|
"pre-bash-issue-budget.mjs",
|
|
309
317
|
"pre-bash-memory-propose-audit.mjs",
|
|
310
318
|
"pre-bash-staging-fence.mjs",
|
|
311
|
-
"pre-bash-templates-first.mjs"
|
|
319
|
+
"pre-bash-templates-first.mjs",
|
|
320
|
+
"pre-task-scope-disjoint.mjs"
|
|
312
321
|
]
|
|
313
322
|
},
|
|
314
323
|
{
|
|
@@ -320,7 +329,6 @@
|
|
|
320
329
|
"post-bash-issue-budget-refund.mjs",
|
|
321
330
|
"post-edit-validate.mjs",
|
|
322
331
|
"post-subagent-discovery-validator.mjs",
|
|
323
|
-
"post-tool-batch-wave-signal.mjs",
|
|
324
332
|
"pre-bash-issue-budget.mjs",
|
|
325
333
|
"pre-bash-templates-first.mjs"
|
|
326
334
|
]
|
|
@@ -835,8 +843,7 @@
|
|
|
835
843
|
"file": "scripts/lib/env-check.mjs",
|
|
836
844
|
"reachable_from": [
|
|
837
845
|
"post-bash-write-verify.mjs",
|
|
838
|
-
"post-edit-validate.mjs"
|
|
839
|
-
"pre-bash-memory-propose-audit.mjs"
|
|
846
|
+
"post-edit-validate.mjs"
|
|
840
847
|
]
|
|
841
848
|
},
|
|
842
849
|
{
|
|
@@ -947,6 +954,12 @@
|
|
|
947
954
|
"skill-invocation-telemetry.mjs"
|
|
948
955
|
]
|
|
949
956
|
},
|
|
957
|
+
{
|
|
958
|
+
"file": "scripts/lib/fleet-protocol.mjs",
|
|
959
|
+
"reachable_from": [
|
|
960
|
+
"on-session-start.mjs"
|
|
961
|
+
]
|
|
962
|
+
},
|
|
950
963
|
{
|
|
951
964
|
"file": "scripts/lib/frontend-detect/detect.mjs",
|
|
952
965
|
"reachable_from": [
|
|
@@ -963,8 +976,7 @@
|
|
|
963
976
|
"file": "scripts/lib/hardening.mjs",
|
|
964
977
|
"reachable_from": [
|
|
965
978
|
"post-bash-write-verify.mjs",
|
|
966
|
-
"post-edit-validate.mjs"
|
|
967
|
-
"pre-bash-memory-propose-audit.mjs"
|
|
979
|
+
"post-edit-validate.mjs"
|
|
968
980
|
]
|
|
969
981
|
},
|
|
970
982
|
{
|
|
@@ -1016,6 +1028,7 @@
|
|
|
1016
1028
|
"pre-bash-sessions-ledger-guard.mjs",
|
|
1017
1029
|
"pre-bash-staging-fence.mjs",
|
|
1018
1030
|
"pre-bash-templates-first.mjs",
|
|
1031
|
+
"pre-edit-sessions-ledger-guard.mjs",
|
|
1019
1032
|
"pre-task-scope-disjoint.mjs",
|
|
1020
1033
|
"skill-invocation-telemetry.mjs"
|
|
1021
1034
|
]
|
|
@@ -1045,6 +1058,7 @@
|
|
|
1045
1058
|
"pre-bash-sessions-ledger-guard.mjs",
|
|
1046
1059
|
"pre-bash-staging-fence.mjs",
|
|
1047
1060
|
"pre-bash-templates-first.mjs",
|
|
1061
|
+
"pre-edit-sessions-ledger-guard.mjs",
|
|
1048
1062
|
"pre-task-scope-disjoint.mjs",
|
|
1049
1063
|
"skill-invocation-telemetry.mjs",
|
|
1050
1064
|
"subagent-telemetry.mjs"
|
|
@@ -1145,7 +1159,21 @@
|
|
|
1145
1159
|
]
|
|
1146
1160
|
},
|
|
1147
1161
|
{
|
|
1148
|
-
"file": "scripts/lib/orphan-reaper.mjs",
|
|
1162
|
+
"file": "scripts/lib/orphan-reaper/defaults.mjs",
|
|
1163
|
+
"reachable_from": [
|
|
1164
|
+
"on-stop.mjs",
|
|
1165
|
+
"post-tool-batch-wave-signal.mjs"
|
|
1166
|
+
]
|
|
1167
|
+
},
|
|
1168
|
+
{
|
|
1169
|
+
"file": "scripts/lib/orphan-reaper/scan-throttle.mjs",
|
|
1170
|
+
"reachable_from": [
|
|
1171
|
+
"on-stop.mjs",
|
|
1172
|
+
"post-tool-batch-wave-signal.mjs"
|
|
1173
|
+
]
|
|
1174
|
+
},
|
|
1175
|
+
{
|
|
1176
|
+
"file": "scripts/lib/orphan-reaper/trigger.mjs",
|
|
1149
1177
|
"reachable_from": [
|
|
1150
1178
|
"on-stop.mjs",
|
|
1151
1179
|
"post-tool-batch-wave-signal.mjs"
|
|
@@ -1242,13 +1270,6 @@
|
|
|
1242
1270
|
"on-session-start.mjs"
|
|
1243
1271
|
]
|
|
1244
1272
|
},
|
|
1245
|
-
{
|
|
1246
|
-
"file": "scripts/lib/process-group.mjs",
|
|
1247
|
-
"reachable_from": [
|
|
1248
|
-
"on-stop.mjs",
|
|
1249
|
-
"post-tool-batch-wave-signal.mjs"
|
|
1250
|
-
]
|
|
1251
|
-
},
|
|
1252
1273
|
{
|
|
1253
1274
|
"file": "scripts/lib/resource-probe.mjs",
|
|
1254
1275
|
"reachable_from": [
|
|
@@ -1264,9 +1285,7 @@
|
|
|
1264
1285
|
{
|
|
1265
1286
|
"file": "scripts/lib/resource-probe/parsers.mjs",
|
|
1266
1287
|
"reachable_from": [
|
|
1267
|
-
"on-session-start.mjs"
|
|
1268
|
-
"on-stop.mjs",
|
|
1269
|
-
"post-tool-batch-wave-signal.mjs"
|
|
1288
|
+
"on-session-start.mjs"
|
|
1270
1289
|
]
|
|
1271
1290
|
},
|
|
1272
1291
|
{
|
|
@@ -1284,10 +1303,12 @@
|
|
|
1284
1303
|
{
|
|
1285
1304
|
"file": "scripts/lib/scope-gate.mjs",
|
|
1286
1305
|
"reachable_from": [
|
|
1306
|
+
"on-stop.mjs",
|
|
1287
1307
|
"post-bash-write-verify.mjs",
|
|
1288
1308
|
"post-edit-validate.mjs",
|
|
1289
1309
|
"post-tool-batch-wave-signal.mjs",
|
|
1290
|
-
"pre-bash-memory-propose-audit.mjs"
|
|
1310
|
+
"pre-bash-memory-propose-audit.mjs",
|
|
1311
|
+
"pre-task-scope-disjoint.mjs"
|
|
1291
1312
|
]
|
|
1292
1313
|
},
|
|
1293
1314
|
{
|
|
@@ -1387,8 +1408,7 @@
|
|
|
1387
1408
|
"reachable_from": [
|
|
1388
1409
|
"on-session-end.mjs",
|
|
1389
1410
|
"on-session-start.mjs",
|
|
1390
|
-
"on-stop.mjs"
|
|
1391
|
-
"post-tool-batch-wave-signal.mjs"
|
|
1411
|
+
"on-stop.mjs"
|
|
1392
1412
|
]
|
|
1393
1413
|
},
|
|
1394
1414
|
{
|
|
@@ -1643,13 +1663,6 @@
|
|
|
1643
1663
|
"pre-bash-staging-fence.mjs"
|
|
1644
1664
|
]
|
|
1645
1665
|
},
|
|
1646
|
-
{
|
|
1647
|
-
"file": "scripts/lib/wave-executor/dispatch-common.mjs",
|
|
1648
|
-
"reachable_from": [
|
|
1649
|
-
"on-stop.mjs",
|
|
1650
|
-
"post-tool-batch-wave-signal.mjs"
|
|
1651
|
-
]
|
|
1652
|
-
},
|
|
1653
1666
|
{
|
|
1654
1667
|
"file": "scripts/lib/wave-sizing.mjs",
|
|
1655
1668
|
"reachable_from": [
|