@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
|
@@ -395,6 +395,14 @@ function parseCliWorkstream(args) {
|
|
|
395
395
|
args: args.slice(),
|
|
396
396
|
};
|
|
397
397
|
}
|
|
398
|
+
function workstreamDirectoryExists(cwd, name) {
|
|
399
|
+
try {
|
|
400
|
+
return node_fs_1.default.readdirSync(node_path_1.default.join(planningRoot(cwd), 'workstreams')).includes(name);
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
398
406
|
function resolveActiveWorkstream(cwd, args, env = process.env, deps = {}) {
|
|
399
407
|
const parsed = parseCliWorkstream(args);
|
|
400
408
|
const getStored = deps.getStored || ((dir) => getActiveWorkstream(dir, deps));
|
|
@@ -415,6 +423,13 @@ function resolveActiveWorkstream(cwd, args, env = process.env, deps = {}) {
|
|
|
415
423
|
if (ws && !validateWorkstreamName(ws)) {
|
|
416
424
|
throw new Error('Invalid workstream name: must be alphanumeric, hyphens, underscores, or dots');
|
|
417
425
|
}
|
|
426
|
+
// #4772: a reserved name (`none`) is rejected from every source (--ws, env,
|
|
427
|
+
// pointer) unless a directory of that name already exists (grandfathered).
|
|
428
|
+
// Grandfathering compares the directory listing exactly, so a case-insensitive
|
|
429
|
+
// filesystem (macOS, Windows) cannot let `NONE` through on the strength of `none`.
|
|
430
|
+
if (ws && (0, workstream_name_policy_cjs_1.isReservedWorkstreamName)(ws) && !workstreamDirectoryExists(cwd, ws)) {
|
|
431
|
+
throw new Error((0, workstream_name_policy_cjs_1.reservedWorkstreamNameMessage)(ws, source));
|
|
432
|
+
}
|
|
418
433
|
return {
|
|
419
434
|
ws,
|
|
420
435
|
source,
|
|
@@ -52,6 +52,7 @@ const CANONICAL_HEADERS = {
|
|
|
52
52
|
'recommendation',
|
|
53
53
|
'strategy',
|
|
54
54
|
'decision outcome',
|
|
55
|
+
'locked decisions',
|
|
55
56
|
],
|
|
56
57
|
considered_options: [
|
|
57
58
|
'considered options',
|
|
@@ -190,7 +191,8 @@ function normalizeAdrHeader(raw) {
|
|
|
190
191
|
.toLowerCase()
|
|
191
192
|
.replace(/[\s:._-]+/g, ' ')
|
|
192
193
|
.replace(/[^\w\s]/g, '')
|
|
193
|
-
.trim()
|
|
194
|
+
.trim()
|
|
195
|
+
.replace(/^\d+(?:\s+\d+)*\s+/, '');
|
|
194
196
|
}
|
|
195
197
|
// Normalized synonym index (audit M7). classifyHeader receives an ALREADY-normalized
|
|
196
198
|
// header (via normalizeAdrHeader), but historically compared it against the RAW synonym
|
|
@@ -483,7 +483,10 @@ function agentFileExists(agentsDir, name, runtime) {
|
|
|
483
483
|
// kimi requires BOTH the persona yaml and the prompt md (same as checkAgentsInstalled).
|
|
484
484
|
const kimiYaml = node_path_1.default.join(agentsDir, 'subagents', `${name}.yaml`);
|
|
485
485
|
const kimiPrompt = node_path_1.default.join(agentsDir, 'subagents', `${name}.md`);
|
|
486
|
-
|
|
486
|
+
// #5169: descriptor-declared (`hostBehaviors.requiresSubagentPair`); a label
|
|
487
|
+
// that is not a registered runtime declares nothing, so it never requires the pair.
|
|
488
|
+
return (0, runtime_name_policy_cjs_1.hostBehaviorsFor)(runtime).requiresSubagentPair === true
|
|
489
|
+
&& node_fs_1.default.existsSync(kimiYaml) && node_fs_1.default.existsSync(kimiPrompt);
|
|
487
490
|
}
|
|
488
491
|
/**
|
|
489
492
|
* Resolve a per-plan `agent_hint` specialist name to a dispatchable subagent
|
|
@@ -25,10 +25,15 @@ const coreUtils = require("./core-utils.cjs");
|
|
|
25
25
|
const { normalizeLineEndings } = coreUtils;
|
|
26
26
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
27
27
|
const planningWorkspace = require("./planning-workspace.cjs");
|
|
28
|
-
const { planningDir, quickDirFrom, todosDir } = planningWorkspace;
|
|
28
|
+
const { planningDir, quickDirFrom, debugDir, todosDir } = planningWorkspace;
|
|
29
29
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
30
30
|
const frontmatter = require("./frontmatter.cjs");
|
|
31
|
-
|
|
31
|
+
// #4378 (roll-in): scanSeeds publishes the SAME canonical seed identity the
|
|
32
|
+
// list-seeds gate derives — one grammar, two surfaces, no drift. commands.cjs
|
|
33
|
+
// does not require this module, so the edge is acyclic.
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
35
|
+
const commandsModule = require("./commands.cjs");
|
|
36
|
+
const { extractFrontmatter, frontmatterBlock, spliceFrontmatter, isFrontmatterWriteRefusal } = frontmatter;
|
|
32
37
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
33
38
|
const phaseIdMod = require("./phase-id.cjs");
|
|
34
39
|
const { PHASE_NUMBER_TOKEN_SOURCE, scopeToPhase } = phaseIdMod;
|
|
@@ -41,6 +46,11 @@ const shell_command_projection_cjs_2 = require("./shell-command-projection.cjs")
|
|
|
41
46
|
const io = require("./io.cjs");
|
|
42
47
|
const { output, error: ioError } = io;
|
|
43
48
|
const command_arg_projection_cjs_1 = require("./command-arg-projection.cjs");
|
|
49
|
+
// #5118: the verification-status owner's report reader and closed enum.
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
51
|
+
const verificationMod = require("./verification.cjs");
|
|
52
|
+
const { reportStatusOf, VERIFICATION_STATUS, VerificationStatusError } = verificationMod;
|
|
53
|
+
const clock_cjs_1 = require("./clock.cjs");
|
|
44
54
|
// The SCOPE BOUNDARY convention's filename (`agents/gsd-executor.md`), shared
|
|
45
55
|
// verbatim with the #2287 phase-boundary reader in `uat.cts`.
|
|
46
56
|
const DEFERRED_ITEMS_FILENAME = 'deferred-items.md';
|
|
@@ -252,19 +262,27 @@ function deriveOpenQuestionsDigest(questions) {
|
|
|
252
262
|
}
|
|
253
263
|
// ─── scanDebugSessions ────────────────────────────────────────────────────────
|
|
254
264
|
/**
|
|
255
|
-
*
|
|
265
|
+
* #4869: gsd-debugger's archive_session step appends every resolved session to
|
|
266
|
+
* this file in the debug directory. It is a document, not a session: it has no
|
|
267
|
+
* frontmatter, so its status would derive `unknown` and read as open forever.
|
|
268
|
+
* Excluded by this fixed name only. Any other file with missing or unparseable
|
|
269
|
+
* frontmatter is still an open session. Every shipped debug-directory reader
|
|
270
|
+
* excludes the same name from active sessions (#5011).
|
|
271
|
+
*/
|
|
272
|
+
const DEBUG_KNOWLEDGE_BASE_FILENAME = 'knowledge-base.md';
|
|
273
|
+
/**
|
|
274
|
+
* Scan the root-scoped .planning/debug/ directory supplied by the caller for open sessions.
|
|
256
275
|
* Open = status NOT in ['resolved', 'complete'].
|
|
257
|
-
* Ignores the resolved/ subdirectory.
|
|
276
|
+
* Ignores the resolved/ subdirectory and the debugger's knowledge base.
|
|
258
277
|
*/
|
|
259
|
-
function scanDebugSessions(
|
|
260
|
-
|
|
261
|
-
if (!node_fs_1.default.existsSync(debugDir))
|
|
278
|
+
function scanDebugSessions(debugPath) {
|
|
279
|
+
if (!node_fs_1.default.existsSync(debugPath))
|
|
262
280
|
return { items: [], acknowledged: 0 };
|
|
263
281
|
const results = [];
|
|
264
282
|
let acknowledged = 0;
|
|
265
283
|
let files;
|
|
266
284
|
try {
|
|
267
|
-
files = node_fs_1.default.readdirSync(
|
|
285
|
+
files = node_fs_1.default.readdirSync(debugPath, { withFileTypes: true });
|
|
268
286
|
}
|
|
269
287
|
catch {
|
|
270
288
|
return { items: [{ scan_error: true, slug: '', status: '', updated: '', hypothesis: '' }], acknowledged: 0 };
|
|
@@ -274,10 +292,12 @@ function scanDebugSessions(planDir) {
|
|
|
274
292
|
continue;
|
|
275
293
|
if (!entry.name.endsWith('.md'))
|
|
276
294
|
continue;
|
|
277
|
-
|
|
295
|
+
if (entry.name === DEBUG_KNOWLEDGE_BASE_FILENAME)
|
|
296
|
+
continue;
|
|
297
|
+
const filePath = node_path_1.default.join(debugPath, entry.name);
|
|
278
298
|
let safeFilePath;
|
|
279
299
|
try {
|
|
280
|
-
safeFilePath = (0, security_cjs_1.requireSafePath)(filePath,
|
|
300
|
+
safeFilePath = (0, security_cjs_1.requireSafePath)(filePath, node_path_1.default.dirname(debugPath), 'debug session file', security_cjs_1.PathAcceptance.AbsoluteInsideRoot);
|
|
281
301
|
}
|
|
282
302
|
catch {
|
|
283
303
|
continue;
|
|
@@ -286,9 +306,9 @@ function scanDebugSessions(planDir) {
|
|
|
286
306
|
// document at this read boundary, same seam as `src/uat.cts`'s
|
|
287
307
|
// `readNormalizedDocument` — `platformReadSync` performs no line-ending
|
|
288
308
|
// normalization itself, and extractFrontmatter/status-derivation below
|
|
289
|
-
// degrade a lone-CR file's frontmatter to `unknown`, which
|
|
290
|
-
//
|
|
291
|
-
//
|
|
309
|
+
// degrade a lone-CR file's frontmatter to `unknown`, which this scan
|
|
310
|
+
// reports as an open session (#4869) — so an un-normalized resolved
|
|
311
|
+
// session would resurface as open.
|
|
292
312
|
const rawContent = (0, shell_command_projection_cjs_1.platformReadSync)(safeFilePath);
|
|
293
313
|
if (rawContent === null)
|
|
294
314
|
continue;
|
|
@@ -586,9 +606,11 @@ function scanTodos(todosBase) {
|
|
|
586
606
|
}
|
|
587
607
|
const displayFiles = openFiles.slice(0, 5);
|
|
588
608
|
for (const { entry, content, fm } of displayFiles) {
|
|
589
|
-
// Extract first line of body after frontmatter
|
|
590
|
-
|
|
591
|
-
const
|
|
609
|
+
// Extract first line of body after frontmatter — the block `extractFrontmatter` read above
|
|
610
|
+
// (the one fence owner), so a `---` inside a value cannot end it early.
|
|
611
|
+
const block = frontmatterBlock(content);
|
|
612
|
+
const todoBody = block ? block.rest : content;
|
|
613
|
+
const firstLine = (0, text_lines_cjs_1.splitLines)(todoBody.trim())[0] || '';
|
|
592
614
|
const summary = (0, security_cjs_1.sanitizeForDisplay)(firstLine.slice(0, 100));
|
|
593
615
|
results.push({
|
|
594
616
|
filename: (0, security_cjs_1.sanitizeLabel)(entry.name),
|
|
@@ -602,6 +624,14 @@ function scanTodos(todosBase) {
|
|
|
602
624
|
}
|
|
603
625
|
return { items: results, acknowledged };
|
|
604
626
|
}
|
|
627
|
+
// #4378 (roll-in): true when the filename is a well-formed seed name —
|
|
628
|
+
// `SEED-` prefix, `.md` suffix, and no control bytes anywhere in between (the
|
|
629
|
+
// scanSeeds admission filter passes such names through to the identity
|
|
630
|
+
// derivation; a name with an embedded control byte falls back to its raw
|
|
631
|
+
// stem exactly as the pre-canonical code did).
|
|
632
|
+
function seedIdMatchRawName(name) {
|
|
633
|
+
return !/[\u0000-\u001f\u007f]/.test(name);
|
|
634
|
+
}
|
|
605
635
|
// ─── scanSeeds ────────────────────────────────────────────────────────────────
|
|
606
636
|
/**
|
|
607
637
|
* Scan .planning/seeds/SEED-*.md for unimplemented seeds.
|
|
@@ -653,16 +683,18 @@ function scanSeeds(planDir) {
|
|
|
653
683
|
acknowledged++;
|
|
654
684
|
continue;
|
|
655
685
|
}
|
|
656
|
-
//
|
|
657
|
-
//
|
|
658
|
-
//
|
|
659
|
-
//
|
|
660
|
-
//
|
|
661
|
-
//
|
|
662
|
-
//
|
|
663
|
-
|
|
664
|
-
const
|
|
665
|
-
const
|
|
686
|
+
// #4378 (roll-in): the canonical identity comes from the SAME derivation
|
|
687
|
+
// the list-seeds surface uses — frontmatter `id:` when it matches a seed
|
|
688
|
+
// grammar (legacy `SEED-NNN` or date-suffixed `SEED-YYMMDD-xxx`), else the
|
|
689
|
+
// filename's id prefix, else the whole stem. The old fused
|
|
690
|
+
// filename-stem id (e.g. `SEED-081-region` for `SEED-081-region.md`)
|
|
691
|
+
// disagreed with list-seeds and misfiled deferrals; publishing the
|
|
692
|
+
// canonical id keeps the two surfaces answering identically. The raw-
|
|
693
|
+
// basename fallback for control-byte-bearing names is preserved.
|
|
694
|
+
const stem = node_path_1.default.basename(entry.name, '.md');
|
|
695
|
+
const derived = commandsModule.deriveSeedIdentity(stem, fm.id);
|
|
696
|
+
const seed_id = seedIdMatchRawName(entry.name) ? derived.seed_id : stem;
|
|
697
|
+
const slug = (0, security_cjs_1.sanitizeLabel)(derived.slug);
|
|
666
698
|
let title = (0, security_cjs_1.sanitizeForDisplay)(fm.title || '');
|
|
667
699
|
if (!title) {
|
|
668
700
|
const headingMatch = content.match(/^#\s*(.+)$/m);
|
|
@@ -801,9 +833,9 @@ function scanUatGaps(planDir, cwd) {
|
|
|
801
833
|
// document at this read boundary, same seam as `src/uat.cts`'s
|
|
802
834
|
// `readNormalizedDocument` — `platformReadSync` performs no line-ending
|
|
803
835
|
// normalization itself, and extractFrontmatter/status-derivation below
|
|
804
|
-
// degrade a lone-CR file's frontmatter to `unknown`, which
|
|
805
|
-
//
|
|
806
|
-
//
|
|
836
|
+
// degrade a lone-CR file's frontmatter to `unknown`, which this scan
|
|
837
|
+
// reports as an open gap unless `result: all_pass` (#4869 triage) — so
|
|
838
|
+
// an un-normalized terminal UAT would resurface as open.
|
|
807
839
|
const rawContent = (0, shell_command_projection_cjs_1.platformReadSync)(safeFilePath);
|
|
808
840
|
if (rawContent === null)
|
|
809
841
|
continue;
|
|
@@ -882,8 +914,10 @@ function scanVerificationGaps(planDir, cwd) {
|
|
|
882
914
|
continue;
|
|
883
915
|
const content = normalizeLineEndings(rawContent);
|
|
884
916
|
const fm = extractFrontmatter(content, safeFilePath);
|
|
885
|
-
|
|
886
|
-
|
|
917
|
+
// #5118: the owner's report reader judges `status` — exact match, no
|
|
918
|
+
// case folding; an out-of-set value throws VerificationStatusError.
|
|
919
|
+
const status = reportStatusOf(fm, safeFilePath);
|
|
920
|
+
if (status !== VERIFICATION_STATUS.GAPS_FOUND && status !== VERIFICATION_STATUS.HUMAN_NEEDED)
|
|
887
921
|
continue;
|
|
888
922
|
if (isAuditItemAcknowledged(fm, { snapshotKey: 'status', currentValue: status })) {
|
|
889
923
|
acknowledged++;
|
|
@@ -1059,8 +1093,10 @@ function scanDeferredItems(planDir, cwd) {
|
|
|
1059
1093
|
function auditOpenArtifacts(cwd) {
|
|
1060
1094
|
const planDir = planningDir(cwd);
|
|
1061
1095
|
const debugSessions = (() => {
|
|
1096
|
+
// #5042: debug sessions are shared project state; workflow writers use
|
|
1097
|
+
// the root .planning/debug directory even when a workstream is active.
|
|
1062
1098
|
try {
|
|
1063
|
-
return scanDebugSessions(
|
|
1099
|
+
return scanDebugSessions(debugDir(cwd));
|
|
1064
1100
|
}
|
|
1065
1101
|
catch {
|
|
1066
1102
|
return { items: [{ scan_error: true, slug: '', status: '', updated: '', hypothesis: '' }], acknowledged: 0 };
|
|
@@ -1083,7 +1119,7 @@ function auditOpenArtifacts(cwd) {
|
|
|
1083
1119
|
}
|
|
1084
1120
|
})();
|
|
1085
1121
|
const todos = (() => {
|
|
1086
|
-
// #4256:
|
|
1122
|
+
// #4256: todos are shared project state, like debug sessions (#5042),
|
|
1087
1123
|
// so the close gate reads todosDir(cwd) (the root), not the workstream-
|
|
1088
1124
|
// scoped planDir every other scan below receives. Reading planDir here
|
|
1089
1125
|
// made audit-open print "All artifact types clear. Safe to proceed."
|
|
@@ -1115,7 +1151,11 @@ function auditOpenArtifacts(cwd) {
|
|
|
1115
1151
|
try {
|
|
1116
1152
|
return scanVerificationGaps(planDir, cwd);
|
|
1117
1153
|
}
|
|
1118
|
-
catch {
|
|
1154
|
+
catch (err) {
|
|
1155
|
+
// #5118: an out-of-set report status is the owner's hard error, not a
|
|
1156
|
+
// scan failure to fold into a sentinel — let it reach the CLI seam.
|
|
1157
|
+
if (err instanceof VerificationStatusError)
|
|
1158
|
+
throw err;
|
|
1119
1159
|
return { items: [{ scan_error: true, phase: '', file: '', status: '' }], acknowledged: 0 };
|
|
1120
1160
|
}
|
|
1121
1161
|
})();
|
|
@@ -1384,6 +1424,26 @@ function resolvePhaseTargetDir(planDir, cwd, phase, archivedMilestone) {
|
|
|
1384
1424
|
* artifact identifier that resolves outside the project is refused before
|
|
1385
1425
|
* any read or write is attempted.
|
|
1386
1426
|
*/
|
|
1427
|
+
/**
|
|
1428
|
+
* #4802: splice the acknowledgement marker, surfacing `spliceFrontmatter`'s
|
|
1429
|
+
* write refusal (the one owner of that decision) as an `ioError` naming the
|
|
1430
|
+
* file — an unparseable frontmatter block is NOT an empty one, and splicing
|
|
1431
|
+
* over it would discard every field the author actually wrote.
|
|
1432
|
+
*/
|
|
1433
|
+
function spliceAcknowledgement(content, fm, fileLabel) {
|
|
1434
|
+
try {
|
|
1435
|
+
return spliceFrontmatter(content, fm);
|
|
1436
|
+
}
|
|
1437
|
+
catch (err) {
|
|
1438
|
+
if (!isFrontmatterWriteRefusal(err))
|
|
1439
|
+
throw err;
|
|
1440
|
+
if (err.code === 'FRONTMATTER_UNPARSEABLE') {
|
|
1441
|
+
ioError(`refusing to acknowledge — the frontmatter of "${fileLabel}" is not parseable YAML (splicing would discard every other frontmatter field); fix the YAML syntax error first, then re-run`);
|
|
1442
|
+
}
|
|
1443
|
+
ioError(`refusing to acknowledge "${fileLabel}" — ${err.message}`);
|
|
1444
|
+
throw err; // unreachable — ioError throws
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1387
1447
|
function cmdAuditAcknowledge(cwd, args, raw) {
|
|
1388
1448
|
// args already has the family + subcommand tokens stripped by the caller
|
|
1389
1449
|
// (audit-command-router.cts:147 passes `hubArgs.slice(2)`), so validation
|
|
@@ -1403,7 +1463,9 @@ function cmdAuditAcknowledge(cwd, args, raw) {
|
|
|
1403
1463
|
// All declared flags above are value flags, so each resolves to `string |
|
|
1404
1464
|
// null` at runtime; the cast narrows away the `boolean` arm of
|
|
1405
1465
|
// ParsedNamedArgs's value type that this call site never produces.
|
|
1406
|
-
|
|
1466
|
+
// #4905: without --at, the operator-facing local calendar day (#2136)
|
|
1467
|
+
// through the clock seam, which honors the GSD_NOW_MS pin (#474).
|
|
1468
|
+
const at = atFlag || clock_cjs_1.realClock.localToday();
|
|
1407
1469
|
const planDir = planningDir(cwd);
|
|
1408
1470
|
const markerBase = { milestone: milestone, at };
|
|
1409
1471
|
// #3078-CR MEDIUM 2: every `fs.readFileSync` in this function (below, and
|
|
@@ -1494,7 +1556,7 @@ function cmdAuditAcknowledge(cwd, args, raw) {
|
|
|
1494
1556
|
currentValue = deriveOpenQuestionsDigest(deriveOpenQuestions(normalizedContent, fm));
|
|
1495
1557
|
}
|
|
1496
1558
|
fm.audit_acknowledged = { ...markerBase, [snapshotKey]: currentValue };
|
|
1497
|
-
const newContent =
|
|
1559
|
+
const newContent = spliceAcknowledgement(content, fm, file);
|
|
1498
1560
|
(0, shell_command_projection_cjs_2.platformWriteSync)(safeFilePath, newContent);
|
|
1499
1561
|
output({ acknowledged: true, category, phase, file, [snapshotKey]: currentValue }, raw, 'true');
|
|
1500
1562
|
return;
|
|
@@ -1533,9 +1595,48 @@ function cmdAuditAcknowledge(cwd, args, raw) {
|
|
|
1533
1595
|
else if (category === 'seeds') {
|
|
1534
1596
|
if (!seedId)
|
|
1535
1597
|
ioError('--seed-id is required for --category seeds');
|
|
1536
|
-
|
|
1537
|
-
|
|
1598
|
+
// #4378 (roll-in): `--seed-id` arrives as whichever id an audit/list
|
|
1599
|
+
// surface published — the canonical identity (frontmatter `id:` or the
|
|
1600
|
+
// derived prefix, e.g. `SEED-081`, `SEED-260914-k3x`) or, for callers
|
|
1601
|
+
// scripted against pre-canonical output, the full filename stem. Resolve
|
|
1602
|
+
// by scanning the seeds directory and matching each candidate's derived
|
|
1603
|
+
// identity (falling back to the literal stem), then prove the winner with
|
|
1604
|
+
// requireSafePath exactly like every other acknowledge target. The direct
|
|
1605
|
+
// `seeds/<seedId>.md` build stays as the final fallback so a genuine
|
|
1606
|
+
// miss still reports the same "file not found" error as before.
|
|
1607
|
+
const seedsAckDir = node_path_1.default.join(planDir, 'seeds');
|
|
1608
|
+
let ackCandidate = null;
|
|
1609
|
+
let ackEntries = [];
|
|
1610
|
+
try {
|
|
1611
|
+
ackEntries = node_fs_1.default.readdirSync(seedsAckDir).filter((n) => n.startsWith('SEED-') && n.endsWith('.md'));
|
|
1612
|
+
}
|
|
1613
|
+
catch {
|
|
1614
|
+
ackEntries = [];
|
|
1615
|
+
}
|
|
1616
|
+
for (const name of ackEntries) {
|
|
1617
|
+
const stem = node_path_1.default.basename(name, '.md');
|
|
1618
|
+
let fmId;
|
|
1619
|
+
try {
|
|
1620
|
+
const rawAck = (0, shell_command_projection_cjs_1.platformReadSync)(node_path_1.default.join(seedsAckDir, name));
|
|
1621
|
+
if (rawAck !== null)
|
|
1622
|
+
fmId = extractFrontmatter(normalizeLineEndings(rawAck), node_path_1.default.join(seedsAckDir, name)).id;
|
|
1623
|
+
}
|
|
1624
|
+
catch {
|
|
1625
|
+
fmId = undefined;
|
|
1626
|
+
}
|
|
1627
|
+
const { seed_id: derivedAckId } = commandsModule.deriveSeedIdentity(stem, fmId);
|
|
1628
|
+
if (derivedAckId === seedId || stem === seedId) {
|
|
1629
|
+
ackCandidate = name;
|
|
1630
|
+
break;
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
if (ackCandidate !== null) {
|
|
1634
|
+
safeFilePath = (0, security_cjs_1.requireSafePath)(node_path_1.default.join(seedsAckDir, ackCandidate), planDir, 'audit acknowledge target', security_cjs_1.PathAcceptance.AbsoluteInsideRoot);
|
|
1635
|
+
}
|
|
1636
|
+
else {
|
|
1637
|
+
safeFilePath = (0, security_cjs_1.requireSafePath)(node_path_1.default.join(seedsAckDir, `${seedId}.md`), planDir, 'audit acknowledge target', security_cjs_1.PathAcceptance.AbsoluteInsideRoot);
|
|
1538
1638
|
ioError(`file not found: seeds/${seedId}.md`);
|
|
1639
|
+
}
|
|
1539
1640
|
const content = node_fs_1.default.readFileSync(safeFilePath, 'utf-8');
|
|
1540
1641
|
currentValue = (extractFrontmatter(content, safeFilePath).status || 'dormant').toLowerCase();
|
|
1541
1642
|
}
|
|
@@ -1584,11 +1685,12 @@ function cmdAuditAcknowledge(cwd, args, raw) {
|
|
|
1584
1685
|
return; // unreachable — ioError throws — satisfies TS control-flow analysis
|
|
1585
1686
|
}
|
|
1586
1687
|
const presenceOnly = category === 'todos';
|
|
1587
|
-
const
|
|
1688
|
+
const existingContent = createIfMissing ? '' : node_fs_1.default.readFileSync(safeFilePath, 'utf-8');
|
|
1689
|
+
const fm = createIfMissing ? fmForCreate : extractFrontmatter(existingContent, safeFilePath);
|
|
1588
1690
|
fm.audit_acknowledged = presenceOnly ? { ...markerBase } : { ...markerBase, [snapshotKey]: currentValue };
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1691
|
+
// #4802: createIfMissing splices into '' (no block to refuse on); an existing
|
|
1692
|
+
// file with broken YAML is refused by `spliceAcknowledgement`.
|
|
1693
|
+
const newContent = spliceAcknowledgement(existingContent, fm, safeFilePath);
|
|
1592
1694
|
(0, shell_command_projection_cjs_2.platformWriteSync)(safeFilePath, newContent);
|
|
1593
1695
|
output({ acknowledged: true, category, ...(presenceOnly ? {} : { [snapshotKey]: currentValue }) }, raw, 'true');
|
|
1594
1696
|
}
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
* When `workflow.windows_enforce` is true, `/gsd-ship` blocks while any entry is
|
|
8
8
|
* `open`; an entry can be `waived` only with a recorded reason or `fixed`.
|
|
9
9
|
*
|
|
10
|
-
* LEAF MODULE — imports node:fs + node:path,
|
|
11
|
-
* modules require()d at runtime:
|
|
12
|
-
* milestone stamp) and capability-lock.cjs (the #3780
|
|
13
|
-
* lock). No other src/ imports.
|
|
10
|
+
* LEAF MODULE — imports node:fs + node:path, the leaf frontmatter-fence.cjs (the one
|
|
11
|
+
* frontmatter fence owner), plus two compiled sibling lib modules require()d at runtime:
|
|
12
|
+
* workstream-inventory.cjs (the #4487 milestone stamp) and capability-lock.cjs (the #3780
|
|
13
|
+
* cross-process ledger lock). No other src/ imports.
|
|
14
14
|
*
|
|
15
15
|
* Storage format (`.planning/WINDOWS.md`):
|
|
16
16
|
* ---
|
|
@@ -68,6 +68,7 @@ exports.cmdWindowsWaive = cmdWindowsWaive;
|
|
|
68
68
|
exports.cmdWindowsMarkFixed = cmdWindowsMarkFixed;
|
|
69
69
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
70
70
|
const node_path_1 = __importDefault(require("node:path"));
|
|
71
|
+
const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
|
|
71
72
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
72
73
|
const workstreamInventory = require("./workstream-inventory.cjs");
|
|
73
74
|
// ─── Constants ─────────────────────────────────────────────────────────────
|
|
@@ -385,21 +386,20 @@ function locateJsonBlock(raw, expectedTotal) {
|
|
|
385
386
|
* structural deviation — fail-closed on drift.
|
|
386
387
|
*/
|
|
387
388
|
function parseFrontmatterStrict(raw) {
|
|
388
|
-
|
|
389
|
+
// The block is the one the one fence owner finds (`locateFrontmatterFence`).
|
|
390
|
+
const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(raw);
|
|
391
|
+
if (!fence) {
|
|
389
392
|
throw new WindowsError(exports.REASON.WINDOWS_LEDGER_MALFORMED, 'Ledger missing frontmatter opening ---');
|
|
390
393
|
}
|
|
391
|
-
|
|
392
|
-
const closeIdx = raw.indexOf('\n---', headerEnd);
|
|
393
|
-
if (closeIdx === -1) {
|
|
394
|
+
if (!fence.closed) {
|
|
394
395
|
throw new WindowsError(exports.REASON.WINDOWS_LEDGER_MALFORMED, 'Ledger missing frontmatter closing ---');
|
|
395
396
|
}
|
|
396
|
-
const yamlBody = raw.slice(
|
|
397
|
+
const yamlBody = raw.slice(fence.openEnd, fence.bodyEnd);
|
|
397
398
|
const out = {};
|
|
398
399
|
for (const rawLine of yamlBody.split(/\r?\n/)) {
|
|
399
|
-
// #3116:
|
|
400
|
-
//
|
|
401
|
-
//
|
|
402
|
-
// parseJsonBlock also slices by byte offset) is unaffected.
|
|
400
|
+
// #3116: strip a trailing CR per line (`.` never matches CR, so the key: value regex
|
|
401
|
+
// below would fail on it) without touching the rest of `raw`, which parseJsonBlock also
|
|
402
|
+
// slices by byte offset.
|
|
403
403
|
const line = rawLine.replace(/\r$/, '');
|
|
404
404
|
if (line.trim() === '')
|
|
405
405
|
continue;
|
|
@@ -32,7 +32,7 @@ function _getNestedConfigValue(config, dotKey) {
|
|
|
32
32
|
return { found: true, value: current };
|
|
33
33
|
}
|
|
34
34
|
const _warnedRawConfigPaths = new Set();
|
|
35
|
-
function _readRawConfigKey(filePath, dotKey) {
|
|
35
|
+
function _readRawConfigKey(filePath, dotKey, quiet = false) {
|
|
36
36
|
try {
|
|
37
37
|
const raw = node_fs_1.default.readFileSync(filePath, 'utf8');
|
|
38
38
|
let parsed;
|
|
@@ -40,7 +40,7 @@ function _readRawConfigKey(filePath, dotKey) {
|
|
|
40
40
|
parsed = JSON.parse(raw);
|
|
41
41
|
}
|
|
42
42
|
catch {
|
|
43
|
-
if (!_warnedRawConfigPaths.has(filePath)) {
|
|
43
|
+
if (!quiet && !_warnedRawConfigPaths.has(filePath)) {
|
|
44
44
|
_warnedRawConfigPaths.add(filePath);
|
|
45
45
|
try {
|
|
46
46
|
process.stderr.write(`gsd-tools: warning: failed to parse ${filePath} as JSON — skipping for activation resolution\n`);
|
|
@@ -67,9 +67,14 @@ function _readRawConfigKey(filePath, dotKey) {
|
|
|
67
67
|
* 3. Root config.json at planningRoot(cwd)/config.json (only if path differs).
|
|
68
68
|
* 4. registry.configSchema[dotKey].default — schema default.
|
|
69
69
|
* 5. Absent → { found: false, value: undefined }.
|
|
70
|
+
*
|
|
71
|
+
* `quiet: true` (default false) suppresses the one-time stderr warning for a config.json that is
|
|
72
|
+
* not valid JSON: a gate reads its switch quietly (a malformed config is simply "key absent"), it
|
|
73
|
+
* never writes to stderr (#5139).
|
|
70
74
|
*/
|
|
71
75
|
function resolveConfigKey(dotKey, opts) {
|
|
72
76
|
const { config, cwd, registry } = opts;
|
|
77
|
+
const quiet = opts.quiet === true;
|
|
73
78
|
// Level 1: loadConfig result
|
|
74
79
|
const fromConfig = _getNestedConfigValue(config, dotKey);
|
|
75
80
|
if (fromConfig.found)
|
|
@@ -78,11 +83,11 @@ function resolveConfigKey(dotKey, opts) {
|
|
|
78
83
|
if (cwd) {
|
|
79
84
|
const wsConfigPath = node_path_1.default.join(planningDir(cwd), 'config.json');
|
|
80
85
|
const rootConfigPath = node_path_1.default.join(planningRoot(cwd), 'config.json');
|
|
81
|
-
const fromWs = _readRawConfigKey(wsConfigPath, dotKey);
|
|
86
|
+
const fromWs = _readRawConfigKey(wsConfigPath, dotKey, quiet);
|
|
82
87
|
if (fromWs.found)
|
|
83
88
|
return { found: true, value: fromWs.value };
|
|
84
89
|
if (wsConfigPath !== rootConfigPath) {
|
|
85
|
-
const fromRoot = _readRawConfigKey(rootConfigPath, dotKey);
|
|
90
|
+
const fromRoot = _readRawConfigKey(rootConfigPath, dotKey, quiet);
|
|
86
91
|
if (fromRoot.found)
|
|
87
92
|
return { found: true, value: fromRoot.value };
|
|
88
93
|
}
|