session-orchestrator 5.0.0 → 5.2.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/autopilot/SKILL.md +1 -0
- package/.agents/skills/bootstrap/SKILL.md +2 -0
- package/.agents/skills/brainstorm/SKILL.md +3 -0
- package/.agents/skills/close/SKILL.md +17 -0
- package/.agents/skills/debug/SKILL.md +2 -0
- package/.agents/skills/discovery/SKILL.md +2 -1
- package/.agents/skills/dispatcher/SKILL.md +2 -0
- package/.agents/skills/eli5/SKILL.md +2 -0
- package/.agents/skills/eval/SKILL.md +1 -0
- package/.agents/skills/evolve/SKILL.md +2 -1
- package/.agents/skills/go/SKILL.md +18 -0
- package/.agents/skills/grill/SKILL.md +2 -0
- package/.agents/skills/harness-audit/SKILL.md +16 -0
- package/.agents/skills/memory-cleanup/SKILL.md +1 -0
- package/.agents/skills/persona-panel/SKILL.md +1 -0
- package/.agents/skills/plan/SKILL.md +3 -1
- package/.agents/skills/portfolio/SKILL.md +17 -0
- package/.agents/skills/reconcile/SKILL.md +1 -0
- package/.agents/skills/release/SKILL.md +18 -0
- package/.agents/skills/repo-audit/SKILL.md +1 -0
- package/.agents/skills/spinout/SKILL.md +1 -0
- package/.agents/skills/sunset-review/SKILL.md +2 -0
- package/.agents/skills/test/SKILL.md +17 -0
- package/.agents/skills/ux-grill/SKILL.md +2 -0
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +2 -2
- package/.codex-plugin/skills/autopilot/SKILL.md +5 -4
- package/.codex-plugin/skills/bootstrap/SKILL.md +8 -4
- package/.codex-plugin/skills/brainstorm/SKILL.md +11 -4
- package/.codex-plugin/skills/close/SKILL.md +3 -3
- package/.codex-plugin/skills/convergence-monitoring/SKILL.md +2 -0
- package/.codex-plugin/skills/convergence-monitoring/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/debug/SKILL.md +11 -4
- package/.codex-plugin/skills/discovery/SKILL.md +8 -4
- package/.codex-plugin/skills/dispatcher/SKILL.md +4 -4
- package/.codex-plugin/skills/eli5/SKILL.md +9 -4
- package/.codex-plugin/skills/eval/SKILL.md +9 -4
- package/.codex-plugin/skills/evolve/SKILL.md +9 -4
- package/.codex-plugin/skills/go/SKILL.md +3 -3
- package/.codex-plugin/skills/grill/SKILL.md +11 -4
- package/.codex-plugin/skills/harness-audit/SKILL.md +4 -3
- package/.codex-plugin/skills/memory-cleanup/SKILL.md +9 -4
- package/.codex-plugin/skills/npm-publish/SKILL.md +2 -0
- package/.codex-plugin/skills/npm-publish/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/persona-panel/SKILL.md +5 -5
- package/.codex-plugin/skills/plan/SKILL.md +8 -4
- package/.codex-plugin/skills/portfolio/SKILL.md +3 -3
- package/.codex-plugin/skills/reconcile/SKILL.md +9 -4
- package/.codex-plugin/skills/release/SKILL.md +3 -3
- package/.codex-plugin/skills/repo-audit/SKILL.md +6 -4
- package/.codex-plugin/skills/spinout/SKILL.md +4 -4
- package/.codex-plugin/skills/sunset-review/SKILL.md +5 -4
- package/.codex-plugin/skills/test/SKILL.md +3 -3
- package/.codex-plugin/skills/ux-grill/SKILL.md +11 -4
- package/.cursor/commands/autopilot.md +4 -4
- package/.cursor/commands/bootstrap.md +5 -4
- package/.cursor/commands/brainstorm.md +5 -4
- package/.cursor/commands/close.md +4 -3
- package/.cursor/commands/convergence-monitoring.md +13 -0
- package/.cursor/commands/debug.md +4 -4
- package/.cursor/commands/discovery.md +4 -4
- package/.cursor/commands/dispatcher.md +4 -4
- package/.cursor/commands/eli5.md +4 -4
- package/.cursor/commands/eval.md +4 -4
- package/.cursor/commands/evolve.md +4 -4
- package/.cursor/commands/go.md +4 -3
- package/.cursor/commands/grill.md +4 -4
- package/.cursor/commands/harness-audit.md +3 -3
- package/.cursor/commands/memory-cleanup.md +4 -4
- package/.cursor/commands/npm-publish.md +13 -0
- package/.cursor/commands/persona-panel.md +4 -4
- package/.cursor/commands/plan.md +5 -4
- package/.cursor/commands/portfolio.md +3 -3
- package/.cursor/commands/reconcile.md +4 -4
- package/.cursor/commands/release.md +4 -3
- package/.cursor/commands/repo-audit.md +4 -4
- package/.cursor/commands/spinout.md +4 -4
- package/.cursor/commands/sunset-review.md +4 -4
- package/.cursor/commands/test.md +3 -3
- package/.cursor/commands/ux-grill.md +4 -4
- package/.cursor/rules/010-session-workflow.mdc +2 -2
- package/.cursor/skills/bootstrap/SKILL.md +1 -0
- package/.cursor/skills/close/SKILL.md +13 -0
- package/.cursor/skills/debug/SKILL.md +0 -1
- package/.cursor/skills/discovery/SKILL.md +0 -1
- package/.cursor/skills/dispatcher/SKILL.md +0 -1
- package/.cursor/skills/eli5/SKILL.md +0 -1
- package/.cursor/skills/evolve/SKILL.md +0 -1
- package/.cursor/skills/go/SKILL.md +13 -0
- package/.cursor/skills/grill/SKILL.md +0 -1
- package/.cursor/skills/harness-audit/SKILL.md +12 -0
- package/.cursor/skills/portfolio/SKILL.md +12 -0
- package/.cursor/skills/release/SKILL.md +13 -0
- package/.cursor/skills/repo-audit/SKILL.md +0 -1
- package/.cursor/skills/sunset-review/SKILL.md +0 -1
- package/.cursor/skills/test/SKILL.md +12 -0
- package/.cursor/skills/ux-grill/SKILL.md +0 -1
- package/.cursor-plugin/plugin.json +2 -2
- package/.orchestrator/policy/blocked-commands.json +10 -0
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +80 -0
- package/README.md +74 -235
- package/commands/session.md +10 -0
- package/docs/USER-GUIDE.md +24 -0
- package/docs/ci-setup.md +53 -0
- package/docs/codex-setup.md +1 -1
- package/docs/components.md +12 -5
- package/docs/events-schema.md +5 -1
- package/docs/install.md +128 -0
- package/docs/persona-panel.md +1 -1
- package/docs/pi-setup.md +1 -1
- package/docs/rule-authoring.md +83 -14
- package/docs/scope-collision-guard.md +2 -0
- package/docs/session-config-reference.md +6 -4
- package/docs/session-config-template.md +38 -0
- package/docs/telemetry.md +15 -0
- package/hooks/_lib/hook-import-set.json +46 -6
- package/hooks/_lib/subagent-paths.mjs +15 -0
- package/hooks/_lib/vcs-create-matcher.mjs +217 -62
- package/hooks/enforce-scope.mjs +42 -1
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks.json +1 -1
- package/hooks/on-session-end.mjs +14 -2
- package/hooks/on-stop.mjs +43 -1
- package/hooks/post-bash-write-verify.mjs +3 -0
- package/hooks/pre-auq-clarity.mjs +3 -0
- package/hooks/pre-bash-issue-budget.mjs +103 -17
- package/hooks/pre-task-scope-disjoint.mjs +152 -3
- package/hooks/skill-invocation-telemetry.mjs +2 -1
- package/package.json +3 -2
- package/pi/prompts/autopilot.md +3 -3
- package/pi/prompts/bootstrap.md +3 -3
- package/pi/prompts/brainstorm.md +3 -3
- package/pi/prompts/close.md +2 -2
- package/pi/prompts/convergence-monitoring.md +11 -0
- package/pi/prompts/debug.md +3 -3
- package/pi/prompts/discovery.md +3 -3
- package/pi/prompts/dispatcher.md +3 -3
- package/pi/prompts/eli5.md +3 -3
- package/pi/prompts/eval.md +3 -3
- package/pi/prompts/evolve.md +3 -3
- package/pi/prompts/go.md +2 -2
- package/pi/prompts/grill.md +3 -3
- package/pi/prompts/harness-audit.md +2 -3
- package/pi/prompts/memory-cleanup.md +3 -3
- package/pi/prompts/npm-publish.md +11 -0
- package/pi/prompts/persona-panel.md +3 -3
- package/pi/prompts/plan.md +3 -3
- package/pi/prompts/portfolio.md +2 -2
- package/pi/prompts/reconcile.md +3 -3
- package/pi/prompts/release.md +3 -3
- package/pi/prompts/repo-audit.md +3 -4
- package/pi/prompts/session.md +1 -1
- package/pi/prompts/spinout.md +3 -3
- package/pi/prompts/sunset-review.md +3 -3
- package/pi/prompts/templates-ack.md +1 -1
- package/pi/prompts/test.md +3 -3
- package/pi/prompts/ux-grill.md +3 -3
- package/scripts/archive-closed-prds.mjs +2 -2
- package/scripts/auq-audit.mjs +2 -3
- package/scripts/backfill-abandoned-sessions.mjs +57 -3
- package/scripts/backfill-evidence-digest.mjs +2 -1
- package/scripts/backfill-learnings-from-vault.mjs +2 -2
- package/scripts/check-package-manager.mjs +2 -2
- package/scripts/ci/assert-vitest-green.mjs +2 -1
- package/scripts/emit-session.mjs +2 -3
- package/scripts/export-hw-learnings.mjs +2 -1
- package/scripts/express-path.mjs +1 -1
- package/scripts/gc-stale-worktrees.mjs +2 -1
- package/scripts/generate-codex-skills.mjs +48 -4
- package/scripts/generate-cursor-adapter.mjs +173 -9
- package/scripts/generate-hook-import-set.mjs +12 -27
- package/scripts/generate-pi-prompts.mjs +183 -13
- package/scripts/github-protection-audit.mjs +2 -3
- package/scripts/lib/agent-frontmatter.mjs +23 -1
- package/scripts/lib/claude-md-budget-lint.mjs +2 -5
- package/scripts/lib/command-blocker.mjs +209 -9
- package/scripts/lib/config/drift-check.mjs +19 -0
- package/scripts/lib/convergence-monitor.mjs +2 -2
- package/scripts/lib/cursor-hook-bridge.mjs +2 -2
- package/scripts/lib/description-surface.mjs +2 -5
- package/scripts/lib/dispatcher/cli.mjs +2 -1
- package/scripts/lib/ecosystem-wizard.mjs +2 -1
- package/scripts/lib/fetch-baseline.mjs +3 -8
- package/scripts/lib/gitlab-ops/stale-mr-sweep.mjs +2 -1
- package/scripts/lib/gitlab-portfolio/cli.mjs +2 -1
- package/scripts/lib/instruction-budget-guard.mjs +186 -46
- package/scripts/lib/is-main-module.mjs +82 -0
- package/scripts/lib/locks/index.mjs +32 -25
- package/scripts/lib/maintenance-due-banner.mjs +69 -3
- package/scripts/lib/peer-discovery.mjs +2 -5
- package/scripts/lib/playwright-driver/runner.mjs +63 -2
- package/scripts/lib/reconcile/rule-expiry-sweep.mjs +642 -0
- package/scripts/lib/rules-sync.mjs +2 -5
- package/scripts/lib/scope-echo.mjs +392 -7
- package/scripts/lib/session-close-backfill.mjs +58 -6
- package/scripts/lib/state-md.mjs +84 -3
- package/scripts/lib/sunset/walker.mjs +31 -4
- package/scripts/lib/tests-src-ratio.mjs +2 -6
- package/scripts/lib/tmux-layout/telemetry-stats.mjs +2 -1
- package/scripts/lib/user-invocable-skills.mjs +185 -0
- package/scripts/lib/validate/check-banner-parity.mjs +2 -2
- package/scripts/lib/validate/check-cursor-adapter.mjs +2 -2
- package/scripts/lib/validate/check-dead-bridge.mjs +2 -2
- package/scripts/lib/validate/check-doc-cli-commands.mjs +2 -2
- package/scripts/lib/validate/check-entry-guard.mjs +366 -0
- package/scripts/lib/validate/check-guard-requires-parity.mjs +2 -2
- package/scripts/lib/validate/check-hooks-emit-event-guard.mjs +2 -2
- package/scripts/lib/validate/check-learning-provenance.mjs +2 -2
- package/scripts/lib/validate/check-skill-links.mjs +27 -6
- package/scripts/lib/validate/check-skill-script-paths.mjs +2 -2
- package/scripts/lib/validate/check-test-git-config-target.mjs +2 -2
- package/scripts/lib/validate/check-unicode-safety.mjs +2 -2
- package/scripts/lib/validate/check-untracked-test-deps.mjs +2 -2
- package/scripts/lib/validate/check-unwired-features.mjs +266 -11
- package/scripts/lib/validate/check-validator-registration.mjs +2 -2
- package/scripts/lib/validate/check-vcs-repo-flag.mjs +2 -2
- package/scripts/lib/validate-vendored-rules.mjs +35 -9
- package/scripts/lib/wave-transcript-tail.mjs +2 -2
- package/scripts/lock-reaper.mjs +2 -1
- package/scripts/materialize-wave-scope.mjs +87 -4
- package/scripts/migrate-sessions-jsonl.mjs +2 -1
- package/scripts/migrate-vault-paths.mjs +2 -3
- package/scripts/release.mjs +124 -35
- package/scripts/relocate-vault-corpus.mjs +2 -3
- package/scripts/repair-invalid-sessions.mjs +2 -2
- package/scripts/session-shape.mjs +2 -2
- package/scripts/site-numbers.mjs +35 -11
- package/scripts/sweep-expired-rules.mjs +216 -0
- package/scripts/validate-plugin.mjs +9 -0
- package/scripts/vault-consolidate.mjs +2 -2
- package/scripts/vault-mirror.mjs +2 -3
- package/scripts/wave-scope-binding.mjs +2 -3
- package/skills/_shared/bootstrap-gate.md +1 -1
- package/skills/_shared/monitor-patterns.md +1 -1
- package/skills/_shared/research-evidence.md +53 -0
- package/skills/_shared/state-ownership.md +3 -0
- package/skills/autopilot/SKILL.md +58 -4
- package/skills/bootstrap/SKILL.md +51 -1
- package/skills/brainstorm/SKILL.md +16 -0
- package/skills/claude-md-drift-check/checker.mjs +49 -11
- package/{commands/close.md → skills/close/SKILL.md} +9 -3
- package/skills/debug/SKILL.md +10 -0
- package/skills/discovery/SKILL.md +24 -1
- package/skills/discovery/probes-session.md +2 -2
- package/skills/dispatcher/SKILL.md +38 -7
- package/skills/eli5/SKILL.md +11 -0
- package/skills/eval/SKILL.md +14 -0
- package/skills/evolve/SKILL.md +8 -1
- package/skills/evolve/references/evolve-dialectic-mode.md +6 -2
- package/{commands/go.md → skills/go/SKILL.md} +9 -1
- package/skills/grill/SKILL.md +19 -0
- package/{commands/harness-audit.md → skills/harness-audit/SKILL.md} +7 -2
- package/skills/hook-development/SKILL.md +46 -41
- package/skills/memory-cleanup/SKILL.md +7 -0
- package/skills/npm-publish/SKILL.md +1 -1
- package/skills/persona-panel/SKILL.md +56 -1
- package/skills/persona-panel/persona-format.md +1 -1
- package/skills/plan/SKILL.md +28 -1
- package/skills/playwright-driver/SKILL.md +7 -10
- package/{commands/portfolio.md → skills/portfolio/SKILL.md} +8 -2
- package/skills/reconcile/SKILL.md +10 -0
- package/{commands/release.md → skills/release/SKILL.md} +16 -2
- package/skills/repo-audit/SKILL.md +7 -0
- package/skills/session-end/plan-verification.md +2 -2
- package/skills/session-plan/SKILL.md +1 -1
- package/skills/session-start/SKILL.md +5 -4
- package/skills/session-start/phase-8-5-express-path.md +6 -6
- package/skills/session-start/references/phase-1-5-session-continuity.md +1 -1
- package/skills/session-start/references/phase-2-7-portfolio-snapshot.md +1 -1
- package/skills/session-start/references/phase-4-ssot-environment-check.md +4 -3
- package/skills/spinout/SKILL.md +12 -1
- package/skills/sunset-review/SKILL.md +13 -0
- package/{commands/test.md → skills/test/SKILL.md} +10 -4
- package/skills/ux-grill/SKILL.md +19 -1
- package/skills/wave-executor/SKILL.md +7 -4
- package/skills/wave-executor/references/wave-executor-state-init.md +13 -1
- package/skills/wave-executor/references/wave-loop-dispatch.md +3 -1
- package/skills/wave-executor/references/wave-loop-review.md +17 -1
- package/commands/autopilot.md +0 -80
- package/commands/bootstrap.md +0 -56
- package/commands/brainstorm.md +0 -48
- package/commands/debug.md +0 -36
- package/commands/discovery.md +0 -32
- package/commands/dispatcher.md +0 -59
- package/commands/eli5.md +0 -33
- package/commands/eval.md +0 -28
- package/commands/evolve.md +0 -10
- package/commands/grill.md +0 -45
- package/commands/memory-cleanup.md +0 -26
- package/commands/persona-panel.md +0 -121
- package/commands/plan.md +0 -15
- package/commands/reconcile.md +0 -23
- package/commands/repo-audit.md +0 -24
- package/commands/spinout.md +0 -15
- package/commands/sunset-review.md +0 -27
- package/commands/ux-grill.md +0 -51
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ux-grill
|
|
3
3
|
description: "Use when a running web app's UX has to be audited reproducibly rather than by feel — a deterministic mechanical pass over routes and viewports (axe, target size, horizontal overflow, page title, scripted journeys) followed by a screenshot-grounded interrogation of the operator, journey by journey, with two persona lenses from the target repo's manifest. Triggered by \"grill the UX\", \"roast the dashboard\", \"UX-Audit\", \"/ux-grill\". Bootstraps its own manifest from a loopback URL on the first run, so it never requires a hand-written file to start."
|
|
4
|
-
disable-model-invocation: true
|
|
5
4
|
---
|
|
6
5
|
|
|
7
6
|
# ux-grill
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "session-orchestrator",
|
|
3
|
-
"version": "5.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "5.2.0",
|
|
4
|
+
"description": "A repeatable Plan, Go, Close workflow for AI coding sessions: /session reads your repo and agrees the scope, /go runs the work in waves with a quality gate between each, /close verifies and commits. Runs on Claude Code, Codex CLI, Cursor and Pi.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Bernhard Goetzendorfer"
|
|
7
7
|
},
|
|
@@ -116,6 +116,16 @@
|
|
|
116
116
|
"modes": ["truncate"],
|
|
117
117
|
"rationale": "Truncating redirect (>, &>, N>) onto protected artefacts silently destroys them — #983. Append (>>) stays allowed.",
|
|
118
118
|
"sources": ["#983"]
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"id": "redirect-harness-memory",
|
|
122
|
+
"type": "redirect-truncate",
|
|
123
|
+
"pattern": ">",
|
|
124
|
+
"severity": "block",
|
|
125
|
+
"target-denylist": ["~/.claude/projects/*/memory/**","~/.codex/projects/*/memory/**","~/.cursor/projects/*/memory/**"],
|
|
126
|
+
"modes": ["truncate","append"],
|
|
127
|
+
"rationale": "The harness auto-memory directory is injected as TRUSTED project context into every later session, yet lives outside git diff, CI review, check-owner-leakage (git ls-files only) and gitleaks. #1352 closed the Edit/Write lane for dispatched agents; this closes the shell-redirect lane, append included. NAMED CEILING (BV-004), every case measured 2026-09-13: (a) redirect-shaped by construction — `tee -a` and an in-process write (node -e fs.appendFileSync) are NOT covered; (b) NAMED CEILING: `eval` with a non-literal payload (`eval \"$CMD\"`, `eval $(…)`) is unreachable — the command text does not exist at hook time (`unresolved` class, #641). Literal `eval '… > target'`, `dd of=target` and `env -S <str> …` are covered since #1366; (c) a cwd-relative target after a directory change (`cd ~ && … > .claude/projects/*/memory/…`) is out of reach — the hook does not know the chain's cwd and a relative target is judged repo-root-relative, which is not lexically solvable; (d) `$HOME` / `${HOME}` / `$(…)` / backticks in the target fall into the pre-existing `unresolved` class (#641), where the hook warns and allows rather than guessing — for a home directory that is the most natural spelling. (e) the payload-evaluation budget is SHARED and finite (`MAX_PAYLOAD_EVALUATIONS` = 32 in `scripts/lib/command-blocker.mjs`): once it is spent, redirect-target collection returns `{unresolved, reason: 'budget-exhausted'}`, which this rule treats like every other unresolved target — warn and ALLOW. Measured 2026-09-16: 40 `eval 'echo fN'` fillers followed by `eval 'echo x > ~/.claude/…/MEMORY.md'` → ALLOW plus `⚠ unresolved redirect target (budget-exhausted)`. Not a regression of #1366 — `bash -c` fillers exhaust the same budget at HEAD (#988 T2) — but a standing ceiling of the same class as (d), and an attacker-controllable one: the filler count is free. Revisit together with (d) if the unresolved class is ever made blocking. Revisit if the policy grows a non-redirect target class or the payload traversal learns redirects. Home-anchored entries are matched against the expanded ABSOLUTE path (#1362) because relativizeAgainstRoot discards every out-of-repo target by design.",
|
|
128
|
+
"sources": ["#1352","#1362"]
|
|
119
129
|
}
|
|
120
130
|
]
|
|
121
131
|
}
|
package/AGENTS.md
CHANGED
|
@@ -31,7 +31,7 @@ These are the non-obvious, mistake-causing facts that must load every session. E
|
|
|
31
31
|
Phase 4 of session-start invokes `scripts/lib/ci-status-banner.mjs` via `checkCiStatus({ repoRoot })` to render a 🚨 banner when CI is red on HEAD.
|
|
32
32
|
Never claim CI green from `npm test` alone — the 8-pipeline silent regression (2026-05-09 → 2026-05-10, fixed in deep-2) is the cautionary tale. <!-- consistency:exempt:runtime-only -->
|
|
33
33
|
- **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`:
|
|
34
|
-
**
|
|
34
|
+
**11 of its 15 rules are `severity: block`, the other 4 only warn** (measured 2026-09-16: `jq '[.rules[].severity]|group_by(.)|map({(.[0]):length})|add' .orchestrator/policy/blocked-commands.json`). On Codex, the destructive-command rules are instructions only because no compatible `PreToolUse` command handler is wired.
|
|
35
35
|
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).
|
|
36
36
|
- **Session Config below is runtime-critical.** `scripts/parse-config.mjs` parses the `## Session Config` block; `claude-md-drift-check` Check 6 enforces top-level-key parity against `docs/session-config-template.md`. Edit it like code, not prose — a dropped key changes runtime behaviour.
|
|
37
37
|
- **Live state is not in this file.** Stack: Node 24+, vitest, ESLint 10 (`npm ci` after clone). Test counts, backlog, version, component inventory drift fast — the SSOT is README badges + `.orchestrator/metrics/sessions.jsonl`. Per-session detail lives in the Meta-Vault decisions log (linked above), not here.
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,86 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [5.2.0] - 2026-09-17
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `scripts/lib/is-main-module.mjs` (`isMainModule(importMetaUrl)`, realpath-resolved on both sides) plus the BLOCKING validator `scripts/lib/validate/check-entry-guard.mjs`, registered in `scripts/validate-plugin.mjs` (#1371). The issue's premise was refuted first: the sweep it recorded as landed on `f1da471f` is unknown to `git log --all`, and the module it depended on did not exist. 51 files carry the new guard (50 from the enumerated sweep plus `scripts/lib/validate/check-unwired-features.mjs` as an in-scope same-pattern site); the hand-rolled `process.argv[1]` comparison came in **15** textual variants, not the 17 the issue claimed. The validator measures **0 fragile of 508** modules on the current tree. Two of its own defects were caught by its own tests before it was registered: a git pathspec `**` that silently skipped 95 files, and a `file://` occurrence inside a comment counted as a guard.
|
|
15
|
+
- `tests/scripts/pack-install-lifecycle.test.mjs`, the `test:pack` script in `package.json` and the CI job `pack-lifecycle` in `.gitlab-ci.yml`, hard-wired into `pipeline-gate`'s `needs` (#1375). It installs the ACTUAL tarball rather than the checkout and asserts the installed `pre-bash-destructive-guard.mjs` denies `rm -rf /` while staying silent on a benign command. Measured end-to-end in W1: `npm pack` 15 s, tarball 3,963,485 B, install 3 s / 67 packages. It is deliberately NOT in `npm test` — it needs the network, so it is its own script and its own job.
|
|
16
|
+
- Six skill mirrors `skills/{close,go,harness-audit,portfolio,release,test}/SKILL.md` (plus the generated `.agents/` and `.cursor/` adapter copies) so the bare commands resolve under `claude -p` (#1370). Two mechanisms were isolated and proven separately in W1, against `claude 2.1.273` with a minimal plugin: `/session` and `/plan` are reserved TERMINAL BUILT-INS (they shadow a plugin even with an empty `CLAUDE_CONFIG_DIR`, so they get the namespaced form documented rather than a mirror), and `Unknown command` hits exactly those `commands/*.md` that have no same-named `skills/<n>/SKILL.md` — a blind prediction confirmed 3/3. Pinned by `tests/commands/headless-bare-command-availability.test.mjs`.
|
|
17
|
+
- The send and receive halves of the FILE-SCOPE chain now JOIN on the digest (#1092). `hooks/pre-task-scope-disjoint.mjs` adds `scope_digest`, `marker_found`, `echo_instruction_present`, `instructed_digest` and `digest_consistent` to `scope_checked`; `scripts/lib/scope-echo.mjs` gains `--verify` (6 kebab-case verdicts plus the degraded `echo-only` and a `malformed_lines` floor-marker); `scripts/materialize-wave-scope.mjs` emits `orchestrator.wave_dispatch.scope_materialized` with `transport_observable`, and `--verify --emit` writes `orchestrator.wave_dispatch.scope_verified`. Before this the halves were unpairable even in principle: 609 send-side against 51 receive-side records whose agent-id sets overlap in ZERO elements. Measured on this session's wave 4: 5/5 `matched`. New E2E suite `tests/hooks/pre-task-scope-injection-e2e.test.mjs` plus `tests/skills/wave-loop-scope-marker.test.mjs`.
|
|
18
|
+
- `resolveSessionStartedAt()` / `resolveSessionIds()` in `scripts/lib/state-md.mjs` and an optional STATE.md `session-id:` key (raw UUID) in the wave-executor state-init template (#1368). `started_at` now comes from `session.lock` instead of being prose-written, and `commands/close.md` falls back to `readLock().session_id`.
|
|
19
|
+
- `STARTED_AT_DRIFT_TOLERANCE_MS` (6 h) in `scripts/lib/session-close-backfill.mjs` (#1368), with a negative test proving a 9 h drift is still rejected.
|
|
20
|
+
- `ownSessionIsEnding` on `backfillAbandonedSession()` plus self-exclusion in `planSessions()` (`scripts/lib/session-close-backfill.mjs`, `scripts/backfill-abandoned-sessions.mjs`, #1376) — the parameter is passed only from `hooks/on-session-end.mjs` under the #863 attestation guard.
|
|
21
|
+
- `sidecar_missing` on `orchestrator.agent.stopped` in `hooks/on-stop.mjs` (#1289). It is the DENOMINATOR for every meta-derived field on that record, so a census of `agent_type_meta` gaps can name how many of them are "sidecar not found" rather than "producer broken".
|
|
22
|
+
- Maintenance-due signal 7, `generated-rules-expiring`, in `scripts/lib/maintenance-due-banner.mjs` (`MAINTENANCE_TOTAL_SIGNALS` 6 → 7, `GENERATED_RULE_EXPIRY_HORIZON_DAYS` = 7), backed by the new exports `isMachineGeneratedRule` / `listMachineGeneratedRules` / `isExpiredGeneratedRule` in `scripts/lib/instruction-budget-guard.mjs` (#1367, instrument half). Measured in W1: `rule-loader.mjs` filters `expires-at` only on READ and no code path ever deletes an expired file (3 historical files sat 16–19 days expired on disk and were removed by hand); the entire generated corpus expires within 57 days. The alarm is a session-start banner, not a vitest case, because a test comparing `expires-at` against TODAY is a calendar time-bomb in a blocking gate — the predicate itself is tested against an injected clock in `tests/rules/generated-corpus-expiry.test.mjs`.
|
|
23
|
+
- `findLoopedIssueCreate()` in `hooks/_lib/vcs-create-matcher.mjs` plus the `xargs` bulk deny in `hooks/pre-bash-issue-budget.mjs`, bound to the causing statement (#1289 B1 and the #1106-class loop lane). Measured at the real hook: `xargs` forms yielded 0 statements, so the fix is local to the matcher, not an intervention in `WRAPPER_UNWRAP`.
|
|
24
|
+
- `scripts/lib/reconcile/rule-expiry-sweep.mjs` (`planRuleExpirySweep`/`applyRuleExpirySweep`) plus CLI `scripts/sweep-expired-rules.mjs` (#1377) — the missing REMOVAL half of the generated-rule TTL: `scripts/lib/rule-loader.mjs` already stops injecting an expired generated rule at read time, but nothing ever removed one from disk. `--dry-run` is the default, `--apply` is the only write path, `--json` emits the full plan. An expired entry's prose block is deleted while its `## Provenance` pair is kept as `markers only` (a same-line HTML comment), because `/reconcile` dedupes on that pair and dropping it would re-propose the learning; a file is deleted only when every pair on it is expired, and every pair is stamped terminal via `markCandidateProcessed` before the `unlink`. Two fail-open branches, both reported rather than guessed: an entry whose `learning-id` does not resolve against `learnings.jsonl` (`unresolvedPairIds`) keeps its file, and a file whose `###` headings do not map 1:1 onto its non-`markers only` pairs is reported `no-1to1-mapping` and left untouched (measured 2026-09-17: the mapping holds in 3 of 7 live files). Writes are refused through a symlink or outside `.claude/rules/` (path confinement) and are atomic. Emits `orchestrator.rules.expiry_sweep_applied` (`docs/events-schema.md`) on the `--apply` path only, with `rewritten`/`deleted`/`stamped`/`write_errors`/`expired_entries`/`files_scanned` always present including as `0`. Wired into maintenance-loop signal 7's banner (row 3, `skills/wave-executor/SKILL.md` + `skills/session-start/SKILL.md`) and documented in `docs/rule-authoring.md` § "The expiry sweep". Live dry run 2026-09-17: 7 files scanned, 0 rewrites (nothing expired yet), 4 `no-1to1-mapping`, 5 of 92 provenance-pair ids unresolvable.
|
|
25
|
+
- `scripts/lib/locks/index.mjs` restored as a one-cycle `export *` deprecation shim (0 named exports, one-time `console.warn`) after having been deleted for 0 importers (see Removed, 5.1.0-cycle) — `package.json` carries no `exports` map, so every packed `scripts/lib/` path is public and a pre-5.1.0 deep-importer of this path would hit a bare runtime "module not found" with no compile-time warning. Covered by `tests/lib/locks/index-shim.test.mjs`; removal deferred to 6.0.0 (`.claude/rules/development.md` § Package Lifecycle & Versioning).
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Every slash command now has exactly ONE definition. 24 `commands/*.md` files were folded into their same-named `skills/<name>/SKILL.md` (frontmatter `user-invocable: true` + `argument-hint` + `disable-model-invocation`, body under `## Invocation`), leaving `commands/session.md` and `commands/templates-ack.md` as the only command files. Reason, measured 2026-09-16 on `claude 2.1.273` with a throwaway plugin: Claude Code registers a `commands/<name>.md` AND a user-invocable `skills/<name>/SKILL.md` both as `/session-orchestrator:<name>`, so every twin was listed twice in the interactive `/` picker; under `claude -p` the twin ran the SKILL body (the command file was dead), and a `user-invocable: false` skill beside a command was recognised but ran 0 turns — so the mirrors from #1370 had made `/close`, `/go`, `/harness-audit`, `/portfolio`, `/release` and `/test` duplicates, and `discovery`, `evolve`, `plan` had been silently dead headless all along. The Cursor and Pi generators now emit a wrapper for `commands/*.md` ∪ skills with explicit `user-invocable: true` (28 slash commands: 2 + 26), the Codex generator emits the `$ARGUMENTS` contract for those skills, and `tests/commands/headless-bare-command-availability.test.mjs` forbids the command/skill twin outright.
|
|
30
|
+
- Rule-corpus consolidation (#1367, #1372): `pathScoped` 122,763 → 109,932 B and `generated` 75,130 → 69,941 B across 7 consolidated files, with **92/92 provenance pairs kept** — the provenance pair is what stops `/reconcile` from re-proposing an absorbed learning, so only the prose was deleted. 9 blocked reconcile proposals were absorbed and 1 rejected as already materialized. `.claude/rules/testing.md` −7,717 B of web-framework prose (Server Action, E2E, Accessibility, half of CI Integration — a Node CLI repo has no call site for any of it) and `.claude/rules/receiving-review.md` −562 B with its pin re-derived to 8,009 (#1038) rather than raised.
|
|
31
|
+
- `DEFAULT_GENERATED_BYTE_CEILING` in `scripts/lib/instruction-budget-guard.mjs` 124,000 → 95,000 (#1308), chosen by replaying all 91 historical states of `.claude/rules/`: the real peak is 99,774 B at `2ae08fe0` (the old docblock claimed 89,763), 124,000 fires 0/91 and 95,000 fires **1/91**. The replay is in the docblock, so the next editor can falsify it (HR-105).
|
|
32
|
+
- `docs/rule-authoring.md` point 3: `paths:` is the CANONICAL scope key for `.claude/rules/` and `globs:` an accepted alias, instead of demanding both as byte-identical mirrors. `scripts/lib/validate-vendored-rules.mjs`'s `paths-frontmatter` probe is re-scoped to `rules/` library sources, where it is a vendoring convention (#742) rather than the loader-compatibility gate it was documented as — `rule-loader.mjs` has accepted `paths:` since #795.
|
|
33
|
+
- `scripts/lib/command-blocker.mjs` traverses into `eval` literals, `dd of=` (with `conv=notrunc` / `oflag=append` classified as append) and `env -S <op> …` (#1366). Measured at the real hook beforehand: six previously-open forms were ALLOW on BOTH redirect rules; they now deny, and benign forms stay ALLOW. `eval "$CMD"` remains a named ceiling (BV-004) — a variable payload is not lexically solvable.
|
|
34
|
+
- `SCOPE_MARKER` in `scripts/lib/scope-echo.mjs` is case-SENSITIVE (#1092). The lowercase match was the cause of this session's 5 `unparseable` W1 dispatches: the Learnings-Index header contains the words "file scope" and was classified as a FILE-SCOPE block.
|
|
35
|
+
- `isCliEntrypoint()` in `scripts/lib/validate/check-unwired-features.mjs` recognises `isMainModule(`, `export *` barrels enter the population, and `reportableRoots` replaces the basename-collision filter (#1293 remainder) — census of unreachable modules 2 → 0.
|
|
36
|
+
- `commands/{close,go,harness-audit,portfolio,release,test}.md` reduced to the entry-contract shape, with the body owned by the new mirrored skill (#1370).
|
|
37
|
+
- STATE.md `started_at` is sourced from the session lock in `skills/wave-executor/references/wave-executor-state-init.md` and `skills/_shared/state-ownership.md` (#1368) — it was 100 % prose-written before, which is what produced the 48-minute drift that made `/close` re-run session-end.
|
|
38
|
+
- Surface counts in `docs/components.md` (skills 44 → 50) and the session-start / audit docs re-measured against the tree: 50 skills, 39 validators, 25 rule files, 685 test files.
|
|
39
|
+
- MR !39 merged as `1c02346a` (research-evidence contract + hook-development corrections). The panel verdict was MERGE WITH EDITS, and both edits land here: `skills/hook-development/SKILL.md` now states where and when the `UserPromptSubmit` field name was checked and that no handler in this plugin exercises either spelling, and `skills/_shared/research-evidence.md` cross-references PSA-006's executed-command transcript for counts, percentages and distributions.
|
|
40
|
+
- `scripts/lib/validate/check-entry-guard.mjs` gains a second oracle for the bare `process.argv[1].endsWith('<x>.mjs')` basename form (plus its `?.`, `String(...)` and `(argv[1] || '')` receiver variants) alongside the existing `===`/`!==` comparison oracle — the two hand-written guards this check was originally built to catch (`scripts/lib/ecosystem-wizard.mjs`, `scripts/lib/fetch-baseline.mjs`, see Fixed) used the bare form, which the comparison oracle could never see, so reverting either file's fix would have been caught by nothing. `ALLOWLIST` is now empty (its one entry, for `fetch-baseline.mjs`'s hybrid guard, no longer applies) but the mechanism is kept rather than deleted.
|
|
41
|
+
- `scripts/lib/validate/check-skill-links.mjs` scans `.cursor/rules` (added to `SCAN_DIRS`) including its `.mdc` extension (new `MD_EXTENSIONS` export) — that surface ships in the npm tarball and, after #1370 folded `commands/go.md`/`commands/close.md` into skills, carried two now-dangling citations of them. Measured 2026-09-17: `.cursor/rules/*.mdc` contains zero `[text](target)` links today, so the widening adds 9 scanned files and 0 checked links — it is a forward guard, not a catch of the backticked-code-span citation class that actually caused the dangling reference (see Fixed for that repair).
|
|
42
|
+
- `skills/claude-md-drift-check/checker.mjs` extracts `countSlashCommands()` (the `commands/*.md` ∪ user-invocable-skills union, deduplicated) as the ONE implementation shared by the `command-count` surface (Check 5) and the `docs-parity` sub-check (Check 10) — the two counters had drifted independently since #1370 folded 24 command files into skills, leaving `docs-parity` on a raw `commands/` `readdirSync()` that undercounted; the check now reports `ok` / exit 0 where it was red on HEAD.
|
|
43
|
+
- `scripts/generate-cursor-adapter.mjs` reads `disable-model-invocation` from the SOURCE skill's own frontmatter (new `disablesModelInvocation()`: emit when the source declares it, OR when the skill is not user-invocable at all) instead of deriving it from `user-invocable` — 6 skills that are both `user-invocable: true` AND operator-only (`bootstrap`, `brainstorm`, `close`, `go`, `plan`, `release`) had silently lost the flag on both their `.cursor/commands/*.md` and `.cursor/skills/*/SKILL.md` wrappers, which would let a Cursor model auto-invoke `/close`, `/go` or `/release`. The generator now delegates to `scripts/lib/user-invocable-skills.mjs`'s `isUserInvocableValue()` (see below) and tolerates a UTF-8 BOM / CRLF frontmatter block, which previously made it parse as "no frontmatter" at all.
|
|
44
|
+
- `scripts/lib/user-invocable-skills.mjs`'s `isUserInvocableValue()` is now the one `user-invocable` normaliser for the Cursor, Pi and Codex generators and every counter — it strips a trailing `# comment` and one layer of matching quotes before comparing, accepts case-insensitive `true`, and WARNs (without accepting) on the YAML-1.1-but-not-1.2 lookalikes `yes`/`y`/`on`/`t`/`1`, which `generate-codex-skills`'s js-yaml `CORE_SCHEMA` reads as plain strings rather than booleans.
|
|
45
|
+
- `scripts/lib/agent-frontmatter.mjs`'s `parseAgentFrontmatter()` no longer hoists a key nested under a top-level mapping (e.g. `metadata:\n user-invocable: true`) up to top level, and strips a leading UTF-8 BOM before matching the frontmatter fence — both previously made a counter see a slash command no generator recognised.
|
|
46
|
+
- `scripts/release.mjs`'s `--check`/`--publish` CI-preflight rows (`ci-green-on-head`, `ci-green-on-head-github`) now query both platforms for the commit actually being released (new exported `evaluateCiPreflightRows(repoRoot, head, opts)`, `sha: head`) instead of letting the GitHub branch fall back to the mirror's own `HEAD` — before `head-pushed-github` proves `github/main == local HEAD`, the GitHub row could read green for a commit GitHub had never seen (measured 2026-09-16 for `3ebf0e9d`).
|
|
47
|
+
- `skills/autopilot/SKILL.md` documents the Headless Driver Wiring (Option A, `scripts/autopilot.mjs`) as its own subsection rather than folded verbatim into the old command text, and corrects its DI table's `resourceEvaluator`/`peerCounter` rows to match the live code: `peerCounter` returns a SESSION count via `detectPeers()`, not a process count (`.claude/rules/host-resources.md` § HR-103), and refreshes the cached probe snapshot `resourceEvaluator` reads rather than each calling `probe()` independently. `skills/dispatcher/SKILL.md` Phase 4 documents `/session` and `/plan` as reserved-terminal-built-in / `disable-model-invocation`-blocked names the coordinator hands to the operator to type verbatim, versus `/discovery`, which carries neither restriction and the coordinator invokes directly.
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- Destructive-command policy census in `CLAUDE.md` / `AGENTS.md`, `.orchestrator/steering/structure.md` and `docs/components.md` still said 14 rules / 10 blocking; the 15th rule (`redirect-harness-memory`, landed 2026-09-13) makes it **15 rules, 11 blocking, 4 warning** (measured 2026-09-16 at `68fbebf9`). `README.md` said 44 skills against 50 on disk. Both found by the `/close` discovery scan (`ssot-code-diff`).
|
|
52
|
+
- `skills/session-end/plan-verification.md` § SESSION_START_REF accessor imported a `parseFrontmatter` that `scripts/lib/state-md.mjs` never exported (measured 2026-09-16 at `3fe9d50e`: `typeof m.parseFrontmatter` → `undefined`), so the documented snippet threw and every close silently fell back to `origin/main`. It now uses `parseStateMd(...).frontmatter`, the export that exists.
|
|
53
|
+
- The issue-budget exemption bypass in `hooks/pre-bash-issue-budget.mjs` (security panel, MED): an exempt FIRST statement lifted the `xargs` and loop bulk deny for the whole command.
|
|
54
|
+
- `findRecordedSession()` in `scripts/lib/session-close-backfill.mjs` compared `started_at` to the MILLISECOND (#1368), so `/close` re-ran session-end for a session already in the ledger. With no template writing `session-id:` (0 matches measured), the native-UUID path of the precheck could never fire — the millisecond compare was not an edge case, it was the only path.
|
|
55
|
+
- `hooks/on-session-end.mjs` skipped the backfill whenever a live lock was present, including the session's own (#1376) — exactly one wrong caller, measured; unclosed sessions were left without a ledger record.
|
|
56
|
+
- The docblock of `hooks/pre-task-scope-disjoint.mjs` described a CLASSIFICATION as a decision.
|
|
57
|
+
- The docblock of `scripts/lib/instruction-budget-guard.mjs`: 3 refuted sentences and stale headroom numbers removed.
|
|
58
|
+
- The verdict `injection_missing` is spelled `injection-missing` (`scripts/lib/scope-echo.mjs`, `docs/events-schema.md`, `docs/scope-collision-guard.md`, `scripts/materialize-wave-scope.mjs`) — it was the one snake_case member of an otherwise kebab-case enum. There is no dual-emit: records written before 2026-09-16 carry the old key in `by_verdict`, and `docs/events-schema.md` says so.
|
|
59
|
+
- `README.md`, `site/llms.txt` and `site/llms-full.txt` still said "10 blocking" destructive-command rules after the two prior census passes each corrected a different subset of surfaces (`06836586`: `CLAUDE.md`/`AGENTS.md`/`structure.md`/`docs/components.md`; `1ef26415`: `site/index.html`/`site/de/index.html`/`site/guide/index.html` plus one line each in the two `llms*.txt` files) — the remaining occurrences are now 15 rules / 11 blocking / 4 warning (measured via `jq` over `.orchestrator/policy/blocked-commands.json`, `9e8146b4`). `skills/discovery/probes-session.md`'s remediation recommendation changed from `/bootstrap --retroactive` (which only writes a missing lock and validates nothing, #832 item 8) to `node scripts/validate-plugin.mjs`.
|
|
60
|
+
- The issue-budget loop guard (`hooks/pre-bash-issue-budget.mjs`, `hooks/_lib/vcs-create-matcher.mjs`, #1379): `findLoopedIssueCreates()` (plural — replacing the single-result `findLoopedIssueCreate`, kept as a `@deprecated` wrapper returning its first element) now reports EVERY looped issue-create statement in a command. Previously an exempt FIRST loop lifted the bulk deny for every LATER, non-exempt loop in the same command — `for i in 1 2 3; do glab issue create --label carryover --title x$i; done; for j in 1 2 3; do glab issue create --title junk$j; done` ALLOWed with a ledger count of 1. The `warn`-mode undercount notice is now gated on whether ANY bulk statement in the command was uncountable rather than on the LAST statement's verdict, so a trailing exempt statement no longer silences it. Both the deny and the warn text now name the lane the violation was found on (`loop`/`xargs`/`mixed`) instead of always saying "shell loop body" (which previously misdirected an `xargs`-only violation).
|
|
61
|
+
- `scripts/lib/ecosystem-wizard.mjs` and `scripts/lib/fetch-baseline.mjs` (#1378) now use `isMainModule(import.meta.url)` for their CLI entry guard instead of, respectively, a bare `process.argv[1].endsWith('ecosystem-wizard.mjs')` and a hybrid `===`-plus-`endsWith` comparison — both are symlink-fragile (a same-named file elsewhere satisfies `endsWith`; `import.meta.url` is a realpath, `process.argv[1]` is the path as typed) and were the two hand-written guards `check-entry-guard.mjs` was built to catch (see Changed for the new oracle that closes the remaining gap).
|
|
62
|
+
- `.cursor/rules/010-session-workflow.mdc` cited the deleted `commands/go.md` and `commands/close.md` (folded into skills by #1370, 3ebf0e9d) — now cites `skills/go/SKILL.md` and `skills/close/SKILL.md`.
|
|
63
|
+
|
|
64
|
+
### Removed
|
|
65
|
+
|
|
66
|
+
- `commands/{autopilot,bootstrap,brainstorm,close,debug,discovery,dispatcher,eli5,eval,evolve,go,grill,harness-audit,memory-cleanup,persona-panel,plan,portfolio,reconcile,release,repo-audit,spinout,sunset-review,test,ux-grill}.md` — folded into the same-named skills (see Changed). The `.cursor/commands/`, `pi/prompts/` and `.codex-plugin/skills/` wrappers are regenerated from the skills.
|
|
67
|
+
- `.claude/rules/git-and-worktrees.md` — absorbed into `.claude/rules/toolchain-and-build.md` (4 globs carried over, 21/21 verified against `git ls-files`), and the 17 citation sites swept.
|
|
68
|
+
- The 9 standalone reconcile rule files — absorbed into the thematic consolidated files, provenance pairs intact.
|
|
69
|
+
- The live-repo vacuum guards in `tests/lib/validate/check-unwired-features.test.mjs` and `tests/rules/generated-corpus-expiry.test.mjs`, and the calendar assertion in the expiry test — a test that passes because it found nothing to measure is indistinguishable from a broken one.
|
|
70
|
+
|
|
71
|
+
## [5.1.0] - 2026-09-13
|
|
72
|
+
|
|
73
|
+
### Added
|
|
74
|
+
|
|
75
|
+
- `docs/install.md` — the requirements matrix, per-harness install commands, upgrade path (incl. how the session-start banner detects a behind-copy) and the full uninstall/what-stays-behind list, moved out of the README so the landing page can be read in one screen.
|
|
76
|
+
- Playwright local-install preflight in `scripts/lib/playwright-driver/runner.mjs` (#1359). The host-global `playwright` package is gone (browser-kit pins the toolchain per repo), so `npx playwright test` in a target repo without a local install no longer resolves — it starts an unpinned registry download in the middle of what is supposed to be a test run. The runner now resolves `@playwright/test` or `playwright` from the target's own `node_modules` (walking up, so a monorepo hoist counts) and exits 2 with an actionable message instead. It runs AFTER the `--dry-run` exit, and that ordering is pinned by a test.
|
|
77
|
+
- Policy rule `redirect-harness-memory` + home-anchored denylist matching in `scripts/lib/command-blocker.mjs` (#1352, #1362). The harness auto-memory directory is injected as TRUSTED project context into every later session yet lives outside `git diff`, CI review, `check-owner-leakage` (tracked files only) and gitleaks. #1352 closed the Edit/Write lane for dispatched agents; this closes the shell-redirect lane, append included. Denylist entries starting with `~/` are matched against the expanded ABSOLUTE target, because `relativizeAgainstRoot` discards every out-of-repo target by design — measured: no glob spelling could reach the directory before. Relative ENTRIES keep byte-identical behaviour (pinned), while a relative TARGET is resolved against the repo root first — without that, `> ../../.claude/projects/<enc>/memory/MEMORY.md` reached the very file the tilde spelling blocks. NAMED CEILING (BV-004), all four measured as allow: `tee -a` and in-process writes; redirects inside `eval`/`dd of=` payloads; `cd ~ && … > .claude/…` (cwd-relative, not lexically solvable); and `$HOME`/`${HOME}`/`$(…)` targets, which stay in the pre-existing `unresolved` warn-and-allow class (#641).
|
|
78
|
+
- Signal S5 `hand-keyed-learning-subject` in `scripts/lib/validate/check-unwired-features.mjs` (#1363). `sizingSubject()` (#1247) had ZERO mechanical consumers — prose told an LLM to derive the `effective-sizing` subject through it, and nothing enforced that, so a hand-concatenated subject silently re-merged a 7-wave `ultradeep` session onto the 5-wave `deep` row. The check imports the helper (which is what gives it a consumer at all) and re-derives the subject of every written `effective-sizing` learning. Only canonically-shaped subjects are judged: measured on this repo's live ledger, 1 of 6 is canonically keyed, so judging free-form prose would put the class at 83% on day one — the broken instrument `.claude/rules/host-resources.md` § HR-101 forbids.
|
|
79
|
+
- `orchestrator.scope.coordinator_carveout_allowed` (#1361). The coordinator carve-out returned `emitAllow()`, which is `process.exit(0)` with no log path — whether the branch ever fired was structurally unanswerable (HR-105). The event carries the `classifyCaller` `discriminator`, so the fail-open case is countable.
|
|
80
|
+
|
|
81
|
+
### Changed
|
|
82
|
+
|
|
83
|
+
- `isPinnedActionComment()` in `scripts/release.mjs` — the version drift sweep no longer reads a SHA-pinned third-party action's trailing version comment as our own stale surface. `.github/workflows/test.yml` pins `actions/setup-node@a0853c2… # v5.0.0`, and the sweep for the previous tag 5.0.0 matched it, blocking `--publish` on a file no release ever writes. The collision is coincidence and recurs for any action whose pin equals our next version, so the carve-out is a PREDICATE, not an allowlist row (the unenumerable-table failure `.claude/rules/measurement-discipline.md` records). Two conditions, both required: the line pins with `uses:` before the comment marker, and every occurrence of the literal sits after it — a version in the pin itself is still swept. Both directions proven by mutation: removing the predicate turns 1 test red, loosening it to "any YAML comment" turns 2 red.
|
|
84
|
+
- README reduced from 314 to 151 lines, 3684 to 1694 words and 22 to 10 sections, measured against ten comparable repositories whose medians are 80 lines / 330 words / 5 sections. The animated illustration, the four film links and the AI-illustration disclaimer paragraph left the landing page (the assets stay in `site/video/` and on session-orchestrator.com); a Mermaid flow diagram of `/session` → `/go` → quality gate → `/close` with the fails-loop took that slot. The diagram is deliberately short-labelled: GitHub renders Mermaid in a sandboxed iframe and anchors its pan/zoom buttons to that iframe's right edge, so the 997 B and 905 B natural widths filled the 838 px container and ran under the controls — only the 690 px variant clears them. Prose rewritten in the `skills/eli5` register (no analogies, every greppable token kept). Nothing was deleted: the relocated sections live in `docs/install.md`, `docs/components.md` (destructive-command guard + import probe), `docs/telemetry.md` ("Your data stays in your repo"), `docs/USER-GUIDE.md` § 21 (hook PATH, `bootstrap.lock`) and `CONTRIBUTING.md` (`npx husky`, `rules/` vs `.claude/rules/`).
|
|
85
|
+
- The plugin description is one sentence across `package.json`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json` (both slots), `.codex-plugin/plugin.json` and `.cursor-plugin/plugin.json`, adopting the plain wording already used in the GitHub About field instead of the previous jargon line. npm shows it from the published tarball, so it only becomes visible with this release.
|
|
86
|
+
- `CODE_OF_CONDUCT.md` moved to `.github/CODE_OF_CONDUCT.md` — a location GitHub supports natively, so the repository's "Code of conduct" tab is unchanged. It had zero inbound references. The other three community-health files stay at the repo root deliberately: `SECURITY.md` is named by path in `.orchestrator/policy/blocked-commands.json` (moving it would silently void that protection), in `package.json` `files[]` and in `CODEOWNERS`; `CONTRIBUTING.md` is in the `HISTORY_ALLOWLIST` of `scripts/release.mjs`; and `CODEOWNERS` is scaffolded to consumer repos at root by four `skills/bootstrap/` files.
|
|
87
|
+
- `hooks/enforce-scope.mjs` grants the #245 coordinator carve-out to the COORDINATOR only (#1361). The carve-out returned `emitAllow()` before Gate 7 without consulting `classifyCaller`, so any dispatched wave agent could write `.claude/STATE.md` — PSA-005/PSA-007 territory — and, worse, overwrite the LIVE `wave-scope.json`, rewriting its own scope manifest and disarming every later gate of the same wave. The RCR-007 allow-census ran first: across 1069 subagent transcripts carrying 4385 real `Write`/`Edit`/`MultiEdit` calls, **0** targeted a carve-out path, so the fix takes nothing away from a legitimate writer. Ambiguity stays fail-OPEN, same posture and same discriminator as Gate 5c.
|
|
88
|
+
- `docs/session-config-template.md` catalogues four further runtime-read keys in the opt-in block (#1364): `heavy-repo`, `worktree-cleanup`, `persona-gate-wave` and the nested `test` block. Three more (`cross-repo`, `gitlab-portfolio`, `worktree-exclude`) are deliberately NOT catalogued yet — `claude-md-drift-check` Check 10b turns any opt-in template key missing from `docs/session-config-reference.md` into an `errors[]` entry, measured at 3 errors, so the reference has to be written first. `skill-evolution` and `dispatcher-autonomy` stay parity-exempt by design (#646 / #679).
|
|
89
|
+
|
|
10
90
|
## [5.0.0] - 2026-09-13
|
|
11
91
|
|
|
12
92
|
Migration from 4.x: [v5 migration guide](docs/migration-v5.md). The major version reflects the changed `readCurrentStatus()` return contract and the now-enabled default close-time discovery scan.
|