@opengsd/gsd-core 1.11.0 → 1.12.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/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +1 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +17 -9
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +0 -1
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +3 -1
- package/agents/gsd-plan-checker.md +15 -55
- package/agents/gsd-planner.md +6 -4
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-verifier.md +1 -1
- package/bin/install.js +609 -134
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/quick.md +8 -4
- package/gsd-core/bin/gsd-tools.cjs +567 -51
- package/gsd-core/bin/lib/active-workstream-store.cjs +8 -0
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +162 -0
- package/gsd-core/bin/lib/api-coverage.cjs +30 -9
- package/gsd-core/bin/lib/artifacts.cjs +2 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +30 -11
- package/gsd-core/bin/lib/audit.cjs +163 -41
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +336 -95
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-validator.cjs +205 -18
- package/gsd-core/bin/lib/check-command-router.cjs +145 -5
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +410 -4
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +543 -44
- package/gsd-core/bin/lib/complexity-trigger.cjs +26 -6
- package/gsd-core/bin/lib/config-loader.cjs +118 -29
- package/gsd-core/bin/lib/config.cjs +92 -2
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +84 -7
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/frontmatter.cjs +840 -305
- package/gsd-core/bin/lib/gap-checker.cjs +27 -3
- package/gsd-core/bin/lib/git-base-branch.cjs +174 -39
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +7 -3
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +6 -3
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +22 -8
- package/gsd-core/bin/lib/health-diagnostic.cjs +23 -3
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +120 -41
- package/gsd-core/bin/lib/install-engine.cjs +68 -3
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +33 -1
- package/gsd-core/bin/lib/install-profiles.cjs +78 -4
- package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +10 -7
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +160 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-table.cjs +52 -4
- package/gsd-core/bin/lib/milestone.cjs +90 -5
- package/gsd-core/bin/lib/model-catalog.cjs +177 -19
- package/gsd-core/bin/lib/model-resolver.cjs +10 -28
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/phase-estimation.cjs +17 -8
- package/gsd-core/bin/lib/phase-id.cjs +70 -4
- package/gsd-core/bin/lib/phase-lifecycle.cjs +24 -16
- package/gsd-core/bin/lib/phase-locator.cjs +138 -17
- package/gsd-core/bin/lib/phase.cjs +405 -84
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-scan.cjs +13 -2
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -14
- package/gsd-core/bin/lib/planning-workspace.cjs +56 -0
- package/gsd-core/bin/lib/probe-core.cjs +4 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +71 -45
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +9 -9
- package/gsd-core/bin/lib/roadmap-command-router.cjs +45 -31
- package/gsd-core/bin/lib/roadmap-parser.cjs +79 -16
- package/gsd-core/bin/lib/roadmap.cjs +74 -19
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +96 -8
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +34 -1
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +287 -55
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-slash.cjs +72 -2
- package/gsd-core/bin/lib/shell-command-projection.cjs +71 -8
- package/gsd-core/bin/lib/smart-entry.cjs +12 -22
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +47 -18
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +186 -0
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +517 -101
- package/gsd-core/bin/lib/state.cjs +946 -163
- package/gsd-core/bin/lib/surface.cjs +10 -2
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- package/gsd-core/bin/lib/uat-predicate.cjs +58 -20
- package/gsd-core/bin/lib/uat.cjs +1376 -125
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-safety-gate.cjs +37 -7
- package/gsd-core/bin/lib/unusable-input.cjs +13 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/vendor/README.md +43 -5
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/verification.cjs +14 -1
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +95 -40
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +177 -21
- package/gsd-core/bin/shared/config-defaults.manifest.json +7 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +3 -2
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +37 -19
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +1 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +9 -12
- package/gsd-core/references/execute-phase-wave-guard.md +11 -9
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +3 -3
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +22 -0
- package/gsd-core/references/model-profiles.md +1 -1
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +37 -8
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +2 -2
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +11 -11
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/phase-prompt.md +3 -0
- package/gsd-core/templates/state.md +7 -0
- 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 +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +4 -9
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +10 -26
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +2 -2
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +1 -1
- package/gsd-core/workflows/code-review-fix.md +1 -1
- package/gsd-core/workflows/code-review.md +121 -40
- package/gsd-core/workflows/complete-milestone.md +15 -10
- package/gsd-core/workflows/debug.md +5 -3
- package/gsd-core/workflows/diagnose-issues.md +12 -6
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +3 -7
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +2 -2
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +1 -1
- package/gsd-core/workflows/eval-review.md +4 -9
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +113 -11
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +22 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +38 -54
- package/gsd-core/workflows/execute-plan.md +17 -12
- package/gsd-core/workflows/explore.md +1 -1
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +2 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +3 -6
- package/gsd-core/workflows/import.md +14 -11
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +44 -11
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +2 -2
- package/gsd-core/workflows/new-milestone.md +9 -21
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +12 -26
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +2 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +121 -42
- package/gsd-core/workflows/plan-review-convergence.md +46 -9
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +27 -12
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -3
- package/gsd-core/workflows/quick/steps/quick-verification.md +2 -4
- package/gsd-core/workflows/quick/steps/research-phase.md +2 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +20 -29
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +193 -15
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +2 -2
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +3 -5
- package/gsd-core/workflows/ship.md +12 -6
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +23 -1
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +1 -1
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +5 -5
- package/gsd-core/workflows/ui-phase.md +10 -16
- package/gsd-core/workflows/ui-review.md +6 -10
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +6 -10
- package/gsd-core/workflows/validate-phase.md +2 -2
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +57 -18
- package/hooks/dist/gsd-agent-isolation-guard.js +77 -38
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +3 -1
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +28 -23
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -1
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +16 -7
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +17 -8
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +215 -26
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +34 -16
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +77 -38
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +3 -1
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +28 -23
- package/hooks/gsd-cursor-subagent-stop.js +3 -1
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +16 -7
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +17 -8
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +215 -26
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +34 -16
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +12 -7
- package/scripts/base64-scan.sh +74 -12
- package/scripts/build-hooks.js +5 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +45 -12
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-capability-registry.cjs +8 -6
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-loop-host-contract.cjs +134 -1
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +32 -2
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-docs-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +4 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-health-diagnostic-rule-table.cjs +65 -8
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +21 -8
- package/scripts/lint-planning-prompt-drift.cjs +38 -1
- package/scripts/lint-removed-but-needed.cjs +184 -16
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-write-path-drift.cjs +337 -432
- package/scripts/lint-test-file-count.allowlist.json +122 -4
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +51 -64
- package/scripts/lint-vendored-deps.cjs +208 -35
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/prompt-injection-scan.sh +75 -14
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +22 -3
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-quick/SKILL.md +8 -4
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -109
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/state-write-path-drift-baseline.json +0 -19
|
@@ -37,8 +37,8 @@ echo "$ARGUMENTS" | grep -qE '\-\-ws\s+\S+' && GSD_WS=$(echo "$ARGUMENTS" | grep
|
|
|
37
37
|
## 1.5. Config Gate (feature disabled by default)
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
|
-
_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}"; if [ -f "$
|
|
41
|
-
CONVERGENCE_ENABLED=$(gsd_run query config-get workflow.plan_review_convergence 2>/dev/null || echo "false")
|
|
40
|
+
_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
|
|
41
|
+
CONVERGENCE_ENABLED=$(gsd_run query config-get workflow.plan_review_convergence --raw 2>/dev/null || echo "false")
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
**If `CONVERGENCE_ENABLED` is not `"true"`:** Display and exit:
|
|
@@ -134,9 +134,7 @@ PHASE_INFO=$(gsd_run roadmap get-phase "${PHASE}")
|
|
|
134
134
|
Display startup banner:
|
|
135
135
|
|
|
136
136
|
```text
|
|
137
|
-
|
|
138
|
-
GSD ► PLAN CONVERGENCE — Phase {phase_number}
|
|
139
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
137
|
+
### GSD ► PLAN CONVERGENCE — Phase {phase_number}
|
|
140
138
|
|
|
141
139
|
Reviewers: {REVIEWER_DISPLAY}
|
|
142
140
|
Max cycles: {MAX_CYCLES}
|
|
@@ -200,9 +198,50 @@ Your final response MUST include a machine-readable line of exactly this form:
|
|
|
200
198
|
Where <N> is the integer count of HIGH-severity concerns that REMAIN UNRESOLVED in this cycle's findings.
|
|
201
199
|
Where <M> is the integer count of actionable MEDIUM/LOW concerns that REMAIN UNRESOLVED because the latest PLAN.md files do not yet incorporate them or explicitly defer/reject them.
|
|
202
200
|
|
|
201
|
+
Consensus gate (applies to NEWLY RAISED HIGHs only; evaluate before the counting rules below):
|
|
202
|
+
This gate engages ONLY when 2 or more reviewers actually ran and produced a review section this
|
|
203
|
+
cycle. With exactly one reviewer, skip this entire gate — a single reviewer's HIGH always counts,
|
|
204
|
+
exactly as before.
|
|
205
|
+
|
|
206
|
+
Classify each newly raised HIGH by what the claim ASSERTS, not by whether it happens to contain a
|
|
207
|
+
file:line citation:
|
|
208
|
+
- EXISTENCE-CLASS — asserts that a named symbol, file, path, flag, commit, or ID exists,
|
|
209
|
+
is absent, or says something specific ("X does not exist", "the plan cites Y which is missing",
|
|
210
|
+
"file Z contains Q").
|
|
211
|
+
- JUDGMENT-CLASS — asserts a design or correctness property ("no idempotency on retried writes",
|
|
212
|
+
"race between A and B", "missing rate limit"). A judgment-class HIGH stays judgment-class even
|
|
213
|
+
when it cites a file for context.
|
|
214
|
+
|
|
215
|
+
A HIGH raised by 2+ reviewers is corroborated and always counts.
|
|
216
|
+
|
|
217
|
+
For a HIGH raised by exactly ONE reviewer:
|
|
218
|
+
- EXISTENCE-CLASS — counts only if the source-grounding pass independently confirms it against
|
|
219
|
+
real project source, or another reviewer raised the same or a materially overlapping concern
|
|
220
|
+
(i.e. it lands in REVIEWS.md's Consensus Summary "Agreed Concerns").
|
|
221
|
+
- JUDGMENT-CLASS — counts UNLESS that reviewer's own section OPENS with an evidence-quality
|
|
222
|
+
discount marker blockquote: `[reviewed-without-source-citations]` or
|
|
223
|
+
`[reviewed-without-repo-access]`, or the reviewer is a diff-only lane (CodeRabbit). The marker
|
|
224
|
+
must be the LEADING blockquote of that reviewer's section — a review that merely quotes a
|
|
225
|
+
marker while discussing it is NOT marked. Corroboration by another reviewer overrides the
|
|
226
|
+
marker and the HIGH counts.
|
|
227
|
+
|
|
228
|
+
Judgment-class findings are deliberately NOT subject to corroboration. Different reviewers catch
|
|
229
|
+
materially different classes of issue, so requiring two of them to independently raise the same
|
|
230
|
+
architectural concern would suppress exactly the findings a multi-reviewer setup exists to surface.
|
|
231
|
+
|
|
232
|
+
FAIL OPEN: if EVERY reviewer that ran this cycle carries a discount marker, this gate does not
|
|
233
|
+
apply at all — count as if it were absent. A gate must never manufacture convergence out of a
|
|
234
|
+
cycle in which nothing was verified.
|
|
235
|
+
|
|
236
|
+
A HIGH suppressed by this gate is still listed under "## Current HIGH Concerns", tagged
|
|
237
|
+
`(single-reviewer, unconfirmed)`. It is excluded from current_high only — never silently dropped,
|
|
238
|
+
and never removed from the report.
|
|
239
|
+
|
|
240
|
+
This gate governs current_high only. current_actionable is unaffected.
|
|
241
|
+
|
|
203
242
|
Counting rules:
|
|
204
243
|
INCLUDE in the count:
|
|
205
|
-
- Newly raised HIGHs in this cycle
|
|
244
|
+
- Newly raised HIGHs in this cycle (subject to the consensus gate above)
|
|
206
245
|
- PARTIALLY RESOLVED HIGHs: concern acknowledged and a mitigation is in progress, but not yet verified/completed
|
|
207
246
|
- Previously raised HIGHs that are still unresolved
|
|
208
247
|
|
|
@@ -359,9 +398,7 @@ gsd_run state planned-phase --phase "${PHASE}" --name "${phase_name}" --plans "$
|
|
|
359
398
|
|
|
360
399
|
Display:
|
|
361
400
|
```text
|
|
362
|
-
|
|
363
|
-
GSD ► CONVERGENCE COMPLETE ✓
|
|
364
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
401
|
+
### GSD ► CONVERGENCE COMPLETE ✓
|
|
365
402
|
|
|
366
403
|
Phase {phase_number} converged in {cycle} cycle(s).
|
|
367
404
|
No HIGH concerns remaining.
|
|
@@ -135,8 +135,8 @@ Store relevant file paths as `$BREADCRUMBS`.
|
|
|
135
135
|
|
|
136
136
|
<step name="commit-seed">
|
|
137
137
|
```bash
|
|
138
|
-
_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}"; if [ -f "$
|
|
139
|
-
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --default "" 2>/dev/null || echo "")
|
|
138
|
+
_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
|
|
139
|
+
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --raw --default "" 2>/dev/null || echo "")
|
|
140
140
|
gsd_run query commit "docs: plant seed — {$IDEA}" --files .planning/seeds/SEED-{PADDED}-{slug}.md
|
|
141
141
|
```
|
|
142
142
|
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
<purpose>
|
|
2
|
-
Create a clean branch for pull requests by filtering
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
Create a clean branch for pull requests by filtering .planning/ paths out of the
|
|
3
|
+
cherry-picked history. Two modes, selected by the `planning.pr_strict` config key:
|
|
4
|
+
|
|
5
|
+
- **default** (`planning.pr_strict: false`) — the PR branch contains code changes and
|
|
6
|
+
structural planning state. Reviewers don't see GSD transient artifacts (PLAN.md,
|
|
7
|
+
SUMMARY.md, CONTEXT.md, RESEARCH.md, etc.), but milestone archives, STATE.md,
|
|
8
|
+
ROADMAP.md, and PROJECT.md changes are preserved.
|
|
9
|
+
- **strict** (`planning.pr_strict: true`) — *every* .planning/ path is filtered out,
|
|
10
|
+
structural files included. This is what makes `planning.commit_docs: true` safe for a
|
|
11
|
+
project that versions its planning tree locally but publishes none of it: planning state
|
|
12
|
+
keeps real git history (so `/gsd:undo` and revert paths have something to restore) and
|
|
13
|
+
executor worktrees still find their PLAN.md, while the public PR carries nothing from
|
|
14
|
+
`.planning/`.
|
|
6
15
|
|
|
7
16
|
Uses git cherry-pick with path filtering to rebuild a clean history.
|
|
8
17
|
</purpose>
|
|
@@ -14,7 +23,7 @@ Parse `$ARGUMENTS` for target branch. If no argument is supplied, detect the
|
|
|
14
23
|
default branch via the single resolver (#1146).
|
|
15
24
|
|
|
16
25
|
```bash
|
|
17
|
-
_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}"; if [ -f "$
|
|
26
|
+
_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
|
|
18
27
|
CURRENT_BRANCH=$(git branch --show-current)
|
|
19
28
|
TARGET=${1:-$(gsd_run query git.base-branch)}
|
|
20
29
|
```
|
|
@@ -22,6 +31,7 @@ TARGET=${1:-$(gsd_run query git.base-branch)}
|
|
|
22
31
|
Check preconditions:
|
|
23
32
|
- Must be on a feature branch (not main/master)
|
|
24
33
|
- Must have commits ahead of target
|
|
34
|
+
- Working tree must be clean
|
|
25
35
|
|
|
26
36
|
```bash
|
|
27
37
|
AHEAD=$(git rev-list --count "$TARGET".."$CURRENT_BRANCH" 2>/dev/null)
|
|
@@ -29,17 +39,36 @@ if [ "$AHEAD" = "0" ]; then
|
|
|
29
39
|
echo "No commits ahead of $TARGET — nothing to filter."
|
|
30
40
|
exit 0
|
|
31
41
|
fi
|
|
42
|
+
|
|
43
|
+
# The filter below removes files from the index AND the working tree before each
|
|
44
|
+
# commit lands, and this command switches branches underneath the user's own
|
|
45
|
+
# checkout. An uncommitted edit to a tracked file would be destroyed by that, and
|
|
46
|
+
# git cherry-pick refuses to run against a dirty tree anyway — so fail here, where
|
|
47
|
+
# the message is legible, rather than midway through the cherry-pick loop.
|
|
48
|
+
DIRTY=$(git status --porcelain --untracked-files=no)
|
|
49
|
+
if [ -n "$DIRTY" ]; then
|
|
50
|
+
echo "Working tree has uncommitted changes — commit or stash them first:" >&2
|
|
51
|
+
echo "$DIRTY" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Resolve the filter mode from config. A non-zero exit or an unset key means the default
|
|
57
|
+
mode; only the literal string `true` selects strict.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
PR_STRICT=$(gsd_run query config-get planning.pr_strict --raw 2>/dev/null)
|
|
61
|
+
if [ "$PR_STRICT" = "true" ]; then PR_MODE="strict"; else PR_MODE="default"; PR_STRICT="false"; fi
|
|
32
62
|
```
|
|
33
63
|
|
|
34
64
|
Display:
|
|
35
65
|
```
|
|
36
|
-
|
|
37
|
-
GSD ► PR BRANCH
|
|
38
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
66
|
+
### GSD ► PR BRANCH
|
|
39
67
|
|
|
40
68
|
Branch: {CURRENT_BRANCH}
|
|
41
69
|
Target: {TARGET}
|
|
42
70
|
Commits: {AHEAD} ahead
|
|
71
|
+
Mode: {PR_MODE} (planning.pr_strict={PR_STRICT})
|
|
43
72
|
```
|
|
44
73
|
</step>
|
|
45
74
|
|
|
@@ -207,47 +236,62 @@ Classify commits:
|
|
|
207
236
|
git log --oneline "$TARGET".."$CURRENT_BRANCH" --no-merges
|
|
208
237
|
```
|
|
209
238
|
|
|
210
|
-
**
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
239
|
+
**Canonical path declarations.** These two lines are the single source of truth for the
|
|
240
|
+
whole command. `create_pr_branch` derives *which paths it removes* from them, and `verify`
|
|
241
|
+
derives *which paths must not appear* from the same two lines — so the two steps cannot
|
|
242
|
+
disagree about what the filter promised. Declare them exactly once; do not restate either
|
|
243
|
+
list anywhere else in this file.
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# Transient planning subdirectories — reviewer noise (PLAN.md, SUMMARY.md, CONTEXT.md,
|
|
247
|
+
# RESEARCH.md, and friends). Filtered out in BOTH modes.
|
|
248
|
+
TRANSIENT_DIRS="phases quick research threads todos debug seeds codebase ui-reviews"
|
|
249
|
+
|
|
250
|
+
# Structural planning files — repository planning state. Preserved in default mode,
|
|
251
|
+
# filtered out in strict mode. Anchored on both alternatives so `.planning/STATEX.md`
|
|
252
|
+
# and `.planning/STATE.md.bak` are NOT treated as structural.
|
|
253
|
+
STRUCTURAL_RE="^\.planning/(STATE|ROADMAP|MILESTONES|PROJECT|REQUIREMENTS)\.md$|^\.planning/milestones/"
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Derive the mode's two projections — `FILTER_PATHS` (what `create_pr_branch` removes from
|
|
257
|
+
each cherry-picked commit) and `FORBIDDEN_RE` (what `verify` asserts is absent):
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
if [ "$PR_STRICT" = "true" ]; then
|
|
261
|
+
FILTER_PATHS=".planning/"
|
|
262
|
+
FORBIDDEN_RE="^\.planning/"
|
|
263
|
+
else
|
|
264
|
+
FILTER_PATHS=$(for d in $TRANSIENT_DIRS; do printf '.planning/%s/ ' "$d"; done)
|
|
265
|
+
FORBIDDEN_RE="^\.planning/($(echo "$TRANSIENT_DIRS" | tr ' ' '|'))/"
|
|
266
|
+
fi
|
|
267
|
+
```
|
|
228
268
|
|
|
229
269
|
For each commit, check what it touches:
|
|
230
270
|
|
|
231
271
|
```bash
|
|
232
272
|
# For each commit hash
|
|
233
273
|
FILES=$(git diff-tree --no-commit-id --name-only -r $HASH)
|
|
234
|
-
NON_PLANNING=$(echo "$FILES" | grep -v "^\.planning/"
|
|
235
|
-
STRUCTURAL=$(echo "$FILES" | grep -
|
|
236
|
-
TRANSIENT_ONLY=$(echo "$FILES" | grep "^\.planning/" | grep -vE "^\.planning/(STATE|ROADMAP|MILESTONES|PROJECT|REQUIREMENTS)\.md|^\.planning/milestones/" | wc -l)
|
|
274
|
+
NON_PLANNING=$(echo "$FILES" | grep -c -v "^\.planning/" || true)
|
|
275
|
+
STRUCTURAL=$(echo "$FILES" | grep -Ec "$STRUCTURAL_RE" || true)
|
|
237
276
|
```
|
|
238
277
|
|
|
239
278
|
Classify:
|
|
240
|
-
- **Code commits**:
|
|
241
|
-
- **
|
|
242
|
-
|
|
243
|
-
- **
|
|
279
|
+
- **Code commits**: touch at least one non-`.planning/` file → INCLUDE (both modes)
|
|
280
|
+
- **Mixed commits**: touch code + any planning files → INCLUDE (both modes; the planning
|
|
281
|
+
paths are filtered out by `create_pr_branch`, not the commit)
|
|
282
|
+
- **Structural planning commits**: touch only structural `.planning/` files → INCLUDE in
|
|
283
|
+
**default** mode; **EXCLUDE** in strict mode, which has no structural carve-out
|
|
284
|
+
- **Transient planning commits**: touch only `.planning/` paths that are not structural →
|
|
285
|
+
EXCLUDE (both modes)
|
|
286
|
+
|
|
287
|
+
In strict mode this collapses to a single rule: `NON_PLANNING > 0` → INCLUDE, else EXCLUDE.
|
|
244
288
|
|
|
245
289
|
Display analysis:
|
|
246
290
|
```
|
|
247
|
-
Commits to include: {N} (code changes + structural planning)
|
|
248
|
-
Commits to exclude: {N} (
|
|
249
|
-
Mixed commits: {N} (code + planning — included)
|
|
250
|
-
Structural planning commits: {N} (
|
|
291
|
+
Commits to include: {N} (code changes{, + structural planning — default mode only})
|
|
292
|
+
Commits to exclude: {N} (planning-only)
|
|
293
|
+
Mixed commits: {N} (code + planning — included, planning paths filtered)
|
|
294
|
+
Structural planning commits: {N} ({included|excluded — strict mode})
|
|
251
295
|
```
|
|
252
296
|
</step>
|
|
253
297
|
|
|
@@ -259,18 +303,69 @@ PR_BRANCH="${CURRENT_BRANCH}-pr"
|
|
|
259
303
|
git checkout -b "$PR_BRANCH" "$TARGET"
|
|
260
304
|
```
|
|
261
305
|
|
|
262
|
-
Cherry-pick
|
|
306
|
+
Cherry-pick the included commits, in order, filtering `$FILTER_PATHS` out of each one.
|
|
307
|
+
|
|
308
|
+
The filter forces every filtered path back to **exactly what the PR branch's HEAD already
|
|
309
|
+
has**, in both the index and the working tree. That is stricter than simply un-staging, and
|
|
310
|
+
both halves matter:
|
|
311
|
+
|
|
312
|
+
- `git rm -r -f --ignore-unmatch` clears the index entry (including an unmerged one) and
|
|
313
|
+
removes the file the pick just wrote. It only ever touches paths that are in the index, so
|
|
314
|
+
a genuinely untracked planning file of the user's is never harmed.
|
|
315
|
+
- `git checkout HEAD --` then restores whatever the target branch legitimately tracks at
|
|
316
|
+
those paths. **Without this, un-staging a path the target branch already tracks records a
|
|
317
|
+
DELETION** — the generated PR would remove the base branch's planning files. In strict mode
|
|
318
|
+
that would be the base's entire `.planning/` tree.
|
|
319
|
+
|
|
320
|
+
Leaving the filtered file behind in the working tree is not an option either: a later commit
|
|
321
|
+
touching the same planning path makes `git cherry-pick` abort with *"untracked working tree
|
|
322
|
+
files would be overwritten by merge"*, and every remaining commit is silently dropped.
|
|
263
323
|
|
|
264
324
|
```bash
|
|
265
|
-
for HASH in $
|
|
266
|
-
|
|
267
|
-
#
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
for
|
|
271
|
-
git rm -r --
|
|
325
|
+
for HASH in $INCLUDED_COMMITS; do
|
|
326
|
+
# A modify/delete conflict on a filtered path is EXPECTED and is resolved below — the
|
|
327
|
+
# filtered path is absent from HEAD by construction. Do not treat it as a failure here.
|
|
328
|
+
git cherry-pick --no-commit "$HASH" || true
|
|
329
|
+
|
|
330
|
+
for P in $FILTER_PATHS; do
|
|
331
|
+
git rm -r -f -q --ignore-unmatch -- "$P" 2>/dev/null || true
|
|
332
|
+
git checkout HEAD -- "$P" 2>/dev/null || true
|
|
272
333
|
done
|
|
273
|
-
|
|
334
|
+
|
|
335
|
+
# Anything still unmerged is a REAL conflict, outside the filter. Halt — do not
|
|
336
|
+
# improvise a resolution and do not continue, which would drop the rest of the queue.
|
|
337
|
+
# Unwind first: this loop runs in the user's own checkout, so exiting mid-sequence
|
|
338
|
+
# would strand them on a half-built branch with cherry-pick state still live.
|
|
339
|
+
if [ -n "$(git diff --name-only --diff-filter=U)" ]; then
|
|
340
|
+
echo "Conflict outside the .planning/ filter while picking $HASH:" >&2
|
|
341
|
+
git diff --name-only --diff-filter=U >&2
|
|
342
|
+
# Order matters. `--quit` drops the sequencer state but leaves the unmerged index
|
|
343
|
+
# in place, and an unmerged index makes `git checkout` refuse — so reset first.
|
|
344
|
+
# $PR_BRANCH is disposable and every commit on it was cherry-picked, and the
|
|
345
|
+
# clean-tree precondition guarantees the user had nothing uncommitted, so a hard
|
|
346
|
+
# reset here cannot destroy anything of theirs.
|
|
347
|
+
git cherry-pick --quit 2>/dev/null || true
|
|
348
|
+
git reset -q --hard HEAD
|
|
349
|
+
if git checkout -q "$CURRENT_BRANCH"; then
|
|
350
|
+
git branch -q -D "$PR_BRANCH" 2>/dev/null || true
|
|
351
|
+
echo "Restored $CURRENT_BRANCH and removed the partial $PR_BRANCH." >&2
|
|
352
|
+
else
|
|
353
|
+
# Never claim a restore that did not happen — say exactly where they are.
|
|
354
|
+
echo "Could not return to $CURRENT_BRANCH; you are still on $PR_BRANCH." >&2
|
|
355
|
+
echo "Run: git checkout $CURRENT_BRANCH && git branch -D $PR_BRANCH" >&2
|
|
356
|
+
fi
|
|
357
|
+
echo "Resolve the conflict against $TARGET, then re-run /gsd:pr-branch." >&2
|
|
358
|
+
exit 1
|
|
359
|
+
fi
|
|
360
|
+
|
|
361
|
+
# Nothing left after filtering (possible when a pick's only surviving content was
|
|
362
|
+
# planning state): clear the sequencer rather than failing on an empty commit.
|
|
363
|
+
if git diff --cached --quiet; then
|
|
364
|
+
git cherry-pick --quit 2>/dev/null || true
|
|
365
|
+
continue
|
|
366
|
+
fi
|
|
367
|
+
|
|
368
|
+
git commit -q -C "$HASH"
|
|
274
369
|
done
|
|
275
370
|
```
|
|
276
371
|
|
|
@@ -281,20 +376,50 @@ git checkout "$CURRENT_BRANCH"
|
|
|
281
376
|
</step>
|
|
282
377
|
|
|
283
378
|
<step name="verify">
|
|
379
|
+
Assert against the **active mode's** contract — `$FORBIDDEN_RE`, the same declaration
|
|
380
|
+
`create_pr_branch` filtered on. Counting every `.planning/` path unconditionally would
|
|
381
|
+
contradict default mode, which is specified to preserve structural files: a correct run
|
|
382
|
+
would report itself as failed on every phase that touched STATE.md, which is every phase.
|
|
383
|
+
|
|
284
384
|
```bash
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
385
|
+
DIFF_PATHS=$(git diff --name-only "$TARGET".."$PR_BRANCH")
|
|
386
|
+
FORBIDDEN=$(echo "$DIFF_PATHS" | grep -Ec "$FORBIDDEN_RE" || true)
|
|
387
|
+
PLANNING_TOTAL=$(echo "$DIFF_PATHS" | grep -c "^\.planning/" || true)
|
|
388
|
+
ALLOWED=$((PLANNING_TOTAL - FORBIDDEN))
|
|
389
|
+
TOTAL_FILES=$(echo "$DIFF_PATHS" | grep -c . || true)
|
|
288
390
|
PR_COMMITS=$(git rev-list --count "$TARGET".."$PR_BRANCH")
|
|
391
|
+
|
|
392
|
+
# #3679: a DELETED planning path is never legitimate — this workflow only ever
|
|
393
|
+
# excludes content a cherry-picked commit ADDED; pre-existing target-tracked
|
|
394
|
+
# planning files must survive byte-identical. Name-only counting cannot see
|
|
395
|
+
# status (a deleted structural/allowed path verifies clean there), so gate on
|
|
396
|
+
# deletions explicitly, across every planning category.
|
|
397
|
+
PLANNING_DELETIONS=$(git diff --name-status --no-renames "$TARGET".."$PR_BRANCH" | grep "^D" | grep -c "\.planning/" || true)
|
|
398
|
+
|
|
399
|
+
# Default mode preserves anything under .planning/ that is neither transient nor
|
|
400
|
+
# structural — config.json, intel/, workstreams/. That is deliberate and unchanged, but it
|
|
401
|
+
# must not be silent: report it so the user can choose strict mode knowingly.
|
|
402
|
+
OTHER=$(echo "$DIFF_PATHS" | grep "^\.planning/" | grep -Ev "$FORBIDDEN_RE" | grep -Ev "$STRUCTURAL_RE" || true)
|
|
289
403
|
```
|
|
290
404
|
|
|
405
|
+
`$FORBIDDEN` is the pass/fail number — it must be `0`. A non-zero value means the filter
|
|
406
|
+
did not do what this mode promised; report it and do not tell the user to push.
|
|
407
|
+
|
|
408
|
+
`$PLANNING_DELETIONS` is a second hard gate (#3679) — it must also be `0`. A non-zero
|
|
409
|
+
value means the PR branch would DELETE planning files the target branch tracks
|
|
410
|
+
(`git diff --name-status --no-renames "$TARGET".."$PR_BRANCH" | grep "^D" | grep "\.planning/"` lists
|
|
411
|
+
them). That is data loss, not filtering — report it, do not tell the user to push, and
|
|
412
|
+
rebuild the branch.
|
|
413
|
+
|
|
291
414
|
Display results:
|
|
292
415
|
```
|
|
293
416
|
✅ PR branch created: {PR_BRANCH}
|
|
294
417
|
|
|
295
418
|
Original: {AHEAD} commits, {ORIGINAL_FILES} files
|
|
296
419
|
PR branch: {PR_COMMITS} commits, {TOTAL_FILES} files
|
|
297
|
-
|
|
420
|
+
Mode: {PR_MODE}
|
|
421
|
+
Planning paths in diff: {PLANNING_TOTAL} (allowed {ALLOWED}, forbidden {FORBIDDEN} — must be 0)
|
|
422
|
+
Planning deletions: {PLANNING_DELETIONS} (must be 0 — #3679)
|
|
298
423
|
|
|
299
424
|
Next steps:
|
|
300
425
|
git push origin {PR_BRANCH}
|
|
@@ -302,14 +427,25 @@ Next steps:
|
|
|
302
427
|
|
|
303
428
|
Or use /gsd:ship to create the PR automatically.
|
|
304
429
|
```
|
|
430
|
+
|
|
431
|
+
When `$OTHER` is non-empty (default mode only — strict forbids all of it), append:
|
|
432
|
+
```
|
|
433
|
+
ℹ️ These .planning/ paths are neither transient nor structural, so default mode keeps them:
|
|
434
|
+
{OTHER}
|
|
435
|
+
Set `planning.pr_strict: true` to keep every .planning/ path out of the PR branch.
|
|
436
|
+
```
|
|
305
437
|
</step>
|
|
306
438
|
|
|
307
439
|
</process>
|
|
308
440
|
|
|
309
441
|
<success_criteria>
|
|
442
|
+
- [ ] Working tree was clean before the PR branch was created
|
|
310
443
|
- [ ] PR branch created from target
|
|
311
444
|
- [ ] Planning-only commits excluded
|
|
312
|
-
- [ ]
|
|
445
|
+
- [ ] Zero paths matching the active mode's `$FORBIDDEN_RE` in the PR branch diff —
|
|
446
|
+
strict: no `.planning/` path at all; default: none from `$TRANSIENT_DIRS`
|
|
447
|
+
- [ ] No `.planning/` path the target branch already tracked was deleted
|
|
448
|
+
- [ ] Every included commit landed — none dropped by a failed cherry-pick
|
|
313
449
|
- [ ] Commit messages preserved from original
|
|
314
450
|
- [ ] User shown next steps
|
|
315
451
|
</success_criteria>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<purpose>
|
|
2
2
|
Orchestrate the full developer profiling flow: consent, session analysis (or questionnaire fallback), profile generation, result display, and artifact creation.
|
|
3
3
|
|
|
4
|
-
This workflow wires Phase 1 (session pipeline) and Phase 2 (profiling engine) into a cohesive user-facing experience. All heavy lifting is done by existing `
|
|
4
|
+
This workflow wires Phase 1 (session pipeline) and Phase 2 (profiling engine) into a cohesive user-facing experience. All heavy lifting is done by existing `gsd_run query` handlers and the gsd-user-profiler agent -- this workflow orchestrates the sequence, handles branching, and provides the UX.
|
|
5
5
|
</purpose>
|
|
6
6
|
|
|
7
7
|
<required_reading>
|
|
@@ -15,13 +15,12 @@ Key references:
|
|
|
15
15
|
|
|
16
16
|
<process>
|
|
17
17
|
```bash
|
|
18
|
-
_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}"; if [ -f "$
|
|
19
|
-
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --default "" 2>/dev/null || echo "")
|
|
18
|
+
_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
|
|
19
|
+
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --raw --default "" 2>/dev/null || echo "")
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
**If `response_language` is set:** All user-facing questions, prompts, and explanations in this workflow MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
|
|
23
23
|
|
|
24
|
-
|
|
25
24
|
## 1. Initialize
|
|
26
25
|
|
|
27
26
|
Parse flags from $ARGUMENTS:
|
|
@@ -37,7 +36,6 @@ PROFILE_PATH="$HOME/.claude/gsd-core/USER-PROFILE.md"
|
|
|
37
36
|
|
|
38
37
|
**If profile exists AND --refresh NOT set AND --questionnaire NOT set:**
|
|
39
38
|
|
|
40
|
-
|
|
41
39
|
**Text mode (`workflow.text_mode: true` in config or `--text` flag):** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS` OR `text_mode` from init JSON is `true`. When TEXT_MODE is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available.
|
|
42
40
|
Use AskUserQuestion:
|
|
43
41
|
- header: "Existing Profile"
|
|
@@ -72,9 +70,7 @@ Continue to step 2.
|
|
|
72
70
|
Display consent screen:
|
|
73
71
|
|
|
74
72
|
```
|
|
75
|
-
|
|
76
|
-
GSD > PROFILE YOUR CODING STYLE
|
|
77
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
73
|
+
### GSD > PROFILE YOUR CODING STYLE
|
|
78
74
|
|
|
79
75
|
Claude starts every conversation generic. A profile teaches Claude
|
|
80
76
|
how YOU actually work -- not how you think you work.
|
|
@@ -166,9 +162,17 @@ Display: "✓ Sampled N messages from M projects"
|
|
|
166
162
|
|
|
167
163
|
Display: "◆ Analyzing patterns..."
|
|
168
164
|
|
|
165
|
+
```bash
|
|
166
|
+
PROFILER_MODEL=$(gsd_run query resolve-model gsd-user-profiler --raw)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
<!-- #2517 model-omit-on-inherit -->
|
|
170
|
+
|
|
171
|
+
> **Model omission (#2517).** Omit the `model` parameter entirely when the value it would carry (`PROFILER_MODEL`) is `"inherit"` or empty. An empty value 404s on runtimes without native tier aliases — the default on non-Claude runtimes. Omitting it inherits the orchestrator's model. See @gsd-core/references/model-profile-resolution.md.
|
|
172
|
+
|
|
169
173
|
**Spawn gsd-user-profiler agent using Task tool:**
|
|
170
174
|
|
|
171
|
-
Use the Task tool to spawn the `gsd-user-profiler` agent. Provide it with:
|
|
175
|
+
Use the Task tool to spawn the `gsd-user-profiler` agent, passing `model="{PROFILER_MODEL}"` (omit the parameter per the rule above when the value is `"inherit"` or empty). Provide it with:
|
|
172
176
|
- The sampled JSONL file path from profile-sample output
|
|
173
177
|
- The user-profiling reference doc at `$HOME/.claude/gsd-core/references/user-profiling.md`
|
|
174
178
|
|
|
@@ -382,7 +386,7 @@ gsd_run query generate-claude-profile --analysis "$ANALYSIS_PATH" --global --jso
|
|
|
382
386
|
|
|
383
387
|
Display: "✓ Added profile section to $HOME/.claude/CLAUDE.md"
|
|
384
388
|
|
|
385
|
-
**Error handling:** If any `
|
|
389
|
+
**Error handling:** If any `gsd_run query` call fails, display the error message and use AskUserQuestion to offer "Retry" or "Skip this artifact". On retry, re-run the command. On skip, continue to next artifact.
|
|
386
390
|
|
|
387
391
|
---
|
|
388
392
|
|
|
@@ -413,9 +417,7 @@ If nothing changed: Display "No changes detected -- your profile is already up t
|
|
|
413
417
|
**Display final summary:**
|
|
414
418
|
|
|
415
419
|
```
|
|
416
|
-
|
|
417
|
-
GSD > PROFILE COMPLETE ✓
|
|
418
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
420
|
+
### GSD > PROFILE COMPLETE ✓
|
|
419
421
|
|
|
420
422
|
Your profile: $HOME/.claude/gsd-core/USER-PROFILE.md
|
|
421
423
|
```
|
|
@@ -459,7 +461,7 @@ rm -f "$ANALYSIS_PATH" 2>/dev/null
|
|
|
459
461
|
- [ ] Profile written to USER-PROFILE.md via write-profile subcommand
|
|
460
462
|
- [ ] Result display shows report card table and highlight reel with evidence
|
|
461
463
|
- [ ] Artifact selection uses multiSelect with all options pre-selected
|
|
462
|
-
- [ ] Artifacts generated sequentially via
|
|
464
|
+
- [ ] Artifacts generated sequentially via `gsd_run query` subcommands
|
|
463
465
|
- [ ] Refresh diff shows changed dimensions when --refresh was used
|
|
464
466
|
- [ ] Temp files cleaned up on completion
|
|
465
467
|
</success_criteria>
|