@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
|
@@ -103,37 +103,28 @@ Runs unconditionally on every audit. Ensures screenshots never reach a commit ev
|
|
|
103
103
|
## Screenshot Capture (CLI only — no MCP, no persistent browser)
|
|
104
104
|
|
|
105
105
|
```bash
|
|
106
|
-
#
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"$SCREENSHOT_DIR
|
|
116
|
-
--viewport-size=
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
"$SCREENSHOT_DIR
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
"$SCREENSHOT_DIR/tablet.png" \
|
|
126
|
-
--viewport-size=768,1024 2>/dev/null
|
|
127
|
-
|
|
128
|
-
echo "Screenshots captured to $SCREENSHOT_DIR"
|
|
129
|
-
else
|
|
130
|
-
echo "No dev server at localhost:3000 — code-only audit"
|
|
131
|
-
fi
|
|
106
|
+
# Ports 3000, 5173, 8080 (DEV_PORTS: digit runs only); 000 or 5xx = no server; a shot counts only if the file is non-empty.
|
|
107
|
+
DEV_URL=""; SCREENSHOT_DIR=""
|
|
108
|
+
for PORT in $(printf '%s' "${DEV_PORTS:-3000 5173 8080}" | tr -cs '0-9' ' '); do
|
|
109
|
+
DEV_STATUS=$(curl -sL --max-time 5 -o /dev/null -w "%{http_code}" "http://localhost:$PORT" 2>/dev/null) || DEV_STATUS="000"
|
|
110
|
+
case "$DEV_STATUS" in 000|""|5*) ;; *) DEV_URL="http://localhost:$PORT"; break ;; esac
|
|
111
|
+
done
|
|
112
|
+
if [ -n "$DEV_URL" ]; then
|
|
113
|
+
SCREENSHOT_DIR=".planning/ui-reviews/${PADDED_PHASE}-$(date +%Y%m%d-%H%M%S)"; mkdir -p "$SCREENSHOT_DIR"; SHOTS_OK=0
|
|
114
|
+
for SHOT in desktop:1440,900 mobile:375,812 tablet:768,1024; do
|
|
115
|
+
N="${SHOT%%:*}"; S="${SHOT#*:}"; F="$SCREENSHOT_DIR/$N.png"
|
|
116
|
+
if npx playwright screenshot "$DEV_URL" "$F" --viewport-size="$S" --timeout=30000 </dev/null >/dev/null 2>&1 && [ -s "$F" ]; then SHOTS_OK=$((SHOTS_OK + 1))
|
|
117
|
+
else rm -f "$F"; echo "Screenshot FAILED: $N ($S) from $DEV_URL"; fi
|
|
118
|
+
done
|
|
119
|
+
case "$SHOTS_OK" in
|
|
120
|
+
3) echo "Screenshots captured (3/3) to $SCREENSHOT_DIR" ;;
|
|
121
|
+
0) echo "Screenshots NOT captured: $DEV_URL answered but every capture failed — code-only audit" ;;
|
|
122
|
+
*) echo "Screenshots PARTIAL ($SHOTS_OK/3) in $SCREENSHOT_DIR" ;;
|
|
123
|
+
esac
|
|
124
|
+
else echo "No dev server on localhost:3000, 5173 or 8080 — code-only audit"; fi
|
|
132
125
|
```
|
|
133
126
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
Try port 3000 first, then 5173 (Vite default), then 8080.
|
|
127
|
+
No dev server: code-review-only audit; say screenshots were not captured. The block's last line is its outcome (`captured`, `PARTIAL`, `NOT captured`): record `captured` only for the first, else name the failed captures and score visual pillars without them.
|
|
137
128
|
|
|
138
129
|
</screenshot_approach>
|
|
139
130
|
|
|
@@ -325,7 +316,7 @@ Read all files from `<required_reading>`. Parse SUMMARY.md, PLAN.md, CONTEXT.md,
|
|
|
325
316
|
Run the gitignore gate from `<gitignore_gate>`. MUST happen before step 3.
|
|
326
317
|
|
|
327
318
|
## Step 3: Detect Dev Server and Capture Screenshots
|
|
328
|
-
Run `<screenshot_approach
|
|
319
|
+
Run `<screenshot_approach>`; record its outcome line.
|
|
329
320
|
|
|
330
321
|
## Step 4: Scan Implemented Files
|
|
331
322
|
|
package/agents/gsd-ui-auditor.md
CHANGED
|
@@ -78,29 +78,21 @@ If no UI-SPEC exists: audit against abstract 6-pillar standards.
|
|
|
78
78
|
|
|
79
79
|
## Screenshot Storage Safety
|
|
80
80
|
|
|
81
|
-
**MUST run before any screenshot capture.** Prevents
|
|
81
|
+
**MUST run before any screenshot capture.** Prevents capture output from reaching git history.
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
84
|
# Ensure directory exists
|
|
85
85
|
mkdir -p .planning/ui-reviews
|
|
86
86
|
|
|
87
|
-
#
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
*.jpg
|
|
94
|
-
*.jpeg
|
|
95
|
-
*.gif
|
|
96
|
-
*.bmp
|
|
97
|
-
*.tiff
|
|
98
|
-
GITIGNORE
|
|
99
|
-
echo "Created .planning/ui-reviews/.gitignore"
|
|
100
|
-
fi
|
|
87
|
+
# Append any pattern the file lacks — an older .gitignore is still covered; never rewritten.
|
|
88
|
+
[ -f .planning/ui-reviews/.gitignore ] \
|
|
89
|
+
|| { printf '# UI-audit captures — never commit\n' > .planning/ui-reviews/.gitignore; echo "Created .planning/ui-reviews/.gitignore"; }
|
|
90
|
+
for p in '*.png' '*.webp' '*.jpg' '*.jpeg' '*.gif' '*.bmp' '*.tiff' 'interaction/'; do
|
|
91
|
+
grep -qxF -- "$p" .planning/ui-reviews/.gitignore || printf '%s\n' "$p" >> .planning/ui-reviews/.gitignore
|
|
92
|
+
done
|
|
101
93
|
```
|
|
102
94
|
|
|
103
|
-
|
|
95
|
+
Keeps captures out of a commit even after `git add .`: screenshots by extension, and `interaction/` as a whole (its snapshot carries form values, its console output can carry tokens).
|
|
104
96
|
|
|
105
97
|
</gitignore_gate>
|
|
106
98
|
|
|
@@ -109,37 +101,171 @@ This gate runs unconditionally on every audit. The .gitignore ensures screenshot
|
|
|
109
101
|
## Screenshot Capture (CLI only — no MCP, no persistent browser)
|
|
110
102
|
|
|
111
103
|
```bash
|
|
112
|
-
#
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
104
|
+
# Ports 3000, 5173 (Vite), 8080 (DEV_PORTS keeps only its digit runs). -L follows redirects; only 000 or a 5xx is
|
|
105
|
+
# "no server"; --max-time bounds a silent port. A capture counts only if playwright exits 0 AND the file is non-empty.
|
|
106
|
+
DEV_URL=""
|
|
107
|
+
SCREENSHOT_DIR=""
|
|
108
|
+
for PORT in $(printf '%s' "${DEV_PORTS:-3000 5173 8080}" | tr -cs '0-9' ' '); do
|
|
109
|
+
DEV_STATUS=$(curl -sL --max-time 5 -o /dev/null -w "%{http_code}" "http://localhost:$PORT" 2>/dev/null) || DEV_STATUS="000"
|
|
110
|
+
case "$DEV_STATUS" in 000|""|5*) ;; *) DEV_URL="http://localhost:$PORT"; break ;; esac
|
|
111
|
+
done
|
|
112
|
+
|
|
113
|
+
if [ -n "$DEV_URL" ]; then
|
|
116
114
|
SCREENSHOT_DIR=".planning/ui-reviews/${PADDED_PHASE}-$(date +%Y%m%d-%H%M%S)"
|
|
117
115
|
mkdir -p "$SCREENSHOT_DIR"
|
|
116
|
+
SHOTS_OK=0
|
|
117
|
+
for SHOT in desktop:1440,900 mobile:375,812 tablet:768,1024; do
|
|
118
|
+
N="${SHOT%%:*}"; S="${SHOT#*:}"
|
|
119
|
+
if npx playwright screenshot "$DEV_URL" "$SCREENSHOT_DIR/$N.png" --viewport-size="$S" --timeout=30000 </dev/null >/dev/null 2>&1 \
|
|
120
|
+
&& [ -s "$SCREENSHOT_DIR/$N.png" ]; then
|
|
121
|
+
SHOTS_OK=$((SHOTS_OK + 1))
|
|
122
|
+
else
|
|
123
|
+
rm -f "$SCREENSHOT_DIR/$N.png"; echo "Screenshot FAILED: $N ($S) from $DEV_URL"
|
|
124
|
+
fi
|
|
125
|
+
done
|
|
126
|
+
case "$SHOTS_OK" in
|
|
127
|
+
3) echo "Screenshots captured (3/3) to $SCREENSHOT_DIR" ;;
|
|
128
|
+
0) echo "Screenshots NOT captured: $DEV_URL answered but every capture failed — code-only audit" ;;
|
|
129
|
+
*) echo "Screenshots PARTIAL ($SHOTS_OK/3) in $SCREENSHOT_DIR" ;;
|
|
130
|
+
esac
|
|
131
|
+
else
|
|
132
|
+
echo "No dev server on localhost:3000, 5173 or 8080 — code-only audit"
|
|
133
|
+
fi
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
No dev server: code-review-only audit (Tailwind class audit, string audit for generic labels, state handling check); say screenshots were not captured. The block's last line is its outcome: `captured`, `PARTIAL` or `NOT captured`. Record `captured` only for the first; otherwise name the failed captures and score the visual pillars without them.
|
|
118
137
|
|
|
119
|
-
|
|
120
|
-
npx playwright screenshot http://localhost:3000 \
|
|
121
|
-
"$SCREENSHOT_DIR/desktop.png" \
|
|
122
|
-
--viewport-size=1440,900 2>/dev/null
|
|
138
|
+
<!-- gsd:ui-interaction-capture -->
|
|
123
139
|
|
|
124
|
-
|
|
125
|
-
npx playwright screenshot http://localhost:3000 \
|
|
126
|
-
"$SCREENSHOT_DIR/mobile.png" \
|
|
127
|
-
--viewport-size=375,812 2>/dev/null
|
|
140
|
+
### Interaction capture (default-off — `workflow.ui_interaction_capture`)
|
|
128
141
|
|
|
129
|
-
|
|
130
|
-
npx playwright screenshot http://localhost:3000 \
|
|
131
|
-
"$SCREENSHOT_DIR/tablet.png" \
|
|
132
|
-
--viewport-size=768,1024 2>/dev/null
|
|
142
|
+
The static captures show only the first paint of `/` (`npx playwright screenshot` has no click, fill, hover, press, snapshot or console verb), yet the Experience Design pillar is scored on interaction. When the `<config>` block carries `interaction_capture: true` (`workflow.ui_interaction_capture`, read by `/gsd:ui-review`) **and** a Chrome binary resolves, the `chrome-devtools` CLI (`chrome-devtools-mcp`) adds post-interaction captures over `Bash` alone: no MCP server, no `tools:` change. Key off, or no Chrome: one status line, then the audit as before.
|
|
133
143
|
|
|
134
|
-
|
|
144
|
+
```bash
|
|
145
|
+
# INTERACTION_CAPTURE: the <config> block's `interaction_capture` (absent = off); SCREENSHOT_DIR/DEV_URL: above.
|
|
146
|
+
INTERACTION_CAPTURE="${INTERACTION_CAPTURE:-false}"
|
|
147
|
+
INTERACTION_STATUS="off"
|
|
148
|
+
|
|
149
|
+
# An installed Chrome, never a download; CHROME_BIN overrides.
|
|
150
|
+
CHROME_BIN="${CHROME_BIN:-}"
|
|
151
|
+
if [ -z "$CHROME_BIN" ]; then
|
|
152
|
+
for _c in google-chrome google-chrome-stable chromium chromium-browser chrome; do
|
|
153
|
+
if command -v "$_c" >/dev/null 2>&1; then CHROME_BIN=$(command -v "$_c"); break; fi
|
|
154
|
+
done
|
|
155
|
+
fi
|
|
156
|
+
if [ -z "$CHROME_BIN" ] && [ -x "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" ]; then
|
|
157
|
+
CHROME_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
|
158
|
+
fi
|
|
159
|
+
if [ -z "$CHROME_BIN" ] && [ -x "${PROGRAMFILES:-/nonexistent}/Google/Chrome/Application/chrome.exe" ]; then
|
|
160
|
+
CHROME_BIN="${PROGRAMFILES}/Google/Chrome/Application/chrome.exe"
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
# Floor, not a pin (--workspace needs 1.9.0); -y answers npx's prompt. --sessionId (hex/dashes) keys the
|
|
164
|
+
# daemon socket; concurrent audits need their own: BASHPID not $$ (subshells share $$) + $RANDOM.
|
|
165
|
+
CDT_SESSION="$(date +%s)-${BASHPID:-$$}-$RANDOM"
|
|
166
|
+
CDT="npx -y -p chrome-devtools-mcp@${CHROME_DEVTOOLS_MCP_VERSION:-^1.9.0} chrome-devtools --sessionId $CDT_SESSION"
|
|
167
|
+
# cdt <ceiling-s> <verb> [args...]: every driver call is bounded (no timeout(1) on macOS) by a watchdog killing the
|
|
168
|
+
# job's process group at the ceiling (TERM, KILL 2 s later; npm forwards SIGTERM only to its direct child). It is an
|
|
169
|
+
# exec'd bash (a subshell keeps the caller's stdio open) polling the GROUP (a child can outlive the leader holding
|
|
170
|
+
# stdout) and standing down once it is empty; never signalled (bash 3.2 may not interrupt `wait`; Git Bash hangs).
|
|
171
|
+
CDT_T_START="${CHROME_DEVTOOLS_START_TIMEOUT:-180}"
|
|
172
|
+
CDT_T_STEP="${CHROME_DEVTOOLS_STEP_TIMEOUT:-60}"
|
|
173
|
+
cdt() {
|
|
174
|
+
local ceiling="$1" pid wd rc=0; shift
|
|
175
|
+
set -m; $CDT "$@" & pid=$!; set +m # -m: job = own process group
|
|
176
|
+
"${BASH:-bash}" -c 'n=$(($1 * 10)); while kill -0 -- "-$2" 2>/dev/null; do [ "$n" -gt 0 ] || { kill -TERM -- "-$2" 2>/dev/null; sleep 2; kill -0 -- "-$2" 2>/dev/null && kill -KILL -- "-$2" 2>/dev/null; exit 0; }; sleep 0.1 || exit 0; n=$((n - 1)); done' _ "$ceiling" "$pid" >/dev/null 2>&1 & wd=$!
|
|
177
|
+
wait "$pid" || rc=$?
|
|
178
|
+
wait "$wd" 2>/dev/null || true
|
|
179
|
+
return "$rc"
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if [ "$INTERACTION_CAPTURE" != "true" ]; then
|
|
183
|
+
echo "Interaction capture: off (workflow.ui_interaction_capture is false)"
|
|
184
|
+
elif [ -z "${SCREENSHOT_DIR:-}" ] || [ ! -d "$SCREENSHOT_DIR" ]; then
|
|
185
|
+
INTERACTION_STATUS="skipped (no dev server reached)"
|
|
186
|
+
echo "Interaction capture: skipped — static capture reached no dev server"
|
|
187
|
+
elif [ -z "$CHROME_BIN" ]; then
|
|
188
|
+
INTERACTION_STATUS="skipped (no Chrome binary resolved)"
|
|
189
|
+
echo "Interaction capture: skipped — no Chrome binary resolved (set CHROME_BIN)"
|
|
135
190
|
else
|
|
136
|
-
|
|
191
|
+
DEV_URL="${DEV_URL:-http://localhost:3000}"
|
|
192
|
+
INTERACTION_DIR="$SCREENSHOT_DIR/interaction"
|
|
193
|
+
mkdir -p "$INTERACTION_DIR"
|
|
194
|
+
ICAPTURED=0
|
|
195
|
+
IFAILED=0
|
|
196
|
+
PAGE_ID=""
|
|
197
|
+
cdt_me() { exec /bin/sh -c 'echo "$PPID"'; }
|
|
198
|
+
CDT_STARTED=0; CDT_SHELL=$(cdt_me)
|
|
199
|
+
|
|
200
|
+
ishot() {
|
|
201
|
+
if cdt "$CDT_T_STEP" take_screenshot "$PAGE_ID" --filePath "$INTERACTION_DIR/$1.png" >/dev/null 2>&1 \
|
|
202
|
+
&& [ -s "$INTERACTION_DIR/$1.png" ]; then
|
|
203
|
+
ICAPTURED=$((ICAPTURED + 1))
|
|
204
|
+
else
|
|
205
|
+
rm -f "$INTERACTION_DIR/$1.png"
|
|
206
|
+
IFAILED=$((IFAILED + 1))
|
|
207
|
+
echo " interaction capture FAILED: $1"
|
|
208
|
+
fi
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
# cdt_stop: owed once after a successful start; trapped on EXIT, flag-deduped, installing shell only (never a subshell copy).
|
|
212
|
+
cdt_stop() { [ "$CDT_STARTED" = 1 ] && [ "$(cdt_me)" = "$CDT_SHELL" ] || return 0; CDT_STARTED=0; cdt "$CDT_T_STEP" stop >/dev/null 2>&1 || true; }
|
|
213
|
+
|
|
214
|
+
# --isolated: throwaway profile. --workspace: writes under the capture dir only (--allowUnrestrictedPaths is deprecated).
|
|
215
|
+
if cdt "$CDT_T_START" start -e "$CHROME_BIN" --isolated --workspace "$INTERACTION_DIR" --usageStatistics=false >/dev/null 2>&1; then
|
|
216
|
+
CDT_STARTED=1; trap cdt_stop EXIT
|
|
217
|
+
# new_page marks the page `[selected]`: the pageId every later verb takes. --timeout (ms) bounds the navigation; tr: CRLF.
|
|
218
|
+
PAGE_ID=""
|
|
219
|
+
if NEW_PAGE_OUT=$(cdt "$CDT_T_STEP" new_page "$DEV_URL" --timeout 30000 2>/dev/null); then
|
|
220
|
+
PAGE_ID=$(printf '%s\n' "$NEW_PAGE_OUT" | tr -d '\r' | sed -n 's/^\([0-9][0-9]*\): .*\[selected\]$/\1/p' | head -1)
|
|
221
|
+
fi
|
|
222
|
+
if [ -n "$PAGE_ID" ]; then
|
|
223
|
+
if ! cdt "$CDT_T_STEP" resize_page "$PAGE_ID" 1440 900 >/dev/null 2>&1; then
|
|
224
|
+
IFAILED=$((IFAILED + 1))
|
|
225
|
+
echo " interaction step FAILED: resize_page"
|
|
226
|
+
fi
|
|
227
|
+
if ! cdt "$CDT_T_STEP" take_snapshot "$PAGE_ID" --filePath "$INTERACTION_DIR/snapshot.txt" >/dev/null 2>&1; then
|
|
228
|
+
rm -f "$INTERACTION_DIR/snapshot.txt"
|
|
229
|
+
IFAILED=$((IFAILED + 1))
|
|
230
|
+
echo " interaction step FAILED: take_snapshot"
|
|
231
|
+
fi
|
|
232
|
+
ishot baseline
|
|
233
|
+
# Focus ring: first focusable.
|
|
234
|
+
if cdt "$CDT_T_STEP" press_key "$PAGE_ID" Tab >/dev/null 2>&1; then
|
|
235
|
+
ishot focus-first
|
|
236
|
+
else
|
|
237
|
+
IFAILED=$((IFAILED + 1))
|
|
238
|
+
echo " interaction step FAILED: press_key Tab"
|
|
239
|
+
fi
|
|
240
|
+
# --- Drive each interactive component UI-SPEC.md declares (or the snapshot shows): a uid from the latest snapshot, one capture each:
|
|
241
|
+
# cdt "$CDT_T_STEP" hover "$PAGE_ID" <uid> && ishot hover-<label>
|
|
242
|
+
# cdt "$CDT_T_STEP" click "$PAGE_ID" <uid> && ishot <label>-open
|
|
243
|
+
# cdt "$CDT_T_STEP" fill "$PAGE_ID" <uid> "<value>" && ishot <label>-filled
|
|
244
|
+
# cdt "$CDT_T_STEP" press_key "$PAGE_ID" Enter && ishot <label>-submitted
|
|
245
|
+
# (re-take take_snapshot after each interaction)
|
|
246
|
+
cdt "$CDT_T_STEP" list_console_messages "$PAGE_ID" > "$INTERACTION_DIR/console.txt" 2>/dev/null || true
|
|
247
|
+
else
|
|
248
|
+
echo " new_page FAILED: $DEV_URL"
|
|
249
|
+
fi
|
|
250
|
+
cdt_stop
|
|
251
|
+
else
|
|
252
|
+
echo " start FAILED (npx fetch, Chrome at $CHROME_BIN, or the ${CDT_T_START}s ceiling)"
|
|
253
|
+
fi
|
|
254
|
+
|
|
255
|
+
if [ "$ICAPTURED" -gt 0 ]; then
|
|
256
|
+
INTERACTION_STATUS="captured ($ICAPTURED state(s), $IFAILED failed) in $INTERACTION_DIR"
|
|
257
|
+
else
|
|
258
|
+
INTERACTION_STATUS="not captured (driver or capture failure)"
|
|
259
|
+
fi
|
|
260
|
+
echo "Interaction capture: $INTERACTION_STATUS"
|
|
137
261
|
fi
|
|
138
262
|
```
|
|
139
263
|
|
|
140
|
-
|
|
264
|
+
`wait_for` is MCP-only: where a state needs settling, poll `cdt "$CDT_T_STEP" evaluate_script "() => document.readyState" --pageId "$PAGE_ID"` for `complete`. The driver is Chromium-only; Firefox and WebKit stay on `npx playwright screenshot -b firefox|webkit`.
|
|
265
|
+
|
|
266
|
+
Carry `$INTERACTION_STATUS` into the report's `**Interaction captures:**` field. **Never report an interaction state you did not capture** — key off or section skipped, interaction findings are code-derived and say so.
|
|
141
267
|
|
|
142
|
-
|
|
268
|
+
<!-- /gsd:ui-interaction-capture -->
|
|
143
269
|
|
|
144
270
|
</screenshot_approach>
|
|
145
271
|
|
|
@@ -300,6 +426,7 @@ Write to: `$PHASE_DIR/$PADDED_PHASE-UI-REVIEW.md`
|
|
|
300
426
|
**Audited:** {date}
|
|
301
427
|
**Baseline:** {UI-SPEC.md / abstract standards}
|
|
302
428
|
**Screenshots:** {captured / not captured (no dev server)}
|
|
429
|
+
**Interaction captures:** {$INTERACTION_STATUS — off / skipped (reason) / captured (N states) / not captured (reason)}
|
|
303
430
|
|
|
304
431
|
---
|
|
305
432
|
|
|
@@ -366,7 +493,7 @@ Run the gitignore gate from `<gitignore_gate>`. This MUST happen before step 3.
|
|
|
366
493
|
|
|
367
494
|
## Step 3: Detect Dev Server and Capture Screenshots
|
|
368
495
|
|
|
369
|
-
Run the screenshot approach from `<screenshot_approach
|
|
496
|
+
Run the screenshot approach from `<screenshot_approach>`; record its outcome line. Then run its interaction-capture section with `INTERACTION_CAPTURE` set from the `<config>` block's `interaction_capture` value, and record `$INTERACTION_STATUS` verbatim — it is `off` unless `workflow.ui_interaction_capture` is on and a Chrome binary resolved.
|
|
370
497
|
|
|
371
498
|
## Step 4: Scan Implemented Files
|
|
372
499
|
|
|
@@ -407,6 +534,7 @@ Use output format from `<output_format>`. If registry audit produced flags, add
|
|
|
407
534
|
**Phase:** {phase_number} - {phase_name}
|
|
408
535
|
**Overall Score:** {total}/24
|
|
409
536
|
**Screenshots:** {captured / not captured}
|
|
537
|
+
**Interaction captures:** {$INTERACTION_STATUS}
|
|
410
538
|
|
|
411
539
|
### Pillar Summary
|
|
412
540
|
| Pillar | Score |
|
|
@@ -441,6 +569,7 @@ UI audit is complete when:
|
|
|
441
569
|
- [ ] .gitignore gate executed before any screenshot capture
|
|
442
570
|
- [ ] Dev server detection attempted
|
|
443
571
|
- [ ] Screenshots captured (or noted as unavailable)
|
|
572
|
+
- [ ] Interaction-capture outcome recorded from `$INTERACTION_STATUS` (off, skipped with reason, or captured)
|
|
444
573
|
- [ ] All 6 pillars scored with evidence
|
|
445
574
|
- [ ] Registry safety audit executed (if shadcn + third-party registries present)
|
|
446
575
|
- [ ] Top 3 priority fixes identified with concrete solutions
|
|
@@ -176,7 +176,7 @@ Read template `~/.claude/gsd-core/templates/UI-SPEC.md`. Fill all sections. Writ
|
|
|
176
176
|
|
|
177
177
|
## Step 6: Commit (optional)
|
|
178
178
|
```bash
|
|
179
|
-
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; };
|
|
179
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
180
180
|
gsd_run query commit "docs($PHASE): UI design contract" --files "$PHASE_DIR/$PADDED_PHASE-UI-SPEC.md"
|
|
181
181
|
```
|
|
182
182
|
|
|
@@ -327,7 +327,7 @@ This file is the canonical output of this agent. The orchestrator reads `$PHASE_
|
|
|
327
327
|
## Step 6: Commit (optional)
|
|
328
328
|
|
|
329
329
|
```bash
|
|
330
|
-
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; };
|
|
330
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
331
331
|
gsd_run query commit "docs($PHASE): UI design contract" --files "$PHASE_DIR/$PADDED_PHASE-UI-SPEC.md"
|
|
332
332
|
```
|
|
333
333
|
|
package/agents/gsd-verifier.md
CHANGED
|
@@ -80,6 +80,12 @@ At verification decision points, apply structured reasoning:
|
|
|
80
80
|
At verification decision points, reference calibration examples:
|
|
81
81
|
@~/.claude/gsd-core/references/few-shot-examples/verifier.md
|
|
82
82
|
|
|
83
|
+
## Resolver Bootstrap (Every Mode)
|
|
84
|
+
|
|
85
|
+
`gsd_run` is used in initial and re-verification mode alike, so it is defined here, before Step 0, not inside a mode-specific step. Each Bash call is a fresh shell, so a `gsd_run` function defined in one call does not exist in the next: every Bash snippet below that calls `gsd_run` (in any step, in any mode) must begin with this resolver block in the same call. If `gsd-tools.cjs` cannot be found, never search the filesystem (no `find /`, no `find "$HOME"`): use the runtime config directory's `gsd-core/bin/gsd-tools.cjs` (`${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/gsd-tools.cjs` on Claude Code) or stop and report.
|
|
86
|
+
|
|
87
|
+
@~/.claude/gsd-core/references/gsd-run-resolver.md
|
|
88
|
+
|
|
83
89
|
## Step 0: Check for Previous Verification
|
|
84
90
|
|
|
85
91
|
```bash
|
|
@@ -104,7 +110,6 @@ Set `is_re_verification = false`, proceed with Step 1.
|
|
|
104
110
|
## Step 1: Load Context (Initial Mode Only)
|
|
105
111
|
|
|
106
112
|
```bash
|
|
107
|
-
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif _gsd_at "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd_run is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; case "$(gsd_run runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') GSD_IDENTITY_STATUS=ok;; esac; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
108
113
|
ls "$PHASE_DIR"/*-PLAN.md 2>/dev/null
|
|
109
114
|
ls "$PHASE_DIR"/*-SUMMARY.md 2>/dev/null
|
|
110
115
|
gsd_run query roadmap.get-phase "$PHASE_NUM"
|
|
@@ -245,11 +250,13 @@ overrides:
|
|
|
245
250
|
Use `gsd-tools query` for artifact verification against must_haves in PLAN frontmatter:
|
|
246
251
|
|
|
247
252
|
```bash
|
|
248
|
-
ARTIFACT_RESULT=$(gsd_run query verify.artifacts "$PLAN_PATH")
|
|
253
|
+
ARTIFACT_RESULT=$(gsd_run query verify.artifacts "$PLAN_PATH") && ARTIFACT_EXIT=0 || ARTIFACT_EXIT=$?
|
|
249
254
|
```
|
|
250
255
|
|
|
251
256
|
Parse JSON result: `{ all_passed, passed, total, artifacts: [{path, exists, issues, passed}] }`
|
|
252
257
|
|
|
258
|
+
The exit status follows the verdict (#5170): `0` = every artifact passed; `1` = negative verdict (`all_passed: false`), the JSON is still authoritative, so map each artifact below; `66` (`NO_INPUT`) = the plan declares no `must_haves.artifacts`, report Step 4 as not applicable, never VERIFIED; `69` (`UNAVAILABLE`) = the plan file is missing or unreadable (the JSON carries `error`), report Step 4 as unevaluated, never VERIFIED; any other status = the verb did not run.
|
|
259
|
+
|
|
253
260
|
For each artifact in result:
|
|
254
261
|
- `exists=false` → MISSING
|
|
255
262
|
- `issues` contains "Only N lines" or "Missing pattern" → STUB
|
|
@@ -289,10 +296,10 @@ grep -r "$artifact_name" "${search_path:-src/}" --include="*.ts" --include="*.ts
|
|
|
289
296
|
|
|
290
297
|
## Step 4b: Data-Flow Trace (Level 4)
|
|
291
298
|
|
|
292
|
-
Trace each rendered value back to a real data source.
|
|
293
|
-
recipes:
|
|
299
|
+
Trace each rendered value back to a real data source. Procedure and
|
|
300
|
+
recipes: @~/.claude/gsd-core/references/verifier-wiring-patterns.md
|
|
294
301
|
|
|
295
|
-
Flag any value whose chain
|
|
302
|
+
Flag any value whose chain ends in a static return, a hardcoded literal, or
|
|
296
303
|
a mock rather than a real query.
|
|
297
304
|
|
|
298
305
|
**Data-flow status vocabulary:**
|
|
@@ -321,11 +328,13 @@ Key links are critical connections. If broken, the goal fails even with all arti
|
|
|
321
328
|
Use `gsd-tools query` for key link verification against must_haves in PLAN frontmatter:
|
|
322
329
|
|
|
323
330
|
```bash
|
|
324
|
-
LINKS_RESULT=$(gsd_run query verify.key-links "$PLAN_PATH")
|
|
331
|
+
LINKS_RESULT=$(gsd_run query verify.key-links "$PLAN_PATH") && LINKS_EXIT=0 || LINKS_EXIT=$?
|
|
325
332
|
```
|
|
326
333
|
|
|
327
334
|
Parse JSON result: `{ all_verified, verified, total, links: [{from, to, via, verified, detail}] }`
|
|
328
335
|
|
|
336
|
+
The exit status follows the verdict (#5170): `0` = every link verified; `1` = negative verdict (`all_verified: false`), the JSON is still authoritative; `66` (`NO_INPUT`) = the plan declares no `must_haves.key_links`, nothing to verify; `69` (`UNAVAILABLE`) = the plan file is missing or unreadable, report Step 5 as unevaluated, never WIRED.
|
|
337
|
+
|
|
329
338
|
For each link:
|
|
330
339
|
- `verified=true` → WIRED
|
|
331
340
|
- `verified=false` with "not found" in detail → NOT_WIRED
|
|
@@ -335,8 +344,8 @@ For each link:
|
|
|
335
344
|
|
|
336
345
|
### Wiring patterns
|
|
337
346
|
|
|
338
|
-
Verify each link below;
|
|
339
|
-
|
|
347
|
+
Verify each link below; per-pattern procedures and recipes:
|
|
348
|
+
@~/.claude/gsd-core/references/verifier-wiring-patterns.md
|
|
340
349
|
|
|
341
350
|
- **Component → API** — the component actually calls the endpoint it claims.
|
|
342
351
|
- **API → Database** — the endpoint issues a real query, not a static return.
|
|
@@ -382,7 +391,8 @@ SUMMARY_FILES=$(gsd_run query summary-extract "$PHASE_DIR"/*-SUMMARY.md --fields
|
|
|
382
391
|
# Option 2: Verify commits exist (if commit hashes documented)
|
|
383
392
|
COMMIT_HASHES=$(grep -oE "[a-f0-9]{7,40}" "$PHASE_DIR"/*-SUMMARY.md | head -10)
|
|
384
393
|
if [ -n "$COMMIT_HASHES" ]; then
|
|
385
|
-
|
|
394
|
+
# Exit 0 = every hash is a commit, exit 1 = at least one is not (read the JSON); 69 = not a git repo (could not look).
|
|
395
|
+
COMMITS_VALID=$(gsd_run query verify.commits $COMMIT_HASHES) && COMMITS_EXIT=0 || COMMITS_EXIT=$?
|
|
386
396
|
fi
|
|
387
397
|
|
|
388
398
|
# Fallback: grep for files
|
|
@@ -411,7 +421,7 @@ grep -n -B 2 -A 2 "console\.log" "$file" 2>/dev/null | grep -E "^\s*(const|funct
|
|
|
411
421
|
|
|
412
422
|
**Debt marker gate:** Any `TBD`, `FIXME`, or `XXX` marker in a file modified by this phase is a 🛑 BLOCKER unless the same line references formal follow-up work (`issue #123`, `PR #123`, `#123`, or `DEF-*`). Unreferenced markers mean completion is not auditable; set `status: gaps_found` and list each marker under `gaps`.
|
|
413
423
|
|
|
414
|
-
**Re-verification evidence gate (#3304):** in re-verification mode, a 🛑 Blocker other than an unresolved debt marker (always self-evidencing) blocks unconditionally only if it is a carried-forward gap (Step 0's `gaps:`) or the flagged file was git-modified since the prior `verified:` timestamp (fail closed: unresolvable history counts as modified). Otherwise it predates the gap-closure round unflagged and needs deterministic evidence — a named test run red, or another
|
|
424
|
+
**Re-verification evidence gate (#3304):** in re-verification mode, a 🛑 Blocker other than an unresolved debt marker (always self-evidencing) blocks unconditionally only if it is a carried-forward gap (Step 0's `gaps:`) or the flagged file was git-modified since the prior `verified:` timestamp (fail closed: unresolvable history counts as modified). Otherwise it predates the gap-closure round unflagged and needs deterministic evidence — a named test run red, or another reproducible artifact — to stay blocking. Algorithm: @~/.claude/gsd-core/references/verifier-evidence-gate.md. Unevidenced → 📋 Advisory: record in `advisory:` frontmatter, exclude from Step 9 Rule 1, never revert a completed must-have.
|
|
415
425
|
|
|
416
426
|
Categorize: 🛑 Blocker (prevents goal or unresolved debt marker) | ⚠️ Warning (incomplete) | ℹ️ Info (notable) | 📋 Advisory (re-verification only — new-scope, unevidenced; see above)
|
|
417
427
|
|
|
@@ -554,7 +564,7 @@ Classify status using this decision tree IN ORDER (most restrictive first):
|
|
|
554
564
|
|
|
555
565
|
**A ⚠️ PRESENT_BEHAVIOR_UNVERIFIED truth is never FAILED and never VERIFIED.** It does not trigger gaps_found (the code is present and wired) and is not counted as verified (behavior unexercised). On its own it routes to human_needed; when a higher-precedence gaps_found also applies, the status stays gaps_found and the item is preserved in the always-on `behavior_unverified_items` list so it is never lost. Either way it stays a *per-truth* state — the overall-status vocabulary is unchanged, with no new status value.
|
|
556
566
|
|
|
557
|
-
> **Shared status seam**: the status vocabulary (`passed`, `gaps_found`, `human_needed`
|
|
567
|
+
> **Shared status seam**: the status vocabulary (`passed`, `gaps_found`, `human_needed` — the writer subset of the closed `VERIFICATION_STATUS` enum) and the per-status routing are owned by `src/verification.cts` via `gsd_run query verification.status`. Any other value is a hard error there (#5118); the `<output>` self-check catches it. This agent is the single emitter of the frontmatter status field; consumers (ship.md, execute-phase.md) read routing from that query instead of re-deriving it.
|
|
558
568
|
|
|
559
569
|
**Score (presence- vs behavior-verified split):**
|
|
560
570
|
|
|
@@ -654,7 +664,7 @@ Deferred items are informational only — they do not require closure plans.
|
|
|
654
664
|
USER_STORY_VALID=$(gsd_run query user-story.validate --story "$PHASE_GOAL" --pick valid)
|
|
655
665
|
```
|
|
656
666
|
|
|
657
|
-
If `valid != true`, refuse to verify. Surface the discrepancy and ask the user to run `/gsd
|
|
667
|
+
If `valid != true`, refuse to verify. Surface the discrepancy and ask the user to run `/gsd:mvp-phase ${PHASE}` to set a proper User Story goal. The verb owns the canonical regex `/^As a .+, I want to .+, so that .+\.$/` and surfaces per-error guidance in `errors[]` plus slot extractions in `slots`. Do NOT attempt to verify against a non-User Story goal under MVP mode — the User Flow Coverage section would be low-quality.
|
|
658
668
|
|
|
659
669
|
**Mode is all-or-nothing per phase** (PRD decision Q1, inherited from Phase 1). The MVP Mode Verification rules apply to the whole phase or not at all.
|
|
660
670
|
|
|
@@ -668,7 +678,7 @@ If `valid != true`, refuse to verify. Surface the discrepancy and ask the user t
|
|
|
668
678
|
|
|
669
679
|
**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation.
|
|
670
680
|
|
|
671
|
-
**#4155:**
|
|
681
|
+
**#4155 / #5095:** the fingerprint command adds the phase's own PLAN/SUMMARY files automatically (+superseded, nested `plans/`) and never counts the report itself — list only the changed implementation files (and any other evidence), ROOT-relative; planning-root docs are inert (#4623). `gsd_run query verification.fingerprint {phaseDir} {file}...`, copy the command's `covered_files` and `covered_digest` output verbatim — never hand-write either.
|
|
672
682
|
|
|
673
683
|
Create `.planning/phases/{phase_dir}/{phase_num}-VERIFICATION.md`:
|
|
674
684
|
|
|
@@ -679,7 +689,7 @@ verified: YYYY-MM-DDTHH:MM:SSZ
|
|
|
679
689
|
status: passed | gaps_found | human_needed
|
|
680
690
|
score: N/M must-haves verified
|
|
681
691
|
covered_files: [...]
|
|
682
|
-
covered_digest: "
|
|
692
|
+
covered_digest: "v3:sha256:..."
|
|
683
693
|
behavior_unverified: 0 # Count of ⚠️ PRESENT_BEHAVIOR_UNVERIFIED truths (present + wired, behavior not exercised); each is detailed in behavior_unverified_items below (and in human_verification when status is human_needed)
|
|
684
694
|
overrides_applied: 0 # Count of PASSED (override) items included in score
|
|
685
695
|
overrides: # Only if overrides exist — carried forward or newly added
|
|
@@ -815,6 +825,19 @@ _Verified: {timestamp}_
|
|
|
815
825
|
_Verifier: Claude (gsd-verifier)_
|
|
816
826
|
```
|
|
817
827
|
|
|
828
|
+
## Self-check the written status (#5118)
|
|
829
|
+
|
|
830
|
+
After writing VERIFICATION.md, read it back through its owner:
|
|
831
|
+
|
|
832
|
+
```bash
|
|
833
|
+
gsd_run query verification.status "{phaseDir}" --pick status
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
Gate on the exit code only. Non-zero is the write-time hard error (stderr names the value and the
|
|
837
|
+
accepted `passed | gaps_found | human_needed`): fix the frontmatter `status` to the Step 9 decision
|
|
838
|
+
and re-run before returning. A printed value that differs from yours (e.g. `stale`) is routing,
|
|
839
|
+
not an error — never edit `status` to match it.
|
|
840
|
+
|
|
818
841
|
## Return to Orchestrator
|
|
819
842
|
|
|
820
843
|
**DO NOT COMMIT.** The orchestrator bundles VERIFICATION.md with other phase artifacts.
|