@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
|
@@ -162,6 +162,12 @@ const REASON = Object.freeze({
|
|
|
162
162
|
// Axis 2 (§8.6, retained): a raw `fs.writeFileSync(` call targeting the
|
|
163
163
|
// state path — see `findRawStateWrites`.
|
|
164
164
|
RAW_STATE_WRITE: 'raw_state_write',
|
|
165
|
+
// ADR-4629 §8.1 (epic #4629, C1): a residual `readModifyWriteStateMd(path,
|
|
166
|
+
// (content) => …)` call whose transform is an inline anonymous arrow/function
|
|
167
|
+
// — the opaque shape §8.1 replaces with a declared StateWriteIntent. Recognized
|
|
168
|
+
// by `findOpaqueStateTransforms`; a CAPABILITY in C1 (not wired into collect()),
|
|
169
|
+
// wired terminal in C2 as the residual callers migrate (ADR-3408 §6 phasing).
|
|
170
|
+
OPAQUE_STATE_TRANSFORM: 'opaque_state_transform',
|
|
165
171
|
// Axis 4 (§8.3, Decision 4(d)): prompt-layer prose shelling out to a
|
|
166
172
|
// write-side `gsd-tools` subcommand — see `findPromptSeamUses`.
|
|
167
173
|
PROMPT_LAYER_STATE_WRITE: 'prompt_layer_state_write',
|
|
@@ -645,6 +651,91 @@ function findRawStateWrites(rel, text) {
|
|
|
645
651
|
return out;
|
|
646
652
|
}
|
|
647
653
|
|
|
654
|
+
// ADR-4629 §8.1 (epic #4629, C1) — OPAQUE-TRANSFORM RECOGNITION.
|
|
655
|
+
//
|
|
656
|
+
// A residual `readModifyWriteStateMd(path, (content) => …)` call whose transform
|
|
657
|
+
// (2nd) argument is an inline anonymous arrow / function expression is the opaque
|
|
658
|
+
// shape §8.1 replaces with a declared StateWriteIntent: `readModifyWriteStateMd`
|
|
659
|
+
// goes THROUGH the seam (it is NOT a raw-write bypass — Axis 2's concern), but its
|
|
660
|
+
// opaque body transform is neither verified (§8.2) nor bounded (§8.3). This
|
|
661
|
+
// function RECOGNIZES that shape.
|
|
662
|
+
//
|
|
663
|
+
// C1 ships recognition as a CAPABILITY: it is exported and unit-tested (positive
|
|
664
|
+
// control on a seeded fixture) but is DELIBERATELY NOT wired into `collect()`'s
|
|
665
|
+
// failing scan. §8.1's caller-side rule is *Required — Phase 2*; wiring it now
|
|
666
|
+
// would turn the ~16 residual callers red at once, and ADR-3473 §8.6 retired the
|
|
667
|
+
// ratchet that would otherwise be needed to absorb them. C2 wires this terminal as
|
|
668
|
+
// the verifying executor lands and the callers migrate under ADR-3408 §6 phasing.
|
|
669
|
+
//
|
|
670
|
+
// String match, never an AST — same over-report-safe posture as every axis here.
|
|
671
|
+
const OPAQUE_RMW_CALL_RE = /\breadModifyWriteStateMd\s*\(/g;
|
|
672
|
+
// The transform arg is OPAQUE when it BEGINS an inline anonymous function: an
|
|
673
|
+
// arrow (`(…) =>`, `ident =>`, optionally `async`) or a `function` expression. A
|
|
674
|
+
// bare identifier / object (a declared StateWriteIntent, Phase 2+) is NOT opaque.
|
|
675
|
+
const ANON_TRANSFORM_RE =
|
|
676
|
+
/^\s*(?:async\s+)?(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>|^\s*(?:async\s+)?function\b/;
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Capture the top-level, comma-separated argument list of a call, starting at
|
|
680
|
+
* `startIdx` (the index just AFTER the opening `(`) — across newlines and
|
|
681
|
+
* string-aware, tracking `()[]{}` depth. Returns the raw arg strings, or null if
|
|
682
|
+
* the parens never balance (a truncated arg list is never flagged). Generalizes
|
|
683
|
+
* `captureFirstArg`'s depth/inStr bookkeeping to every argument.
|
|
684
|
+
*/
|
|
685
|
+
function captureCallArgList(text, startIdx) {
|
|
686
|
+
let depth = 0;
|
|
687
|
+
let inStr = null;
|
|
688
|
+
const args = [];
|
|
689
|
+
let cur = '';
|
|
690
|
+
for (let i = startIdx; i < text.length; i++) {
|
|
691
|
+
const ch = text[i];
|
|
692
|
+
if (inStr) {
|
|
693
|
+
cur += ch;
|
|
694
|
+
if (ch === inStr && text[i - 1] !== '\\') inStr = null;
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
697
|
+
if (ch === '"' || ch === "'" || ch === '`') { inStr = ch; cur += ch; continue; }
|
|
698
|
+
if (ch === '(' || ch === '[' || ch === '{') { depth++; cur += ch; continue; }
|
|
699
|
+
if (ch === ')' || ch === ']' || ch === '}') {
|
|
700
|
+
if (ch === ')' && depth === 0) {
|
|
701
|
+
if (cur.trim() !== '' || args.length) args.push(cur);
|
|
702
|
+
return args;
|
|
703
|
+
}
|
|
704
|
+
depth--; cur += ch; continue;
|
|
705
|
+
}
|
|
706
|
+
if (ch === ',' && depth === 0) { args.push(cur); cur = ''; continue; }
|
|
707
|
+
cur += ch;
|
|
708
|
+
}
|
|
709
|
+
return null; // parens never balanced
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* Recognize residual opaque-transform STATE.md writes (ADR-4629 §8.1). Returns a
|
|
714
|
+
* finding per `readModifyWriteStateMd(` call whose 2nd argument is an inline
|
|
715
|
+
* anonymous transform. CAPABILITY only in C1 — not called by `collect()`.
|
|
716
|
+
*/
|
|
717
|
+
function findOpaqueStateTransforms(rel, text) {
|
|
718
|
+
const rawLines = text.split('\n');
|
|
719
|
+
const stripped = stripComments(text).join('\n');
|
|
720
|
+
const out = [];
|
|
721
|
+
let m;
|
|
722
|
+
OPAQUE_RMW_CALL_RE.lastIndex = 0;
|
|
723
|
+
while ((m = OPAQUE_RMW_CALL_RE.exec(stripped)) !== null) {
|
|
724
|
+
const args = captureCallArgList(stripped, m.index + m[0].length);
|
|
725
|
+
if (!args || args.length < 2) continue;
|
|
726
|
+
if (!ANON_TRANSFORM_RE.test(args[1])) continue;
|
|
727
|
+
const lineNo = stripped.slice(0, m.index).split('\n').length;
|
|
728
|
+
out.push({
|
|
729
|
+
reason: REASON.OPAQUE_STATE_TRANSFORM,
|
|
730
|
+
axis: 'opaque-transform',
|
|
731
|
+
file: sanitizeForReport(rel),
|
|
732
|
+
line: lineNo,
|
|
733
|
+
source: sanitizeForReport((rawLines[lineNo - 1] || '').trim()),
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
return out;
|
|
737
|
+
}
|
|
738
|
+
|
|
648
739
|
// The two write-seam STAGE functions, matched only as CALLS (`\(`
|
|
649
740
|
// immediately after, modulo whitespace) — never as bare mentions of the
|
|
650
741
|
// name. `writeStateMd(` is deliberately NOT included here (that arm is
|
|
@@ -941,6 +1032,8 @@ module.exports = {
|
|
|
941
1032
|
nearestPrecedingAssignment,
|
|
942
1033
|
findRawStateWrites,
|
|
943
1034
|
targetsStatePath,
|
|
1035
|
+
findOpaqueStateTransforms,
|
|
1036
|
+
captureCallArgList,
|
|
944
1037
|
findCompositionBypasses,
|
|
945
1038
|
findPromptSeamUses,
|
|
946
1039
|
isInsideCodeSpan,
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_doc": "Baseline of modules currently exceeding the 2-test-file limit. Each entry locks in TODAY's exact test filenames as the allowlisted set (identity ratchet). Adding a NEW test file to a capped module fails (novel). Removing one requires pruning this list (stale, ratchet-down). When a cluster drops to
|
|
2
|
+
"_doc": "Baseline of modules currently exceeding the 2-test-file limit. Each entry locks in TODAY's exact test filenames as the allowlisted set (identity ratchet). Adding a NEW test file to a capped module fails (novel). Removing one requires pruning this list (stale, ratchet-down). When a cluster drops to ≤ 2, remove its entry entirely. New entries require justification in PR description.",
|
|
3
3
|
"modules": {
|
|
4
|
+
"ui-consideration-probe": {
|
|
5
|
+
"files": [
|
|
6
|
+
"ui-consideration-probe-docs-fixtures.test.cjs",
|
|
7
|
+
"ui-consideration-probe-ui-phase-contract.test.cjs",
|
|
8
|
+
"ui-consideration-probe.test.cjs"
|
|
9
|
+
],
|
|
10
|
+
"issue": "4657",
|
|
11
|
+
"justification": "The ui-consideration-probe cluster gains its workflow-prose contract file (tests/ui-consideration-probe-ui-phase-contract.test.cjs, #4657), mirroring the edge probe's split (edge-probe.test.cjs / edge-probe-docs-fixtures.test.cjs / edge-probe-spec-phase-contract.test.cjs). The contract file reads shipped gsd-core/workflows/ui-phase.md under the source-text-is-the-product exception, which the unit file deliberately does not carry (it asserts typed returns only)."
|
|
12
|
+
},
|
|
4
13
|
"adr-parser": {
|
|
5
14
|
"files": [
|
|
6
15
|
"adr-parser.property.test.cjs",
|
|
@@ -40,7 +49,7 @@
|
|
|
40
49
|
"frontmatter.unit.test.cjs"
|
|
41
50
|
],
|
|
42
51
|
"issue": "3881",
|
|
43
|
-
"justification": "Grandfathered by #3227 for the original 4-file cluster (pre-existing over-cap, not new sprawl). #3881 (ADR-3473
|
|
52
|
+
"justification": "Grandfathered by #3227 for the original 4-file cluster (pre-existing over-cap, not new sprawl). #3881 (ADR-3473 §8.1, the js-yaml parser migration) adds two more: frontmatter-golden-parity.test.cjs (D-series golden-corpus diff against the legacy parser, ~900 real documents — cannot be folded into an existing file without losing its independent-of-current-parser provenance) and frontmatter-roundtrip.property.test.cjs (fast-check property coverage the migration's bijective-contract rule requires). Both are migration-specific, not incidental sprawl."
|
|
44
53
|
},
|
|
45
54
|
"graphify": {
|
|
46
55
|
"files": [
|
|
@@ -123,6 +132,7 @@
|
|
|
123
132
|
"state-prune.test.cjs",
|
|
124
133
|
"state-rebuild-cli.test.cjs",
|
|
125
134
|
"state-rebuild.test.cjs",
|
|
135
|
+
"state-todos-render.test.cjs",
|
|
126
136
|
"state-write-path-drift-guard.test.cjs",
|
|
127
137
|
"state.test.cjs"
|
|
128
138
|
],
|
|
@@ -136,10 +146,11 @@
|
|
|
136
146
|
"verify-npm-publish.test.cjs",
|
|
137
147
|
"verify-test-quality.test.cjs",
|
|
138
148
|
"verify-work-auto-transition.test.cjs",
|
|
149
|
+
"verify-work-deferred-promotion.test.cjs",
|
|
139
150
|
"verify.test.cjs"
|
|
140
151
|
],
|
|
141
|
-
"issue": "#3813
|
|
142
|
-
"justification": "verify-command-grounding added by #2401/#3678; allowlist follow-up landed with #3606 (base was red on this lane)."
|
|
152
|
+
"issue": "#3813 — the live-path #1883 suite drives buildPlanningSnapshot in-process with an fs fault; the verify module suites are CLI-driving and cannot host an fs monkeypatch",
|
|
153
|
+
"justification": "verify-command-grounding added by #2401/#3678; allowlist follow-up landed with #3606 (base was red on this lane). #4546 adds verify-work-deferred-promotion (deferred-follow-up promotion writer contract + parity)."
|
|
143
154
|
},
|
|
144
155
|
"install": {
|
|
145
156
|
"files": [
|
|
@@ -153,7 +164,7 @@
|
|
|
153
164
|
"install-write-confinement.test.cjs",
|
|
154
165
|
"install.test.cjs"
|
|
155
166
|
],
|
|
156
|
-
"issue": "#3798
|
|
167
|
+
"issue": "#3798 — the profile-closure spawn test reads the real repo surface (commands+workflows+agents); consolidating it into install.test.cjs would put a whole-repo scan behind the suite's heaviest file"
|
|
157
168
|
},
|
|
158
169
|
"edge-probe": {
|
|
159
170
|
"files": [
|
|
@@ -251,8 +262,8 @@
|
|
|
251
262
|
"docs-state-md-locale-parity.test.cjs",
|
|
252
263
|
"docs-update.test.cjs"
|
|
253
264
|
],
|
|
254
|
-
"issue": "3873 | #3839
|
|
255
|
-
"justification": "ADR-3473
|
|
265
|
+
"issue": "3873 | #3839 — the hook-event parity suite cross-checks the four docs hook tables against src/runtime-hooks-surface.cts registrations; a generated-docs concern distinct from content freshness and registry parity",
|
|
266
|
+
"justification": "ADR-3473 §8.8 makes docs/reference/state-md.md and its four locale siblings generated-and-committed and adds the repo's first locale-parity check (verified: no locale-parity lint precedent exists here). That check is a distinct concern from docs-update (content freshness) and docs-parity-live-registry (registry parity); folding it into either would place an unrelated subject inside them purely to satisfy a count. The section it guards is absent from all four translations today and documents the status enum behind #3853."
|
|
256
267
|
},
|
|
257
268
|
"audit": {
|
|
258
269
|
"files": [
|
|
@@ -264,7 +275,7 @@
|
|
|
264
275
|
"audit-uat-summary-segmentation.test.cjs",
|
|
265
276
|
"audit-workstream-layouts.test.cjs"
|
|
266
277
|
],
|
|
267
|
-
"issue": "#3804/#3805
|
|
278
|
+
"issue": "#3804/#3805 — audit-layout and acknowledged-marker suites drive the real audit-uat CLI against on-disk fixtures | #3817 — regression suite proving countReal counts the truncation remainder marker instead of treating it as one phantom item | #3783 — dedicated suite for the summary.current_milestone/archived segmentation, matching this module's one-file-per-feature-slice precedent (e.g. audit-uat-acknowledged.test.cjs) rather than growing the unrelated 6900+ line tests/uat.test.cjs (a different module, keyed off uat.cjs)"
|
|
268
279
|
},
|
|
269
280
|
"shell-command-projection": {
|
|
270
281
|
"files": [
|
|
@@ -272,7 +283,16 @@
|
|
|
272
283
|
"shell-command-projection-md-normalize.test.cjs",
|
|
273
284
|
"shell-command-projection-path-sep.test.cjs"
|
|
274
285
|
],
|
|
275
|
-
"issue": "#3854
|
|
286
|
+
"issue": "#3854 — the tight-list suite pins the markdown write-normalizer's blank-line policy through the exported normalizeContent/platformWriteSync seam; a distinct concern from dispatch routing and path separation"
|
|
287
|
+
},
|
|
288
|
+
"ui-consideration-probe": {
|
|
289
|
+
"files": [
|
|
290
|
+
"ui-consideration-probe-docs-fixtures.test.cjs",
|
|
291
|
+
"ui-consideration-probe-ui-phase-contract.test.cjs",
|
|
292
|
+
"ui-consideration-probe.test.cjs"
|
|
293
|
+
],
|
|
294
|
+
"issue": "4657",
|
|
295
|
+
"justification": "The ui-consideration-probe cluster gains its workflow-prose contract file (tests/ui-consideration-probe-ui-phase-contract.test.cjs, #4657), mirroring the edge probe's split (edge-probe.test.cjs / edge-probe-docs-fixtures.test.cjs / edge-probe-spec-phase-contract.test.cjs). The contract file reads shipped gsd-core/workflows/ui-phase.md under the source-text-is-the-product exception, which the unit file deliberately does not carry (it asserts typed returns only)."
|
|
276
296
|
}
|
|
277
297
|
}
|
|
278
298
|
}
|
|
@@ -161,8 +161,24 @@ function compareFiles(relA, relB) {
|
|
|
161
161
|
* @param {string} spec
|
|
162
162
|
* @returns {string}
|
|
163
163
|
*/
|
|
164
|
+
const PIN_OPERATOR_RE = /^(\^|~|>=|<=|>|<|=)?/;
|
|
165
|
+
|
|
164
166
|
function stripRangeOperator(spec) {
|
|
165
|
-
return String(spec || '').trim().replace(
|
|
167
|
+
return String(spec || '').trim().replace(PIN_OPERATOR_RE, '').trim();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* The leading range-operator token (if any) a package.json dependency spec
|
|
172
|
+
* was written with — the inverse half of stripRangeOperator, needed by
|
|
173
|
+
* `fixRow` to rebuild a pin (`<same operator>` + `<new version>`) that
|
|
174
|
+
* preserves the author's original range style instead of collapsing every
|
|
175
|
+
* pin to an exact version.
|
|
176
|
+
* @param {string} spec
|
|
177
|
+
* @returns {string} the operator (e.g. "^", "~", ">="), or "" for an exact pin
|
|
178
|
+
*/
|
|
179
|
+
function pinOperatorPrefix(spec) {
|
|
180
|
+
const m = String(spec || '').trim().match(PIN_OPERATOR_RE);
|
|
181
|
+
return (m && m[1]) || '';
|
|
166
182
|
}
|
|
167
183
|
|
|
168
184
|
/**
|
|
@@ -211,12 +227,40 @@ function checkHandAuthoredTwin(row) {
|
|
|
211
227
|
return findings;
|
|
212
228
|
}
|
|
213
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Read a row's pin state: the package.json devDependencies spec for
|
|
232
|
+
* `row.name` and, if `node_modules/<row.name>/package.json` exists, its
|
|
233
|
+
* installed version. Shared by checkRow (compares) and fixRow (rewrites) so
|
|
234
|
+
* the two can never silently diverge on how a pin is read.
|
|
235
|
+
* @param {VendoredPackage} row
|
|
236
|
+
* @param {string} [pkgRoot] Override for testing -- defaults to the real repo ROOT. Lets a
|
|
237
|
+
* test point fixRow's pin-rewrite at an isolated temp package.json instead of writing the
|
|
238
|
+
* real, shared one, which other concurrently-running node --test files read at module
|
|
239
|
+
* top-level (the same race class already fixed for the vendored .cjs copy).
|
|
240
|
+
* @returns {{pinnedSpec: string | undefined, installedVersion: string | undefined}}
|
|
241
|
+
*/
|
|
242
|
+
function readPinState(row, pkgRoot = ROOT) {
|
|
243
|
+
const pkgPath = path.join(pkgRoot, 'package.json');
|
|
244
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
245
|
+
const pinnedSpec = pkg.devDependencies && pkg.devDependencies[row.name];
|
|
246
|
+
const installedPkgPath = path.join(pkgRoot, 'node_modules', row.name, 'package.json');
|
|
247
|
+
let installedVersion;
|
|
248
|
+
if (fs.existsSync(installedPkgPath)) {
|
|
249
|
+
installedVersion = JSON.parse(fs.readFileSync(installedPkgPath, 'utf8')).version;
|
|
250
|
+
}
|
|
251
|
+
return { pinnedSpec, installedVersion };
|
|
252
|
+
}
|
|
253
|
+
|
|
214
254
|
/**
|
|
215
255
|
* Run all applicable freshness checks for one vendored package row.
|
|
216
256
|
* @param {VendoredPackage} row
|
|
257
|
+
* @param {string} [pkgRoot] Override for testing -- defaults to the real repo ROOT. Lets a
|
|
258
|
+
* test point fixRow's pin-rewrite at an isolated temp package.json instead of writing the
|
|
259
|
+
* real, shared one, which other concurrently-running node --test files read at module
|
|
260
|
+
* top-level (the same race class already fixed for the vendored .cjs copy).
|
|
217
261
|
* @returns {string[]} findings (empty when the row is fresh)
|
|
218
262
|
*/
|
|
219
|
-
function checkRow(row) {
|
|
263
|
+
function checkRow(row, pkgRoot = ROOT) {
|
|
220
264
|
const findings = [];
|
|
221
265
|
|
|
222
266
|
const cjsDrift = compareFiles(row.vendoredCjs, row.upstreamCjs);
|
|
@@ -235,31 +279,96 @@ function checkRow(row) {
|
|
|
235
279
|
findings.push(...checkHandAuthoredTwin(row));
|
|
236
280
|
}
|
|
237
281
|
|
|
238
|
-
const
|
|
239
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
240
|
-
const pinnedSpec = pkg.devDependencies && pkg.devDependencies[row.name];
|
|
282
|
+
const { pinnedSpec, installedVersion } = readPinState(row, pkgRoot);
|
|
241
283
|
if (!pinnedSpec) {
|
|
242
284
|
findings.push(`package.json devDependencies.${row.name} is missing`);
|
|
285
|
+
} else if (installedVersion === undefined) {
|
|
286
|
+
findings.push(`node_modules/${row.name}/package.json does not exist (run npm install)`);
|
|
243
287
|
} else {
|
|
244
|
-
const
|
|
245
|
-
if (
|
|
246
|
-
findings.push(
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if (pinned !== installed.version) {
|
|
251
|
-
findings.push(
|
|
252
|
-
`package.json devDependencies.${row.name} ("${pinnedSpec}" -> "${pinned}") != `
|
|
253
|
-
+ `node_modules/${row.name}/package.json version ("${installed.version}")`,
|
|
254
|
-
);
|
|
255
|
-
}
|
|
288
|
+
const pinned = stripRangeOperator(pinnedSpec);
|
|
289
|
+
if (pinned !== installedVersion) {
|
|
290
|
+
findings.push(
|
|
291
|
+
`package.json devDependencies.${row.name} ("${pinnedSpec}" -> "${pinned}") != `
|
|
292
|
+
+ `node_modules/${row.name}/package.json version ("${installedVersion}")`,
|
|
293
|
+
);
|
|
256
294
|
}
|
|
257
295
|
}
|
|
258
296
|
|
|
259
297
|
return findings;
|
|
260
298
|
}
|
|
261
299
|
|
|
300
|
+
/**
|
|
301
|
+
* Mechanically resolve a vendored package's byte/pin drift: copy the
|
|
302
|
+
* upstream .cjs (and, for `upstream-verbatim` rows, the .d.cts twins) over
|
|
303
|
+
* the vendored copy, and bump the package.json pin to the installed
|
|
304
|
+
* version, preserving the original range-operator prefix. Then re-runs
|
|
305
|
+
* `checkRow` and returns whatever findings remain.
|
|
306
|
+
*
|
|
307
|
+
* This NEVER hand-edits a `hand-authored` twin (e.g. js-yaml.d.cts) — that
|
|
308
|
+
* file encodes a human's deliberate judgment about which exports are safe
|
|
309
|
+
* to expose, and only a human can tell whether a declared-export-missing
|
|
310
|
+
* finding is mechanical drift or a real upstream API break. If one remains
|
|
311
|
+
* after this runs, that is by design: the caller must not treat it as
|
|
312
|
+
* fixed.
|
|
313
|
+
* @param {VendoredPackage} row
|
|
314
|
+
* @param {string} [pkgRoot] Override for testing -- defaults to the real repo ROOT. Lets a
|
|
315
|
+
* test point fixRow's pin-rewrite at an isolated temp package.json instead of writing the
|
|
316
|
+
* real, shared one, which other concurrently-running node --test files read at module
|
|
317
|
+
* top-level (the same race class already fixed for the vendored .cjs copy).
|
|
318
|
+
* @returns {string[]} findings remaining after the fix (empty when fully resolved)
|
|
319
|
+
*/
|
|
320
|
+
function fixRow(row, pkgRoot = ROOT) {
|
|
321
|
+
fs.copyFileSync(resolvePath(row.upstreamCjs), resolvePath(row.vendoredCjs));
|
|
322
|
+
|
|
323
|
+
if (row.twinKind === 'upstream-verbatim' && row.upstreamDts) {
|
|
324
|
+
if (row.vendoredDts) fs.copyFileSync(resolvePath(row.upstreamDts), resolvePath(row.vendoredDts));
|
|
325
|
+
if (row.srcTwin) fs.copyFileSync(resolvePath(row.upstreamDts), resolvePath(row.srcTwin));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const { pinnedSpec, installedVersion } = readPinState(row, pkgRoot);
|
|
329
|
+
if (pinnedSpec && installedVersion !== undefined) {
|
|
330
|
+
const newPin = `${pinOperatorPrefix(pinnedSpec)}${installedVersion}`;
|
|
331
|
+
if (newPin !== pinnedSpec) {
|
|
332
|
+
const pkgPath = path.join(pkgRoot, 'package.json');
|
|
333
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
334
|
+
pkg.devDependencies[row.name] = newPin;
|
|
335
|
+
fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return checkRow(row, pkgRoot);
|
|
340
|
+
}
|
|
341
|
+
|
|
262
342
|
function main() {
|
|
343
|
+
if (process.argv.includes('--fix')) {
|
|
344
|
+
/** @type {Record<string, string[]>} */
|
|
345
|
+
const remaining = {};
|
|
346
|
+
for (const row of VENDORED) {
|
|
347
|
+
const findings = fixRow(row);
|
|
348
|
+
if (findings.length > 0) remaining[row.name] = findings;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const names = VENDORED.map((row) => row.name).join(', ');
|
|
352
|
+
|
|
353
|
+
if (Object.keys(remaining).length === 0) {
|
|
354
|
+
process.stdout.write(
|
|
355
|
+
`ok lint-vendored-deps --fix: gsd-core/bin/lib/vendor/{${names}} refreshed and now match node_modules and their pinned versions\n`,
|
|
356
|
+
);
|
|
357
|
+
return 0;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const detail = Object.entries(remaining)
|
|
361
|
+
.map(([name, findings]) => ` ${name}:\n${findings.map((f) => ` ${f}`).join('\n')}`)
|
|
362
|
+
.join('\n');
|
|
363
|
+
throw new ExitError(
|
|
364
|
+
1,
|
|
365
|
+
`lint-vendored-deps --fix: mechanical drift refreshed, but the following row(s)\n`
|
|
366
|
+
+ 'still have findings that --fix cannot resolve automatically — these need a\n'
|
|
367
|
+
+ 'human, not just a re-run of --fix:\n'
|
|
368
|
+
+ detail,
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
|
|
263
372
|
const findings = [];
|
|
264
373
|
for (const row of VENDORED) {
|
|
265
374
|
findings.push(...checkRow(row));
|
|
@@ -288,9 +397,11 @@ if (require.main === module) runMain(main);
|
|
|
288
397
|
module.exports = {
|
|
289
398
|
compareFiles,
|
|
290
399
|
stripRangeOperator,
|
|
400
|
+
pinOperatorPrefix,
|
|
291
401
|
VENDORED,
|
|
292
402
|
buildRefreshCommand,
|
|
293
403
|
checkRow,
|
|
404
|
+
fixRow,
|
|
294
405
|
declaredValueExports,
|
|
295
406
|
checkHandAuthoredTwin,
|
|
296
407
|
resolvePath,
|
|
@@ -274,6 +274,26 @@
|
|
|
274
274
|
"code": "2086",
|
|
275
275
|
"message": "Double quote to prevent globbing and word splitting."
|
|
276
276
|
},
|
|
277
|
+
{
|
|
278
|
+
"file": "gsd-core/workflows/complete-milestone/detail/elaboration.md",
|
|
279
|
+
"code": "2001",
|
|
280
|
+
"message": "See if you can use ${variable//search/replace} instead."
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"file": "gsd-core/workflows/complete-milestone/detail/elaboration.md",
|
|
284
|
+
"code": "2001",
|
|
285
|
+
"message": "See if you can use ${variable//search/replace} instead."
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"file": "gsd-core/workflows/complete-milestone/detail/elaboration.md",
|
|
289
|
+
"code": "2086",
|
|
290
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"file": "gsd-core/workflows/complete-milestone/detail/elaboration.md",
|
|
294
|
+
"code": "2086",
|
|
295
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
296
|
+
},
|
|
277
297
|
{
|
|
278
298
|
"file": "gsd-core/workflows/debug.md",
|
|
279
299
|
"code": "2010",
|
|
@@ -369,6 +389,11 @@
|
|
|
369
389
|
"code": "2086",
|
|
370
390
|
"message": "Double quote to prevent globbing and word splitting."
|
|
371
391
|
},
|
|
392
|
+
{
|
|
393
|
+
"file": "gsd-core/workflows/execute-phase/detail/elaboration.md",
|
|
394
|
+
"code": "2086",
|
|
395
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
396
|
+
},
|
|
372
397
|
{
|
|
373
398
|
"file": "gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md",
|
|
374
399
|
"code": "2016",
|
|
@@ -469,6 +494,56 @@
|
|
|
469
494
|
"code": "2012",
|
|
470
495
|
"message": "Use find instead of ls to better handle non-alphanumeric filenames."
|
|
471
496
|
},
|
|
497
|
+
{
|
|
498
|
+
"file": "gsd-core/workflows/new-milestone.md",
|
|
499
|
+
"code": "2086",
|
|
500
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
"file": "gsd-core/workflows/new-milestone.md",
|
|
504
|
+
"code": "2086",
|
|
505
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
"file": "gsd-core/workflows/new-milestone.md",
|
|
509
|
+
"code": "2086",
|
|
510
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
"file": "gsd-core/workflows/new-milestone.md",
|
|
514
|
+
"code": "2086",
|
|
515
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
"file": "gsd-core/workflows/new-milestone.md",
|
|
519
|
+
"code": "2086",
|
|
520
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
"file": "gsd-core/workflows/new-milestone.md",
|
|
524
|
+
"code": "2086",
|
|
525
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
"file": "gsd-core/workflows/new-milestone.md",
|
|
529
|
+
"code": "2086",
|
|
530
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
"file": "gsd-core/workflows/new-milestone.md",
|
|
534
|
+
"code": "2086",
|
|
535
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
"file": "gsd-core/workflows/new-milestone.md",
|
|
539
|
+
"code": "2086",
|
|
540
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
"file": "gsd-core/workflows/new-milestone.md",
|
|
544
|
+
"code": "2086",
|
|
545
|
+
"message": "Double quote to prevent globbing and word splitting."
|
|
546
|
+
},
|
|
472
547
|
{
|
|
473
548
|
"file": "gsd-core/workflows/new-project.md",
|
|
474
549
|
"code": "2012",
|
|
@@ -479,6 +554,16 @@
|
|
|
479
554
|
"code": "2012",
|
|
480
555
|
"message": "Use find instead of ls to better handle non-alphanumeric filenames."
|
|
481
556
|
},
|
|
557
|
+
{
|
|
558
|
+
"file": "gsd-core/workflows/new-project/detail/elaboration.md",
|
|
559
|
+
"code": "2012",
|
|
560
|
+
"message": "Use find instead of ls to better handle non-alphanumeric filenames."
|
|
561
|
+
},
|
|
562
|
+
{
|
|
563
|
+
"file": "gsd-core/workflows/new-project/detail/elaboration.md",
|
|
564
|
+
"code": "2012",
|
|
565
|
+
"message": "Use find instead of ls to better handle non-alphanumeric filenames."
|
|
566
|
+
},
|
|
482
567
|
{
|
|
483
568
|
"file": "gsd-core/workflows/new-workspace.md",
|
|
484
569
|
"code": "2164",
|
|
@@ -1023,5 +1108,20 @@
|
|
|
1023
1108
|
"file": "gsd-core/workflows/verify-work/steps/mvp-uat-framing.md",
|
|
1024
1109
|
"code": "2086",
|
|
1025
1110
|
"message": "Double quote to prevent globbing and word splitting."
|
|
1111
|
+
},
|
|
1112
|
+
{
|
|
1113
|
+
"file": "gsd-core/workflows/execute-phase/steps/code-review-disposition.md",
|
|
1114
|
+
"code": "2317",
|
|
1115
|
+
"message": "Command appears to be unreachable. Check usage (or ignore if invoked indirectly)."
|
|
1116
|
+
},
|
|
1117
|
+
{
|
|
1118
|
+
"file": "gsd-core/workflows/execute-phase/steps/code-review-disposition.md",
|
|
1119
|
+
"code": "2317",
|
|
1120
|
+
"message": "Command appears to be unreachable. Check usage (or ignore if invoked indirectly)."
|
|
1121
|
+
},
|
|
1122
|
+
{
|
|
1123
|
+
"file": "gsd-core/workflows/execute-phase/steps/code-review-disposition.md",
|
|
1124
|
+
"code": "2317",
|
|
1125
|
+
"message": "Command appears to be unreachable. Check usage (or ignore if invoked indirectly)."
|
|
1026
1126
|
}
|
|
1027
1127
|
]
|
|
@@ -171,6 +171,10 @@ ALLOWLIST=(
|
|
|
171
171
|
# allowlist cannot reach it either, because the literal `child_process` is
|
|
172
172
|
# not adjacent to `.exec`. See the note at the pattern itself.
|
|
173
173
|
'tests/continuation-grammar-parity.test.cjs'
|
|
174
|
+
# #4906 Phase 5 — regex.exec('### Phase 03: ...') fixtures.
|
|
175
|
+
# Same DEFECT.PROMPT-INJECTION-SCAN-COLLISION class as above:
|
|
176
|
+
# RegExp.prototype.exec, not code execution.
|
|
177
|
+
'tests/phase-id.test.cjs'
|
|
174
178
|
# #3676 row 11b — quick-batch's task-list parser must treat a
|
|
175
179
|
# prompt-injection-shaped task description as inert data, never
|
|
176
180
|
# interpreted. The fixture has to be a real "ignore all previous
|
|
@@ -179,6 +183,20 @@ ALLOWLIST=(
|
|
|
179
183
|
# rendering, never a command. Same DEFECT.PROMPT-INJECTION-SCAN-COLLISION
|
|
180
184
|
# class as the input-validator fixtures above.
|
|
181
185
|
'tests/quick-batch.test.cjs'
|
|
186
|
+
# #4209 — the regression test pinning gsd-code-reviewer.md's untrusted-evidence
|
|
187
|
+
# contract discusses the injection attack it defends against (embedded
|
|
188
|
+
# redirection, "act as an instruction") without performing it. gsd-code-reviewer.md
|
|
189
|
+
# ITSELF is deliberately NOT allowlisted — R2 (#4209 review): a production prompt
|
|
190
|
+
# that ingests untrusted third-party output should stay in-scope for this scanner,
|
|
191
|
+
# not be exempted wholesale; its defense-contract wording was reworded instead to
|
|
192
|
+
# avoid literally spelling out the trigger phrase (see git blame on that section).
|
|
193
|
+
# Same DEFECT.PROMPT-INJECTION-SCAN-COLLISION class as the entries above.
|
|
194
|
+
'tests/code-review-pipeline-regression.test.cjs'
|
|
195
|
+
# #4209 agy-F1 regression test — a crafted-filename fixture containing the literal
|
|
196
|
+
# phrase "Ignore all prior instructions." to prove validatePaths rejects it before
|
|
197
|
+
# it ever reaches an external-reviewer prompt. Discusses/detects the attack pattern
|
|
198
|
+
# as test data, never performs it. Same class as the entries above.
|
|
199
|
+
'tests/reviewer-step-dispatch.test.cjs'
|
|
182
200
|
)
|
|
183
201
|
|
|
184
202
|
is_allowlisted() {
|