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/scripts/eval-session.mjs
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* Follows .claude/rules/cli-design.md:
|
|
9
9
|
* - `--json` for machine output; human-readable by default.
|
|
10
10
|
* - Data → stdout, diagnostics → stderr.
|
|
11
|
-
* - Exit codes: 0 success/match · 1 user-error/drift · 2 system error
|
|
11
|
+
* - Exit codes: 0 success/match · 1 user-error/drift · 2 system error ·
|
|
12
|
+
* 3 verify version-mismatch (non-standard, documented in --help).
|
|
12
13
|
*
|
|
13
14
|
* ## Append failures are NOT exit 0 (GitLab #969)
|
|
14
15
|
*
|
|
@@ -40,6 +41,17 @@
|
|
|
40
41
|
* Session-end Phase 3.7d remains advisory and MUST NOT gate on this exit code —
|
|
41
42
|
* it catches a non-zero exit and logs a WARN (skills/session-end/SKILL.md).
|
|
42
43
|
*
|
|
44
|
+
* ## A rubric change is not scoring drift (GitLab #1400)
|
|
45
|
+
*
|
|
46
|
+
* `--verify` re-scores a stored record with the CURRENT engine. When the stored
|
|
47
|
+
* `rubric_version` differs from `RUBRIC_VERSION`, the two sides answer different
|
|
48
|
+
* pre-registered check sets, so neither MATCH nor DRIFT is true: the run exits
|
|
49
|
+
* `3` with `verdict: "version-mismatch"` and re-scores nothing. Exit `0` would
|
|
50
|
+
* sell a cross-rubric comparison as a reproducibility proof; exit `1` would put
|
|
51
|
+
* a planned rubric bump in the same bucket as a forged record. Measured
|
|
52
|
+
* 2026-09-19: all 40 records in this repo's journal are `rubric-v1` and every
|
|
53
|
+
* one of them exited 1 as DRIFT under the rubric-v2 engine.
|
|
54
|
+
*
|
|
43
55
|
* Usage:
|
|
44
56
|
* eval-session.mjs [--session <id>] [--json] [--no-write]
|
|
45
57
|
* [--metrics-dir <path>] [--rubric <path>]
|
|
@@ -68,6 +80,8 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
68
80
|
const EXIT_OK = 0;
|
|
69
81
|
const EXIT_USER = 1;
|
|
70
82
|
const EXIT_SYSTEM = 2;
|
|
83
|
+
/** Non-standard, `--verify` only: the stored record predates the current rubric (#1400). */
|
|
84
|
+
const EXIT_VERSION_MISMATCH = 3;
|
|
71
85
|
|
|
72
86
|
function readPkgVersion() {
|
|
73
87
|
try {
|
|
@@ -103,6 +117,9 @@ EXIT CODES
|
|
|
103
117
|
1 user error (session not found, unknown run-id, record failed validation)
|
|
104
118
|
/ verify drift
|
|
105
119
|
2 system error (could not append the record to the eval journal)
|
|
120
|
+
3 verify version-mismatch: the stored record was scored under a different
|
|
121
|
+
rubric than ${RUBRIC_VERSION}, so it is not re-verifiable with this engine
|
|
122
|
+
(non-standard code — neither a match nor drift)
|
|
106
123
|
`;
|
|
107
124
|
|
|
108
125
|
function fail(exitCode, message) {
|
|
@@ -211,6 +228,49 @@ function runVerify(runId, values) {
|
|
|
211
228
|
fail(EXIT_USER, `--verify: run-id not found in eval journal: ${runId}`);
|
|
212
229
|
}
|
|
213
230
|
|
|
231
|
+
// #1400 — check the rubric BEFORE re-scoring. A record scored under another
|
|
232
|
+
// rubric answers a different pre-registered check set, so re-running the
|
|
233
|
+
// current engine over it produces a comparison nobody asked for. A record
|
|
234
|
+
// with no `rubric_version` at all is unattributable and counts as a mismatch.
|
|
235
|
+
const storedRubric = typeof stored.rubric_version === 'string' && stored.rubric_version
|
|
236
|
+
? stored.rubric_version
|
|
237
|
+
: null;
|
|
238
|
+
if (storedRubric !== RUBRIC_VERSION) {
|
|
239
|
+
// Deliberately NO diff of the dimensions the two rubrics share. Such a diff
|
|
240
|
+
// is technically possible but would carry almost no signal here. Measured
|
|
241
|
+
// 2026-09-19 over this repo's 40-record journal, replaying every record
|
|
242
|
+
// through `evaluateSession` + `diffDimensions`: all 40 differ on
|
|
243
|
+
// `process-safety` (its formula IS the v2 change) and all 40 gain a
|
|
244
|
+
// `present-in-fresh-only` `guard-friction`; restricted to the
|
|
245
|
+
// formula-unchanged dimensions, only 4 of 40 are byte-identical and the
|
|
246
|
+
// other 36 differ on `verification-evidence` / `gate-health` because the
|
|
247
|
+
// events they were scored from predate this journal's `events.jsonl`. So a
|
|
248
|
+
// "common dimensions" diff would re-report 90% of the journal as drift under
|
|
249
|
+
// a new name — the same misdirection in another shape (HR-101: a class that
|
|
250
|
+
// fires on ~90% of samples is a broken instrument, not a signal).
|
|
251
|
+
// Ceiling: holds while a rubric bump coincides with truncated evidence.
|
|
252
|
+
// Revisit-Trigger: the next rubric bump where every stored record's source
|
|
253
|
+
// events are still present — then a common-dimension diff carries signal.
|
|
254
|
+
if (values.json) {
|
|
255
|
+
writeStdoutLineSync(
|
|
256
|
+
JSON.stringify({
|
|
257
|
+
run_id: runId,
|
|
258
|
+
match: false,
|
|
259
|
+
verdict: 'version-mismatch',
|
|
260
|
+
stored_rubric_version: storedRubric,
|
|
261
|
+
engine_rubric_version: RUBRIC_VERSION,
|
|
262
|
+
}),
|
|
263
|
+
);
|
|
264
|
+
} else {
|
|
265
|
+
writeStdoutLineSync(
|
|
266
|
+
`VERSION-MISMATCH: ${runId} was scored under ${storedRubric ?? '(no rubric_version)'}; ` +
|
|
267
|
+
`this engine scores ${RUBRIC_VERSION} — not re-verifiable with this engine ` +
|
|
268
|
+
'(not drift, not a match).',
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
process.exit(EXIT_VERSION_MISMATCH);
|
|
272
|
+
}
|
|
273
|
+
|
|
214
274
|
let fresh;
|
|
215
275
|
try {
|
|
216
276
|
fresh = evaluateSession({
|
|
@@ -236,7 +296,9 @@ function runVerify(runId, values) {
|
|
|
236
296
|
|
|
237
297
|
if (diffs.length === 0) {
|
|
238
298
|
if (values.json) {
|
|
239
|
-
writeStdoutLineSync(
|
|
299
|
+
writeStdoutLineSync(
|
|
300
|
+
JSON.stringify({ run_id: runId, match: true, verdict: 'match', dimensions: fresh.dimensions.length }),
|
|
301
|
+
);
|
|
240
302
|
} else {
|
|
241
303
|
writeStdoutLineSync(`MATCH: ${runId} re-evaluates identically across ${fresh.dimensions.length} dimension(s).`);
|
|
242
304
|
}
|
|
@@ -244,7 +306,7 @@ function runVerify(runId, values) {
|
|
|
244
306
|
}
|
|
245
307
|
|
|
246
308
|
if (values.json) {
|
|
247
|
-
writeStdoutLineSync(JSON.stringify({ run_id: runId, match: false, diffs }));
|
|
309
|
+
writeStdoutLineSync(JSON.stringify({ run_id: runId, match: false, verdict: 'drift', diffs }));
|
|
248
310
|
} else {
|
|
249
311
|
const out = [`DRIFT: ${runId} re-evaluation differs from the stored record:`];
|
|
250
312
|
for (const d of diffs) {
|
|
@@ -63,6 +63,7 @@ import { parseSessionConfig } from './lib/config.mjs';
|
|
|
63
63
|
import { createSecretValueMasker } from './lib/secret-masker.mjs';
|
|
64
64
|
import { stableHostname, readHostAliases } from './lib/host-identity.mjs';
|
|
65
65
|
import { emitEvent, sessionAttribution } from './lib/events.mjs';
|
|
66
|
+
import { isMainModule } from './lib/is-main-module.mjs';
|
|
66
67
|
|
|
67
68
|
// Vault-relative default write target (Epic #774 — docs Public-Split removed
|
|
68
69
|
// the prior in-repo generated telemetry doc in favor of the private Meta-Vault).
|
|
@@ -724,7 +725,7 @@ export async function exportHwLearnings(opts) {
|
|
|
724
725
|
}
|
|
725
726
|
|
|
726
727
|
// Run as CLI when invoked directly
|
|
727
|
-
const isMain =
|
|
728
|
+
const isMain =isMainModule(import.meta.url);
|
|
728
729
|
if (isMain) {
|
|
729
730
|
const opts = parseArgs(process.argv.slice(2));
|
|
730
731
|
|
package/scripts/express-path.mjs
CHANGED
|
@@ -281,7 +281,7 @@ async function main() {
|
|
|
281
281
|
|
|
282
282
|
// The banner the coordinator echoes into the transcript — `/go` and
|
|
283
283
|
// session-plan's Express Path Short-Circuit both key off this EXACT line
|
|
284
|
-
// (`
|
|
284
|
+
// (`skills/go/SKILL.md` § Express Path Detection), so it is written verbatim,
|
|
285
285
|
// without the `express-path:` diagnostic prefix. Still stderr: stdout belongs
|
|
286
286
|
// to the verdict.
|
|
287
287
|
if (verdict.activated) {
|
|
@@ -26,6 +26,7 @@ import os from 'node:os';
|
|
|
26
26
|
import path from 'node:path';
|
|
27
27
|
|
|
28
28
|
import { validateWorkspacePath } from './lib/worktree/lifecycle.mjs';
|
|
29
|
+
import { isMainModule } from './lib/is-main-module.mjs';
|
|
29
30
|
|
|
30
31
|
// ---------------------------------------------------------------------------
|
|
31
32
|
// Constants
|
|
@@ -658,7 +659,7 @@ EXIT CODES
|
|
|
658
659
|
// CLI guard — prevents process.exit during test-time imports (#368)
|
|
659
660
|
// ---------------------------------------------------------------------------
|
|
660
661
|
|
|
661
|
-
if (import.meta.url
|
|
662
|
+
if (isMainModule(import.meta.url)) {
|
|
662
663
|
main().catch((err) => {
|
|
663
664
|
process.stderr.write(`gc-stale-worktrees: unexpected error: ${err?.stack ?? err}\n`);
|
|
664
665
|
process.exit(2);
|
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
* This generator writes two artefacts, both DERIVED and never hand-edited:
|
|
13
13
|
*
|
|
14
14
|
* 1. `AGENTS.md` — a BYTE-IDENTICAL copy of `CLAUDE.md`.
|
|
15
|
-
* 2. `.agents/skills/<name>/SKILL.md` — a portable mirror of each
|
|
16
|
-
*
|
|
15
|
+
* 2. `.agents/skills/<name>/SKILL.md` — a portable mirror of each skill and
|
|
16
|
+
* command (commands own overlapping names), carrying ONLY spec-legal
|
|
17
17
|
* frontmatter plus a pointer body (progressive disclosure — the mirror
|
|
18
|
-
* never duplicates the canonical instructions).
|
|
18
|
+
* never duplicates the canonical instructions). Native Codex invocation
|
|
19
|
+
* policy travels in an adjacent `agents/openai.yaml` when applicable.
|
|
19
20
|
*
|
|
20
21
|
* ## Why a generated copy and NOT a symlink (measured, not preferred)
|
|
21
22
|
*
|
|
@@ -53,6 +54,9 @@ import path from 'node:path';
|
|
|
53
54
|
import { fileURLToPath } from 'node:url';
|
|
54
55
|
import { execFileSync } from 'node:child_process';
|
|
55
56
|
import yaml from 'js-yaml';
|
|
57
|
+
import { isUserInvocableValue } from './lib/user-invocable-skills.mjs';
|
|
58
|
+
|
|
59
|
+
const POLICY_MARKER = '# Generated by scripts/generate-agents-skills.mjs; do not edit.\n';
|
|
56
60
|
|
|
57
61
|
/**
|
|
58
62
|
* The complete set of SKILL.md frontmatter keys agentskills.io permits outside
|
|
@@ -159,29 +163,40 @@ export function toPortableFrontmatter(source, skillName) {
|
|
|
159
163
|
*
|
|
160
164
|
* @param {string} skillName
|
|
161
165
|
* @param {Record<string, unknown>} portableFm
|
|
166
|
+
* @param {string} [canonical] plugin-relative source path; defaults to the skill
|
|
162
167
|
* @returns {string}
|
|
163
168
|
*/
|
|
164
|
-
export function renderMirror(skillName, portableFm) {
|
|
169
|
+
export function renderMirror(skillName, portableFm, canonical = `skills/${skillName}/SKILL.md`) {
|
|
165
170
|
const front = yaml.dump(portableFm, { lineWidth: -1, noRefs: true, quotingType: '"' });
|
|
166
|
-
const
|
|
167
|
-
|
|
171
|
+
const command = canonical.startsWith('commands/');
|
|
172
|
+
const lines = [
|
|
168
173
|
'---',
|
|
169
174
|
front.trimEnd(),
|
|
170
175
|
'---',
|
|
171
176
|
'',
|
|
172
177
|
`# ${skillName}`,
|
|
173
178
|
'',
|
|
174
|
-
`> **Portable mirror — generated, do not edit.** The canonical
|
|
179
|
+
`> **Portable mirror — generated, do not edit.** The canonical workflow lives at`,
|
|
175
180
|
`> [\`${canonical}\`](../../../${canonical}); read that file for the full instructions.`,
|
|
176
181
|
`> This mirror carries only agentskills.io-spec-legal frontmatter so harnesses that`,
|
|
177
182
|
`> discover skills under \`.agents/skills/\` can find and route to the skill.`,
|
|
178
183
|
'>',
|
|
179
184
|
'> Regenerate with `node scripts/generate-agents-skills.mjs`.',
|
|
180
185
|
'',
|
|
181
|
-
|
|
186
|
+
'Read the linked document in full and follow its complete workflow, including prechecks and stop conditions. Resolve its link relative to this SKILL.md, not the project working directory. The plugin root is three directories above this file. Resolve package paths such as `skills/` and `scripts/` from that root and relative links in the canonical document from its own directory. Keep the user’s project as the target of project operations.',
|
|
187
|
+
];
|
|
188
|
+
if (command || isUserInvocableValue(portableFm.metadata?.['user-invocable'])) lines.push(
|
|
189
|
+
'',
|
|
190
|
+
'`$ARGUMENTS` means the trailing user input after the selected command skill, or an empty string when absent. Preserve flags, quoted text, and Unicode as data. Do not perform global substitution in the command document, shell expansion on the argument string, or execution of that string as shell code. Pass command arguments through structured tool parameters or safely quoted individual arguments.',
|
|
191
|
+
);
|
|
192
|
+
if (command) lines.push(
|
|
193
|
+
'',
|
|
194
|
+
'Read the full command before invoking an internal skill. An instruction to invoke a skill (including `session-orchestrator:<name>` or the `Skill` tool) means read and follow the canonical `skills/<name>/SKILL.md` beneath the plugin root. Do not redispatch the public command adapter: a same-named command and internal skill are distinct documents, and redispatch would recurse.',
|
|
195
|
+
);
|
|
196
|
+
return [...lines, ''].join('\n');
|
|
182
197
|
}
|
|
183
198
|
|
|
184
|
-
/** Parse a
|
|
199
|
+
/** Parse a source's YAML frontmatter block; returns null when absent/unparseable. */
|
|
185
200
|
function readFrontmatter(absPath) {
|
|
186
201
|
const content = readFileSync(absPath, 'utf8');
|
|
187
202
|
const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
|
|
@@ -205,6 +220,44 @@ export function listSourceSkills(pluginRoot) {
|
|
|
205
220
|
.sort();
|
|
206
221
|
}
|
|
207
222
|
|
|
223
|
+
/** Union of canonical skills and commands, preserving command precedence. */
|
|
224
|
+
function listSourceEntries(pluginRoot) {
|
|
225
|
+
const sources = new Map(listSourceSkills(pluginRoot).map((name) => [name, `skills/${name}/SKILL.md`]));
|
|
226
|
+
const commands = path.join(pluginRoot, 'commands');
|
|
227
|
+
if (existsSync(commands) && statSync(commands).isDirectory()) {
|
|
228
|
+
for (const entry of readdirSync(commands, { withFileTypes: true })) {
|
|
229
|
+
if (!entry.isFile() || !entry.name.endsWith('.md') || /^[._]/.test(entry.name)) continue;
|
|
230
|
+
sources.set(entry.name.slice(0, -3), `commands/${entry.name}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return sources;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Match Codex policy precedence: command, native skill override, public skill. */
|
|
237
|
+
function invocationPolicy(pluginRoot, name, canonical, fm) {
|
|
238
|
+
if (!canonical.startsWith('commands/')) {
|
|
239
|
+
const nativePath = path.join(pluginRoot, 'skills', name, 'agents', 'openai.yaml');
|
|
240
|
+
if (existsSync(nativePath)) {
|
|
241
|
+
const native = yaml.load(readFileSync(nativePath, 'utf8'), { schema: yaml.CORE_SCHEMA });
|
|
242
|
+
const isRecord = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
243
|
+
if (!isRecord(native) || (Object.hasOwn(native, 'policy') && !isRecord(native.policy))) {
|
|
244
|
+
throw new Error(`${nativePath}: native skill metadata and policy must be mappings`);
|
|
245
|
+
}
|
|
246
|
+
if (native.policy && Object.hasOwn(native.policy, 'allow_implicit_invocation')) {
|
|
247
|
+
if (typeof native.policy.allow_implicit_invocation !== 'boolean') {
|
|
248
|
+
throw new Error(`${nativePath}: policy.allow_implicit_invocation must be a boolean`);
|
|
249
|
+
}
|
|
250
|
+
return native.policy.allow_implicit_invocation;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (!isUserInvocableValue(fm['user-invocable'], canonical)) return undefined;
|
|
254
|
+
}
|
|
255
|
+
if (Object.hasOwn(fm, 'disable-model-invocation') && typeof fm['disable-model-invocation'] !== 'boolean') {
|
|
256
|
+
throw new Error(`${canonical}: disable-model-invocation must be a boolean`);
|
|
257
|
+
}
|
|
258
|
+
return fm['disable-model-invocation'] !== true;
|
|
259
|
+
}
|
|
260
|
+
|
|
208
261
|
/**
|
|
209
262
|
* Is `AGENTS.md` already an alias of `CLAUDE.md` by construction?
|
|
210
263
|
*
|
|
@@ -268,34 +321,53 @@ export function generateAgentsSurface({ pluginRoot, check = false }) {
|
|
|
268
321
|
|
|
269
322
|
// --- Artefact 2: .agents/skills/<name>/SKILL.md ---------------------------
|
|
270
323
|
const mirrorRoot = path.join(pluginRoot, '.agents', 'skills');
|
|
271
|
-
const
|
|
324
|
+
const sources = listSourceEntries(pluginRoot);
|
|
325
|
+
const skills = [...sources.keys()].sort();
|
|
272
326
|
let files = 0;
|
|
273
327
|
let bytes = 0;
|
|
274
328
|
|
|
275
329
|
for (const name of skills) {
|
|
276
|
-
const
|
|
330
|
+
const canonical = sources.get(name);
|
|
331
|
+
const src = path.join(pluginRoot, canonical);
|
|
277
332
|
const fm = readFrontmatter(src);
|
|
278
333
|
if (fm === null) {
|
|
279
|
-
warnings.push(`${
|
|
334
|
+
warnings.push(`${canonical}: has no parseable frontmatter — skipped`);
|
|
280
335
|
continue;
|
|
281
336
|
}
|
|
282
337
|
const { fm: portable, warnings: w } = toPortableFrontmatter(fm, name);
|
|
283
338
|
warnings.push(...w);
|
|
284
|
-
const
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
339
|
+
const artifacts = new Map([['SKILL.md', renderMirror(name, portable, canonical)]]);
|
|
340
|
+
const policy = invocationPolicy(pluginRoot, name, canonical, fm);
|
|
341
|
+
const policyPath = path.join(mirrorRoot, name, 'agents', 'openai.yaml');
|
|
342
|
+
if (policy !== undefined) {
|
|
343
|
+
artifacts.set('agents/openai.yaml', POLICY_MARKER + yaml.dump({
|
|
344
|
+
interface: { display_name: name },
|
|
345
|
+
policy: { allow_implicit_invocation: policy },
|
|
346
|
+
}, { lineWidth: -1, noRefs: true }));
|
|
347
|
+
} else if (existsSync(policyPath) && readFileSync(policyPath, 'utf8').startsWith(POLICY_MARKER)) {
|
|
348
|
+
if (check) drift.push(`.agents/skills/${name}/agents/openai.yaml is obsolete`);
|
|
349
|
+
else {
|
|
350
|
+
rmSync(policyPath);
|
|
351
|
+
written.push(`removed .agents/skills/${name}/agents/openai.yaml`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
for (const [file, rendered] of artifacts) {
|
|
355
|
+
const relative = `.agents/skills/${name}/${file}`;
|
|
356
|
+
const dest = path.join(mirrorRoot, name, file);
|
|
357
|
+
files += 1;
|
|
358
|
+
bytes += Buffer.byteLength(rendered, 'utf8');
|
|
359
|
+
const current = existsSync(dest) ? readFileSync(dest, 'utf8') : null;
|
|
360
|
+
if (file === 'agents/openai.yaml' && current !== null && !current.startsWith(POLICY_MARKER)) {
|
|
361
|
+
drift.push(`${relative} conflicts with an unrelated native policy — retained`);
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
if (current === rendered) continue;
|
|
365
|
+
if (check) drift.push(`${relative} is ${current === null ? 'missing' : 'stale'}`);
|
|
366
|
+
else {
|
|
367
|
+
mkdirSync(path.dirname(dest), { recursive: true });
|
|
368
|
+
writeFileSync(dest, rendered, 'utf8');
|
|
369
|
+
written.push(relative);
|
|
370
|
+
}
|
|
299
371
|
}
|
|
300
372
|
}
|
|
301
373
|
|
|
@@ -306,7 +378,7 @@ export function generateAgentsSurface({ pluginRoot, check = false }) {
|
|
|
306
378
|
for (const entry of readdirSync(mirrorRoot, { withFileTypes: true })) {
|
|
307
379
|
if (!entry.isDirectory() || known.has(entry.name)) continue;
|
|
308
380
|
if (check) {
|
|
309
|
-
drift.push(`.agents/skills/${entry.name}/ is an orphan (no
|
|
381
|
+
drift.push(`.agents/skills/${entry.name}/ is an orphan (no skill or command source)`);
|
|
310
382
|
} else {
|
|
311
383
|
rmSync(path.join(mirrorRoot, entry.name), { recursive: true, force: true });
|
|
312
384
|
written.push(`removed .agents/skills/${entry.name}/`);
|
|
@@ -356,8 +428,9 @@ function main(argv) {
|
|
|
356
428
|
}
|
|
357
429
|
} else {
|
|
358
430
|
for (const w of result.warnings) process.stderr.write(` WARN: agents-surface: ${w}\n`);
|
|
431
|
+
for (const d of result.drift) process.stderr.write(`✗ agents-surface: ${d}\n`);
|
|
359
432
|
process.stdout.write(
|
|
360
|
-
`agents-surface: ${result.written.length} file(s) written, ${result.files}
|
|
433
|
+
`agents-surface: ${result.written.length} file(s) written, ${result.files} portable artefact(s), ${result.bytes} bytes\n`,
|
|
361
434
|
);
|
|
362
435
|
}
|
|
363
436
|
return result.ok ? 0 : 1;
|
|
@@ -9,6 +9,7 @@ import { dirname, join, resolve } from 'node:path';
|
|
|
9
9
|
import { fileURLToPath } from 'node:url';
|
|
10
10
|
import yaml from 'js-yaml';
|
|
11
11
|
import { toPortableFrontmatter } from './generate-agents-skills.mjs';
|
|
12
|
+
import { isUserInvocableValue } from './lib/user-invocable-skills.mjs';
|
|
12
13
|
|
|
13
14
|
const OUTPUT = '.codex-plugin/skills';
|
|
14
15
|
const MARKER = 'Generated by scripts/generate-codex-skills.mjs; do not edit.';
|
|
@@ -26,8 +27,19 @@ function validateFrontmatter(fm, name, path) {
|
|
|
26
27
|
if (typeof fm.description !== 'string' || !fm.description.trim() || fm.description.trim().length > 1024) {
|
|
27
28
|
fail('description must be a non-empty string of at most 1024 characters');
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
if (Object.hasOwn(fm, 'disable-model-invocation') && typeof fm['disable-model-invocation'] !== 'boolean') {
|
|
31
|
+
fail('disable-model-invocation must be a boolean');
|
|
32
|
+
}
|
|
33
|
+
// `user-invocable` is deliberately NOT a hard fail on a non-boolean: a quoted
|
|
34
|
+
// or cased value (`"true"`, `True`) used to crash this generator while the
|
|
35
|
+
// Cursor and Pi generators emitted a wrapper for it and the counters ignored
|
|
36
|
+
// it — four readings of one key. `isUserInvocableValue` is now the single
|
|
37
|
+
// normaliser; a value it cannot read as `true` demotes the skill (with its own
|
|
38
|
+
// WARN for the truthy-looking cases) instead of stopping the build.
|
|
39
|
+
if (Object.hasOwn(fm, 'user-invocable')
|
|
40
|
+
&& typeof fm['user-invocable'] !== 'boolean'
|
|
41
|
+
&& typeof fm['user-invocable'] !== 'string') {
|
|
42
|
+
fail('user-invocable must be a boolean (or the string form `"true"`/`"false"`)');
|
|
31
43
|
}
|
|
32
44
|
for (const key of ['argument-hint', 'license', 'compatibility']) {
|
|
33
45
|
if (Object.hasOwn(fm, key) && typeof fm[key] !== 'string') fail(`${key} must be a string`);
|
|
@@ -42,6 +54,19 @@ function validateFrontmatter(fm, name, path) {
|
|
|
42
54
|
}
|
|
43
55
|
}
|
|
44
56
|
|
|
57
|
+
/**
|
|
58
|
+
* The repo-wide marker for "operator-facing slash command" — delegated to
|
|
59
|
+
* `isUserInvocableValue`, the ONE normaliser, so this generator, the Cursor and
|
|
60
|
+
* Pi generators and the counters cannot disagree about a quoted or cased value.
|
|
61
|
+
*
|
|
62
|
+
* @param {Record<string, unknown>} fm
|
|
63
|
+
* @param {string} [path] named in the shared WARN when a truthy-looking value is demoted
|
|
64
|
+
* @returns {boolean}
|
|
65
|
+
*/
|
|
66
|
+
function isUserInvocable(fm, path) {
|
|
67
|
+
return isUserInvocableValue(fm?.['user-invocable'], path);
|
|
68
|
+
}
|
|
69
|
+
|
|
45
70
|
/** Existing native policy is meaningful; Claude's user-invocable flag is not a substitute. */
|
|
46
71
|
function readNativePolicy(root, name) {
|
|
47
72
|
const path = `skills/${name}/agents/openai.yaml`;
|
|
@@ -80,7 +105,14 @@ function readSources(root) {
|
|
|
80
105
|
try { fm = yaml.load(match[1], { schema: yaml.CORE_SCHEMA }); }
|
|
81
106
|
catch (error) { throw new Error(`${path}: invalid YAML: ${error.message}`, { cause: error }); }
|
|
82
107
|
validateFrontmatter(fm, name, path);
|
|
83
|
-
|
|
108
|
+
// Policy precedence for a skill: a native `agents/openai.yaml` wins; else
|
|
109
|
+
// an explicitly user-invocable skill (a slash command that used to be a
|
|
110
|
+
// `commands/*.md` file) derives it from `disable-model-invocation` exactly
|
|
111
|
+
// as command sources do; a library skill emits no policy.
|
|
112
|
+
const policy = command
|
|
113
|
+
? fm['disable-model-invocation'] !== true
|
|
114
|
+
: (readNativePolicy(root, name) ?? (isUserInvocable(fm, path) ? fm['disable-model-invocation'] !== true : undefined));
|
|
115
|
+
sources.push({ name, path, command, fm, policy });
|
|
84
116
|
}
|
|
85
117
|
}
|
|
86
118
|
return sources;
|
|
@@ -128,9 +160,21 @@ function renderSkill(source, warnings) {
|
|
|
128
160
|
'',
|
|
129
161
|
'Resolve this link relative to this SKILL.md, not the project working directory. The plugin root is three directories above this file. Resolve package paths such as `skills/` and `scripts/` from that root; resolve relative links inside the canonical document from its own directory. Keep the user’s project as the target of project operations.',
|
|
130
162
|
];
|
|
131
|
-
|
|
163
|
+
// `$ARGUMENTS` semantics belong to every OPERATOR-FACING document — a
|
|
164
|
+
// `commands/*.md`, and equally a skill that declares `user-invocable: true`
|
|
165
|
+
// and references `$ARGUMENTS` in its own body. Gating them on `source.command`
|
|
166
|
+
// alone silently dropped the argument-handling contract from every command
|
|
167
|
+
// body that was folded into its same-named skill.
|
|
168
|
+
if (source.command || isUserInvocable(source.fm)) lines.push(
|
|
132
169
|
'',
|
|
133
170
|
'`$ARGUMENTS` means the trailing user input after the selected command skill, or an empty string when absent. Preserve flags, quoted text, and Unicode as data. Do not perform global substitution in the command document, shell expansion on the argument string, or execution of that string as shell code. When the workflow needs a command, pass its arguments through structured tool parameters or safely quoted individual arguments.',
|
|
171
|
+
);
|
|
172
|
+
// The redispatch warning is only TRUE for a command source: it exists because
|
|
173
|
+
// a same-named command and internal skill are two distinct documents. A
|
|
174
|
+
// user-invocable SKILL is already the canonical document, so telling it not to
|
|
175
|
+
// redispatch "the public command adapter" would describe a file that does not
|
|
176
|
+
// exist.
|
|
177
|
+
if (source.command) lines.push(
|
|
134
178
|
'',
|
|
135
179
|
'Read the full command before invoking an internal skill. An instruction to invoke a skill (including `session-orchestrator:<name>` or the `Skill` tool) means read and follow the canonical `skills/<name>/SKILL.md` beneath the plugin root. Do not redispatch the public command adapter: a same-named command and internal skill are distinct documents, and redispatch would recurse.',
|
|
136
180
|
);
|