session-orchestrator 3.24.0 → 4.0.1
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 +3 -2
- package/.codex-plugin/skills/architecture/SKILL.md +20 -0
- package/.codex-plugin/skills/autopilot/SKILL.md +21 -0
- package/.codex-plugin/skills/autopilot/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/bootstrap/SKILL.md +22 -0
- package/.codex-plugin/skills/bootstrap/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/brainstorm/SKILL.md +22 -0
- package/.codex-plugin/skills/brainstorm/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/claude-md-drift-check/SKILL.md +17 -0
- package/.codex-plugin/skills/close/SKILL.md +21 -0
- package/.codex-plugin/skills/close/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/convergence-monitoring/SKILL.md +24 -0
- package/.codex-plugin/skills/debug/SKILL.md +21 -0
- package/.codex-plugin/skills/debug/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/discovery/SKILL.md +21 -0
- package/.codex-plugin/skills/discovery/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/dispatcher/SKILL.md +21 -0
- package/.codex-plugin/skills/dispatcher/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/docs-orchestrator/SKILL.md +20 -0
- package/.codex-plugin/skills/ecosystem-health/SKILL.md +22 -0
- package/.codex-plugin/skills/eli5/SKILL.md +21 -0
- package/.codex-plugin/skills/eli5/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/eval/SKILL.md +21 -0
- package/.codex-plugin/skills/eval/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/evolve/SKILL.md +21 -0
- package/.codex-plugin/skills/evolve/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/frontmatter-guard/SKILL.md +17 -0
- package/.codex-plugin/skills/gitlab-ops/SKILL.md +22 -0
- package/.codex-plugin/skills/gitlab-portfolio/SKILL.md +17 -0
- package/.codex-plugin/skills/go/SKILL.md +22 -0
- package/.codex-plugin/skills/go/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/grill/SKILL.md +21 -0
- package/.codex-plugin/skills/grill/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/harness-audit/SKILL.md +19 -0
- package/.codex-plugin/skills/harness-audit/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/hook-development/SKILL.md +17 -0
- package/.codex-plugin/skills/mcp-builder/SKILL.md +17 -0
- package/.codex-plugin/skills/memory-cleanup/SKILL.md +21 -0
- package/.codex-plugin/skills/memory-cleanup/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/mode-selector/SKILL.md +19 -0
- package/.codex-plugin/skills/npm-publish/SKILL.md +18 -0
- package/.codex-plugin/skills/peekaboo-driver/SKILL.md +20 -0
- package/.codex-plugin/skills/persona-panel/SKILL.md +22 -0
- package/.codex-plugin/skills/persona-panel/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/plan/SKILL.md +22 -0
- package/.codex-plugin/skills/plan/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/playwright-driver/SKILL.md +22 -0
- package/.codex-plugin/skills/portfolio/SKILL.md +21 -0
- package/.codex-plugin/skills/portfolio/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/quality-gates/SKILL.md +22 -0
- package/.codex-plugin/skills/reconcile/SKILL.md +21 -0
- package/.codex-plugin/skills/reconcile/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/release/SKILL.md +22 -0
- package/.codex-plugin/skills/release/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/remote-offload/SKILL.md +22 -0
- package/.codex-plugin/skills/repo-audit/SKILL.md +19 -0
- package/.codex-plugin/skills/repo-audit/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/session/SKILL.md +21 -0
- package/.codex-plugin/skills/session/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/session-end/SKILL.md +22 -0
- package/.codex-plugin/skills/session-plan/SKILL.md +22 -0
- package/.codex-plugin/skills/session-start/SKILL.md +22 -0
- package/.codex-plugin/skills/spinout/SKILL.md +21 -0
- package/.codex-plugin/skills/spinout/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/sunset-review/SKILL.md +21 -0
- package/.codex-plugin/skills/sunset-review/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/templates-ack/SKILL.md +21 -0
- package/.codex-plugin/skills/templates-ack/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/test/SKILL.md +21 -0
- package/.codex-plugin/skills/test/agents/openai.yaml +5 -0
- package/.codex-plugin/skills/test-runner/SKILL.md +22 -0
- package/.codex-plugin/skills/tmux-layout/SKILL.md +23 -0
- package/.codex-plugin/skills/using-orchestrator/SKILL.md +19 -0
- package/.codex-plugin/skills/vault-mirror/SKILL.md +17 -0
- package/.codex-plugin/skills/vault-sync/SKILL.md +17 -0
- package/.codex-plugin/skills/wave-executor/SKILL.md +22 -0
- package/.codex-plugin/skills/write-executable-plan/SKILL.md +24 -0
- 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 +1 -1
- package/.cursor-plugin/plugin.json +30 -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 +1314 -2
- package/NOTICE +11 -6
- package/README.md +135 -94
- 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 +108 -62
- package/docs/codex-setup.md +107 -29
- package/docs/components.md +38 -16
- package/docs/cursor-setup.md +6 -2
- package/docs/events-schema.md +9 -6
- package/docs/instruction-delivery.md +69 -0
- package/{agents/memory-proposal-collector.md → docs/memory-proposal-flow.md} +1 -8
- package/docs/migration-v4.md +365 -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 +5 -5
- package/docs/session-config-reference.md +57 -56
- package/docs/session-config-template.md +6 -29
- package/docs/telemetry.md +157 -3
- package/docs/vault-docs-architecture.md +50 -11
- package/hooks/_lib/hook-import-set.json +1488 -0
- package/hooks/_lib/subagent-transcript.mjs +562 -0
- package/hooks/config-protection.mjs +2 -2
- package/hooks/cwd-change-restore.mjs +2 -2
- package/hooks/enforce-commands.mjs +69 -0
- 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 +2 -2
- package/hooks/on-session-start.mjs +103 -2
- package/hooks/on-stop.mjs +60 -14
- package/hooks/operator-steer.mjs +2 -2
- package/hooks/post-bash-write-verify.mjs +85 -0
- package/hooks/post-edit-import-probe.mjs +344 -0
- package/hooks/post-subagent-discovery-validator.mjs +187 -431
- package/hooks/post-tool-batch-wave-signal.mjs +118 -4
- package/hooks/post-tool-failure-corrective-context.mjs +2 -2
- package/hooks/post-tooluse-frontend-slop.mjs +3 -3
- package/hooks/pre-bash-destructive-guard.mjs +39 -13
- package/hooks/skill-invocation-telemetry.mjs +17 -5
- package/hooks/subagent-telemetry.mjs +13 -4
- package/monitors/monitors.json +3 -3
- package/package.json +9 -1
- package/pi/prompts/session.md +2 -2
- package/scripts/backfill-abandoned-sessions.mjs +50 -4
- package/scripts/backfill-learnings-from-vault.mjs +9 -3
- package/scripts/dialectic-deriver.mjs +73 -8
- package/scripts/export-hw-learnings.mjs +113 -1
- package/scripts/generate-agents-skills.mjs +378 -0
- package/scripts/generate-codex-skills.mjs +246 -0
- package/scripts/generate-cursor-adapter.mjs +45 -8
- package/scripts/generate-hook-import-set.mjs +292 -0
- package/scripts/lib/agent-status.mjs +13 -2
- 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/ci-status-banner.mjs +220 -75
- package/scripts/lib/codex/plugin-contract.mjs +88 -6
- package/scripts/lib/config/auto-dream.mjs +2 -1
- package/scripts/lib/config/block-header.mjs +8 -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 +2 -1
- 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 +7 -2
- package/scripts/lib/config/host-paths.mjs +20 -4
- 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 +2 -1
- 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/convergence-monitor.mjs +82 -16
- 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.mjs +22 -6
- package/scripts/lib/frontmatter-guard.mjs +131 -13
- package/scripts/lib/gates/gate-full.mjs +30 -0
- package/scripts/lib/gates/gate-helpers.mjs +76 -0
- package/scripts/lib/hardware-pattern-detector.mjs +18 -1
- 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-proposals/store.mjs +30 -22
- package/scripts/lib/owner-config-banner.mjs +41 -6
- package/scripts/lib/owner-config-loader.mjs +21 -10
- package/scripts/lib/owner-interview.mjs +3 -3
- package/scripts/lib/owner-yaml.mjs +215 -15
- package/scripts/lib/platform.mjs +108 -15
- package/scripts/lib/plugin-update-banner.mjs +414 -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 +51 -11
- package/scripts/lib/reconcile/idempotency.mjs +37 -4
- package/scripts/lib/reconcile/writer.mjs +40 -18
- package/scripts/lib/session-close-backfill.mjs +67 -9
- package/scripts/lib/session-id.mjs +12 -23
- package/scripts/lib/session-identity/own-session.mjs +125 -10
- 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 +64 -3
- package/scripts/lib/session-schema/validator.mjs +38 -4
- package/scripts/lib/session-start-probes.mjs +30 -1
- 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 +202 -9
- package/scripts/lib/telemetry/sync.mjs +368 -12
- package/scripts/lib/telemetry-flush-health-banner.mjs +211 -0
- package/scripts/lib/validate/check-agents-skills.mjs +327 -0
- package/scripts/lib/validate/check-agents.mjs +3 -3
- package/scripts/lib/validate/check-codex-skills.mjs +191 -0
- package/scripts/lib/validate/check-cursor-adapter.mjs +234 -72
- package/scripts/lib/validate/check-hooks-symmetry.mjs +45 -16
- package/scripts/lib/validate/check-owner-leakage.mjs +319 -22
- package/scripts/lib/validate/check-skill-links.mjs +193 -0
- package/scripts/lib/validate/check-skill-script-paths.mjs +47 -28
- package/scripts/lib/validate/check-test-git-config-target.mjs +192 -12
- package/scripts/lib/validate/check-unwired-features.mjs +163 -15
- package/scripts/lib/validate/check-validator-registration.mjs +10 -4
- package/scripts/lib/validate/confidential-names.mjs +95 -30
- package/scripts/lib/validate/enumerate-repo-files.mjs +317 -0
- package/scripts/lib/validate/repo-files.mjs +48 -14
- 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/narrative-mirror.mjs +127 -18
- 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 +5 -7
- package/scripts/lib/wave-resource-gate.mjs +8 -2
- package/scripts/lib/wave-sizing.mjs +4 -1
- package/scripts/lib/wave-transcript-tail.mjs +118 -4
- package/scripts/materialize-wave-scope.mjs +12 -5
- package/scripts/memory-propose.mjs +19 -5
- package/scripts/migrate-cold-start-seed.mjs +4 -1
- package/scripts/parse-config.mjs +60 -3
- package/scripts/release.mjs +430 -31
- package/scripts/repair-invalid-sessions.mjs +3 -3
- package/scripts/run-quality-gate.mjs +128 -11
- package/scripts/site-numbers.mjs +344 -8
- 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 +164 -0
- package/scripts/validate-wave-scope.mjs +28 -8
- package/scripts/wave-scope-binding.mjs +215 -0
- package/skills/_shared/instruction-file-resolution.md +10 -0
- package/skills/_shared/parallel-aware-preamble.md +1 -0
- 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/evolve/SKILL.md +65 -26
- package/skills/frontmatter-guard/SKILL.md +11 -5
- package/skills/npm-publish/SKILL.md +1 -1
- package/skills/reconcile/SKILL.md +33 -0
- package/skills/remote-offload/SKILL.md +1 -1
- package/skills/session-end/SKILL.md +18 -905
- package/skills/session-end/phase-3-6-tail.md +10 -3
- 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 +22 -904
- 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 +160 -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/SKILL.md +10 -0
- package/skills/vault-sync/validator.mjs +21 -27
- package/skills/wave-executor/SKILL.md +15 -1
- 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 -1309
- 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 -270
- 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
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Check: every `scripts/**.mjs` path cited in `skills/`, `commands
|
|
4
|
-
* `agents/` either EXISTS or is annotated as deliberately absent
|
|
5
|
-
* Extended (#1187) to also cite `scripts/**.sh` and `hooks/**.sh` —
|
|
6
|
-
* "## Mode: BLOCKING for `.mjs`, ADVISORY for `.sh`" below for why that
|
|
7
|
-
* is advisory, not blocking.
|
|
3
|
+
* Check: every `scripts/**.mjs` path cited in `skills/`, `commands/`,
|
|
4
|
+
* `agents/` and `docs/` either EXISTS or is annotated as deliberately absent
|
|
5
|
+
* (#1176). Extended (#1187) to also cite `scripts/**.sh` and `hooks/**.sh` —
|
|
6
|
+
* see "## Mode: BLOCKING for `.mjs`, ADVISORY for `.sh`" below for why that
|
|
7
|
+
* half is advisory, not blocking. `docs/` joined `SCAN_DIRS` in #1208, after
|
|
8
|
+
* the 22 dead paths it carried at the time (9 `.mjs`, all ADR/reference
|
|
9
|
+
* prose) were annotated — see that section below for the census and why
|
|
10
|
+
* widening the scan root had to wait for the annotation pass, not precede it.
|
|
8
11
|
*
|
|
9
12
|
* ## Why
|
|
10
13
|
*
|
|
@@ -12,8 +15,8 @@
|
|
|
12
15
|
* `node scripts/lib/auto-commit.mjs` costs an operator a failed command and a
|
|
13
16
|
* re-derivation of what the file was supposed to do — and nothing in the
|
|
14
17
|
* corpus notices, because a markdown file compiles under every gate. Measured
|
|
15
|
-
* 2026-09-02 @ c3ab480: 237 distinct citations across the three scan
|
|
16
|
-
* 7 of them dead.
|
|
18
|
+
* 2026-09-02 @ c3ab480: 237 distinct citations across the (then three) scan
|
|
19
|
+
* roots, 7 of them dead.
|
|
17
20
|
*
|
|
18
21
|
* ## Fences are skipped, and that is most of the answer
|
|
19
22
|
*
|
|
@@ -58,27 +61,37 @@
|
|
|
58
61
|
* The `.sh` half of the citation grammar (below) does not get that same
|
|
59
62
|
* severity by default. A #1176 repo-wide grep (`scripts/hooks` prose across
|
|
60
63
|
* `skills/commands/agents/docs/hooks`) found 27 distinct `.sh` citations, 21
|
|
61
|
-
* dead — but only ONE of those 27
|
|
62
|
-
* (`skills/contract-version-bump/SKILL.md:134`,
|
|
63
|
-
* cross-repo path — see the dry-run note at
|
|
64
|
-
* `strictSh` option). The other 26
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
64
|
+
* dead — but at the time only ONE of those 27 sat inside this checker's
|
|
65
|
+
* (then three) scan roots (`skills/contract-version-bump/SKILL.md:134`,
|
|
66
|
+
* itself arguably a cross-repo path — see the dry-run note at
|
|
67
|
+
* `scanSkillScriptPaths`'s `strictSh` option). The other 26 lived in `docs/`,
|
|
68
|
+
* which this checker did not yet scan.
|
|
69
|
+
*
|
|
70
|
+
* #1208 closed that gap in two steps, annotation before widening rather than
|
|
71
|
+
* the reverse: first, a `dirs: ['docs']` re-scan (530 citations, 66 files)
|
|
72
|
+
* found 50 findings — 22 unique dead paths (9 `.mjs`, 15 `.sh`) across
|
|
73
|
+
* 24 (file, path) pairs, concentrated in `docs/adr/*.md` (ADR prose citing
|
|
74
|
+
* not-yet-built modules like `scripts/lib/tool-adapter.mjs`) and
|
|
75
|
+
* `docs/changelog/v2.md` (23 `.sh` citations to the pre-`.mjs`-migration
|
|
76
|
+
* shell scripts, #218/#317 — historical by construction). Every one of the
|
|
77
|
+
* 22 was annotated (`planned #<iid>` for the ADR gaps, `historical` for the
|
|
78
|
+
* changelog, `example` for the one illustrative path in
|
|
79
|
+
* `docs/scope-collision-guard.md`) — zero of them were real defects. Only
|
|
80
|
+
* then did `SCAN_DIRS` gain `'docs'`, so the widening added zero new
|
|
81
|
+
* BLOCKING findings on arrival (re-verify: `scanSkillScriptPaths({
|
|
82
|
+
* pluginRoot, dirs: ['docs'] })` → `ok: true`, `findings: 0`). The wider
|
|
83
|
+
* `hooks/` `.sh` prose census (26 of the 27 `.sh` citations above are outside
|
|
84
|
+
* `SCAN_DIRS` even now, since `hooks/` prose itself is not a scanned root)
|
|
85
|
+
* remains a follow-up for whoever owns those files.
|
|
75
86
|
*
|
|
76
87
|
* A `.sh` finding is therefore `WARN:` by default (visible, never blocking —
|
|
77
88
|
* `ok` and the CLI exit code ignore `severity: 'warn'` findings) and only
|
|
78
89
|
* becomes `FAIL:`/blocking under the `--strict-sh` CLI flag (or
|
|
79
90
|
* `strictSh: true` for `scanSkillScriptPaths()` callers) — flip that default
|
|
80
91
|
* once the dead `.sh` citations this checker CAN see are fixed by their doc
|
|
81
|
-
* owner (BV-004 revisit trigger).
|
|
92
|
+
* owner (BV-004 revisit trigger). `--strict-sh` gained a validate-plugin run
|
|
93
|
+
* surface in #1208 (advisory, non-blocking — see `scripts/validate-plugin.mjs`
|
|
94
|
+
* near its `check-skill-script-paths.mjs` call).
|
|
82
95
|
*
|
|
83
96
|
* @module scripts/lib/validate/check-skill-script-paths
|
|
84
97
|
*/
|
|
@@ -86,11 +99,11 @@
|
|
|
86
99
|
import { existsSync, readFileSync } from 'node:fs';
|
|
87
100
|
import path from 'node:path';
|
|
88
101
|
import { pathToFileURL } from 'node:url';
|
|
89
|
-
import {
|
|
102
|
+
import { enumerateRepoFiles } from './enumerate-repo-files.mjs';
|
|
90
103
|
import { forEachLine } from './markdown-fences.mjs';
|
|
91
104
|
|
|
92
105
|
/** Documentation roots whose prose is treated as a claim about the repo. */
|
|
93
|
-
export const SCAN_DIRS = Object.freeze(['skills', 'commands', 'agents']);
|
|
106
|
+
export const SCAN_DIRS = Object.freeze(['skills', 'commands', 'agents', 'docs']);
|
|
94
107
|
|
|
95
108
|
/**
|
|
96
109
|
* A cited script path. One regex, one alternation, reused for every
|
|
@@ -246,10 +259,16 @@ export function scanSkillScriptPaths({ pluginRoot, dirs = SCAN_DIRS, strictSh =
|
|
|
246
259
|
/** @type {string[]} */
|
|
247
260
|
let files;
|
|
248
261
|
try {
|
|
249
|
-
// The
|
|
250
|
-
//
|
|
251
|
-
//
|
|
252
|
-
|
|
262
|
+
// The population is "exists in this repo, tracked or not" (#1248) — NOT
|
|
263
|
+
// "is versioned". A doc that cites a dead script is a defect the moment it
|
|
264
|
+
// is written; the bare git index cannot see it until it is staged, so the
|
|
265
|
+
// check reported clean on the exact tree carrying the bug (measured: an
|
|
266
|
+
// untracked `skills/zz-probe/SKILL.md` → `1 passed, 0 failed` before
|
|
267
|
+
// `git add -A`, `0 passed, 1 failed` after). `enumerateRepoFiles` still
|
|
268
|
+
// honours `.gitignore`, so the #1143 exposure a bare `readdirSync` walk
|
|
269
|
+
// would reintroduce (a worktree under `.claude/worktrees/`, gitignored
|
|
270
|
+
// `docs/specs/*.md`) stays closed — see that module's header.
|
|
271
|
+
files = enumerateRepoFiles({ repoRoot: pluginRoot, dirs, exts: ['.md'] });
|
|
253
272
|
} catch (error) {
|
|
254
273
|
findings.push({
|
|
255
274
|
kind: 'tool-error',
|
|
@@ -40,6 +40,37 @@
|
|
|
40
40
|
* measures that second population so the gap is visible in the OUTPUT, not
|
|
41
41
|
* only in this comment.
|
|
42
42
|
*
|
|
43
|
+
* ## Wrapper-aware: `fixtureGit` / `fixtureGitSpawn` are git invocations
|
|
44
|
+
*
|
|
45
|
+
* Since 2026-09-06 most fixtures do not spawn `git` themselves — they call
|
|
46
|
+
* `fixtureGit(args, cwd, opts)` / `fixtureGitSpawn(…)` from
|
|
47
|
+
* `tests/_helpers/tmp-fixture.mjs`, which prepend `...NO_BACKGROUND_WRITER` and
|
|
48
|
+
* spawn the binary inside the helper. Two consequences, both measured
|
|
49
|
+
* 2026-09-07 against this tree:
|
|
50
|
+
*
|
|
51
|
+
* - Resolving only the helper's own two `execFileSync`/`spawnSync` lines
|
|
52
|
+
* (i.e. teaching {@link classifyArgv} to skip the allowlisted flag-only
|
|
53
|
+
* spread, see {@link NOOP_PREFIX_SPREADS}) changes NOTHING: `applicable`
|
|
54
|
+
* stays at **17**, because the token after the allowlisted spread is
|
|
55
|
+
* `...args` — an unknown spread the census must still refuse to guess past.
|
|
56
|
+
* - Recognising the two helpers BY NAME, and reading the argv array's first
|
|
57
|
+
* element as the subcommand, lifts `applicable` to **~200** with **0**
|
|
58
|
+
* findings (197 → 198 → 200 across the 2026-09-07 re-measurements as
|
|
59
|
+
* sibling waves added fixtures; re-measure before quoting) — the census
|
|
60
|
+
* then sees the real test population instead of a residue. That population is **244** `fixtureGit`/`fixtureGitSpawn` call
|
|
61
|
+
* sites, measured 2026-09-07 with
|
|
62
|
+
* `rg -o "\bfixtureGit(Spawn)?\s*\(" tests/ -g '*.mjs' | wc -l`
|
|
63
|
+
* (the header claimed 239 until that re-measurement; `applicable` is the
|
|
64
|
+
* smaller number because read-only and unresolved-argv calls are excluded).
|
|
65
|
+
*
|
|
66
|
+
* Wrapper-aware is therefore the mode this file implements. It costs one extra
|
|
67
|
+
* rule: the helper takes its target as the SECOND POSITIONAL, not as a `cwd:`
|
|
68
|
+
* key, and `undefined`, `null` or an ABSENT second positional all mean "no
|
|
69
|
+
* destination was handed to the helper" — see {@link wrapperHasCwd}, which
|
|
70
|
+
* judges the COMMENT-STRIPPED tail so an inline comment cannot stand in for the
|
|
71
|
+
* argument. Judging a wrapper call by the `cwd:` scan alone would have reported
|
|
72
|
+
* nearly every routed fixture as untargeted.
|
|
73
|
+
*
|
|
43
74
|
* Further named gaps:
|
|
44
75
|
* - **A non-literal argv array is never judged.** `execFileSync('git', args, …)`
|
|
45
76
|
* cannot be classified from the call site; counted as `unresolvedArgv`.
|
|
@@ -163,6 +194,16 @@ const TARGET_DECLARING_GLOBALS = Object.freeze(['-C', '--git-dir', '--work-tree'
|
|
|
163
194
|
/** Call shapes that hand an argv ARRAY to a `git` binary. */
|
|
164
195
|
const ARGV_CALL_RE = /\b(?:execFileSync|execFile|spawnSync|spawn)\s*\(\s*['"]git['"]\s*,\s*/g;
|
|
165
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Call shapes that route a `git` argv through this suite's fixture helpers.
|
|
199
|
+
*
|
|
200
|
+
* `fixtureGit(args, cwd, opts)` / `fixtureGitSpawn(args, cwd, opts)` from
|
|
201
|
+
* `tests/_helpers/tmp-fixture.mjs` ARE git invocations — the binary is inside
|
|
202
|
+
* the helper. Recognising them by name is what makes the census reflect the
|
|
203
|
+
* real test population; see § Wrapper-aware in the header.
|
|
204
|
+
*/
|
|
205
|
+
const WRAPPER_CALL_RE = /\b(?:fixtureGit|fixtureGitSpawn)\s*\(/g;
|
|
206
|
+
|
|
166
207
|
/** Call shapes that hand a SHELL STRING opening with `git` to a shell. */
|
|
167
208
|
const SHELL_CALL_RE = /\b(?:execSync|exec)\s*\(\s*(['"`])\s*git\s/g;
|
|
168
209
|
|
|
@@ -226,15 +267,30 @@ function matchBracket(text, open, openChar, closeChar) {
|
|
|
226
267
|
}
|
|
227
268
|
|
|
228
269
|
/**
|
|
229
|
-
* @typedef {{t:'lit', v:string} | {t:'spread'} | {t:'expr'}} ArgvToken
|
|
230
|
-
* `lit` a string literal · `spread` a `...rest` element
|
|
270
|
+
* @typedef {{t:'lit', v:string} | {t:'spread', name:string} | {t:'expr'}} ArgvToken
|
|
271
|
+
* `lit` a string literal · `spread` a `...rest` element, carrying the spread
|
|
272
|
+
* identifier (`''` when it is not a plain identifier) · `expr` any other
|
|
231
273
|
* expression (an identifier, a member access, an interpolated template).
|
|
232
274
|
*
|
|
233
275
|
* The `spread`/`expr` split is load-bearing, not cosmetic: `['init','-q',dir]`
|
|
234
276
|
* carries its target in an `expr` positional, while `['-C',dir,...args]`
|
|
235
277
|
* carries an unknowable tail in a `spread`. Folding both to "opaque" is what
|
|
236
278
|
* produced the first measurement's 11 false positives.
|
|
279
|
+
*
|
|
280
|
+
* The spread's NAME is load-bearing in turn — see {@link NOOP_PREFIX_SPREADS}.
|
|
281
|
+
*/
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Spread identifiers that are known to contain ONLY `git` global flags, so a
|
|
285
|
+
* leading `...NAME` may be skipped exactly as a literal `-c k=v` run is.
|
|
286
|
+
*
|
|
287
|
+
* An explicit allowlist, never a heuristic: any OTHER spread keeps the
|
|
288
|
+
* fail-closed `subcommand: null`, because guessing past an unknown spread is
|
|
289
|
+
* precisely what produced the 11 false positives named in the header.
|
|
290
|
+
*
|
|
291
|
+
* @type {ReadonlySet<string>}
|
|
237
292
|
*/
|
|
293
|
+
const NOOP_PREFIX_SPREADS = new Set(['NO_BACKGROUND_WRITER']);
|
|
238
294
|
|
|
239
295
|
/**
|
|
240
296
|
* Tokenize a literal argv array body into ordered tokens.
|
|
@@ -245,13 +301,13 @@ function matchBracket(text, open, openChar, closeChar) {
|
|
|
245
301
|
export function tokenizeArgv(inner) {
|
|
246
302
|
/** @type {ArgvToken[]} */
|
|
247
303
|
const tokens = [];
|
|
248
|
-
const re = /(['"])((?:\\.|(?!\1)[^\\])*)\1|`([^`$]*)`|(\.\.\.)[\w$.[\]]
|
|
304
|
+
const re = /(['"])((?:\\.|(?!\1)[^\\])*)\1|`([^`$]*)`|(\.\.\.)([\w$.[\]]*)|([A-Za-z_$][\w$.[\]]*|`[^`]*`)/g;
|
|
249
305
|
/** @type {RegExpExecArray|null} */
|
|
250
306
|
let m;
|
|
251
307
|
while ((m = re.exec(inner)) !== null) {
|
|
252
308
|
if (m[2] !== undefined) tokens.push({ t: 'lit', v: m[2] });
|
|
253
309
|
else if (m[3] !== undefined) tokens.push({ t: 'lit', v: m[3] });
|
|
254
|
-
else if (m[4] !== undefined) tokens.push({ t: 'spread' });
|
|
310
|
+
else if (m[4] !== undefined) tokens.push({ t: 'spread', name: m[5] ?? '' });
|
|
255
311
|
else tokens.push({ t: 'expr' });
|
|
256
312
|
}
|
|
257
313
|
return tokens;
|
|
@@ -268,8 +324,13 @@ export function classifyArgv(tokens) {
|
|
|
268
324
|
let index = 0;
|
|
269
325
|
while (index < tokens.length) {
|
|
270
326
|
const token = tokens[index];
|
|
271
|
-
//
|
|
272
|
-
|
|
327
|
+
// An ALLOWLISTED flag-only spread is skipped exactly like a `-c k=v` run.
|
|
328
|
+
if (token.t === 'spread' && NOOP_PREFIX_SPREADS.has(token.name)) {
|
|
329
|
+
index += 1;
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
// Any other non-literal in leading-flag position makes the subcommand
|
|
333
|
+
// unknowable; never guess past it.
|
|
273
334
|
if (token.t !== 'lit') return { hasArgvTarget, subcommand: null, rest: [] };
|
|
274
335
|
if (!token.v.startsWith('-')) break;
|
|
275
336
|
|
|
@@ -416,6 +477,84 @@ export function insideStringLiteral(body, index) {
|
|
|
416
477
|
return quote !== null;
|
|
417
478
|
}
|
|
418
479
|
|
|
480
|
+
/**
|
|
481
|
+
* Replace every comment in `text` with a single space, leaving string literals
|
|
482
|
+
* untouched.
|
|
483
|
+
*
|
|
484
|
+
* Not cosmetic: {@link wrapperHasCwd} judges the SECOND POSITIONAL textually,
|
|
485
|
+
* so an inline `/* … *\/` between the comma and the argument used to shift the
|
|
486
|
+
* argument out of view and the call read as targeted — a comment that says
|
|
487
|
+
* "no cwd" measured as a cwd. `inCommentLine` cannot serve here: it answers a
|
|
488
|
+
* question about a whole LINE, while this one runs inside a call expression.
|
|
489
|
+
*
|
|
490
|
+
* @param {string} text
|
|
491
|
+
* @returns {string} same length semantics, comments blanked to one space
|
|
492
|
+
*/
|
|
493
|
+
export function stripComments(text) {
|
|
494
|
+
let out = '';
|
|
495
|
+
/** @type {string|null} */
|
|
496
|
+
let quote = null;
|
|
497
|
+
for (let i = 0; i < text.length; i += 1) {
|
|
498
|
+
const ch = text[i];
|
|
499
|
+
if (quote !== null) {
|
|
500
|
+
out += ch;
|
|
501
|
+
if (ch === '\\') {
|
|
502
|
+
out += text[i + 1] ?? '';
|
|
503
|
+
i += 1;
|
|
504
|
+
} else if (ch === quote) quote = null;
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
if (ch === "'" || ch === '"' || ch === '`') {
|
|
508
|
+
quote = ch;
|
|
509
|
+
out += ch;
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
if (ch === '/' && text[i + 1] === '*') {
|
|
513
|
+
const end = text.indexOf('*/', i + 2);
|
|
514
|
+
i = end === -1 ? text.length : end + 1;
|
|
515
|
+
out += ' ';
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
if (ch === '/' && text[i + 1] === '/') {
|
|
519
|
+
const end = text.indexOf('\n', i);
|
|
520
|
+
i = end === -1 ? text.length : end - 1;
|
|
521
|
+
out += ' ';
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
out += ch;
|
|
525
|
+
}
|
|
526
|
+
return out;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Decide whether a fixture-helper call names a working directory.
|
|
531
|
+
*
|
|
532
|
+
* `fixtureGit(args, cwd, opts)` takes the target as its SECOND POSITIONAL, not
|
|
533
|
+
* as a `cwd:` key — so the textual `cwd:` scan that judges a raw `execFileSync`
|
|
534
|
+
* would report every one of these as untargeted.
|
|
535
|
+
*
|
|
536
|
+
* Three shapes are explicitly NOT a target, because none of them hands the
|
|
537
|
+
* helper a destination: a literal `undefined` (the documented "the argv names
|
|
538
|
+
* the target" form), a literal `null` (same at runtime — `spawnSync` inherits
|
|
539
|
+
* the ambient cwd for both), and an ABSENT second positional. Judging is done
|
|
540
|
+
* on the COMMENT-STRIPPED tail: `fixtureGit([…], /* no cwd *\/ undefined)` read
|
|
541
|
+
* as targeted before 2026-09-07 — the comment, not the argument, was what the
|
|
542
|
+
* second-positional scan saw.
|
|
543
|
+
*
|
|
544
|
+
* @param {string} tail call arguments AFTER the argv array's `]`, bounded by
|
|
545
|
+
* the call's closing paren
|
|
546
|
+
* @returns {boolean}
|
|
547
|
+
*/
|
|
548
|
+
export function wrapperHasCwd(tail) {
|
|
549
|
+
const clean = stripComments(tail);
|
|
550
|
+
const m = /^\s*,\s*/.exec(clean);
|
|
551
|
+
if (m) {
|
|
552
|
+
const second = clean.slice(m[0].length);
|
|
553
|
+
if (second !== '' && !/^(?:undefined|null)\b/.test(second) && !/^,/.test(second)) return true;
|
|
554
|
+
}
|
|
555
|
+
return CWD_OPTION_RE.test(clean);
|
|
556
|
+
}
|
|
557
|
+
|
|
419
558
|
/**
|
|
420
559
|
* Scan one file for `git` invocations.
|
|
421
560
|
*
|
|
@@ -428,7 +567,7 @@ export function scanFile(relative, body, tally) {
|
|
|
428
567
|
/** @type {Array<{kind: string, file: string, line: number, form: string, command: string, message: string}>} */
|
|
429
568
|
const findings = [];
|
|
430
569
|
|
|
431
|
-
/** @type {Array<{index: number, form: 'argv'|'shell', tokens: Array<string|null>, tail: string}>} */
|
|
570
|
+
/** @type {Array<{index: number, form: 'argv'|'shell'|'wrapper', tokens: Array<string|null>, tail: string}>} */
|
|
432
571
|
const calls = [];
|
|
433
572
|
|
|
434
573
|
ARGV_CALL_RE.lastIndex = 0;
|
|
@@ -454,6 +593,35 @@ export function scanFile(relative, body, tally) {
|
|
|
454
593
|
});
|
|
455
594
|
}
|
|
456
595
|
|
|
596
|
+
WRAPPER_CALL_RE.lastIndex = 0;
|
|
597
|
+
while ((m = WRAPPER_CALL_RE.exec(body)) !== null) {
|
|
598
|
+
const openParen = m.index + m[0].length - 1;
|
|
599
|
+
const callEnd = matchBracket(body, openParen, '(', ')');
|
|
600
|
+
if (callEnd === -1) {
|
|
601
|
+
tally.unresolvedArgv += 1;
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
const argsText = body.slice(openParen + 1, callEnd);
|
|
605
|
+
const arrayStart = argsText.search(/\S/);
|
|
606
|
+
if (arrayStart === -1 || argsText[arrayStart] !== '[') {
|
|
607
|
+
// `fixtureGit(args, dir)` — a variable argv, unjudgeable like its
|
|
608
|
+
// `execFileSync` counterpart.
|
|
609
|
+
tally.unresolvedArgv += 1;
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
const close = matchBracket(argsText, arrayStart, '[', ']');
|
|
613
|
+
if (close === -1) {
|
|
614
|
+
tally.unresolvedArgv += 1;
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
calls.push({
|
|
618
|
+
index: m.index,
|
|
619
|
+
form: 'wrapper',
|
|
620
|
+
tokens: tokenizeArgv(argsText.slice(arrayStart + 1, close)),
|
|
621
|
+
tail: argsText.slice(close + 1),
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
|
|
457
625
|
SHELL_CALL_RE.lastIndex = 0;
|
|
458
626
|
while ((m = SHELL_CALL_RE.exec(body)) !== null) {
|
|
459
627
|
const quote = m[1];
|
|
@@ -487,11 +655,20 @@ export function scanFile(relative, body, tally) {
|
|
|
487
655
|
}
|
|
488
656
|
tally.applicable += 1;
|
|
489
657
|
|
|
490
|
-
// The options object: everything up to the end of the call expression.
|
|
658
|
+
// The options object: everything up to the end of the call expression. For
|
|
659
|
+
// a wrapper call `call.tail` is ALREADY bounded by the call's own closing
|
|
660
|
+
// paren, and its second positional — not a `cwd:` key — carries the target.
|
|
661
|
+
const isWrapper = call.form === 'wrapper';
|
|
491
662
|
const callEnd = matchBracket(call.tail, call.tail.indexOf('('), '(', ')');
|
|
492
|
-
const optionsText =
|
|
493
|
-
|
|
494
|
-
|
|
663
|
+
const optionsText = isWrapper
|
|
664
|
+
? call.tail
|
|
665
|
+
: callEnd === -1
|
|
666
|
+
? call.tail.slice(0, 400)
|
|
667
|
+
: call.tail.slice(0, callEnd);
|
|
668
|
+
const opaqueOptions = !isWrapper && OPAQUE_OPTIONS_RE.test(call.tail);
|
|
669
|
+
const hasCwd = isWrapper
|
|
670
|
+
? wrapperHasCwd(call.tail)
|
|
671
|
+
: CWD_OPTION_RE.test(optionsText);
|
|
495
672
|
const hasEnvTarget = GIT_ENV_TARGET_RE.test(optionsText);
|
|
496
673
|
const hasTarget =
|
|
497
674
|
hasArgvTarget || hasCwd || hasEnvTarget || hasSubcommandTarget(subcommand, rest);
|
|
@@ -582,7 +759,10 @@ export function inspectTestGitConfigTarget(pluginRoot) {
|
|
|
582
759
|
});
|
|
583
760
|
return result;
|
|
584
761
|
}
|
|
585
|
-
|
|
762
|
+
// Cheap prefilter. The second alternative is load-bearing since the census
|
|
763
|
+
// became wrapper-aware: a file that only calls `fixtureGit([...])` never
|
|
764
|
+
// writes the quoted binary name and would otherwise be skipped unseen.
|
|
765
|
+
if (!/['"`]\s*git[\s'"`]/.test(body) && !/\bfixtureGit(?:Spawn)?\s*\(/.test(body)) continue;
|
|
586
766
|
findings.push(...scanFile(relative, body, tally));
|
|
587
767
|
}
|
|
588
768
|
|