session-orchestrator 3.23.0 → 4.0.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 +18 -0
- package/.agents/skills/autopilot/SKILL.md +17 -0
- package/.agents/skills/bootstrap/SKILL.md +20 -0
- package/.agents/skills/brainstorm/SKILL.md +22 -0
- package/.agents/skills/claude-md-drift-check/SKILL.md +15 -0
- package/.agents/skills/convergence-monitoring/SKILL.md +22 -0
- package/.agents/skills/debug/SKILL.md +22 -0
- package/.agents/skills/discovery/SKILL.md +20 -0
- package/.agents/skills/dispatcher/SKILL.md +15 -0
- package/.agents/skills/docs-orchestrator/SKILL.md +18 -0
- package/.agents/skills/ecosystem-health/SKILL.md +20 -0
- package/.agents/skills/eli5/SKILL.md +20 -0
- package/.agents/skills/eval/SKILL.md +21 -0
- package/.agents/skills/evolve/SKILL.md +21 -0
- package/.agents/skills/frontmatter-guard/SKILL.md +15 -0
- package/.agents/skills/gitlab-ops/SKILL.md +20 -0
- package/.agents/skills/gitlab-portfolio/SKILL.md +15 -0
- package/.agents/skills/grill/SKILL.md +22 -0
- package/.agents/skills/hook-development/SKILL.md +15 -0
- package/.agents/skills/mcp-builder/SKILL.md +15 -0
- package/.agents/skills/memory-cleanup/SKILL.md +21 -0
- package/.agents/skills/mode-selector/SKILL.md +17 -0
- package/.agents/skills/npm-publish/SKILL.md +16 -0
- package/.agents/skills/peekaboo-driver/SKILL.md +18 -0
- package/.agents/skills/persona-panel/SKILL.md +17 -0
- package/.agents/skills/plan/SKILL.md +20 -0
- package/.agents/skills/playwright-driver/SKILL.md +20 -0
- package/.agents/skills/quality-gates/SKILL.md +20 -0
- package/.agents/skills/reconcile/SKILL.md +21 -0
- package/.agents/skills/remote-offload/SKILL.md +20 -0
- package/.agents/skills/repo-audit/SKILL.md +16 -0
- package/.agents/skills/session-end/SKILL.md +20 -0
- package/.agents/skills/session-plan/SKILL.md +20 -0
- package/.agents/skills/session-start/SKILL.md +20 -0
- package/.agents/skills/spinout/SKILL.md +16 -0
- package/.agents/skills/sunset-review/SKILL.md +16 -0
- package/.agents/skills/test-runner/SKILL.md +20 -0
- package/.agents/skills/tmux-layout/SKILL.md +21 -0
- package/.agents/skills/using-orchestrator/SKILL.md +17 -0
- package/.agents/skills/vault-mirror/SKILL.md +15 -0
- package/.agents/skills/vault-sync/SKILL.md +15 -0
- package/.agents/skills/wave-executor/SKILL.md +20 -0
- package/.agents/skills/write-executable-plan/SKILL.md +22 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/commands/autopilot.md +2 -2
- package/.cursor/commands/bootstrap.md +1 -1
- package/.cursor/commands/brainstorm.md +1 -1
- package/.cursor/commands/debug.md +1 -1
- package/.cursor/commands/discovery.md +1 -1
- package/.cursor/commands/dispatcher.md +2 -2
- package/.cursor/commands/eli5.md +2 -2
- package/.cursor/commands/eval.md +2 -2
- package/.cursor/commands/evolve.md +1 -1
- package/.cursor/commands/go.md +1 -1
- package/.cursor/commands/grill.md +2 -2
- package/.cursor/commands/memory-cleanup.md +2 -2
- package/.cursor/commands/persona-panel.md +1 -1
- package/.cursor/commands/plan.md +1 -1
- package/.cursor/commands/portfolio.md +1 -1
- package/.cursor/commands/reconcile.md +2 -2
- package/.cursor/commands/release.md +2 -2
- package/.cursor/commands/session.md +2 -2
- package/.cursor/commands/spinout.md +2 -2
- package/.cursor/commands/sunset-review.md +2 -2
- package/.cursor/commands/templates-ack.md +2 -2
- package/.cursor/commands/test.md +2 -2
- package/.cursor/skills/brainstorm/SKILL.md +1 -1
- package/.cursor/skills/eval/SKILL.md +1 -1
- package/.cursor/skills/quality-gates/SKILL.md +1 -1
- package/.cursor/skills/remote-offload/SKILL.md +13 -0
- package/.orchestrator/policy/blocked-commands.json +121 -0
- package/.orchestrator/policy/ecosystem.schema.json +66 -0
- package/.orchestrator/policy/quality-gates.example.json +16 -0
- package/.orchestrator/policy/quality-gates.schema.json +38 -0
- package/.orchestrator/policy/templates-policy.json +27 -0
- package/.orchestrator/policy/test-profiles.json +47 -0
- package/AGENTS.md +225 -0
- package/CHANGELOG.md +1401 -0
- package/NOTICE +11 -6
- package/README.md +127 -92
- package/agents/db-specialist.md +0 -1
- package/agents/eval-judge.md +1 -1
- package/agents/skill-applied-judge.md +1 -1
- package/assets/wave-lifecycle.svg +98 -0
- package/commands/release.md +6 -3
- package/commands/session.md +18 -3
- package/docs/README.md +4 -0
- package/{agents/AGENTS.md → docs/agent-authoring.md} +19 -26
- package/docs/baseline.md +67 -0
- package/docs/ci-setup.md +249 -48
- package/docs/codex-setup.md +66 -22
- package/docs/components.md +37 -16
- package/docs/cursor-setup.md +6 -2
- package/docs/events-schema.md +51 -10
- package/docs/instruction-delivery.md +62 -0
- package/{agents/memory-proposal-collector.md → docs/memory-proposal-flow.md} +1 -8
- package/docs/migration-v4.md +341 -0
- package/docs/pi-setup.md +6 -1
- package/docs/plugin-architecture-v3.md +1 -1
- package/docs/rule-authoring.md +85 -19
- package/docs/scope-collision-guard.md +8 -8
- package/docs/session-config-reference.md +120 -61
- package/docs/session-config-template.md +40 -33
- package/docs/telemetry/telemetry-claims.md +11 -10
- package/docs/telemetry.md +187 -4
- package/docs/vault-docs-architecture.md +50 -11
- package/hooks/_lib/atomic-json.mjs +111 -0
- package/hooks/_lib/hook-import-set.json +1487 -0
- package/hooks/_lib/subagent-paths.mjs +143 -0
- package/hooks/_lib/subagent-transcript.mjs +562 -0
- package/hooks/config-protection.mjs +2 -2
- package/hooks/cwd-change-restore.mjs +11 -31
- package/hooks/enforce-commands.mjs +69 -0
- package/hooks/enforce-scope.mjs +35 -6
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks-cursor.json +10 -0
- package/hooks/hooks-pi.json +5 -0
- package/hooks/hooks.json +6 -1
- package/hooks/loop-guard.mjs +3 -3
- package/hooks/on-session-end.mjs +280 -14
- package/hooks/on-session-start.mjs +153 -4
- package/hooks/on-stop.mjs +371 -17
- package/hooks/operator-steer.mjs +2 -2
- package/hooks/post-bash-write-verify.mjs +189 -4
- package/hooks/post-edit-import-probe.mjs +344 -0
- package/hooks/post-subagent-discovery-validator.mjs +278 -392
- package/hooks/post-tool-batch-wave-signal.mjs +272 -44
- package/hooks/post-tool-failure-corrective-context.mjs +11 -34
- package/hooks/post-tooluse-frontend-slop.mjs +3 -3
- package/hooks/pre-bash-destructive-guard.mjs +39 -13
- package/hooks/pre-bash-memory-propose-audit.mjs +13 -7
- package/hooks/skill-invocation-telemetry.mjs +17 -5
- package/hooks/subagent-telemetry.mjs +24 -30
- package/monitors/monitors.json +3 -3
- package/package.json +9 -1
- package/pi/prompts/session.md +2 -2
- package/plugin.json +27 -0
- package/scripts/autopilot.mjs +26 -12
- package/scripts/backfill-abandoned-sessions.mjs +130 -15
- package/scripts/backfill-learnings-from-vault.mjs +9 -3
- package/scripts/dialectic-deriver.mjs +73 -8
- package/scripts/emit-event.mjs +10 -2
- package/scripts/export-hw-learnings.mjs +113 -1
- package/scripts/generate-agents-skills.mjs +378 -0
- package/scripts/generate-cursor-adapter.mjs +45 -8
- package/scripts/generate-hook-import-set.mjs +249 -0
- package/scripts/lib/agent-status.mjs +13 -2
- package/scripts/lib/auq/parse.mjs +5 -29
- package/scripts/lib/auto-dialectic.mjs +68 -0
- package/scripts/lib/auto-dream.mjs +38 -36
- package/scripts/lib/autonomy/suitability.mjs +6 -0
- package/scripts/lib/autopilot/loop.mjs +2 -2
- package/scripts/lib/autopilot/worktree-pipeline.mjs +82 -6
- package/scripts/lib/build-live-signals.mjs +25 -22
- package/scripts/lib/ci-status-banner.mjs +220 -75
- package/scripts/lib/codex/plugin-contract.mjs +82 -6
- package/scripts/lib/cold-start-detector.mjs +23 -14
- package/scripts/lib/config/auto-dream.mjs +2 -1
- package/scripts/lib/config/block-header.mjs +63 -0
- package/scripts/lib/config/block-preprocess.mjs +177 -0
- package/scripts/lib/config/broken-window.mjs +2 -1
- package/scripts/lib/config/cold-start.mjs +2 -1
- package/scripts/lib/config/config-protection.mjs +22 -2
- package/scripts/lib/config/context-coverage.mjs +2 -1
- package/scripts/lib/config/cross-repo.mjs +2 -1
- package/scripts/lib/config/custom-phases.mjs +2 -1
- package/scripts/lib/config/dialectic.mjs +2 -1
- package/scripts/lib/config/discovery-validator.mjs +9 -3
- package/scripts/lib/config/dispatcher-autonomy-capture.mjs +24 -1
- package/scripts/lib/config/dispatcher-autonomy.mjs +2 -1
- package/scripts/lib/config/docs-orchestrator.mjs +2 -1
- package/scripts/lib/config/docs-staleness.mjs +2 -1
- package/scripts/lib/config/drift-check.mjs +2 -1
- package/scripts/lib/config/eval.mjs +2 -1
- package/scripts/lib/config/events-rotation.mjs +2 -1
- package/scripts/lib/config/evolve.mjs +8 -2
- package/scripts/lib/config/frontend-slop-hook.mjs +7 -3
- package/scripts/lib/config/gitlab-portfolio.mjs +2 -1
- package/scripts/lib/config/handover-gate.mjs +2 -1
- package/scripts/lib/config/health-endpoints.mjs +388 -0
- package/scripts/lib/config/issue-budget.mjs +2 -1
- package/scripts/lib/config/loop-guard.mjs +2 -1
- package/scripts/lib/config/memory.mjs +2 -1
- package/scripts/lib/config/moc-staleness.mjs +2 -1
- package/scripts/lib/config/persona-gate-wave.mjs +2 -1
- package/scripts/lib/config/private-config-dir.mjs +67 -0
- package/scripts/lib/config/reconcile.mjs +2 -1
- package/scripts/lib/config/remote-hosts.mjs +234 -0
- package/scripts/lib/config/section-extractor.mjs +7 -1
- package/scripts/lib/config/skill-evolution.mjs +2 -1
- package/scripts/lib/config/slopcheck.mjs +2 -1
- package/scripts/lib/config/state-md-lock.mjs +2 -1
- package/scripts/lib/config/templates-first.mjs +2 -1
- package/scripts/lib/config/test.mjs +2 -1
- package/scripts/lib/config/vault-integration.mjs +7 -1
- package/scripts/lib/config/vault-mirror-quality.mjs +2 -1
- package/scripts/lib/config/vault-staleness.mjs +2 -1
- package/scripts/lib/config/vault-sync.mjs +2 -1
- package/scripts/lib/config/verification-auto-fix.mjs +2 -1
- package/scripts/lib/config/wave-reviewers.mjs +2 -1
- package/scripts/lib/config/worktree-orphans.mjs +2 -1
- package/scripts/lib/config.mjs +31 -3
- package/scripts/lib/convergence-monitor.mjs +82 -16
- package/scripts/lib/dispatcher/enumerate.mjs +2 -17
- package/scripts/lib/dispatcher/rank.mjs +124 -48
- package/scripts/lib/ecosystem-health.mjs +16 -2
- package/scripts/lib/eval/engine.mjs +9 -1
- package/scripts/lib/eval/session-resolve.mjs +23 -4
- package/scripts/lib/events-schema.mjs +48 -0
- package/scripts/lib/events.mjs +256 -7
- package/scripts/lib/evolve/autonomy-verdict.mjs +9 -4
- package/scripts/lib/evolve/autopilot-effectiveness.mjs +18 -1
- package/scripts/lib/frontmatter-guard.mjs +131 -13
- package/scripts/lib/gates/gate-full.mjs +26 -0
- package/scripts/lib/gates/gate-helpers.mjs +76 -0
- package/scripts/lib/gitlab-portfolio/cli.mjs +3 -15
- package/scripts/lib/hardware-pattern-detector.mjs +18 -1
- package/scripts/lib/harness-audit/categories/category1.mjs +17 -6
- package/scripts/lib/harness-audit/categories/category4.mjs +31 -11
- package/scripts/lib/host-identity.mjs +50 -11
- package/scripts/lib/instruction-budget-guard.mjs +171 -5
- package/scripts/lib/learnings/evolve-telemetry.mjs +178 -0
- package/scripts/lib/learnings/io.mjs +60 -6
- package/scripts/lib/memory-banner.mjs +20 -8
- package/scripts/lib/memory-proposals/store.mjs +30 -22
- package/scripts/lib/owner-config-banner.mjs +43 -6
- package/scripts/lib/owner-config-loader.mjs +21 -10
- package/scripts/lib/owner-interview.mjs +3 -3
- package/scripts/lib/owner-yaml.mjs +207 -14
- package/scripts/lib/peer-discovery.mjs +20 -2
- package/scripts/lib/platform.mjs +108 -15
- package/scripts/lib/plugin-update-banner.mjs +406 -0
- package/scripts/lib/project-hygiene.mjs +38 -2
- package/scripts/lib/qg-command-drift-banner.mjs +50 -12
- package/scripts/lib/quality-gate.mjs +133 -44
- package/scripts/lib/reconcile/emitter.mjs +68 -6
- package/scripts/lib/reconcile/engine.mjs +249 -9
- package/scripts/lib/reconcile/idempotency.mjs +37 -4
- package/scripts/lib/reconcile/writer.mjs +40 -18
- package/scripts/lib/scope-gate.mjs +36 -0
- package/scripts/lib/session-close-backfill.mjs +125 -18
- package/scripts/lib/session-discovery.mjs +57 -3
- package/scripts/lib/session-end/phase-skip.mjs +2 -2
- package/scripts/lib/session-id.mjs +12 -23
- package/scripts/lib/session-identity/own-session.mjs +187 -11
- package/scripts/lib/session-lock-shape.mjs +43 -0
- package/scripts/lib/session-lock.mjs +5 -10
- package/scripts/lib/session-registry.mjs +25 -9
- package/scripts/lib/session-schema/constants.mjs +36 -2
- package/scripts/lib/session-schema/validator.mjs +38 -4
- package/scripts/lib/session-start-probes.mjs +18 -1
- package/scripts/lib/session-transition.mjs +1 -1
- package/scripts/lib/sessions-canonical.mjs +446 -0
- package/scripts/lib/sessions-staleness-banner.mjs +18 -11
- package/scripts/lib/skill-health/join.mjs +17 -4
- package/scripts/lib/state-md.mjs +78 -0
- package/scripts/lib/sunset/walker.mjs +6 -0
- package/scripts/lib/telemetry/schema.mjs +255 -17
- package/scripts/lib/telemetry/sync.mjs +417 -24
- package/scripts/lib/tmux-layout/telemetry.mjs +14 -2
- package/scripts/lib/validate/check-agents-skills.mjs +327 -0
- package/scripts/lib/validate/check-agents.mjs +3 -3
- package/scripts/lib/validate/check-cursor-adapter.mjs +234 -72
- package/scripts/lib/validate/check-doc-cli-commands.mjs +9 -33
- package/scripts/lib/validate/check-hooks-emit-event-guard.mjs +370 -0
- package/scripts/lib/validate/check-hooks-symmetry.mjs +45 -16
- package/scripts/lib/validate/check-owner-leakage.mjs +281 -20
- package/scripts/lib/validate/check-skill-links.mjs +163 -0
- package/scripts/lib/validate/check-skill-script-paths.mjs +455 -0
- package/scripts/lib/validate/check-untracked-test-deps.mjs +10 -0
- package/scripts/lib/validate/check-unwired-features.mjs +0 -9
- package/scripts/lib/validate/check-validator-registration.mjs +254 -0
- package/scripts/lib/validate/check-vcs-repo-flag.mjs +6 -28
- package/scripts/lib/validate/enumerate-repo-files.mjs +317 -0
- package/scripts/lib/validate/markdown-fences.mjs +196 -0
- package/scripts/lib/vault-backfill/template.mjs +63 -6
- package/scripts/lib/vault-mirror/process.mjs +165 -42
- package/scripts/lib/vault-mirror/telemetry.mjs +2 -2
- package/scripts/lib/vault-status/board-lock.mjs +185 -0
- package/scripts/lib/vault-status/board-writer.mjs +174 -135
- package/scripts/lib/vault-status/narrative-mirror.mjs +129 -37
- package/scripts/lib/wave-executor/dispatch-common.mjs +164 -0
- package/scripts/lib/wave-executor/foreign-dispatch.mjs +7 -142
- package/scripts/lib/wave-executor/remote-dispatch.mjs +502 -0
- package/scripts/lib/wave-resource-gate.mjs +133 -7
- package/scripts/lib/wave-sizing.mjs +4 -1
- package/scripts/lib/wave-transcript-tail.mjs +142 -8
- package/scripts/materialize-wave-scope.mjs +32 -9
- package/scripts/memory-propose.mjs +146 -8
- package/scripts/migrate-cold-start-seed.mjs +4 -1
- package/scripts/parse-config.mjs +60 -3
- package/scripts/promote-vault-strict.mjs +4 -15
- package/scripts/release.mjs +337 -29
- package/scripts/repair-invalid-sessions.mjs +3 -3
- package/scripts/run-quality-gate.mjs +128 -11
- package/scripts/site-numbers.mjs +36 -4
- package/scripts/sweep-expired-learnings.mjs +90 -0
- package/scripts/sync-vault-schema.mjs +3 -1
- package/scripts/telemetry.mjs +2 -2
- package/scripts/validate-plugin.mjs +187 -0
- package/scripts/validate-wave-scope.mjs +28 -8
- package/scripts/vault-consolidate.mjs +3 -11
- package/scripts/vault-integration-watcher.mjs +2 -4
- package/scripts/vault-mirror.mjs +111 -26
- package/scripts/wave-scope-binding.mjs +215 -0
- package/skills/_shared/instruction-file-resolution.md +10 -0
- package/skills/_shared/parallel-aware-auq.md +31 -2
- package/skills/_shared/parallel-aware-preamble.md +18 -4
- package/skills/_shared/platform-tools.md +1 -1
- package/skills/_shared/state-ownership.md +1 -1
- package/skills/architecture/SKILL.md +7 -5
- package/skills/{domain-model/SKILL.md → architecture/references/domain-model.md} +9 -9
- package/skills/autopilot/SKILL.md +4 -18
- package/skills/claude-md-drift-check/SKILL.md +5 -1
- package/skills/claude-md-drift-check/checker.mjs +62 -2
- package/skills/convergence-monitoring/SIGNALS.md +55 -0
- package/skills/discovery/probes/vault-staleness.mjs +37 -13
- package/skills/discovery/probes-arch.md +20 -18
- package/skills/dispatcher/SKILL.md +3 -2
- package/skills/ecosystem-health/SKILL.md +4 -1
- package/skills/ecosystem-health/wizard.md +5 -0
- package/skills/evolve/SKILL.md +87 -11
- package/skills/frontmatter-guard/SKILL.md +11 -5
- package/skills/npm-publish/SKILL.md +1 -1
- package/skills/reconcile/SKILL.md +38 -2
- package/skills/remote-offload/SKILL.md +89 -0
- package/skills/session-end/SKILL.md +18 -905
- package/skills/session-end/phase-3-6-tail.md +19 -9
- package/skills/session-end/plan-verification.md +221 -155
- package/skills/session-end/references/phase-2-quality-gate.md +93 -0
- package/skills/session-end/references/phase-3-documentation-updates.md +229 -0
- package/skills/session-end/references/phase-4a-worktree-cleanup.md +120 -0
- package/skills/session-end/references/phase-4b-worktree-orphan-sweep.md +58 -0
- package/skills/session-end/references/phase-5-issue-cleanup.md +104 -0
- package/skills/session-end/references/session-summary-template.md +62 -0
- package/skills/session-plan/SKILL.md +49 -0
- package/skills/session-start/SKILL.md +41 -900
- package/skills/session-start/phase-8-5-express-path.md +1 -1
- package/skills/session-start/references/phase-1-1-dispatcher-autonomy-capture.md +55 -0
- package/skills/session-start/references/phase-1-2-session-lock.md +140 -0
- package/skills/session-start/references/phase-1-5-session-continuity.md +254 -0
- package/skills/session-start/references/phase-1-7-vault-status-board.md +53 -0
- package/skills/session-start/references/phase-2-7-portfolio-snapshot.md +75 -0
- package/skills/session-start/references/phase-4-ssot-environment-check.md +155 -0
- package/skills/session-start/references/phase-6-5-forced-reads.md +75 -0
- package/skills/session-start/references/phase-6-6-project-intelligence.md +81 -0
- package/skills/session-start/references/phase-6-7-memory-banner-telemetry-consent.md +103 -0
- package/skills/vault-sync/validator.mjs +21 -27
- package/skills/wave-executor/SKILL.md +16 -2
- package/skills/wave-executor/references/wave-loop-dispatch.md +612 -0
- package/skills/wave-executor/references/wave-loop-review.md +570 -0
- package/skills/wave-executor/references/wave-loop-scope-manifest.md +162 -0
- package/skills/wave-executor/wave-loop.md +14 -1271
- package/templates/_shared/journey-manifest.md +10 -6
- package/.cursor/commands/autopilot-multi.md +0 -14
- package/.cursor/commands/contract-version-bump.md +0 -14
- package/.cursor/commands/journey-audit.md +0 -14
- package/.cursor/skills/contract-version-bump/SKILL.md +0 -12
- package/.cursor/skills/daily/SKILL.md +0 -12
- package/.cursor/skills/domain-model/SKILL.md +0 -13
- package/.cursor/skills/journey-audit/SKILL.md +0 -13
- package/.cursor/skills/skill-creator/SKILL.md +0 -13
- package/.cursor/skills/ubiquitous-language/SKILL.md +0 -13
- package/commands/autopilot-multi.md +0 -74
- package/commands/contract-version-bump.md +0 -28
- package/commands/journey-audit.md +0 -43
- package/pi/prompts/autopilot-multi.md +0 -12
- package/pi/prompts/contract-version-bump.md +0 -12
- package/pi/prompts/journey-audit.md +0 -12
- package/scripts/autopilot-multi.mjs +0 -885
- package/scripts/backfill-learnings-expires.mjs +0 -196
- package/scripts/backfill-learnings.mjs +0 -203
- package/scripts/fleet-instruction-scan.mjs +0 -141
- package/scripts/lib/autopilot/dep-graph.mjs +0 -417
- package/scripts/lib/autopilot/multi-killswitch.mjs +0 -184
- package/scripts/lib/webhook-url.mjs +0 -105
- package/scripts/lifecycle-sim-v6.mjs +0 -347
- package/scripts/migrate-learnings-jsonl.mjs +0 -189
- package/scripts/migrate-subagents-jsonl.mjs +0 -196
- package/scripts/upload-social-preview.mjs +0 -316
- package/skills/_shared/model-selection.md +0 -64
- package/skills/contract-version-bump/SKILL.md +0 -219
- package/skills/daily/SKILL.md +0 -222
- package/skills/daily/generate.sh +0 -92
- package/skills/daily/templates/daily.md.tpl +0 -36
- package/skills/journey-audit/SKILL.md +0 -269
- package/skills/skill-creator/SKILL.md +0 -168
- package/skills/ubiquitous-language/SKILL.md +0 -97
- package/skills/vault-sync/package-lock.json +0 -40
- /package/skills/{domain-model → architecture/references}/ADR-FORMAT.md +0 -0
- /package/skills/{domain-model → architecture/references}/CONTEXT-FORMAT.md +0 -0
|
@@ -4,99 +4,261 @@
|
|
|
4
4
|
// Exit 0 = all checks passed, 1 = at least one failure.
|
|
5
5
|
|
|
6
6
|
import { spawnSync } from 'node:child_process';
|
|
7
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
8
|
-
import { join } from 'node:path';
|
|
7
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
8
|
+
import { join, relative } from 'node:path';
|
|
9
|
+
import { pathToFileURL } from 'node:url';
|
|
10
|
+
|
|
11
|
+
import yaml from 'js-yaml';
|
|
9
12
|
|
|
10
13
|
import { CURSOR_TO_CANONICAL_EVENT } from '../cursor-hook-bridge.mjs';
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
console.error('Usage: check-cursor-adapter.mjs <plugin-root>');
|
|
15
|
-
process.exit(1);
|
|
16
|
-
}
|
|
15
|
+
/** agentskills.io caps a skill/command description at 1024 characters. */
|
|
16
|
+
const DESCRIPTION_MAX = 1024;
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
encoding: 'utf8',
|
|
33
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
34
|
-
});
|
|
35
|
-
if (result.status === 0) {
|
|
36
|
-
pass('.cursor/commands and .cursor/skills are up to date with commands/ and skills/');
|
|
37
|
-
} else {
|
|
38
|
-
const detail = ((result.stdout ?? '') + (result.stderr ?? '')).trim();
|
|
39
|
-
fail(`Cursor adapter wrappers are stale${detail ? `: ${detail}` : ''}`);
|
|
18
|
+
/**
|
|
19
|
+
* Locate a top-level frontmatter key's line number (1-based) so a violation can
|
|
20
|
+
* be reported as `file:line` rather than `file`.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} content raw file content
|
|
23
|
+
* @param {string} key frontmatter key
|
|
24
|
+
* @returns {number} 1-based line number, or 1 when the key is absent
|
|
25
|
+
*/
|
|
26
|
+
function frontmatterKeyLine(content, key) {
|
|
27
|
+
const lines = content.split('\n');
|
|
28
|
+
const needle = new RegExp(`^${key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*:`);
|
|
29
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
30
|
+
if (i > 0 && lines[i] === '---') break; // end of frontmatter
|
|
31
|
+
if (needle.test(lines[i])) return i + 1;
|
|
40
32
|
}
|
|
33
|
+
return 1;
|
|
41
34
|
}
|
|
42
35
|
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Validate ONE generated artefact's frontmatter against the Cursor/agentskills
|
|
38
|
+
* spec, independent of the generator that produced it.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} filePath absolute path to the artefact
|
|
41
|
+
* @param {string} rel path to report violations against
|
|
42
|
+
* @param {{requireName: boolean}} opts
|
|
43
|
+
* @returns {string[]} violation strings, empty when the artefact is conformant
|
|
44
|
+
*/
|
|
45
|
+
function validateArtefactFrontmatter(filePath, rel, { requireName }) {
|
|
46
|
+
const violations = [];
|
|
47
|
+
const content = readFileSync(filePath, 'utf8');
|
|
48
|
+
|
|
49
|
+
if (!content.startsWith('---\n')) {
|
|
50
|
+
return [`${rel}:1 — no YAML frontmatter block (file must start with '---')`];
|
|
51
|
+
}
|
|
52
|
+
const end = content.indexOf('\n---\n', 3);
|
|
53
|
+
if (end === -1) {
|
|
54
|
+
return [`${rel}:1 — frontmatter block is never closed`];
|
|
55
|
+
}
|
|
45
56
|
|
|
46
|
-
|
|
47
|
-
if (!existsSync(hooksPath)) {
|
|
48
|
-
fail('.cursor/hooks.json exists');
|
|
49
|
-
} else {
|
|
50
|
-
let hooksJson;
|
|
57
|
+
let fm;
|
|
51
58
|
try {
|
|
52
|
-
|
|
53
|
-
pass('.cursor/hooks.json is valid JSON');
|
|
59
|
+
fm = yaml.load(content.slice(4, end + 1), { schema: yaml.CORE_SCHEMA });
|
|
54
60
|
} catch (err) {
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
return [`${rel}:1 — frontmatter is not parseable YAML: ${err.message.split('\n')[0]}`];
|
|
62
|
+
}
|
|
63
|
+
if (fm === null || typeof fm !== 'object' || Array.isArray(fm)) {
|
|
64
|
+
return [`${rel}:1 — frontmatter does not parse to a mapping`];
|
|
57
65
|
}
|
|
58
66
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
// `argument-hint`, when present, MUST be a string. Its canonical authored
|
|
68
|
+
// form is `[mode] [--flag]`, which YAML reads as a flow SEQUENCE unless the
|
|
69
|
+
// generator quotes it — GH#54, which made Copilot CLI >= 1.0.65 silently drop
|
|
70
|
+
// the file. Type, not presence, is the assertion: an array here is the bug.
|
|
71
|
+
if (Object.hasOwn(fm, 'argument-hint')) {
|
|
72
|
+
const hint = fm['argument-hint'];
|
|
73
|
+
if (typeof hint !== 'string') {
|
|
74
|
+
violations.push(
|
|
75
|
+
`${rel}:${frontmatterKeyLine(content, 'argument-hint')} — argument-hint must be a string, got ${Array.isArray(hint) ? 'array' : typeof hint} (GH#54: an unquoted [a] [b] is a YAML flow sequence)`,
|
|
76
|
+
);
|
|
77
|
+
} else if (hint.trim() === '') {
|
|
78
|
+
violations.push(`${rel}:${frontmatterKeyLine(content, 'argument-hint')} — argument-hint is present but empty`);
|
|
64
79
|
}
|
|
80
|
+
}
|
|
65
81
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
82
|
+
const required = requireName ? ['name', 'description'] : ['description'];
|
|
83
|
+
for (const key of required) {
|
|
84
|
+
const value = fm[key];
|
|
85
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
86
|
+
violations.push(
|
|
87
|
+
`${rel}:${frontmatterKeyLine(content, key)} — ${key} must be a non-empty string, got ${value === undefined ? 'nothing' : (Array.isArray(value) ? 'array' : typeof value)}`,
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (typeof fm.description === 'string' && fm.description.length > DESCRIPTION_MAX) {
|
|
93
|
+
violations.push(
|
|
94
|
+
`${rel}:${frontmatterKeyLine(content, 'description')} — description is ${fm.description.length} chars, over the ${DESCRIPTION_MAX} limit (agentskills.io)`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return violations;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Validate every generated Cursor artefact under `<pluginRoot>/.cursor`.
|
|
103
|
+
*
|
|
104
|
+
* This deliberately does NOT run the generator. Comparing generator output to
|
|
105
|
+
* generator output — which is all `--check` does — cannot see a defect the
|
|
106
|
+
* generator itself emits: it would report "up to date" while every file is
|
|
107
|
+
* broken, and a snapshot-style guard would freeze the broken files as the
|
|
108
|
+
* expectation. This reads the artefacts and judges them against the spec.
|
|
109
|
+
*
|
|
110
|
+
* @param {string} pluginRoot
|
|
111
|
+
* @returns {{files: number, violations: string[]}}
|
|
112
|
+
*/
|
|
113
|
+
export function validateCursorArtefacts(pluginRoot) {
|
|
114
|
+
const violations = [];
|
|
115
|
+
let files = 0;
|
|
116
|
+
|
|
117
|
+
const commandsDir = join(pluginRoot, '.cursor', 'commands');
|
|
118
|
+
if (existsSync(commandsDir)) {
|
|
119
|
+
for (const name of readdirSync(commandsDir).filter((n) => n.endsWith('.md')).sort()) {
|
|
120
|
+
const filePath = join(commandsDir, name);
|
|
121
|
+
files += 1;
|
|
122
|
+
violations.push(
|
|
123
|
+
...validateArtefactFrontmatter(filePath, relative(pluginRoot, filePath), { requireName: false }),
|
|
124
|
+
);
|
|
75
125
|
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const skillsDir = join(pluginRoot, '.cursor', 'skills');
|
|
129
|
+
if (existsSync(skillsDir)) {
|
|
130
|
+
for (const name of readdirSync(skillsDir).sort()) {
|
|
131
|
+
const filePath = join(skillsDir, name, 'SKILL.md');
|
|
132
|
+
let isDir;
|
|
133
|
+
try { isDir = statSync(join(skillsDir, name)).isDirectory(); } catch { isDir = false; }
|
|
134
|
+
if (!isDir || !existsSync(filePath)) continue;
|
|
135
|
+
files += 1;
|
|
136
|
+
violations.push(
|
|
137
|
+
...validateArtefactFrontmatter(filePath, relative(pluginRoot, filePath), { requireName: true }),
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return { files, violations };
|
|
143
|
+
}
|
|
76
144
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
145
|
+
/**
|
|
146
|
+
* CLI entry point. Kept behind a direct-invocation guard so the module can be
|
|
147
|
+
* imported for {@link validateCursorArtefacts} without running (and exiting).
|
|
148
|
+
*
|
|
149
|
+
* @param {string|undefined} pluginRoot
|
|
150
|
+
* @returns {never}
|
|
151
|
+
*/
|
|
152
|
+
function runCli(pluginRoot) {
|
|
153
|
+
if (!pluginRoot) {
|
|
154
|
+
console.error('Usage: check-cursor-adapter.mjs <plugin-root>');
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let passed = 0;
|
|
159
|
+
let failed = 0;
|
|
160
|
+
|
|
161
|
+
function pass(msg) { console.log(` PASS: ${msg}`); passed += 1; }
|
|
162
|
+
function fail(msg) { console.log(` FAIL: ${msg}`); failed += 1; }
|
|
163
|
+
|
|
164
|
+
console.log('--- Check 1: generated Cursor command and skill wrappers ---');
|
|
165
|
+
|
|
166
|
+
const generator = join(pluginRoot, 'scripts', 'generate-cursor-adapter.mjs');
|
|
167
|
+
if (!existsSync(generator)) {
|
|
168
|
+
fail('scripts/generate-cursor-adapter.mjs exists');
|
|
169
|
+
} else {
|
|
170
|
+
const result = spawnSync(process.execPath, [generator, '--check'], {
|
|
171
|
+
cwd: pluginRoot,
|
|
172
|
+
encoding: 'utf8',
|
|
173
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
81
174
|
});
|
|
82
|
-
if (
|
|
83
|
-
pass('.cursor/
|
|
175
|
+
if (result.status === 0) {
|
|
176
|
+
pass('.cursor/commands and .cursor/skills are up to date with commands/ and skills/');
|
|
84
177
|
} else {
|
|
85
|
-
|
|
178
|
+
const detail = ((result.stdout ?? '') + (result.stderr ?? '')).trim();
|
|
179
|
+
fail(`Cursor adapter wrappers are stale${detail ? `: ${detail}` : ''}`);
|
|
86
180
|
}
|
|
87
181
|
}
|
|
88
|
-
}
|
|
89
182
|
|
|
90
|
-
console.log('');
|
|
91
|
-
console.log('--- Check
|
|
183
|
+
console.log('');
|
|
184
|
+
console.log('--- Check 1b: generated artefacts conform to the frontmatter spec ---');
|
|
185
|
+
|
|
186
|
+
// Check 1 above runs the generator against its own output. That comparison is
|
|
187
|
+
// structurally blind to a defect the generator EMITS — it reported "up to
|
|
188
|
+
// date" while 24 of 28 command wrappers carried an array-shaped
|
|
189
|
+
// `argument-hint` (GH#54). Check 1b judges the artefacts against the spec
|
|
190
|
+
// instead, so a generator bug surfaces as a failure rather than as a snapshot.
|
|
191
|
+
const { files: artefactCount, violations } = validateCursorArtefacts(pluginRoot);
|
|
192
|
+
if (violations.length === 0) {
|
|
193
|
+
pass(`${artefactCount} generated Cursor artefact(s) have spec-conformant frontmatter`);
|
|
194
|
+
} else {
|
|
195
|
+
for (const violation of violations) process.stderr.write(`FAIL: ${violation}\n`);
|
|
196
|
+
fail(`${violations.length} generated Cursor artefact(s) violate the frontmatter spec (see stderr for file:line)`);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
console.log('');
|
|
200
|
+
console.log('--- Check 2: .cursor/hooks.json native manifest ---');
|
|
201
|
+
|
|
202
|
+
const hooksPath = join(pluginRoot, '.cursor', 'hooks.json');
|
|
203
|
+
if (!existsSync(hooksPath)) {
|
|
204
|
+
fail('.cursor/hooks.json exists');
|
|
205
|
+
} else {
|
|
206
|
+
let hooksJson;
|
|
207
|
+
try {
|
|
208
|
+
hooksJson = JSON.parse(readFileSync(hooksPath, 'utf8'));
|
|
209
|
+
pass('.cursor/hooks.json is valid JSON');
|
|
210
|
+
} catch (err) {
|
|
211
|
+
fail(`.cursor/hooks.json is not valid JSON: ${err.message}`);
|
|
212
|
+
hooksJson = null;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (hooksJson) {
|
|
216
|
+
if (hooksJson.version === 1) {
|
|
217
|
+
pass('.cursor/hooks.json version is 1');
|
|
218
|
+
} else {
|
|
219
|
+
fail('.cursor/hooks.json version must be 1');
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const declared = Object.keys(hooksJson.hooks || {});
|
|
223
|
+
const expected = Object.keys(CURSOR_TO_CANONICAL_EVENT);
|
|
224
|
+
const missing = expected.filter((event) => !declared.includes(event));
|
|
225
|
+
const extra = declared.filter((event) => !expected.includes(event));
|
|
226
|
+
if (missing.length === 0 && extra.length === 0) {
|
|
227
|
+
pass(`.cursor/hooks.json events match CURSOR_TO_CANONICAL_EVENT (${expected.length})`);
|
|
228
|
+
} else {
|
|
229
|
+
if (missing.length > 0) fail(`.cursor/hooks.json missing events: ${missing.join(', ')}`);
|
|
230
|
+
if (extra.length > 0) fail(`.cursor/hooks.json extra events: ${extra.join(', ')}`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const bridgeRef = 'scripts/lib/cursor-hook-bridge.mjs';
|
|
234
|
+
const allPointAtBridge = declared.every((event) => {
|
|
235
|
+
const entries = Array.isArray(hooksJson.hooks[event]) ? hooksJson.hooks[event] : [];
|
|
236
|
+
return entries.some((entry) => typeof entry.command === 'string' && entry.command.includes(bridgeRef) && entry.command.includes(`--event ${event}`));
|
|
237
|
+
});
|
|
238
|
+
if (allPointAtBridge) {
|
|
239
|
+
pass('.cursor/hooks.json commands invoke cursor-hook-bridge.mjs with --event');
|
|
240
|
+
} else {
|
|
241
|
+
fail('.cursor/hooks.json commands must invoke scripts/lib/cursor-hook-bridge.mjs --event <name>');
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
console.log('');
|
|
247
|
+
console.log('--- Check 3: Cursor hook bridge module ---');
|
|
248
|
+
|
|
249
|
+
const bridgePath = join(pluginRoot, 'scripts', 'lib', 'cursor-hook-bridge.mjs');
|
|
250
|
+
if (existsSync(bridgePath)) {
|
|
251
|
+
pass('scripts/lib/cursor-hook-bridge.mjs exists');
|
|
252
|
+
} else {
|
|
253
|
+
fail('scripts/lib/cursor-hook-bridge.mjs exists');
|
|
254
|
+
}
|
|
92
255
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
} else {
|
|
97
|
-
fail('scripts/lib/cursor-hook-bridge.mjs exists');
|
|
256
|
+
console.log('');
|
|
257
|
+
console.log(`Results: ${passed} passed, ${failed} failed`);
|
|
258
|
+
process.exit(failed > 0 ? 1 : 0);
|
|
98
259
|
}
|
|
99
260
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
process.
|
|
261
|
+
// Direct invocation only — importing this module must not run the CLI.
|
|
262
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
263
|
+
runCli(process.argv[2]);
|
|
264
|
+
}
|
|
@@ -67,6 +67,7 @@ import path from 'node:path';
|
|
|
67
67
|
import { spawnSync } from 'node:child_process';
|
|
68
68
|
import { pathToFileURL } from 'node:url';
|
|
69
69
|
import { listRepoFiles } from './repo-files.mjs';
|
|
70
|
+
import { SHELL_LANGS, forEachLine } from './markdown-fences.mjs';
|
|
70
71
|
|
|
71
72
|
/** Directories walked for documentation. Mirrors check-vcs-repo-flag.mjs. */
|
|
72
73
|
const SCAN_DIRS = Object.freeze([
|
|
@@ -80,10 +81,6 @@ const SCAN_DIRS = Object.freeze([
|
|
|
80
81
|
'templates',
|
|
81
82
|
]);
|
|
82
83
|
|
|
83
|
-
/** Never descend into these. */
|
|
84
|
-
/** Fence languages whose body is shell. Anything else is prose. */
|
|
85
|
-
const SHELL_LANGS = Object.freeze(new Set(['bash', 'sh', 'shell', 'console', 'zsh']));
|
|
86
|
-
|
|
87
84
|
/** The CLIs this check knows how to interrogate. */
|
|
88
85
|
const BINS = Object.freeze(['gh', 'glab']);
|
|
89
86
|
|
|
@@ -204,44 +201,23 @@ export function extractCandidates(body) {
|
|
|
204
201
|
const candidates = [];
|
|
205
202
|
/** @type {{line: number, text: string}[]} */
|
|
206
203
|
const shellLines = [];
|
|
207
|
-
/** @type {{marker: string, length: number, shell: boolean} | null} */
|
|
208
|
-
let fence = null;
|
|
209
204
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const fenceMatch = raw.match(/^\s*(`{3,}|~{3,})\s*([A-Za-z0-9_+-]*)/);
|
|
214
|
-
if (fenceMatch) {
|
|
215
|
-
const marker = fenceMatch[1][0];
|
|
216
|
-
const length = fenceMatch[1].length;
|
|
217
|
-
const lang = fenceMatch[2].toLowerCase();
|
|
218
|
-
if (fence === null) {
|
|
219
|
-
fence = { marker, length, shell: SHELL_LANGS.has(lang) };
|
|
220
|
-
continue;
|
|
221
|
-
}
|
|
222
|
-
// A closing fence uses the same char, is at least as long, and has no info string.
|
|
223
|
-
if (marker === fence.marker && length >= fence.length && lang === '') {
|
|
224
|
-
fence = null;
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
// Otherwise it is fence content (a nested fence inside a wider one).
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (fence !== null) {
|
|
231
|
-
if (!fence.shell) continue;
|
|
205
|
+
forEachLine(body, (raw, { lineNumber, inFence, lang }) => {
|
|
206
|
+
if (inFence) {
|
|
207
|
+
if (!SHELL_LANGS.has(lang)) return;
|
|
232
208
|
const stripped = raw.replace(/^\s*[$❯>]\s+/, '');
|
|
233
|
-
if (/^\s*#/.test(stripped))
|
|
234
|
-
shellLines.push({ line:
|
|
235
|
-
|
|
209
|
+
if (/^\s*#/.test(stripped)) return;
|
|
210
|
+
shellLines.push({ line: lineNumber, text: stripped });
|
|
211
|
+
return;
|
|
236
212
|
}
|
|
237
213
|
|
|
238
214
|
for (const span of raw.matchAll(/`([^`]+)`/g)) {
|
|
239
215
|
const text = span[1].trim();
|
|
240
216
|
if (/^(?:gh|glab)\s/.test(text)) {
|
|
241
|
-
candidates.push({ line:
|
|
217
|
+
candidates.push({ line: lineNumber, text, channel: 'inline-span' });
|
|
242
218
|
}
|
|
243
219
|
}
|
|
244
|
-
}
|
|
220
|
+
});
|
|
245
221
|
|
|
246
222
|
for (const entry of joinContinuations(shellLines)) {
|
|
247
223
|
candidates.push({ line: entry.line, text: entry.text, channel: 'shell-fence' });
|