@opengsd/gsd-core 1.18.0 → 1.20.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 +2 -1
- package/.opencode/plugins/gsd-core.js +2 -3
- package/agents/gsd-code-fixer.compact.md +7 -7
- package/agents/gsd-code-fixer.md +13 -7
- package/agents/gsd-code-reviewer.compact.md +49 -8
- package/agents/gsd-code-reviewer.md +53 -14
- package/agents/gsd-executor.md +8 -4
- package/agents/gsd-verifier.md +1 -1
- package/bin/install.js +422 -103
- package/commands/gsd/update.md +5 -2
- package/gsd-core/bin/gsd-tools.cjs +179 -30
- package/gsd-core/bin/lib/agent-install-check.cjs +29 -3
- package/gsd-core/bin/lib/args-terminator.cjs +114 -0
- package/gsd-core/bin/lib/broken-windows.cjs +59 -1
- package/gsd-core/bin/lib/capability-lifecycle.cjs +1 -12
- package/gsd-core/bin/lib/capability-lock.cjs +13 -2
- package/gsd-core/bin/lib/capability-registry.cjs +376 -103
- package/gsd-core/bin/lib/capability-state.cjs +14 -8
- package/gsd-core/bin/lib/capability-validator.cjs +32 -0
- package/gsd-core/bin/lib/commands.cjs +27 -17
- package/gsd-core/bin/lib/config-loader.cjs +13 -3
- package/gsd-core/bin/lib/config.cjs +256 -58
- package/gsd-core/bin/lib/core-utils.cjs +45 -0
- package/gsd-core/bin/lib/decision-coverage-support.cjs +74 -0
- package/gsd-core/bin/lib/frontmatter.cjs +21 -3
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +2 -2
- package/gsd-core/bin/lib/gate-context-drift.cjs +9 -4
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +6 -1
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +6 -1
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +134 -13
- package/gsd-core/bin/lib/gate-phase-context.cjs +7 -8
- package/gsd-core/bin/lib/gate-schema-drift.cjs +1 -1
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +63 -22
- package/gsd-core/bin/lib/gate-ui-safety.cjs +23 -5
- package/gsd-core/bin/lib/git-info-exclude.cjs +52 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +31 -12
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +9 -7
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +3 -3
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +4 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +52 -1
- package/gsd-core/bin/lib/host-integration.cjs +13 -6
- package/gsd-core/bin/lib/init.cjs +245 -68
- package/gsd-core/bin/lib/install-engine.cjs +246 -32
- package/gsd-core/bin/lib/install-profiles.cjs +9 -4
- package/gsd-core/bin/lib/installer-migration-report.cjs +2 -0
- package/gsd-core/bin/lib/io.cjs +6 -0
- package/gsd-core/bin/lib/markdown-line-diff.cjs +147 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +147 -1
- package/gsd-core/bin/lib/markdown-table.cjs +23 -0
- package/gsd-core/bin/lib/mcp-server.cjs +8 -5
- package/gsd-core/bin/lib/milestone-lock.cjs +8 -1
- package/gsd-core/bin/lib/milestone-release-map.cjs +244 -0
- package/gsd-core/bin/lib/milestone-release-tags.cjs +440 -0
- package/gsd-core/bin/lib/milestone.cjs +61 -51
- package/gsd-core/bin/lib/model-catalog.cjs +8 -0
- package/gsd-core/bin/lib/normalize-test-command.cjs +67 -0
- package/gsd-core/bin/lib/phase-entry-grammar.cjs +119 -0
- package/gsd-core/bin/lib/phase-id-display.cjs +2 -0
- package/gsd-core/bin/lib/phase-id.cjs +629 -38
- package/gsd-core/bin/lib/phase-lifecycle.cjs +12 -44
- package/gsd-core/bin/lib/phase-locator.cjs +328 -19
- package/gsd-core/bin/lib/phase.cjs +3066 -653
- package/gsd-core/bin/lib/planning-document.cjs +26 -5
- package/gsd-core/bin/lib/planning-inspect.cjs +27 -35
- package/gsd-core/bin/lib/planning-snapshot.cjs +15 -8
- package/gsd-core/bin/lib/planning-workspace.cjs +21 -3
- package/gsd-core/bin/lib/pristine-baseline.cjs +11 -3
- package/gsd-core/bin/lib/read-only-git-env.cjs +79 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +2 -2
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +57 -2
- package/gsd-core/bin/lib/review-lane-invocation.cjs +125 -18
- package/gsd-core/bin/lib/review-lane-runner.cjs +33 -4
- package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +11 -9
- package/gsd-core/bin/lib/roadmap-parser.cjs +735 -137
- package/gsd-core/bin/lib/roadmap-progress.cjs +136 -0
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +47 -7
- package/gsd-core/bin/lib/roadmap.cjs +383 -123
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +381 -14
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +8 -4
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +60 -16
- package/gsd-core/bin/lib/shell-command-projection.cjs +151 -19
- package/gsd-core/bin/lib/smart-entry.cjs +35 -11
- package/gsd-core/bin/lib/state-contract.cjs +39 -15
- package/gsd-core/bin/lib/state-document.cjs +344 -27
- package/gsd-core/bin/lib/state-transition.cjs +156 -32
- package/gsd-core/bin/lib/state.cjs +527 -186
- package/gsd-core/bin/lib/surface.cjs +9 -0
- package/gsd-core/bin/lib/task-command-router.cjs +5 -25
- package/gsd-core/bin/lib/task-content-resolution.cjs +46 -1
- package/gsd-core/bin/lib/template.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +3 -2
- package/gsd-core/bin/lib/vendor/re2js.cjs +863 -577
- package/gsd-core/bin/lib/vendor/re2js.d.cts +284 -219
- package/gsd-core/bin/lib/verification.cjs +96 -9
- package/gsd-core/bin/lib/verify.cjs +4 -2
- package/gsd-core/bin/lib/workstream-inventory.cjs +26 -20
- package/gsd-core/bin/lib/worktree-safety.cjs +22 -1
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +411 -10
- package/gsd-core/references/cicd-review-patterns.md +45 -0
- package/gsd-core/references/git-integration.md +11 -0
- package/gsd-core/references/loop-hook-dispatch.md +13 -6
- package/gsd-core/references/necessity-review.md +48 -0
- package/gsd-core/references/planning-config.md +2 -0
- package/gsd-core/references/tdd.md +2 -2
- package/gsd-core/templates/DEBUG.md +16 -0
- package/gsd-core/templates/config.json +2 -1
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/audit-fix.md +2 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +10 -1
- package/gsd-core/workflows/code-review-fix.md +46 -5
- package/gsd-core/workflows/code-review.md +64 -7
- package/gsd-core/workflows/complete-milestone/steps/project-md-evolution-review.md +145 -0
- package/gsd-core/workflows/complete-milestone/steps/release-map.md +80 -0
- package/gsd-core/workflows/complete-milestone.md +37 -150
- package/gsd-core/workflows/diagnose-issues.md +29 -5
- package/gsd-core/workflows/discuss-phase/modes/power.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +33 -2
- package/gsd-core/workflows/discuss-phase-power.md +19 -2
- package/gsd-core/workflows/discuss-phase.md +6 -10
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +13 -7
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +7 -2
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +11 -2
- package/gsd-core/workflows/execute-phase.md +10 -6
- package/gsd-core/workflows/execute-plan.md +1 -1
- package/gsd-core/workflows/health.md +2 -1
- package/gsd-core/workflows/import.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +2 -2
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +13 -9
- package/gsd-core/workflows/plan-phase.md +14 -14
- package/gsd-core/workflows/pr-branch.md +2 -0
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -1
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +8 -1
- package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +2 -1
- package/gsd-core/workflows/quick.md +1 -1
- package/gsd-core/workflows/reapply-patches.md +104 -0
- package/gsd-core/workflows/review.md +70 -154
- package/gsd-core/workflows/section-manifest.json +5 -0
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/settings-advanced.md +57 -9
- package/gsd-core/workflows/settings.md +1 -0
- package/gsd-core/workflows/ship.md +15 -4
- package/gsd-core/workflows/spec-phase.md +3 -6
- package/gsd-core/workflows/verify-work.md +4 -3
- package/hooks/dist/gsd-agent-isolation-guard.js +11 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
- package/hooks/dist/gsd-graphify-update.sh +6 -0
- package/hooks/dist/gsd-path-export.js +95 -0
- package/hooks/dist/gsd-secret-read-guard.js +172 -39
- package/hooks/dist/gsd-statusline.js +37 -3
- package/hooks/dist/gsd-windsurf-pre-write.js +29 -2
- package/hooks/dist/gsd-workflow-guard.js +3 -2
- package/hooks/dist/gsd-worktree-path-guard.js +29 -2
- package/hooks/dist/lib/git-probe.js +16 -0
- package/hooks/dist/lib/isolation-sentinel.js +44 -0
- package/hooks/dist/managed-hooks-registry.cjs +1 -0
- package/hooks/gsd-agent-isolation-guard.js +11 -1
- package/hooks/gsd-cursor-subagent-start.js +6 -2
- package/hooks/gsd-graphify-update.sh +6 -0
- package/hooks/gsd-path-export.js +95 -0
- package/hooks/gsd-secret-read-guard.js +172 -39
- package/hooks/gsd-statusline.js +37 -3
- package/hooks/gsd-windsurf-pre-write.js +29 -2
- package/hooks/gsd-workflow-guard.js +3 -2
- package/hooks/gsd-worktree-path-guard.js +29 -2
- package/hooks/hooks.json +1 -0
- package/hooks/lib/git-probe.js +16 -0
- package/hooks/lib/isolation-sentinel.js +44 -0
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +15 -8
- package/pi/gsd.cjs +1047 -10
- package/pi/package-agents/gsd-advisor-researcher.md +113 -0
- package/pi/package-agents/gsd-ai-researcher.md +111 -0
- package/pi/package-agents/gsd-assumptions-analyzer.md +110 -0
- package/pi/package-agents/gsd-code-fixer.md +774 -0
- package/pi/package-agents/gsd-code-reviewer.md +441 -0
- package/pi/package-agents/gsd-codebase-mapper.md +850 -0
- package/pi/package-agents/gsd-debug-session-manager.md +416 -0
- package/pi/package-agents/gsd-debugger.md +1274 -0
- package/pi/package-agents/gsd-doc-classifier.md +269 -0
- package/pi/package-agents/gsd-doc-synthesizer.md +259 -0
- package/pi/package-agents/gsd-doc-verifier.md +212 -0
- package/pi/package-agents/gsd-doc-writer.md +626 -0
- package/pi/package-agents/gsd-dom-verifier.md +164 -0
- package/pi/package-agents/gsd-domain-researcher.md +144 -0
- package/pi/package-agents/gsd-eval-auditor.md +185 -0
- package/pi/package-agents/gsd-eval-planner.md +149 -0
- package/pi/package-agents/gsd-executor.md +898 -0
- package/pi/package-agents/gsd-framework-selector.md +159 -0
- package/pi/package-agents/gsd-integration-checker.md +476 -0
- package/pi/package-agents/gsd-intel-updater.md +338 -0
- package/pi/package-agents/gsd-mempalace-curator.md +49 -0
- package/pi/package-agents/gsd-nyquist-auditor.md +200 -0
- package/pi/package-agents/gsd-pattern-mapper.md +340 -0
- package/pi/package-agents/gsd-phase-researcher.md +897 -0
- package/pi/package-agents/gsd-plan-checker.md +1077 -0
- package/pi/package-agents/gsd-planner.md +1003 -0
- package/pi/package-agents/gsd-project-researcher.md +611 -0
- package/pi/package-agents/gsd-research-synthesizer.md +259 -0
- package/pi/package-agents/gsd-roadmapper.md +779 -0
- package/pi/package-agents/gsd-security-auditor.md +171 -0
- package/pi/package-agents/gsd-ui-auditor.md +581 -0
- package/pi/package-agents/gsd-ui-checker.md +417 -0
- package/pi/package-agents/gsd-ui-researcher.md +469 -0
- package/pi/package-agents/gsd-user-profiler.md +174 -0
- package/pi/package-agents/gsd-verifier.md +963 -0
- package/pi/package-agents/manifest.json +39 -0
- package/pi/package-skills/gsd-add-tests/SKILL.md +39 -0
- package/pi/package-skills/gsd-ai-integration-phase/SKILL.md +36 -0
- package/pi/package-skills/gsd-audit-fix/SKILL.md +34 -0
- package/pi/package-skills/gsd-audit-milestone/SKILL.md +40 -0
- package/pi/package-skills/gsd-audit-uat/SKILL.md +26 -0
- package/pi/package-skills/gsd-autonomous/SKILL.md +52 -0
- package/pi/package-skills/gsd-capture/SKILL.md +68 -0
- package/pi/package-skills/gsd-cleanup/SKILL.md +25 -0
- package/pi/package-skills/gsd-code-review/SKILL.md +71 -0
- package/pi/package-skills/gsd-complete-milestone/SKILL.md +147 -0
- package/pi/package-skills/gsd-config/SKILL.md +60 -0
- package/pi/package-skills/gsd-debug/SKILL.md +64 -0
- package/pi/package-skills/gsd-discuss-phase/SKILL.md +74 -0
- package/pi/package-skills/gsd-docs-update/SKILL.md +50 -0
- package/pi/package-skills/gsd-eval-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-execute-phase/SKILL.md +62 -0
- package/pi/package-skills/gsd-explore/SKILL.md +26 -0
- package/pi/package-skills/gsd-extract-learnings/SKILL.md +25 -0
- package/pi/package-skills/gsd-fast/SKILL.md +33 -0
- package/pi/package-skills/gsd-forensics/SKILL.md +59 -0
- package/pi/package-skills/gsd-graphify/SKILL.md +210 -0
- package/pi/package-skills/gsd-health/SKILL.md +36 -0
- package/pi/package-skills/gsd-help/SKILL.md +37 -0
- package/pi/package-skills/gsd-import/SKILL.md +46 -0
- package/pi/package-skills/gsd-inbox/SKILL.md +42 -0
- package/pi/package-skills/gsd-ingest-docs/SKILL.md +43 -0
- package/pi/package-skills/gsd-manager/SKILL.md +46 -0
- package/pi/package-skills/gsd-map-codebase/SKILL.md +85 -0
- package/pi/package-skills/gsd-mempalace-capture/SKILL.md +111 -0
- package/pi/package-skills/gsd-mempalace-recall/SKILL.md +111 -0
- package/pi/package-skills/gsd-milestone-summary/SKILL.md +54 -0
- package/pi/package-skills/gsd-mvp-phase/SKILL.md +45 -0
- package/pi/package-skills/gsd-new-milestone/SKILL.md +49 -0
- package/pi/package-skills/gsd-new-project/SKILL.md +49 -0
- package/pi/package-skills/gsd-next/SKILL.md +34 -0
- package/pi/package-skills/gsd-ns-context/SKILL.md +31 -0
- package/pi/package-skills/gsd-ns-ideate/SKILL.md +30 -0
- package/pi/package-skills/gsd-ns-manage/SKILL.md +42 -0
- package/pi/package-skills/gsd-ns-project/SKILL.md +34 -0
- package/pi/package-skills/gsd-ns-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-ns-workflow/SKILL.md +44 -0
- package/pi/package-skills/gsd-onboard/SKILL.md +46 -0
- package/pi/package-skills/gsd-pause-work/SKILL.md +48 -0
- package/pi/package-skills/gsd-phase/SKILL.md +61 -0
- package/pi/package-skills/gsd-plan-phase/SKILL.md +62 -0
- package/pi/package-skills/gsd-plan-review-convergence/SKILL.md +63 -0
- package/pi/package-skills/gsd-pr-branch/SKILL.md +31 -0
- package/pi/package-skills/gsd-profile-user/SKILL.md +48 -0
- package/pi/package-skills/gsd-progress/SKILL.md +51 -0
- package/pi/package-skills/gsd-quick/SKILL.md +179 -0
- package/pi/package-skills/gsd-quick-batch/SKILL.md +114 -0
- package/pi/package-skills/gsd-resume-work/SKILL.md +31 -0
- package/pi/package-skills/gsd-review/SKILL.md +50 -0
- package/pi/package-skills/gsd-review-backlog/SKILL.md +65 -0
- package/pi/package-skills/gsd-secure-phase/SKILL.md +37 -0
- package/pi/package-skills/gsd-settings/SKILL.md +30 -0
- package/pi/package-skills/gsd-ship/SKILL.md +27 -0
- package/pi/package-skills/gsd-sketch/SKILL.md +56 -0
- package/pi/package-skills/gsd-spec-phase/SKILL.md +63 -0
- package/pi/package-skills/gsd-spike/SKILL.md +53 -0
- package/pi/package-skills/gsd-stats/SKILL.md +22 -0
- package/pi/package-skills/gsd-surface/SKILL.md +177 -0
- package/pi/package-skills/gsd-thread/SKILL.md +29 -0
- package/pi/package-skills/gsd-ui-phase/SKILL.md +35 -0
- package/pi/package-skills/gsd-ui-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-ultraplan-phase/SKILL.md +38 -0
- package/pi/package-skills/gsd-undo/SKILL.md +38 -0
- package/pi/package-skills/gsd-update/SKILL.md +54 -0
- package/pi/package-skills/gsd-validate-phase/SKILL.md +37 -0
- package/pi/package-skills/gsd-verify-work/SKILL.md +41 -0
- package/pi/package-skills/gsd-workspace/SKILL.md +57 -0
- package/pi/package-skills/gsd-workstreams/SKILL.md +73 -0
- package/scripts/build-hooks.js +4 -0
- package/scripts/ci-next-health.cjs +246 -23
- package/scripts/command-contract-helpers.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +22 -7
- package/scripts/gen-features.cjs +14 -2
- package/scripts/gen-health-docs.cjs +13 -1
- package/scripts/gen-pi-package-skills.cjs +217 -0
- package/scripts/lib/drift-scan.cjs +27 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +17 -1
- package/scripts/lib/platform-conformance-tier.generated.cjs +37 -1
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +3 -3
- package/scripts/lint-phase-enumeration-drift.cjs +8 -4
- package/scripts/lint-retired-runtime-name.cjs +5 -0
- package/scripts/lint-roadmap-progress-drift.cjs +421 -0
- package/scripts/mutation-matrix.cjs +23 -1
- package/scripts/npm-audit-baseline.cjs +41 -7
- package/scripts/reviewed-or-maintainer-policy.cjs +181 -0
- package/scripts/select-docs-guards.cjs +1 -1
- package/scripts/self-test-report-policy.cjs +350 -0
- package/scripts/sync-next-version.cjs +38 -6
- package/skills/gsd-update/SKILL.md +5 -2
- package/vscode/package.json +1 -1
- package/scripts/diagnose-validate-commit-in-tier.cjs +0 -270
- package/scripts/diagnose-validate-commit-phases.cjs +0 -348
- package/scripts/xtrace-phase-timing.cjs +0 -205
|
@@ -2,15 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
Detail for the `kind == "gate"` dispatch at the execute:wave:post hook point, extracted from the host step 5.7 (#3606 — the host file carries a frozen pre-phase-6 byte ceiling, #1168; evaluation detail lives here).
|
|
4
4
|
|
|
5
|
-
⚠ **Validate `check` before shell use** (third-party manifest input) — `gsd-core/references/loop-hook-dispatch.md` § `gate`.
|
|
5
|
+
⚠ **Validate `check` before shell use** (third-party manifest input; wherever `${hook.check.query}` appears, write the dot-normalized query, each `.` as `-`, and validate and pass that same value) — `gsd-core/references/loop-hook-dispatch.md` § `gate`.
|
|
6
6
|
|
|
7
|
-
**For each active entry where `kind == "gate"`** (process in array order), run the gate check — a `predicate` gate (ADR-2008 / #2008) uses the check CLI's `predicate` form with the predicate JSON and phase number (shown in the block below):
|
|
7
|
+
**For each active entry where `kind == "gate"`** (process in array order), run the gate check — a `predicate` gate (ADR-2008 / #2008) uses the check CLI's `predicate` form with the predicate JSON, phase directory and phase number (shown in the second block below):
|
|
8
|
+
|
|
9
|
+
When `check.query` is set (a named-query gate):
|
|
8
10
|
|
|
9
11
|
```bash
|
|
10
12
|
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
11
13
|
GATE_RESULT=$(gsd_run check ${hook.check.query} "${PHASE_NUMBER}" --raw) && CHECK_EXIT=0 || CHECK_EXIT=$?
|
|
12
14
|
```
|
|
13
15
|
|
|
16
|
+
When `check.predicate` is set (a predicate gate), pass every phase value this step holds (`phase_dir` and `phase_number` from the init bundle) (#5290):
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# same shell as the block above: gsd_run is already defined by its preamble
|
|
20
|
+
GATE_RESULT=$(gsd_run check predicate --predicate '<predicate JSON>' --phase-dir "${PHASE_DIR}" --phase-number "${PHASE_NUMBER}" --raw) && CHECK_EXIT=0 || CHECK_EXIT=$?
|
|
21
|
+
```
|
|
22
|
+
|
|
14
23
|
**Step 1 — did the CHECK COMMAND itself succeed?**
|
|
15
24
|
|
|
16
25
|
If the check command failed (non-zero `CHECK_EXIT`, empty output, or unparseable JSON):
|
|
@@ -605,11 +605,13 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
605
605
|
- Bad: "Executing terrain generation plan"
|
|
606
606
|
- Good: "Procedural terrain generator using Perlin noise — creates height maps and biome zones. Required before vehicle physics."
|
|
607
607
|
|
|
608
|
-
2.5. **Per-plan worktree decision (run for each plan in this wave BEFORE
|
|
608
|
+
2.5. **Per-plan worktree decision (run for each plan in this wave BEFORE any dispatch):**
|
|
609
609
|
|
|
610
|
-
Read and execute `gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md` for each plan. It extracts `PLAN_FILES` from the plan's JSON, intersects against `SUBMODULE_PATHS` (with normalization, bidirectional matching, and glob-prefix handling), and sets `USE_WORKTREES_FOR_PLAN` to `false` when the plan touches a submodule path. Append `plan_id` to a `WAVE_WORKTREE_PLANS` accumulator when `USE_WORKTREES_FOR_PLAN != false`.
|
|
610
|
+
Read and execute **Part 1** of `gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md` for each plan. It extracts `PLAN_FILES` from the plan's JSON, intersects against `SUBMODULE_PATHS` (with normalization, bidirectional matching, and glob-prefix handling), and sets `USE_WORKTREES_FOR_PLAN` to `false` when the plan touches a submodule path. Append `plan_id` to a `WAVE_WORKTREE_PLANS` accumulator when `USE_WORKTREES_FOR_PLAN != false`. **Store each plan's decision** (`plan_id → USE_WORKTREES_FOR_PLAN`): the shared `USE_WORKTREES_FOR_PLAN` value is overwritten by the next plan's decision.
|
|
611
611
|
|
|
612
|
-
The dispatch
|
|
612
|
+
The plan-scoped dispatch-isolation record is **not written here**. It is a single slot, so it is written in step 3, immediately before each plan's own dispatch (Part 2 of the gate, #5516).
|
|
613
|
+
|
|
614
|
+
The dispatch branches in step 3 gate on both `USE_WORKTREES` and the dispatched plan's own stored `USE_WORKTREES_FOR_PLAN` (#2474).
|
|
613
615
|
|
|
614
616
|
2.75. **Execute:wave:pre capability dispatch:**
|
|
615
617
|
|
|
@@ -632,6 +634,8 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
632
634
|
|
|
633
635
|
**Substitute `{plan_id}` in the prompt below with this plan's `id` field** from the `phase-plan-index` JSON loaded in step 1 (the same field referred to elsewhere in this workflow as `plan.id`) — unmodified and un-truncated, never a paraphrase. The guard hooks compare this value verbatim against the sentinel the per-plan gate wrote (`per-plan-worktree-gate.md`'s `plan_id`); a paraphrase or an omission costs the dispatch its recorded isolation decision.
|
|
634
636
|
|
|
637
|
+
**Record this plan's isolation immediately before its dispatch (#5516).** Restore the dispatched plan's **stored decision** from step 2.5 (`plan_id` := this plan's `id`, `USE_WORKTREES_FOR_PLAN` := the value stored for that plan, and `PLAN_FILES` / `PLAN_DELETIONS` re-extracted from this plan's JSON, since the later plans' decisions overwrote them) and run **Part 2** of `gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md`, so the single-slot sentinel names the plan being dispatched. Do not run it for any other plan, and do not batch it ahead of the dispatches.
|
|
638
|
+
|
|
635
639
|
**Executor routing (#1689/#3370).** Per plan, run `gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md` to set `EXECUTOR_TYPE` for `subagent_type="{EXECUTOR_TYPE}"` below.
|
|
636
640
|
|
|
637
641
|
**TDD-applicability resolution (#4266/#4272).** Run `gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md`.
|
|
@@ -954,7 +958,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
954
958
|
if [ "${TEST_EXIT}" -eq 0 ]; then
|
|
955
959
|
# Update ROADMAP plan progress for each completed plan in this wave
|
|
956
960
|
for plan_id in {completed_plan_ids}; do
|
|
957
|
-
gsd_run query roadmap.update-plan-progress "${PHASE_NUMBER}" "${plan_id}" "complete"
|
|
961
|
+
PROGRESS=$(gsd_run query roadmap.update-plan-progress "${PHASE_NUMBER}" "${plan_id}" "complete") && REASON=$(jq -er '.reason//""' <<<"$PROGRESS") && [ "$REASON" != missing_phase_details ] || { echo "ERROR: ROADMAP update-plan-progress did not complete for ${PHASE_NUMBER}-${plan_id} (missing_phase_details decline, failed query, or jq not installed). STOP: skip this plan's completion steps." >&2; exit 1; }
|
|
958
962
|
done
|
|
959
963
|
|
|
960
964
|
# Only commit tracking files if they actually changed
|
|
@@ -1114,8 +1118,8 @@ When executor returns a checkpoint AND `AUTO_MODE` is `true`:
|
|
|
1114
1118
|
[Awaiting section from agent return]
|
|
1115
1119
|
```
|
|
1116
1120
|
5. User responds: "approved"/"done" | issue description | decision selection
|
|
1117
|
-
6. **Spawn continuation agent (NOT resume)**
|
|
1118
|
-
- `{completed_tasks_table}`: From checkpoint return
|
|
1121
|
+
6. **Spawn continuation agent (NOT resume)** with a prompt built from these placeholders (there is no separate template file; this list is the contract):
|
|
1122
|
+
- `{completed_tasks_table}`: From checkpoint return, wrapped in a `<completed_tasks>` tag (the executor's continuation handling keys on it)
|
|
1119
1123
|
- `{resume_task_number}` + `{resume_task_name}`: Current task
|
|
1120
1124
|
- `{user_response}`: What user provided
|
|
1121
1125
|
- `{resume_instructions}`: Based on checkpoint type
|
|
@@ -504,7 +504,7 @@ IS_WORKTREE=$([ -f .git ] && echo "true" || echo "false")
|
|
|
504
504
|
|
|
505
505
|
if [ "$IS_WORKTREE" != "true" ]; then
|
|
506
506
|
# use_worktrees: false → this handler is the sole post-plan sync point (#2661)
|
|
507
|
-
gsd_run query roadmap.update-plan-progress "${PHASE}"
|
|
507
|
+
PROGRESS=$(gsd_run query roadmap.update-plan-progress "${PHASE}") && REASON=$(jq -er '.reason//""' <<<"$PROGRESS") && [ "$REASON" != missing_phase_details ] || { echo "ERROR: ROADMAP update-plan-progress did not complete for ${PHASE}-${PLAN} (missing_phase_details decline, failed query, or jq not installed). STOP: skip this plan's completion steps." >&2; exit 1; }
|
|
508
508
|
fi
|
|
509
509
|
```
|
|
510
510
|
Counts PLAN vs SUMMARY files on disk. Updates progress table row with correct count and status (`In Progress` or `Complete` with date).
|
|
@@ -249,7 +249,7 @@ Report final status.
|
|
|
249
249
|
| W027 | warning | Stale git worktree (not modified in a long time) | No |
|
|
250
250
|
| W028 | warning | A GSD-owned install scope shadows another on this machine | No |
|
|
251
251
|
| W029 | warning | .planning/ matches a gitignore rule but is still tracked by git (gitignore has no effect on already-tracked files) | No |
|
|
252
|
-
| W030 | warning | Phase verification report status is outside the closed set |
|
|
252
|
+
| W030 | warning | Phase verification report status is outside the closed set | Yes (known legacy statuses only) |
|
|
253
253
|
| I001 | info | Plan without SUMMARY (may be in progress) | No |
|
|
254
254
|
| I010 | info | Resolved CWD reported alongside the E010 home-directory guard | No |
|
|
255
255
|
|
|
@@ -266,6 +266,7 @@ Note: this table is **generated** — do not hand-edit it. It is produced by `no
|
|
|
266
266
|
| addNyquistKey | Add workflow.nyquist_validation: true to config.json | None — matches existing default |
|
|
267
267
|
| addAiIntegrationPhaseKey | Add workflow.ai_integration_phase: true to config.json | None — matches existing default |
|
|
268
268
|
| backfillMilestones | Synthesize missing MILESTONES.md entries from `.planning/milestones/vX.Y-ROADMAP.md` snapshots | None — additive only; triggered by `--backfill` flag |
|
|
269
|
+
| repairVerificationStatus | Rewrite a known legacy verification `status` (`pass_with_caveats`) to `passed`, keeping the original as `legacy_status` | None — only the `status` line changes; unknown statuses are never touched |
|
|
269
270
|
|
|
270
271
|
**Not repairable (too risky):**
|
|
271
272
|
- PROJECT.md, ROADMAP.md content
|
|
@@ -227,7 +227,7 @@ Agent({
|
|
|
227
227
|
|
|
228
228
|
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
|
|
229
229
|
|
|
230
|
-
Handle the checker return by severity, never by the sentinel alone: count BLOCKER + WARNING entries in the YAML issues block; an entry whose severity is missing or unrecognized counts as a BLOCKER (fail closed). If the return is `## VERIFICATION PASSED
|
|
230
|
+
Handle the checker return by severity, never by the sentinel alone: count BLOCKER + WARNING entries in the YAML issues block; an entry whose severity is missing or unrecognized counts as a BLOCKER (fail closed). A `## VERIFICATION PASSED` return that lists an entry whose severity is BLOCKER or WARNING, in the YAML issues block or listed in prose (a mention such as "no warnings" or a zero count is not an entry) is counted as `## ISSUES FOUND`, the prose entries counted as BLOCKER/WARNING entries (#5578). If the return is `## VERIFICATION PASSED` with no such entry, or the count is zero — every entry is explicitly INFO — display `ℹ advisory — {dimension}: {description}` per INFO entry and treat the plan as imported; INFO is advisory and never blocks an import (#3724). Otherwise:
|
|
231
231
|
- Display the blocking issues to the user
|
|
232
232
|
- Ask the user to resolve issues before the plan is considered imported
|
|
233
233
|
- Do not delete the written file — the user can fix and re-validate manually
|
|
@@ -50,7 +50,7 @@ Display:
|
|
|
50
50
|
Spawn the planner in **outline-only** mode — it must write only the outline manifest, not any
|
|
51
51
|
PLAN.md files:
|
|
52
52
|
|
|
53
|
-
**Dispatch/wait gate — `PLANNER_STALL_DETECTION_ENABLED
|
|
53
|
+
**Dispatch/wait gate — `PLANNER_STALL_DETECTION_ENABLED` (config key `planner.stall_detection_enabled`, resolved in `plan-phase/steps/stall-detection-helpers.md`):**
|
|
54
54
|
- **`true` (default):** use `run_in_background=true` in the Agent() call below, then use `gsd_stall_watch` after it.
|
|
55
55
|
|
|
56
56
|
```javascript
|
|
@@ -146,7 +146,7 @@ GSD_ARGS=${GSD_ARGS%$'\n'}
|
|
|
146
146
|
4. Spawn the planner in **single-plan** mode — it must write exactly one PLAN.md file. The prompt
|
|
147
147
|
is unchanged per plan; what changes is whether the runnable set's Agent() calls are issued one
|
|
148
148
|
at a time (serial) or together in one message (concurrent, every call still carrying
|
|
149
|
-
`run_in_background=true` exactly as today when `PLANNER_STALL_DETECTION_ENABLED` is `true`
|
|
149
|
+
`run_in_background=true` exactly as today when `PLANNER_STALL_DETECTION_ENABLED` (config key `planner.stall_detection_enabled`) is `true`
|
|
150
150
|
(default)):
|
|
151
151
|
```javascript
|
|
152
152
|
Agent(
|
|
@@ -103,23 +103,27 @@ PLANNER_STALL_THRESHOLD_MINUTES=$(gsd_run query config-get planner.stall_thresho
|
|
|
103
103
|
# a reliability risk this fix cannot afford: a malformed config value would
|
|
104
104
|
# abort the stall-watcher itself with a bash syntax error, silently defeating
|
|
105
105
|
# the exact hang-recovery this issue is about. Reject anything that is not a
|
|
106
|
-
# bare
|
|
107
|
-
# degrades to the safe default instead of crashing the watcher.
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
# bare positive integer before it is ever used, so a bad config value
|
|
107
|
+
# degrades to the safe default instead of crashing the watcher. Zero is
|
|
108
|
+
# rejected too (#3923): an interval of 0 makes every gsd_stall_watch cycle a
|
|
109
|
+
# zero-length sleep, and a threshold of 0 declares a healthy agent stalled on
|
|
110
|
+
# the first check. At most 9 digits, so `* 60` can never overflow.
|
|
111
|
+
[[ "$PLANNER_STALL_INTERVAL_MINUTES" =~ ^[1-9][0-9]{0,8}$ ]] || PLANNER_STALL_INTERVAL_MINUTES=5
|
|
112
|
+
[[ "$PLANNER_STALL_THRESHOLD_MINUTES" =~ ^[1-9][0-9]{0,8}$ ]] || PLANNER_STALL_THRESHOLD_MINUTES=10
|
|
110
113
|
|
|
111
114
|
# gsd_stall_should_recover — pure decision function, no IO, no sleeping. Given how
|
|
112
115
|
# long the orchestrator has been waiting plus two liveness signals (a completion
|
|
113
116
|
# marker found in the agent's output file, and fresh on-disk artifact activity),
|
|
114
117
|
# decides whether to keep waiting, treat the wait as satisfied, or auto-surface the
|
|
115
118
|
# existing accept/retry/stop recovery menu (9a/11a). Never kills or retries anything
|
|
116
|
-
# itself — it only classifies. Re-validates both numeric args as bare
|
|
117
|
-
# integers (defense in depth — safe to call with any input, not just
|
|
118
|
-
# config globals above) before either ever
|
|
119
|
+
# itself — it only classifies. Re-validates both numeric args as bounded bare
|
|
120
|
+
# non-negative integers (defense in depth — safe to call with any input, not just
|
|
121
|
+
# the resolved config globals above, which are always >= 1) before either ever
|
|
122
|
+
# reaches arithmetic expansion. It accepts 0 so callers can test boundaries.
|
|
119
123
|
gsd_stall_should_recover() {
|
|
120
124
|
local elapsed_seconds="$1" threshold_minutes="$2" marker_found="$3" artifact_fresh="$4"
|
|
121
|
-
[[ "$elapsed_seconds" =~ ^[0-9]
|
|
122
|
-
[[ "$threshold_minutes" =~ ^[0-9]
|
|
125
|
+
[[ "$elapsed_seconds" =~ ^[0-9]{1,15}$ ]] || elapsed_seconds=0
|
|
126
|
+
[[ "$threshold_minutes" =~ ^[0-9]{1,9}$ ]] || threshold_minutes=10
|
|
123
127
|
local threshold_seconds=$(( threshold_minutes * 60 ))
|
|
124
128
|
if [ "$marker_found" = "true" ]; then
|
|
125
129
|
echo "marker_received"; return 0
|
|
@@ -528,7 +528,7 @@ Read the `activeHooks` array directly from `PLAN_PRE_HOOKS_JSON` / `HOOKS_JSON`
|
|
|
528
528
|
- In pipeline / `--auto` mode, invoke the hook's `ref.skill` via `Skill(skill="gsd-${ref.skill}", args="${PHASE} --auto ${GSD_WS}")`.
|
|
529
529
|
- In manual mode, display the existing non-blocking `/gsd:ai-integration-phase {N}` recommendation and let the user continue planning without AI-SPEC or stop to run the capability workflow first.
|
|
530
530
|
|
|
531
|
-
Run the UI deterministic gate whenever **any** `plan:pre` UI hook is active — including the step-only case (`workflow.ui_safety_gate` off). (`check.query` = `"ui.plan-gate"
|
|
531
|
+
Run the UI deterministic gate whenever **any** `plan:pre` UI hook is active — including the step-only case (`workflow.ui_safety_gate` off). (`check.query` = `"ui.plan-gate"`, dot-normalized to `ui-plan-gate` per `loop-hook-dispatch.md` § `gate`.)
|
|
532
532
|
|
|
533
533
|
```bash
|
|
534
534
|
GATE=$(gsd_run check ui-plan-gate "${PHASE}" --raw) && GATE_EXIT=0 || GATE_EXIT=$?
|
|
@@ -635,10 +635,10 @@ SKETCH_FINDINGS_PATH=$(ls ./.claude/skills/sketch-findings-*/SKILL.md 2>/dev/nul
|
|
|
635
635
|
# Resolve the phase SPEC (carries the ## Edge Coverage section the planner lifts resolved
|
|
636
636
|
# edges from). UNCONDITIONAL — must NOT live in §4.5 Check AI-SPEC, which is skipped
|
|
637
637
|
# on non-AI phases; gating it there silently starves the planner of the SPEC (#550 review).
|
|
638
|
-
#
|
|
638
|
+
# init resolves the plain phase SPEC (never the -AI-SPEC.md / -UI-SPEC.md variants) through the one shared predicate.
|
|
639
639
|
PHASE_DIR_FOR_SPEC=$(_gsd_field "$INIT" phase_dir)
|
|
640
|
-
|
|
641
|
-
|
|
640
|
+
SPEC_PATH=$(_gsd_field "$INIT" spec_path)
|
|
641
|
+
SPEC_FILE="${SPEC_PATH}"
|
|
642
642
|
# Resolve the phase UI-SPEC separately (the glob above excludes -UI-SPEC.md); it carries the
|
|
643
643
|
# ## UI Considerations section the planner lifts by the same rule as ## Edge Coverage (#1867).
|
|
644
644
|
UI_SPEC_FILE=$(ls "${PHASE_DIR_FOR_SPEC}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
|
@@ -960,7 +960,7 @@ Every task MUST include these fields — they are NOT optional:
|
|
|
960
960
|
|
|
961
961
|
**If `CHUNKED_MODE` is `false` (default):** Spawn the planner as a single long-lived Agent:
|
|
962
962
|
|
|
963
|
-
**Dispatch/wait gate — `PLANNER_STALL_DETECTION_ENABLED
|
|
963
|
+
**Dispatch/wait gate — `PLANNER_STALL_DETECTION_ENABLED` (config key `planner.stall_detection_enabled`, resolved in `plan-phase/steps/stall-detection-helpers.md`):**
|
|
964
964
|
- **`true` (default):** use `run_in_background=true` in the Agent() call shown below, then use `gsd_stall_watch` as specified after it.
|
|
965
965
|
|
|
966
966
|
```text
|
|
@@ -1109,7 +1109,7 @@ Agent(
|
|
|
1109
1109
|
)
|
|
1110
1110
|
```
|
|
1111
1111
|
|
|
1112
|
-
**Dispatch/wait gate — `PLANNER_STALL_DETECTION_ENABLED
|
|
1112
|
+
**Dispatch/wait gate — `PLANNER_STALL_DETECTION_ENABLED` (config key `planner.stall_detection_enabled`, resolved in `plan-phase/steps/stall-detection-helpers.md`):**
|
|
1113
1113
|
- **`true` (default):** use `run_in_background=true` in the Agent() call above, then use `gsd_stall_watch` below.
|
|
1114
1114
|
|
|
1115
1115
|
**ORCHESTRATOR RULE — ALL RUNTIMES (when `PLANNER_STALL_DETECTION_ENABLED` is `true`):** `TS=$(date +%s)`; repeat `CHECKER_STALL_RESULT=$(gsd_stall_watch "$TS" "{outputFile}" "${PHASE_DIR}"'/*-PLAN.md' "## VERIFICATION PASSED" "## ISSUES FOUND")` while waiting/active.
|
|
@@ -1118,7 +1118,7 @@ Agent(
|
|
|
1118
1118
|
|
|
1119
1119
|
## 11. Handle Checker Return
|
|
1120
1120
|
|
|
1121
|
-
- **`marker_received` + `## VERIFICATION PASSED`:**
|
|
1121
|
+
- **`marker_received` + `## VERIFICATION PASSED`:** If the return lists an entry whose severity is BLOCKER or WARNING, in the YAML issues block or listed in prose (a mention such as "no warnings" or a zero count is not an entry), treat it as `## ISSUES FOUND` instead: display issues, check iteration count, proceed to step 12, which counts those prose entries as BLOCKER/WARNING entries (the no-YAML-block shortcut there does not apply). The sentinel never decides alone, and an entry with a missing or unrecognized severity counts as a BLOCKER (#5578). Otherwise display confirmation, proceed to step 13.
|
|
1122
1122
|
- **`marker_received` + `## ISSUES FOUND`:** Display issues, check iteration count, proceed to step 12.
|
|
1123
1123
|
- **`stalled`:** Automatically surface 11a's recovery choice (Accept verification / Retry checker / Stop) — no manual interrupt needed.
|
|
1124
1124
|
- **Empty / truncated / no recognized marker:** → Filesystem fallback (step 11a).
|
|
@@ -1143,7 +1143,7 @@ Track `stall_reentry_count` (starts at 0; incremented each time "Adjust approach
|
|
|
1143
1143
|
|
|
1144
1144
|
**If iteration_count < 3:**
|
|
1145
1145
|
|
|
1146
|
-
Parse issue count from checker return: count BLOCKER + WARNING entries in the YAML issues block (structured output from gsd-plan-checker); an entry whose severity is missing or unrecognized counts as a BLOCKER (fail closed). If the checker's return contains no YAML issues block (i.e., the plan was approved with no issues), treat `issue_count` as 0 and skip the stall check — the plan passed. Proceed to step 13 — likewise when every entry in the block is explicitly INFO (display them as advisories). Advisory format: `ℹ advisory — {dimension}: {description}` per INFO entry, listed once before the step-13 output.
|
|
1146
|
+
Parse issue count from checker return: count BLOCKER + WARNING entries in the YAML issues block (structured output from gsd-plan-checker); an entry whose severity is missing or unrecognized counts as a BLOCKER (fail closed). Entries a `## VERIFICATION PASSED` return lists in prose count the same way (#5578). If the checker's return contains no YAML issues block and lists no BLOCKER or WARNING entry in prose (i.e., the plan was approved with no issues), treat `issue_count` as 0 and skip the stall check — the plan passed. Proceed to step 13 — likewise when every entry in the block is explicitly INFO (display them as advisories). Advisory format: `ℹ advisory — {dimension}: {description}` per INFO entry, listed once before the step-13 output.
|
|
1147
1147
|
|
|
1148
1148
|
Display (only when entering the revision loop — skip if the paragraph above already proceeded to step 13): `Revision iteration {N}/3 -- {blocker_count} blockers, {warning_count} warnings`
|
|
1149
1149
|
|
|
@@ -1206,7 +1206,7 @@ Agent(
|
|
|
1206
1206
|
)
|
|
1207
1207
|
```
|
|
1208
1208
|
|
|
1209
|
-
**Dispatch/wait gate — `PLANNER_STALL_DETECTION_ENABLED
|
|
1209
|
+
**Dispatch/wait gate — `PLANNER_STALL_DETECTION_ENABLED` (config key `planner.stall_detection_enabled`, resolved in `plan-phase/steps/stall-detection-helpers.md`):**
|
|
1210
1210
|
- **`true` (default):** use `run_in_background=true` in the Agent() call above, then use `gsd_stall_watch` below.
|
|
1211
1211
|
|
|
1212
1212
|
**ORCHESTRATOR RULE — ALL RUNTIMES (when `PLANNER_STALL_DETECTION_ENABLED` is `true`):** (7.99; no marker, mtimes only) `TS=$(date +%s)`; repeat `PLANNER_STALL_RESULT=$(gsd_stall_watch "$TS" "{outputFile}" "${PHASE_DIR}"'/*-PLAN.md')` while waiting/active — `stalled` -> 1) Accept as revised, to step 13, 2) Retry, 3) Stop.
|
|
@@ -1288,7 +1288,7 @@ Spawn checker again (step 10), then increment `iteration_count`.
|
|
|
1288
1288
|
|
|
1289
1289
|
**If iteration_count >= 3:**
|
|
1290
1290
|
|
|
1291
|
-
Recount BLOCKER + WARNING by the same rule — an entry whose severity is missing or unrecognized counts as a BLOCKER (fail closed). If `issue_count` is 0 — PASSED, or every entry in the block is explicitly INFO — display any advisories and proceed to step 13; the gate below fires on everything else (#3724).
|
|
1291
|
+
Recount BLOCKER + WARNING by the same rule — an entry whose severity is missing or unrecognized counts as a BLOCKER (fail closed). If `issue_count` is 0 — PASSED with no BLOCKER/WARNING entry in the YAML block or in prose, or every entry in the block is explicitly INFO — display any advisories and proceed to step 13; the gate below fires on everything else (#3724).
|
|
1292
1292
|
|
|
1293
1293
|
Display: `Max iterations reached. {N} issues remain:` + issue list
|
|
1294
1294
|
|
|
@@ -1441,7 +1441,7 @@ This step is derived entirely from existing PLAN frontmatter — no extra LLM pa
|
|
|
1441
1441
|
gsd_run query roadmap.annotate-dependencies "${PHASE_NUMBER}"
|
|
1442
1442
|
```
|
|
1443
1443
|
|
|
1444
|
-
|
|
1444
|
+
Skip this step if `plan_count` is 0. Re-running regenerates the annotation from current PLAN frontmatter; an unchanged result writes nothing, and an unrecognised checklist row leaves ROADMAP.md untouched and reports `skipped: "unrecognised_checklist_row"`. The `**Cross-cutting constraints:**` header line ends in an HTML-comment marker; that block is machine-owned and the bullets directly under it are regenerated. Put hand-written bullets after a blank line. Bullets kept from a block written before the marker existed are reported as `stale_legacy_constraints`.
|
|
1445
1445
|
|
|
1446
1446
|
## 13d. Commit Plans if commit_docs is true
|
|
1447
1447
|
|
|
@@ -1478,7 +1478,7 @@ every other registered hook at this point).
|
|
|
1478
1478
|
|
|
1479
1479
|
**Step and contribution dispatch:** dispatch every `kind == "step"` hook and inject every `kind == "contribution"` fragment per @gsd-core/references/loop-hook-dispatch.md (skip each kind silently when none), before gate evaluation below.
|
|
1480
1480
|
|
|
1481
|
-
⚠ **Validate `check` before shell use** (third-party manifest input) — `loop-hook-dispatch.md` § `gate`.
|
|
1481
|
+
⚠ **Validate `check` before shell use** (third-party manifest input; wherever `${hook.check.query}` appears, write the dot-normalized query, each `.` as `-`, and validate and pass that same value) — `loop-hook-dispatch.md` § `gate`.
|
|
1482
1482
|
|
|
1483
1483
|
**For each active entry where `kind == "gate"`** (process in array order). **Dispatch by check shape** (the registry validates exactly one of `query`/`predicate`/`agentVerdict`):
|
|
1484
1484
|
|
|
@@ -1486,9 +1486,9 @@ every other registered hook at this point).
|
|
|
1486
1486
|
# named-query gate:
|
|
1487
1487
|
GATE_RESULT=$(gsd_run check ${hook.check.query} "${PHASE_DIR}" "${PHASE_REQ_IDS}" --raw) && CHECK_EXIT=0 || CHECK_EXIT=$?
|
|
1488
1488
|
```
|
|
1489
|
-
OR, for a generic `predicate` gate (ADR-2008 / #2008), inline the predicate as compact JSON (note the `--phase-dir`/`--phase-req-ids` flags feed `${PHASE_DIR}`/`${PHASE_REQ_IDS}` interpolation):
|
|
1489
|
+
OR, for a generic `predicate` gate (ADR-2008 / #2008), inline the predicate as compact JSON (note the `--phase-dir`/`--phase-number`/`--phase-req-ids` flags feed `${PHASE_DIR}`/`${PHASE_NUMBER}`/`${PHASE_REQ_IDS}` interpolation):
|
|
1490
1490
|
```bash
|
|
1491
|
-
GATE_RESULT=$(gsd_run check predicate --predicate '<hook.check.predicate as JSON>' --phase-dir "${PHASE_DIR}" --phase-req-ids "${PHASE_REQ_IDS}" --raw) && CHECK_EXIT=0 || CHECK_EXIT=$?
|
|
1491
|
+
GATE_RESULT=$(gsd_run check predicate --predicate '<hook.check.predicate as JSON>' --phase-dir "${PHASE_DIR}" --phase-number "${PHASE_NUMBER}" --phase-req-ids "${PHASE_REQ_IDS}" --raw) && CHECK_EXIT=0 || CHECK_EXIT=$?
|
|
1492
1492
|
```
|
|
1493
1493
|
(Read the hook's `check` object in-context to pick the branch; a gate with neither is a malformed registry entry — skip with a warning.)
|
|
1494
1494
|
|
|
@@ -90,6 +90,8 @@ jq dependency). Write dirty repo names to a temp file so the list survives acros
|
|
|
90
90
|
subsequent command executions:
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
|
+
# #5548: drop inherited repo-location vars (set inside git hooks) so cwd, not GIT_DIR, picks ROOT.
|
|
94
|
+
unset GIT_ALTERNATE_OBJECT_DIRECTORIES GIT_OBJECT_DIRECTORY GIT_DIR GIT_WORK_TREE GIT_IMPLICIT_WORK_TREE GIT_GRAFT_FILE GIT_INDEX_FILE GIT_NO_REPLACE_OBJECTS GIT_REPLACE_REF_BASE GIT_PREFIX GIT_SHALLOW_FILE GIT_COMMON_DIR
|
|
93
95
|
ROOT=$(git rev-parse --show-toplevel)
|
|
94
96
|
DIRTY_FILE=$(mktemp)
|
|
95
97
|
|
|
@@ -82,7 +82,7 @@ Agent(
|
|
|
82
82
|
|
|
83
83
|
**Handle checker return:**
|
|
84
84
|
|
|
85
|
-
- **`## VERIFICATION PASSED`:**
|
|
85
|
+
- **`## VERIFICATION PASSED`:** If the return lists an entry whose severity is BLOCKER or WARNING, in the YAML issues block or listed in prose (a mention such as "no warnings" or a zero count is not an entry), handle it as `## ISSUES FOUND` below, counting the prose entries as BLOCKER/WARNING entries; the sentinel never decides alone, and an entry with a missing or unrecognized severity counts as a BLOCKER (#5578). Otherwise display confirmation, proceed to step 6.
|
|
86
86
|
- **`## ISSUES FOUND`:** Count BLOCKER + WARNING entries in the YAML issues block; an entry whose severity is missing or unrecognized counts as a BLOCKER (fail closed). If zero — every entry is explicitly INFO — display `ℹ advisory — {dimension}: {description}` per entry and proceed to step 6; INFO is advisory and never enters the loop (#3724). Otherwise display issues, check iteration count, enter revision loop.
|
|
87
87
|
|
|
88
88
|
**Revision loop (max 2 iterations):**
|
|
@@ -16,7 +16,6 @@ _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-pars
|
|
|
16
16
|
QUICK_PLAN_PARENT=""
|
|
17
17
|
QUICK_PLAN_COMMIT=""
|
|
18
18
|
if [ "${USE_WORKTREES}" != "false" ]; then
|
|
19
|
-
QUICK_PLAN_PARENT=$(git rev-parse HEAD)
|
|
20
19
|
COMMIT_DOCS=$(gsd_run query config-get commit_docs --raw 2>/dev/null || echo "true")
|
|
21
20
|
if [ "$COMMIT_DOCS" != "false" ]; then
|
|
22
21
|
# pre-dispatch plan commit — PLAN.md is always in scope. CONTEXT.md/RESEARCH.md
|
|
@@ -52,5 +51,13 @@ if [ "${USE_WORKTREES}" != "false" ]; then
|
|
|
52
51
|
if [ -z "$QUICK_PLAN_COMMIT" ]; then
|
|
53
52
|
QUICK_PLAN_COMMIT=$(git rev-parse HEAD)
|
|
54
53
|
fi
|
|
54
|
+
# #5209: the alternate base is the PLAN commit's immediate parent, read AFTER the
|
|
55
|
+
# commit attempt so it holds whether the planner already committed the plan or this
|
|
56
|
+
# step just did. Empty when docs commits are off and for a root commit.
|
|
57
|
+
if [ "$COMMIT_DOCS" != "false" ]; then
|
|
58
|
+
_GSD_PLAN_AT=$(git log -1 --format=%H -- "${QUICK_DIR}/${quick_id}-PLAN.md" 2>/dev/null || true)
|
|
59
|
+
[ -n "$_GSD_PLAN_AT" ] || _GSD_PLAN_AT="$QUICK_PLAN_COMMIT"
|
|
60
|
+
QUICK_PLAN_PARENT=$(git rev-parse --verify --quiet "${_GSD_PLAN_AT}^" 2>/dev/null || true)
|
|
61
|
+
fi
|
|
55
62
|
fi
|
|
56
63
|
```
|
|
@@ -73,7 +73,8 @@ that require a ROADMAP phase goal.
|
|
|
73
73
|
counts as BLOCKER, fail closed; pure INFO entries are advisory only and never
|
|
74
74
|
enter the revision loop):
|
|
75
75
|
|
|
76
|
-
- **`## VERIFICATION PASSED`** or all-INFO: proceed to the next item.
|
|
76
|
+
- **`## VERIFICATION PASSED`** (with no BLOCKER/WARNING entry) or all-INFO: proceed to the next item.
|
|
77
|
+
- **`## VERIFICATION PASSED` that nevertheless lists an entry whose severity is BLOCKER or WARNING, in the YAML issues block or listed in prose (a mention such as "no warnings" or a zero count is not an entry):** handled as `## ISSUES FOUND`, counting the prose entries as BLOCKER/WARNING entries; the sentinel never decides alone (#5578).
|
|
77
78
|
- **Any BLOCKER/WARNING:** revision loop, max 2 iterations total for this item.
|
|
78
79
|
|
|
79
80
|
**Revision (iteration < 2):**
|
|
@@ -541,7 +541,7 @@ SUMMARY.md and stop — the user must rerun with worktrees disabled.
|
|
|
541
541
|
|
|
542
542
|
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
|
|
543
543
|
|
|
544
|
-
If the executor ran isolated (`ISOLATION = "harness-worktree"` at dispatch), append its returned `{agent_id, worktree_path, branch, expected_base, allowed_bases}` metadata to `QUICK_WORKTREE_MANIFEST` before cleanup. Set `expected_base` to `${EXPECTED_BASE}` and `allowed_bases` to `["${EXPECTED_BASE}", "${QUICK_PLAN_PARENT}"]` with duplicates removed. If any required field is unavailable, stop and ask for recovery; do not discover global worktrees.
|
|
544
|
+
If the executor ran isolated (`ISOLATION = "harness-worktree"` at dispatch), append its returned `{agent_id, worktree_path, branch, expected_base, allowed_bases}` metadata to `QUICK_WORKTREE_MANIFEST` before cleanup. Set `expected_base` to `${EXPECTED_BASE}` and `allowed_bases` to `["${EXPECTED_BASE}", "${QUICK_PLAN_PARENT}"]` with duplicates and empty values removed. If any required field is unavailable, stop and ask for recovery; do not discover global worktrees.
|
|
545
545
|
|
|
546
546
|
After executor returns:
|
|
547
547
|
1. **Worktree cleanup:** If the executor ran isolated (`ISOLATION = "harness-worktree"` at dispatch), merge the worktree branch back and clean up:
|
|
@@ -10,6 +10,21 @@ After a GSD update wipes and reinstalls files, this workflow merges user's previ
|
|
|
10
10
|
|
|
11
11
|
<process>
|
|
12
12
|
|
|
13
|
+
## Step 0: Parse interactive mode (#4435)
|
|
14
|
+
|
|
15
|
+
Read the arguments passed after `--reapply`:
|
|
16
|
+
|
|
17
|
+
- no `--interactive` → `INTERACTIVE_MODE=off` (the default; Step 4 runs exactly as before)
|
|
18
|
+
- bare `--interactive` or `--interactive=exceptions` → `INTERACTIVE_MODE=exceptions`
|
|
19
|
+
- `--interactive=all` → `INTERACTIVE_MODE=all`
|
|
20
|
+
- any other `--interactive=<value>` → STOP with: `unknown --interactive value '<value>' (expected exceptions or all)`. Do not reapply anything.
|
|
21
|
+
|
|
22
|
+
When the mode is not `off`, tell the user once, before the first prompt: on the first interactive run
|
|
23
|
+
for this install, `--interactive=all` is recommended, because the recommendations have not yet been
|
|
24
|
+
checked against this install's customizations.
|
|
25
|
+
|
|
26
|
+
**Text mode (`workflow.text_mode: true` in config or `--text` flag):** Set `TEXT_MODE=true` if `--text` is present in the arguments OR `workflow.text_mode` 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 where `AskUserQuestion` is not available.
|
|
27
|
+
|
|
13
28
|
## Step 1: Detect backed-up patches
|
|
14
29
|
|
|
15
30
|
Check for local patches directory:
|
|
@@ -250,6 +265,75 @@ merge paths below, unchanged. If the classifier cannot run at all (e.g. `GSD_HOM
|
|
|
250
265
|
unset), fall back to merging every file as before; never report `Incorporated` without the
|
|
251
266
|
classifier's structured confirmation.
|
|
252
267
|
|
|
268
|
+
### Step 4 interactive review (#4435) — only when `INTERACTIVE_MODE` is not `off`
|
|
269
|
+
|
|
270
|
+
Verbatim matching cannot see an edit that upstream adopted in different words, an edit whose
|
|
271
|
+
surrounding stock text upstream rewrote, or an edit whose anchor lines upstream deleted. Interactive
|
|
272
|
+
mode shows each user edit (hunk) and lets the USER decide. Present and gate: the tool recommends,
|
|
273
|
+
the user decides, and nothing is retired without the user's answer.
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
DECISIONS_FILE="$(mktemp "${TMPDIR:-/tmp}/gsd-reapply-decisions.XXXXXX")"
|
|
277
|
+
HUNKS_ARGS=(
|
|
278
|
+
--patches-dir "$PATCHES_DIR"
|
|
279
|
+
--config-dir "$CONFIG_DIR"
|
|
280
|
+
)
|
|
281
|
+
if [ -d "$PRISTINE_DIR" ]; then
|
|
282
|
+
HUNKS_ARGS+=(--pristine-dir "$PRISTINE_DIR")
|
|
283
|
+
fi
|
|
284
|
+
HUNKS_ARGS+=(--hunks --json)
|
|
285
|
+
|
|
286
|
+
# Informational: exits 0. Each hunk carries hunk_hash, kind, stock_lines, user_lines,
|
|
287
|
+
# recommendation (keep | retire | review), reasons, and exception (true/false).
|
|
288
|
+
HUNKS_OUTPUT="$(node "${GSD_HOME}/gsd-core/bin/verify-reapply-patches.cjs" "${HUNKS_ARGS[@]}")"
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
The decisions file lives in a temp directory, never inside `gsd-local-patches/`, because the
|
|
292
|
+
Step 5a gate treats every file in that directory as a backed-up patch.
|
|
293
|
+
|
|
294
|
+
For each file in `HUNKS_OUTPUT.files`, for each hunk:
|
|
295
|
+
|
|
296
|
+
- `INTERACTIVE_MODE=all`: present EVERY hunk.
|
|
297
|
+
- `INTERACTIVE_MODE=exceptions`: present only hunks with `exception: true`. Every other hunk is kept
|
|
298
|
+
without asking. Print one summary line for each:
|
|
299
|
+
`kept without review: {file} hunk {hunk_id}: "{first user line, truncated to 60 chars}"`.
|
|
300
|
+
|
|
301
|
+
Presenting a hunk means asking the user one question (`AskUserQuestion`, or under TEXT_MODE a
|
|
302
|
+
plain-text numbered list the user answers by number) that shows:
|
|
303
|
+
|
|
304
|
+
- **Stock text:** `stock_lines` (or "(none — your lines were inserted)" when empty)
|
|
305
|
+
- **Your text:** `user_lines` (or "(none — you deleted the stock text)" when empty)
|
|
306
|
+
- **Recommendation:** `recommendation`, with `reasons` explained in plain words:
|
|
307
|
+
`already_upstream` (the shipped file already has it), `partially_upstream` (only some of it is
|
|
308
|
+
there), `region_changed_upstream` (upstream also changed this spot, for example by rewording it),
|
|
309
|
+
`anchor_orphaned` (the lines it sat between are gone), `baseline_unconfirmed` (no verified
|
|
310
|
+
pre-update copy, so read the whole file), `diff_too_large` (the file changed too much to split it
|
|
311
|
+
into separate edits)
|
|
312
|
+
- Options: **Keep** (graft it), **Retire** (drop it; keep upstream's text), **Rewrite** (the user
|
|
313
|
+
supplies replacement text, which is applied instead)
|
|
314
|
+
|
|
315
|
+
Write a decision entry only from the user's answer to that hunk's question. Never write `retire` or
|
|
316
|
+
`rewrite` for a hunk the user was not asked about, and never pick an answer on the user's behalf,
|
|
317
|
+
even when the recommendation is `retire`. A hunk kept without review in `exceptions` mode is
|
|
318
|
+
recorded as `keep`. Record each answer in `DECISIONS_FILE` as JSON:
|
|
319
|
+
|
|
320
|
+
```json
|
|
321
|
+
{ "decisions": [ { "file": "<file>", "hunk_hash": "<hunk_hash>", "disposition": "keep|retire|rewrite" } ] }
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
A `rewrite` entry must also carry `"replacement_lines": [...]` — exactly the lines the user supplied.
|
|
325
|
+
The Step 5a gate then requires those lines to be present in the merged file, so a rewrite is verified
|
|
326
|
+
like any kept edit. `keep` and `retire` entries never carry `replacement_lines`.
|
|
327
|
+
|
|
328
|
+
Shell variables do not survive between separate command invocations. Write `INTERACTIVE_MODE` and the
|
|
329
|
+
`DECISIONS_FILE` path down when you set them, and set both again in the same command that runs the
|
|
330
|
+
Step 5a verifier.
|
|
331
|
+
|
|
332
|
+
Then merge each file with the paths below, applying only `keep` hunks and the user's replacement
|
|
333
|
+
text for `rewrite` hunks. A file whose hunks were all retired is left exactly as installed and
|
|
334
|
+
reported `Incorporated` ("Retired by user decision"). A file with some hunks retired is reported
|
|
335
|
+
`Merged` with "{N} hunk(s) retired by user decision".
|
|
336
|
+
|
|
253
337
|
For each file in `backup-meta.json`:
|
|
254
338
|
|
|
255
339
|
1. **Read the backed-up version** (user's modified copy from `gsd-local-patches/`)
|
|
@@ -352,6 +436,11 @@ VERIFY_ARGS=(
|
|
|
352
436
|
if [ -d "$PRISTINE_DIR" ]; then
|
|
353
437
|
VERIFY_ARGS+=(--pristine-dir "$PRISTINE_DIR")
|
|
354
438
|
fi
|
|
439
|
+
# #4435: hunks the user retired or rewrote are excused only through the recorded,
|
|
440
|
+
# hash-bound decisions. A decision whose hunk no longer matches exits 2 (stale).
|
|
441
|
+
if [ "$INTERACTIVE_MODE" != "off" ] && [ -s "$DECISIONS_FILE" ]; then
|
|
442
|
+
VERIFY_ARGS+=(--decisions "$DECISIONS_FILE")
|
|
443
|
+
fi
|
|
355
444
|
VERIFY_ARGS+=(--json)
|
|
356
445
|
|
|
357
446
|
# Capture stdout (the structured JSON report) separately from stderr so that
|
|
@@ -456,6 +545,18 @@ Then re-run /gsd:update --reapply to re-verify.
|
|
|
456
545
|
|
|
457
546
|
Do not proceed to cleanup until the verifier exits 0.
|
|
458
547
|
|
|
548
|
+
**If `VERIFY_STATUS` is 2 and stderr names a `stale decision`** (#4435), a recorded answer no longer
|
|
549
|
+
matches its hunk because the backup or baseline changed after the user saw it. STOP, discard
|
|
550
|
+
`DECISIONS_FILE`, and re-run `/gsd:update --reapply --interactive` so the user decides on the current
|
|
551
|
+
text. Never edit the decisions file to make it match.
|
|
552
|
+
|
|
553
|
+
When decisions were passed, the JSON report carries `decisions.retired` — every hunk excused by a
|
|
554
|
+
user `retire` or `rewrite` decision. Before Step 6, show the user this list (file, hunk id,
|
|
555
|
+
disposition) and ask them to confirm that each one is a decision they made. The gate can prove that a
|
|
556
|
+
decision matches the exact text that was shown, but not who made it, so the user's confirmation of
|
|
557
|
+
this list is the final check. If the user disowns any entry, restore that hunk from the backup and
|
|
558
|
+
re-run Step 5a without it. List each confirmed entry in the Step 7 report.
|
|
559
|
+
|
|
459
560
|
**Only when `VERIFY_STATUS` is 0** (or when all files had zero significant user-added lines, which the verifier reports as `Failures: 0`) may execution continue to gate 5b.
|
|
460
561
|
|
|
461
562
|
### 5b: Hunk Verification Table review (advisory gate, #1999)
|
|
@@ -493,6 +594,8 @@ Do not proceed to cleanup until both gates (5a and 5b) pass.
|
|
|
493
594
|
|
|
494
595
|
## Step 6: Cleanup option
|
|
495
596
|
|
|
597
|
+
If `DECISIONS_FILE` was created (#4435), delete it now: `rm -f "$DECISIONS_FILE"`.
|
|
598
|
+
|
|
496
599
|
Ask user:
|
|
497
600
|
- "Keep patch backups for reference?" → preserve `gsd-local-patches/`
|
|
498
601
|
- "Clean up patch backups?" → remove `gsd-local-patches/` directory
|
|
@@ -520,6 +623,7 @@ Ask user:
|
|
|
520
623
|
- [ ] User modifications identified and merged into new version
|
|
521
624
|
- [ ] Superseded customizations classified `Incorporated` by the deterministic pre-flight classifier (pristine-confirmed) and not re-grafted
|
|
522
625
|
- [ ] Conflicts surfaced to user with both versions shown
|
|
626
|
+
- [ ] With `--interactive`, every presented hunk was decided by the user (never by the agent), retired/rewritten hunks were passed to the Step 5a gate through the hash-bound decisions file, and each retirement is listed in the report
|
|
523
627
|
- [ ] Status reported for each file with summary of what was preserved
|
|
524
628
|
- [ ] Post-merge verification checks each file for dropped hunks and warns if content appears missing
|
|
525
629
|
</success_criteria>
|