@opengsd/gsd-core 1.13.0 → 1.15.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/README.ja-JP.md +3 -3
- package/README.ko-KR.md +3 -3
- package/README.pt-BR.md +3 -3
- package/README.zh-CN.md +3 -3
- package/agents/gsd-advisor-researcher.compact.md +85 -0
- package/agents/gsd-ai-researcher.compact.md +96 -0
- package/agents/gsd-assumptions-analyzer.compact.md +81 -0
- package/agents/gsd-code-fixer.compact.md +459 -0
- package/agents/gsd-code-fixer.md +9 -8
- package/agents/gsd-code-reviewer.compact.md +269 -0
- package/agents/gsd-code-reviewer.md +15 -3
- package/agents/gsd-codebase-mapper.compact.md +760 -0
- package/agents/gsd-debug-session-manager.compact.md +360 -0
- package/agents/gsd-debug-session-manager.md +17 -2
- package/agents/gsd-debugger.md +2 -2
- package/agents/gsd-doc-classifier.compact.md +192 -0
- package/agents/gsd-doc-synthesizer.compact.md +200 -0
- package/agents/gsd-doc-verifier.compact.md +143 -0
- package/agents/gsd-doc-writer.compact.md +440 -0
- package/agents/gsd-dom-verifier.compact.md +138 -0
- package/agents/gsd-domain-researcher.compact.md +141 -0
- package/agents/gsd-eval-auditor.compact.md +160 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-eval-planner.compact.md +137 -0
- package/agents/gsd-executor.md +13 -8
- package/agents/gsd-framework-selector.compact.md +82 -0
- package/agents/gsd-integration-checker.compact.md +245 -0
- package/agents/gsd-intel-updater.compact.md +226 -0
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.compact.md +45 -0
- package/agents/gsd-nyquist-auditor.compact.md +179 -0
- package/agents/gsd-pattern-mapper.compact.md +275 -0
- package/agents/gsd-phase-researcher.md +19 -11
- package/agents/gsd-plan-checker.md +8 -7
- package/agents/gsd-planner.md +12 -8
- package/agents/gsd-project-researcher.compact.md +587 -0
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +212 -0
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-roadmapper.compact.md +454 -0
- package/agents/gsd-roadmapper.md +13 -0
- package/agents/gsd-security-auditor.compact.md +162 -0
- package/agents/gsd-ui-auditor.compact.md +404 -0
- package/agents/gsd-ui-auditor.md +155 -17
- package/agents/gsd-ui-checker.compact.md +277 -0
- package/agents/gsd-ui-researcher.compact.md +282 -0
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-user-profiler.compact.md +108 -0
- package/agents/gsd-verifier.md +10 -9
- package/bin/install.js +848 -163
- package/commands/gsd/autonomous.md +2 -2
- package/commands/gsd/capture.md +1 -1
- package/commands/gsd/cleanup.md +1 -0
- package/commands/gsd/code-review.md +2 -1
- package/commands/gsd/complete-milestone.md +1 -0
- package/commands/gsd/config.md +1 -0
- package/commands/gsd/debug.md +1 -0
- package/commands/gsd/graphify.md +1 -0
- package/commands/gsd/health.md +1 -0
- package/commands/gsd/mempalace-capture.md +8 -3
- package/commands/gsd/mempalace-recall.md +1 -0
- package/commands/gsd/new-milestone.md +1 -0
- package/commands/gsd/new-project.md +1 -0
- package/commands/gsd/next.md +1 -0
- package/commands/gsd/pause-work.md +1 -0
- package/commands/gsd/phase.md +1 -0
- package/commands/gsd/plan-review-convergence.md +6 -6
- package/commands/gsd/pr-branch.md +1 -0
- package/commands/gsd/progress.md +1 -1
- package/commands/gsd/quick-batch.md +1 -1
- package/commands/gsd/resume-work.md +1 -0
- package/commands/gsd/review-backlog.md +1 -0
- package/commands/gsd/review.md +2 -3
- package/commands/gsd/settings.md +2 -1
- package/commands/gsd/stats.md +1 -0
- package/commands/gsd/thread.md +1 -0
- package/commands/gsd/workspace.md +1 -0
- package/commands/gsd/workstreams.md +1 -0
- package/gsd-core/bin/check-latest-version.cjs +8 -3
- package/gsd-core/bin/gsd-tools.cjs +672 -146
- package/gsd-core/bin/lib/adr-parser.cjs +4 -2
- package/gsd-core/bin/lib/artifacts.cjs +2 -1
- package/gsd-core/bin/lib/audit.cjs +119 -34
- package/gsd-core/bin/lib/broken-windows.cjs +168 -49
- package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
- package/gsd-core/bin/lib/capability-loader.cjs +135 -1
- package/gsd-core/bin/lib/capability-registry.cjs +96 -189
- package/gsd-core/bin/lib/capability-source.cjs +19 -2
- package/gsd-core/bin/lib/capability-validator.cjs +14 -2
- package/gsd-core/bin/lib/check-command-router.cjs +213 -49
- package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
- package/gsd-core/bin/lib/codex-agent-toml.cjs +21 -25
- package/gsd-core/bin/lib/commands.cjs +823 -112
- package/gsd-core/bin/lib/config-loader.cjs +66 -4
- package/gsd-core/bin/lib/config.cjs +186 -45
- package/gsd-core/bin/lib/coverage.cjs +1 -1
- package/gsd-core/bin/lib/decisions.cjs +164 -45
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
- package/gsd-core/bin/lib/frontmatter.cjs +13 -0
- package/gsd-core/bin/lib/graphify.cjs +10 -2
- package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +12 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
- package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
- package/gsd-core/bin/lib/init.cjs +614 -86
- package/gsd-core/bin/lib/install-engine.cjs +29 -3
- package/gsd-core/bin/lib/install-profiles.cjs +14 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +41 -5
- package/gsd-core/bin/lib/loop-resolver.cjs +50 -31
- package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
- package/gsd-core/bin/lib/milestone.cjs +37 -13
- package/gsd-core/bin/lib/model-resolver.cjs +253 -53
- package/gsd-core/bin/lib/phase-command-router.cjs +16 -2
- package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
- package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
- package/gsd-core/bin/lib/phase-id.cjs +268 -27
- package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
- package/gsd-core/bin/lib/phase-locator.cjs +29 -10
- package/gsd-core/bin/lib/phase.cjs +393 -88
- package/gsd-core/bin/lib/plan-document.cjs +49 -1
- package/gsd-core/bin/lib/planning-document.cjs +459 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +52 -19
- package/gsd-core/bin/lib/planning-snapshot.cjs +61 -12
- package/gsd-core/bin/lib/planning-workspace.cjs +57 -3
- package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
- package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
- package/gsd-core/bin/lib/probe-core.cjs +7 -1
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
- package/gsd-core/bin/lib/project-root.cjs +41 -2
- package/gsd-core/bin/lib/quick-batch.cjs +1 -1
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
- package/gsd-core/bin/lib/research-store.cjs +11 -12
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
- package/gsd-core/bin/lib/review-lane-invocation.cjs +23 -0
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
- package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +12 -4
- package/gsd-core/bin/lib/roadmap-parser.cjs +219 -18
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +1539 -13
- package/gsd-core/bin/lib/roadmap.cjs +356 -42
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +310 -41
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +15 -4
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +13 -5
- package/gsd-core/bin/lib/runtime-homes.cjs +4 -0
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +408 -37
- package/gsd-core/bin/lib/runtime-name-policy.cjs +111 -1
- package/gsd-core/bin/lib/security.cjs +126 -7
- package/gsd-core/bin/lib/shell-command-projection.cjs +10 -6
- package/gsd-core/bin/lib/state-document.cjs +130 -28
- package/gsd-core/bin/lib/state-md-schema.cjs +21 -14
- package/gsd-core/bin/lib/state-transition.cjs +181 -30
- package/gsd-core/bin/lib/state.cjs +265 -27
- package/gsd-core/bin/lib/surface.cjs +77 -3
- package/gsd-core/bin/lib/task-command-router.cjs +12 -6
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +78 -5
- package/gsd-core/bin/lib/uat-predicate.cjs +47 -4
- package/gsd-core/bin/lib/uat.cjs +9 -1
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +100 -9
- package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
- package/gsd-core/bin/lib/update-context.cjs +30 -24
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
- package/gsd-core/bin/lib/verification.cjs +315 -30
- package/gsd-core/bin/lib/verify-command-grounding.cjs +47 -3
- package/gsd-core/bin/lib/verify.cjs +320 -48
- package/gsd-core/bin/lib/workstream-inventory.cjs +1 -0
- package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
- package/gsd-core/bin/lib/worktree-safety.cjs +797 -58
- package/gsd-core/bin/shared/config-defaults.manifest.json +4 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +6 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +439 -80
- package/gsd-core/references/checkpoints.md +5 -3
- package/gsd-core/references/compact-content-gate.md +66 -0
- package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe.md +195 -21
- package/gsd-core/references/execute-phase-between-wave-reset.md +7 -6
- package/gsd-core/references/execute-phase-wave-guard.md +22 -11
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +18 -0
- package/gsd-core/references/model-profiles.md +13 -4
- package/gsd-core/references/phase-argument-parsing.md +9 -7
- package/gsd-core/references/phase-id-convention.md +28 -0
- package/gsd-core/references/planner-gap-closure.md +2 -0
- package/gsd-core/references/planner-load-graph-context.md +24 -13
- package/gsd-core/references/planner-verify-command-grounding.md +14 -0
- package/gsd-core/references/planning-config.md +14 -2
- package/gsd-core/references/tdd.md +30 -4
- package/gsd-core/references/thinking-models-planning.md +18 -2
- package/gsd-core/references/ui-consideration-probe.md +10 -5
- package/gsd-core/references/verification-patterns.md +17 -4
- package/gsd-core/references/verify-command-path-resolvability.md +10 -2
- package/gsd-core/references/worktree-path-safety.md +433 -2
- package/gsd-core/templates/README.md +7 -1
- package/gsd-core/templates/state.md +6 -3
- package/gsd-core/templates/summary.compact.md +212 -0
- package/gsd-core/templates/user-setup.compact.md +199 -0
- package/gsd-core/templates/user-setup.md +0 -9
- 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 +1 -1
- package/gsd-core/workflows/add-tests.md +2 -2
- package/gsd-core/workflows/add-todo.md +6 -5
- package/gsd-core/workflows/ai-integration-phase.md +11 -3
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +1 -1
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
- package/gsd-core/workflows/autonomous.md +29 -16
- package/gsd-core/workflows/check-todos.md +6 -4
- package/gsd-core/workflows/cleanup.md +5 -3
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +8 -1
- package/gsd-core/workflows/code-review-fix.md +108 -22
- package/gsd-core/workflows/code-review.md +216 -73
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
- package/gsd-core/workflows/complete-milestone.md +41 -264
- package/gsd-core/workflows/debug.md +3 -3
- package/gsd-core/workflows/diagnose-issues.md +1 -1
- 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 +1 -1
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +2 -2
- package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
- package/gsd-core/workflows/docs-update.md +17 -158
- package/gsd-core/workflows/edit-phase.md +1 -1
- package/gsd-core/workflows/eval-review.md +10 -3
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1017 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +19 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +43 -4
- package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- 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 +46 -9
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
- package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +24 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
- package/gsd-core/workflows/execute-phase.md +83 -172
- package/gsd-core/workflows/execute-plan.md +24 -10
- package/gsd-core/workflows/explore.md +3 -3
- package/gsd-core/workflows/extract-learnings.md +2 -1
- 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 -2
- package/gsd-core/workflows/help/modes/full.compact.md +398 -0
- package/gsd-core/workflows/help/modes/full.md +5 -5
- package/gsd-core/workflows/help/modes/topic.md +15 -5
- package/gsd-core/workflows/help.md +1 -1
- package/gsd-core/workflows/import.md +2 -2
- package/gsd-core/workflows/inbox.md +2 -2
- package/gsd-core/workflows/ingest-docs.md +3 -3
- package/gsd-core/workflows/insert-phase.md +1 -1
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +2 -2
- package/gsd-core/workflows/map-codebase.md +52 -5
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +1 -1
- package/gsd-core/workflows/new-milestone.md +56 -14
- package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
- package/gsd-core/workflows/new-project.md +39 -209
- package/gsd-core/workflows/new-workspace.md +2 -2
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/note.md +1 -1
- package/gsd-core/workflows/onboard.md +1 -1
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
- package/gsd-core/workflows/plan-phase.md +45 -187
- package/gsd-core/workflows/plan-review-convergence.md +21 -5
- package/gsd-core/workflows/plant-seed.md +62 -20
- package/gsd-core/workflows/pr-branch.md +132 -20
- package/gsd-core/workflows/profile-user.md +2 -2
- package/gsd-core/workflows/progress.md +1 -1
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +25 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +1 -1
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +1 -1
- 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 +1 -1
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +1 -1
- package/gsd-core/workflows/quick.md +29 -10
- package/gsd-core/workflows/reapply-patches.md +86 -6
- package/gsd-core/workflows/remove-phase.md +1 -1
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +1 -1
- package/gsd-core/workflows/review.md +31 -16
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -2
- package/gsd-core/workflows/settings-advanced.md +30 -10
- package/gsd-core/workflows/settings-integrations.md +2 -3
- package/gsd-core/workflows/settings.md +22 -9
- package/gsd-core/workflows/ship.md +3 -2
- 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 +2 -2
- package/gsd-core/workflows/spec-phase.md +15 -5
- 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 +5 -5
- package/gsd-core/workflows/thread.md +1 -1
- package/gsd-core/workflows/transition.md +1 -1
- package/gsd-core/workflows/ui-phase.md +44 -8
- package/gsd-core/workflows/ui-review.md +18 -4
- package/gsd-core/workflows/ultraplan-phase.md +1 -1
- package/gsd-core/workflows/undo.md +339 -20
- package/gsd-core/workflows/update.md +14 -12
- package/gsd-core/workflows/validate-phase.md +3 -2
- package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +101 -196
- package/hooks/dist/gsd-agent-isolation-guard.js +66 -16
- package/hooks/dist/gsd-context-monitor.js +88 -15
- package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
- package/hooks/dist/gsd-secret-read-guard.js +71 -19
- package/hooks/dist/gsd-statusline.js +81 -20
- package/hooks/dist/gsd-validate-commit.sh +97 -8
- package/hooks/dist/gsd-worktree-path-guard.js +25 -14
- package/hooks/dist/gsd-write-guard.js +46 -1
- package/hooks/dist/lib/dispatch-identity.js +187 -0
- package/hooks/dist/lib/filename-classification.js +64 -0
- package/hooks/dist/lib/isolation-deny-reason.js +53 -1
- package/hooks/dist/lib/isolation-sentinel.js +58 -19
- package/hooks/gsd-agent-isolation-guard.js +66 -16
- package/hooks/gsd-context-monitor.js +88 -15
- package/hooks/gsd-cursor-subagent-start.js +34 -14
- package/hooks/gsd-secret-read-guard.js +71 -19
- package/hooks/gsd-statusline.js +81 -20
- package/hooks/gsd-validate-commit.sh +97 -8
- package/hooks/gsd-worktree-path-guard.js +25 -14
- package/hooks/gsd-write-guard.js +46 -1
- package/hooks/lib/dispatch-identity.js +187 -0
- package/hooks/lib/filename-classification.js +64 -0
- package/hooks/lib/isolation-deny-reason.js +53 -1
- package/hooks/lib/isolation-sentinel.js +58 -19
- package/package.json +11 -6
- package/scripts/benchmark-compact-content-variants.cjs +298 -0
- package/scripts/benchmark-compact-content.cjs +368 -0
- package/scripts/build-hooks.js +15 -6
- package/scripts/check-contract-drift.cjs +131 -12
- package/scripts/check-env.cjs +36 -8
- package/scripts/check-glossary-refs.cjs +25 -21
- package/scripts/ci-next-health.cjs +271 -0
- package/scripts/ci-prepare-test-scope.cjs +7 -7
- package/scripts/ci-test-scope.cjs +126 -20
- package/scripts/ci-timeout-report.cjs +1 -1
- package/scripts/command-contract-helpers.cjs +3 -0
- package/scripts/diff-touches-shipped-paths.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +35 -2
- package/scripts/gen-adr-index.cjs +8 -2
- package/scripts/gen-inventory-manifest.cjs +12 -0
- package/scripts/gen-loop-host-contract.cjs +69 -0
- package/scripts/gen-platform-conformance-tier.cjs +557 -0
- package/scripts/lib/drift-scan.cjs +1 -1
- package/scripts/lib/macos-conformance-tier.generated.cjs +224 -0
- package/scripts/lib/ndjson-reporter.cjs +3 -2
- package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
- package/scripts/lib/platform-conformance-tier.generated.cjs +287 -0
- package/scripts/lib/suite-detection.cjs +32 -0
- package/scripts/lint-allowed-tools-parity.cjs +221 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +47 -3
- package/scripts/lint-phase-arg-assignment.cjs +257 -0
- package/scripts/lint-phase-id-drift.cjs +623 -13
- package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
- package/scripts/lint-response-language-coverage.cjs +9 -3
- package/scripts/lint-retired-runtime-name.cjs +619 -0
- package/scripts/lint-source-test-name-collision.cjs +1 -1
- package/scripts/lint-state-write-path-drift.cjs +93 -0
- package/scripts/lint-test-file-count.allowlist.json +29 -9
- package/scripts/lint-vendored-deps.cjs +128 -17
- package/scripts/lint-workflow-shellcheck-baseline.json +100 -0
- package/scripts/prompt-injection-scan.sh +18 -0
- package/scripts/release-tarball-smoke.cjs +194 -1
- package/scripts/workflow-size.cjs +139 -0
- package/skills/gsd-autonomous/SKILL.md +2 -2
- package/skills/gsd-capture/SKILL.md +1 -1
- package/skills/gsd-cleanup/SKILL.md +1 -0
- package/skills/gsd-code-review/SKILL.md +2 -1
- package/skills/gsd-complete-milestone/SKILL.md +1 -0
- package/skills/gsd-config/SKILL.md +1 -0
- package/skills/gsd-debug/SKILL.md +1 -0
- package/skills/gsd-graphify/SKILL.md +1 -0
- package/skills/gsd-health/SKILL.md +1 -0
- package/skills/gsd-mempalace-capture/SKILL.md +8 -3
- package/skills/gsd-mempalace-recall/SKILL.md +1 -0
- package/skills/gsd-new-milestone/SKILL.md +1 -0
- package/skills/gsd-new-project/SKILL.md +1 -0
- package/skills/gsd-next/SKILL.md +1 -0
- package/skills/gsd-pause-work/SKILL.md +1 -0
- package/skills/gsd-phase/SKILL.md +1 -0
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -5
- package/skills/gsd-pr-branch/SKILL.md +1 -0
- package/skills/gsd-progress/SKILL.md +1 -1
- package/skills/gsd-quick-batch/SKILL.md +1 -1
- package/skills/gsd-resume-work/SKILL.md +1 -0
- package/skills/gsd-review/SKILL.md +2 -3
- package/skills/gsd-review-backlog/SKILL.md +1 -0
- package/skills/gsd-settings/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +1 -0
- package/skills/gsd-thread/SKILL.md +1 -0
- package/skills/gsd-workspace/SKILL.md +1 -0
- package/skills/gsd-workstreams/SKILL.md +1 -0
- package/vscode/package.json +1 -1
- package/gsd-core/templates/claude-md.md +0 -145
- package/gsd-core/templates/codebase/concerns.md +0 -310
- package/gsd-core/templates/codebase/conventions.md +0 -307
- package/gsd-core/templates/codebase/integrations.md +0 -280
- package/gsd-core/templates/codebase/structure.md +0 -285
- package/gsd-core/templates/codebase/testing.md +0 -480
- package/gsd-core/templates/debug-subagent-prompt.md +0 -91
- package/gsd-core/templates/discovery.md +0 -146
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
// Shell-agnostic: invoked as `node scripts/ci-prepare-test-scope.cjs` from any shell.
|
|
5
5
|
//
|
|
6
6
|
// Required environment variables (set by the workflow step's `env:` block):
|
|
7
|
-
// TEST_SCOPE — "
|
|
7
|
+
// TEST_SCOPE — "targeted" (the `windows` scope was retired by #4641:
|
|
8
|
+
// test-conformance is now the sole Windows selector)
|
|
8
9
|
// TARGETED_TESTS — space-separated test file list (from ci-test-scope.cjs output)
|
|
9
|
-
// WINDOWS_TESTS — space-separated test file list for the windows lane
|
|
10
10
|
//
|
|
11
11
|
// Writes: .ci-selected-tests.txt (one file per line, no blanks)
|
|
12
12
|
// Exit 0 = success; exit 1 = unknown scope.
|
|
@@ -46,13 +46,14 @@ function isResolvable(entry, root) {
|
|
|
46
46
|
|
|
47
47
|
// Resolve the scoped test selection for the lane. Pure (no I/O beyond the
|
|
48
48
|
// existence probe under `root`) so it can be unit-tested directly.
|
|
49
|
-
function resolveSelection({ scope, targeted,
|
|
49
|
+
function resolveSelection({ scope, targeted, root }) {
|
|
50
50
|
let selected;
|
|
51
|
-
if (scope === '
|
|
52
|
-
selected = windows;
|
|
53
|
-
} else if (scope === 'targeted') {
|
|
51
|
+
if (scope === 'targeted') {
|
|
54
52
|
selected = targeted;
|
|
55
53
|
} else {
|
|
54
|
+
// #4641: the `windows` scope was retired (test-conformance is now the
|
|
55
|
+
// sole Windows selector) — an unknown/retired scope must fail loudly
|
|
56
|
+
// rather than silently selecting nothing.
|
|
56
57
|
throw new ExitError(1, `::error::Unknown test scope: ${scope}`);
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -75,7 +76,6 @@ function main() {
|
|
|
75
76
|
const lines = resolveSelection({
|
|
76
77
|
scope: process.env.TEST_SCOPE || '',
|
|
77
78
|
targeted: process.env.TARGETED_TESTS || '',
|
|
78
|
-
windows: process.env.WINDOWS_TESTS || '',
|
|
79
79
|
root,
|
|
80
80
|
});
|
|
81
81
|
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { execFileSync } = require('child_process');
|
|
6
|
-
const { existsSync, readdirSync, appendFileSync } = require('fs');
|
|
6
|
+
const { existsSync, readdirSync, appendFileSync, readFileSync } = require('fs');
|
|
7
7
|
|
|
8
8
|
const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
|
9
|
+
const { classifyContent, NOISY_FOR_SOURCE_REACHABILITY } = require('./gen-platform-conformance-tier.cjs');
|
|
9
10
|
|
|
10
11
|
// Workflow files that are purely administrative / policy bots. Changes to these
|
|
11
12
|
// files do NOT require the cross-platform test matrix — only a lightweight
|
|
@@ -484,12 +485,68 @@ function addAll(set, values) {
|
|
|
484
485
|
// fullMatrix=true, so the full Windows lane already runs when those paths
|
|
485
486
|
// change. The old six-hint list pulled 102 of ~633 test files into the scoped
|
|
486
487
|
// windows lane, turning it into a ~10-minute job on every PR.
|
|
488
|
+
// #4641: the scoped windows lane itself is gone. These hints now drive
|
|
489
|
+
// full_matrix instead — a matched RULE whose tests[] includes a
|
|
490
|
+
// windows-hint filename AND that hinted file is itself in the conformance
|
|
491
|
+
// tier (per reachesConformanceTierOrSeam) escalates straight to full_matrix
|
|
492
|
+
// (routed to test-conformance, the sole Windows selector) rather than
|
|
493
|
+
// feeding a side lane. Tier-backed on purpose: full_matrix only ever runs
|
|
494
|
+
// CONFORMANCE_TIER_FILES, so a hint on a non-tier file would cost 4 CI jobs
|
|
495
|
+
// with zero Windows coverage of that file. See
|
|
496
|
+
// docs/adr/4641-windows-selector-consolidation.md.
|
|
487
497
|
const WINDOWS_HINTS = ['windows', 'win32', 'shell', 'path'];
|
|
488
498
|
const isWindowsHint = s => WINDOWS_HINTS.some(k => s.toLowerCase().includes(k));
|
|
489
499
|
|
|
490
|
-
|
|
500
|
+
// A change to the classification mechanism itself cannot be presumed safe by
|
|
501
|
+
// the very mechanism being changed (#4592).
|
|
502
|
+
const CLASSIFIER_DEFINITION_FILES = new Set([
|
|
503
|
+
'scripts/gen-platform-conformance-tier.cjs',
|
|
504
|
+
'scripts/lib/platform-conformance-tier.generated.cjs',
|
|
505
|
+
'scripts/lib/suite-detection.cjs',
|
|
506
|
+
]);
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Does `file`'s blast radius reach (a) Phase 2's conformance-tier test-file
|
|
510
|
+
* list or (b) a live platform-conditional signal in src/? Fail-safe: any
|
|
511
|
+
* thrown error (a require failure, a readFileSync failure, a malformed
|
|
512
|
+
* generated module, etc.) is treated as uncertainty and returns true — per
|
|
513
|
+
* #4592's explicit "fail-safe to full_matrix=true on any reachability-
|
|
514
|
+
* computation error or uncertainty" requirement.
|
|
515
|
+
* `loadConformanceTier` is injectable (defaults to the real generated module)
|
|
516
|
+
* solely so tests can simulate a load failure without touching the real,
|
|
517
|
+
* committed generated file.
|
|
518
|
+
* @param {string} file
|
|
519
|
+
* @param {{loadConformanceTier?: () => {CONFORMANCE_TIER_FILES: string[]}}} [deps]
|
|
520
|
+
* @returns {boolean}
|
|
521
|
+
*/
|
|
522
|
+
function reachesConformanceTierOrSeam(file, deps = {}) {
|
|
523
|
+
const loadConformanceTier =
|
|
524
|
+
deps.loadConformanceTier || (() => require('./lib/platform-conformance-tier.generated.cjs'));
|
|
525
|
+
try {
|
|
526
|
+
if (file.startsWith('tests/') && file.endsWith('.test.cjs')) {
|
|
527
|
+
const { CONFORMANCE_TIER_FILES } = loadConformanceTier();
|
|
528
|
+
return CONFORMANCE_TIER_FILES.includes(file);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (file.startsWith('src/')) {
|
|
532
|
+
const content = readFileSync(file, 'utf8');
|
|
533
|
+
const { signals } = classifyContent(content);
|
|
534
|
+
const narrowSignals = signals.filter(signal => !NOISY_FOR_SOURCE_REACHABILITY.has(signal));
|
|
535
|
+
return narrowSignals.length > 0;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return false;
|
|
539
|
+
} catch {
|
|
540
|
+
return true;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// `reachabilityDeps` is injectable (defaults to {}, which makes
|
|
545
|
+
// reachesConformanceTierOrSeam use the real generated module) solely so
|
|
546
|
+
// tests can simulate a reachability-computation failure without touching
|
|
547
|
+
// the real, committed generated file.
|
|
548
|
+
function classify(files, reachabilityDeps = {}) {
|
|
491
549
|
const targeted = new Set();
|
|
492
|
-
const windows = new Set();
|
|
493
550
|
const reasons = [];
|
|
494
551
|
let productOrPipelineChanged = false; // product/pipeline code (excludes docs)
|
|
495
552
|
let inertCiChanged = false; // inert workflow files
|
|
@@ -526,15 +583,35 @@ function classify(files) {
|
|
|
526
583
|
|
|
527
584
|
if (file.startsWith('tests/') && file.endsWith('.test.cjs')) {
|
|
528
585
|
targeted.add(file);
|
|
529
|
-
// #494
|
|
530
|
-
//
|
|
531
|
-
//
|
|
532
|
-
//
|
|
533
|
-
//
|
|
534
|
-
//
|
|
535
|
-
//
|
|
536
|
-
//
|
|
537
|
-
|
|
586
|
+
// #494 originally narrowed this to skip full_matrix for changed test
|
|
587
|
+
// files, on the theory that ubuntu targeted_tests + the scoped windows
|
|
588
|
+
// lane already covered them. Rescinded per #4421: PR #4384 landed a
|
|
589
|
+
// macOS-only regression on 2026-09-06 that stayed invisible pre-merge
|
|
590
|
+
// precisely because this carve-out suppressed the only macOS signal.
|
|
591
|
+
// #4592: the blanket rule is replaced with a reachability check — only
|
|
592
|
+
// a changed test file that actually reaches Phase 2's conformance-tier
|
|
593
|
+
// list (or is the classification mechanism itself) forces full_matrix.
|
|
594
|
+
if (reachesConformanceTierOrSeam(file, reachabilityDeps)) {
|
|
595
|
+
fullMatrix = true;
|
|
596
|
+
reasons.push(`${file}: conformance-tier reachability`);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// #4592: a src/-only diff (no test file touched) must still be able to
|
|
601
|
+
// set full_matrix=true when it carries a live platform-conditional
|
|
602
|
+
// signal — this is independent of the tests/ branch above.
|
|
603
|
+
if (file.startsWith('src/') && reachesConformanceTierOrSeam(file, reachabilityDeps)) {
|
|
604
|
+
fullMatrix = true;
|
|
605
|
+
reasons.push(`${file}: platform seam reachability`);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// #4592: a changed file that IS the classification mechanism itself
|
|
609
|
+
// (neither under tests/ nor src/, so neither branch above reaches it)
|
|
610
|
+
// must also force full_matrix — a change to the mechanism cannot be
|
|
611
|
+
// presumed safe by the very mechanism being changed.
|
|
612
|
+
if (CLASSIFIER_DEFINITION_FILES.has(file)) {
|
|
613
|
+
fullMatrix = true;
|
|
614
|
+
reasons.push(`${file}: reachability classifier definition changed`);
|
|
538
615
|
}
|
|
539
616
|
|
|
540
617
|
for (const rule of RULES) {
|
|
@@ -542,6 +619,32 @@ function classify(files) {
|
|
|
542
619
|
addAll(targeted, rule.tests);
|
|
543
620
|
reasons.push(`${file}: ${rule.name}`);
|
|
544
621
|
if (rule.fullMatrix) fullMatrix = true;
|
|
622
|
+
// #4641: a rule that pulls in a test file matching a Windows-sensitive
|
|
623
|
+
// filename hint is the one non-redundant residue of the deleted
|
|
624
|
+
// scoped windows lane — escalate to full_matrix (test-conformance)
|
|
625
|
+
// instead of feeding a side lane. TIER-BACKED (measured): full_matrix
|
|
626
|
+
// routes to test-conformance, which runs ONLY CONFORMANCE_TIER_FILES —
|
|
627
|
+
// escalating on the filename hint alone can fire on a hinted test that
|
|
628
|
+
// isn't in that tier, costing 4 CI jobs while never actually running it
|
|
629
|
+
// on Windows. The predicate below requires BOTH the hint AND tier
|
|
630
|
+
// membership (via reachesConformanceTierOrSeam, the same fail-safe
|
|
631
|
+
// reachability helper used elsewhere in this file, so error/uncertainty
|
|
632
|
+
// behavior stays identical). Measured: over the 16 RULES entries this
|
|
633
|
+
// narrowed form fires on the same rules as the un-narrowed form today
|
|
634
|
+
// (no behavior change now, correct-by-construction going forward). The
|
|
635
|
+
// broader alternative — escalate on ANY tier member a rule pulls in,
|
|
636
|
+
// ignoring the filename hint — was measured and rejected: it fires on
|
|
637
|
+
// 14 of 16 rules, newly escalating most ordinary product-code PRs
|
|
638
|
+
// (src/, agents/, commands/, hooks/, skills/, config paths). Only one
|
|
639
|
+
// rule's escalation is live today: 'portability lint rules (ADR-1703)'.
|
|
640
|
+
// Four others already had fullMatrix: true (no-op here), and 'inert
|
|
641
|
+
// CI''s escalation is overridden downstream by the inert-CI reset.
|
|
642
|
+
// Distinct, greppable reason so the conformance-lane coverage for it
|
|
643
|
+
// is traceable per rule.
|
|
644
|
+
if (rule.tests.some(t => isWindowsHint(t) && reachesConformanceTierOrSeam(t, reachabilityDeps))) {
|
|
645
|
+
fullMatrix = true;
|
|
646
|
+
reasons.push(`${file}: ${rule.name} (windows-hint rule test, #4641)`);
|
|
647
|
+
}
|
|
545
648
|
}
|
|
546
649
|
}
|
|
547
650
|
}
|
|
@@ -555,7 +658,7 @@ function classify(files) {
|
|
|
555
658
|
// covered by .github/workflows/install-smoke.yml
|
|
556
659
|
'tests/release-tarball-smoke.install.test.cjs',
|
|
557
660
|
]);
|
|
558
|
-
for (const f of SCOPED_LANE_EXCLUDE) { targeted.delete(f);
|
|
661
|
+
for (const f of SCOPED_LANE_EXCLUDE) { targeted.delete(f); }
|
|
559
662
|
|
|
560
663
|
// code_changed: true when product/pipeline OR inert CI changed.
|
|
561
664
|
// Docs-only PRs (neither flag set) get code_changed=false → full matrix skip.
|
|
@@ -569,8 +672,6 @@ function classify(files) {
|
|
|
569
672
|
targetedTests.push('unit');
|
|
570
673
|
}
|
|
571
674
|
|
|
572
|
-
const windowsTests = existingTests([...new Set([...windows, ...targetedTests.filter(isWindowsHint)])].sort());
|
|
573
|
-
|
|
574
675
|
// Inert-CI-only: full_matrix must be false (override any RULES that fired).
|
|
575
676
|
if (inertCiChanged && !productOrPipelineChanged) {
|
|
576
677
|
fullMatrix = false;
|
|
@@ -579,12 +680,11 @@ function classify(files) {
|
|
|
579
680
|
// Normalize: when code_changed is false, the output must be self-consistent.
|
|
580
681
|
// A docs file can coincidentally match a coarse content RULE (e.g. docs/installer-migrations.md
|
|
581
682
|
// matches the installer rule via path.includes('install')), leaving full_matrix=true and
|
|
582
|
-
// non-empty targeted_tests
|
|
683
|
+
// non-empty targeted_tests. The workflow skips correctly (gated on code_changed)
|
|
583
684
|
// but the output object would be self-contradictory. Force a clean "nothing to run" result.
|
|
584
685
|
if (!codeChanged) {
|
|
585
686
|
fullMatrix = false;
|
|
586
687
|
targetedTests.length = 0;
|
|
587
|
-
windowsTests.length = 0;
|
|
588
688
|
}
|
|
589
689
|
|
|
590
690
|
return {
|
|
@@ -592,7 +692,6 @@ function classify(files) {
|
|
|
592
692
|
product_changed: productOrPipelineChanged,
|
|
593
693
|
full_matrix: fullMatrix,
|
|
594
694
|
targeted_tests: targetedTests,
|
|
595
|
-
windows_tests: windowsTests,
|
|
596
695
|
reasons: [...new Set(reasons)].sort(),
|
|
597
696
|
};
|
|
598
697
|
}
|
|
@@ -604,7 +703,6 @@ function writeOutputs(result) {
|
|
|
604
703
|
`product_changed=${result.product_changed}`,
|
|
605
704
|
`full_matrix=${result.full_matrix}`,
|
|
606
705
|
`targeted_tests=${result.targeted_tests.join(' ')}`,
|
|
607
|
-
`windows_tests=${result.windows_tests.join(' ')}`,
|
|
608
706
|
];
|
|
609
707
|
appendFileSync(process.env.GITHUB_OUTPUT, `${lines.join('\n')}\n`);
|
|
610
708
|
}
|
|
@@ -630,4 +728,12 @@ if (require.main === module) {
|
|
|
630
728
|
runMain(main);
|
|
631
729
|
}
|
|
632
730
|
|
|
633
|
-
module.exports = {
|
|
731
|
+
module.exports = {
|
|
732
|
+
RULES,
|
|
733
|
+
missingRuleTestFiles,
|
|
734
|
+
PROTECTED_WORKFLOWS,
|
|
735
|
+
INERT_WORKFLOWS,
|
|
736
|
+
missingProtectedWorkflows,
|
|
737
|
+
classify,
|
|
738
|
+
reachesConformanceTierOrSeam,
|
|
739
|
+
};
|
|
@@ -33,8 +33,8 @@ const WORKFLOWS_DIR = path.join(__dirname, '..', '.github', 'workflows');
|
|
|
33
33
|
const JOB_RULES = [
|
|
34
34
|
{ workflowFile: 'test.yml', jobKey: 'test-inert', test: (name) => name === 'test (inert CI)' },
|
|
35
35
|
{ workflowFile: 'test.yml', jobKey: 'test', test: (name) => name.startsWith('test (') && name !== 'test (inert CI)' },
|
|
36
|
-
{ workflowFile: 'test.yml', jobKey: 'test-full', test: (name) => name.startsWith('full test (') },
|
|
37
36
|
{ workflowFile: 'test.yml', jobKey: 'coverage-gate', test: (name) => name === 'Coverage gate (merged shards)' },
|
|
37
|
+
{ workflowFile: 'test.yml', jobKey: 'test-conformance', test: (name) => name.startsWith('conformance test (') },
|
|
38
38
|
{ workflowFile: 'install-smoke.yml', jobKey: 'smoke', test: (name) => name.startsWith('smoke (') },
|
|
39
39
|
];
|
|
40
40
|
|
|
@@ -890,6 +890,7 @@ const VIOLATION_KINDS = Object.freeze({
|
|
|
890
890
|
LEGACY_READ_TAG: 'legacy_read_tag',
|
|
891
891
|
READ_TAG_GATE_MISSING: 'read_tag_gate_missing',
|
|
892
892
|
UNMATCHED_CONSUMER_TOKEN: 'unmatched_consumer_token',
|
|
893
|
+
UNRESOLVED_REFERENCE_INCLUDE: 'unresolved_reference_include',
|
|
893
894
|
});
|
|
894
895
|
|
|
895
896
|
/**
|
|
@@ -925,6 +926,8 @@ const REMEDIES = Object.freeze({
|
|
|
925
926
|
"add the <required_reading> MUST-Read gate clause to this agent's instructions (see docs/AGENTS.md)",
|
|
926
927
|
unmatched_consumer_token:
|
|
927
928
|
'declare the producing agent and marker in the registry, or remove the dispatch — nothing emits this token',
|
|
929
|
+
unresolved_reference_include:
|
|
930
|
+
'fix the gsd-core/references/ pointer so it names an existing reference file whole and ends at the name (whitespace, end of line, or closing punctuation)',
|
|
928
931
|
});
|
|
929
932
|
|
|
930
933
|
/**
|
|
@@ -72,7 +72,7 @@ function isShipped(diffPath, shipPrefixes) {
|
|
|
72
72
|
// forward slashes, but a developer running this locally on a different
|
|
73
73
|
// tool's output shouldn't get a false negative).
|
|
74
74
|
const p = diffPath.replace(/\\/g, '/');
|
|
75
|
-
return shipPrefixes.some((s) => p === s || p.startsWith(s + '/'));
|
|
75
|
+
return shipPrefixes.some((s) => p === s || p.startsWith(s + '/')); // allow-handrolled-containment: shipped-path filtering for a CI check, not a safety decision
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// #2980: commits that touch `.github/workflows/*` cannot be cherry-picked
|
|
@@ -9,8 +9,12 @@
|
|
|
9
9
|
*
|
|
10
10
|
* A prior version of this PR added a `docs guards` RULE to `RULES` in
|
|
11
11
|
* scripts/ci-test-scope.cjs, on the theory that classify()'s `!codeChanged`
|
|
12
|
-
* normalization (which
|
|
13
|
-
* docs-only diffs) made the RULE inert to classify()'s
|
|
12
|
+
* normalization (which at the time zeroed fullMatrix/targeted_tests/
|
|
13
|
+
* windows_tests for docs-only diffs) made the RULE inert to classify()'s
|
|
14
|
+
* scope decision. (#4641 later removed `windows_tests` from classify()'s
|
|
15
|
+
* output entirely; the normalization today only zeroes fullMatrix and
|
|
16
|
+
* targeted_tests. This paragraph is historical narration of a rejected
|
|
17
|
+
* design, not a description of current behaviour.)
|
|
14
18
|
*
|
|
15
19
|
* That is true for docs-ONLY diffs and FALSE for MIXED docs+code diffs:
|
|
16
20
|
* `codeChanged` is true whenever ANY changed file is product/pipeline code,
|
|
@@ -170,6 +174,7 @@ const DOCS_GUARD_TESTS = {
|
|
|
170
174
|
// entry).
|
|
171
175
|
'tests/learnings.test.cjs': ['docs/FEATURES.md'],
|
|
172
176
|
'tests/analyze-dependencies.test.cjs': ['docs/COMMANDS.md'],
|
|
177
|
+
'tests/auto-select-attribute.test.cjs': ['docs/reference/plan-md.md'],
|
|
173
178
|
'tests/autonomous-converge.test.cjs': [
|
|
174
179
|
'docs/COMMANDS.md',
|
|
175
180
|
'docs/how-to/run-phases-autonomously.md',
|
|
@@ -193,6 +198,7 @@ const DOCS_GUARD_TESTS = {
|
|
|
193
198
|
// (commit-files-pathspec.test.cjs:1618) — cannot be resolved to specific
|
|
194
199
|
// files without re-deriving the scan's own file-discovery logic.
|
|
195
200
|
'tests/commit-files-pathspec.test.cjs': ['*'],
|
|
201
|
+
'tests/compact-content-4139.test.cjs': ['docs/CONFIGURATION.md'],
|
|
196
202
|
'tests/config-field-docs.test.cjs': ['docs/CONFIGURATION.md'],
|
|
197
203
|
'tests/config.test.cjs': ['docs/CONFIGURATION.md'],
|
|
198
204
|
'tests/context-index-sync.test.cjs': ['docs/CONTEXT-INDEX.json'],
|
|
@@ -267,6 +273,32 @@ const DOCS_GUARD_TESTS = {
|
|
|
267
273
|
// seeding, so a content edit to any of them (e.g. renaming a landmark
|
|
268
274
|
// heading/string a hostile-input test targets) can change this test's
|
|
269
275
|
// fixture assumptions.
|
|
276
|
+
// #4728: pins the retirement of Gemini CLI prose from every localized
|
|
277
|
+
// how-to/ARCHITECTURE/USER-GUIDE/CONFIGURATION/context-monitor mirror, plus
|
|
278
|
+
// the PRESERVE (Antigravity) and MODEL-AXIS (Gemini 2.5 Pro) negative-space
|
|
279
|
+
// checks in the same locales.
|
|
280
|
+
'tests/gemini-runtime-removed.test.cjs': [
|
|
281
|
+
'docs/ja-JP/how-to/install-on-your-runtime.md',
|
|
282
|
+
'docs/ko-KR/how-to/install-on-your-runtime.md',
|
|
283
|
+
'docs/pt-BR/how-to/install-on-your-runtime.md',
|
|
284
|
+
'docs/zh-CN/how-to/install-on-your-runtime.md',
|
|
285
|
+
'docs/ja-JP/ARCHITECTURE.md',
|
|
286
|
+
'docs/ko-KR/ARCHITECTURE.md',
|
|
287
|
+
'docs/pt-BR/ARCHITECTURE.md',
|
|
288
|
+
'docs/zh-CN/ARCHITECTURE.md',
|
|
289
|
+
'docs/ja-JP/USER-GUIDE.md',
|
|
290
|
+
'docs/ko-KR/USER-GUIDE.md',
|
|
291
|
+
'docs/pt-BR/USER-GUIDE.md',
|
|
292
|
+
'docs/zh-CN/USER-GUIDE.md',
|
|
293
|
+
'docs/ja-JP/CONFIGURATION.md',
|
|
294
|
+
'docs/ko-KR/CONFIGURATION.md',
|
|
295
|
+
'docs/pt-BR/CONFIGURATION.md',
|
|
296
|
+
'docs/zh-CN/CONFIGURATION.md',
|
|
297
|
+
'docs/ja-JP/context-monitor.md',
|
|
298
|
+
'docs/ko-KR/context-monitor.md',
|
|
299
|
+
'docs/pt-BR/context-monitor.md',
|
|
300
|
+
'docs/zh-CN/context-monitor.md',
|
|
301
|
+
],
|
|
270
302
|
'tests/gen-state-md-docs.test.cjs': [
|
|
271
303
|
'docs/reference/state-md.md',
|
|
272
304
|
'docs/ja-JP/reference/state-md.md',
|
|
@@ -371,6 +403,7 @@ const DOCS_GUARD_TESTS = {
|
|
|
371
403
|
'docs/how-to/plan-a-phase.md',
|
|
372
404
|
'docs/AGENTS.md',
|
|
373
405
|
],
|
|
406
|
+
'tests/ui-interaction-capture.test.cjs': ['docs/CONFIGURATION.md'],
|
|
374
407
|
'tests/ui-spec-inventory-provenance.test.cjs': [
|
|
375
408
|
'docs/FEATURES.md',
|
|
376
409
|
'docs/how-to/design-a-ui-phase.md',
|
|
@@ -31,6 +31,7 @@ const path = require('node:path');
|
|
|
31
31
|
|
|
32
32
|
const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
|
33
33
|
const { escapeRegex: escapeRegExp } = require('../gsd-core/bin/lib/pattern.cjs');
|
|
34
|
+
const { isContainedIn } = require('../gsd-core/bin/lib/security.cjs');
|
|
34
35
|
|
|
35
36
|
const ROOT = path.resolve(__dirname, '..');
|
|
36
37
|
const ADR_DIR = path.join(ROOT, 'docs', 'adr');
|
|
@@ -176,10 +177,15 @@ const ADR_FILENAME_RE = /^[0-9]+-[a-z0-9-]+\.md$/;
|
|
|
176
177
|
* segment merely BEGINS with two dots (`..hidden.md`), and a false "escapes
|
|
177
178
|
* the repository" on a valid path is a worse failure than a miss — hence the
|
|
178
179
|
* whole-segment `rel === '..' || rel.startsWith('..' + sep)` form.
|
|
180
|
+
*
|
|
181
|
+
* Delegates to the shared `isContainedIn` (ADR-4650): every call site here
|
|
182
|
+
* already resolved both operands itself (either lexically, before any
|
|
183
|
+
* filesystem call, or via realpathSync after a symlink) and needs only this
|
|
184
|
+
* comparison step — the exact already-resolved-caller case `isContainedIn`
|
|
185
|
+
* documents.
|
|
179
186
|
*/
|
|
180
187
|
function escapesRoot(abs, root) {
|
|
181
|
-
|
|
182
|
-
return rel === '..' || rel.startsWith(`..${path.sep}`) || path.isAbsolute(rel);
|
|
188
|
+
return !isContainedIn(abs, root);
|
|
183
189
|
}
|
|
184
190
|
|
|
185
191
|
/**
|
|
@@ -91,6 +91,18 @@ const NESTED_FAMILIES = [
|
|
|
91
91
|
subdir: 'steps',
|
|
92
92
|
filter: (f) => f.endsWith('.md'),
|
|
93
93
|
},
|
|
94
|
+
{
|
|
95
|
+
name: 'workflow_detail',
|
|
96
|
+
root: path.join(ROOT, 'gsd-core', 'workflows'),
|
|
97
|
+
subdir: 'detail',
|
|
98
|
+
filter: (f) => f.endsWith('.md'),
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'workflow_templates',
|
|
102
|
+
root: path.join(ROOT, 'gsd-core', 'workflows'),
|
|
103
|
+
subdir: 'templates',
|
|
104
|
+
filter: (f) => f.endsWith('.md'),
|
|
105
|
+
},
|
|
94
106
|
];
|
|
95
107
|
|
|
96
108
|
/**
|
|
@@ -78,6 +78,23 @@ const ROLE_TO_AGENT = {
|
|
|
78
78
|
verifier: 'gsd-verifier',
|
|
79
79
|
};
|
|
80
80
|
|
|
81
|
+
// #4740 — Role → family mapping. Three families: orchestration, planning,
|
|
82
|
+
// execution. This constrains what a workflow may DECLARE in agent-roles for
|
|
83
|
+
// a given step (admissibility), a separate concern from ROLE_TO_AGENT's
|
|
84
|
+
// agent-file presence check above.
|
|
85
|
+
const ROLE_FAMILY = {
|
|
86
|
+
orchestrator: 'orchestration',
|
|
87
|
+
researcher: 'planning', planner: 'planning', checker: 'planning',
|
|
88
|
+
executor: 'execution', verifier: 'execution',
|
|
89
|
+
};
|
|
90
|
+
const EXPECTED_FAMILY_BY_STEP = {
|
|
91
|
+
discuss: 'orchestration',
|
|
92
|
+
plan: 'planning',
|
|
93
|
+
execute: 'execution',
|
|
94
|
+
verify: 'orchestration',
|
|
95
|
+
ship: 'orchestration',
|
|
96
|
+
};
|
|
97
|
+
|
|
81
98
|
// ─── Parser ───────────────────────────────────────────────────────────────────
|
|
82
99
|
|
|
83
100
|
/**
|
|
@@ -228,6 +245,52 @@ function crossCheckRoles(content, agentRoles, fileName) {
|
|
|
228
245
|
return errors;
|
|
229
246
|
}
|
|
230
247
|
|
|
248
|
+
// ─── Cross-check: declared roles vs. their permitted family (#4740) ──────────
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* For a step, verify every role declared in agentRoles belongs to that step's
|
|
252
|
+
* expected family (orchestration / planning / execution).
|
|
253
|
+
*
|
|
254
|
+
* Unlike `assertPointsCoverage`'s `if (!expected) continue // caught
|
|
255
|
+
* elsewhere` guard, an unknown step here fails CLOSED: for points
|
|
256
|
+
* there is a second net (the canonical-set and duplicate checks), but nothing
|
|
257
|
+
* else in the repo validates role families, so failing open on an unknown
|
|
258
|
+
* step would make it the one input that silently bypasses this gate — the
|
|
259
|
+
* "unknown resolving to a safe known" failure mode this check exists to close.
|
|
260
|
+
*
|
|
261
|
+
* Pure: never sorts, de-dupes, or otherwise mutates `agentRoles` — the same
|
|
262
|
+
* array `buildContract` puts into the generated contract.
|
|
263
|
+
*
|
|
264
|
+
* @param {string} step The step named in the marker block.
|
|
265
|
+
* @param {string[]} agentRoles Roles declared in the block.
|
|
266
|
+
* @param {string} fileName For error messages.
|
|
267
|
+
* @returns {string[]} Array of error strings; empty = OK.
|
|
268
|
+
*/
|
|
269
|
+
function crossCheckRoleFamilies(step, agentRoles, fileName) {
|
|
270
|
+
const expectedFamily = EXPECTED_FAMILY_BY_STEP[step];
|
|
271
|
+
if (!expectedFamily) {
|
|
272
|
+
return [fileName + ': step "' + step + '" has no entry in EXPECTED_FAMILY_BY_STEP'];
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const errors = [];
|
|
276
|
+
for (const role of agentRoles) {
|
|
277
|
+
const family = ROLE_FAMILY[role];
|
|
278
|
+
if (!family) {
|
|
279
|
+
errors.push(
|
|
280
|
+
fileName + ': declared agent-role "' + role + '" has no entry in ROLE_FAMILY mapping',
|
|
281
|
+
);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
if (family !== expectedFamily) {
|
|
285
|
+
errors.push(
|
|
286
|
+
fileName + ': declared agent-role "' + role + '" (family "' + family +
|
|
287
|
+
'") is not permitted at step "' + step + '" (expected family "' + expectedFamily + '")',
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return errors;
|
|
292
|
+
}
|
|
293
|
+
|
|
231
294
|
// ─── 12-points coverage assertion ────────────────────────────────────────────
|
|
232
295
|
|
|
233
296
|
/**
|
|
@@ -331,6 +394,10 @@ function buildContract(workflowsDir) {
|
|
|
331
394
|
const roleErrors = crossCheckRoles(content, entry.agentRoles, file);
|
|
332
395
|
allErrors.push(...roleErrors);
|
|
333
396
|
|
|
397
|
+
// Cross-check role families (#4740)
|
|
398
|
+
const roleFamilyErrors = crossCheckRoleFamilies(entry.step, entry.agentRoles, file);
|
|
399
|
+
allErrors.push(...roleFamilyErrors);
|
|
400
|
+
|
|
334
401
|
for (const auxiliary of auxiliaryHosts) {
|
|
335
402
|
let auxiliaryContent;
|
|
336
403
|
try {
|
|
@@ -667,6 +734,7 @@ function getWiredLoopPoints(repoRoot) {
|
|
|
667
734
|
module.exports = {
|
|
668
735
|
parseLoopHostBlock,
|
|
669
736
|
crossCheckRoles,
|
|
737
|
+
crossCheckRoleFamilies,
|
|
670
738
|
assertPointsCoverage,
|
|
671
739
|
buildContract,
|
|
672
740
|
serializeContract,
|
|
@@ -676,6 +744,7 @@ module.exports = {
|
|
|
676
744
|
CANONICAL_POINTS,
|
|
677
745
|
EXPECTED_POINTS_BY_STEP,
|
|
678
746
|
ROLE_TO_AGENT,
|
|
747
|
+
ROLE_FAMILY,
|
|
679
748
|
scanWiredPoints,
|
|
680
749
|
getWiredLoopPoints,
|
|
681
750
|
coveredKindsInRegion,
|