session-orchestrator 5.1.0 → 5.3.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/architecture/SKILL.md +3 -1
- package/.agents/skills/autopilot/SKILL.md +6 -1
- package/.agents/skills/autopilot/agents/openai.yaml +5 -0
- package/.agents/skills/bootstrap/SKILL.md +7 -1
- package/.agents/skills/bootstrap/agents/openai.yaml +5 -0
- package/.agents/skills/brainstorm/SKILL.md +8 -1
- package/.agents/skills/brainstorm/agents/openai.yaml +5 -0
- package/.agents/skills/claude-md-drift-check/SKILL.md +3 -1
- package/.agents/skills/close/SKILL.md +21 -0
- package/.agents/skills/close/agents/openai.yaml +5 -0
- package/.agents/skills/convergence-monitoring/SKILL.md +4 -2
- package/.agents/skills/debug/SKILL.md +7 -1
- package/.agents/skills/debug/agents/openai.yaml +5 -0
- package/.agents/skills/discovery/SKILL.md +7 -2
- package/.agents/skills/discovery/agents/openai.yaml +5 -0
- package/.agents/skills/dispatcher/SKILL.md +7 -1
- package/.agents/skills/dispatcher/agents/openai.yaml +5 -0
- package/.agents/skills/docs-orchestrator/SKILL.md +3 -1
- package/.agents/skills/ecosystem-health/SKILL.md +3 -1
- package/.agents/skills/eli5/SKILL.md +7 -1
- package/.agents/skills/eli5/agents/openai.yaml +5 -0
- package/.agents/skills/eval/SKILL.md +7 -2
- package/.agents/skills/eval/agents/openai.yaml +5 -0
- package/.agents/skills/evolve/SKILL.md +8 -3
- package/.agents/skills/evolve/agents/openai.yaml +5 -0
- package/.agents/skills/frontmatter-guard/SKILL.md +3 -1
- package/.agents/skills/gitlab-ops/SKILL.md +3 -1
- package/.agents/skills/gitlab-portfolio/SKILL.md +3 -1
- package/.agents/skills/go/SKILL.md +22 -0
- package/.agents/skills/go/agents/openai.yaml +5 -0
- package/.agents/skills/grill/SKILL.md +7 -1
- package/.agents/skills/grill/agents/openai.yaml +5 -0
- package/.agents/skills/harness-audit/SKILL.md +20 -0
- package/.agents/skills/harness-audit/agents/openai.yaml +5 -0
- package/.agents/skills/hook-development/SKILL.md +3 -1
- package/.agents/skills/mcp-builder/SKILL.md +3 -1
- package/.agents/skills/memory-cleanup/SKILL.md +6 -1
- package/.agents/skills/memory-cleanup/agents/openai.yaml +5 -0
- package/.agents/skills/mode-selector/SKILL.md +3 -1
- package/.agents/skills/npm-publish/SKILL.md +4 -2
- package/.agents/skills/peekaboo-driver/SKILL.md +3 -1
- package/.agents/skills/persona-panel/SKILL.md +6 -1
- package/.agents/skills/persona-panel/agents/openai.yaml +5 -0
- package/.agents/skills/plan/SKILL.md +8 -2
- package/.agents/skills/plan/agents/openai.yaml +5 -0
- package/.agents/skills/playwright-driver/SKILL.md +3 -1
- package/.agents/skills/portfolio/SKILL.md +21 -0
- package/.agents/skills/portfolio/agents/openai.yaml +5 -0
- package/.agents/skills/quality-gates/SKILL.md +3 -1
- package/.agents/skills/reconcile/SKILL.md +6 -1
- package/.agents/skills/reconcile/agents/openai.yaml +5 -0
- package/.agents/skills/release/SKILL.md +22 -0
- package/.agents/skills/release/agents/openai.yaml +5 -0
- package/.agents/skills/remote-offload/SKILL.md +3 -1
- package/.agents/skills/repo-audit/SKILL.md +6 -1
- package/.agents/skills/repo-audit/agents/openai.yaml +5 -0
- package/.agents/skills/session/SKILL.md +21 -0
- package/.agents/skills/session/agents/openai.yaml +5 -0
- package/.agents/skills/session-end/SKILL.md +3 -1
- package/.agents/skills/session-plan/SKILL.md +3 -1
- package/.agents/skills/session-start/SKILL.md +3 -1
- package/.agents/skills/spinout/SKILL.md +6 -1
- package/.agents/skills/spinout/agents/openai.yaml +5 -0
- package/.agents/skills/sunset-review/SKILL.md +7 -1
- package/.agents/skills/sunset-review/agents/openai.yaml +5 -0
- package/.agents/skills/templates-ack/SKILL.md +21 -0
- package/.agents/skills/templates-ack/agents/openai.yaml +5 -0
- package/.agents/skills/test/SKILL.md +21 -0
- package/.agents/skills/test/agents/openai.yaml +5 -0
- package/.agents/skills/test-runner/SKILL.md +3 -1
- package/.agents/skills/tmux-layout/SKILL.md +3 -1
- package/.agents/skills/using-orchestrator/SKILL.md +3 -1
- package/.agents/skills/ux-grill/SKILL.md +7 -1
- package/.agents/skills/ux-grill/agents/openai.yaml +5 -0
- package/.agents/skills/vault-mirror/SKILL.md +3 -1
- package/.agents/skills/vault-sync/SKILL.md +3 -1
- package/.agents/skills/wave-executor/SKILL.md +3 -1
- package/.agents/skills/write-executable-plan/SKILL.md +3 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +4 -4
- 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 +1 -1
- 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 +1 -1
- 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/session/SKILL.md +1 -1
- 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/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/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/session.md +1 -1
- 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/000-session-orchestrator.mdc +0 -2
- package/.cursor/rules/010-session-workflow.mdc +2 -2
- package/.cursor/rules/050-plan.mdc +1 -1
- package/.cursor/skills/bootstrap/SKILL.md +1 -0
- package/.cursor/skills/close/SKILL.md +13 -0
- package/.cursor/skills/convergence-monitoring/SKILL.md +1 -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/eval/SKILL.md +1 -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/npm-publish/SKILL.md +1 -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 +1 -1
- package/.orchestrator/policy/blocked-commands.json +13 -4
- package/AGENTS.md +3 -2
- package/CHANGELOG.md +197 -0
- package/README.md +11 -9
- package/SECURITY.md +12 -0
- package/agents/dialectic-deriver.md +13 -10
- package/agents/eval-judge.md +67 -45
- package/agents/skill-applied-judge.md +34 -19
- package/commands/session.md +17 -3
- package/docs/baseline.md +12 -6
- package/docs/ci-setup.md +53 -0
- package/docs/codex-setup.md +15 -3
- package/docs/components.md +13 -6
- package/docs/events-schema.md +59 -9
- package/docs/install.md +16 -0
- package/docs/persona-panel.md +1 -1
- package/docs/pi-setup.md +1 -1
- package/docs/rule-authoring.md +135 -14
- package/docs/scope-collision-guard.md +2 -0
- package/docs/session-config-reference.md +106 -11
- package/docs/session-config-template.md +31 -2
- package/docs/telemetry.md +2 -0
- package/hooks/_lib/hook-import-set.json +125 -8
- package/hooks/_lib/subagent-paths.mjs +15 -0
- package/hooks/_lib/subagent-transcript.mjs +582 -31
- package/hooks/_lib/vcs-create-matcher.mjs +217 -62
- package/hooks/config-protection.mjs +11 -3
- package/hooks/cwd-change-restore.mjs +11 -3
- package/hooks/enforce-commands.mjs +70 -23
- package/hooks/enforce-scope.mjs +143 -33
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks.json +1 -1
- package/hooks/loop-guard.mjs +11 -3
- package/hooks/on-session-end.mjs +72 -25
- package/hooks/on-session-start.mjs +48 -11
- package/hooks/on-stop.mjs +211 -23
- package/hooks/operator-steer.mjs +11 -3
- package/hooks/post-bash-issue-budget-refund.mjs +18 -8
- package/hooks/post-bash-write-verify.mjs +6 -2
- package/hooks/post-edit-import-probe.mjs +17 -9
- package/hooks/post-edit-validate.mjs +13 -5
- package/hooks/post-subagent-discovery-validator.mjs +98 -13
- package/hooks/post-tool-batch-wave-signal.mjs +200 -38
- package/hooks/post-tool-failure-corrective-context.mjs +11 -5
- package/hooks/post-tooluse-frontend-slop.mjs +10 -4
- package/hooks/pre-auq-clarity.mjs +18 -2
- package/hooks/pre-bash-destructive-guard.mjs +80 -9
- package/hooks/pre-bash-issue-budget.mjs +119 -28
- package/hooks/pre-bash-memory-propose-audit.mjs +86 -54
- package/hooks/pre-bash-sessions-ledger-guard.mjs +391 -20
- package/hooks/pre-bash-staging-fence.mjs +335 -31
- package/hooks/pre-bash-templates-first.mjs +19 -14
- package/hooks/pre-task-scope-disjoint.mjs +385 -5
- package/hooks/skill-invocation-telemetry.mjs +2 -1
- package/hooks/subagent-telemetry.mjs +15 -19
- package/hooks/wave-scope-commit-guard.mjs +197 -100
- package/monitors/monitors.json +1 -1
- package/output-styles/wave-summary.md +1 -1
- package/package.json +2 -1
- 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/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/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 +2 -2
- 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/rules/README.md +1 -1
- package/rules/opt-in-domain/prompt-caching.md +1 -1
- package/rules/opt-in-stack/backend-data.md +1 -1
- package/rules/opt-in-stack/backend.md +3 -3
- package/rules/opt-in-stack/frontend.md +1 -1
- package/rules/opt-in-stack/security-web.md +3 -3
- package/rules/opt-in-stack/swift.md +1 -1
- package/scripts/archive-closed-prds.mjs +2 -2
- package/scripts/auq-audit.mjs +2 -3
- package/scripts/autopilot.mjs +23 -2
- package/scripts/backfill-abandoned-sessions.mjs +171 -15
- 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/check-sessions-integrity.mjs +300 -0
- package/scripts/ci/assert-vitest-green.mjs +2 -1
- package/scripts/dialectic-deriver.mjs +50 -13
- package/scripts/emit-session.mjs +77 -32
- package/scripts/eval-session.mjs +65 -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-agents-skills.mjs +102 -29
- package/scripts/generate-codex-skills.mjs +48 -4
- package/scripts/generate-cursor-adapter.mjs +220 -11
- 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/agent-status.mjs +2 -31
- package/scripts/lib/auq/clarity.mjs +10 -2
- package/scripts/lib/auq/parse.mjs +12 -31
- package/scripts/lib/auq/schema.mjs +56 -41
- package/scripts/lib/auto-dialectic.mjs +304 -15
- package/scripts/lib/autopilot/flags.mjs +12 -1
- package/scripts/lib/autopilot/kill-switches.mjs +6 -3
- package/scripts/lib/autopilot/loop.mjs +14 -1
- package/scripts/lib/autopilot/stall-sampler.mjs +80 -23
- package/scripts/lib/ci-status-banner.mjs +376 -16
- package/scripts/lib/claude-md-budget-lint.mjs +2 -5
- package/scripts/lib/command-blocker.mjs +408 -33
- package/scripts/lib/config/dialectic.mjs +12 -3
- package/scripts/lib/config/drift-check.mjs +19 -0
- package/scripts/lib/config/gate.mjs +74 -0
- package/scripts/lib/config/reaper.mjs +162 -0
- package/scripts/lib/config.mjs +14 -0
- package/scripts/lib/convergence-monitor.mjs +76 -13
- 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-health.mjs +11 -0
- package/scripts/lib/ecosystem-wizard.mjs +2 -1
- package/scripts/lib/eval/engine.mjs +421 -53
- package/scripts/lib/eval/judge.mjs +463 -40
- package/scripts/lib/eval/schema.mjs +10 -1
- package/scripts/lib/events-rotation.mjs +221 -25
- package/scripts/lib/events-schema.mjs +114 -0
- package/scripts/lib/events.mjs +524 -5
- package/scripts/lib/fetch-baseline.mjs +3 -8
- package/scripts/lib/frontmatter-guard.mjs +21 -10
- package/scripts/lib/gates/gate-baseline.mjs +27 -2
- package/scripts/lib/gates/gate-full.mjs +28 -3
- package/scripts/lib/gates/gate-helpers.mjs +243 -21
- package/scripts/lib/gates/gate-incremental.mjs +28 -3
- package/scripts/lib/gates/gate-per-file.mjs +27 -2
- package/scripts/lib/gitlab-ops/stale-mr-sweep.mjs +2 -1
- package/scripts/lib/gitlab-portfolio/cli.mjs +2 -1
- package/scripts/lib/gitlab-portfolio/markdown-writer.mjs +6 -1
- package/scripts/lib/instruction-budget-guard.mjs +332 -50
- package/scripts/lib/io.mjs +42 -8
- package/scripts/lib/is-main-module.mjs +82 -0
- package/scripts/lib/issue-close-strip-labels.mjs +207 -49
- package/scripts/lib/js-mask.mjs +197 -0
- package/scripts/lib/learnings/evolve-telemetry.mjs +11 -7
- package/scripts/lib/locks/index.mjs +32 -25
- package/scripts/lib/maintenance-due-banner.mjs +122 -91
- package/scripts/lib/orphan-reaper.mjs +1588 -0
- package/scripts/lib/peer-cards/merger.mjs +48 -10
- package/scripts/lib/peer-cards/reader.mjs +78 -2
- package/scripts/lib/peer-discovery.mjs +2 -5
- package/scripts/lib/playwright-driver/runner.mjs +2 -1
- package/scripts/lib/process-group.mjs +899 -0
- package/scripts/lib/quality-gate.mjs +107 -28
- package/scripts/lib/reconcile/backlog.mjs +368 -0
- package/scripts/lib/reconcile/engine.mjs +55 -188
- package/scripts/lib/reconcile/rule-expiry-sweep.mjs +884 -0
- package/scripts/lib/reconcile/sanitize.mjs +69 -3
- package/scripts/lib/reconcile-nudge-banner.mjs +138 -45
- package/scripts/lib/resource-probe/parsers.mjs +31 -0
- package/scripts/lib/rule-loader.mjs +41 -12
- package/scripts/lib/rules-sync.mjs +2 -5
- package/scripts/lib/scope-echo.mjs +429 -7
- package/scripts/lib/scope-gate.mjs +605 -1
- package/scripts/lib/session-close-backfill.mjs +91 -12
- package/scripts/lib/session-id.mjs +9 -20
- package/scripts/lib/session-invocation.mjs +20 -0
- package/scripts/lib/session-schema/constants.mjs +30 -2
- package/scripts/lib/session-schema/normalizer.mjs +56 -4
- package/scripts/lib/session-schema.mjs +8 -3
- package/scripts/lib/session-start-probes.mjs +95 -10
- package/scripts/lib/sessions-canonical.mjs +23 -0
- package/scripts/lib/sessions-integrity-banner.mjs +7 -1
- package/scripts/lib/sessions-staleness-banner.mjs +193 -51
- package/scripts/lib/skill-evidence-window.mjs +891 -0
- package/scripts/lib/skill-evolution/candidate-intake.mjs +133 -12
- package/scripts/lib/skill-evolution/engine.mjs +18 -9
- package/scripts/lib/skill-judge.mjs +45 -3
- package/scripts/lib/state-md.mjs +84 -3
- package/scripts/lib/sunset/walker.mjs +31 -4
- package/scripts/lib/tail-window.mjs +56 -0
- package/scripts/lib/telemetry/schema.mjs +30 -0
- package/scripts/lib/telemetry/sync.mjs +61 -6
- package/scripts/lib/telemetry-flush-health-banner.mjs +4 -22
- package/scripts/lib/test-runner/issue-reconcile.mjs +48 -16
- package/scripts/lib/tests-src-ratio.mjs +2 -6
- package/scripts/lib/tmux-layout/telemetry-stats.mjs +74 -14
- package/scripts/lib/user-invocable-skills.mjs +205 -0
- package/scripts/lib/ux-grill/reconcile.mjs +48 -22
- package/scripts/lib/validate/check-agents-skills.mjs +26 -15
- package/scripts/lib/validate/check-banner-parity.mjs +2 -2
- package/scripts/lib/validate/check-cursor-adapter.mjs +3 -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 +329 -0
- package/scripts/lib/validate/check-guard-requires-parity.mjs +2 -2
- package/scripts/lib/validate/check-hook-entry-guards.mjs +636 -0
- 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-pi-prompts.mjs +1 -0
- package/scripts/lib/validate/check-rules.mjs +7 -5
- package/scripts/lib/validate/check-skill-links.mjs +35 -6
- package/scripts/lib/validate/check-skill-script-paths.mjs +241 -29
- package/scripts/lib/validate/check-test-git-config-target.mjs +26 -36
- package/scripts/lib/validate/check-unicode-safety.mjs +2 -2
- package/scripts/lib/validate/check-untracked-test-deps.mjs +9 -104
- package/scripts/lib/validate/check-unwired-features.mjs +220 -33
- package/scripts/lib/validate/check-validator-registration.mjs +36 -12
- package/scripts/lib/validate/check-vcs-repo-flag.mjs +2 -2
- package/scripts/lib/validate/confidential-names.mjs +10 -0
- package/scripts/lib/validate-vendored-rules.mjs +39 -12
- package/scripts/lib/vault-mirror/namespace.mjs +46 -8
- package/scripts/lib/vault-mirror/process.mjs +10 -3
- package/scripts/lib/vault-mirror/render-sessions.mjs +12 -2
- package/scripts/lib/vault-status/narrative-mirror.mjs +31 -7
- package/scripts/lib/vault-yaml.mjs +118 -0
- package/scripts/lib/wave-transcript-tail.mjs +2 -2
- package/scripts/lib/worktree/lifecycle.mjs +153 -1
- 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-session-lock.mjs +305 -0
- package/scripts/release.mjs +109 -39
- package/scripts/relocate-vault-corpus.mjs +2 -3
- package/scripts/repair-invalid-sessions.mjs +2 -2
- package/scripts/resolve-session-invocation.mjs +59 -0
- package/scripts/run-quality-gate.mjs +156 -17
- package/scripts/session-shape.mjs +2 -2
- package/scripts/site-numbers.mjs +35 -11
- package/scripts/sweep-expired-rules.mjs +227 -0
- package/scripts/validate-plugin.mjs +21 -0
- package/scripts/validate-wave-scope.mjs +32 -105
- package/scripts/vault-consolidate.mjs +2 -2
- package/scripts/vault-mirror.mjs +11 -4
- 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/platform-tools.md +23 -11
- package/skills/_shared/research-evidence.md +53 -0
- package/skills/_shared/state-ownership.md +3 -0
- package/skills/autopilot/SKILL.md +80 -11
- package/skills/bootstrap/SKILL.md +51 -1
- package/skills/brainstorm/SKILL.md +16 -0
- package/skills/claude-md-drift-check/SKILL.md +1 -1
- package/skills/claude-md-drift-check/checker.mjs +49 -11
- package/{commands/close.md → skills/close/SKILL.md} +9 -3
- package/skills/convergence-monitoring/README.md +8 -1
- package/skills/convergence-monitoring/SIGNALS.md +50 -6
- package/skills/convergence-monitoring/SKILL.md +15 -6
- 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 +52 -23
- package/skills/eval/rubric-v1.md +1 -0
- package/skills/eval/rubric-v2.md +457 -0
- package/skills/evolve/SKILL.md +9 -2
- package/skills/evolve/references/evolve-dialectic-mode.md +46 -25
- package/skills/gitlab-ops/SKILL.md +3 -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 +2 -2
- 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/{commands/portfolio.md → skills/portfolio/SKILL.md} +8 -2
- package/skills/reconcile/SKILL.md +21 -0
- package/{commands/release.md → skills/release/SKILL.md} +16 -2
- package/skills/repo-audit/SKILL.md +7 -0
- package/skills/session-end/SKILL.md +13 -16
- package/skills/session-end/discovery-scan.md +1 -1
- package/skills/session-end/phase-3-6-tail.md +55 -9
- package/skills/session-end/plan-verification.md +2 -2
- package/skills/session-end/references/phase-5-issue-cleanup.md +9 -14
- package/skills/session-end/session-metrics-write.md +10 -0
- package/skills/session-plan/SKILL.md +18 -6
- package/skills/session-plan/references/session-plan-task-classification.md +2 -2
- 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 +6 -4
- 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 +20 -2
- package/skills/wave-executor/SKILL.md +14 -7
- package/skills/wave-executor/circuit-breaker.md +2 -0
- package/skills/wave-executor/references/wave-executor-state-init.md +18 -4
- package/skills/wave-executor/references/wave-loop-dispatch.md +5 -2
- 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
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* sweep-expired-rules.mjs — CLI for the generated-rule expiry sweep (#1377).
|
|
4
|
+
*
|
|
5
|
+
* The sibling of `scripts/sweep-expired-learnings.mjs`, one corpus over:
|
|
6
|
+
* that one moves expired LEARNINGS out of `learnings.jsonl`, this one removes
|
|
7
|
+
* expired ENTRIES from the consolidated `.claude/rules/*.md` files that were
|
|
8
|
+
* generated from them. `scripts/lib/rule-loader.mjs` already refuses to inject
|
|
9
|
+
* an expired generated rule; nothing until now removed one from disk.
|
|
10
|
+
*
|
|
11
|
+
* All planning and writing logic lives in
|
|
12
|
+
* `scripts/lib/reconcile/rule-expiry-sweep.mjs`
|
|
13
|
+
* (`planRuleExpirySweep` / `applyRuleExpirySweep`). This file is argv parsing,
|
|
14
|
+
* output formatting, the event emit, and exit codes — nothing else.
|
|
15
|
+
*
|
|
16
|
+
* SAFETY: `--dry-run` is the DEFAULT and writes nothing. `--apply` is the only
|
|
17
|
+
* write path, and it rewrites or deletes TRACKED files under `.claude/rules/`.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* node scripts/sweep-expired-rules.mjs [--dry-run|--apply] [--json]
|
|
21
|
+
* [--grace-days N] [--now ISO] [--repo-root PATH] [--learnings PATH]
|
|
22
|
+
*
|
|
23
|
+
* Exit codes (the same contract as the learnings sweep CLI, deliberately —
|
|
24
|
+
* two sibling commands with inverted codes is a trap for the operator who
|
|
25
|
+
* learns one of them):
|
|
26
|
+
* 0 Success, including the no-op when nothing is expired
|
|
27
|
+
* 1 Usage/invocation error (bad flag or value)
|
|
28
|
+
* 2 Sweep error (an I/O or validation failure inside the lib, or any
|
|
29
|
+
* per-file error on the `--apply` path)
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { emitEvent } from './lib/events.mjs';
|
|
33
|
+
import { isMainModule } from './lib/is-main-module.mjs';
|
|
34
|
+
import {
|
|
35
|
+
RULE_EXPIRY_SWEEP_EVENT,
|
|
36
|
+
applyRuleExpirySweep,
|
|
37
|
+
planRuleExpirySweep,
|
|
38
|
+
} from './lib/reconcile/rule-expiry-sweep.mjs';
|
|
39
|
+
|
|
40
|
+
const DEFAULT_GRACE_DAYS = 0;
|
|
41
|
+
|
|
42
|
+
function printHelp() {
|
|
43
|
+
process.stdout.write(
|
|
44
|
+
`Usage: node scripts/sweep-expired-rules.mjs [--dry-run|--apply] [--json] [--grace-days N] [--now ISO] [--repo-root PATH] [--learnings PATH]
|
|
45
|
+
|
|
46
|
+
Removes EXPIRED entries from the consolidated machine-generated rule files in
|
|
47
|
+
.claude/rules/. An expired entry's prose block is deleted; its "## Provenance"
|
|
48
|
+
pair is KEPT as a "markers only" bullet, because /reconcile dedupes on those
|
|
49
|
+
markers and dropping one re-proposes the learning. A file is deleted only when
|
|
50
|
+
every substantive entry expired, and every provenance key is stamped terminal
|
|
51
|
+
before the unlink.
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
--dry-run Preview the plan; write nothing (DEFAULT)
|
|
55
|
+
--apply Perform the rewrites/deletes and emit the ledger event
|
|
56
|
+
--json Emit a single machine-parseable JSON summary line
|
|
57
|
+
--grace-days N Days past expiry before an entry is swept (default: ${DEFAULT_GRACE_DAYS})
|
|
58
|
+
--now ISO Injected clock (testing / what-if planning)
|
|
59
|
+
--repo-root PATH Repo root (default: process.cwd())
|
|
60
|
+
--learnings PATH Learnings store, repo-relative (default: the metrics store)
|
|
61
|
+
|
|
62
|
+
Exit codes: 0 success 1 usage/invocation error 2 sweep error
|
|
63
|
+
`,
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Exit 1 with a diagnostic on stderr (usage/invocation errors). */
|
|
68
|
+
function usageError(message) {
|
|
69
|
+
process.stderr.write(`sweep-expired-rules: ${message}\n`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function parseArgs(argv) {
|
|
74
|
+
const args = {
|
|
75
|
+
dryRun: true,
|
|
76
|
+
json: false,
|
|
77
|
+
graceDays: DEFAULT_GRACE_DAYS,
|
|
78
|
+
now: null,
|
|
79
|
+
repoRoot: process.cwd(),
|
|
80
|
+
learnings: null,
|
|
81
|
+
};
|
|
82
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
83
|
+
const a = argv[i];
|
|
84
|
+
if (a === '--apply') args.dryRun = false;
|
|
85
|
+
else if (a === '--dry-run') args.dryRun = true;
|
|
86
|
+
else if (a === '--json') args.json = true;
|
|
87
|
+
else if (a === '--grace-days') {
|
|
88
|
+
const raw = argv[++i];
|
|
89
|
+
const v = Number(raw);
|
|
90
|
+
if (!Number.isFinite(v) || v < 0) {
|
|
91
|
+
usageError(`--grace-days requires a non-negative number, got: ${raw}`);
|
|
92
|
+
}
|
|
93
|
+
args.graceDays = v;
|
|
94
|
+
} else if (a === '--now') {
|
|
95
|
+
const raw = argv[++i];
|
|
96
|
+
if (typeof raw !== 'string' || !Number.isFinite(Date.parse(raw))) {
|
|
97
|
+
usageError(`--now requires an ISO timestamp, got: ${raw}`);
|
|
98
|
+
}
|
|
99
|
+
args.now = raw;
|
|
100
|
+
} else if (a === '--repo-root') {
|
|
101
|
+
const raw = argv[++i];
|
|
102
|
+
if (typeof raw !== 'string' || raw.length === 0) usageError('--repo-root requires a path');
|
|
103
|
+
args.repoRoot = raw;
|
|
104
|
+
} else if (a === '--learnings') {
|
|
105
|
+
const raw = argv[++i];
|
|
106
|
+
if (typeof raw !== 'string' || raw.length === 0) usageError('--learnings requires a path');
|
|
107
|
+
args.learnings = raw;
|
|
108
|
+
} else if (a === '--help' || a === '-h') {
|
|
109
|
+
printHelp();
|
|
110
|
+
process.exit(0);
|
|
111
|
+
} else {
|
|
112
|
+
usageError(`unknown argument: ${a}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return args;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Roll the plan up into the summary both output modes render.
|
|
120
|
+
*
|
|
121
|
+
* `header_raises` is additive (#1388 P7): a header-raise is an
|
|
122
|
+
* `action: 'rewrite'` plan carrying `reason: 'header-raise'`, so it was counted
|
|
123
|
+
* inside `rewrites` and invisible on the human stdout line although `--json`
|
|
124
|
+
* always carried `plans[].reason`. It is a SUBSET of `rewrites`, never a
|
|
125
|
+
* sibling category — the two are deliberately not disjoint.
|
|
126
|
+
*/
|
|
127
|
+
export function summarize(plan, args, applied) {
|
|
128
|
+
const counts = { rewrite: 0, delete: 0, keep: 0 };
|
|
129
|
+
for (const p of plan.plans) counts[p.action] = (counts[p.action] ?? 0) + 1;
|
|
130
|
+
const headerRaises = plan.plans.filter((p) => p.reason === 'header-raise').length;
|
|
131
|
+
return {
|
|
132
|
+
dry_run: args.dryRun,
|
|
133
|
+
grace_days: args.graceDays,
|
|
134
|
+
files_scanned: plan.plans.length,
|
|
135
|
+
rewrites: counts.rewrite,
|
|
136
|
+
header_raises: headerRaises,
|
|
137
|
+
deletes: counts.delete,
|
|
138
|
+
keeps: counts.keep,
|
|
139
|
+
expired_entries: plan.plans.reduce((n, p) => n + p.expiredPairIds.length, 0),
|
|
140
|
+
unresolved_pairs: plan.plans.reduce((n, p) => n + p.unresolvedPairIds.length, 0),
|
|
141
|
+
malformed_lines: plan.malformedLines,
|
|
142
|
+
rules_dir_readable: plan.ok,
|
|
143
|
+
skipped: plan.skipped,
|
|
144
|
+
plans: plan.plans.map(({ nextContent: _nextContent, ...rest }) => rest),
|
|
145
|
+
...(applied ? { applied } : {}),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function main(argv) {
|
|
150
|
+
const args = parseArgs(argv);
|
|
151
|
+
|
|
152
|
+
let plan;
|
|
153
|
+
try {
|
|
154
|
+
plan = await planRuleExpirySweep({
|
|
155
|
+
repoRoot: args.repoRoot,
|
|
156
|
+
now: args.now ?? undefined,
|
|
157
|
+
graceDays: args.graceDays,
|
|
158
|
+
learningsPath: args.learnings ?? undefined,
|
|
159
|
+
});
|
|
160
|
+
} catch (err) {
|
|
161
|
+
process.stderr.write(`sweep-expired-rules: planning failed: ${err?.message ?? err}\n`);
|
|
162
|
+
process.exit(2);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
let applied = null;
|
|
166
|
+
if (!args.dryRun) {
|
|
167
|
+
applied = applyRuleExpirySweep(plan, { repoRoot: args.repoRoot, now: args.now ?? undefined });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const summary = summarize(plan, args, applied);
|
|
171
|
+
|
|
172
|
+
if (args.json) process.stdout.write(`${JSON.stringify(summary)}\n`);
|
|
173
|
+
else {
|
|
174
|
+
process.stdout.write(
|
|
175
|
+
`sweep-expired-rules: ${args.dryRun ? 'dry-run' : 'applied'} — ` +
|
|
176
|
+
`${summary.files_scanned} generated rule file(s), ${summary.rewrites} rewrite(s) ` +
|
|
177
|
+
`(${summary.header_raises} header-raise(s)), ` +
|
|
178
|
+
`${summary.deletes} delete(s), ${summary.expired_entries} expired entr(ies), ` +
|
|
179
|
+
`${summary.unresolved_pairs} unresolved pair(s), ${summary.skipped.length} skipped, ` +
|
|
180
|
+
`${summary.malformed_lines} malformed learnings line(s)\n`,
|
|
181
|
+
);
|
|
182
|
+
for (const s of plan.skipped) process.stdout.write(` skipped ${s.file}: ${s.reason}\n`);
|
|
183
|
+
for (const p of plan.plans) {
|
|
184
|
+
if (p.advisory) process.stdout.write(` advisory ${p.file}: ${p.advisory}\n`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (applied) {
|
|
189
|
+
for (const e of applied.errors) {
|
|
190
|
+
process.stderr.write(`sweep-expired-rules: ${e.file}: ${e.error}\n`);
|
|
191
|
+
}
|
|
192
|
+
// Emitted on apply ONLY, and AFTER the writes: a record's presence is proof
|
|
193
|
+
// that `.claude/rules/` was actually changed, never that a preview ran.
|
|
194
|
+
// Wrapped because `emitEvent` THROWS `EventValidationError` — a telemetry
|
|
195
|
+
// failure must not turn a completed sweep into a non-zero exit.
|
|
196
|
+
try {
|
|
197
|
+
await emitEvent(
|
|
198
|
+
RULE_EXPIRY_SWEEP_EVENT,
|
|
199
|
+
{
|
|
200
|
+
rewritten: applied.rewritten.length,
|
|
201
|
+
deleted: applied.deleted.length,
|
|
202
|
+
stamped: applied.stamped,
|
|
203
|
+
write_errors: applied.errors.length,
|
|
204
|
+
expired_entries: summary.expired_entries,
|
|
205
|
+
files_scanned: summary.files_scanned,
|
|
206
|
+
source: 'sweep-expired-rules-cli',
|
|
207
|
+
},
|
|
208
|
+
{ repoRoot: args.repoRoot },
|
|
209
|
+
);
|
|
210
|
+
} catch (err) {
|
|
211
|
+
process.stderr.write(`sweep-expired-rules: event emit failed: ${err?.message ?? err}\n`);
|
|
212
|
+
}
|
|
213
|
+
if (applied.errors.length > 0) process.exit(2);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (!plan.ok) {
|
|
217
|
+
process.stderr.write(
|
|
218
|
+
'sweep-expired-rules: .claude/rules/ exists but could not be enumerated — ' +
|
|
219
|
+
'the plan above is INCOMPLETE, not clean.\n',
|
|
220
|
+
);
|
|
221
|
+
process.exit(2);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (isMainModule(import.meta.url)) {
|
|
226
|
+
await main(process.argv.slice(2));
|
|
227
|
+
}
|
|
@@ -424,6 +424,27 @@ if (runCheck('check-unicode-safety.mjs') !== 0) checkFailed = 1;
|
|
|
424
424
|
process.stdout.write('\n');
|
|
425
425
|
if (runCheck('check-dead-bridge.mjs') !== 0) checkFailed = 1;
|
|
426
426
|
|
|
427
|
+
// BLOCKING (#1371): a hand-written `process.argv[1] === import.meta.url` entry
|
|
428
|
+
// guard is false under any symlinked invocation, so main() never runs and the
|
|
429
|
+
// process still exits 0 — the caller reads silence as success. This can block
|
|
430
|
+
// honestly because the backlog was drained to zero in the same change: the check
|
|
431
|
+
// is not red on arrival for work nobody intends to do (contrast the WARN-only
|
|
432
|
+
// censuses below, each of which had a standing backlog when it landed).
|
|
433
|
+
process.stdout.write('\n');
|
|
434
|
+
if (runCheck('check-entry-guard.mjs') !== 0) checkFailed = 1;
|
|
435
|
+
|
|
436
|
+
// BLOCKING (#1422), the complement of the check above: `check-entry-guard`
|
|
437
|
+
// judges the FORM of a guard that already exists, so a registered hook with NO
|
|
438
|
+
// guard at all passes it trivially — the #1393 regression class exactly. This
|
|
439
|
+
// one asks the other half of the question over the union of the four platform
|
|
440
|
+
// manifests: does every registered hook run its entry only under
|
|
441
|
+
// `isMainModule(import.meta.url)` / `invokedAsScript()`, and does no profile
|
|
442
|
+
// gate sit at module top level where its `process.exit(0)` kills a mere
|
|
443
|
+
// importer. Blocking honestly: 27/27 registered hooks were guarded at the
|
|
444
|
+
// moment it landed, because #1393 drained the backlog first.
|
|
445
|
+
process.stdout.write('\n');
|
|
446
|
+
if (runCheck('check-hook-entry-guards.mjs') !== 0) checkFailed = 1;
|
|
447
|
+
|
|
427
448
|
// FAIL-capable, unlike the WARN-only censuses below: R2+R4 were measured at
|
|
428
449
|
// 1 hit / 1 TP / 0 FP each against the full test corpus, so this check cannot be
|
|
429
450
|
// red on arrival for anything but a real instance of the class. The alternatives
|
|
@@ -69,7 +69,6 @@
|
|
|
69
69
|
* 2 — I/O error (file not found, unreadable stdin, unreadable sidecar file)
|
|
70
70
|
*/
|
|
71
71
|
|
|
72
|
-
import path from 'node:path';
|
|
73
72
|
import { readFileSync, existsSync, statSync } from 'node:fs';
|
|
74
73
|
import { execFileSync } from 'node:child_process';
|
|
75
74
|
import { warn } from './lib/common.mjs';
|
|
@@ -86,6 +85,17 @@ import {
|
|
|
86
85
|
// which roles are allowed to grant zero paths.
|
|
87
86
|
isReadOnlyWaveRole,
|
|
88
87
|
READ_ONLY_WAVE_ROLES,
|
|
88
|
+
// #1398 cond. 4 / #1405 / #1406 — THE grading predicate for an absolute Gate 5b
|
|
89
|
+
// grant. Lives in scope-gate.mjs so this CLI and `hooks/enforce-scope.mjs`
|
|
90
|
+
// grade one and the same way (BV-003): before the move, only this CLI could
|
|
91
|
+
// grade at all, so the hook honoured grants the CLI would have refused and a
|
|
92
|
+
// manifest that skipped the CLI was never graded.
|
|
93
|
+
gradeScopeEntry,
|
|
94
|
+
// #1398 cond. 4 — the `resolve` injection the predicate above takes. Moved
|
|
95
|
+
// into scope-gate.mjs (from a private copy here) once the hot-path cost was
|
|
96
|
+
// measured rather than assumed, so this CLI and `hooks/enforce-scope.mjs` pass
|
|
97
|
+
// the SAME resolver and can no longer reach different verdicts for one grant.
|
|
98
|
+
canonicalizeGrantPrefix,
|
|
89
99
|
// Aliased: `expandTestSiblings` is ALSO the name of the pre-existing
|
|
90
100
|
// boolean parameter threaded through validate()/assertSubsetOrDie for the
|
|
91
101
|
// #970 flag. Aliasing the import avoids shadowing that parameter rather than
|
|
@@ -338,79 +348,6 @@ function validateSessionBinding(obj, errors, warnings) {
|
|
|
338
348
|
}
|
|
339
349
|
}
|
|
340
350
|
|
|
341
|
-
/**
|
|
342
|
-
* Literal filesystem-root forms — POSIX "/" and the Windows equivalents "\"
|
|
343
|
-
* and a bare drive root ("C:\", "C:\\", ...). Checked independently of
|
|
344
|
-
* `path.isAbsolute()` because that primitive is platform-native: on a POSIX
|
|
345
|
-
* host (this repo's dev/CI hosts) it never reports `C:\` as absolute, so a
|
|
346
|
-
* Windows-literal-root entry would otherwise slip past every check below.
|
|
347
|
-
* @type {ReadonlySet<string>}
|
|
348
|
-
*/
|
|
349
|
-
const FILESYSTEM_ROOT_LITERALS = new Set(['/', '\\']);
|
|
350
|
-
const WINDOWS_DRIVE_ROOT_RE = /^[A-Za-z]:\\+$/;
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* @param {string} entry
|
|
354
|
-
* @returns {boolean}
|
|
355
|
-
*/
|
|
356
|
-
function isFilesystemRootLiteral(entry) {
|
|
357
|
-
return FILESYSTEM_ROOT_LITERALS.has(entry) || WINDOWS_DRIVE_ROOT_RE.test(entry);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Well-known top-level system/home directories. A FIXED DENYLIST (not a
|
|
362
|
-
* segment-count threshold): the #792 legitimate grant
|
|
363
|
-
* (`/private/tmp/<session>/scratchpad/**`) is itself a single-segment-deep
|
|
364
|
-
* grant under an unusual root ("private"), so any segment-count heuristic
|
|
365
|
-
* tight enough to catch `/etc/**` risks catching that too, or must be tuned
|
|
366
|
-
* loosely enough to leave a gap. A fixed list of the directories a
|
|
367
|
-
* hallucinated/mis-copied wave-scope entry could plausibly land on is
|
|
368
|
-
* predictable, auditable in a one-line diff, and does not touch legitimate
|
|
369
|
-
* deep grants under any other root.
|
|
370
|
-
* @type {ReadonlySet<string>}
|
|
371
|
-
*/
|
|
372
|
-
const DENIED_ABSOLUTE_TOP_SEGMENTS = new Set([
|
|
373
|
-
'etc',
|
|
374
|
-
'Users',
|
|
375
|
-
'home',
|
|
376
|
-
'root',
|
|
377
|
-
'bin',
|
|
378
|
-
'sbin',
|
|
379
|
-
'usr',
|
|
380
|
-
'System',
|
|
381
|
-
'var',
|
|
382
|
-
'boot',
|
|
383
|
-
'dev',
|
|
384
|
-
'proc',
|
|
385
|
-
'sys',
|
|
386
|
-
'Library',
|
|
387
|
-
'Applications',
|
|
388
|
-
'Windows',
|
|
389
|
-
]);
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* The top-level path segment of an absolute POSIX-style entry (the segment
|
|
393
|
-
* immediately after the leading "/"), if it is on the denylist above.
|
|
394
|
-
* @param {string} entry
|
|
395
|
-
* @returns {string|null}
|
|
396
|
-
*/
|
|
397
|
-
function deniedTopSegment(entry) {
|
|
398
|
-
const first = entry.split('/').filter(Boolean)[0];
|
|
399
|
-
return first && DENIED_ABSOLUTE_TOP_SEGMENTS.has(first) ? first : null;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* Does this entry contain a glob wildcard? Mirrors this codebase's own glob
|
|
404
|
-
* convention (`isGlobScopeEntry` in scripts/lib/scope-gate.mjs / #796): `*`
|
|
405
|
-
* is the sole wildcard metachar used in allowedPaths/fileScope entries
|
|
406
|
-
* throughout this repo (no `?`/`[]`/`{}` glob syntax is supported or tested
|
|
407
|
-
* anywhere else in scope-gate.mjs or enforce-scope.mjs).
|
|
408
|
-
* @param {string} entry
|
|
409
|
-
* @returns {boolean}
|
|
410
|
-
*/
|
|
411
|
-
function hasWildcard(entry) {
|
|
412
|
-
return entry.includes('*');
|
|
413
|
-
}
|
|
414
351
|
|
|
415
352
|
/**
|
|
416
353
|
* Validate allowedPaths array: must exist, be an array of non-empty strings,
|
|
@@ -463,37 +400,27 @@ function validateAllowedPaths(obj, errors, warnings) {
|
|
|
463
400
|
errors.push('allowedPaths contains empty string');
|
|
464
401
|
continue;
|
|
465
402
|
}
|
|
466
|
-
// #870
|
|
467
|
-
//
|
|
468
|
-
//
|
|
469
|
-
//
|
|
470
|
-
//
|
|
471
|
-
//
|
|
472
|
-
//
|
|
473
|
-
//
|
|
474
|
-
//
|
|
475
|
-
//
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
} else if (!hasWildcard(entry)) {
|
|
488
|
-
errors.push(
|
|
489
|
-
`allowedPaths contains a bare absolute file grant with no wildcard: ${entry} — a single concrete out-of-repo file has no established legitimate use in this codebase; scope a glob instead`,
|
|
490
|
-
);
|
|
491
|
-
} else {
|
|
492
|
-
warnings.push(
|
|
493
|
-
`allowedPaths contains an absolute (out-of-repo) path: ${entry} — honoured by hooks/enforce-scope.mjs Gate 5b; verify this grant is intentional`,
|
|
494
|
-
);
|
|
495
|
-
}
|
|
496
|
-
}
|
|
403
|
+
// #870 / #1398 / #1405 / #1406 — grade the entry as a Gate 5b grant through
|
|
404
|
+
// the SHARED predicate (`scripts/lib/scope-gate.mjs` gradeScopeEntry), the
|
|
405
|
+
// same one `hooks/enforce-scope.mjs` Gate 5b calls. Most absolute entries are
|
|
406
|
+
// a SANCTIONED out-of-repo grant and only WARN — the validator must not
|
|
407
|
+
// contradict the hook it validates for (#792/#870) — while the catastrophic
|
|
408
|
+
// subclasses (filesystem root, denylisted system directory in either its
|
|
409
|
+
// literal or its canonical spelling, a home grant at or above the user level
|
|
410
|
+
// or into a credential directory, a tilde that nothing expands, and a
|
|
411
|
+
// non-canonical prefix Gate 5b can never match) hard-reject here, BEFORE the
|
|
412
|
+
// hook is ever consulted. `null` = an ordinary relative entry, nothing to say.
|
|
413
|
+
//
|
|
414
|
+
// SAME PREDICATE, SAME RESOLVER (#1398 cond. 4). The resolver used to live
|
|
415
|
+
// here, which made the two callers' ARGUMENT shapes differ and let one grant
|
|
416
|
+
// reach two verdicts (`/tmp/x/**`: hook `warn`, this CLI `error`). Since the
|
|
417
|
+
// hot-path cost was measured (+0.067 ms per Gate 5b hit — see
|
|
418
|
+
// {@link canonicalizeGrantPrefix}) both callers pass this exact function, so
|
|
419
|
+
// the only remaining asymmetry is the CONSEQUENCE: exit-1 refusal here,
|
|
420
|
+
// allow-with-notice there.
|
|
421
|
+
const grade = gradeScopeEntry(entry, { resolve: canonicalizeGrantPrefix });
|
|
422
|
+
if (grade !== null) {
|
|
423
|
+
(grade.verdict === 'error' ? errors : warnings).push(`allowedPaths ${grade.message}`);
|
|
497
424
|
}
|
|
498
425
|
// Reject path traversal: any `../` segment. INDEPENDENT of the absolute checks
|
|
499
426
|
// above — an absolute entry that ALSO contains `../` must still be rejected
|
|
@@ -84,7 +84,6 @@
|
|
|
84
84
|
|
|
85
85
|
import { promises as fs } from 'node:fs';
|
|
86
86
|
import path from 'node:path';
|
|
87
|
-
import { pathToFileURL } from 'node:url';
|
|
88
87
|
|
|
89
88
|
import { die, utcTimestamp, expandTilde } from './lib/common.mjs';
|
|
90
89
|
import { parseColumnFlags, CliFlagError } from './lib/cli-flags.mjs';
|
|
@@ -96,6 +95,7 @@ import {
|
|
|
96
95
|
stageBackup,
|
|
97
96
|
compressAndCleanupBackup,
|
|
98
97
|
} from './lib/vault-consolidate-fs.mjs';
|
|
98
|
+
import { isMainModule } from './lib/is-main-module.mjs';
|
|
99
99
|
|
|
100
100
|
const DEFAULT_SOURCE = '~/Projects/vault';
|
|
101
101
|
const DEFAULT_CANONICAL = '~/Projects/Bernhard/vault';
|
|
@@ -580,7 +580,7 @@ async function main() {
|
|
|
580
580
|
// `process.argv[1]` is undefined when the module is loaded via `node -e
|
|
581
581
|
// "import(...)"` (no script path in argv), so guard against it before calling
|
|
582
582
|
// pathToFileURL — otherwise the import itself throws ERR_INVALID_ARG_TYPE.
|
|
583
|
-
if (
|
|
583
|
+
if (isMainModule(import.meta.url)) {
|
|
584
584
|
main().catch((e) => {
|
|
585
585
|
console.error(e);
|
|
586
586
|
process.exit(1);
|
package/scripts/vault-mirror.mjs
CHANGED
|
@@ -53,7 +53,6 @@ import { existsSync } from 'node:fs';
|
|
|
53
53
|
import { resolve } from 'node:path';
|
|
54
54
|
import { createInterface } from 'node:readline';
|
|
55
55
|
import { createReadStream } from 'node:fs';
|
|
56
|
-
import { pathToFileURL } from 'node:url';
|
|
57
56
|
|
|
58
57
|
import { processLearning, processSession, getMaskerStats } from './lib/vault-mirror/process.mjs';
|
|
59
58
|
import { emitMirrorEvent, emitMirrorRunEvent } from './lib/vault-mirror/telemetry.mjs';
|
|
@@ -64,6 +63,7 @@ import { resolveRepoNamespace } from './lib/vault-mirror/namespace.mjs';
|
|
|
64
63
|
import { resolveCanonicalSuffixes } from './lib/named-vault-resolver.mjs';
|
|
65
64
|
import { loadOwnerConfig } from './lib/owner-yaml.mjs';
|
|
66
65
|
import { canonicalizeSessions } from './lib/sessions-canonical.mjs';
|
|
66
|
+
import { isMainModule } from './lib/is-main-module.mjs';
|
|
67
67
|
|
|
68
68
|
// ── Canonical-vault helpers (#600 D2 / #607 D2) ────────────────────────────────
|
|
69
69
|
// These are module-level (above the CLI bootstrap) so the module is import-safe
|
|
@@ -166,8 +166,7 @@ export function _normalizeRemote(url) {
|
|
|
166
166
|
// (`node vault-mirror.mjs ...`). When imported from a unit test, argv belongs to
|
|
167
167
|
// the test runner — parsing it would spuriously process.exit. The exported
|
|
168
168
|
// helpers above are unaffected by this guard.
|
|
169
|
-
const _isDirectInvocation =
|
|
170
|
-
Boolean(process.argv[1]) && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
169
|
+
const _isDirectInvocation =isMainModule(import.meta.url);
|
|
171
170
|
|
|
172
171
|
if (_isDirectInvocation) {
|
|
173
172
|
let parsedFlags;
|
|
@@ -486,6 +485,10 @@ async function main() {
|
|
|
486
485
|
kind,
|
|
487
486
|
force,
|
|
488
487
|
vaultName,
|
|
488
|
+
// #1389: the repo whose `.vault.yaml` declares the namespace slug. This CLI
|
|
489
|
+
// has no repo-root flag, so it is the invocation cwd — bound ONCE here and
|
|
490
|
+
// shared by every processor call and the auto-commit below.
|
|
491
|
+
repoRoot: process.cwd(),
|
|
489
492
|
qualityMinNarrativeChars,
|
|
490
493
|
qualityMinConfidence,
|
|
491
494
|
};
|
|
@@ -694,7 +697,11 @@ async function main() {
|
|
|
694
697
|
// Opt-in: triggers only when --session-id is provided. Callers (session-end, evolve)
|
|
695
698
|
// pass it explicitly; bare invocations stay quiet to preserve legacy behaviour.
|
|
696
699
|
if (!dryRun && !noCommit && sessionIdArg) {
|
|
697
|
-
autoCommitVaultMirror(
|
|
700
|
+
autoCommitVaultMirror(
|
|
701
|
+
resolve(vaultDir),
|
|
702
|
+
sessionIdArg,
|
|
703
|
+
resolveRepoNamespace({ vaultName, repoRoot: ctx.repoRoot }),
|
|
704
|
+
);
|
|
698
705
|
}
|
|
699
706
|
}
|
|
700
707
|
|
|
@@ -37,10 +37,9 @@
|
|
|
37
37
|
*/
|
|
38
38
|
|
|
39
39
|
import { parseArgs } from 'node:util';
|
|
40
|
-
import { resolve as resolvePath } from 'node:path';
|
|
41
|
-
import { fileURLToPath } from 'node:url';
|
|
42
40
|
import { attributionForRecord, emitEvent } from './lib/events.mjs';
|
|
43
41
|
import { MANIFEST_SESSION_KEYS } from './lib/session-identity/own-session.mjs';
|
|
42
|
+
import { isMainModule } from './lib/is-main-module.mjs';
|
|
44
43
|
|
|
45
44
|
const HELP = `Usage: node scripts/wave-scope-binding.mjs [--merge] [--wave N] [--role R] [--repo-root DIR]
|
|
46
45
|
|
|
@@ -210,6 +209,6 @@ function readStdin() {
|
|
|
210
209
|
|
|
211
210
|
// `import.meta.main` is not available on every supported Node — compare argv[1]
|
|
212
211
|
// instead, so importing this module from a test never runs the CLI.
|
|
213
|
-
if (
|
|
212
|
+
if (isMainModule(import.meta.url)) {
|
|
214
213
|
await main(process.argv.slice(2));
|
|
215
214
|
}
|
|
@@ -102,7 +102,7 @@ source: projects-baseline | plugin-template | claude-init
|
|
|
102
102
|
|
|
103
103
|
A repo that has already been bootstrapped passes the gate on every subsequent invocation with zero overhead. The gate check reads three files and performs two grep operations — negligible cost.
|
|
104
104
|
|
|
105
|
-
`/bootstrap --retroactive` exists for repos that predate the gate (have `CLAUDE.md` + Session Config but no `bootstrap.lock`). It writes the lock without re-scaffolding. Documented in `
|
|
105
|
+
`/bootstrap --retroactive` exists for repos that predate the gate (have `CLAUDE.md` + Session Config but no `bootstrap.lock`). It writes the lock without re-scaffolding. Documented in `skills/bootstrap/SKILL.md`.
|
|
106
106
|
|
|
107
107
|
## Auto-Skill Dispatch (opt-in, default: off)
|
|
108
108
|
|
|
@@ -23,7 +23,7 @@ coverage check.
|
|
|
23
23
|
|
|
24
24
|
## Pattern 1 — GitLab pipeline + GitHub mirror sync (post-push)
|
|
25
25
|
|
|
26
|
-
**When.** After `git push origin main` from `
|
|
26
|
+
**When.** After `git push origin main` from `skills/close/SKILL.md` Phase 6.
|
|
27
27
|
Watches the GitLab pipeline through to a terminal status, then prints
|
|
28
28
|
the GitHub mirror's main-branch SHA so the operator can confirm parity.
|
|
29
29
|
|
|
@@ -8,15 +8,17 @@ The current platform is determined by the `scripts/lib/platform.mjs` library:
|
|
|
8
8
|
- `$SO_PLATFORM` = `claude` | `codex` | `cursor` | `pi`
|
|
9
9
|
- Environment: `$CLAUDE_PLUGIN_ROOT` (Claude Code), `$CODEX_PLUGIN_ROOT` (Codex CLI), `$CURSOR_RULES_DIR` (Cursor IDE), or `$PI_PLUGIN_ROOT` (Pi)
|
|
10
10
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
11
|
+
## File and Shell Tool Adaptation
|
|
12
|
+
|
|
13
|
+
Skill bodies use Claude Code names as operations, not as a requirement that every
|
|
14
|
+
harness expose those exact tools. Use the current runtime's available tools.
|
|
15
|
+
Measured in Codex Desktop 0.153.4 on 2026-09-19: `exec_command` runs shell
|
|
16
|
+
commands (`cat`, `rg`, `rg --files` for Read/Grep/Glob); `apply_patch` performs
|
|
17
|
+
file edits. These may be exposed through a `functions.exec` tools namespace.
|
|
18
|
+
Never call an unavailable `Read`, `Bash`, or `Skill` tool by name. An instruction
|
|
19
|
+
to invoke `session-orchestrator:<name>` means read and follow the canonical
|
|
20
|
+
`skills/<name>/SKILL.md` relative to the plugin root when no Skill tool exists.
|
|
21
|
+
Keep the user's project as the working directory for project operations.
|
|
20
22
|
|
|
21
23
|
## Platform-Specific Tool Mapping
|
|
22
24
|
|
|
@@ -24,7 +26,7 @@ These tools have the same name and behavior on all platforms. Cursor IDE uses eq
|
|
|
24
26
|
|
|
25
27
|
| Function | Claude Code | Codex CLI | Cursor IDE | Pi |
|
|
26
28
|
|----------|------------|-----------|------------|----|
|
|
27
|
-
| Present choices to user | `AskUserQuestion` tool with structured options |
|
|
29
|
+
| Present choices to user | `AskUserQuestion` tool with structured options | Available native user-input tool, respecting its mode restrictions; plain-text fallback when unavailable | Available native choice tool or numbered Markdown list | Numbered Markdown list v1; native UI adapter planned |
|
|
28
30
|
| Dispatch subagent | `Agent({ description, prompt, subagent_type })` | Native multi-agent collaboration namespace: `spawn_agent`, `list_agents`, `wait_agent`, `send_message`, `followup_task`, `interrupt_agent`, `close_agent`. Measured 2026-08-25 on `codex-cli 0.141.0` — `codex features list` → `multi_agent stable true`. | No native in-session Agent tool. Coordinator-side foreign dispatch via the headless `cursor-agent` CLI exists (`scripts/lib/wave-executor/foreign-dispatch.mjs`, #1150) — measured 2026-08-25 on `cursor-agent 2026.08.11-e8db854`. | Sequential execution v1. Do not assume native subagents until the Pi SDK dispatcher exists. |
|
|
29
31
|
| Track tasks | `TaskCreate` / `TaskUpdate` / `TaskList` | Plain-text checklist in response context | Plain-text checklist (same as Codex) | Plain-text checklist (same as Codex) |
|
|
30
32
|
| Enter plan mode | `EnterPlanMode` / `ExitPlanMode` tools | `/plan` slash command (prompt-level, not tool-based) | Instruction-based: "Focus on analysis and planning. Do not modify files until the user approves." | `/plan` prompt template; use instruction-based planning when tool mode is unavailable |
|
|
@@ -37,7 +39,13 @@ When a skill instructs "Use the AskUserQuestion tool", apply this pattern:
|
|
|
37
39
|
|
|
38
40
|
**On Claude Code:** Use the AskUserQuestion tool with structured options as documented.
|
|
39
41
|
|
|
40
|
-
**On Codex
|
|
42
|
+
**On Codex:** Prefer the available native user-input tool. In the measured Desktop
|
|
43
|
+
0.153.4 runtime (2026-09-19), `request_user_input_async` allows a question while
|
|
44
|
+
independent work continues; `request_user_input` has mode restrictions. Follow
|
|
45
|
+
the live tool contract. Existing user authorization remains valid; do not ask
|
|
46
|
+
again merely because a workflow names `AskUserQuestion`.
|
|
47
|
+
|
|
48
|
+
**When no suitable native tool is available (including Cursor IDE / Pi):** Present the same choices as a numbered Markdown list and ask the user to respond:
|
|
41
49
|
```
|
|
42
50
|
Choose one:
|
|
43
51
|
1. Option A — description
|
|
@@ -85,6 +93,10 @@ No Session Orchestrator Pi subagent dispatcher exists in v1. Execute wave tasks
|
|
|
85
93
|
|
|
86
94
|
Skills use `model-preference` (Claude), `model-preference-codex` (Codex), `model-preference-cursor` (Cursor), and active-model fallback on Pi in YAML frontmatter.
|
|
87
95
|
|
|
96
|
+
These are preferences, not authority to replace a user's selected model,
|
|
97
|
+
reasoning effort, or service tier. Preserve the current settings unless the user
|
|
98
|
+
requests a change; inherit them for native subagents.
|
|
99
|
+
|
|
88
100
|
## State Directory
|
|
89
101
|
|
|
90
102
|
- **Claude Code:** `.claude/` (STATE.md, wave-scope.json)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Research Evidence Contract
|
|
2
|
+
|
|
3
|
+
Use this contract when research informs a plan, audit, recommendation, or
|
|
4
|
+
research-agent handoff. Scale it to the decision: a trivial local lookup may be
|
|
5
|
+
one sentence; a comparison with several sources needs one record per material
|
|
6
|
+
claim. It does not require external research when repository evidence is enough.
|
|
7
|
+
|
|
8
|
+
## Record
|
|
9
|
+
|
|
10
|
+
For each finding that changes the recommendation, retain:
|
|
11
|
+
|
|
12
|
+
- **Source:** stable reference plus source revision or publication/update date.
|
|
13
|
+
For repository evidence, prefer `SHA:path:line`; for changing external facts,
|
|
14
|
+
include the observation date.
|
|
15
|
+
- **Basis:** label the finding `observed` for a measurement or source-code
|
|
16
|
+
inspection (name which), `documented` for a source's claim, or `inference`
|
|
17
|
+
when it follows from other evidence. A test found in source is not an
|
|
18
|
+
executed test. Never present one class as another. Counts, percentages and
|
|
19
|
+
distributions additionally require PSA-006's executed-command transcript
|
|
20
|
+
(`.claude/rules/parallel-sessions.md` § PSA-006) — command, file scope,
|
|
21
|
+
result, measurement time.
|
|
22
|
+
- **Local equivalent:** name the existing repository feature, dependency, rule,
|
|
23
|
+
or workflow that already covers the need; use `none found` only after a search
|
|
24
|
+
proportionate to the task.
|
|
25
|
+
- **Disposition:** `adopt`, `adapt`, `experiment`, `reject`, or
|
|
26
|
+
`already stronger`, with one short reason. `Adopt` still means implement
|
|
27
|
+
through the current repository's conventions; it does not authorize copying,
|
|
28
|
+
installing, publishing, or another external mutation.
|
|
29
|
+
- **Next check:** state one falsifiable next step when uncertainty remains: what
|
|
30
|
+
result would confirm or overturn the disposition.
|
|
31
|
+
|
|
32
|
+
Keep quoted text minimal. Record limitations that materially constrain the
|
|
33
|
+
claim. A source revision proves which artifact was inspected; it does not prove
|
|
34
|
+
that its documented behavior works.
|
|
35
|
+
|
|
36
|
+
## Private sources
|
|
37
|
+
|
|
38
|
+
Treat private/internal sources as evidence for an authorized private audience
|
|
39
|
+
only. Follow [Private capability context](private-capability-context.md) for
|
|
40
|
+
lookup and retention. Do not copy private identities, paths, excerpts, or
|
|
41
|
+
derived implementation details into a public plan or handoff. Re-establish a
|
|
42
|
+
public claim from an authorized public source, or omit it. Source access never
|
|
43
|
+
expands the task's implementation or external-action authority.
|
|
44
|
+
|
|
45
|
+
## Compact example
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
Source: vendor guide, rev 3.2, observed 2026-09-15
|
|
49
|
+
Basis: documented — retries use exponential backoff; runtime behavior untested
|
|
50
|
+
Local equivalent: src/retry.mjs already provides capped linear retries
|
|
51
|
+
Disposition: experiment — compare failure recovery before changing the default
|
|
52
|
+
Next check: 100 replayed failures; reject if success rate does not improve
|
|
53
|
+
```
|