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
package/pi/prompts/plan.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: "Use this skill when performing structured project planning and PRD generation with three modes: new (project kickoff with repo scaffolding), feature (compact feature PRD), retro (data-driven retrospective). All modes share a researched Q&A engine that dispatches parallel Explore agents before each question wave, presents options via AskUserQuestion with recommendations, and produces documents with prioritized issue creation."
|
|
3
3
|
argument-hint: "[new|feature|retro]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /plan
|
|
7
7
|
|
|
8
|
-
Use the Session Orchestrator
|
|
8
|
+
Use the Session Orchestrator skill definition at `skills/plan/SKILL.md`.
|
|
9
9
|
|
|
10
10
|
Arguments: $@
|
|
11
11
|
|
|
12
|
-
Read that
|
|
12
|
+
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
package/pi/prompts/portfolio.md
CHANGED
|
@@ -5,8 +5,8 @@ argument-hint: "[--dry-run] [--repo <name>]"
|
|
|
5
5
|
|
|
6
6
|
# /portfolio
|
|
7
7
|
|
|
8
|
-
Use the Session Orchestrator
|
|
8
|
+
Use the Session Orchestrator skill definition at `skills/portfolio/SKILL.md`.
|
|
9
9
|
|
|
10
10
|
Arguments: $@
|
|
11
11
|
|
|
12
|
-
Read that
|
|
12
|
+
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
package/pi/prompts/reconcile.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Use this skill when the user wants to reconcile learnings into rules, run /reconcile, propose rules from learnings, turn learnings into .claude/rules/ entries, or review what rules would be generated from current session learnings. On-demand version of session-end Phase 3.6.8.
|
|
3
3
|
argument-hint: "[--dry-run]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /reconcile
|
|
7
7
|
|
|
8
|
-
Use the Session Orchestrator
|
|
8
|
+
Use the Session Orchestrator skill definition at `skills/reconcile/SKILL.md`.
|
|
9
9
|
|
|
10
10
|
Arguments: $@
|
|
11
11
|
|
|
12
|
-
Read that
|
|
12
|
+
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
package/pi/prompts/release.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Cut a release — the order the steps must run in, and the criteria that abort a release
|
|
2
|
+
description: "Cut a release — the order the steps must run in, and the criteria that abort a release"
|
|
3
3
|
argument-hint: "[X.Y.Z]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /release
|
|
7
7
|
|
|
8
|
-
Use the Session Orchestrator
|
|
8
|
+
Use the Session Orchestrator skill definition at `skills/release/SKILL.md`.
|
|
9
9
|
|
|
10
10
|
Arguments: $@
|
|
11
11
|
|
|
12
|
-
Read that
|
|
12
|
+
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
package/pi/prompts/repo-audit.md
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
3
|
-
argument-hint: ""
|
|
2
|
+
description: "Use this skill when the user wants to audit a repository for baseline compliance, check code quality, security posture, CI/CD setup, testing, documentation, and ecosystem configuration. Runs 9 checklist categories and emits a Markdown report plus JSON sidecar at .orchestrator/metrics/repo-audit-<timestamp>.json. <example>Context: User is in a project repo and wants a baseline compliance check. user: \"/repo-audit\" assistant: \"Running repo-audit across 9 categories — Configuration, Code Quality, Git Hygiene, CI/CD, Testing, Security, Documentation, Clank Integration (optional), and MCP Configuration. Will produce a Markdown checklist report and JSON sidecar.\" <commentary>The user wants a compliance check; this skill is appropriate because it runs all 9 categories with pass/fail/warn/skipped statuses and writes structured output.</commentary></example>"
|
|
4
3
|
---
|
|
5
4
|
|
|
6
5
|
# /repo-audit
|
|
7
6
|
|
|
8
|
-
Use the Session Orchestrator
|
|
7
|
+
Use the Session Orchestrator skill definition at `skills/repo-audit/SKILL.md`.
|
|
9
8
|
|
|
10
9
|
Arguments: $@
|
|
11
10
|
|
|
12
|
-
Read that
|
|
11
|
+
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
package/pi/prompts/session.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Start a development session (housekeeping, feature, deep; ultradeep = deep + profile)
|
|
3
|
-
argument-hint: "[housekeeping|feature|deep|ultradeep]"
|
|
2
|
+
description: "Start a development session (housekeeping, feature, deep; ultradeep = deep + profile)"
|
|
3
|
+
argument-hint: "[housekeeping|feature|deep|ultradeep] [task context]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /session
|
package/pi/prompts/spinout.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: "Use when extracting a project into its own repo — a venture spinout (e.g. a product leaving its incubator repo) or a sanitized content-snapshot fork. Guided 5-step runbook: target sphere + path, confidentiality/sanitize check, copy + fresh git init, SNAPSHOT-FREEZE marker in the source repo, remotes + registration. Trigger on 'spin out X', 'extract this into its own repo', 'fork X sanitized'."
|
|
3
3
|
argument-hint: "[--type venture|snapshot] [--dry-run]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /spinout
|
|
7
7
|
|
|
8
|
-
Use the Session Orchestrator
|
|
8
|
+
Use the Session Orchestrator skill definition at `skills/spinout/SKILL.md`.
|
|
9
9
|
|
|
10
10
|
Arguments: $@
|
|
11
11
|
|
|
12
|
-
Read that
|
|
12
|
+
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: "Use this skill when the user wants to identify unused, near-zero-use, or stale skills/agents/commands in the plugin surface so they can be demoted or retired. Combines agent-dispatch telemetry (start-events only) with static reference scanning, classifies every surface item into Active / Investigate / Demote / Retire, and emits a Markdown report plus JSON sidecar. NEVER auto-deletes — surfaces candidates for human decision. Quarterly cadence. <example>Context: The plugin surface has grown and the maintainer wants to prune dead weight. user: \"/sunset-review\" assistant: \"Running the sunset walk — classifying skills, agents, and commands by usage telemetry + static refs, grouped by Retire / Demote / Investigate / Active. No item is deleted automatically; I'll surface Retire/Demote candidates for your decision.\" <commentary>The user wants a usage-driven prune candidate list; this skill runs the read-only walker, presents grouped verdicts, and writes a sidecar — it never deletes.</commentary></example>"
|
|
3
3
|
argument-hint: "[--kind skill|agent|command] [--window-days N]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /sunset-review
|
|
7
7
|
|
|
8
|
-
Use the Session Orchestrator
|
|
8
|
+
Use the Session Orchestrator skill definition at `skills/sunset-review/SKILL.md`.
|
|
9
9
|
|
|
10
10
|
Arguments: $@
|
|
11
11
|
|
|
12
|
-
Read that
|
|
12
|
+
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Acknowledge templates-first policy for the current session — bypasses the pre-bash-templates-first hook for the remainder of the session
|
|
2
|
+
description: "Acknowledge templates-first policy for the current session — bypasses the pre-bash-templates-first hook for the remainder of the session"
|
|
3
3
|
argument-hint: "[optional-reason]"
|
|
4
4
|
---
|
|
5
5
|
|
package/pi/prompts/test.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Agentic end-to-end test orchestrator — drive web/macOS flows, evaluate UX rubric, reconcile issues
|
|
2
|
+
description: "Agentic end-to-end test orchestrator — drive web/macOS flows, evaluate UX rubric, reconcile issues"
|
|
3
3
|
argument-hint: "[scope|profile-name] [--since <git-ref>] [--full]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /test
|
|
7
7
|
|
|
8
|
-
Use the Session Orchestrator
|
|
8
|
+
Use the Session Orchestrator skill definition at `skills/test/SKILL.md`.
|
|
9
9
|
|
|
10
10
|
Arguments: $@
|
|
11
11
|
|
|
12
|
-
Read that
|
|
12
|
+
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
package/pi/prompts/ux-grill.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
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."
|
|
3
3
|
argument-hint: "[url | manifest-path]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /ux-grill
|
|
7
7
|
|
|
8
|
-
Use the Session Orchestrator
|
|
8
|
+
Use the Session Orchestrator skill definition at `skills/ux-grill/SKILL.md`.
|
|
9
9
|
|
|
10
10
|
Arguments: $@
|
|
11
11
|
|
|
12
|
-
Read that
|
|
12
|
+
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
package/rules/README.md
CHANGED
|
@@ -9,7 +9,7 @@ It is **not** the always-on rule set of *this* repository — those live in
|
|
|
9
9
|
"rules" but play opposite roles: `rules/` ships rules **out** to other repos,
|
|
10
10
|
`.claude/rules/` is what this repo runs on day-to-day.
|
|
11
11
|
|
|
12
|
-
Every file here carries a
|
|
12
|
+
Every rule file here carries a
|
|
13
13
|
`<!-- source: session-orchestrator plugin (canonical: rules/<path>) -->` header.
|
|
14
14
|
On sync, plugin-sourced files are overwritten in the consumer while its
|
|
15
15
|
locally-authored rules are preserved (copy-on-write). The canonical manifest of
|
|
@@ -185,4 +185,4 @@ async function updateUser(id: string, data: Partial<User>): Promise<void> {
|
|
|
185
185
|
- Batch operations: use `.upsert()` or `.insert()` with arrays instead of individual inserts in loops.
|
|
186
186
|
|
|
187
187
|
## See Also
|
|
188
|
-
|
|
188
|
+
security-web.md · frontend.md · backend.md · swift.md · parallel-sessions.md
|
|
@@ -165,7 +165,7 @@ Split api and worker into separate processes when any of these apply: queue-base
|
|
|
165
165
|
- Named events (`event: <name>\n`) instead of untyped `data:` payloads, so client code reads `source.addEventListener('<name>', ...)` rather than switching on payload shape.
|
|
166
166
|
- Naming: lowercase, dot-scoped, noun-verb. Examples: `draft.ready`, `classification.done`, `job.failed`, `stream.heartbeat`, `stream.end`.
|
|
167
167
|
- Scope events by domain, not by endpoint. Two endpoints emitting `job.failed` is fine if the payload shape is identical.
|
|
168
|
-
- Document the event catalog in the service's `CLAUDE.md` or `docs/api.md` — consumers need to know what to listen for without reading source.
|
|
168
|
+
- Document the event catalog in the service's `CLAUDE.md` or `docs/api.md` — consumers need to know what to listen for without reading source. <!-- path-check: example -->
|
|
169
169
|
|
|
170
170
|
### Client reconnect pattern
|
|
171
171
|
- `EventSource` reconnects automatically on network drop. Use the `Last-Event-ID` header to resume from the last received ID — set `id: <number>\n` on each server event for this to work.
|
|
@@ -285,7 +285,7 @@ Uses the canonical envelope from the [Canonical API Response Envelope](#canonica
|
|
|
285
285
|
- **Reusable helper:** candidate for `@your-org/http-client` or a dedicated `@your-org/ringbuffer` package if demand grows past 2 consumer repos.
|
|
286
286
|
|
|
287
287
|
## Feature Flags
|
|
288
|
-
- Use environment-variable-backed typed flags as default (see `docs/feature-flags.md`).
|
|
288
|
+
- Use environment-variable-backed typed flags as default (see `docs/feature-flags.md`). <!-- path-check: example -->
|
|
289
289
|
- Naming convention: `FF_<FEATURE_NAME>` in `.env`.
|
|
290
290
|
- Every flag must have an expiry date. Remove within 30 days of full rollout.
|
|
291
291
|
|
|
@@ -387,4 +387,4 @@ export async function askAI(prompt: string, options?: { model?: string; maxToken
|
|
|
387
387
|
- Checking budget after the LLM call (check before, enforce before spending)
|
|
388
388
|
|
|
389
389
|
## See Also
|
|
390
|
-
|
|
390
|
+
security-web.md · frontend.md · backend-data.md · swift.md · parallel-sessions.md
|
|
@@ -95,4 +95,4 @@ tier: wave-only
|
|
|
95
95
|
- No arbitrary z-index (`z-index: 999 / 9999`). Build a semantic z-index scale (dropdown → sticky → modal → toast → tooltip); never magic numbers.
|
|
96
96
|
|
|
97
97
|
## See Also
|
|
98
|
-
|
|
98
|
+
security-web.md · backend.md · backend-data.md · parallel-sessions.md
|
|
@@ -67,7 +67,7 @@ CSRF, rate limiting, CSP, and transport security. Core security rules are in `se
|
|
|
67
67
|
|
|
68
68
|
#### SEC-011: CSP single-source enforcement
|
|
69
69
|
- Advisory rules are silent when they regress. Wire the single-source rule into a mechanical check so duplicates fail fast.
|
|
70
|
-
- Canonical hook: `templates/shared/hooks/check-csp-single-source.sh`. Greps all TS/JS under the given paths for `Content-Security-Policy`, filters to `proxy.ts` / `middleware.ts` / `next.config.*`, fails if more than one file matches.
|
|
70
|
+
- Canonical hook: `templates/shared/hooks/check-csp-single-source.sh`. Greps all TS/JS under the given paths for `Content-Security-Policy`, filters to `proxy.ts` / `middleware.ts` / `next.config.*`, fails if more than one file matches. <!-- path-check: example -->
|
|
71
71
|
- **Wire into pre-push (Husky):**
|
|
72
72
|
```json
|
|
73
73
|
// package.json
|
|
@@ -77,7 +77,7 @@ CSRF, rate limiting, CSP, and transport security. Core security rules are in `se
|
|
|
77
77
|
# .husky/pre-push
|
|
78
78
|
pnpm run hook:check-csp
|
|
79
79
|
```
|
|
80
|
-
- **Wire into CI security stage:** copy the `check-csp-single-source` job from `templates/shared/hooks/README.md` into `.gitlab-ci.yml`. Runs on every merge request.
|
|
80
|
+
- **Wire into CI security stage:** copy the `check-csp-single-source` job from `templates/shared/hooks/README.md` into `.gitlab-ci.yml`. Runs on every merge request. <!-- path-check: example -->
|
|
81
81
|
- Exit codes: `0` pass, `1` duplicate CSP source (SEC-011 violation), `2` tool error.
|
|
82
82
|
- Why: browsers receiving two `Content-Security-Policy` headers take the intersection — nonces and `strict-dynamic` break silently. Humans miss this in review; a grep doesn't.
|
|
83
83
|
|
|
@@ -191,4 +191,4 @@ securityMiddleware(app);
|
|
|
191
191
|
- **Template Literals**: Never use tagged template literals with user input for SQL, HTML, or shell commands. Use parameterized queries, DOMPurify, or `child_process.execFile()` respectively.
|
|
192
192
|
|
|
193
193
|
## See Also
|
|
194
|
-
|
|
194
|
+
frontend.md · backend.md · backend-data.md · swift.md · parallel-sessions.md
|
|
@@ -62,4 +62,4 @@ tier: wave-only
|
|
|
62
62
|
- Validate all server-sent data with Codable schemas. Never `force-unwrap` optional JSON fields.
|
|
63
63
|
|
|
64
64
|
## See Also
|
|
65
|
-
|
|
65
|
+
frontend.md · backend.md · parallel-sessions.md
|
|
@@ -41,7 +41,6 @@
|
|
|
41
41
|
|
|
42
42
|
import { readFileSync } from 'node:fs';
|
|
43
43
|
import { spawnSync } from 'node:child_process';
|
|
44
|
-
import { pathToFileURL } from 'node:url';
|
|
45
44
|
import { join } from 'node:path';
|
|
46
45
|
|
|
47
46
|
import { findProjectRoot, resolveInstructionFile, warn } from './lib/common.mjs';
|
|
@@ -52,6 +51,7 @@ import { defaultGlabRepo } from './lib/vcs-repo-spec.mjs';
|
|
|
52
51
|
import { readLock } from './lib/session-lock.mjs';
|
|
53
52
|
import { resolveStateMdPath } from './lib/state-md/frontmatter-mutators.mjs';
|
|
54
53
|
import { parseStateMd } from './lib/state-md/yaml-parser.mjs';
|
|
54
|
+
import { isMainModule } from './lib/is-main-module.mjs';
|
|
55
55
|
|
|
56
56
|
const DEFAULT_PRD_DIR = 'docs/prd';
|
|
57
57
|
const DEFAULT_VAULT_SUBDIR = '01-projects/session-orchestrator/prd';
|
|
@@ -635,7 +635,7 @@ export function main({
|
|
|
635
635
|
// CLI guard — prevents process.exit during test-time imports
|
|
636
636
|
// ---------------------------------------------------------------------------
|
|
637
637
|
|
|
638
|
-
if (
|
|
638
|
+
if (isMainModule(import.meta.url)) {
|
|
639
639
|
try {
|
|
640
640
|
const { code } = main();
|
|
641
641
|
process.exit(code ?? 0);
|
package/scripts/auq-audit.mjs
CHANGED
|
@@ -76,6 +76,7 @@ import {
|
|
|
76
76
|
} from './lib/auq/schema.mjs';
|
|
77
77
|
import { corpusKindOf, parseRepo } from './lib/auq/parse.mjs';
|
|
78
78
|
import { writeStdoutLineSync } from './lib/io.mjs';
|
|
79
|
+
import { isMainModule } from './lib/is-main-module.mjs';
|
|
79
80
|
|
|
80
81
|
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
81
82
|
const REPO_ROOT_DEFAULT = path.resolve(HERE, '..');
|
|
@@ -818,8 +819,6 @@ function pkgVersion() {
|
|
|
818
819
|
}
|
|
819
820
|
}
|
|
820
821
|
|
|
821
|
-
const invokedDirectly =
|
|
822
|
-
process.argv[1] !== undefined &&
|
|
823
|
-
path.resolve(process.argv[1]) === path.resolve(fileURLToPath(import.meta.url));
|
|
822
|
+
const invokedDirectly =isMainModule(import.meta.url);
|
|
824
823
|
|
|
825
824
|
if (invokedDirectly) main();
|
package/scripts/autopilot.mjs
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* --max-sessions=N Max iterations (1..50, default 5).
|
|
15
15
|
* --max-hours=H Max wall-clock hours (0.5..24.0, default 4.0).
|
|
16
16
|
* --confidence-threshold=0.X Mode confidence gate (0.0..1.0, default 0.85).
|
|
17
|
+
* --max-tokens=N Cumulative output-token budget (0..10000000, default 500000; 0 disables).
|
|
17
18
|
* --dry-run Emit a single record without spawning sessions.
|
|
18
19
|
* --verbose Pipe child process stdio (instead of inherit).
|
|
19
20
|
*
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
import { readFileSync, existsSync } from 'node:fs';
|
|
36
37
|
import { spawnSync, spawn } from 'node:child_process';
|
|
37
38
|
import { resolve } from 'node:path';
|
|
39
|
+
import { fileURLToPath } from 'node:url';
|
|
38
40
|
|
|
39
41
|
import {
|
|
40
42
|
runLoop,
|
|
@@ -55,6 +57,14 @@ import { readCanonicalSessions } from './lib/sessions-canonical.mjs';
|
|
|
55
57
|
|
|
56
58
|
const argv = process.argv.slice(2);
|
|
57
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Plugin root, resolved from THIS file's own location (`<root>/scripts/autopilot.mjs`
|
|
62
|
+
* → `<root>`) and never from an env var. The driver is spawned unattended from an
|
|
63
|
+
* arbitrary cwd, so `--plugin-dir` must name the plugin that owns this very file;
|
|
64
|
+
* an env-var read would point wherever the operator's shell last happened to point.
|
|
65
|
+
*/
|
|
66
|
+
const PLUGIN_ROOT = resolve(fileURLToPath(new URL('.', import.meta.url)), '..');
|
|
67
|
+
|
|
58
68
|
const hasHeadless = argv.includes('--headless');
|
|
59
69
|
const hasVerbose = argv.includes('--verbose');
|
|
60
70
|
|
|
@@ -69,7 +79,7 @@ const flagsForParse = argv.filter(
|
|
|
69
79
|
(a) => a !== '--headless' && a !== '--verbose'
|
|
70
80
|
);
|
|
71
81
|
|
|
72
|
-
const { maxSessions, maxHours, confidenceThreshold, dryRun } = parseFlags(flagsForParse);
|
|
82
|
+
const { maxSessions, maxHours, confidenceThreshold, maxTokens, dryRun } = parseFlags(flagsForParse);
|
|
73
83
|
|
|
74
84
|
// ---------------------------------------------------------------------------
|
|
75
85
|
// Session Config (parsed once, shared by thresholds + decay readers)
|
|
@@ -269,9 +279,14 @@ async function sessionRunner({ mode, autopilotRunId }) {
|
|
|
269
279
|
? ['ignore', 'pipe', 'pipe']
|
|
270
280
|
: ['ignore', 'inherit', 'inherit'];
|
|
271
281
|
|
|
282
|
+
// `session` is a RESERVED terminal-only built-in name under `claude -p`: the
|
|
283
|
+
// bare `/session <mode>` form answers "/session isn't available in this
|
|
284
|
+
// environment." and the child exits having done nothing (measured 2026-09-16,
|
|
285
|
+
// claude 2.1.273 — `commands/session.md` § Headless). Only the namespaced form
|
|
286
|
+
// resolves, and only when the plugin that defines it is on `--plugin-dir`.
|
|
272
287
|
const child = spawn(
|
|
273
288
|
'claude',
|
|
274
|
-
['-p', `/session ${mode}
|
|
289
|
+
['-p', `/session-orchestrator:session ${mode}`, '--plugin-dir', PLUGIN_ROOT],
|
|
275
290
|
{
|
|
276
291
|
env: { ...process.env, AUTOPILOT_RUN_ID: autopilotRunId },
|
|
277
292
|
stdio: childStdio,
|
|
@@ -372,12 +387,18 @@ async function main() {
|
|
|
372
387
|
maxSessions,
|
|
373
388
|
maxHours,
|
|
374
389
|
confidenceThreshold,
|
|
390
|
+
maxTokens,
|
|
375
391
|
dryRun,
|
|
376
392
|
modeSelector,
|
|
377
393
|
sessionRunner,
|
|
378
394
|
resourceEvaluator,
|
|
379
395
|
peerCounter,
|
|
380
396
|
abortSignal: controller.signal,
|
|
397
|
+
// STALL_TIMEOUT progress marker. `autopilot.jsonl` is written ONCE per
|
|
398
|
+
// invocation (after the loop), so its mtime belongs to the PREVIOUS run and
|
|
399
|
+
// fired the kill-switch after iteration 1; the session.lock heartbeat is
|
|
400
|
+
// refreshed while a session is alive. See stall-sampler.mjs § PRECEDENCE.
|
|
401
|
+
sessionLockPath: resolve('.orchestrator/session.lock'),
|
|
381
402
|
runId: autopilotRunId,
|
|
382
403
|
branch: branch ?? undefined,
|
|
383
404
|
});
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* backfill-abandoned-sessions.mjs — one-time historical migration CLI (#724 C1).
|
|
4
4
|
*
|
|
5
|
-
* Scans `.orchestrator/metrics/events.jsonl`
|
|
5
|
+
* Scans `.orchestrator/metrics/events.jsonl` — and every rotated archive
|
|
6
|
+
* beside it (#1414) — for every distinct
|
|
6
7
|
* `orchestrator.session.started` UUID that has no counterpart in
|
|
7
8
|
* `.orchestrator/metrics/sessions.jsonl`, bridges each to its semantic id via
|
|
8
9
|
* `orchestrator.session.lock.acquired` where available, and synthesizes a
|
|
@@ -39,11 +40,13 @@
|
|
|
39
40
|
import fs from 'node:fs';
|
|
40
41
|
import path from 'node:path';
|
|
41
42
|
import { parseArgs } from 'node:util';
|
|
42
|
-
import { fileURLToPath } from 'node:url';
|
|
43
43
|
|
|
44
44
|
import { backfillAbandonedSession, isUuid } from './lib/session-close-backfill.mjs';
|
|
45
|
-
import { emitEvent } from './lib/events.mjs';
|
|
45
|
+
import { SCAN_CHUNK_BYTES, emitEvent, listEventSourcesNewestFirst } from './lib/events.mjs';
|
|
46
46
|
import { getProjectDir } from './lib/platform.mjs';
|
|
47
|
+
import { isMainModule } from './lib/is-main-module.mjs';
|
|
48
|
+
import { isLockLive, readLock } from './lib/session-lock.mjs';
|
|
49
|
+
import { readProcessLocalSessionIds } from './lib/session-identity/own-session.mjs';
|
|
47
50
|
|
|
48
51
|
const LOCK_ACQUIRED = 'orchestrator.session.lock.acquired';
|
|
49
52
|
const SESSION_STARTED = 'orchestrator.session.started';
|
|
@@ -101,11 +104,29 @@ function readJsonl(filePath) {
|
|
|
101
104
|
* session.started UUID, each bridged to its semantic id via lock.acquired
|
|
102
105
|
* where one exists. Preserves first-seen order.
|
|
103
106
|
*
|
|
107
|
+
* THIS VERY PROCESS is excluded (#1376). The shared core's own
|
|
108
|
+
* `skipped-own-live-lock` branch used to carry that job alone, but it is now
|
|
109
|
+
* defeasible: `ownSessionIsEnding` lets the SessionEnd hook record its own
|
|
110
|
+
* session, so the CLI must not depend on a branch whose meaning the caller
|
|
111
|
+
* chooses. The exclusion needs THREE conjuncts, and dropping any one of them
|
|
112
|
+
* breaks it in a different direction:
|
|
113
|
+
* 1. the candidate names the lock (by either id, including the #863 (d)
|
|
114
|
+
* lock shape that stores the semantic id in `session_id`),
|
|
115
|
+
* 2. the lock is LIVE — a stale lock names a session nobody is running, and
|
|
116
|
+
* reconstructing it is exactly this CLI's job, and
|
|
117
|
+
* 3. a PROCESS-LOCAL id (hook payload / harness env, never the repo-global
|
|
118
|
+
* lock — see `readProcessLocalSessionIds`) matches the lock, which is
|
|
119
|
+
* what distinguishes THIS process from a PEER's running session in the
|
|
120
|
+
* same working copy. Without it the repo-global lock would vouch for
|
|
121
|
+
* itself and a peer's live session would read as "me".
|
|
122
|
+
* A peer's live session is NOT excluded here and does not need to be: the core
|
|
123
|
+
* still rejects it through the untouched own/foreign live-lock guards.
|
|
124
|
+
*
|
|
104
125
|
* @param {{ repoRoot: string }} args
|
|
105
126
|
* @returns {Array<{ sessionId: string, semanticSessionId: string|null }>}
|
|
106
127
|
*/
|
|
107
128
|
export function planSessions({ repoRoot }) {
|
|
108
|
-
const
|
|
129
|
+
const eventsPath = path.join(repoRoot, '.orchestrator', 'metrics', 'events.jsonl');
|
|
109
130
|
|
|
110
131
|
// Two independent UUID -> semantic bridges (#1167). `lock.acquired` is the
|
|
111
132
|
// original one, but a session that LOST the lock-acquire race never emits it;
|
|
@@ -117,24 +138,159 @@ export function planSessions({ repoRoot }) {
|
|
|
117
138
|
// lock.acquired keeps precedence — it is the older, mode-carrying attestation.
|
|
118
139
|
const semanticFromLock = new Map();
|
|
119
140
|
const semanticFromEnded = new Map();
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
141
|
+
const seen = new Set();
|
|
142
|
+
/** Distinct `session.started` ids in FIRST-SEEN (chronological) order. */
|
|
143
|
+
const startedIds = [];
|
|
144
|
+
|
|
145
|
+
// #1414 — the whole history, OLDEST SOURCE FIRST, streamed line by line. The
|
|
146
|
+
// previous `readJsonl` of the active file alone missed every session whose
|
|
147
|
+
// `session.started` had been rotated into `_archive/`; reading the same
|
|
148
|
+
// sources through `readEventsWithRotations` instead would have loaded up to
|
|
149
|
+
// ~60 MB into memory on a path that runs at SESSION START
|
|
150
|
+
// (`hooks/on-session-start.mjs` → `backfillOnSessionStart`). Reversing the
|
|
151
|
+
// newest-first source list keeps first-seen order chronological, exactly as
|
|
152
|
+
// the single-file read produced it.
|
|
153
|
+
for (const source of [...listEventSourcesNewestFirst({ filePath: eventsPath })].reverse()) {
|
|
154
|
+
forEachJsonlRecord(source.path, (ev) => {
|
|
155
|
+
if (!ev || typeof ev !== 'object') return;
|
|
156
|
+
if (typeof ev.session_id === 'string' && typeof ev.semantic_session_id === 'string') {
|
|
157
|
+
if (ev.event === LOCK_ACQUIRED) semanticFromLock.set(ev.session_id, ev.semantic_session_id);
|
|
158
|
+
else if (ev.event === SESSION_ENDED) {
|
|
159
|
+
semanticFromEnded.set(ev.session_id, ev.semantic_session_id);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (ev.event !== SESSION_STARTED || typeof ev.session_id !== 'string') return;
|
|
163
|
+
if (seen.has(ev.session_id)) return;
|
|
164
|
+
seen.add(ev.session_id);
|
|
165
|
+
startedIds.push(ev.session_id);
|
|
166
|
+
});
|
|
124
167
|
}
|
|
168
|
+
|
|
169
|
+
// Resolved AFTER the pass, never during it: a `lock.acquired` / `session.ended`
|
|
170
|
+
// bridge may sit later in the stream (or in a later source) than the
|
|
171
|
+
// `session.started` it names, and deciding mid-stream would mint a synthetic
|
|
172
|
+
// id for a session whose semantic id was two lines further on.
|
|
125
173
|
const semanticByUuid = new Map([...semanticFromEnded, ...semanticFromLock]);
|
|
126
174
|
|
|
127
|
-
const
|
|
175
|
+
const runningIds = readRunningSessionIds(repoRoot);
|
|
176
|
+
|
|
128
177
|
const plan = [];
|
|
129
|
-
for (const
|
|
130
|
-
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
plan.push({ sessionId
|
|
178
|
+
for (const sessionId of startedIds) {
|
|
179
|
+
const semanticSessionId = semanticByUuid.get(sessionId) ?? null;
|
|
180
|
+
if (runningIds.has(sessionId)
|
|
181
|
+
|| (semanticSessionId !== null && runningIds.has(semanticSessionId))) continue;
|
|
182
|
+
plan.push({ sessionId, semanticSessionId });
|
|
134
183
|
}
|
|
135
184
|
return plan;
|
|
136
185
|
}
|
|
137
186
|
|
|
187
|
+
/**
|
|
188
|
+
* Stream one JSONL file, handing every PARSED record to `onRecord` in file
|
|
189
|
+
* order — without ever holding the file in memory (#1414).
|
|
190
|
+
*
|
|
191
|
+
* MISSING (ENOENT) → silent no-op; UNREADABLE → a stderr WARN, same split as
|
|
192
|
+
* {@link readJsonl} (#1188: a missing ledger is the fresh-repo case, an
|
|
193
|
+
* unreadable one used to read as "no records" and made every count below
|
|
194
|
+
* silently wrong). Malformed lines are skipped, as in the full-read path.
|
|
195
|
+
*
|
|
196
|
+
* A line split across a chunk boundary is CARRIED as a BUFFER, so neither a
|
|
197
|
+
* record nor a multibyte character is ever cut in half — the 0x0A byte cannot
|
|
198
|
+
* occur inside a UTF-8 continuation sequence.
|
|
199
|
+
*
|
|
200
|
+
* @param {string} filePath
|
|
201
|
+
* @param {(record: object) => void} onRecord
|
|
202
|
+
*/
|
|
203
|
+
function forEachJsonlRecord(filePath, onRecord) {
|
|
204
|
+
const emit = (buf) => {
|
|
205
|
+
const text = buf.toString('utf8').trim();
|
|
206
|
+
if (!text) return;
|
|
207
|
+
try {
|
|
208
|
+
onRecord(JSON.parse(text));
|
|
209
|
+
} catch {
|
|
210
|
+
/* skip malformed */
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
let fd;
|
|
215
|
+
try {
|
|
216
|
+
fd = fs.openSync(filePath, 'r');
|
|
217
|
+
} catch (err) {
|
|
218
|
+
if (!err || err.code !== 'ENOENT') {
|
|
219
|
+
process.stderr.write(
|
|
220
|
+
`⚠ backfill-abandoned-sessions: cannot read ${filePath} ` +
|
|
221
|
+
`(${err?.code ?? '?'}: ${err?.message ?? String(err)}) — ` +
|
|
222
|
+
'treating as EMPTY, counts below are floors\n',
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
try {
|
|
228
|
+
const size = fs.fstatSync(fd).size;
|
|
229
|
+
const buf = Buffer.alloc(SCAN_CHUNK_BYTES);
|
|
230
|
+
let pos = 0;
|
|
231
|
+
let carry = Buffer.alloc(0);
|
|
232
|
+
while (pos < size) {
|
|
233
|
+
const n = fs.readSync(fd, buf, 0, SCAN_CHUNK_BYTES, pos);
|
|
234
|
+
if (n <= 0) break;
|
|
235
|
+
pos += n;
|
|
236
|
+
const block =
|
|
237
|
+
carry.length > 0
|
|
238
|
+
? Buffer.concat([carry, buf.subarray(0, n)])
|
|
239
|
+
: Buffer.from(buf.subarray(0, n));
|
|
240
|
+
let start = 0;
|
|
241
|
+
let idx = block.indexOf(0x0a, start);
|
|
242
|
+
while (idx !== -1) {
|
|
243
|
+
emit(block.subarray(start, idx));
|
|
244
|
+
start = idx + 1;
|
|
245
|
+
idx = block.indexOf(0x0a, start);
|
|
246
|
+
}
|
|
247
|
+
carry = block.subarray(start);
|
|
248
|
+
}
|
|
249
|
+
if (carry.length > 0) emit(carry);
|
|
250
|
+
} catch (err) {
|
|
251
|
+
process.stderr.write(
|
|
252
|
+
`⚠ backfill-abandoned-sessions: cannot read ${filePath} ` +
|
|
253
|
+
`(${err?.code ?? '?'}: ${err?.message ?? String(err)}) — ` +
|
|
254
|
+
'treating as EMPTY, counts below are floors\n',
|
|
255
|
+
);
|
|
256
|
+
} finally {
|
|
257
|
+
try {
|
|
258
|
+
fs.closeSync(fd);
|
|
259
|
+
} catch {
|
|
260
|
+
/* best-effort */
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* The id(s) naming the session THIS process is, when that session holds the
|
|
267
|
+
* live lock — else the empty set (#1376). Never throws: an unreadable lock,
|
|
268
|
+
* an absent one, or an env without any process-local id all degrade to "no
|
|
269
|
+
* exclusion", which is the pre-#1376 behaviour.
|
|
270
|
+
*
|
|
271
|
+
* @param {string} repoRoot
|
|
272
|
+
* @returns {Set<string>}
|
|
273
|
+
*/
|
|
274
|
+
function readRunningSessionIds(repoRoot) {
|
|
275
|
+
const ids = new Set();
|
|
276
|
+
try {
|
|
277
|
+
const lock = readLock({ repoRoot });
|
|
278
|
+
if (!lock || !isLockLive(lock)) return ids;
|
|
279
|
+
const lockIds = [lock.session_id, lock.semantic_session_id]
|
|
280
|
+
.filter((id) => typeof id === 'string' && id.length > 0);
|
|
281
|
+
const processLocal = new Set(readProcessLocalSessionIds());
|
|
282
|
+
// Conjunct 3 — only a PROCESS-LOCAL witness may promote the repo-global
|
|
283
|
+
// lock to "this is me". Membership is tested against the lock's ids, not
|
|
284
|
+
// the other way round, so an env var that happens to name some other
|
|
285
|
+
// session never widens the exclusion.
|
|
286
|
+
if (!lockIds.some((id) => processLocal.has(id))) return ids;
|
|
287
|
+
for (const id of lockIds) ids.add(id);
|
|
288
|
+
} catch {
|
|
289
|
+
/* readLock is no-throw by contract; the contract is not ours to trust */
|
|
290
|
+
}
|
|
291
|
+
return ids;
|
|
292
|
+
}
|
|
293
|
+
|
|
138
294
|
/**
|
|
139
295
|
* Cheap pre-filter (#926): the set of session ids ALREADY present in
|
|
140
296
|
* sessions.jsonl.
|
|
@@ -527,7 +683,7 @@ async function main() {
|
|
|
527
683
|
process.exit(0);
|
|
528
684
|
}
|
|
529
685
|
|
|
530
|
-
const isDirectRun =
|
|
686
|
+
const isDirectRun = isMainModule(import.meta.url);
|
|
531
687
|
if (isDirectRun) {
|
|
532
688
|
main().catch((err) => {
|
|
533
689
|
process.stderr.write(`backfill-abandoned-sessions: unexpected error: ${err?.stack ?? err}\n`);
|
|
@@ -50,6 +50,7 @@ import { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
|
50
50
|
import { join, relative, resolve } from 'node:path';
|
|
51
51
|
|
|
52
52
|
import { computeEvidenceDigest } from './lib/reconcile/renderer.mjs';
|
|
53
|
+
import { isMainModule } from './lib/is-main-module.mjs';
|
|
53
54
|
|
|
54
55
|
/** ISO-8601 instant — mirrors the renderer's `EVIDENCE_RECORDED_AT_RE`. */
|
|
55
56
|
const EVIDENCE_RECORDED_AT_RE = /^\d{4}-\d{2}-\d{2}T[0-9:.]+(?:Z|[+-]\d{2}:\d{2})$/;
|
|
@@ -373,4 +374,4 @@ function main(argv) {
|
|
|
373
374
|
process.exit(unsealable === 0 ? 0 : 1);
|
|
374
375
|
}
|
|
375
376
|
|
|
376
|
-
if (import.meta.url
|
|
377
|
+
if (isMainModule(import.meta.url)) main(process.argv.slice(2));
|