@opengsd/gsd-core 1.15.0 → 1.16.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +85 -5
- package/agents/gsd-code-fixer.compact.md +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-code-reviewer.compact.md +5 -3
- package/agents/gsd-code-reviewer.md +8 -6
- package/agents/gsd-debug-session-manager.compact.md +1 -1
- package/agents/gsd-debug-session-manager.md +1 -1
- package/agents/gsd-debugger.md +2 -2
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +4 -4
- package/agents/gsd-intel-updater.compact.md +1 -1
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +2 -2
- package/agents/gsd-phase-researcher.md +1 -1
- package/agents/gsd-plan-checker.md +7 -2
- package/agents/gsd-planner.md +3 -3
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +1 -1
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-ui-auditor.compact.md +21 -30
- package/agents/gsd-ui-auditor.md +42 -51
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +31 -9
- package/bin/install.js +126 -196
- package/commands/gsd/add-tests.md +6 -1
- package/commands/gsd/ai-integration-phase.md +6 -1
- package/commands/gsd/audit-fix.md +5 -0
- package/commands/gsd/audit-milestone.md +6 -1
- package/commands/gsd/autonomous.md +5 -0
- package/commands/gsd/capture.md +8 -4
- package/commands/gsd/code-review.md +7 -2
- package/commands/gsd/complete-milestone.md +4 -0
- package/commands/gsd/config.md +7 -3
- package/commands/gsd/debug.md +11 -7
- package/commands/gsd/discuss-phase.md +7 -3
- package/commands/gsd/docs-update.md +12 -7
- package/commands/gsd/eval-review.md +6 -1
- package/commands/gsd/execute-phase.md +12 -7
- package/commands/gsd/extract-learnings.md +5 -0
- package/commands/gsd/fast.md +4 -0
- package/commands/gsd/forensics.md +5 -1
- package/commands/gsd/graphify.md +10 -6
- package/commands/gsd/health.md +5 -0
- package/commands/gsd/help.md +7 -2
- package/commands/gsd/import.md +7 -3
- package/commands/gsd/inbox.md +5 -0
- package/commands/gsd/ingest-docs.md +5 -1
- package/commands/gsd/manager.md +6 -1
- package/commands/gsd/map-codebase.md +7 -3
- package/commands/gsd/mempalace-capture.md +5 -1
- package/commands/gsd/mempalace-recall.md +5 -1
- package/commands/gsd/milestone-summary.md +5 -1
- package/commands/gsd/mvp-phase.md +8 -3
- package/commands/gsd/new-milestone.md +6 -1
- package/commands/gsd/new-project.md +5 -0
- package/commands/gsd/next.md +6 -1
- package/commands/gsd/ns-context.md +4 -0
- package/commands/gsd/ns-ideate.md +4 -0
- package/commands/gsd/ns-manage.md +4 -0
- package/commands/gsd/ns-project.md +4 -0
- package/commands/gsd/ns-review.md +4 -0
- package/commands/gsd/ns-workflow.md +4 -0
- package/commands/gsd/onboard.md +6 -1
- package/commands/gsd/pause-work.md +5 -1
- package/commands/gsd/phase.md +8 -4
- package/commands/gsd/plan-phase.md +6 -1
- package/commands/gsd/plan-review-convergence.md +5 -1
- package/commands/gsd/pr-branch.md +4 -0
- package/commands/gsd/profile-user.md +5 -1
- package/commands/gsd/progress.md +6 -1
- package/commands/gsd/quick-batch.md +20 -8
- package/commands/gsd/quick.md +12 -7
- package/commands/gsd/review.md +5 -1
- package/commands/gsd/secure-phase.md +6 -1
- package/commands/gsd/ship.md +5 -0
- package/commands/gsd/sketch.md +7 -2
- package/commands/gsd/spec-phase.md +5 -1
- package/commands/gsd/spike.md +8 -3
- package/commands/gsd/surface.md +5 -1
- package/commands/gsd/thread.md +4 -0
- package/commands/gsd/ui-phase.md +6 -1
- package/commands/gsd/ui-review.md +6 -1
- package/commands/gsd/ultraplan-phase.md +5 -1
- package/commands/gsd/undo.md +5 -1
- package/commands/gsd/update.md +6 -2
- package/commands/gsd/validate-phase.md +6 -1
- package/commands/gsd/verify-work.md +6 -1
- package/commands/gsd/workspace.md +7 -3
- package/gsd-core/bin/gsd-tools.cjs +142 -56
- package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
- package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
- package/gsd-core/bin/lib/audit.cjs +78 -44
- package/gsd-core/bin/lib/broken-windows.cjs +13 -13
- package/gsd-core/bin/lib/capability-activation.cjs +9 -4
- package/gsd-core/bin/lib/capability-registry.cjs +183 -103
- package/gsd-core/bin/lib/capability-validator.cjs +16 -0
- package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
- package/gsd-core/bin/lib/check-command-router.cjs +164 -1712
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
- package/gsd-core/bin/lib/cli-exit.cjs +12 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +11 -8
- package/gsd-core/bin/lib/command-aliases.cjs +7 -0
- package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
- package/gsd-core/bin/lib/commands.cjs +173 -170
- package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
- package/gsd-core/bin/lib/config.cjs +43 -12
- package/gsd-core/bin/lib/core-utils.cjs +6 -1
- package/gsd-core/bin/lib/coverage.cjs +4 -8
- package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
- package/gsd-core/bin/lib/drift.cjs +177 -42
- package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
- package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
- package/gsd-core/bin/lib/frontmatter.cjs +413 -234
- package/gsd-core/bin/lib/gap-checker.cjs +72 -29
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
- package/gsd-core/bin/lib/gate-args.cjs +53 -0
- package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
- package/gsd-core/bin/lib/gate-config.cjs +46 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
- package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
- package/gsd-core/bin/lib/gate-exit.cjs +27 -0
- package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
- package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
- package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
- package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
- package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
- package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
- package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
- package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
- package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
- package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
- package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
- package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
- package/gsd-core/bin/lib/init.cjs +162 -96
- package/gsd-core/bin/lib/install-engine.cjs +19 -35
- package/gsd-core/bin/lib/install-profiles.cjs +7 -4
- package/gsd-core/bin/lib/io.cjs +122 -3
- package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
- package/gsd-core/bin/lib/milestone.cjs +19 -1
- package/gsd-core/bin/lib/model-resolver.cjs +18 -18
- package/gsd-core/bin/lib/observability/event.cjs +1 -1
- package/gsd-core/bin/lib/observability/logger.cjs +46 -1
- package/gsd-core/bin/lib/pattern.cjs +10 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +11 -4
- package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
- package/gsd-core/bin/lib/phase-id.cjs +1 -1
- package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
- package/gsd-core/bin/lib/phase-status.cjs +360 -0
- package/gsd-core/bin/lib/phase.cjs +280 -80
- package/gsd-core/bin/lib/plan-document.cjs +93 -19
- package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
- package/gsd-core/bin/lib/planning-document.cjs +273 -40
- package/gsd-core/bin/lib/planning-inspect.cjs +42 -8
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +76 -53
- package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
- package/gsd-core/bin/lib/profile-output.cjs +6 -3
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
- package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
- package/gsd-core/bin/lib/report-parser.cjs +269 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +13 -15
- package/gsd-core/bin/lib/roadmap-parser.cjs +82 -15
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +127 -65
- package/gsd-core/bin/lib/roadmap.cjs +169 -72
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +91 -157
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -1
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +13 -10
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +307 -591
- package/gsd-core/bin/lib/runtime-name-policy.cjs +142 -27
- package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +37 -2
- package/gsd-core/bin/lib/smart-entry.cjs +19 -3
- package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
- package/gsd-core/bin/lib/state-contract.cjs +15 -18
- package/gsd-core/bin/lib/state-document.cjs +100 -22
- package/gsd-core/bin/lib/state.cjs +214 -105
- package/gsd-core/bin/lib/surface.cjs +2 -1
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -152
- package/gsd-core/bin/lib/uat-predicate.cjs +313 -35
- package/gsd-core/bin/lib/uat.cjs +424 -7
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +94 -58
- package/gsd-core/bin/lib/vendor/README.md +31 -9
- package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
- package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +1165 -314
- package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
- package/gsd-core/bin/lib/verify.cjs +286 -567
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
- package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
- package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
- package/gsd-core/bin/lib/workstream.cjs +11 -2
- package/gsd-core/bin/shared/config-defaults.manifest.json +5 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +4 -0
- package/gsd-core/references/autonomous-smart-discuss.md +2 -1
- package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
- package/gsd-core/references/execute-mvp-tdd.md +5 -10
- package/gsd-core/references/execute-phase-between-wave-reset.md +3 -0
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +7 -1
- package/gsd-core/references/offer-next.md +1 -1
- package/gsd-core/references/planning-config.md +1 -1
- package/gsd-core/references/spidr-splitting.md +1 -1
- package/gsd-core/references/tdd.md +10 -4
- package/gsd-core/references/verifier-phase-gates.md +5 -2
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -3
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/UAT.md +17 -1
- package/gsd-core/templates/config.json +2 -11
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +8 -7
- package/gsd-core/workflows/add-tests.md +3 -2
- package/gsd-core/workflows/add-todo.md +4 -3
- package/gsd-core/workflows/ai-integration-phase.md +3 -2
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +4 -3
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous.md +28 -18
- package/gsd-core/workflows/check-todos.md +6 -5
- package/gsd-core/workflows/cleanup.md +1 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
- package/gsd-core/workflows/code-review-fix.md +5 -4
- package/gsd-core/workflows/code-review.md +84 -90
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
- package/gsd-core/workflows/complete-milestone.md +12 -7
- package/gsd-core/workflows/debug.md +30 -5
- package/gsd-core/workflows/diagnose-issues.md +3 -2
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +4 -3
- package/gsd-core/workflows/do.md +1 -1
- package/gsd-core/workflows/docs-update.md +4 -3
- package/gsd-core/workflows/edit-phase.md +4 -3
- package/gsd-core/workflows/eval-review.md +5 -3
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +4 -2
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
- package/gsd-core/workflows/execute-phase.md +78 -170
- package/gsd-core/workflows/execute-plan.md +13 -19
- package/gsd-core/workflows/explore.md +2 -2
- package/gsd-core/workflows/extract-learnings.md +3 -2
- package/gsd-core/workflows/fast.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +2 -1
- package/gsd-core/workflows/import.md +3 -2
- package/gsd-core/workflows/inbox.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +4 -3
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +5 -3
- package/gsd-core/workflows/map-codebase.md +4 -3
- package/gsd-core/workflows/milestone-summary.md +3 -2
- package/gsd-core/workflows/mvp-phase.md +14 -14
- package/gsd-core/workflows/new-milestone.md +10 -10
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +1 -1
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/pause-work.md +2 -2
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +1 -1
- package/gsd-core/workflows/plan-phase.md +27 -18
- package/gsd-core/workflows/plan-review-convergence.md +1 -1
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/pr-branch.md +1 -1
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress.md +19 -49
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -2
- package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +15 -10
- package/gsd-core/workflows/quick.md +42 -31
- package/gsd-core/workflows/remove-phase.md +3 -2
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +3 -2
- package/gsd-core/workflows/review.md +3 -2
- package/gsd-core/workflows/scan.md +3 -2
- package/gsd-core/workflows/secure-phase.md +11 -12
- package/gsd-core/workflows/settings-advanced.md +1 -1
- package/gsd-core/workflows/settings-integrations.md +1 -1
- package/gsd-core/workflows/settings.md +1 -1
- package/gsd-core/workflows/ship.md +12 -12
- package/gsd-core/workflows/sketch-wrap-up.md +1 -1
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +1 -1
- package/gsd-core/workflows/spec-phase.md +1 -1
- package/gsd-core/workflows/spike-wrap-up.md +1 -1
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +1 -1
- package/gsd-core/workflows/sync-skills.md +1 -1
- package/gsd-core/workflows/thread.md +2 -2
- package/gsd-core/workflows/transition.md +13 -23
- package/gsd-core/workflows/ui-phase.md +5 -4
- package/gsd-core/workflows/ui-review.md +4 -3
- package/gsd-core/workflows/ultraplan-phase.md +3 -2
- package/gsd-core/workflows/undo.md +1 -1
- package/gsd-core/workflows/validate-phase.md +10 -12
- package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
- package/gsd-core/workflows/verify-work.md +68 -59
- package/hooks/dist/gsd-agent-isolation-guard.js +8 -0
- package/hooks/dist/gsd-check-update-worker.js +8 -0
- package/hooks/dist/gsd-check-update.js +8 -0
- package/hooks/dist/gsd-context-monitor.js +31 -8
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
- package/hooks/dist/gsd-secret-read-guard.js +147 -16
- package/hooks/dist/gsd-statusline.js +15 -7
- package/hooks/dist/gsd-update-banner.js +8 -0
- package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
- package/hooks/dist/gsd-workflow-guard.js +5 -4
- package/hooks/dist/gsd-worktree-path-guard.js +6 -2
- package/hooks/dist/lib/cli-exit.js +12 -0
- package/hooks/dist/lib/git-probe.js +17 -1
- package/hooks/dist/lib/isolation-sentinel.js +2 -2
- package/hooks/gsd-agent-isolation-guard.js +8 -0
- package/hooks/gsd-check-update-worker.js +8 -0
- package/hooks/gsd-check-update.js +8 -0
- package/hooks/gsd-context-monitor.js +31 -8
- package/hooks/gsd-cursor-subagent-start.js +8 -0
- package/hooks/gsd-secret-read-guard.js +147 -16
- package/hooks/gsd-statusline.js +15 -7
- package/hooks/gsd-update-banner.js +8 -0
- package/hooks/gsd-windsurf-pre-write.js +11 -2
- package/hooks/gsd-workflow-guard.js +5 -4
- package/hooks/gsd-worktree-path-guard.js +6 -2
- package/hooks/hooks.json +5 -5
- package/hooks/lib/cli-exit.js +12 -0
- package/hooks/lib/git-probe.js +17 -1
- package/hooks/lib/isolation-sentinel.js +2 -2
- package/package.json +21 -4
- package/scripts/changeset/parse.cjs +52 -4
- package/scripts/ci-timeout-report.cjs +770 -4
- package/scripts/command-contract-helpers.cjs +12 -8
- package/scripts/docs-guard-registry.cjs +6 -0
- package/scripts/gen-features.cjs +13 -8
- package/scripts/gen-hooks-cli-exit.cjs +12 -28
- package/scripts/gen-loop-host-contract.cjs +10 -1
- package/scripts/gen-platform-conformance-tier.cjs +187 -1
- package/scripts/gen-plugin-skills.cjs +87 -1
- package/scripts/gen-research-agents.cjs +24 -31
- package/scripts/gen-scripts-cli-exit.cjs +30 -3
- package/scripts/gen-test-timings.cjs +32 -7
- package/scripts/lib/cli-exit.cjs +12 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +20 -2
- package/scripts/lib/ndjson-reporter.cjs +28 -3
- package/scripts/lib/platform-conformance-tier.generated.cjs +34 -5
- package/scripts/lib/registration-ledger-preload.cjs +155 -0
- package/scripts/lib/vendor-bundle.cjs +59 -0
- package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-completion-predicate-drift.cjs +18 -19
- package/scripts/lint-descriptions.cjs +7 -3
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +10 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
- package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
- package/scripts/lint-phase-enumeration-drift.cjs +12 -8
- package/scripts/lint-phase-id-drift.cjs +29 -0
- package/scripts/lint-planning-document-positive-control.cjs +329 -0
- package/scripts/lint-response-language-coverage.cjs +3 -0
- package/scripts/lint-skill-deps.cjs +7 -3
- package/scripts/lint-test-file-count.allowlist.json +11 -1
- package/scripts/lint-test-file-count.cjs +34 -1
- package/scripts/lint-vendored-deps.cjs +41 -5
- package/scripts/lint-workflow-shellcheck-baseline.json +10 -10
- package/scripts/mutation-matrix.cjs +50 -5
- package/scripts/require-issue-link-policy.cjs +6 -2
- package/scripts/sync-runtime-launcher.cjs +184 -2
- package/scripts/verify-npm-publish.cjs +76 -20
- package/skills/gsd-add-tests/SKILL.md +6 -1
- package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
- package/skills/gsd-audit-fix/SKILL.md +5 -0
- package/skills/gsd-audit-milestone/SKILL.md +6 -1
- package/skills/gsd-autonomous/SKILL.md +5 -0
- package/skills/gsd-capture/SKILL.md +8 -4
- package/skills/gsd-code-review/SKILL.md +7 -2
- package/skills/gsd-complete-milestone/SKILL.md +4 -0
- package/skills/gsd-config/SKILL.md +8 -4
- package/skills/gsd-debug/SKILL.md +11 -7
- package/skills/gsd-discuss-phase/SKILL.md +7 -3
- package/skills/gsd-docs-update/SKILL.md +12 -7
- package/skills/gsd-eval-review/SKILL.md +6 -1
- package/skills/gsd-execute-phase/SKILL.md +12 -7
- package/skills/gsd-extract-learnings/SKILL.md +5 -0
- package/skills/gsd-fast/SKILL.md +4 -0
- package/skills/gsd-forensics/SKILL.md +5 -1
- package/skills/gsd-graphify/SKILL.md +10 -6
- package/skills/gsd-health/SKILL.md +5 -0
- package/skills/gsd-help/SKILL.md +7 -2
- package/skills/gsd-import/SKILL.md +7 -3
- package/skills/gsd-inbox/SKILL.md +5 -0
- package/skills/gsd-ingest-docs/SKILL.md +5 -1
- package/skills/gsd-manager/SKILL.md +6 -1
- package/skills/gsd-map-codebase/SKILL.md +7 -3
- package/skills/gsd-mempalace-capture/SKILL.md +5 -1
- package/skills/gsd-mempalace-recall/SKILL.md +5 -1
- package/skills/gsd-milestone-summary/SKILL.md +5 -1
- package/skills/gsd-mvp-phase/SKILL.md +8 -3
- package/skills/gsd-new-milestone/SKILL.md +6 -1
- package/skills/gsd-new-project/SKILL.md +5 -0
- package/skills/gsd-next/SKILL.md +6 -1
- package/skills/gsd-ns-context/SKILL.md +4 -0
- package/skills/gsd-ns-ideate/SKILL.md +4 -0
- package/skills/gsd-ns-manage/SKILL.md +4 -0
- package/skills/gsd-ns-project/SKILL.md +4 -0
- package/skills/gsd-ns-review/SKILL.md +4 -0
- package/skills/gsd-ns-workflow/SKILL.md +4 -0
- package/skills/gsd-onboard/SKILL.md +6 -1
- package/skills/gsd-pause-work/SKILL.md +5 -1
- package/skills/gsd-phase/SKILL.md +8 -4
- package/skills/gsd-plan-phase/SKILL.md +6 -1
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
- package/skills/gsd-pr-branch/SKILL.md +4 -0
- package/skills/gsd-profile-user/SKILL.md +5 -1
- package/skills/gsd-progress/SKILL.md +6 -1
- package/skills/gsd-quick/SKILL.md +16 -10
- package/skills/gsd-quick-batch/SKILL.md +20 -8
- package/skills/gsd-review/SKILL.md +5 -1
- package/skills/gsd-review-backlog/SKILL.md +3 -2
- package/skills/gsd-secure-phase/SKILL.md +6 -1
- package/skills/gsd-ship/SKILL.md +5 -0
- package/skills/gsd-sketch/SKILL.md +7 -2
- package/skills/gsd-spec-phase/SKILL.md +5 -1
- package/skills/gsd-spike/SKILL.md +8 -3
- package/skills/gsd-surface/SKILL.md +5 -1
- package/skills/gsd-thread/SKILL.md +4 -0
- package/skills/gsd-ui-phase/SKILL.md +6 -1
- package/skills/gsd-ui-review/SKILL.md +6 -1
- package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
- package/skills/gsd-undo/SKILL.md +5 -1
- package/skills/gsd-update/SKILL.md +6 -2
- package/skills/gsd-validate-phase/SKILL.md +6 -1
- package/skills/gsd-verify-work/SKILL.md +6 -1
- package/skills/gsd-workspace/SKILL.md +7 -3
- package/skills/gsd-workstreams/SKILL.md +6 -6
- package/vscode/package.json +1 -1
- package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +0 -24
|
@@ -141,6 +141,38 @@ function buildTestMap(prodPrefixes, allTestFiles) {
|
|
|
141
141
|
return map;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
// #5074: a `<stem>.platform.test.cjs` alongside `<stem>.test.cjs` (or
|
|
145
|
+
// `.test.ts`) in the SAME directory is the other half of that primary file —
|
|
146
|
+
// the platform-sensitive slice extracted so the Windows CI selector runs
|
|
147
|
+
// only the small sibling — not an additional test file. Exclude it from the
|
|
148
|
+
// per-module count and from the allowlist identity comparison. A
|
|
149
|
+
// `.platform.test.cjs` with no base file in the same directory counts
|
|
150
|
+
// normally, so the rule cannot be used to smuggle in new standalone files.
|
|
151
|
+
// An empty stem (bare `platform.test.cjs`) is never treated as a sibling.
|
|
152
|
+
const PLATFORM_SIBLING_RE = /^(.+)\.platform\.test\.(cjs|ts)$/;
|
|
153
|
+
|
|
154
|
+
function isSplitSibling(fileBasename, siblingBasenamesInDir) {
|
|
155
|
+
const m = fileBasename.match(PLATFORM_SIBLING_RE);
|
|
156
|
+
if (!m) return false;
|
|
157
|
+
const stem = m[1];
|
|
158
|
+
if (!stem) return false;
|
|
159
|
+
return siblingBasenamesInDir.includes(`${stem}.test.cjs`) ||
|
|
160
|
+
siblingBasenamesInDir.includes(`${stem}.test.ts`);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function excludeSplitSiblings(testFiles) {
|
|
164
|
+
const basenamesByDir = new Map();
|
|
165
|
+
for (const f of testFiles) {
|
|
166
|
+
const dir = path.dirname(f);
|
|
167
|
+
if (!basenamesByDir.has(dir)) basenamesByDir.set(dir, []);
|
|
168
|
+
basenamesByDir.get(dir).push(path.basename(f));
|
|
169
|
+
}
|
|
170
|
+
return testFiles.filter(f => {
|
|
171
|
+
const dir = path.dirname(f);
|
|
172
|
+
return !isSplitSibling(path.basename(f), basenamesByDir.get(dir));
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
144
176
|
function loadAllowlist() {
|
|
145
177
|
try { return JSON.parse(fs.readFileSync(ALLOWLIST_PATH, 'utf-8')).modules || {}; }
|
|
146
178
|
catch (_) { return {}; }
|
|
@@ -160,6 +192,7 @@ function loadAllowlist() {
|
|
|
160
192
|
* Returns { verdict, prefix, count, knownFiles, novel, stale, files }
|
|
161
193
|
*/
|
|
162
194
|
function evaluateLint({ prefix, testFiles, allowlist }) {
|
|
195
|
+
testFiles = excludeSplitSiblings(testFiles);
|
|
163
196
|
const count = testFiles.length;
|
|
164
197
|
const entry = allowlist[prefix];
|
|
165
198
|
const currentNames = testFiles.map(f => path.basename(f));
|
|
@@ -258,7 +291,7 @@ function run() {
|
|
|
258
291
|
}
|
|
259
292
|
|
|
260
293
|
module.exports = {
|
|
261
|
-
Verdict, evaluateLint, testEffectivePrefix, prodPrefix,
|
|
294
|
+
Verdict, evaluateLint, testEffectivePrefix, prodPrefix, isSplitSibling,
|
|
262
295
|
_collectProdPrefixes: collectProdPrefixes,
|
|
263
296
|
_collectAllTestFiles: collectAllTestFiles,
|
|
264
297
|
_buildTestMap: buildTestMap,
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
const fs = require('node:fs');
|
|
58
58
|
const path = require('node:path');
|
|
59
59
|
const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
|
60
|
+
const { buildVendorBundle } = require('./lib/vendor-bundle.cjs');
|
|
60
61
|
|
|
61
62
|
const ROOT = path.join(__dirname, '..');
|
|
62
63
|
|
|
@@ -89,16 +90,29 @@ function resolvePath(p) {
|
|
|
89
90
|
* or null when there is no bin-side type twin
|
|
90
91
|
* @property {string|null} srcTwin path under src/vendor/ to the source-side type twin tsc
|
|
91
92
|
* resolves for a relative import from src/**, or null
|
|
92
|
-
* @property {
|
|
93
|
+
* @property {boolean} [bundle] Reproducibly bundle upstream and its locked dependencies.
|
|
94
|
+
* @property {'upstream-verbatim'|'upstream-reference'|'hand-authored'} twinKind
|
|
93
95
|
* 'upstream-verbatim': srcTwin/vendoredDts are byte-compared
|
|
94
96
|
* against upstream and each other.
|
|
95
97
|
* 'hand-authored': no upstream counterpart exists, so the
|
|
96
98
|
* twin is excluded from the byte-compare (checks 2 and 3
|
|
97
99
|
* above are skipped for this row).
|
|
100
|
+
* 'upstream-reference': srcTwin must be exactly
|
|
101
|
+
* `export * from '<name>';` (bundled rows).
|
|
98
102
|
*/
|
|
99
103
|
|
|
100
104
|
/** @type {VendoredPackage[]} */
|
|
101
105
|
const VENDORED = [
|
|
106
|
+
...['tap-parser', 'saxes'].map((name) => ({
|
|
107
|
+
name,
|
|
108
|
+
upstreamCjs: name === 'tap-parser' ? 'node_modules/tap-parser/dist/commonjs/index.js' : 'node_modules/saxes/saxes.js',
|
|
109
|
+
vendoredCjs: `gsd-core/bin/lib/vendor/${name}.cjs`,
|
|
110
|
+
upstreamDts: null,
|
|
111
|
+
vendoredDts: null,
|
|
112
|
+
srcTwin: `src/vendor/${name}.d.cts`,
|
|
113
|
+
twinKind: 'upstream-reference',
|
|
114
|
+
bundle: true,
|
|
115
|
+
})),
|
|
102
116
|
{
|
|
103
117
|
name: 're2js',
|
|
104
118
|
upstreamCjs: 'node_modules/re2js/build/index.cjs',
|
|
@@ -127,6 +141,7 @@ const VENDORED = [
|
|
|
127
141
|
* @returns {string}
|
|
128
142
|
*/
|
|
129
143
|
function buildRefreshCommand(row) {
|
|
144
|
+
if (row.bundle) return 'npm run lint:vendored-deps -- --fix';
|
|
130
145
|
const parts = [`cp ${row.upstreamCjs} ${row.vendoredCjs}`];
|
|
131
146
|
if (row.twinKind === 'upstream-verbatim' && row.upstreamDts) {
|
|
132
147
|
if (row.vendoredDts) parts.push(`cp ${row.upstreamDts} ${row.vendoredDts}`);
|
|
@@ -135,7 +150,8 @@ function buildRefreshCommand(row) {
|
|
|
135
150
|
return parts.join(' && ');
|
|
136
151
|
}
|
|
137
152
|
|
|
138
|
-
|
|
153
|
+
// Bundled rows share one refresh command; list it once.
|
|
154
|
+
const REFRESH_COMMAND = [...new Set(VENDORED.map(buildRefreshCommand))].join(' && ');
|
|
139
155
|
|
|
140
156
|
/**
|
|
141
157
|
* Compare two files byte-for-byte. Returns null when equal, or a short
|
|
@@ -263,8 +279,17 @@ function readPinState(row, pkgRoot = ROOT) {
|
|
|
263
279
|
function checkRow(row, pkgRoot = ROOT) {
|
|
264
280
|
const findings = [];
|
|
265
281
|
|
|
266
|
-
|
|
267
|
-
|
|
282
|
+
if (row.bundle) {
|
|
283
|
+
const built = buildVendorBundle(pkgRoot, row.upstreamCjs);
|
|
284
|
+
for (const [file, expected] of [[row.vendoredCjs, built.code], [`${row.vendoredCjs}.LICENSE.txt`, built.notices]]) {
|
|
285
|
+
if (!fs.existsSync(resolvePath(file)) || !fs.readFileSync(resolvePath(file)).equals(expected)) {
|
|
286
|
+
findings.push(`${file} != reproducible upstream bundle (including license notices)`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
const cjsDrift = compareFiles(row.vendoredCjs, row.upstreamCjs);
|
|
291
|
+
if (cjsDrift) findings.push(cjsDrift);
|
|
292
|
+
}
|
|
268
293
|
|
|
269
294
|
if (row.twinKind === 'upstream-verbatim') {
|
|
270
295
|
if (row.upstreamDts && row.vendoredDts) {
|
|
@@ -277,6 +302,11 @@ function checkRow(row, pkgRoot = ROOT) {
|
|
|
277
302
|
}
|
|
278
303
|
} else if (row.twinKind === 'hand-authored') {
|
|
279
304
|
findings.push(...checkHandAuthoredTwin(row));
|
|
305
|
+
} else if (row.twinKind === 'upstream-reference') {
|
|
306
|
+
const expected = `export * from '${row.name}';\n`;
|
|
307
|
+
if (!row.srcTwin || !fs.existsSync(resolvePath(row.srcTwin)) || fs.readFileSync(resolvePath(row.srcTwin), 'utf8') !== expected) {
|
|
308
|
+
findings.push(`${row.name}: type twin must forward the upstream declarations verbatim`);
|
|
309
|
+
}
|
|
280
310
|
}
|
|
281
311
|
|
|
282
312
|
const { pinnedSpec, installedVersion } = readPinState(row, pkgRoot);
|
|
@@ -318,7 +348,13 @@ function checkRow(row, pkgRoot = ROOT) {
|
|
|
318
348
|
* @returns {string[]} findings remaining after the fix (empty when fully resolved)
|
|
319
349
|
*/
|
|
320
350
|
function fixRow(row, pkgRoot = ROOT) {
|
|
321
|
-
|
|
351
|
+
if (row.bundle) {
|
|
352
|
+
const built = buildVendorBundle(pkgRoot, row.upstreamCjs);
|
|
353
|
+
fs.writeFileSync(resolvePath(row.vendoredCjs), built.code);
|
|
354
|
+
fs.writeFileSync(resolvePath(`${row.vendoredCjs}.LICENSE.txt`), built.notices);
|
|
355
|
+
} else {
|
|
356
|
+
fs.copyFileSync(resolvePath(row.upstreamCjs), resolvePath(row.vendoredCjs));
|
|
357
|
+
}
|
|
322
358
|
|
|
323
359
|
if (row.twinKind === 'upstream-verbatim' && row.upstreamDts) {
|
|
324
360
|
if (row.vendoredDts) fs.copyFileSync(resolvePath(row.upstreamDts), resolvePath(row.vendoredDts));
|
|
@@ -354,11 +354,6 @@
|
|
|
354
354
|
"code": "2012",
|
|
355
355
|
"message": "Use find instead of ls to better handle non-alphanumeric filenames."
|
|
356
356
|
},
|
|
357
|
-
{
|
|
358
|
-
"file": "gsd-core/workflows/execute-phase.md",
|
|
359
|
-
"code": "2012",
|
|
360
|
-
"message": "Use find instead of ls to better handle non-alphanumeric filenames."
|
|
361
|
-
},
|
|
362
357
|
{
|
|
363
358
|
"file": "gsd-core/workflows/execute-phase.md",
|
|
364
359
|
"code": "2016",
|
|
@@ -384,11 +379,6 @@
|
|
|
384
379
|
"code": "2086",
|
|
385
380
|
"message": "Double quote to prevent globbing and word splitting."
|
|
386
381
|
},
|
|
387
|
-
{
|
|
388
|
-
"file": "gsd-core/workflows/execute-phase.md",
|
|
389
|
-
"code": "2086",
|
|
390
|
-
"message": "Double quote to prevent globbing and word splitting."
|
|
391
|
-
},
|
|
392
382
|
{
|
|
393
383
|
"file": "gsd-core/workflows/execute-phase/detail/elaboration.md",
|
|
394
384
|
"code": "2086",
|
|
@@ -414,6 +404,16 @@
|
|
|
414
404
|
"code": "2086",
|
|
415
405
|
"message": "Double quote to prevent globbing and word splitting."
|
|
416
406
|
},
|
|
407
|
+
{
|
|
408
|
+
"file": "gsd-core/workflows/execute-phase/steps/verify-phase-goal.md",
|
|
409
|
+
"code": "2012",
|
|
410
|
+
"message": "Use find instead of ls to better handle non-alphanumeric filenames."
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"file": "gsd-core/workflows/execute-phase/steps/verify-phase-goal.md",
|
|
414
|
+
"code": "2086",
|
|
415
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
416
|
+
},
|
|
417
417
|
{
|
|
418
418
|
"file": "gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md",
|
|
419
419
|
"code": "2086",
|
|
@@ -402,11 +402,22 @@ const COVERED = {
|
|
|
402
402
|
// extraTests above) rather than deleted, so the mutants they kill stay killed.
|
|
403
403
|
// frontmatter.test.cjs itself is UNCHANGED and keeps running in the normal
|
|
404
404
|
// (non-mutation) suite — only the mutation shard drops it.
|
|
405
|
+
// - frontmatter-splice.property.test.cjs (#5105): the writer's own property suite,
|
|
406
|
+
// moved out of frontmatter.property.test.cjs when spliceFrontmatter moved to
|
|
407
|
+
// frontmatter-splice.cts. It requires frontmatter.cjs only as the read-back oracle and
|
|
408
|
+
// matches this module's "frontmatter-" prefix, so the derivation would pull it in here;
|
|
409
|
+
// it runs in the frontmatter-splice shard instead. Keeping it out of this shard is the
|
|
410
|
+
// point of the split: the frontmatter shard was cancelled at its 20-minute cap on PR
|
|
411
|
+
// #5114 (1149/1749 mutants tested) with these splice-heavy properties re-run for every
|
|
412
|
+
// parser mutant they happened to cover.
|
|
405
413
|
excludeTests: [
|
|
406
414
|
'frontmatter-cli.test.cjs',
|
|
415
|
+
'frontmatter-splice.property.test.cjs',
|
|
407
416
|
'frontmatter.test.cjs',
|
|
408
417
|
],
|
|
409
|
-
|
|
418
|
+
// 87.72% in CI run 36590493522 on PR #5114 (#5105 added in-process command tests).
|
|
419
|
+
// Floor = floor(87.72) - 1 = 86.
|
|
420
|
+
minScore: 86,
|
|
410
421
|
// MEASUREMENT, not a projection. Under the tap runner with coverageAnalysis: 'perTest'
|
|
411
422
|
// (#3915), Stryker now re-runs only the test files that cover each mutated line instead
|
|
412
423
|
// of all six files for every one of ~1900 mutants. Measured result: the frontmatter shard
|
|
@@ -428,6 +439,37 @@ const COVERED = {
|
|
|
428
439
|
// The prior audit's 'none' vs 'process' comparison (recorded here before this change)
|
|
429
440
|
// is moot: there is nothing left to opt in or out of.
|
|
430
441
|
},
|
|
442
|
+
// frontmatter-splice: net-new module from #5105 — the frontmatter WRITER (spliceFrontmatter
|
|
443
|
+
// and its layout slicing, comment classification, parse budget, key quoting and read-back
|
|
444
|
+
// check), split out of frontmatter.cts by module ownership. Before the split the writer grew
|
|
445
|
+
// frontmatter.cjs from 1249 to 1749 mutants and the frontmatter shard was cancelled at its
|
|
446
|
+
// 20-minute cap (PR #5114, run 36577087588, job 109435636296: 1149/1749 tested at ~1.34
|
|
447
|
+
// s/covered mutant). Stryker's instrumenter counts 1267 mutants in frontmatter.cjs and 498 in
|
|
448
|
+
// frontmatter-splice.cjs after the split. Registered here so the writer is scored at all —
|
|
449
|
+
// mutation coverage does not migrate with relocated code (the context-composer precedent).
|
|
450
|
+
//
|
|
451
|
+
// Tests: frontmatter-splice.property.test.cjs is auto-derived (requires this module, matches
|
|
452
|
+
// the naming rule). extraTests are the other files that drive spliceFrontmatter directly —
|
|
453
|
+
// they are named after frontmatter, so the derivation cannot find them for this module:
|
|
454
|
+
// - frontmatter.unit.test.cjs: the #1572/#1660/#3257/#3742/#4802 splice cases.
|
|
455
|
+
// - frontmatter.property.test.cjs: the #644 prohibitions parse -> splice -> re-parse
|
|
456
|
+
// bijection.
|
|
457
|
+
// - frontmatter-fence.test.cjs: the writer's BOM / CRLF / empty-block fence cases.
|
|
458
|
+
//
|
|
459
|
+
// minScore 62: the module was first registered with a provisional floor of 50 (the minimum
|
|
460
|
+
// the ratchet test permits, tests/mutation-matrix-ratchet.test.cjs:107-116) because the shard
|
|
461
|
+
// cannot run locally (see HOW TO UPDATE above). The first CI measurement was 63.82% (CI run
|
|
462
|
+
// 36586350120, PR #5114), so the floor is set to floor(63.82) - 1 = 62, following this file's
|
|
463
|
+
// convention, together with its RATCHET_BASELINE entry.
|
|
464
|
+
'frontmatter-splice': {
|
|
465
|
+
cjs: 'gsd-core/bin/lib/frontmatter-splice.cjs',
|
|
466
|
+
extraTests: [
|
|
467
|
+
'frontmatter-fence.test.cjs',
|
|
468
|
+
'frontmatter.property.test.cjs',
|
|
469
|
+
'frontmatter.unit.test.cjs',
|
|
470
|
+
],
|
|
471
|
+
minScore: 62,
|
|
472
|
+
},
|
|
431
473
|
// adr-parser / config-schema / active-workstream-store / core-utils: derivation reproduces
|
|
432
474
|
// their prior hand lists exactly (every constraining file's own name already matched the
|
|
433
475
|
// "<module>*" rule) — no extraTests/excludeTests needed. Note config-schema in particular:
|
|
@@ -456,7 +498,10 @@ const COVERED = {
|
|
|
456
498
|
},
|
|
457
499
|
'core-utils': {
|
|
458
500
|
cjs: 'gsd-core/bin/lib/core-utils.cjs',
|
|
459
|
-
|
|
501
|
+
// measured 77.52% (2026-06-14, issue #1187); floor = 77 - 2.
|
|
502
|
+
// CI job 109435636183 (PR #5114, #5105): measured 81.13%. Floor =
|
|
503
|
+
// floor(81.13) - 1 = 80.
|
|
504
|
+
minScore: 80,
|
|
460
505
|
},
|
|
461
506
|
// planning-inspect / plan-document / planning-command-router: net-new modules
|
|
462
507
|
// added by #2790. Registered here so the Stryker gate stops SKIPPING them
|
|
@@ -484,7 +529,7 @@ const COVERED = {
|
|
|
484
529
|
// PASSED — not a local run; mutation shards run `node --test`, hard-blocked
|
|
485
530
|
// in this repo's local environment):
|
|
486
531
|
// planning-command-router 95.65% → floor 94 (already exceeds TARGET_MUTATION_SCORE (80))
|
|
487
|
-
// plan-document 76.58% → floor 75
|
|
532
|
+
// plan-document 76.58% → floor 75; then 81.16% → floor 80 (#5026 parity tests)
|
|
488
533
|
// planning-inspect 57.03% → floor 56 (well below TARGET (80) — ratchet
|
|
489
534
|
// candidate; comfortably clears its own floor but has real room to grow.
|
|
490
535
|
// Raise as its tests improve, never lower it.)
|
|
@@ -507,7 +552,7 @@ const COVERED = {
|
|
|
507
552
|
'planning-inspect': {
|
|
508
553
|
cjs: 'gsd-core/bin/lib/planning-inspect.cjs',
|
|
509
554
|
excludeTests: ['planning-inspect.test.cjs'],
|
|
510
|
-
minScore:
|
|
555
|
+
minScore: 72, // #5118: 73.70% in CI run 36676296090; floor(73.70) - 1
|
|
511
556
|
},
|
|
512
557
|
// plan-document / planning-command-router: their own names never appear in any test
|
|
513
558
|
// filename (the shared dedicated unit file is named after planning-inspect, the module
|
|
@@ -516,7 +561,7 @@ const COVERED = {
|
|
|
516
561
|
'plan-document': {
|
|
517
562
|
cjs: 'gsd-core/bin/lib/plan-document.cjs',
|
|
518
563
|
extraTests: ['planning-inspect.unit.test.cjs'],
|
|
519
|
-
minScore:
|
|
564
|
+
minScore: 80,
|
|
520
565
|
},
|
|
521
566
|
'planning-command-router': {
|
|
522
567
|
cjs: 'gsd-core/bin/lib/planning-command-router.cjs',
|
|
@@ -53,7 +53,10 @@ const DEPENDABOT_LOGIN = 'dependabot[bot]';
|
|
|
53
53
|
// A follow-up-only PR (references an issue without closing it) is only
|
|
54
54
|
// allowed to skip the closing keyword when every changed file is a test or
|
|
55
55
|
// doc file — i.e. it cannot be the PR that actually implements the fix.
|
|
56
|
-
|
|
56
|
+
// #5061: .out-of-scope/ knowledge-base entries are informational documents,
|
|
57
|
+
// already doc-only in pre-pr-gate.sh's DOC_ONLY_RE. Only `*.md` entries
|
|
58
|
+
// qualify there (see allPathsAreTestsOrDocs): the KB holds nothing else.
|
|
59
|
+
const EXEMPT_PATH_PREFIXES = ['tests/', 'docs/', '.out-of-scope/'];
|
|
57
60
|
|
|
58
61
|
// Root-level markdown is documentation — this mirrors the repo's own doc-only
|
|
59
62
|
// classifier (.claude/hooks/pre-pr-gate.sh:111), whose `[^/]+\.md` anchor is
|
|
@@ -115,7 +118,7 @@ function normalizePath(p) {
|
|
|
115
118
|
/**
|
|
116
119
|
* Returns true iff every changed file qualifies as a test/doc file, i.e. each
|
|
117
120
|
* one is one of:
|
|
118
|
-
* 1. under one of EXEMPT_PATH_PREFIXES (`tests/`, `docs/`) — the trailing
|
|
121
|
+
* 1. under one of EXEMPT_PATH_PREFIXES (`tests/`, `docs/`, `.out-of-scope/`) — the trailing
|
|
119
122
|
* slash on each prefix makes this directory-boundary aware, so
|
|
120
123
|
* lookalikes like `tests-e2e/`, `testsuite/`, or `docsite/` are
|
|
121
124
|
* correctly rejected (they are not `tests/` or `docs/`); or
|
|
@@ -126,6 +129,7 @@ function allPathsAreTestsOrDocs(changedFiles) {
|
|
|
126
129
|
if (!Array.isArray(changedFiles) || changedFiles.length === 0) return false;
|
|
127
130
|
return changedFiles.every((file) => {
|
|
128
131
|
const normalized = normalizePath(file);
|
|
132
|
+
if (normalized.startsWith('.out-of-scope/')) return /\.md$/i.test(normalized);
|
|
129
133
|
if (EXEMPT_PATH_PREFIXES.some((prefix) => normalized.startsWith(prefix))) return true;
|
|
130
134
|
return isRootLevelDoc(normalized);
|
|
131
135
|
});
|
|
@@ -272,6 +272,49 @@ function insertPreamble(lines, preamble) {
|
|
|
272
272
|
return [...before, ...preamble, ...after];
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
+
/**
|
|
276
|
+
* The first two statements EVERY version of the launcher preamble opens with
|
|
277
|
+
* (`_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT=`). Matching the pair, not
|
|
278
|
+
* the bare `_GSD_SHIM_NAME=` prefix, means a prose sample or an intentionally
|
|
279
|
+
* different resolver that happens to start a line with the variable name is never
|
|
280
|
+
* mistaken for the preamble and never rewritten (#5169 review).
|
|
281
|
+
*/
|
|
282
|
+
const PREAMBLE_LINE_RE = /^_GSD_SHIM_NAME="gsd-tools\.cjs"; _GSD_RUNTIME_ROOT=/;
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Index of the line that starts a launcher preamble inside `lines`, or -1.
|
|
286
|
+
*
|
|
287
|
+
* Matched by the marker every version of the preamble opens with
|
|
288
|
+
* (`_GSD_SHIM_NAME=`), NOT by equality with the CURRENT text: the sync runs
|
|
289
|
+
* precisely when the snippet changed, so the copy in the file is by definition an
|
|
290
|
+
* older version, and an exact match never found it — which hoisted a guard-fronted
|
|
291
|
+
* preamble to the top of its block on every snippet change (#5169; caught by the
|
|
292
|
+
* #3861 guard-only extraction in tests/code-review-pipeline-regression.test.cjs).
|
|
293
|
+
*/
|
|
294
|
+
function findPreambleStart(lines) {
|
|
295
|
+
return lines.findIndex((l) => PREAMBLE_LINE_RE.test(l));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Place the preamble in a block that ALREADY carried it. A block that opens
|
|
300
|
+
* with a guard (a status check that must run before any launcher resolution,
|
|
301
|
+
* e.g. execute-phase/steps/code-review-disposition.md, #3861) keeps the preamble
|
|
302
|
+
* BEHIND that guard: hoisting it to the top would put the resolver ahead of the
|
|
303
|
+
* guard and change what the guard-only extraction in the tests runs. A block
|
|
304
|
+
* whose preamble already sits at the top (after blank lines), or that had none,
|
|
305
|
+
* takes the ordinary top insertion.
|
|
306
|
+
*
|
|
307
|
+
* The position is kept in STRIPPED coordinates: the lines before the preamble
|
|
308
|
+
* are stripped on their own and their length is the insertion point.
|
|
309
|
+
*/
|
|
310
|
+
function insertPreambleKeepingGuard(original, stripped, preamble) {
|
|
311
|
+
const k = findPreambleStart(original);
|
|
312
|
+
const firstContent = original.findIndex((l) => l.trim() !== '');
|
|
313
|
+
if (k <= firstContent) return insertPreamble(stripped, preamble);
|
|
314
|
+
const at = stripAndReplace(original.slice(0, k), preamble).length;
|
|
315
|
+
return [...stripped.slice(0, at), ...preamble, ...stripped.slice(at)];
|
|
316
|
+
}
|
|
317
|
+
|
|
275
318
|
/**
|
|
276
319
|
* Transform a single markdown file's content.
|
|
277
320
|
* Returns new content string, or null if no changes needed.
|
|
@@ -366,7 +409,9 @@ function transformFile(content, preamble) {
|
|
|
366
409
|
const delegates = delegatesToResolverReference(content);
|
|
367
410
|
const finalBlocks = strippedBlocks.map((stripped, bi) => {
|
|
368
411
|
if (!delegates && bi === preambleTargetIdx) {
|
|
369
|
-
|
|
412
|
+
const range = shellBlockRanges[bi];
|
|
413
|
+
const original = allLines.slice(range.contentStart, range.contentEnd);
|
|
414
|
+
return insertPreambleKeepingGuard(original, stripped, preamble);
|
|
370
415
|
}
|
|
371
416
|
return stripped;
|
|
372
417
|
});
|
|
@@ -405,9 +450,137 @@ function delegatesToResolverReference(content) {
|
|
|
405
450
|
return content.includes('references/gsd-run-resolver.md');
|
|
406
451
|
}
|
|
407
452
|
|
|
453
|
+
// ---------------------------------------------------------------------------
|
|
454
|
+
// `_gsd_homes` — the launcher's runtime-home candidate list, DERIVED from the
|
|
455
|
+
// runtime descriptors (#5169, ADR-5057 §5 "one resolver", #4347).
|
|
456
|
+
//
|
|
457
|
+
// The JS resolver (src/runtime-homes.cts) resolves a runtime's home from its
|
|
458
|
+
// `configHome` descriptor. The shell launcher used to carry a hand-written copy
|
|
459
|
+
// of that list and drifted (it still probed GEMINI_CONFIG_DIR after the runtime
|
|
460
|
+
// was retired, and omitted zcode/pi/kimi). Both now read the same registry:
|
|
461
|
+
// this renderer is the only producer of the `_gsd_homes` text in the snippet,
|
|
462
|
+
// and tests/runtime-launcher-parity.test.cjs fails when the snippet differs
|
|
463
|
+
// from it.
|
|
464
|
+
// ---------------------------------------------------------------------------
|
|
465
|
+
|
|
466
|
+
const HOMES_START = '_gsd_homes() { ';
|
|
467
|
+
const HOMES_END = '; }; if _gsd_at';
|
|
468
|
+
|
|
469
|
+
function shellHomeExpr(configHome) {
|
|
470
|
+
const dotHome = (rel) => `$HOME/${rel}`;
|
|
471
|
+
const withEnvs = (envs, fallback) => envs.reduceRight((acc, name) => `\${${name}:-${acc}}`, fallback);
|
|
472
|
+
switch (configHome.kind) {
|
|
473
|
+
case 'dot-home':
|
|
474
|
+
return [withEnvs(configHome.env, dotHome(configHome.name))];
|
|
475
|
+
case 'dot-home-nested': {
|
|
476
|
+
const probes = configHome.probe && configHome.probe.length > 0 ? configHome.probe : [configHome.name];
|
|
477
|
+
const first = withEnvs(configHome.env.slice(0, 1), dotHome(`${configHome.parent}/${probes[0]}`));
|
|
478
|
+
return [first, ...probes.slice(1).map((p) => dotHome(`${configHome.parent}/${p}`))];
|
|
479
|
+
}
|
|
480
|
+
case 'xdg': {
|
|
481
|
+
const xdgVar = configHome.env[2];
|
|
482
|
+
const base = xdgVar ? `\${${xdgVar}:-$HOME/.config}` : '$HOME/.config';
|
|
483
|
+
return [withEnvs(configHome.env.slice(0, 1), `${base}/${configHome.name}`)];
|
|
484
|
+
}
|
|
485
|
+
case 'generic-agents-root': {
|
|
486
|
+
const probes = configHome.probe.map((p) => p.replace(/^~/, '$HOME'));
|
|
487
|
+
return [withEnvs(configHome.env.slice(0, 1), probes[0]), ...probes.slice(1)];
|
|
488
|
+
}
|
|
489
|
+
default:
|
|
490
|
+
return []; // kind "none": no file-projected home, nothing to probe
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/** The `_gsd_homes() { _gsd_at ...; }` text for a registry + legacy-home table. */
|
|
495
|
+
function renderHomesFunction(registry, legacyHomes) {
|
|
496
|
+
const ids = Object.keys(registry.runtimes).sort((a, b) =>
|
|
497
|
+
a === 'claude' ? -1 : b === 'claude' ? 1 : a < b ? -1 : a > b ? 1 : 0);
|
|
498
|
+
const exprs = [];
|
|
499
|
+
for (const id of ids) {
|
|
500
|
+
const configHome = registry.runtimes[id].runtime && registry.runtimes[id].runtime.configHome;
|
|
501
|
+
if (configHome) exprs.push(...shellHomeExpr(configHome));
|
|
502
|
+
}
|
|
503
|
+
for (const id of Object.keys(legacyHomes).sort()) {
|
|
504
|
+
const legacy = legacyHomes[id];
|
|
505
|
+
exprs.push(`\${${legacy.env}:-$HOME/${legacy.dir.join('/')}}`);
|
|
506
|
+
}
|
|
507
|
+
// One loop over the homes, the `/gsd-core/bin/<shim>` suffix written once: the
|
|
508
|
+
// preamble is inlined into ~240 prompt files, several of which sit at a size cap.
|
|
509
|
+
// The homes are loaded into the FUNCTION's own positional parameters (`set --`
|
|
510
|
+
// is scoped to the function) and walked with `for _h; do`, not `for _h in <list>`:
|
|
511
|
+
// lint-workflow-shellcheck's #4109 structural check flags any `for x in` list that
|
|
512
|
+
// contains a `$`, without parsing the quoting around it.
|
|
513
|
+
const homes = [...new Set(exprs)].map((e) => `"${e}"`).join(' ');
|
|
514
|
+
return `${HOMES_START}set -- ${homes}; for _h; do _gsd_at "$_h/gsd-core/bin/\${_GSD_SHIM_NAME}" && return 0; done; return 1; }`;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/** Locate the `_gsd_homes` function text inside the snippet's single line. */
|
|
518
|
+
function extractHomesFunction(snippetText) {
|
|
519
|
+
const start = snippetText.indexOf(HOMES_START);
|
|
520
|
+
const end = snippetText.indexOf(HOMES_END, start);
|
|
521
|
+
if (start === -1 || end === -1) return null;
|
|
522
|
+
return { start, end: end + '; }'.length, text: snippetText.slice(start, end + '; }'.length) };
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function loadDerivedHomes() {
|
|
526
|
+
const registry = require('../gsd-core/bin/lib/capability-registry.cjs');
|
|
527
|
+
const { LEGACY_NON_REGISTRY_RUNTIME_HOMES } = require('../gsd-core/bin/lib/runtime-name-policy.cjs');
|
|
528
|
+
return renderHomesFunction(registry, LEGACY_NON_REGISTRY_RUNTIME_HOMES);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/** Rewrite the snippet's `_gsd_homes` from the descriptors. Returns true when it changed. */
|
|
532
|
+
function refreshSnippetHomes() {
|
|
533
|
+
const raw = fs.readFileSync(SNIPPET_FILE, 'utf8');
|
|
534
|
+
const found = extractHomesFunction(raw);
|
|
535
|
+
if (!found) throw new Error('_runtime-launcher.snippet.sh has no _gsd_homes function to refresh');
|
|
536
|
+
const derived = loadDerivedHomes();
|
|
537
|
+
if (found.text === derived) return false;
|
|
538
|
+
fs.writeFileSync(SNIPPET_FILE, raw.slice(0, found.start) + derived + raw.slice(found.end), 'utf8');
|
|
539
|
+
return true;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// ---------------------------------------------------------------------------
|
|
543
|
+
// Files that carry the preamble as ONE line but are not transformed by
|
|
544
|
+
// `transformFile` (it would move a per-block definition into the first block):
|
|
545
|
+
// - gsd-core/references/gsd-run-resolver.md — the @-included canonical copy,
|
|
546
|
+
// asserted byte-equal to the snippet;
|
|
547
|
+
// - commands/**/*.md — slash-command templates whose every bash block carries
|
|
548
|
+
// its own definition (each block is a separate shell), originally copied from
|
|
549
|
+
// an older fixed-list resolver that still probed the retired gemini home.
|
|
550
|
+
// Every line that starts a resolver (PREAMBLE_LINE_RE) is replaced by the
|
|
551
|
+
// canonical preamble line, so these copies are generated, not hand-kept (#5169).
|
|
552
|
+
// ---------------------------------------------------------------------------
|
|
553
|
+
const RESOLVER_REFERENCE = path.join(__dirname, '..', 'gsd-core', 'references', 'gsd-run-resolver.md');
|
|
554
|
+
const COMMANDS_DIR = path.join(__dirname, '..', 'commands');
|
|
555
|
+
|
|
556
|
+
function replaceResolverLines(content, preambleLine) {
|
|
557
|
+
return content
|
|
558
|
+
.split('\n')
|
|
559
|
+
.map((line) => (PREAMBLE_LINE_RE.test(line) && line !== preambleLine ? preambleLine : line))
|
|
560
|
+
.join('\n');
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
function syncSingleLinePreambleFiles(preamble) {
|
|
564
|
+
if (preamble.length !== 1) throw new Error('the launcher preamble must be a single line to be inlined per block');
|
|
565
|
+
const files = [RESOLVER_REFERENCE, ...collectFiles(COMMANDS_DIR)];
|
|
566
|
+
let changed = 0;
|
|
567
|
+
for (const f of files) {
|
|
568
|
+
const content = fs.readFileSync(f, 'utf8');
|
|
569
|
+
const next = replaceResolverLines(content, preamble[0]);
|
|
570
|
+
if (next !== content) {
|
|
571
|
+
fs.writeFileSync(f, next, 'utf8');
|
|
572
|
+
changed++;
|
|
573
|
+
console.log(`transformed (preamble line): ${path.relative(path.join(__dirname, '..'), f)}`);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return changed;
|
|
577
|
+
}
|
|
578
|
+
|
|
408
579
|
// Main
|
|
409
580
|
function main() {
|
|
581
|
+
if (refreshSnippetHomes()) console.log('refreshed _gsd_homes in _runtime-launcher.snippet.sh from the runtime descriptors');
|
|
410
582
|
const preamble = loadPreamble();
|
|
583
|
+
syncSingleLinePreambleFiles(preamble);
|
|
411
584
|
|
|
412
585
|
let transformedCount = 0;
|
|
413
586
|
let unchangedCount = 0;
|
|
@@ -447,4 +620,13 @@ if (require.main === module) {
|
|
|
447
620
|
main();
|
|
448
621
|
}
|
|
449
622
|
|
|
450
|
-
module.exports = {
|
|
623
|
+
module.exports = {
|
|
624
|
+
transformFile,
|
|
625
|
+
loadPreamble,
|
|
626
|
+
renderHomesFunction,
|
|
627
|
+
extractHomesFunction,
|
|
628
|
+
loadDerivedHomes,
|
|
629
|
+
refreshSnippetHomes,
|
|
630
|
+
replaceResolverLines,
|
|
631
|
+
PREAMBLE_LINE_RE,
|
|
632
|
+
};
|