@opengsd/gsd-core 1.12.0 → 1.14.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 +12 -0
- package/agents/gsd-advisor-researcher.compact.md +85 -0
- package/agents/gsd-ai-researcher.compact.md +96 -0
- package/agents/gsd-assumptions-analyzer.compact.md +81 -0
- package/agents/gsd-code-fixer.compact.md +458 -0
- package/agents/gsd-code-fixer.md +5 -5
- package/agents/gsd-code-reviewer.compact.md +269 -0
- package/agents/gsd-code-reviewer.md +15 -3
- package/agents/gsd-codebase-mapper.compact.md +760 -0
- package/agents/gsd-debug-session-manager.compact.md +345 -0
- package/agents/gsd-doc-classifier.compact.md +192 -0
- package/agents/gsd-doc-synthesizer.compact.md +200 -0
- package/agents/gsd-doc-verifier.compact.md +143 -0
- package/agents/gsd-doc-writer.compact.md +440 -0
- package/agents/gsd-dom-verifier.compact.md +138 -0
- package/agents/gsd-domain-researcher.compact.md +141 -0
- package/agents/gsd-eval-auditor.compact.md +160 -0
- package/agents/gsd-eval-planner.compact.md +137 -0
- package/agents/gsd-executor.md +63 -35
- package/agents/gsd-framework-selector.compact.md +82 -0
- package/agents/gsd-integration-checker.compact.md +245 -0
- package/agents/gsd-intel-updater.compact.md +226 -0
- package/agents/gsd-mempalace-curator.compact.md +45 -0
- package/agents/gsd-nyquist-auditor.compact.md +179 -0
- package/agents/gsd-pattern-mapper.compact.md +275 -0
- package/agents/gsd-plan-checker.md +76 -57
- package/agents/gsd-planner.md +14 -0
- package/agents/gsd-project-researcher.compact.md +587 -0
- package/agents/gsd-research-synthesizer.compact.md +212 -0
- package/agents/gsd-roadmapper.compact.md +454 -0
- package/agents/gsd-roadmapper.md +13 -0
- package/agents/gsd-security-auditor.compact.md +162 -0
- package/agents/gsd-ui-auditor.compact.md +404 -0
- package/agents/gsd-ui-checker.compact.md +277 -0
- package/agents/gsd-ui-checker.md +19 -3
- package/agents/gsd-ui-researcher.compact.md +282 -0
- package/agents/gsd-ui-researcher.md +29 -0
- package/agents/gsd-user-profiler.compact.md +108 -0
- package/agents/gsd-verifier.md +23 -1
- package/bin/install.js +444 -134
- package/commands/gsd/cleanup.md +1 -0
- package/commands/gsd/code-review.md +2 -1
- package/commands/gsd/complete-milestone.md +1 -0
- package/commands/gsd/config.md +1 -0
- package/commands/gsd/debug.md +1 -0
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/graphify.md +1 -0
- package/commands/gsd/health.md +1 -0
- package/commands/gsd/mempalace-capture.md +1 -0
- package/commands/gsd/mempalace-recall.md +1 -0
- package/commands/gsd/new-milestone.md +1 -0
- package/commands/gsd/new-project.md +1 -0
- package/commands/gsd/next.md +1 -0
- package/commands/gsd/ns-workflow.md +2 -1
- package/commands/gsd/pause-work.md +1 -0
- package/commands/gsd/phase.md +2 -1
- package/commands/gsd/pr-branch.md +1 -0
- package/commands/gsd/quick-batch.md +105 -0
- package/commands/gsd/resume-work.md +1 -0
- package/commands/gsd/review-backlog.md +1 -0
- package/commands/gsd/settings.md +2 -1
- package/commands/gsd/stats.md +1 -0
- package/commands/gsd/surface.md +18 -8
- package/commands/gsd/thread.md +1 -0
- package/commands/gsd/workspace.md +1 -0
- package/commands/gsd/workstreams.md +1 -0
- package/gsd-core/bin/check-latest-version.cjs +8 -3
- package/gsd-core/bin/gsd-tools.cjs +532 -174
- package/gsd-core/bin/lib/adr-parser.cjs +1 -1
- package/gsd-core/bin/lib/artifacts.cjs +2 -1
- package/gsd-core/bin/lib/audit.cjs +39 -22
- package/gsd-core/bin/lib/broken-windows.cjs +168 -49
- package/gsd-core/bin/lib/capability-activation.cjs +27 -0
- package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
- package/gsd-core/bin/lib/capability-loader.cjs +135 -1
- package/gsd-core/bin/lib/capability-registry.cjs +528 -116
- package/gsd-core/bin/lib/capability-source.cjs +19 -2
- package/gsd-core/bin/lib/capability-state.cjs +7 -1
- package/gsd-core/bin/lib/capability-validator.cjs +134 -5
- package/gsd-core/bin/lib/capability-writer.cjs +14 -4
- package/gsd-core/bin/lib/check-command-router.cjs +198 -38
- package/gsd-core/bin/lib/claude-orchestration.cjs +10 -25
- package/gsd-core/bin/lib/clusters.cjs +1 -0
- package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
- package/gsd-core/bin/lib/command-aliases.cjs +16 -0
- package/gsd-core/bin/lib/commands.cjs +981 -79
- package/gsd-core/bin/lib/config-loader.cjs +4 -0
- package/gsd-core/bin/lib/config.cjs +153 -38
- package/gsd-core/bin/lib/core-utils.cjs +34 -7
- package/gsd-core/bin/lib/coverage.cjs +1 -1
- package/gsd-core/bin/lib/decisions.cjs +343 -28
- package/gsd-core/bin/lib/edge-probe.cjs +14 -1
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
- package/gsd-core/bin/lib/file-overlap-partitioner.cjs +74 -0
- package/gsd-core/bin/lib/frontmatter.cjs +137 -23
- package/gsd-core/bin/lib/gap-checker.cjs +22 -13
- package/gsd-core/bin/lib/git-base-branch.cjs +10 -2
- package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +8 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +54 -11
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +87 -23
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
- package/gsd-core/bin/lib/host-integration.cjs +57 -5
- package/gsd-core/bin/lib/init-command-router.cjs +14 -0
- package/gsd-core/bin/lib/init.cjs +539 -60
- package/gsd-core/bin/lib/install-engine.cjs +199 -14
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +45 -0
- package/gsd-core/bin/lib/install-profiles.cjs +36 -14
- package/gsd-core/bin/lib/installer-migration-report.cjs +1 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +33 -4
- package/gsd-core/bin/lib/io.cjs +35 -0
- package/gsd-core/bin/lib/loop-resolver.cjs +64 -39
- package/gsd-core/bin/lib/markdown-table.cjs +123 -0
- package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
- package/gsd-core/bin/lib/milestone.cjs +41 -10
- package/gsd-core/bin/lib/model-resolver.cjs +101 -10
- package/gsd-core/bin/lib/phase-command-router.cjs +20 -7
- package/gsd-core/bin/lib/phase-id.cjs +412 -31
- package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
- package/gsd-core/bin/lib/phase.cjs +941 -98
- package/gsd-core/bin/lib/plan-document.cjs +10 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +34 -18
- package/gsd-core/bin/lib/planning-snapshot.cjs +206 -30
- package/gsd-core/bin/lib/planning-workspace.cjs +153 -29
- package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +285 -0
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +250 -0
- package/gsd-core/bin/lib/quick-batch.cjs +840 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
- package/gsd-core/bin/lib/research-store.cjs +11 -12
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +53 -5
- package/gsd-core/bin/lib/review-lane-invocation.cjs +96 -1
- package/gsd-core/bin/lib/review-lane-runner.cjs +136 -10
- package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
- package/gsd-core/bin/lib/roadmap-parser.cjs +555 -41
- package/gsd-core/bin/lib/roadmap.cjs +292 -69
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +260 -43
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +28 -20
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +294 -108
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +408 -47
- package/gsd-core/bin/lib/security.cjs +126 -7
- package/gsd-core/bin/lib/shell-command-projection.cjs +4 -0
- package/gsd-core/bin/lib/smart-entry.cjs +7 -9
- package/gsd-core/bin/lib/state-document.cjs +159 -32
- package/gsd-core/bin/lib/state-md-schema.cjs +44 -27
- package/gsd-core/bin/lib/state-transition.cjs +465 -62
- package/gsd-core/bin/lib/state.cjs +906 -151
- package/gsd-core/bin/lib/surface.cjs +83 -10
- package/gsd-core/bin/lib/task-command-router.cjs +12 -6
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +133 -0
- package/gsd-core/bin/lib/uat.cjs +1420 -516
- package/gsd-core/bin/lib/update-context.cjs +36 -26
- package/gsd-core/bin/lib/validate.cjs +230 -12
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +316 -23
- package/gsd-core/bin/lib/verify-command-grounding.cjs +1 -1
- package/gsd-core/bin/lib/verify-command-router.cjs +1 -0
- package/gsd-core/bin/lib/verify.cjs +531 -36
- package/gsd-core/bin/lib/workstream-inventory.cjs +21 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +21 -7
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +13 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +507 -81
- package/gsd-core/references/agent-contracts.md +3 -3
- package/gsd-core/references/compact-content-gate.md +66 -0
- package/gsd-core/references/edge-probe.md +17 -13
- package/gsd-core/references/execute-mvp-tdd.md +18 -16
- package/gsd-core/references/execute-phase-response-language.md +6 -0
- package/gsd-core/references/executor-examples.md +42 -0
- package/gsd-core/references/few-shot-examples/plan-checker.md +15 -15
- package/gsd-core/references/loop-hook-dispatch.md +18 -0
- package/gsd-core/references/model-profiles.md +12 -3
- package/gsd-core/references/mvp-concepts.md +2 -2
- package/gsd-core/references/plan-checker-examples.md +41 -0
- package/gsd-core/references/planner-antipatterns.md +25 -0
- package/gsd-core/references/planner-chunked.md +5 -1
- package/gsd-core/references/planner-coupling.md +42 -0
- package/gsd-core/references/planner-quick-batch.md +71 -0
- package/gsd-core/references/planner-reviews.md +47 -0
- package/gsd-core/references/planner-revision.md +75 -2
- package/gsd-core/references/planning-config.md +5 -1
- package/gsd-core/references/response-language-directive.md +9 -0
- package/gsd-core/references/revision-loop.md +118 -11
- package/gsd-core/references/tdd.md +17 -9
- package/gsd-core/references/thinking-models-planning.md +18 -2
- package/gsd-core/references/verification-patterns.md +17 -4
- package/gsd-core/references/verifier-evidence-gate.md +160 -0
- package/gsd-core/references/worktree-path-safety.md +112 -2
- package/gsd-core/templates/README.md +7 -1
- package/gsd-core/templates/phase-prompt.md +4 -0
- package/gsd-core/templates/state.md +6 -3
- package/gsd-core/templates/summary.compact.md +212 -0
- package/gsd-core/templates/user-setup.compact.md +199 -0
- package/gsd-core/templates/user-setup.md +0 -9
- package/gsd-core/templates/verification-report.md +5 -0
- package/gsd-core/workflows/add-backlog.md +2 -0
- package/gsd-core/workflows/add-phase.md +2 -0
- package/gsd-core/workflows/add-tests.md +1 -1
- package/gsd-core/workflows/add-todo.md +4 -3
- package/gsd-core/workflows/ai-integration-phase.md +1 -1
- package/gsd-core/workflows/analyze-dependencies.md +2 -0
- package/gsd-core/workflows/audit-fix.md +2 -0
- package/gsd-core/workflows/audit-milestone.md +2 -0
- package/gsd-core/workflows/audit-uat.md +2 -0
- package/gsd-core/workflows/autonomous.md +15 -10
- package/gsd-core/workflows/check-todos.md +5 -3
- package/gsd-core/workflows/cleanup.md +4 -2
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +22 -13
- package/gsd-core/workflows/code-review-fix.md +5 -3
- package/gsd-core/workflows/code-review.md +211 -43
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
- package/gsd-core/workflows/complete-milestone.md +40 -254
- package/gsd-core/workflows/debug.md +1 -1
- package/gsd-core/workflows/diagnose-issues.md +5 -1
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/all.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/analyze.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/auto.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/batch.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/default.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/power.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/text.md +2 -0
- package/gsd-core/workflows/discuss-phase/templates/context.md +2 -0
- package/gsd-core/workflows/discuss-phase/templates/discussion-log.md +2 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
- package/gsd-core/workflows/discuss-phase-power.md +2 -0
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +43 -13
- package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
- package/gsd-core/workflows/docs-update.md +15 -156
- package/gsd-core/workflows/edit-phase.md +2 -0
- package/gsd-core/workflows/eval-review.md +1 -1
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +20 -3
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +24 -3
- package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +8 -2
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +25 -0
- package/gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md +2 -0
- package/gsd-core/workflows/execute-phase.md +78 -159
- package/gsd-core/workflows/execute-plan.md +28 -15
- package/gsd-core/workflows/explore.md +2 -0
- package/gsd-core/workflows/extract-learnings.md +2 -0
- package/gsd-core/workflows/fast.md +6 -0
- package/gsd-core/workflows/forensics.md +2 -0
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +1 -1
- package/gsd-core/workflows/help/modes/brief.md +2 -0
- package/gsd-core/workflows/help/modes/default.md +2 -0
- package/gsd-core/workflows/help/modes/full.compact.md +398 -0
- package/gsd-core/workflows/help/modes/full.md +12 -0
- package/gsd-core/workflows/help/modes/topic.md +2 -0
- package/gsd-core/workflows/help.md +3 -1
- package/gsd-core/workflows/import.md +3 -3
- package/gsd-core/workflows/inbox.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +2 -0
- package/gsd-core/workflows/list-phase-assumptions.md +2 -0
- package/gsd-core/workflows/list-seeds.md +2 -0
- package/gsd-core/workflows/list-workspaces.md +2 -0
- package/gsd-core/workflows/manager.md +3 -3
- package/gsd-core/workflows/map-codebase.md +52 -3
- package/gsd-core/workflows/milestone-summary.md +2 -0
- package/gsd-core/workflows/mvp-phase.md +1 -1
- package/gsd-core/workflows/new-milestone.md +55 -13
- package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
- package/gsd-core/workflows/new-project.md +37 -205
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +2 -0
- package/gsd-core/workflows/node-repair.md +2 -0
- package/gsd-core/workflows/note.md +2 -0
- package/gsd-core/workflows/onboard.md +1 -1
- package/gsd-core/workflows/pause-work.md +19 -4
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +100 -18
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +9 -0
- package/gsd-core/workflows/plan-phase.md +144 -185
- package/gsd-core/workflows/plan-review-convergence.md +102 -10
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/pr-branch.md +30 -10
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress/steps/forensic-audit.md +1 -1
- package/gsd-core/workflows/progress.md +25 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +37 -2
- package/gsd-core/workflows/quick/steps/research-phase.md +3 -3
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +55 -0
- package/gsd-core/workflows/quick-batch/steps/completion.md +65 -0
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +100 -0
- package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +147 -0
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +158 -0
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +95 -0
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +49 -0
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +73 -0
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +169 -0
- package/gsd-core/workflows/quick-batch.md +203 -0
- package/gsd-core/workflows/quick.md +21 -4
- package/gsd-core/workflows/reapply-patches.md +79 -3
- package/gsd-core/workflows/remove-phase.md +2 -0
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +6 -2
- package/gsd-core/workflows/review.md +215 -10
- package/gsd-core/workflows/scan.md +2 -0
- package/gsd-core/workflows/section-manifest.json +12 -0
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -0
- package/gsd-core/workflows/settings-advanced.md +2 -0
- package/gsd-core/workflows/settings-integrations.md +9 -8
- package/gsd-core/workflows/settings.md +19 -6
- package/gsd-core/workflows/ship.md +10 -10
- package/gsd-core/workflows/sketch-wrap-up.md +2 -0
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +1 -1
- package/gsd-core/workflows/spec-phase.md +24 -19
- package/gsd-core/workflows/spike-wrap-up.md +2 -0
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +2 -0
- package/gsd-core/workflows/sync-skills.md +12 -4
- package/gsd-core/workflows/thread.md +2 -0
- package/gsd-core/workflows/transition.md +2 -0
- package/gsd-core/workflows/ui-phase.md +26 -5
- package/gsd-core/workflows/ui-review.md +1 -1
- package/gsd-core/workflows/ultraplan-phase.md +2 -0
- package/gsd-core/workflows/undo.md +1 -1
- package/gsd-core/workflows/update.md +48 -43
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
- package/gsd-core/workflows/verify-work.md +68 -182
- package/hooks/dist/gsd-agent-isolation-guard.js +42 -16
- package/hooks/dist/gsd-check-update-worker.js +19 -2
- package/hooks/dist/gsd-context-monitor.js +371 -27
- package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
- package/hooks/dist/gsd-node-runner.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +30 -5
- package/hooks/dist/gsd-read-guard.js +2 -0
- package/hooks/dist/gsd-read-injection-scanner.js +5 -5
- package/hooks/dist/gsd-secret-read-guard.js +1105 -0
- package/hooks/dist/gsd-statusline.js +18 -10
- package/hooks/dist/gsd-validate-commit.sh +474 -7
- package/hooks/dist/gsd-workflow-guard.js +2 -1
- package/hooks/dist/gsd-worktree-path-guard.js +25 -14
- package/hooks/dist/gsd-write-guard.js +46 -1
- package/hooks/dist/lib/dispatch-identity.js +187 -0
- package/hooks/dist/lib/filename-classification.js +64 -0
- package/hooks/dist/lib/git-cmd.js +210 -1
- package/hooks/dist/lib/injection-patterns.js +36 -6
- package/hooks/dist/lib/isolation-deny-reason.js +53 -1
- package/hooks/dist/lib/isolation-sentinel.js +58 -19
- package/hooks/dist/managed-hooks-registry.cjs +1 -0
- package/hooks/gsd-agent-isolation-guard.js +42 -16
- package/hooks/gsd-check-update-worker.js +19 -2
- package/hooks/gsd-context-monitor.js +371 -27
- package/hooks/gsd-cursor-subagent-start.js +34 -14
- package/hooks/gsd-node-runner.sh +1 -0
- package/hooks/gsd-prompt-guard.js +30 -5
- package/hooks/gsd-read-guard.js +2 -0
- package/hooks/gsd-read-injection-scanner.js +5 -5
- package/hooks/gsd-secret-read-guard.js +1105 -0
- package/hooks/gsd-statusline.js +18 -10
- package/hooks/gsd-validate-commit.sh +474 -7
- package/hooks/gsd-workflow-guard.js +2 -1
- package/hooks/gsd-worktree-path-guard.js +25 -14
- package/hooks/gsd-write-guard.js +46 -1
- package/hooks/hooks.json +6 -0
- package/hooks/lib/dispatch-identity.js +187 -0
- package/hooks/lib/filename-classification.js +64 -0
- package/hooks/lib/git-cmd.js +210 -1
- package/hooks/lib/injection-patterns.js +36 -6
- package/hooks/lib/isolation-deny-reason.js +53 -1
- package/hooks/lib/isolation-sentinel.js +58 -19
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +13 -9
- package/scripts/benchmark-compact-content-variants.cjs +298 -0
- package/scripts/benchmark-compact-content.cjs +368 -0
- package/scripts/build-hooks.js +11 -4
- package/scripts/check-contract-drift.cjs +4 -1
- package/scripts/check-env.cjs +36 -8
- package/scripts/check-glossary-refs.cjs +25 -21
- package/scripts/ci-next-health.cjs +271 -0
- package/scripts/ci-prepare-test-scope.cjs +7 -7
- package/scripts/ci-test-scope.cjs +133 -20
- package/scripts/ci-timeout-report.cjs +1 -1
- package/scripts/diff-touches-shipped-paths.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +17 -2
- package/scripts/gen-adr-index.cjs +8 -2
- package/scripts/gen-inventory-manifest.cjs +12 -0
- package/scripts/gen-loop-host-contract.cjs +67 -15
- package/scripts/gen-platform-conformance-tier.cjs +557 -0
- package/scripts/lib/drift-scan.cjs +1 -1
- package/scripts/lib/macos-conformance-tier.generated.cjs +210 -0
- package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
- package/scripts/lib/platform-conformance-tier.generated.cjs +276 -0
- package/scripts/lib/shellcheck-fetch.cjs +247 -0
- package/scripts/lib/suite-detection.cjs +32 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -6
- 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-allowed-tools-parity.cjs +221 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +24 -2
- package/scripts/lint-phase-enumeration-drift.cjs +24 -6
- package/scripts/lint-phase-id-drift.cjs +465 -15
- package/scripts/lint-portable-grep.cjs +176 -0
- package/scripts/lint-response-language-coverage.cjs +530 -0
- package/scripts/lint-source-test-name-collision.cjs +1 -1
- package/scripts/lint-test-file-count.allowlist.json +4 -1
- package/scripts/lint-vendored-deps.cjs +128 -17
- package/scripts/lint-workflow-shellcheck-baseline.json +1112 -0
- package/scripts/lint-workflow-shellcheck.cjs +614 -0
- package/scripts/npm-audit-baseline.cjs +376 -0
- package/scripts/prompt-injection-scan.sh +22 -0
- package/scripts/require-issue-link-policy.cjs +16 -1
- package/scripts/workflow-size.cjs +139 -0
- package/skills/gsd-cleanup/SKILL.md +1 -0
- package/skills/gsd-code-review/SKILL.md +2 -1
- package/skills/gsd-complete-milestone/SKILL.md +1 -0
- package/skills/gsd-config/SKILL.md +1 -0
- package/skills/gsd-debug/SKILL.md +1 -0
- package/skills/gsd-execute-phase/SKILL.md +1 -1
- package/skills/gsd-graphify/SKILL.md +1 -0
- package/skills/gsd-health/SKILL.md +1 -0
- package/skills/gsd-mempalace-capture/SKILL.md +1 -0
- package/skills/gsd-mempalace-recall/SKILL.md +1 -0
- package/skills/gsd-new-milestone/SKILL.md +1 -0
- package/skills/gsd-new-project/SKILL.md +1 -0
- package/skills/gsd-next/SKILL.md +1 -0
- package/skills/gsd-ns-workflow/SKILL.md +1 -0
- package/skills/gsd-pause-work/SKILL.md +1 -0
- package/skills/gsd-phase/SKILL.md +2 -1
- package/skills/gsd-pr-branch/SKILL.md +1 -0
- package/skills/gsd-quick-batch/SKILL.md +105 -0
- package/skills/gsd-resume-work/SKILL.md +1 -0
- package/skills/gsd-review-backlog/SKILL.md +1 -0
- package/skills/gsd-settings/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +1 -0
- package/skills/gsd-surface/SKILL.md +18 -8
- package/skills/gsd-thread/SKILL.md +1 -0
- package/skills/gsd-workspace/SKILL.md +1 -0
- package/skills/gsd-workstreams/SKILL.md +1 -0
- package/vscode/package.json +1 -1
- package/gsd-core/templates/claude-md.md +0 -145
- package/gsd-core/templates/codebase/concerns.md +0 -310
- package/gsd-core/templates/codebase/conventions.md +0 -307
- package/gsd-core/templates/codebase/integrations.md +0 -280
- package/gsd-core/templates/codebase/structure.md +0 -285
- package/gsd-core/templates/codebase/testing.md +0 -480
- package/gsd-core/templates/debug-subagent-prompt.md +0 -91
- package/gsd-core/templates/discovery.md +0 -146
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
**Step 6: Worktree create + executor dispatch**
|
|
2
|
+
|
|
3
|
+
This is the batch's MUTATING wave — worktree create/executor dispatch/merge
|
|
4
|
+
are the operations `isolation == "none"` caps to concurrency 1 (row 6),
|
|
5
|
+
unlike planning/research above.
|
|
6
|
+
|
|
7
|
+
**Auto-degrade on stale fork base (row 38, mirrors `/gsd:quick`'s own #1941
|
|
8
|
+
guard):**
|
|
9
|
+
```bash
|
|
10
|
+
_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
|
|
11
|
+
if [ "$ISOLATION" = "harness-worktree" ] && [ "${USE_WORKTREES:-true}" != "false" ]; then
|
|
12
|
+
_QB_SHOULD_DEGRADE=$(gsd_run query worktree.base-check --mode "$ISOLATION" --pick shouldDegrade 2>/dev/null || true)
|
|
13
|
+
if [ "$_QB_SHOULD_DEGRADE" = "true" ]; then
|
|
14
|
+
echo "⚠ [#1941] Worktree fork base diverged — auto-degrading quick-batch to sequential mode." >&2
|
|
15
|
+
USE_WORKTREES=false
|
|
16
|
+
ISOLATION=none
|
|
17
|
+
fi
|
|
18
|
+
fi
|
|
19
|
+
gsd_run query dispatch-isolation --raw --force-isolation "$ISOLATION" >/dev/null 2>&1 || true
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Effective concurrency for this MUTATING wave** (`mutating` forces
|
|
23
|
+
`isolation == none` to 1 regardless of `--jobs`/capacity — row 6):
|
|
24
|
+
```bash
|
|
25
|
+
QB_EXEC_CONC_JSON=$(gsd_run quick-batch effective-concurrency --jobs "$JOBS" --task-count "$ITEM_COUNT" --capacity "$CAPACITY" --isolation "$ISOLATION" --mutating --raw)
|
|
26
|
+
EXEC_CONCURRENCY=$(printf '%s' "$QB_EXEC_CONC_JSON" | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{try{const j=JSON.parse(s);process.stdout.write(String(j.concurrency))}catch{process.stdout.write("1")}})')
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Dispatch rounds.** Repeat until no item is eligible-and-not-yet-dispatched
|
|
30
|
+
(bounded by `$ITEM_COUNT` rounds):
|
|
31
|
+
|
|
32
|
+
1. Re-derive eligibility (also reconciles crash-window/blocked-propagation —
|
|
33
|
+
safe to call repeatedly, idempotent when nothing changed):
|
|
34
|
+
```bash
|
|
35
|
+
QB_ELIG_JSON=$(gsd_run quick-batch resume --batch "$BATCH_ID" --raw)
|
|
36
|
+
```
|
|
37
|
+
Parse `eligible` (quick ids ready to execute — every dependency already
|
|
38
|
+
`complete`) and refresh `$BATCH_MANIFEST_JSON` from its `manifest`.
|
|
39
|
+
|
|
40
|
+
**Crash-window guard (mirrors `planner-wave.md`'s PLAN.md-existence
|
|
41
|
+
check one layer earlier — #3677):** `quick-batch resume`'s `eligible` is
|
|
42
|
+
purely status/dependency-derived; it does NOT know an item already
|
|
43
|
+
finished executing. A coordinator crash between this step returning
|
|
44
|
+
(executor committed, `SUMMARY.md` written) and Step 7's merge leaves
|
|
45
|
+
`BATCH.json` at `pending` with no STATE.md row yet (that row is written
|
|
46
|
+
only in Step 9) — so on `--resume`, such an item still comes back
|
|
47
|
+
`eligible` here. Before computing `spawn-plan`, determine which eligible
|
|
48
|
+
items already have `${item_dir}/${quick_id}-SUMMARY.md` on disk (same
|
|
49
|
+
`item_dir` derivation via `generate-slug` every other step uses), then
|
|
50
|
+
let the PURE `quick-batch filter-executed` verb
|
|
51
|
+
(`filterAlreadyExecuted`, `src/quick-batch-dispatch.cts`) decide which
|
|
52
|
+
ids are actually safe to spawn — never re-derive that split inline:
|
|
53
|
+
```bash
|
|
54
|
+
EXECUTED_IDS_JSON="[]" # JSON array of quick_ids whose SUMMARY.md already exists on disk this round
|
|
55
|
+
QB_FILTER_JSON=$(gsd_run quick-batch filter-executed --eligible "$ELIGIBLE_IDS_JSON" --executed "$EXECUTED_IDS_JSON" --raw)
|
|
56
|
+
```
|
|
57
|
+
Parse `spawnEligible` (safe to spawn this round) and `alreadyExecuted`
|
|
58
|
+
(diagnostic only — report these as "already executed, routing to merge"
|
|
59
|
+
rather than dispatching them). Replace `$ELIGIBLE_IDS_JSON` with
|
|
60
|
+
`spawnEligible` before continuing to backpressure below.
|
|
61
|
+
|
|
62
|
+
NEVER re-dispatch it into a second worktree for any id `filter-executed`
|
|
63
|
+
returns in `alreadyExecuted`. It is not lost: Step 7's own mergeable-wave
|
|
64
|
+
criterion
|
|
65
|
+
(`gsd-core/workflows/quick-batch/steps/merge-wave.md` Step 1) already
|
|
66
|
+
picks up any `pending` item with an on-disk `SUMMARY.md` that isn't yet
|
|
67
|
+
merged, independent of this eligible/spawn list — dropping it here only
|
|
68
|
+
prevents the duplicate dispatch, it does not remove it from the batch.
|
|
69
|
+
|
|
70
|
+
2. **Backpressure.** Not every eligible item necessarily spawns this round —
|
|
71
|
+
cap fan-out at `$EXEC_CONCURRENCY` minus current in-flight count (row
|
|
72
|
+
27/39):
|
|
73
|
+
```bash
|
|
74
|
+
QB_SPAWN_JSON=$(gsd_run quick-batch spawn-plan --eligible "$ELIGIBLE_IDS_JSON" --capacity "$EXEC_CONCURRENCY" --in-flight "$IN_FLIGHT_COUNT" --raw)
|
|
75
|
+
```
|
|
76
|
+
Parse `spawn` (dispatch these now) and `pending` (leave `pending` in
|
|
77
|
+
`BATCH.json` — already the case, no write needed; NEVER mark these
|
|
78
|
+
`failed`, NEVER increase fan-out to compensate).
|
|
79
|
+
|
|
80
|
+
3. **Create worktrees + dispatch executors, ONE AT A TIME per `spawn` item**
|
|
81
|
+
(`git worktree add` races on `.git/config.lock` — never simultaneous,
|
|
82
|
+
`execute-phase.md`'s own discipline):
|
|
83
|
+
|
|
84
|
+
For each item in `spawn`, in order:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
SLUG=$(gsd_run query generate-slug "$description" --raw)
|
|
88
|
+
ITEM_DIR="${quick_dir}/${quick_id}-${SLUG}"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**`isolation == "harness-worktree"`:** one `Agent()` per message,
|
|
92
|
+
`run_in_background: true`. Same prompt shape as `/gsd:quick`'s own
|
|
93
|
+
executor dispatch (Step 6 of `quick.md`) — required_reading, agent skills,
|
|
94
|
+
`<submodule_commit_guard>` using this project's `$SUBMODULE_PATHS`
|
|
95
|
+
(identical block, verbatim) — with these differences:
|
|
96
|
+
```
|
|
97
|
+
Agent(
|
|
98
|
+
prompt="
|
|
99
|
+
Execute quick-batch item ${quick_id}.
|
|
100
|
+
|
|
101
|
+
<required_reading>
|
|
102
|
+
- ${ITEM_DIR}/${quick_id}-PLAN.md (Plan)
|
|
103
|
+
- ${STATE_PATH} (Project state — READ ONLY, do not write it)
|
|
104
|
+
- ./CLAUDE.md or ./.claude/CLAUDE.md (if exists)
|
|
105
|
+
</required_reading>
|
|
106
|
+
|
|
107
|
+
${AGENT_SKILLS_EXECUTOR}
|
|
108
|
+
|
|
109
|
+
<submodule_commit_guard>
|
|
110
|
+
(same SUBMODULE_PATHS fail-loud guard as /gsd:quick — see gsd-core/workflows/quick.md Step 6)
|
|
111
|
+
</submodule_commit_guard>
|
|
112
|
+
|
|
113
|
+
<constraints>
|
|
114
|
+
- Execute all tasks in the plan; commit each task atomically
|
|
115
|
+
- Create summary at: ${ITEM_DIR}/${quick_id}-SUMMARY.md with `status: complete` in frontmatter
|
|
116
|
+
- NEVER invoke /gsd:quick or any other GSD command — you are a leaf, not a coordinator
|
|
117
|
+
- NEVER write .planning/quick-batches/${BATCH_ID}/BATCH.json
|
|
118
|
+
- Do NOT update STATE.md or ROADMAP.md — the orchestrator owns those writes after every item in this dispatch round completes (ADR-1239 single-writer invariant)
|
|
119
|
+
- Do NOT commit docs artifacts (SUMMARY.md, STATE.md, PLAN.md) — the orchestrator commits them at completion
|
|
120
|
+
</constraints>
|
|
121
|
+
",
|
|
122
|
+
subagent_type="gsd-executor",
|
|
123
|
+
model="{executor_model}",
|
|
124
|
+
{harnessFlag}
|
|
125
|
+
description="Execute ${quick_id}: ${description}"
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
Record `{agent_id, worktree_path, branch, expected_base, allowed_bases}`
|
|
129
|
+
from the executor's return into `$QUICK_BATCH_WORKTREE_MANIFEST` (a JSON
|
|
130
|
+
file, initialized `{"worktrees":[]}` before the first round — same shape
|
|
131
|
+
`/gsd:quick`'s own `QUICK_WORKTREE_MANIFEST` uses).
|
|
132
|
+
|
|
133
|
+
**`isolation == "orchestrator-worktree"`:** GSD creates the worktree
|
|
134
|
+
(`gsd_run query worktree.create --manifest "$QUICK_BATCH_WORKTREE_MANIFEST" --agent-id ... --path ... --branch ... --base ... --files "$PLAN_FILES" --deletions "$PLAN_DELETIONS"`) then
|
|
135
|
+
process-spawns the executor via `dispatch-isolation --json --cwd-target
|
|
136
|
+
--prompt`, exactly as `gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md`'s
|
|
137
|
+
"orchestrator-worktree" section
|
|
138
|
+
describes — reuse that mechanism verbatim, substituting this item's
|
|
139
|
+
`${quick_id}`/`${ITEM_DIR}`/`${quick_id}-PLAN.md` for its
|
|
140
|
+
`{plan_number}`/`{phase_dir}`/`{plan_file}` placeholders.
|
|
141
|
+
|
|
142
|
+
**`isolation == "none"`:** no worktree. Dispatch the executor inline on the
|
|
143
|
+
primary checkout (same prompt, minus the worktree-only framing), one item
|
|
144
|
+
at a time — `EXEC_CONCURRENCY` is already forced to 1 in this mode.
|
|
145
|
+
|
|
146
|
+
**Durable worktree-recovery persistence (#3677 — `harness-worktree`/
|
|
147
|
+
`orchestrator-worktree` only, skip for `none`):** immediately after
|
|
148
|
+
recording `{agent_id, worktree_path, branch, expected_base}` into the
|
|
149
|
+
EPHEMERAL `$QUICK_BATCH_WORKTREE_MANIFEST` above, ALSO persist the same
|
|
150
|
+
triple durably onto this item in `BATCH.json`:
|
|
151
|
+
```bash
|
|
152
|
+
gsd_run quick-batch update --batch "$BATCH_ID" --updates '[{"quickId":"'"$quick_id"'","dispatchedWorktree":"'"$worktree_path"'","dispatchedBranch":"'"$branch"'","dispatchedBase":"'"$expected_base"'"}]'
|
|
153
|
+
```
|
|
154
|
+
The ephemeral manifest is a per-process `mktemp` file (same shape
|
|
155
|
+
`/gsd:quick`'s own `QUICK_WORKTREE_MANIFEST` uses) — it does NOT survive
|
|
156
|
+
a coordinator crash/restart. A RESUMED coordinator's Step 7
|
|
157
|
+
(`merge-wave.md`) reads this durable BATCH.json triple as its fallback
|
|
158
|
+
for any item the crash-window guard above correctly did NOT re-dispatch
|
|
159
|
+
in the current process.
|
|
160
|
+
|
|
161
|
+
> **ORCHESTRATOR RULE — CODEX RUNTIME**: after each `Agent()` call above, wait for it to return before starting the next worktree create.
|
|
162
|
+
|
|
163
|
+
4. **After every item dispatched this round returns:** verify
|
|
164
|
+
`${ITEM_DIR}/${quick_id}-SUMMARY.md` exists. If missing, the item stays
|
|
165
|
+
`pending`/its worktree preserved for diagnosis rather than guessing
|
|
166
|
+
completion — do not proceed to merge for it this round.
|
|
167
|
+
|
|
168
|
+
Continue to Step 7 once every eligible item has been dispatched (across
|
|
169
|
+
however many rounds backpressure required) and returned.
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
@~/.claude/gsd-core/references/response-language-directive.md
|
|
2
|
+
<purpose>
|
|
3
|
+
Batch several `/gsd:quick`-shaped tasks together (#3676, epic #3344, ADR-1239
|
|
4
|
+
"Quick-batch binding"). ONE coordinator (this workflow) owns every shared
|
|
5
|
+
write — `BATCH.json`, STATE.md, worktree create/merge/cleanup — and never
|
|
6
|
+
delegates them to a leaf. Leaves (planner/researcher/checker/executor/
|
|
7
|
+
verifier) return structured results only; they never invoke `/gsd:quick`,
|
|
8
|
+
never touch `BATCH.json`, and never write STATE.md/ROADMAP.md themselves
|
|
9
|
+
(single-writer invariant).
|
|
10
|
+
|
|
11
|
+
Dispatch decisions (effective concurrency, deterministic merge order, spawn
|
|
12
|
+
backpressure, failure/verification routing) are computed by the pure
|
|
13
|
+
`quick-batch-dispatch.cts` module (via the `quick-batch` CLI verbs) — this
|
|
14
|
+
workflow never re-derives that logic inline.
|
|
15
|
+
</purpose>
|
|
16
|
+
|
|
17
|
+
<required_reading>
|
|
18
|
+
Read all files referenced by the invoking prompt's execution_context before starting.
|
|
19
|
+
</required_reading>
|
|
20
|
+
|
|
21
|
+
<available_agent_types>
|
|
22
|
+
Valid GSD subagent types (use exact names — do not fall back to 'general-purpose'):
|
|
23
|
+
- gsd-phase-researcher — Researches technical approaches for an item
|
|
24
|
+
- gsd-planner — Creates a plan for one item (`quick-batch` mode)
|
|
25
|
+
- gsd-plan-checker — Reviews one item's plan before execution
|
|
26
|
+
- gsd-executor — Executes one item's plan, commits, creates SUMMARY.md
|
|
27
|
+
- gsd-verifier — Verifies one item's goal achievement
|
|
28
|
+
</available_agent_types>
|
|
29
|
+
|
|
30
|
+
<process>
|
|
31
|
+
**Step 1: Parse arguments, resolve mode**
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
_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
|
|
35
|
+
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --raw --default "" 2>/dev/null || echo "")
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**If `response_language` is set:** all user-facing questions/prompts/explanations MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English.
|
|
39
|
+
|
|
40
|
+
Validate `$ARGUMENTS` through the CLI's own grammar — never re-derive it inline (single source of truth: `parseQuickBatchArgs`, `src/quick-batch-dispatch.cts`). `$ARGUMENTS` is raw, attacker-influenced task text — pass it as ONE quoted argument via `--text` so the shell never word-splits or glob-expands it; `quick-batch parse-args` does the whitespace split itself, in Node, after the shell is done:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
QB_PARSE_JSON=$(gsd_run quick-batch parse-args --raw --text "$ARGUMENTS")
|
|
44
|
+
QB_PARSE_RC=$?
|
|
45
|
+
if [ $QB_PARSE_RC -ne 0 ]; then
|
|
46
|
+
echo "$QB_PARSE_JSON" >&2
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
if [[ "$QB_PARSE_JSON" == @file:* ]]; then QB_PARSE_JSON=$(cat "${QB_PARSE_JSON#@file:}"); fi
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Parse `$QB_PARSE_JSON` for `jobs` (`"auto"` or an integer), `validate` (bool), `research` (bool), `resume` (batch id or null). Store as `$JOBS`, `$VALIDATE_MODE`, `$RESEARCH_MODE`, `$RESUME_BATCH_ID`.
|
|
53
|
+
|
|
54
|
+
Extract the raw task-list text / `--file <path>` from `$ARGUMENTS` (everything that is not `--jobs <v>`, `--validate`, `--research`, `--resume <id>`, or `--file <path>`'s own flag pair).
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
VALIDATE_PARAM=""; if [ "$VALIDATE_MODE" = true ]; then VALIDATE_PARAM="--validate"; fi
|
|
58
|
+
RESEARCH_PARAM=""; if [ "$RESEARCH_MODE" = true ]; then RESEARCH_PARAM="--research"; fi
|
|
59
|
+
INIT=$(gsd_run query init.quick-batch $VALIDATE_PARAM $RESEARCH_PARAM)
|
|
60
|
+
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
61
|
+
AGENT_SKILLS_PLANNER=$(gsd_run query agent-skills gsd-planner)
|
|
62
|
+
AGENT_SKILLS_EXECUTOR=$(gsd_run query agent-skills gsd-executor)
|
|
63
|
+
AGENT_SKILLS_CHECKER=$(gsd_run query agent-skills gsd-plan-checker)
|
|
64
|
+
AGENT_SKILLS_VERIFIER=$(gsd_run query agent-skills gsd-verifier)
|
|
65
|
+
AGENT_SKILLS_RESEARCHER=$(gsd_run query agent-skills gsd-phase-researcher)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Parse `$INIT` for: `planner_model`, `executor_model`, `checker_model`, `verifier_model`, `researcher_model`, `commit_docs`, `quick_dir`, `quick_batches_dir`, `roadmap_exists`, `planning_exists`.
|
|
69
|
+
|
|
70
|
+
<!-- #2517 model-omit-on-inherit -->
|
|
71
|
+
|
|
72
|
+
> **Model omission (#2517).** Every `Agent()` dispatch below (planner, researcher, plan-checker, executor, verifier) MUST omit the `model` parameter entirely when the value it would carry (`planner_model`, `checker_model`, `executor_model`, `verifier_model`, `researcher_model`) is `"inherit"` or empty. An empty value 404s on runtimes without native tier aliases — the default on non-Claude runtimes, where the installer writes `resolve_model_ids:"omit"`. Omitting it inherits the orchestrator's model. See @gsd-core/references/model-profile-resolution.md.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
STATE_PATH="${quick_dir%/quick}/STATE.md"
|
|
76
|
+
PROJECT_PATH="${quick_dir%/quick}/PROJECT.md"
|
|
77
|
+
USE_WORKTREES=$(gsd_run query config-get workflow.use_worktrees --raw 2>/dev/null || echo "true")
|
|
78
|
+
RUNTIME=$(gsd_run query config-get runtime --default claude --raw 2>/dev/null || echo "claude")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**If `roadmap_exists` is false:** Error — quick-batch requires an active project with ROADMAP.md. Run `/gsd:new-project` first.
|
|
82
|
+
|
|
83
|
+
If the project uses git submodules, parse `SUBMODULE_PATHS` from `.gitmodules` exactly as `/gsd:quick` does (a fail-loud commit-time guard, applied per item at commit time — see `gsd-core/workflows/quick.md` Step 2 for the identical block, reused verbatim below):
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
if [ -f .gitmodules ]; then
|
|
87
|
+
SUBMODULE_PATHS=$(git config --file .gitmodules --get-regexp '^submodule\..*\.path$' 2>/dev/null | awk '{print $2}')
|
|
88
|
+
else
|
|
89
|
+
SUBMODULE_PATHS=""
|
|
90
|
+
fi
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Resolve capacity now (#3676 design row 3-4).** `--jobs auto`/omitted uses this
|
|
94
|
+
value alone; `--jobs N` is capped by it (`min(taskCount, N, capacity)` — the
|
|
95
|
+
`quick-batch effective-concurrency` verb, called per-wave below, does the
|
|
96
|
+
arithmetic; this is only the raw resolve):
|
|
97
|
+
```bash
|
|
98
|
+
CAPACITY=$(gsd_run query dispatch-capacity --raw 2>/dev/null || echo 1)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Resolve isolation now (row 6, 20-22).** Read
|
|
102
|
+
@gsd-core/references/dispatch-isolation-gate.md and run its `Resolve
|
|
103
|
+
ISOLATION`, `Single-agent dispatch sites`, and `Resolve the harness flag`
|
|
104
|
+
blocks in order; they set `ISOLATION`/`HARNESS_FLAG` via `query
|
|
105
|
+
dispatch-isolation`. `ISOLATION` gates every worktree decision below —
|
|
106
|
+
substitute `{harnessFlag}` in Step 6's `Agent()` with `$HARNESS_FLAG`+comma
|
|
107
|
+
when `ISOLATION = "harness-worktree"`, else empty.
|
|
108
|
+
|
|
109
|
+
If `USE_WORKTREES` is not `"false"`, sweep orphaned worktrees before dispatching anything (mirrors `/gsd:quick`'s own startup sweep):
|
|
110
|
+
```bash
|
|
111
|
+
if [ "$USE_WORKTREES" != "false" ]; then
|
|
112
|
+
gsd_run query worktree.reap-orphans 2>/dev/null || true
|
|
113
|
+
fi
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Display banner:
|
|
117
|
+
```
|
|
118
|
+
### GSD ► QUICK BATCH
|
|
119
|
+
◆ jobs=${JOBS} validate=${VALIDATE_MODE} research=${RESEARCH_MODE}${RESUME_BATCH_ID:+ resume=${RESUME_BATCH_ID}}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
**Step 2: Resume or create**
|
|
125
|
+
|
|
126
|
+
If `$RESUME_BATCH_ID` is set: read and execute `gsd-core/workflows/quick-batch/steps/resume-mode.md`.
|
|
127
|
+
It loads the batch via `quick-batch
|
|
128
|
+
resume`, refuses closed on an unknown batch id or a diverged base revision,
|
|
129
|
+
and sets `$BATCH_ID`/`$BATCH_MANIFEST_JSON` for the steps below. Task-list
|
|
130
|
+
parsing and `quick-batch create` are skipped entirely.
|
|
131
|
+
|
|
132
|
+
Otherwise: read and execute `gsd-core/workflows/quick-batch/steps/batch-init.md`.
|
|
133
|
+
It parses the task list (inline or `--file`) and creates the
|
|
134
|
+
batch via `quick-batch create`, setting the same `$BATCH_ID`/
|
|
135
|
+
`$BATCH_MANIFEST_JSON` pair.
|
|
136
|
+
|
|
137
|
+
Either path converges on the same post-condition — continue to Step 3.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
<!-- gsd:section id="research-phase" when="flag:--research" -->
|
|
142
|
+
If `section_manifest` is `null` or `"research-phase"` is in its `included` list: read and execute `gsd-core/workflows/quick-batch/steps/research-phase.md`. Otherwise skip — do not read the file.
|
|
143
|
+
<!-- /gsd:section -->
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
**Step 4: Per-DAG-layer planning**
|
|
148
|
+
|
|
149
|
+
Read and execute `gsd-core/workflows/quick-batch/steps/planner-wave.md`. It
|
|
150
|
+
dispatches a planner per eligible item (one `Agent()` per message, full task
|
|
151
|
+
catalog in every prompt), persists parsed `depends_on`/`files_modified` via
|
|
152
|
+
`quick-batch update` after each layer, and — when `$VALIDATE_MODE` — runs the
|
|
153
|
+
per-item plan-checker loop (`gsd-core/workflows/quick-batch/steps/plan-checker-loop.md`)
|
|
154
|
+
before advancing to the next layer.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
**Step 6: Worktree create + executor dispatch**
|
|
159
|
+
|
|
160
|
+
Read and execute `gsd-core/workflows/quick-batch/steps/worktree-dispatch.md`.
|
|
161
|
+
Worktree create/executor dispatch is serialized per item (one `git worktree
|
|
162
|
+
add` in flight at a time); already-created worktrees run concurrently up to
|
|
163
|
+
the effective MUTATING-wave concurrency.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
**Step 7: Deterministic merge**
|
|
168
|
+
|
|
169
|
+
Read and execute `gsd-core/workflows/quick-batch/steps/merge-wave.md`. Merges
|
|
170
|
+
apply strictly in the wave's original dispatch order (`quick-batch
|
|
171
|
+
merge-eligible`), never completion order.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
<!-- gsd:section id="verification-wave" when="flag:--validate" -->
|
|
176
|
+
If `section_manifest` is `null` or `"verification-wave"` is in its `included` list: read and execute `gsd-core/workflows/quick-batch/steps/verification-wave.md`. Otherwise skip — do not read the file.
|
|
177
|
+
<!-- /gsd:section -->
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
**Step 9: Completion**
|
|
182
|
+
|
|
183
|
+
Read and execute `gsd-core/workflows/quick-batch/steps/completion.md`. Calls
|
|
184
|
+
`completeQuickItem` (via `quick-batch complete`) only for a genuinely
|
|
185
|
+
complete item, updates STATE.md, and prints the final batch report.
|
|
186
|
+
|
|
187
|
+
</process>
|
|
188
|
+
|
|
189
|
+
<success_criteria>
|
|
190
|
+
- [ ] `--discuss`/`--full` rejected with a usage error before any dispatch
|
|
191
|
+
- [ ] A malformed `--jobs` value rejected before any dispatch
|
|
192
|
+
- [ ] `--resume <batch-id>` skips task-list parsing, dispatches only eligible items
|
|
193
|
+
- [ ] Task list parsed (inline or `--file`, ≥2 items) and batch created otherwise
|
|
194
|
+
- [ ] Planner dispatched per eligible item per DAG layer, full task catalog in prompt, `depends_on`/`files_modified` requested ALWAYS
|
|
195
|
+
- [ ] (--research) Researcher dispatched per item before planning
|
|
196
|
+
- [ ] (--validate) Plan-checker loop runs per item after planning (≤2 iterations)
|
|
197
|
+
- [ ] Worktree create/merge/cleanup serialized; concurrent leaves inside already-created worktrees
|
|
198
|
+
- [ ] `isolation == none` forces a mutating wave's concurrency to 1; a research-only wave is unaffected
|
|
199
|
+
- [ ] Merges apply in deterministic wave order, never completion order
|
|
200
|
+
- [ ] (--validate) Verifier dispatched per item post-merge; `human_needed` never completes the item, `gaps_found` fails it without rollback or retry
|
|
201
|
+
- [ ] A merge_failed/scope_violation item is marked failed with the worktree PRESERVED
|
|
202
|
+
- [ ] `completeQuickItem` called only for genuinely complete items; STATE.md updated; artifacts committed
|
|
203
|
+
</success_criteria>
|
|
@@ -43,7 +43,7 @@ _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-pars
|
|
|
43
43
|
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --raw --default "" 2>/dev/null || echo "")
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
**If `response_language` is set:** All user-facing questions, prompts, and explanations
|
|
46
|
+
**If `response_language` is set:** All user-facing output of this workflow — narration between tool calls, status updates, progress notes, findings, questions, prompts, and explanations — MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
|
|
47
47
|
|
|
48
48
|
If `$DESCRIPTION` is empty after parsing, prompt user interactively:
|
|
49
49
|
|
|
@@ -127,9 +127,10 @@ AGENT_SKILLS_PLANNER=$(gsd_run query agent-skills gsd-planner)
|
|
|
127
127
|
AGENT_SKILLS_EXECUTOR=$(gsd_run query agent-skills gsd-executor)
|
|
128
128
|
AGENT_SKILLS_CHECKER=$(gsd_run query agent-skills gsd-plan-checker)
|
|
129
129
|
AGENT_SKILLS_VERIFIER=$(gsd_run query agent-skills gsd-verifier)
|
|
130
|
+
AGENT_SKILLS_RESEARCHER=$(gsd_run query agent-skills gsd-phase-researcher)
|
|
130
131
|
```
|
|
131
132
|
|
|
132
|
-
Parse JSON for: `planner_model`, `executor_model`, `checker_model`, `verifier_model`, `reviewer_model`, `commit_docs`, `branch_name`, `quick_id`, `slug`, `date`, `timestamp`, `quick_dir`, `task_dir`, `roadmap_exists`, `planning_exists`, `response_language`.
|
|
133
|
+
Parse JSON for: `planner_model`, `executor_model`, `checker_model`, `verifier_model`, `reviewer_model`, `researcher_model`, `commit_docs`, `branch_name`, `quick_id`, `slug`, `date`, `timestamp`, `quick_dir`, `task_dir`, `roadmap_exists`, `planning_exists`, `response_language`.
|
|
133
134
|
|
|
134
135
|
`init.quick` does not emit dedicated `state_path`/`project_path` fields, so derive them from the already-absolute `quick_dir` (#2376 — files handed to a spawned subagent must resolve regardless of that subagent's own cwd):
|
|
135
136
|
```bash
|
|
@@ -286,6 +287,13 @@ If `section_manifest` is `null` or `"research-phase"` is in its `included` list:
|
|
|
286
287
|
|
|
287
288
|
**Step 5: Spawn planner (quick mode)**
|
|
288
289
|
|
|
290
|
+
**Capability gate:**
|
|
291
|
+
```bash
|
|
292
|
+
PLAN_PRE_HOOKS_JSON=$(gsd_run loop render-hooks plan:pre --raw)
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Contribution dispatch (#3778):** read `PLAN_PRE_HOOKS_JSON.activeHooks` directly in context. In registry order, inject only active entries with `kind == "contribution"` and `into == "planner"` into each Quick planner prompt below, using `fragment.inline` verbatim plus resolved `configValues`. Do not paste `rendered`. Empty, inactive, incompatible, or non-planner entries inject nothing and do not error. Reuse this snapshot for revisions; do not render again.
|
|
296
|
+
|
|
289
297
|
**If `$VALIDATE_MODE`:** Use `quick-full` mode with stricter constraints.
|
|
290
298
|
|
|
291
299
|
**If NOT `$VALIDATE_MODE`:** Use standard `quick` mode.
|
|
@@ -312,6 +320,8 @@ ${AGENT_SKILLS_PLANNER}
|
|
|
312
320
|
|
|
313
321
|
**Project skills:** Check .claude/skills/ or .agents/skills/ directory (if either exists) — read SKILL.md files, plans should account for project skill rules
|
|
314
322
|
|
|
323
|
+
{For each active entry in `PLAN_PRE_HOOKS_JSON` where `kind == "contribution"` and `into == "planner"` (in array order): inject the entry's `fragment.inline` verbatim here, plus its resolved `configValues` when the entry carries them. If no active planner contributions exist, omit this block entirely.}
|
|
324
|
+
|
|
315
325
|
</planning_context>
|
|
316
326
|
|
|
317
327
|
<constraints>
|
|
@@ -559,7 +569,14 @@ else
|
|
|
559
569
|
fi
|
|
560
570
|
|
|
561
571
|
if [ -n "$DIFF_BASE" ]; then
|
|
562
|
-
|
|
572
|
+
# #4466: bound the tip at the quick task's own last commit, not HEAD --
|
|
573
|
+
# QUICK_COMMITS is already the complete, newest-first list of this task's
|
|
574
|
+
# commits, so its first line is the correct tip. An unbounded `..HEAD`
|
|
575
|
+
# picks up any later commit landed on the same tree in the window between
|
|
576
|
+
# this task's commits and this review step (worktree merge-back, a shared
|
|
577
|
+
# tree, another session) and folds it into this task's own review scope.
|
|
578
|
+
QUICK_TIP=$(echo "$QUICK_COMMITS" | head -1)
|
|
579
|
+
CHANGED_FILES=$(git diff --name-only "${DIFF_BASE}..${QUICK_TIP}" -- . ':!.planning' 2>/dev/null | tr '\n' ' ')
|
|
563
580
|
else
|
|
564
581
|
CHANGED_FILES=""
|
|
565
582
|
fi
|
|
@@ -619,7 +636,7 @@ Insert after `### Blockers/Concerns` section:
|
|
|
619
636
|
|---|-------------|------|--------|-----------|
|
|
620
637
|
```
|
|
621
638
|
|
|
622
|
-
**Note:** If the table already exists
|
|
639
|
+
**Note:** If the table already exists in a legacy (pre-registry) column format, first run `gsd_run quick-tasks-migrate` — the maintainer-decided repair path (#3730) that rewrites the table onto the canonical schema, losslessly bucketing unmapped columns into Description. It is a silent no-op when the table is already canonical or the section is absent, so running it before the first append of every quick task migrates exactly once and never prompts otherwise. After migration, use the canonical column format below.
|
|
623
640
|
|
|
624
641
|
**7c. Append new row to table:**
|
|
625
642
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@~/.claude/gsd-core/references/response-language-directive.md
|
|
2
|
+
|
|
1
3
|
# Reapply Local Patches Workflow
|
|
2
4
|
|
|
3
5
|
Invoked by `/gsd:update --reapply` (`commands/gsd/update.md`).
|
|
@@ -167,7 +169,7 @@ Check if a `gsd-pristine/` directory exists alongside `gsd-local-patches/`:
|
|
|
167
169
|
```bash
|
|
168
170
|
PRISTINE_DIR="$CONFIG_DIR/gsd-pristine"
|
|
169
171
|
```
|
|
170
|
-
If it exists, the installer saved pristine copies at install time. Use these as the baseline.
|
|
172
|
+
If it exists, the installer saved pristine copies at install time. Use these as the baseline. Both the deterministic verifier and the installer's preserve-check resolve each file's snapshot at its canonical path first and, when that misses, by the SHA-256 recorded in `pristine_hashes` — so a snapshot stored at a legacy path (for example, without the `gsd-core/` prefix an earlier release dropped) is still found and, on the next update, relocated to its canonical path (#4145). When no snapshot resolves under `gsd-pristine/`, the deterministic verifier additionally falls back to Option A's git-history walk itself (read-only, same recorded-hash match), which is what keeps Step 5a coverage non-zero on multi-version updates where the hash-validated regeneration had nothing it could promote (#4135).
|
|
171
173
|
|
|
172
174
|
### Option C: No baseline available (two-way fallback)
|
|
173
175
|
If neither git history nor pristine snapshots are available, fall back to two-way comparison — but with **strengthened heuristics** (see Step 3).
|
|
@@ -190,6 +192,58 @@ If neither git history nor pristine snapshots are available, fall back to two-wa
|
|
|
190
192
|
|
|
191
193
|
## Step 4: Merge each file
|
|
192
194
|
|
|
195
|
+
### Step 4 pre-flight: classify superseded customizations (#4136)
|
|
196
|
+
|
|
197
|
+
Before merging anything, run the deterministic classifier. It computes, per backed-up file,
|
|
198
|
+
whether the user's added lines (diff of the backup against the hash-validated pristine
|
|
199
|
+
baseline) are ALREADY present verbatim in the newly installed version — i.e. upstream
|
|
200
|
+
adopted the customization. That is the only ground on which the `Incorporated` status
|
|
201
|
+
below is valid. Never conclude `Incorporated` from a signature line, a heading, or general
|
|
202
|
+
resemblance: the classifier excludes structural/trivial lines and requires every
|
|
203
|
+
significant user-added line to be present, because a false `Incorporated` silently retires
|
|
204
|
+
a live customization.
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
PRISTINE_DIR="${CONFIG_DIR}/gsd-pristine"
|
|
208
|
+
|
|
209
|
+
# Build args as a bash array so paths with spaces survive expansion intact.
|
|
210
|
+
CLASSIFY_ARGS=(
|
|
211
|
+
--patches-dir "$PATCHES_DIR"
|
|
212
|
+
--config-dir "$CONFIG_DIR"
|
|
213
|
+
)
|
|
214
|
+
if [ -d "$PRISTINE_DIR" ]; then
|
|
215
|
+
CLASSIFY_ARGS+=(--pristine-dir "$PRISTINE_DIR")
|
|
216
|
+
fi
|
|
217
|
+
CLASSIFY_ARGS+=(--classify --json)
|
|
218
|
+
|
|
219
|
+
# Informational: exits 0. The binding gate is Step 5a's post-merge verification run.
|
|
220
|
+
CLASSIFY_OUTPUT="$(node "${GSD_HOME}/gsd-core/bin/verify-reapply-patches.cjs" "${CLASSIFY_ARGS[@]}")"
|
|
221
|
+
INCORPORATED_FILES="$(echo "$CLASSIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));(d.incorporated_files||[]).forEach(f=>process.stdout.write(f+'\n'))")"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**For every file in `INCORPORATED_FILES`:**
|
|
225
|
+
|
|
226
|
+
- **Do NOT merge it. Do NOT re-apply its diff.** Leave the newly installed file exactly as
|
|
227
|
+
shipped — the user's customization is already in it. Re-grafting the diff onto a version
|
|
228
|
+
that already contains it duplicates the content (both copies run; a stale graft can
|
|
229
|
+
contradict a richer native upstream step that replaced it).
|
|
230
|
+
- Report the per-file status `Incorporated` — "Already in upstream v{version}" — in the
|
|
231
|
+
Step 3 summary and the Step 7 report.
|
|
232
|
+
- No Hunk Verification Table rows are required for these files (nothing was merged); the
|
|
233
|
+
classifier's structured output is the evidence. If EVERY backed-up file is Incorporated,
|
|
234
|
+
still emit the table with a header row and a single note line naming the incorporated
|
|
235
|
+
files, so the Step 5b absent-table halt is not tripped. Step 5a passes these files
|
|
236
|
+
without special-casing — every user-added line is present in the untouched install.
|
|
237
|
+
- This is what ends the re-graft cycle: because the installed file stays identical to what
|
|
238
|
+
the release ships, the next update's hash comparison no longer flags it as modified, and
|
|
239
|
+
the file drops out of `gsd-local-patches/` on the next cycle.
|
|
240
|
+
|
|
241
|
+
Files NOT in `INCORPORATED_FILES` — reported `needs_merge` (with the lines still missing
|
|
242
|
+
from the new version) or `unknown` (no confirmable pristine baseline) — take the normal
|
|
243
|
+
merge paths below, unchanged. If the classifier cannot run at all (e.g. `GSD_HOME`
|
|
244
|
+
unset), fall back to merging every file as before; never report `Incorporated` without the
|
|
245
|
+
classifier's structured confirmation.
|
|
246
|
+
|
|
193
247
|
For each file in `backup-meta.json`:
|
|
194
248
|
|
|
195
249
|
1. **Read the backed-up version** (user's modified copy from `gsd-local-patches/`)
|
|
@@ -207,6 +261,9 @@ Compare the three versions to isolate changes:
|
|
|
207
261
|
- Sections changed only by upstream → accept upstream version
|
|
208
262
|
- Sections changed by both → flag as CONFLICT, show both, ask user
|
|
209
263
|
- Sections unchanged by either → use new version (identical to all three)
|
|
264
|
+
- User-added content already present verbatim in the new version → already incorporated
|
|
265
|
+
upstream — do NOT re-apply it (the file-level outcome is `Incorporated` when ALL
|
|
266
|
+
user-added content is thus present, as determined by the Step 4 pre-flight classifier)
|
|
210
267
|
|
|
211
268
|
### Two-way merge (fallback when no baseline)
|
|
212
269
|
|
|
@@ -263,7 +320,7 @@ After writing each merged file, verify that user modifications survived the merg
|
|
|
263
320
|
6. **Report status per file:**
|
|
264
321
|
- `Merged` — user modifications applied cleanly (show summary of what was preserved)
|
|
265
322
|
- `Conflict` — user reviewed and chose resolution
|
|
266
|
-
- `Incorporated` — user's modification was already adopted upstream (only valid when pristine baseline confirms this)
|
|
323
|
+
- `Incorporated` — user's modification was already adopted upstream (only valid when pristine baseline confirms this — determined exclusively by the Step 4 pre-flight classifier's `incorporated_files`, never by inspection)
|
|
267
324
|
|
|
268
325
|
**Never report `Skipped — no custom content`.** If a file is in the backup, it has custom content.
|
|
269
326
|
|
|
@@ -305,9 +362,27 @@ VERIFY_STATUS=$?
|
|
|
305
362
|
DRIFTED_COUNT="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(String(d.drifted||0))")"
|
|
306
363
|
DRIFTED_FILES="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));(d.drifted_files||[]).forEach(f=>process.stdout.write(f+'\n'))")"
|
|
307
364
|
NO_BASELINE_COUNT="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(String(d.no_baseline||0))")"
|
|
308
|
-
NO_BASELINE_FILES="$(echo "$VERIFY_OUTPUT"
|
|
365
|
+
NO_BASELINE_FILES="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));(d.no_baseline_files||[]).forEach(f=>process.stdout.write(f+'\n'))")"
|
|
366
|
+
BASELINE_COVERED="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(String(d.baseline_covered||0))")"
|
|
367
|
+
CHECKED_COUNT="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(String(d.checked||0))")"
|
|
309
368
|
```
|
|
310
369
|
|
|
370
|
+
**Baseline coverage headline (#4135)** — BEFORE any pass/fail statement, print the coverage
|
|
371
|
+
N-of-M line. A run where 12 of 13 files were not diff-verified must never present the same way
|
|
372
|
+
as a fully-verified one:
|
|
373
|
+
|
|
374
|
+
```text
|
|
375
|
+
Baseline coverage: {BASELINE_COVERED} of {CHECKED_COUNT} file(s) verified against a pristine
|
|
376
|
+
baseline ({CHECKED_COUNT - BASELINE_COVERED} unverified)
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
The verifier also reports this on every run (JSON field `baseline_covered`; the human summary
|
|
380
|
+
leads with the same line). Operators who want the gate itself to fail on low coverage (cautious
|
|
381
|
+
environments) pass the opt-in strict flag when invoking the verifier:
|
|
382
|
+
`--min-baseline-coverage <fraction between 0 and 1>` — below the threshold the verifier exits
|
|
383
|
+
with code 3 (a real content failure still exits 1 and outranks it). Without the flag the
|
|
384
|
+
default advisory posture is unchanged.
|
|
385
|
+
|
|
311
386
|
**If `NO_BASELINE_COUNT` is greater than 0**, emit an advisory warning (non-blocking — the gate still exits 0 for these files). Do NOT halt:
|
|
312
387
|
|
|
313
388
|
```text
|
|
@@ -437,6 +512,7 @@ Ask user:
|
|
|
437
512
|
- [ ] No file classified as "no custom content" or "SKIP" — every backed-up file is definitionally modified
|
|
438
513
|
- [ ] Three-way merge used when pristine baseline available (git history or gsd-pristine/)
|
|
439
514
|
- [ ] User modifications identified and merged into new version
|
|
515
|
+
- [ ] Superseded customizations classified `Incorporated` by the deterministic pre-flight classifier (pristine-confirmed) and not re-grafted
|
|
440
516
|
- [ ] Conflicts surfaced to user with both versions shown
|
|
441
517
|
- [ ] Status reported for each file with summary of what was preserved
|
|
442
518
|
- [ ] Post-merge verification checks each file for dropped hunks and warns if content appears missing
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@~/.claude/gsd-core/references/response-language-directive.md
|
|
2
|
+
|
|
1
3
|
<purpose>
|
|
2
4
|
Remove an unstarted future phase from the project roadmap, delete its directory, renumber all subsequent phases to maintain a clean linear sequence, and commit the change. The git commit serves as the historical record of removal.
|
|
3
5
|
</purpose>
|
|
@@ -19,7 +19,7 @@ INIT=$(gsd_run query init.remove-workspace "$WORKSPACE_NAME")
|
|
|
19
19
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
**If `response_language` is set:** All user-facing questions, prompts, and explanations
|
|
22
|
+
**If `response_language` is set:** All user-facing output of this workflow — narration between tool calls, status updates, progress notes, findings, questions, prompts, and explanations — 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
24
|
Parse JSON for: `workspace_name`, `workspace_path`, `has_manifest`, `strategy`, `repos`, `repo_count`, `dirty_repos`, `has_dirty_repos`.
|
|
25
25
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@~/.claude/gsd-core/references/response-language-directive.md
|
|
2
|
+
|
|
1
3
|
<trigger>
|
|
2
4
|
Use this workflow when:
|
|
3
5
|
- Starting a new session on an existing project
|
|
@@ -25,10 +27,12 @@ INIT=$(gsd_run query init.resume)
|
|
|
25
27
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
Parse JSON for: `state_exists`, `roadmap_exists`, `project_exists`, `planning_exists`, `has_interrupted_agent`, `interrupted_agent_id`, `commit_docs`.
|
|
30
|
+
Parse JSON for: `state_exists`, `roadmap_exists`, `project_exists`, `planning_exists`, `requirements_exists`, `init_incomplete`, `has_interrupted_agent`, `interrupted_agent_id`, `commit_docs`.
|
|
31
|
+
|
|
32
|
+
**If `init_incomplete` is true (#4040 — interrupted bootstrap):** `.planning/` exists but initialization never finished — one or more of `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md` were never created. This is NOT a STATE.md-reconstruction case (there is no project history to reconstruct from). Route to initialization recovery: resume `/gsd:new-project`, which continues from the first missing artifact and keeps the existing PROJECT.md and any already-created artifacts. Do not proceed to load_state.
|
|
29
33
|
|
|
30
34
|
**If `state_exists` is true:** Proceed to load_state
|
|
31
|
-
**If `state_exists` is false but `roadmap_exists` or `project_exists` is true:** Offer to reconstruct STATE.md
|
|
35
|
+
**If `state_exists` is false but `roadmap_exists` or `project_exists` is true (and `init_incomplete` is false):** Offer to reconstruct STATE.md
|
|
32
36
|
**If `planning_exists` is false:** This is a new project - route to /gsd:new-project
|
|
33
37
|
</step>
|
|
34
38
|
|