@opengsd/gsd-core 1.14.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +85 -5
- package/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-code-fixer.compact.md +7 -6
- package/agents/gsd-code-fixer.md +9 -8
- package/agents/gsd-code-reviewer.compact.md +5 -3
- package/agents/gsd-code-reviewer.md +8 -6
- package/agents/gsd-debug-session-manager.compact.md +17 -2
- package/agents/gsd-debug-session-manager.md +17 -2
- package/agents/gsd-debugger.md +3 -3
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +17 -12
- package/agents/gsd-intel-updater.compact.md +1 -1
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +2 -2
- package/agents/gsd-phase-researcher.md +19 -11
- package/agents/gsd-plan-checker.md +15 -9
- package/agents/gsd-planner.md +15 -11
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +1 -1
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-ui-auditor.compact.md +21 -30
- package/agents/gsd-ui-auditor.md +166 -37
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +37 -14
- package/bin/install.js +764 -287
- package/commands/gsd/add-tests.md +6 -1
- package/commands/gsd/ai-integration-phase.md +6 -1
- package/commands/gsd/audit-fix.md +5 -0
- package/commands/gsd/audit-milestone.md +6 -1
- package/commands/gsd/autonomous.md +7 -2
- package/commands/gsd/capture.md +9 -5
- package/commands/gsd/code-review.md +7 -2
- package/commands/gsd/complete-milestone.md +4 -0
- package/commands/gsd/config.md +7 -3
- package/commands/gsd/debug.md +11 -7
- package/commands/gsd/discuss-phase.md +7 -3
- package/commands/gsd/docs-update.md +12 -7
- package/commands/gsd/eval-review.md +6 -1
- package/commands/gsd/execute-phase.md +12 -7
- package/commands/gsd/extract-learnings.md +5 -0
- package/commands/gsd/fast.md +4 -0
- package/commands/gsd/forensics.md +5 -1
- package/commands/gsd/graphify.md +10 -6
- package/commands/gsd/health.md +5 -0
- package/commands/gsd/help.md +7 -2
- package/commands/gsd/import.md +7 -3
- package/commands/gsd/inbox.md +5 -0
- package/commands/gsd/ingest-docs.md +5 -1
- package/commands/gsd/manager.md +6 -1
- package/commands/gsd/map-codebase.md +7 -3
- package/commands/gsd/mempalace-capture.md +12 -4
- package/commands/gsd/mempalace-recall.md +5 -1
- package/commands/gsd/milestone-summary.md +5 -1
- package/commands/gsd/mvp-phase.md +8 -3
- package/commands/gsd/new-milestone.md +6 -1
- package/commands/gsd/new-project.md +5 -0
- package/commands/gsd/next.md +6 -1
- package/commands/gsd/ns-context.md +4 -0
- package/commands/gsd/ns-ideate.md +4 -0
- package/commands/gsd/ns-manage.md +4 -0
- package/commands/gsd/ns-project.md +4 -0
- package/commands/gsd/ns-review.md +4 -0
- package/commands/gsd/ns-workflow.md +4 -0
- package/commands/gsd/onboard.md +6 -1
- package/commands/gsd/pause-work.md +5 -1
- package/commands/gsd/phase.md +8 -4
- package/commands/gsd/plan-phase.md +6 -1
- package/commands/gsd/plan-review-convergence.md +11 -7
- package/commands/gsd/pr-branch.md +4 -0
- package/commands/gsd/profile-user.md +5 -1
- package/commands/gsd/progress.md +7 -2
- package/commands/gsd/quick-batch.md +21 -9
- package/commands/gsd/quick.md +12 -7
- package/commands/gsd/review.md +7 -4
- package/commands/gsd/secure-phase.md +6 -1
- package/commands/gsd/ship.md +5 -0
- package/commands/gsd/sketch.md +7 -2
- package/commands/gsd/spec-phase.md +5 -1
- package/commands/gsd/spike.md +8 -3
- package/commands/gsd/surface.md +5 -1
- package/commands/gsd/thread.md +4 -0
- package/commands/gsd/ui-phase.md +6 -1
- package/commands/gsd/ui-review.md +6 -1
- package/commands/gsd/ultraplan-phase.md +5 -1
- package/commands/gsd/undo.md +5 -1
- package/commands/gsd/update.md +6 -2
- package/commands/gsd/validate-phase.md +6 -1
- package/commands/gsd/verify-work.md +6 -1
- package/commands/gsd/workspace.md +7 -3
- package/gsd-core/bin/gsd-tools.cjs +477 -78
- package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
- package/gsd-core/bin/lib/adr-parser.cjs +3 -1
- package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
- package/gsd-core/bin/lib/audit.cjs +144 -42
- package/gsd-core/bin/lib/broken-windows.cjs +13 -13
- package/gsd-core/bin/lib/capability-activation.cjs +9 -4
- package/gsd-core/bin/lib/capability-registry.cjs +197 -222
- package/gsd-core/bin/lib/capability-validator.cjs +16 -1
- package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
- package/gsd-core/bin/lib/check-command-router.cjs +164 -1625
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
- package/gsd-core/bin/lib/cli-exit.cjs +12 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +32 -33
- package/gsd-core/bin/lib/command-aliases.cjs +7 -0
- package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
- package/gsd-core/bin/lib/commands.cjs +343 -207
- package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
- package/gsd-core/bin/lib/config-loader.cjs +65 -4
- package/gsd-core/bin/lib/config.cjs +76 -19
- package/gsd-core/bin/lib/core-utils.cjs +6 -1
- package/gsd-core/bin/lib/coverage.cjs +4 -8
- package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
- package/gsd-core/bin/lib/decisions.cjs +30 -14
- package/gsd-core/bin/lib/drift.cjs +177 -42
- package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
- package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
- package/gsd-core/bin/lib/frontmatter.cjs +426 -234
- package/gsd-core/bin/lib/gap-checker.cjs +72 -29
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
- package/gsd-core/bin/lib/gate-args.cjs +53 -0
- package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
- package/gsd-core/bin/lib/gate-config.cjs +46 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
- package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
- package/gsd-core/bin/lib/gate-exit.cjs +27 -0
- package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
- package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
- package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
- package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
- package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
- package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
- package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
- package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
- package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
- package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
- package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
- package/gsd-core/bin/lib/graphify.cjs +10 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
- package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
- package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
- package/gsd-core/bin/lib/init.cjs +364 -132
- package/gsd-core/bin/lib/install-engine.cjs +30 -33
- package/gsd-core/bin/lib/install-profiles.cjs +7 -4
- package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
- package/gsd-core/bin/lib/io.cjs +122 -3
- package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
- package/gsd-core/bin/lib/milestone.cjs +37 -6
- package/gsd-core/bin/lib/model-resolver.cjs +171 -62
- package/gsd-core/bin/lib/observability/event.cjs +1 -1
- package/gsd-core/bin/lib/observability/logger.cjs +46 -1
- package/gsd-core/bin/lib/pattern.cjs +10 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +20 -5
- package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
- 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 +110 -8
- package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
- package/gsd-core/bin/lib/phase-locator.cjs +29 -10
- package/gsd-core/bin/lib/phase-status.cjs +360 -0
- package/gsd-core/bin/lib/phase.cjs +489 -88
- package/gsd-core/bin/lib/plan-document.cjs +142 -20
- package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
- package/gsd-core/bin/lib/planning-document.cjs +692 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +60 -9
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +83 -55
- package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
- package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
- package/gsd-core/bin/lib/probe-core.cjs +7 -1
- package/gsd-core/bin/lib/profile-output.cjs +6 -3
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
- package/gsd-core/bin/lib/project-root.cjs +41 -2
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
- package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
- package/gsd-core/bin/lib/report-parser.cjs +269 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
- package/gsd-core/bin/lib/roadmap-command-router.cjs +25 -19
- package/gsd-core/bin/lib/roadmap-parser.cjs +242 -15
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +1653 -65
- package/gsd-core/bin/lib/roadmap.cjs +405 -88
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +373 -187
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +5 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +14 -7
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +522 -624
- package/gsd-core/bin/lib/runtime-name-policy.cjs +246 -21
- package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +47 -8
- package/gsd-core/bin/lib/smart-entry.cjs +19 -3
- package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
- package/gsd-core/bin/lib/state-contract.cjs +15 -18
- package/gsd-core/bin/lib/state-document.cjs +100 -22
- package/gsd-core/bin/lib/state-transition.cjs +39 -2
- package/gsd-core/bin/lib/state.cjs +256 -105
- package/gsd-core/bin/lib/surface.cjs +19 -2
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -79
- package/gsd-core/bin/lib/uat-predicate.cjs +359 -38
- package/gsd-core/bin/lib/uat.cjs +432 -7
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +167 -40
- package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
- package/gsd-core/bin/lib/vendor/README.md +31 -9
- package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
- package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +1378 -274
- package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
- package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
- package/gsd-core/bin/lib/verify.cjs +357 -531
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
- package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
- package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
- package/gsd-core/bin/lib/workstream.cjs +11 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
- package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
- package/gsd-core/references/autonomous-smart-discuss.md +2 -1
- package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
- package/gsd-core/references/checkpoints.md +5 -3
- 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-mvp-tdd.md +5 -10
- package/gsd-core/references/execute-phase-between-wave-reset.md +10 -6
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- 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 +7 -1
- package/gsd-core/references/model-profiles.md +1 -1
- package/gsd-core/references/offer-next.md +1 -1
- 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 +12 -3
- package/gsd-core/references/spidr-splitting.md +1 -1
- package/gsd-core/references/tdd.md +37 -8
- package/gsd-core/references/ui-consideration-probe.md +10 -5
- package/gsd-core/references/verifier-phase-gates.md +5 -2
- package/gsd-core/references/verify-command-path-resolvability.md +10 -2
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -3
- package/gsd-core/references/worktree-path-safety.md +321 -0
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/UAT.md +17 -1
- package/gsd-core/templates/config.json +2 -11
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +8 -7
- package/gsd-core/workflows/add-tests.md +4 -3
- package/gsd-core/workflows/add-todo.md +6 -5
- package/gsd-core/workflows/ai-integration-phase.md +13 -4
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +4 -3
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
- package/gsd-core/workflows/autonomous.md +43 -23
- package/gsd-core/workflows/check-todos.md +7 -6
- package/gsd-core/workflows/cleanup.md +2 -2
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
- package/gsd-core/workflows/code-review-fix.md +112 -25
- package/gsd-core/workflows/code-review.md +146 -135
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
- package/gsd-core/workflows/complete-milestone.md +13 -8
- package/gsd-core/workflows/debug.md +32 -7
- package/gsd-core/workflows/diagnose-issues.md +3 -2
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +4 -3
- package/gsd-core/workflows/do.md +2 -2
- package/gsd-core/workflows/docs-update.md +6 -5
- package/gsd-core/workflows/edit-phase.md +4 -3
- package/gsd-core/workflows/eval-review.md +14 -5
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1019 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +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/regression-gate.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
- package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
- package/gsd-core/workflows/execute-phase.md +96 -178
- package/gsd-core/workflows/execute-plan.md +18 -23
- package/gsd-core/workflows/explore.md +4 -4
- package/gsd-core/workflows/extract-learnings.md +4 -2
- package/gsd-core/workflows/fast.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +3 -2
- package/gsd-core/workflows/help/modes/full.compact.md +3 -3
- package/gsd-core/workflows/help/modes/full.md +5 -5
- package/gsd-core/workflows/help/modes/topic.md +15 -5
- package/gsd-core/workflows/import.md +4 -3
- package/gsd-core/workflows/inbox.md +2 -2
- package/gsd-core/workflows/ingest-docs.md +3 -3
- package/gsd-core/workflows/insert-phase.md +4 -3
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +6 -4
- package/gsd-core/workflows/map-codebase.md +5 -4
- package/gsd-core/workflows/milestone-summary.md +3 -2
- package/gsd-core/workflows/mvp-phase.md +14 -14
- package/gsd-core/workflows/new-milestone.md +11 -11
- 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 +7 -7
- 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 +2 -2
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
- package/gsd-core/workflows/plan-phase.md +50 -24
- 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 +113 -13
- package/gsd-core/workflows/profile-user.md +2 -2
- package/gsd-core/workflows/progress.md +19 -49
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +27 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +15 -10
- package/gsd-core/workflows/quick.md +62 -39
- package/gsd-core/workflows/reapply-patches.md +9 -3
- package/gsd-core/workflows/remove-phase.md +3 -2
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +3 -2
- package/gsd-core/workflows/review.md +33 -17
- package/gsd-core/workflows/scan.md +3 -2
- package/gsd-core/workflows/secure-phase.md +13 -13
- package/gsd-core/workflows/settings-advanced.md +30 -10
- package/gsd-core/workflows/settings-integrations.md +2 -3
- package/gsd-core/workflows/settings.md +4 -4
- package/gsd-core/workflows/ship.md +14 -13
- 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 +2 -2
- package/gsd-core/workflows/transition.md +13 -23
- package/gsd-core/workflows/ui-phase.md +48 -11
- package/gsd-core/workflows/ui-review.md +21 -6
- package/gsd-core/workflows/ultraplan-phase.md +3 -2
- package/gsd-core/workflows/undo.md +339 -20
- package/gsd-core/workflows/update.md +7 -7
- package/gsd-core/workflows/validate-phase.md +12 -13
- package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
- package/gsd-core/workflows/verify-work.md +129 -55
- package/hooks/dist/gsd-agent-isolation-guard.js +32 -0
- package/hooks/dist/gsd-check-update-worker.js +8 -0
- package/hooks/dist/gsd-check-update.js +8 -0
- package/hooks/dist/gsd-context-monitor.js +31 -8
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
- package/hooks/dist/gsd-secret-read-guard.js +161 -4
- package/hooks/dist/gsd-statusline.js +85 -20
- package/hooks/dist/gsd-update-banner.js +8 -0
- package/hooks/dist/gsd-validate-commit.sh +63 -4
- package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
- package/hooks/dist/gsd-workflow-guard.js +5 -4
- package/hooks/dist/gsd-worktree-path-guard.js +6 -2
- package/hooks/dist/lib/cli-exit.js +12 -0
- package/hooks/dist/lib/git-probe.js +17 -1
- package/hooks/dist/lib/isolation-sentinel.js +2 -2
- package/hooks/gsd-agent-isolation-guard.js +32 -0
- package/hooks/gsd-check-update-worker.js +8 -0
- package/hooks/gsd-check-update.js +8 -0
- package/hooks/gsd-context-monitor.js +31 -8
- package/hooks/gsd-cursor-subagent-start.js +8 -0
- package/hooks/gsd-secret-read-guard.js +161 -4
- package/hooks/gsd-statusline.js +85 -20
- package/hooks/gsd-update-banner.js +8 -0
- package/hooks/gsd-validate-commit.sh +63 -4
- package/hooks/gsd-windsurf-pre-write.js +11 -2
- package/hooks/gsd-workflow-guard.js +5 -4
- package/hooks/gsd-worktree-path-guard.js +6 -2
- package/hooks/hooks.json +5 -5
- package/hooks/lib/cli-exit.js +12 -0
- package/hooks/lib/git-probe.js +17 -1
- package/hooks/lib/isolation-sentinel.js +2 -2
- package/package.json +22 -4
- package/scripts/build-hooks.js +15 -6
- package/scripts/changeset/parse.cjs +52 -4
- package/scripts/check-contract-drift.cjs +127 -11
- package/scripts/ci-timeout-report.cjs +770 -4
- package/scripts/command-contract-helpers.cjs +15 -8
- package/scripts/docs-guard-registry.cjs +34 -0
- package/scripts/gen-features.cjs +13 -8
- package/scripts/gen-hooks-cli-exit.cjs +12 -28
- package/scripts/gen-loop-host-contract.cjs +79 -1
- package/scripts/gen-platform-conformance-tier.cjs +187 -1
- package/scripts/gen-plugin-skills.cjs +87 -1
- package/scripts/gen-research-agents.cjs +24 -31
- package/scripts/gen-scripts-cli-exit.cjs +30 -3
- package/scripts/gen-test-timings.cjs +32 -7
- package/scripts/lib/cli-exit.cjs +12 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +34 -2
- package/scripts/lib/ndjson-reporter.cjs +31 -5
- package/scripts/lib/platform-conformance-tier.generated.cjs +45 -5
- package/scripts/lib/registration-ledger-preload.cjs +155 -0
- package/scripts/lib/vendor-bundle.cjs +59 -0
- package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-completion-predicate-drift.cjs +18 -19
- package/scripts/lint-descriptions.cjs +7 -3
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +38 -1
- package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
- package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
- package/scripts/lint-phase-arg-assignment.cjs +257 -0
- package/scripts/lint-phase-enumeration-drift.cjs +12 -8
- package/scripts/lint-phase-id-drift.cjs +319 -5
- package/scripts/lint-planning-document-positive-control.cjs +329 -0
- package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
- package/scripts/lint-response-language-coverage.cjs +3 -0
- package/scripts/lint-retired-runtime-name.cjs +619 -0
- package/scripts/lint-skill-deps.cjs +7 -3
- package/scripts/lint-state-write-path-drift.cjs +93 -0
- package/scripts/lint-test-file-count.allowlist.json +38 -9
- package/scripts/lint-test-file-count.cjs +34 -1
- package/scripts/lint-vendored-deps.cjs +41 -5
- package/scripts/lint-workflow-shellcheck-baseline.json +25 -10
- package/scripts/mutation-matrix.cjs +50 -5
- package/scripts/prompt-injection-scan.sh +4 -0
- package/scripts/release-tarball-smoke.cjs +194 -1
- package/scripts/require-issue-link-policy.cjs +6 -2
- package/scripts/sync-runtime-launcher.cjs +184 -2
- package/scripts/verify-npm-publish.cjs +76 -20
- package/skills/gsd-add-tests/SKILL.md +6 -1
- package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
- package/skills/gsd-audit-fix/SKILL.md +5 -0
- package/skills/gsd-audit-milestone/SKILL.md +6 -1
- package/skills/gsd-autonomous/SKILL.md +7 -2
- package/skills/gsd-capture/SKILL.md +9 -5
- package/skills/gsd-code-review/SKILL.md +7 -2
- package/skills/gsd-complete-milestone/SKILL.md +4 -0
- package/skills/gsd-config/SKILL.md +8 -4
- package/skills/gsd-debug/SKILL.md +11 -7
- package/skills/gsd-discuss-phase/SKILL.md +7 -3
- package/skills/gsd-docs-update/SKILL.md +12 -7
- package/skills/gsd-eval-review/SKILL.md +6 -1
- package/skills/gsd-execute-phase/SKILL.md +12 -7
- package/skills/gsd-extract-learnings/SKILL.md +5 -0
- package/skills/gsd-fast/SKILL.md +4 -0
- package/skills/gsd-forensics/SKILL.md +5 -1
- package/skills/gsd-graphify/SKILL.md +10 -6
- package/skills/gsd-health/SKILL.md +5 -0
- package/skills/gsd-help/SKILL.md +7 -2
- package/skills/gsd-import/SKILL.md +7 -3
- package/skills/gsd-inbox/SKILL.md +5 -0
- package/skills/gsd-ingest-docs/SKILL.md +5 -1
- package/skills/gsd-manager/SKILL.md +6 -1
- package/skills/gsd-map-codebase/SKILL.md +7 -3
- package/skills/gsd-mempalace-capture/SKILL.md +12 -4
- package/skills/gsd-mempalace-recall/SKILL.md +5 -1
- package/skills/gsd-milestone-summary/SKILL.md +5 -1
- package/skills/gsd-mvp-phase/SKILL.md +8 -3
- package/skills/gsd-new-milestone/SKILL.md +6 -1
- package/skills/gsd-new-project/SKILL.md +5 -0
- package/skills/gsd-next/SKILL.md +6 -1
- package/skills/gsd-ns-context/SKILL.md +4 -0
- package/skills/gsd-ns-ideate/SKILL.md +4 -0
- package/skills/gsd-ns-manage/SKILL.md +4 -0
- package/skills/gsd-ns-project/SKILL.md +4 -0
- package/skills/gsd-ns-review/SKILL.md +4 -0
- package/skills/gsd-ns-workflow/SKILL.md +4 -0
- package/skills/gsd-onboard/SKILL.md +6 -1
- package/skills/gsd-pause-work/SKILL.md +5 -1
- package/skills/gsd-phase/SKILL.md +8 -4
- package/skills/gsd-plan-phase/SKILL.md +6 -1
- package/skills/gsd-plan-review-convergence/SKILL.md +10 -6
- package/skills/gsd-pr-branch/SKILL.md +4 -0
- package/skills/gsd-profile-user/SKILL.md +5 -1
- package/skills/gsd-progress/SKILL.md +7 -2
- package/skills/gsd-quick/SKILL.md +16 -10
- package/skills/gsd-quick-batch/SKILL.md +21 -9
- package/skills/gsd-review/SKILL.md +7 -4
- package/skills/gsd-review-backlog/SKILL.md +3 -2
- package/skills/gsd-secure-phase/SKILL.md +6 -1
- package/skills/gsd-ship/SKILL.md +5 -0
- package/skills/gsd-sketch/SKILL.md +7 -2
- package/skills/gsd-spec-phase/SKILL.md +5 -1
- package/skills/gsd-spike/SKILL.md +8 -3
- package/skills/gsd-surface/SKILL.md +5 -1
- package/skills/gsd-thread/SKILL.md +4 -0
- package/skills/gsd-ui-phase/SKILL.md +6 -1
- package/skills/gsd-ui-review/SKILL.md +6 -1
- package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
- package/skills/gsd-undo/SKILL.md +5 -1
- package/skills/gsd-update/SKILL.md +6 -2
- package/skills/gsd-validate-phase/SKILL.md +6 -1
- package/skills/gsd-verify-work/SKILL.md +6 -1
- package/skills/gsd-workspace/SKILL.md +7 -3
- package/skills/gsd-workstreams/SKILL.md +6 -6
- package/vscode/package.json +1 -1
|
@@ -4,17 +4,31 @@
|
|
|
4
4
|
* Detects structural drift between a committed codebase and the
|
|
5
5
|
* `.planning/codebase/STRUCTURE.md` map produced by `gsd-codebase-mapper`.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Six categories of drift element:
|
|
8
8
|
* - new_dir → a newly-added file whose directory prefix does not appear
|
|
9
|
-
* in
|
|
9
|
+
* in any generated document
|
|
10
10
|
* - barrel → a newly-added barrel export at
|
|
11
11
|
* (packages|apps)/<name>/src/index.(ts|tsx|js|mjs|cjs)
|
|
12
12
|
* - migration → a newly-added migration file under one of the recognized
|
|
13
13
|
* migration directories (supabase, prisma, drizzle, src/migrations, …)
|
|
14
14
|
* - route → a newly-added route module under a `routes/` or `api/` dir
|
|
15
|
+
* - modified → a modified file whose directory prefix IS mapped
|
|
16
|
+
* - deleted → a deleted file whose directory prefix IS mapped
|
|
17
|
+
*
|
|
18
|
+
* Inverse-territory rule (#4886, #5134): an addition is drift OUTSIDE mapped
|
|
19
|
+
* territory (the map cannot describe what did not exist); a modification or
|
|
20
|
+
* deletion is drift INSIDE mapped territory (the map describes it and it
|
|
21
|
+
* changed). A rename is a deletion of the old path plus an addition of the new
|
|
22
|
+
* path; a copy is an addition of the new path. Mapped territory is any
|
|
23
|
+
* directory prefix named in ANY provided generated document.
|
|
15
24
|
*
|
|
16
25
|
* Each file is counted at most once; when a file matches multiple categories
|
|
17
|
-
* the most specific category wins
|
|
26
|
+
* the most specific category wins
|
|
27
|
+
* (deleted > modified > migration > route > barrel > new_dir).
|
|
28
|
+
*
|
|
29
|
+
* Every path that leaves this module (`affectedPaths`, the `--paths` argument,
|
|
30
|
+
* message bullets) passes `sanitizePaths` (#4923); dropped paths are reported
|
|
31
|
+
* as data in `withheldPaths`, never interpolated into the message.
|
|
18
32
|
*
|
|
19
33
|
* Design decisions (see PR for full rubber-duck):
|
|
20
34
|
* - The library is pure. It takes parsed git diff output and returns a
|
|
@@ -38,11 +52,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
52
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
39
53
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
40
54
|
const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
|
|
55
|
+
const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
|
|
41
56
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
42
|
-
const DRIFT_CATEGORIES = Object.freeze(['new_dir', 'barrel', 'migration', 'route']);
|
|
57
|
+
const DRIFT_CATEGORIES = Object.freeze(['new_dir', 'barrel', 'migration', 'route', 'modified', 'deleted']);
|
|
43
58
|
// Category priority when a single file matches multiple rules.
|
|
44
59
|
// Higher index = more specific = wins.
|
|
45
|
-
const CATEGORY_PRIORITY = {
|
|
60
|
+
const CATEGORY_PRIORITY = {
|
|
61
|
+
new_dir: 0, barrel: 1, route: 2, migration: 3, modified: 4, deleted: 5,
|
|
62
|
+
};
|
|
46
63
|
const BARREL_RE = /^(packages|apps)\/[^/]+\/src\/index\.(ts|tsx|js|mjs|cjs)$/;
|
|
47
64
|
const MIGRATION_RES = [
|
|
48
65
|
/^supabase\/migrations\/.+\.sql$/,
|
|
@@ -78,30 +95,99 @@ function classifyFile(file) {
|
|
|
78
95
|
return 'barrel';
|
|
79
96
|
return null;
|
|
80
97
|
}
|
|
98
|
+
// Characters that continue a path component: a prefix occurrence directly
|
|
99
|
+
// preceded by one of `BEFORE_CONT` or followed by one of `AFTER_CONT` is a
|
|
100
|
+
// fragment of a longer word or name, not the prefix itself.
|
|
101
|
+
const BEFORE_CONT_RE = /[A-Za-z0-9_.-]/;
|
|
102
|
+
const AFTER_CONT_RE = /[A-Za-z0-9_-]/;
|
|
81
103
|
/**
|
|
82
|
-
* True iff
|
|
83
|
-
*
|
|
104
|
+
* True iff `needle` occurs in `corpus` at path-component boundaries: the
|
|
105
|
+
* character before it (or the start) is not a path-component character, and
|
|
106
|
+
* the character after it (or the end) is not one either. `.` may follow (a
|
|
107
|
+
* sentence end) but may not precede (`x.src`). Linear scan, no regex built
|
|
108
|
+
* from `needle`.
|
|
109
|
+
*/
|
|
110
|
+
function occursAtBoundary(corpus, needle) {
|
|
111
|
+
if (!needle)
|
|
112
|
+
return false;
|
|
113
|
+
let from = 0;
|
|
114
|
+
for (;;) {
|
|
115
|
+
const at = corpus.indexOf(needle, from);
|
|
116
|
+
if (at === -1)
|
|
117
|
+
return false;
|
|
118
|
+
const end = at + needle.length;
|
|
119
|
+
const beforeOk = at === 0 || !BEFORE_CONT_RE.test(corpus[at - 1]);
|
|
120
|
+
const afterOk = end >= corpus.length || !AFTER_CONT_RE.test(corpus[end]);
|
|
121
|
+
if (beforeOk && afterOk)
|
|
122
|
+
return true;
|
|
123
|
+
from = at + 1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* True iff any prefix of `file` (dir1, dir1/dir2, …) appears in `corpus` (the
|
|
128
|
+
* provided generated documents joined) at path-component boundaries. Used to
|
|
129
|
+
* decide whether a file is in "mapped territory".
|
|
84
130
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
131
|
+
* The documents are free-form markdown, not a structured manifest, so the
|
|
132
|
+
* match is textual — but it is component-aware: `src/lib/` and `` `src/lib` ``
|
|
133
|
+
* map `src/lib`; the word `library` does not map `lib` and `capital` does not
|
|
134
|
+
* map `api`. The `name/` and `` `name` `` forms of the top-level directory
|
|
135
|
+
* fall out of the same boundary rule.
|
|
88
136
|
*/
|
|
89
|
-
function isPathMapped(file,
|
|
137
|
+
function isPathMapped(file, corpus) {
|
|
90
138
|
const norm = (0, shell_command_projection_cjs_1.posixNormalize)(file);
|
|
91
139
|
const parts = norm.split('/');
|
|
92
|
-
//
|
|
140
|
+
// A path with an empty component (`/x`, `a//b`) has no mappable prefix at
|
|
141
|
+
// that depth; never search for the empty string.
|
|
93
142
|
for (let i = parts.length - 1; i >= 1; i--) {
|
|
94
|
-
const
|
|
95
|
-
if (
|
|
143
|
+
const prefixParts = parts.slice(0, i);
|
|
144
|
+
if (prefixParts.some((part) => part === ''))
|
|
145
|
+
continue;
|
|
146
|
+
if (occursAtBoundary(corpus, prefixParts.join('/')))
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
// A single-component path (a root-level file) has no directory prefix; the
|
|
150
|
+
// documented forms name the component itself as a directory.
|
|
151
|
+
if (parts.length === 1 && parts[0] !== '') {
|
|
152
|
+
if (occursAtBoundary(corpus, parts[0] + '/'))
|
|
153
|
+
return true;
|
|
154
|
+
if (corpus.includes('`' + parts[0] + '`'))
|
|
96
155
|
return true;
|
|
97
156
|
}
|
|
98
|
-
// Finally, if even the top-level dir is mentioned, count as mapped.
|
|
99
|
-
if (parts.length > 0 && structureMd.includes(parts[0] + '/'))
|
|
100
|
-
return true;
|
|
101
|
-
if (parts.length > 0 && structureMd.includes('`' + parts[0] + '`'))
|
|
102
|
-
return true;
|
|
103
157
|
return false;
|
|
104
158
|
}
|
|
159
|
+
// Characters that would let a path rewrite a terminal or the reader's view of
|
|
160
|
+
// it: C0 controls, DEL, C1 controls, bidi controls, zero-width characters and
|
|
161
|
+
// the line/paragraph separators.
|
|
162
|
+
const DISPLAY_UNSAFE_RE = /[\u0000-\u001f\u007f-\u009f\u061c\u200b-\u200f\u2028\u2029\u202a-\u202e\u2060\u2066-\u2069\ufeff]/;
|
|
163
|
+
const DISPLAY_MAX_UNITS = 200;
|
|
164
|
+
/**
|
|
165
|
+
* Render an attacker-controlled path for a display surface. Display-unsafe
|
|
166
|
+
* characters become `\uXXXX` (lowercase hex); every other character —
|
|
167
|
+
* including ordinary non-ASCII — is left alone. A result longer than 200
|
|
168
|
+
* UTF-16 code units is cut on a code-point (and escape) boundary so that the
|
|
169
|
+
* result, with its trailing `…`, is exactly 200 code units or fewer.
|
|
170
|
+
*/
|
|
171
|
+
function displaySafePath(p) {
|
|
172
|
+
const pieces = [];
|
|
173
|
+
let total = 0;
|
|
174
|
+
for (const ch of String(p)) {
|
|
175
|
+
const piece = DISPLAY_UNSAFE_RE.test(ch)
|
|
176
|
+
? '\\u' + ch.codePointAt(0).toString(16).padStart(4, '0')
|
|
177
|
+
: ch;
|
|
178
|
+
pieces.push(piece);
|
|
179
|
+
total += piece.length;
|
|
180
|
+
}
|
|
181
|
+
if (total <= DISPLAY_MAX_UNITS)
|
|
182
|
+
return pieces.join('');
|
|
183
|
+
let out = '';
|
|
184
|
+
for (const piece of pieces) {
|
|
185
|
+
if (out.length + piece.length > DISPLAY_MAX_UNITS - 1)
|
|
186
|
+
break;
|
|
187
|
+
out += piece;
|
|
188
|
+
}
|
|
189
|
+
return out + '…';
|
|
190
|
+
}
|
|
105
191
|
// ─── Main detection ──────────────────────────────────────────────────────────
|
|
106
192
|
/**
|
|
107
193
|
* Detect codebase drift.
|
|
@@ -112,40 +198,62 @@ function detectDrift(input) {
|
|
|
112
198
|
return skipped('invalid-input');
|
|
113
199
|
}
|
|
114
200
|
const inp = input;
|
|
115
|
-
const { addedFiles, modifiedFiles, deletedFiles,
|
|
201
|
+
const { addedFiles, modifiedFiles, deletedFiles, documents, } = inp;
|
|
116
202
|
const threshold = Number.isInteger(inp.threshold) && inp.threshold >= 1
|
|
117
203
|
? inp.threshold
|
|
118
204
|
: 3;
|
|
119
205
|
const action = inp.action === 'auto-remap' ? 'auto-remap' : 'warn';
|
|
206
|
+
// STRUCTURE.md is the one required document; the other six only widen the
|
|
207
|
+
// mapped territory and are ignored when absent or not text.
|
|
208
|
+
const docs = documents !== null && typeof documents === 'object'
|
|
209
|
+
? documents
|
|
210
|
+
: {};
|
|
211
|
+
const structureMd = docs['STRUCTURE.md'];
|
|
120
212
|
if (structureMd === null || structureMd === undefined) {
|
|
121
213
|
return skipped('missing-structure-md');
|
|
122
214
|
}
|
|
123
215
|
if (typeof structureMd !== 'string') {
|
|
124
216
|
return skipped('invalid-structure-md');
|
|
125
217
|
}
|
|
218
|
+
const corpus = Object.values(docs)
|
|
219
|
+
.filter((doc) => typeof doc === 'string')
|
|
220
|
+
.join('\n');
|
|
126
221
|
const added = Array.isArray(addedFiles) ? addedFiles.filter((x) => typeof x === 'string') : [];
|
|
127
222
|
const modified = Array.isArray(modifiedFiles) ? modifiedFiles : [];
|
|
128
223
|
const deleted = Array.isArray(deletedFiles) ? deletedFiles : [];
|
|
129
224
|
// Build elements. One element per file, highest-priority category wins.
|
|
130
225
|
const elements = [];
|
|
131
226
|
const seen = new Map();
|
|
227
|
+
const count = (file, category) => {
|
|
228
|
+
// Dedup: if we've already counted this path at higher-or-equal priority, skip
|
|
229
|
+
const prior = seen.get(file);
|
|
230
|
+
if (prior && CATEGORY_PRIORITY[prior] >= CATEGORY_PRIORITY[category])
|
|
231
|
+
return;
|
|
232
|
+
seen.set(file, category);
|
|
233
|
+
};
|
|
132
234
|
for (const rawFile of added) {
|
|
133
235
|
const file = (0, shell_command_projection_cjs_1.posixNormalize)(rawFile);
|
|
134
236
|
const specific = classifyFile(file);
|
|
135
237
|
let category = specific;
|
|
136
238
|
if (!category) {
|
|
137
|
-
if (!isPathMapped(file,
|
|
239
|
+
if (!isPathMapped(file, corpus)) {
|
|
138
240
|
category = 'new_dir';
|
|
139
241
|
}
|
|
140
242
|
else {
|
|
141
243
|
continue; // mapped, known, ordinary file — not drift
|
|
142
244
|
}
|
|
143
245
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
246
|
+
count(file, category);
|
|
247
|
+
}
|
|
248
|
+
// Inverse territory: an edit is drift only where the map describes the file.
|
|
249
|
+
for (const [rawFiles, category] of [[modified, 'modified'], [deleted, 'deleted']]) {
|
|
250
|
+
for (const rawFile of rawFiles) {
|
|
251
|
+
if (typeof rawFile !== 'string')
|
|
252
|
+
continue;
|
|
253
|
+
const file = (0, shell_command_projection_cjs_1.posixNormalize)(rawFile);
|
|
254
|
+
if (file && isPathMapped(file, corpus))
|
|
255
|
+
count(file, category);
|
|
256
|
+
}
|
|
149
257
|
}
|
|
150
258
|
for (const [file, category] of seen.entries()) {
|
|
151
259
|
elements.push({ category, path: file });
|
|
@@ -158,14 +266,20 @@ function detectDrift(input) {
|
|
|
158
266
|
let directive = 'none';
|
|
159
267
|
let spawnMapper = false;
|
|
160
268
|
let affectedPaths = [];
|
|
269
|
+
let withheldPaths = [];
|
|
161
270
|
let message = '';
|
|
162
271
|
if (actionRequired) {
|
|
163
272
|
directive = action;
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
273
|
+
// The one egress seam (#4923): `affectedPaths` is the only path list
|
|
274
|
+
// that reaches the result, the auto-remap line and `--paths`.
|
|
275
|
+
const elementPaths = elements.map((e) => e.path);
|
|
276
|
+
const chosen = chooseAffectedPaths(elementPaths);
|
|
277
|
+
affectedPaths = sanitizePaths(chosen);
|
|
278
|
+
const kept = new Set([...sanitizePaths(elementPaths), ...affectedPaths]);
|
|
279
|
+
withheldPaths = [...new Set([...elementPaths, ...chosen].filter((p) => !kept.has(p)))].sort();
|
|
280
|
+
// An empty `--paths` would remap the whole repo (#3418).
|
|
281
|
+
spawnMapper = action === 'auto-remap' && affectedPaths.length > 0;
|
|
282
|
+
message = buildMessage(elements, affectedPaths, withheldPaths.length, action, inp.runtime);
|
|
169
283
|
}
|
|
170
284
|
return {
|
|
171
285
|
skipped: false,
|
|
@@ -174,6 +288,7 @@ function detectDrift(input) {
|
|
|
174
288
|
directive,
|
|
175
289
|
spawnMapper,
|
|
176
290
|
affectedPaths,
|
|
291
|
+
withheldPaths,
|
|
177
292
|
threshold,
|
|
178
293
|
action,
|
|
179
294
|
message,
|
|
@@ -199,12 +314,16 @@ function skipped(reason) {
|
|
|
199
314
|
directive: 'none',
|
|
200
315
|
spawnMapper: false,
|
|
201
316
|
affectedPaths: [],
|
|
317
|
+
withheldPaths: [],
|
|
202
318
|
message: '',
|
|
203
319
|
};
|
|
204
320
|
}
|
|
205
|
-
function buildMessage(elements, affectedPaths, action, runtime) {
|
|
321
|
+
function buildMessage(elements, affectedPaths, withheldCount, action, runtime) {
|
|
206
322
|
const byCat = {};
|
|
323
|
+
const listable = new Set(sanitizePaths(elements.map((e) => e.path)));
|
|
207
324
|
for (const e of elements) {
|
|
325
|
+
if (!listable.has(e.path))
|
|
326
|
+
continue;
|
|
208
327
|
if (!byCat[e.category])
|
|
209
328
|
byCat[e.category] = [];
|
|
210
329
|
byCat[e.category].push(e.path);
|
|
@@ -218,8 +337,10 @@ function buildMessage(elements, affectedPaths, action, runtime) {
|
|
|
218
337
|
barrel: 'New barrel exports',
|
|
219
338
|
migration: 'New migrations',
|
|
220
339
|
route: 'New route modules',
|
|
340
|
+
modified: 'Modified files in mapped directories',
|
|
341
|
+
deleted: 'Deleted files in mapped directories',
|
|
221
342
|
};
|
|
222
|
-
for (const cat of
|
|
343
|
+
for (const cat of DRIFT_CATEGORIES) {
|
|
223
344
|
if (byCat[cat]) {
|
|
224
345
|
lines.push(`${labels[cat]}:`);
|
|
225
346
|
for (const p of byCat[cat])
|
|
@@ -227,12 +348,18 @@ function buildMessage(elements, affectedPaths, action, runtime) {
|
|
|
227
348
|
}
|
|
228
349
|
}
|
|
229
350
|
lines.push('');
|
|
230
|
-
|
|
351
|
+
// Dropped paths are counted, never named: the names are data in `withheldPaths`.
|
|
352
|
+
if (withheldCount > 0) {
|
|
353
|
+
lines.push(`${withheldCount} path(s) withheld: not passed to the mapper or listed (absolute, traversal, whitespace, non-ASCII or shell-metacharacter characters)`);
|
|
354
|
+
}
|
|
355
|
+
// Nothing safe to scope a refresh to (empty `affectedPaths`): an empty
|
|
356
|
+
// `--paths` would remap the whole repo (#3418), so no command line is emitted.
|
|
357
|
+
if (affectedPaths.length > 0 && action === 'auto-remap') {
|
|
231
358
|
lines.push(`Auto-remap scheduled for paths: ${affectedPaths.join(', ')}`);
|
|
232
359
|
}
|
|
233
|
-
else {
|
|
360
|
+
else if (affectedPaths.length > 0) {
|
|
234
361
|
// drift.cts is a pure library — it must never read env/config. The
|
|
235
|
-
// caller (
|
|
362
|
+
// caller (gate-codebase-drift.cts) resolves the runtime once and
|
|
236
363
|
// passes it in via input.runtime so emitted commands match the project
|
|
237
364
|
// the caller is targeting, not the current process directory.
|
|
238
365
|
const mapCmd = (0, runtime_slash_cjs_1.formatGsdSlash)('map-codebase', runtime || 'claude');
|
|
@@ -256,6 +383,8 @@ function chooseAffectedPaths(paths) {
|
|
|
256
383
|
if (parts.length === 0)
|
|
257
384
|
continue;
|
|
258
385
|
const top = parts[0];
|
|
386
|
+
if (!top)
|
|
387
|
+
continue; // an empty first component (`/x`) names no directory
|
|
259
388
|
if ((top === 'apps' || top === 'packages') && parts.length >= 2) {
|
|
260
389
|
out.add(`${top}/${parts[1]}`);
|
|
261
390
|
}
|
|
@@ -281,26 +410,31 @@ function sanitizePaths(paths) {
|
|
|
281
410
|
continue;
|
|
282
411
|
if (!SAFE_PATH_RE.test(p))
|
|
283
412
|
continue;
|
|
413
|
+
// A `.` component would make `--paths .` (the whole repo) producible (#3418).
|
|
414
|
+
if (p.split('/').some((component) => component === '.'))
|
|
415
|
+
continue;
|
|
284
416
|
out.push(p);
|
|
285
417
|
}
|
|
286
418
|
return out;
|
|
287
419
|
}
|
|
288
|
-
|
|
289
|
-
|
|
420
|
+
/**
|
|
421
|
+
* The block is the one the one fence owner finds (`locateFrontmatterFence`); `body` is
|
|
422
|
+
* everything after the closing fence line and its line ending.
|
|
423
|
+
*/
|
|
290
424
|
function parseFrontmatter(content) {
|
|
291
425
|
if (typeof content !== 'string')
|
|
292
426
|
return { data: {}, body: '' };
|
|
293
|
-
const
|
|
294
|
-
if (!
|
|
427
|
+
const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
|
|
428
|
+
if (!fence?.closed)
|
|
295
429
|
return { data: {}, body: content };
|
|
296
430
|
const data = {};
|
|
297
|
-
for (const line of
|
|
431
|
+
for (const line of content.slice(fence.openEnd, fence.bodyEnd).split(/\r?\n/)) {
|
|
298
432
|
const kv = line.match(/^([A-Za-z0-9_][A-Za-z0-9_-]*):\s*(.*)$/);
|
|
299
433
|
if (!kv)
|
|
300
434
|
continue;
|
|
301
435
|
data[kv[1]] = kv[2];
|
|
302
436
|
}
|
|
303
|
-
return { data, body: content.slice(
|
|
437
|
+
return { data, body: content.slice(fence.closingFenceEnd).replace(/^\r?\n/, '') };
|
|
304
438
|
}
|
|
305
439
|
function serializeFrontmatter(data, body) {
|
|
306
440
|
const keys = Object.keys(data);
|
|
@@ -357,6 +491,7 @@ module.exports = {
|
|
|
357
491
|
detectDrift,
|
|
358
492
|
chooseAffectedPaths,
|
|
359
493
|
sanitizePaths,
|
|
494
|
+
displaySafePath,
|
|
360
495
|
readMappedCommit,
|
|
361
496
|
writeMappedCommit,
|
|
362
497
|
// Exposed for the CLI layer to reuse the same parser.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* frontmatter-fence.cts — the one owner of "where does a document's frontmatter block start
|
|
4
|
+
* and stop" (ADR-5057 one-owner rule; found while implementing #5105).
|
|
5
|
+
*
|
|
6
|
+
* Source in src/frontmatter-fence.cts, compiled to gsd-core/bin/lib/frontmatter-fence.cjs
|
|
7
|
+
* (gitignored), per the repo's ADR-457 build-at-publish convention.
|
|
8
|
+
*
|
|
9
|
+
* Before this module the answer was re-derived some thirty times across `src/` — regexes such
|
|
10
|
+
* as `/^---\r?\n([\s\S]*?)\r?\n---/`, `indexOf('\n---', 4)` scans, `lines[0].trim() === '---'`
|
|
11
|
+
* checks — and the copies disagreed on a BOM, CRLF, an adjacent empty block, `----`, `--- x`,
|
|
12
|
+
* a `---` inside a value and leading whitespace. Every frontmatter reader and writer in `src/`
|
|
13
|
+
* (planning documents, agent/skill/command files, the installer's converters and injectors),
|
|
14
|
+
* in the runtime hooks, and in the two hand-written entry points that load `bin/lib`
|
|
15
|
+
* (`bin/install.js`, `gsd-core/bin/gsd-tools.cjs`) now reads the fence from
|
|
16
|
+
* `locateFrontmatterFence` — directly for offsets, or through `frontmatterRegion`/
|
|
17
|
+
* `frontmatterBlock`/`extractFrontmatter`/`stripFrontmatter` (`frontmatter.cts`) for content.
|
|
18
|
+
* `scripts/lint-frontmatter-fence-drift.cjs` (run by `lint:ci`) fails on a new hand-rolled
|
|
19
|
+
* fence in any of them.
|
|
20
|
+
*
|
|
21
|
+
* A "genuine leaf" module (CONTEXT.md's term): zero I/O, zero imports, so both
|
|
22
|
+
* `frontmatter.cts` and `shell-command-projection.cts` — which import each other's side of a
|
|
23
|
+
* cycle — can depend on it.
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.locateFrontmatterFence = locateFrontmatterFence;
|
|
27
|
+
/** A closing fence is a WHOLE line: three dashes, then only spaces or tabs. */
|
|
28
|
+
const CLOSING_FENCE_LINE = /^---[ \t]*$/;
|
|
29
|
+
/**
|
|
30
|
+
* The lenient closer: a WHOLE line of four or more dashes, then only spaces or tabs. It closes
|
|
31
|
+
* a block only when no exact closer follows the opening fence — the pre-existing lenient parse
|
|
32
|
+
* of a `----`-closed block (#1882, `tests/unusable-input.test.cjs`), kept so such a document
|
|
33
|
+
* still reads its keys instead of reading as unterminated.
|
|
34
|
+
*/
|
|
35
|
+
const LENIENT_CLOSING_FENCE_LINE = /^-{4,}[ \t]*$/;
|
|
36
|
+
function locateFrontmatterFence(text, options = {}) {
|
|
37
|
+
if (typeof text !== 'string') {
|
|
38
|
+
throw new TypeError(`locateFrontmatterFence: expected a string, got ${typeof text}`);
|
|
39
|
+
}
|
|
40
|
+
const bom = text.charCodeAt(0) === 0xfeff ? String.fromCharCode(0xfeff) : '';
|
|
41
|
+
const openingEolAt = (at) => {
|
|
42
|
+
if (text.startsWith('---\r\n', at))
|
|
43
|
+
return '\r\n';
|
|
44
|
+
if (text.startsWith('---\n', at))
|
|
45
|
+
return '\n';
|
|
46
|
+
return null;
|
|
47
|
+
};
|
|
48
|
+
let start = bom.length;
|
|
49
|
+
let found = openingEolAt(start);
|
|
50
|
+
if (found === null && options.allowPreamble === true) {
|
|
51
|
+
for (let newline = text.indexOf('\n', start); newline !== -1; newline = text.indexOf('\n', newline + 1)) {
|
|
52
|
+
found = openingEolAt(newline + 1);
|
|
53
|
+
if (found !== null) {
|
|
54
|
+
start = newline + 1;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (found === null)
|
|
60
|
+
return null;
|
|
61
|
+
const eol = found;
|
|
62
|
+
const openEnd = start + 3 + eol.length;
|
|
63
|
+
const closedAt = (lineStart, lineEnd) => {
|
|
64
|
+
let bodyEnd = openEnd;
|
|
65
|
+
if (lineStart > openEnd) {
|
|
66
|
+
// Back over the line ending that ends the last content line.
|
|
67
|
+
bodyEnd = lineStart - 1;
|
|
68
|
+
if (bodyEnd > openEnd && text[bodyEnd - 1] === '\r')
|
|
69
|
+
bodyEnd -= 1;
|
|
70
|
+
}
|
|
71
|
+
return { bom, eol, openEnd, closed: true, closingStart: lineStart, closingFenceEnd: lineEnd, bodyEnd };
|
|
72
|
+
};
|
|
73
|
+
let lenient = null;
|
|
74
|
+
let lineStart = openEnd;
|
|
75
|
+
while (lineStart <= text.length) {
|
|
76
|
+
const newline = text.indexOf('\n', lineStart);
|
|
77
|
+
const lineEnd = newline === -1 ? text.length : newline > lineStart && text[newline - 1] === '\r' ? newline - 1 : newline;
|
|
78
|
+
const line = text.slice(lineStart, lineEnd);
|
|
79
|
+
if (CLOSING_FENCE_LINE.test(line))
|
|
80
|
+
return closedAt(lineStart, lineEnd);
|
|
81
|
+
if (lenient === null && LENIENT_CLOSING_FENCE_LINE.test(line))
|
|
82
|
+
lenient = [lineStart, lineEnd];
|
|
83
|
+
if (newline === -1)
|
|
84
|
+
break;
|
|
85
|
+
lineStart = newline + 1;
|
|
86
|
+
}
|
|
87
|
+
if (lenient !== null)
|
|
88
|
+
return closedAt(lenient[0], lenient[1]);
|
|
89
|
+
return { bom, eol, openEnd, closed: false, closingStart: -1, closingFenceEnd: -1, bodyEnd: text.length };
|
|
90
|
+
}
|