@opengsd/gsd-core 1.7.0 → 1.8.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 +14 -0
- package/README.md +2 -0
- package/agents/gsd-debug-session-manager.md +42 -4
- package/agents/gsd-debugger.md +87 -29
- package/agents/gsd-executor.md +29 -2
- package/agents/gsd-planner.md +29 -36
- package/agents/gsd-verifier.md +2 -2
- package/bin/install.js +1152 -80
- package/commands/gsd/ai-integration-phase.md +1 -1
- package/commands/gsd/mempalace-capture.md +9 -5
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/plan-phase.md +5 -3
- package/commands/gsd/plan-review-convergence.md +3 -2
- package/gsd-core/bin/gsd-tools.cjs +1878 -2507
- package/gsd-core/bin/lib/adapter-imperative.cjs +8 -1
- package/gsd-core/bin/lib/agent-command-router.cjs +20 -5
- package/gsd-core/bin/lib/api-coverage.cjs +338 -45
- package/gsd-core/bin/lib/broken-windows.cjs +716 -0
- package/gsd-core/bin/lib/capability-command-router.cjs +733 -0
- package/gsd-core/bin/lib/capability-registry.cjs +155 -86
- package/gsd-core/bin/lib/capability-writer.cjs +6 -1
- package/gsd-core/bin/lib/check-command-router.cjs +128 -25
- package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +115 -27
- package/gsd-core/bin/lib/claude-orchestration.cjs +84 -9
- package/gsd-core/bin/lib/command-aliases.cjs +14 -0
- package/gsd-core/bin/lib/commands.cjs +81 -4
- package/gsd-core/bin/lib/config-loader.cjs +14 -2
- package/gsd-core/bin/lib/config.cjs +69 -18
- package/gsd-core/bin/lib/core-utils.cjs +6 -1
- package/gsd-core/bin/lib/decisions.cjs +32 -8
- package/gsd-core/bin/lib/docs.cjs +6 -0
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +14 -2
- package/gsd-core/bin/lib/gap-checker.cjs +17 -2
- package/gsd-core/bin/lib/init.cjs +111 -47
- package/gsd-core/bin/lib/install-engine.cjs +298 -23
- package/gsd-core/bin/lib/install-profiles.cjs +239 -1
- package/gsd-core/bin/lib/installer-migrations/005-opencode-baseline-commands-dir.cjs +146 -0
- package/gsd-core/bin/lib/installer-migrations/006-pi-extension-cjs-to-js.cjs +91 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +44 -5
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +107 -0
- package/gsd-core/bin/lib/milestone.cjs +246 -12
- package/gsd-core/bin/lib/model-catalog.cjs +19 -4
- package/gsd-core/bin/lib/model-resolver.cjs +189 -7
- package/gsd-core/bin/lib/onboard-projection.cjs +11 -8
- package/gsd-core/bin/lib/phase-id.cjs +26 -4
- package/gsd-core/bin/lib/phase.cjs +201 -12
- package/gsd-core/bin/lib/plan-scan.cjs +70 -2
- package/gsd-core/bin/lib/roadmap-parser.cjs +7 -4
- package/gsd-core/bin/lib/roadmap.cjs +13 -3
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +7 -1
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +22 -8
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +16 -0
- package/gsd-core/bin/lib/smart-entry.cjs +69 -4
- package/gsd-core/bin/lib/state-document.cjs +7 -4
- package/gsd-core/bin/lib/state-transition.cjs +22 -1
- package/gsd-core/bin/lib/state.cjs +65 -11
- package/gsd-core/bin/lib/surface.cjs +51 -9
- package/gsd-core/bin/lib/uat.cjs +420 -5
- package/gsd-core/bin/lib/validate.cjs +12 -8
- package/gsd-core/bin/lib/verification.cjs +112 -17
- package/gsd-core/bin/lib/verify.cjs +220 -22
- package/gsd-core/bin/shared/config-schema.manifest.json +3 -2
- package/gsd-core/references/api-coverage.md +37 -7
- package/gsd-core/references/checkpoints.md +1 -1
- package/gsd-core/references/common-bug-patterns.md +13 -0
- package/gsd-core/references/debugger-bug-taxonomy.md +111 -0
- package/gsd-core/references/debugger-fix-acceptance.md +157 -0
- package/gsd-core/references/debugger-philosophy.md +1 -0
- package/gsd-core/references/debugger-prevention.md +98 -0
- package/gsd-core/references/debugger-rca-branching.md +98 -0
- package/gsd-core/references/debugger-repro-hardening.md +130 -0
- package/gsd-core/references/debugger-sbfl.md +110 -0
- package/gsd-core/references/debugger-semantic-recall.md +81 -0
- package/gsd-core/references/execute-phase-quota-recovery.md +55 -0
- package/gsd-core/references/execute-phase-requirement-revert.md +8 -0
- package/gsd-core/references/execute-phase-response-language.md +7 -0
- package/gsd-core/references/planner-antipatterns.md +6 -0
- package/gsd-core/references/planner-mvp-mode.md +12 -13
- package/gsd-core/references/planner-preconditions.md +156 -0
- package/gsd-core/references/planner-reversibility.md +132 -0
- package/gsd-core/references/reviewer-instances.md +9 -7
- package/gsd-core/references/skeleton-template.md +1 -1
- package/gsd-core/references/thinking-models-planning.md +3 -1
- package/gsd-core/templates/DEBUG.md +5 -3
- package/gsd-core/workflows/add-phase.md +2 -0
- package/gsd-core/workflows/add-tests.md +3 -1
- package/gsd-core/workflows/add-todo.md +32 -1
- package/gsd-core/workflows/ai-integration-phase.md +4 -2
- package/gsd-core/workflows/audit-fix.md +2 -2
- package/gsd-core/workflows/check-todos.md +3 -1
- package/gsd-core/workflows/cleanup.md +7 -1
- package/gsd-core/workflows/code-review.md +17 -5
- package/gsd-core/workflows/complete-milestone.md +3 -0
- package/gsd-core/workflows/debug.md +25 -5
- package/gsd-core/workflows/diagnose-issues.md +1 -1
- package/gsd-core/workflows/discovery-phase.md +7 -0
- package/gsd-core/workflows/discuss-phase/templates/context.md +16 -2
- package/gsd-core/workflows/discuss-phase-assumptions.md +3 -0
- package/gsd-core/workflows/do.md +7 -1
- package/gsd-core/workflows/docs-update.md +1 -0
- package/gsd-core/workflows/eval-review.md +3 -0
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +4 -4
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -2
- package/gsd-core/workflows/execute-phase.md +25 -34
- package/gsd-core/workflows/execute-plan.md +15 -4
- package/gsd-core/workflows/graduation.md +3 -0
- package/gsd-core/workflows/health.md +7 -1
- package/gsd-core/workflows/help/modes/full.md +6 -2
- package/gsd-core/workflows/import.md +8 -2
- package/gsd-core/workflows/inbox.md +7 -0
- package/gsd-core/workflows/ingest-docs.md +15 -10
- package/gsd-core/workflows/manager.md +3 -1
- package/gsd-core/workflows/map-codebase.md +4 -4
- package/gsd-core/workflows/mvp-phase.md +3 -0
- package/gsd-core/workflows/new-milestone.md +69 -21
- package/gsd-core/workflows/new-project.md +17 -15
- package/gsd-core/workflows/new-workspace.md +3 -1
- package/gsd-core/workflows/onboard.md +3 -0
- package/gsd-core/workflows/plan-phase.md +14 -5
- package/gsd-core/workflows/plan-review-convergence.md +48 -3
- package/gsd-core/workflows/plant-seed.md +3 -0
- package/gsd-core/workflows/profile-user.md +7 -1
- package/gsd-core/workflows/progress.md +31 -3
- package/gsd-core/workflows/quick.md +19 -7
- package/gsd-core/workflows/remove-workspace.md +3 -0
- package/gsd-core/workflows/review.md +89 -73
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -0
- package/gsd-core/workflows/settings-integrations.md +3 -0
- package/gsd-core/workflows/settings.md +3 -0
- package/gsd-core/workflows/ship.md +50 -3
- package/gsd-core/workflows/sketch.md +3 -0
- package/gsd-core/workflows/smart-entry.md +3 -0
- package/gsd-core/workflows/spike.md +7 -1
- package/gsd-core/workflows/ui-phase.md +3 -1
- package/gsd-core/workflows/ui-review.md +3 -0
- package/gsd-core/workflows/undo.md +7 -0
- package/gsd-core/workflows/update.md +2 -0
- package/gsd-core/workflows/validate-phase.md +3 -0
- package/gsd-core/workflows/verify-phase.md +2 -2
- package/gsd-core/workflows/verify-work.md +7 -3
- package/hooks/dist/gsd-context-monitor.js +27 -9
- package/hooks/dist/gsd-statusline.js +88 -3
- package/hooks/gsd-context-monitor.js +27 -9
- package/hooks/gsd-statusline.js +88 -3
- package/package.json +6 -4
- package/pi/gsd.cjs +8 -2
- package/scripts/changeset/lint.cjs +1 -0
- package/scripts/changeset/parse.cjs +26 -0
- package/scripts/check-glossary-refs.cjs +220 -0
- package/scripts/ci-rebase-check.cjs +48 -4
- package/scripts/gen-adr-index.cjs +526 -0
- package/scripts/gen-test-timings.cjs +201 -0
- package/scripts/lint-portable-timeout.cjs +140 -0
- package/scripts/lint-test-file-count.allowlist.json +1 -0
- package/scripts/release-tarball-smoke.cjs +18 -11
- package/scripts/run-tests.cjs +420 -58
- package/skills/gsd-ai-integration-phase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +9 -5
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-plan-phase/SKILL.md +5 -3
- package/skills/gsd-plan-review-convergence/SKILL.md +3 -2
- package/vscode/package.json +1 -1
|
@@ -131,6 +131,19 @@ CONTEXT: [✓ if has_context | - if not]
|
|
|
131
131
|
## Pending Todos
|
|
132
132
|
- [count] pending — /gsd:capture --list to review
|
|
133
133
|
|
|
134
|
+
## Open Windows
|
|
135
|
+
- [count] open in `.planning/WINDOWS.md` — /gsd:ship blocks while any remain
|
|
136
|
+
(Only show this section if count > 0; suppressed when ledger is empty or absent)
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
WINDOWS_STATUS=$(gsd_run windows status --raw 2>/dev/null || echo '')
|
|
140
|
+
WINDOWS_OPEN=$(printf '%s' "$WINDOWS_STATUS" | jq -r '.ledger.open_count // 0' 2>/dev/null || echo 0)
|
|
141
|
+
WINDOWS_WAIVED=$(printf '%s' "$WINDOWS_STATUS" | jq -r '.ledger.waived_count // 0' 2>/dev/null || echo 0)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Render `Open Windows` only when `$WINDOWS_OPEN` is greater than `0` (or `$WINDOWS_WAIVED` is greater than `0`, so an auditable deferral history remains visible). Phrase: `{WINDOWS_OPEN} open, {WINDOWS_WAIVED} waived — resolves with /gsd:ship gate; inspect via gsd-tools windows status`. The ledger is cross-phase; the count is the project total, not the current phase's.
|
|
145
|
+
|
|
146
|
+
|
|
134
147
|
## Active Debug Sessions
|
|
135
148
|
- [count] active — /gsd:debug to continue
|
|
136
149
|
(Only show this section if count > 0)
|
|
@@ -264,6 +277,7 @@ Track: `outstanding_debt` — `summary.total_items` from the audit.
|
|
|
264
277
|
|-------|------|-------|
|
|
265
278
|
| {phase} | {filename} | {pending_count} pending, {skipped_count} skipped, {blocked_count} blocked |
|
|
266
279
|
| {phase} | {filename} | human_needed — {count} items |
|
|
280
|
+
| {phase} | {filename} | {unresolved_count} deferred items |
|
|
267
281
|
|
|
268
282
|
Review: `/gsd:audit-uat ${GSD_WS}` — full cross-phase audit
|
|
269
283
|
Resume testing: `/gsd:verify-work {phase} ${GSD_WS}` — retest specific phase
|
|
@@ -675,7 +689,7 @@ If `--forensic` IS present: after the standard report and routing suggestion hav
|
|
|
675
689
|
|
|
676
690
|
## Forensic Integrity Audit
|
|
677
691
|
|
|
678
|
-
Running
|
|
692
|
+
Running 7 deep checks against project state...
|
|
679
693
|
|
|
680
694
|
Run each check in order. For each check, emit ✓ (pass) or ⚠ (warning) with concrete evidence when a problem is found.
|
|
681
695
|
|
|
@@ -748,11 +762,24 @@ Emit:
|
|
|
748
762
|
- ✓ `Working tree clean` — if no modified files outside `.planning/`
|
|
749
763
|
- ⚠ `Uncommitted changes in source files` — list up to 10 file paths
|
|
750
764
|
|
|
765
|
+
**Check 7 — Unresolved deferred items**
|
|
766
|
+
|
|
767
|
+
Glob every phase directory's SCOPE BOUNDARY log (executor writes out-of-scope discoveries here per `agents/gsd-executor.md`):
|
|
768
|
+
```bash
|
|
769
|
+
ls .planning/phases/*/deferred-items.md 2>/dev/null || true
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
For each `deferred-items.md` found, read its entries (bullet list, one entry per top-level `- ` line, continuation lines indented beneath it). An entry is RESOLVED only if it carries an explicit `status: resolved` field (case-insensitive) on one of its lines; every other entry — including one with no `status:` field at all — is UNRESOLVED and must be surfaced (fail-safe: never silently drop a possibly-open item).
|
|
773
|
+
|
|
774
|
+
Emit:
|
|
775
|
+
- ✓ `No unresolved deferred items` — if no `deferred-items.md` files exist, or every entry in every file is `status: resolved`
|
|
776
|
+
- ⚠ `Unresolved deferred items found` — list each file's phase directory and its unresolved entry text (max 5 per file, truncated at 80 chars)
|
|
777
|
+
|
|
751
778
|
---
|
|
752
779
|
|
|
753
|
-
After all
|
|
780
|
+
After all 7 checks, display the verdict:
|
|
754
781
|
|
|
755
|
-
**If all
|
|
782
|
+
**If all 7 checks passed:**
|
|
756
783
|
```
|
|
757
784
|
### Verdict: CLEAN
|
|
758
785
|
|
|
@@ -773,6 +800,7 @@ Then for each failed check, add a concrete next action:
|
|
|
773
800
|
- Check 4 (memory pending): `Review the flagged memory entries and resolve or clear them`
|
|
774
801
|
- Check 5 (blocking todos): `Complete the operational steps in .planning/todos/pending/ before continuing`
|
|
775
802
|
- Check 6 (uncommitted code): `Commit or stash the uncommitted changes before advancing`
|
|
803
|
+
- Check 7 (unresolved deferred items): `Address each deferred item and mark it status: resolved in its deferred-items.md, or fold it into the roadmap`
|
|
776
804
|
- Check 1 (STATE inconsistency): `Run /gsd:verify-work ${PHASE} ${GSD_WS} to reconcile state`
|
|
777
805
|
</step>
|
|
778
806
|
|
|
@@ -38,6 +38,13 @@ Parse `$ARGUMENTS` for:
|
|
|
38
38
|
|
|
39
39
|
After parsing, normalize: if `$DISCUSS_MODE` and `$RESEARCH_MODE` and `$VALIDATE_MODE` are all true, set `$FULL_MODE=true`. This ensures `--discuss --research --validate` is treated identically to `--full`.
|
|
40
40
|
|
|
41
|
+
```bash
|
|
42
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; 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
|
|
43
|
+
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --default "" 2>/dev/null || echo "")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**If `response_language` is set:** All user-facing questions, prompts, and explanations in this workflow MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
|
|
47
|
+
|
|
41
48
|
If `$DESCRIPTION` is empty after parsing, prompt user interactively:
|
|
42
49
|
|
|
43
50
|
|
|
@@ -125,7 +132,6 @@ If `$VALIDATE_MODE` only:
|
|
|
125
132
|
**Step 2: Initialize**
|
|
126
133
|
|
|
127
134
|
```bash
|
|
128
|
-
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; 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
|
|
129
135
|
INIT=$(gsd_run query init.quick "$DESCRIPTION")
|
|
130
136
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
131
137
|
AGENT_SKILLS_PLANNER=$(gsd_run query agent-skills gsd-planner)
|
|
@@ -134,7 +140,13 @@ AGENT_SKILLS_CHECKER=$(gsd_run query agent-skills gsd-plan-checker)
|
|
|
134
140
|
AGENT_SKILLS_VERIFIER=$(gsd_run query agent-skills gsd-verifier)
|
|
135
141
|
```
|
|
136
142
|
|
|
137
|
-
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`.
|
|
143
|
+
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`.
|
|
144
|
+
|
|
145
|
+
`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):
|
|
146
|
+
```bash
|
|
147
|
+
STATE_PATH="$(dirname "${quick_dir}")/STATE.md"
|
|
148
|
+
PROJECT_PATH="$(dirname "${quick_dir}")/PROJECT.md"
|
|
149
|
+
```
|
|
138
150
|
|
|
139
151
|
```bash
|
|
140
152
|
USE_WORKTREES=$(gsd_run query config-get workflow.use_worktrees --raw 2>/dev/null || echo "true")
|
|
@@ -247,7 +259,7 @@ mkdir -p "${task_dir}"
|
|
|
247
259
|
Create the directory for this quick task:
|
|
248
260
|
|
|
249
261
|
```bash
|
|
250
|
-
QUICK_DIR="
|
|
262
|
+
QUICK_DIR="${task_dir}"
|
|
251
263
|
mkdir -p "$QUICK_DIR"
|
|
252
264
|
```
|
|
253
265
|
|
|
@@ -413,8 +425,8 @@ Agent(
|
|
|
413
425
|
**Output:** ${QUICK_DIR}/${quick_id}-RESEARCH.md
|
|
414
426
|
|
|
415
427
|
<files_to_read>
|
|
416
|
-
-
|
|
417
|
-
-
|
|
428
|
+
- ${STATE_PATH} (Project state — what's already built)
|
|
429
|
+
- ${PROJECT_PATH} (Project context)
|
|
418
430
|
- ./CLAUDE.md or ./.claude/CLAUDE.md (if exists — project-specific guidelines)
|
|
419
431
|
${DISCUSS_MODE ? '- ' + QUICK_DIR + '/' + quick_id + '-CONTEXT.md (User decisions — research should align with these)' : ''}
|
|
420
432
|
</files_to_read>
|
|
@@ -473,7 +485,7 @@ Agent(
|
|
|
473
485
|
**Description:** ${DESCRIPTION}
|
|
474
486
|
|
|
475
487
|
<files_to_read>
|
|
476
|
-
-
|
|
488
|
+
- ${STATE_PATH} (Project State)
|
|
477
489
|
- ./CLAUDE.md or ./.claude/CLAUDE.md (if exists — follow project-specific guidelines)
|
|
478
490
|
${DISCUSS_MODE ? '- ' + QUICK_DIR + '/' + quick_id + '-CONTEXT.md (User decisions — locked, do not revisit)' : ''}
|
|
479
491
|
${RESEARCH_MODE ? '- ' + QUICK_DIR + '/' + quick_id + '-RESEARCH.md (Research findings — use to inform implementation choices)' : ''}
|
|
@@ -732,7 +744,7 @@ fi
|
|
|
732
744
|
|
|
733
745
|
<files_to_read>
|
|
734
746
|
- ${QUICK_DIR}/${quick_id}-PLAN.md (Plan)
|
|
735
|
-
-
|
|
747
|
+
- ${STATE_PATH} (Project state)
|
|
736
748
|
- ./CLAUDE.md or ./.claude/CLAUDE.md (Project instructions, if exists)
|
|
737
749
|
- .claude/skills/ or .agents/skills/ (Project skills, if either exists — list skills, read SKILL.md for each, follow relevant rules during implementation)
|
|
738
750
|
</files_to_read>
|
|
@@ -14,10 +14,13 @@ Extract workspace name from $ARGUMENTS.
|
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; 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
|
|
17
|
+
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --default "" 2>/dev/null || echo "")
|
|
17
18
|
INIT=$(gsd_run query init.remove-workspace "$WORKSPACE_NAME")
|
|
18
19
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
19
20
|
```
|
|
20
21
|
|
|
22
|
+
**If `response_language` is set:** All user-facing questions, prompts, and explanations in this workflow MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
|
|
23
|
+
|
|
21
24
|
Parse JSON for: `workspace_name`, `workspace_path`, `has_manifest`, `strategy`, `repos`, `repo_count`, `dirty_repos`, `has_dirty_repos`.
|
|
22
25
|
|
|
23
26
|
**If no workspace name provided:**
|
|
@@ -119,10 +119,20 @@ Collect phase artifacts for the review prompt:
|
|
|
119
119
|
```bash
|
|
120
120
|
INIT=$(gsd_run query init.phase-op "${PHASE_ARG}")
|
|
121
121
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
122
|
+
|
|
123
|
+
# #2358: ONE run-scoped temp dir (portable via ${TMPDIR:-/tmp}) so overlapping
|
|
124
|
+
# runs never collide or read each other's stale files.
|
|
125
|
+
RUN_DIR=$(mktemp -d "${TMPDIR:-/tmp}/gsd-review-XXXXXX")
|
|
126
|
+
echo "RUN_DIR=$RUN_DIR"
|
|
122
127
|
```
|
|
123
128
|
|
|
124
129
|
Read from init: `phase_dir`, `phase_number`, `padded_phase`.
|
|
125
130
|
|
|
131
|
+
Capture `RUN_DIR` above (created ONCE) and thread it into every `{run_dir}`
|
|
132
|
+
placeholder and `$RUN_DIR`/`${RUN_DIR}` reference within a bash block. Do NOT
|
|
133
|
+
re-run `mktemp -d` later — every block must resolve to this same directory, or
|
|
134
|
+
`build_prompt`'s writes and `invoke_reviewers`' reads split.
|
|
135
|
+
|
|
126
136
|
Then read:
|
|
127
137
|
1. `.planning/PROJECT.md` (first 80 lines — project context)
|
|
128
138
|
2. Phase section from `.planning/ROADMAP.md`
|
|
@@ -189,40 +199,42 @@ Focus on:
|
|
|
189
199
|
Output your review in markdown format.
|
|
190
200
|
```
|
|
191
201
|
|
|
192
|
-
Write to a temp file:
|
|
202
|
+
Write to a temp file: `{run_dir}/gsd-review-prompt.md`
|
|
193
203
|
|
|
194
204
|
Also write individual section files so the budget tool can re-trim per reviewer:
|
|
195
205
|
|
|
196
206
|
```bash
|
|
207
|
+
RUN_DIR="{run_dir}" # from gather_context
|
|
208
|
+
|
|
197
209
|
# Write individual section files for per-reviewer budget trimming
|
|
198
210
|
# These are always written so reviewers with a budget can invoke prompt-budget
|
|
199
|
-
cp "$INSTRUCTIONS_BLOCK_FILE" "/
|
|
200
|
-
cp "$ROADMAP_SECTION_FILE" "/
|
|
211
|
+
cp "$INSTRUCTIONS_BLOCK_FILE" "${RUN_DIR}/gsd-review-instructions.md"
|
|
212
|
+
cp "$ROADMAP_SECTION_FILE" "${RUN_DIR}/gsd-review-roadmap.md"
|
|
201
213
|
|
|
202
214
|
# Plan files: copy each PLAN.md to a predictable numbered path
|
|
203
215
|
PLAN_INDEX=0
|
|
204
216
|
for PLAN_FILE in "${PHASE_DIR}"/*-PLAN.md; do
|
|
205
217
|
PADDED_IDX=$(printf '%02d' "$PLAN_INDEX")
|
|
206
|
-
cp "$PLAN_FILE" "/
|
|
218
|
+
cp "$PLAN_FILE" "${RUN_DIR}/gsd-review-plan-${PADDED_IDX}.md"
|
|
207
219
|
PLAN_INDEX=$((PLAN_INDEX + 1))
|
|
208
220
|
done
|
|
209
221
|
|
|
210
222
|
# Optional section files (only if content was included in the combined prompt)
|
|
211
223
|
if [ -f ".planning/PROJECT.md" ]; then
|
|
212
|
-
cp .planning/PROJECT.md "/
|
|
224
|
+
cp .planning/PROJECT.md "${RUN_DIR}/gsd-review-project.md"
|
|
213
225
|
fi
|
|
214
226
|
if ls "${PHASE_DIR}/"*"-CONTEXT.md" >/dev/null 2>&1; then
|
|
215
|
-
cat "${PHASE_DIR}/"*"-CONTEXT.md" > "/
|
|
227
|
+
cat "${PHASE_DIR}/"*"-CONTEXT.md" > "${RUN_DIR}/gsd-review-context.md"
|
|
216
228
|
fi
|
|
217
229
|
if ls "${PHASE_DIR}/"*"-RESEARCH.md" >/dev/null 2>&1; then
|
|
218
|
-
cat "${PHASE_DIR}/"*"-RESEARCH.md" > "/
|
|
230
|
+
cat "${PHASE_DIR}/"*"-RESEARCH.md" > "${RUN_DIR}/gsd-review-research.md"
|
|
219
231
|
fi
|
|
220
232
|
if [ -f ".planning/REQUIREMENTS.md" ]; then
|
|
221
|
-
cp .planning/REQUIREMENTS.md "/
|
|
233
|
+
cp .planning/REQUIREMENTS.md "${RUN_DIR}/gsd-review-requirements.md"
|
|
222
234
|
fi
|
|
223
235
|
```
|
|
224
236
|
|
|
225
|
-
Note:
|
|
237
|
+
Note: `INSTRUCTIONS_BLOCK_FILE`, `ROADMAP_SECTION_FILE`, and `PHASE_DIR` come from prompt assembly; `RUN_DIR` is the run-scoped dir from `gather_context` (#2358) re-assigned from `{run_dir}` above. Copy the temp files written during prompt assembly to these section paths (or write each section here if the prompt was built inline).
|
|
226
238
|
</step>
|
|
227
239
|
|
|
228
240
|
<step name="invoke_reviewers">
|
|
@@ -260,18 +272,18 @@ For each selected CLI, invoke in sequence (not parallel — avoid rate limits):
|
|
|
260
272
|
**Gemini:**
|
|
261
273
|
```bash
|
|
262
274
|
if [ -n "$GEMINI_MODEL" ] && [ "$GEMINI_MODEL" != "null" ]; then
|
|
263
|
-
cat /
|
|
275
|
+
cat {run_dir}/gsd-review-prompt.md | gemini -m "$GEMINI_MODEL" -p - 2>/dev/null > {run_dir}/gsd-review-gemini.md
|
|
264
276
|
else
|
|
265
|
-
cat /
|
|
277
|
+
cat {run_dir}/gsd-review-prompt.md | gemini -p - 2>/dev/null > {run_dir}/gsd-review-gemini.md
|
|
266
278
|
fi
|
|
267
279
|
```
|
|
268
280
|
|
|
269
281
|
**Claude (separate session):**
|
|
270
282
|
```bash
|
|
271
283
|
if [ -n "$CLAUDE_MODEL" ] && [ "$CLAUDE_MODEL" != "null" ]; then
|
|
272
|
-
cat /
|
|
284
|
+
cat {run_dir}/gsd-review-prompt.md | claude --model "$CLAUDE_MODEL" -p - 2>/dev/null > {run_dir}/gsd-review-claude.md
|
|
273
285
|
else
|
|
274
|
-
cat /
|
|
286
|
+
cat {run_dir}/gsd-review-prompt.md | claude -p - 2>/dev/null > {run_dir}/gsd-review-claude.md
|
|
275
287
|
fi
|
|
276
288
|
```
|
|
277
289
|
|
|
@@ -286,13 +298,13 @@ fi
|
|
|
286
298
|
# stdout redirect would append that noise to a non-empty file — slipping past the
|
|
287
299
|
# `[ ! -s … ]` empty-output guard as a silently polluted review.
|
|
288
300
|
if [ -n "$CODEX_MODEL" ] && [ "$CODEX_MODEL" != "null" ]; then
|
|
289
|
-
cat /
|
|
301
|
+
cat {run_dir}/gsd-review-prompt.md | codex exec --ephemeral $CODEX_BYPASS_FLAG --model "$CODEX_MODEL" --skip-git-repo-check -o {run_dir}/gsd-review-codex.md - 2>{run_dir}/gsd-review-codex.err >/dev/null
|
|
290
302
|
else
|
|
291
|
-
cat /
|
|
303
|
+
cat {run_dir}/gsd-review-prompt.md | codex exec --ephemeral $CODEX_BYPASS_FLAG --skip-git-repo-check -o {run_dir}/gsd-review-codex.md - 2>{run_dir}/gsd-review-codex.err >/dev/null
|
|
292
304
|
fi
|
|
293
|
-
if [ ! -s /
|
|
294
|
-
echo "Codex review failed or returned empty output. stderr:" > /
|
|
295
|
-
cat /
|
|
305
|
+
if [ ! -s {run_dir}/gsd-review-codex.md ]; then
|
|
306
|
+
echo "Codex review failed or returned empty output. stderr:" > {run_dir}/gsd-review-codex.md
|
|
307
|
+
cat {run_dir}/gsd-review-codex.err >> {run_dir}/gsd-review-codex.md
|
|
296
308
|
fi
|
|
297
309
|
```
|
|
298
310
|
|
|
@@ -301,7 +313,7 @@ fi
|
|
|
301
313
|
Note: CodeRabbit reviews the current git diff/working tree — it does not accept a prompt or model flag. It may take up to 5 minutes. Use `timeout: 360000` on the Bash tool call. The source-grounding requirement in the build_prompt Review Instructions applies only to the prompt-fed reviewers above; CodeRabbit is a diff-only reviewer and never receives it. Treat its output as a diff observation, not a grounded plan-level verdict.
|
|
302
314
|
|
|
303
315
|
```bash
|
|
304
|
-
coderabbit review --prompt-only 2>/dev/null > /
|
|
316
|
+
coderabbit review --prompt-only 2>/dev/null > {run_dir}/gsd-review-coderabbit.md
|
|
305
317
|
```
|
|
306
318
|
|
|
307
319
|
**OpenCode (via GitHub Copilot):**
|
|
@@ -333,30 +345,30 @@ if [ -n "$OPENCODE_MODEL" ] && [ "$OPENCODE_MODEL" != "null" ]; then
|
|
|
333
345
|
else
|
|
334
346
|
set --
|
|
335
347
|
fi
|
|
336
|
-
cat /
|
|
337
|
-
# Reconstruct the review from the assistant text parts
|
|
338
|
-
#
|
|
339
|
-
#
|
|
340
|
-
OPENCODE_REVIEW=$(jq -rs '[.[] | select(.type=="text") | .part.text // empty] | join("\n")' /
|
|
348
|
+
cat {run_dir}/gsd-review-prompt.md | opencode run "$@" --format json - 2>{run_dir}/gsd-review-opencode.err > {run_dir}/gsd-review-opencode.json
|
|
349
|
+
# Reconstruct the review from the assistant text parts into a variable and test
|
|
350
|
+
# its CONTENT, not the file size: an empty extraction still prints a trailing
|
|
351
|
+
# newline that would fool a `[ -s file ]` check into skipping the stub.
|
|
352
|
+
OPENCODE_REVIEW=$(jq -rs '[.[] | select(.type=="text") | .part.text // empty] | join("\n")' {run_dir}/gsd-review-opencode.json 2>/dev/null)
|
|
341
353
|
if [ -n "$OPENCODE_REVIEW" ]; then
|
|
342
|
-
printf '%s\n' "$OPENCODE_REVIEW" > /
|
|
354
|
+
printf '%s\n' "$OPENCODE_REVIEW" > {run_dir}/gsd-review-opencode.md
|
|
343
355
|
else
|
|
344
|
-
# No assistant text (
|
|
356
|
+
# No assistant text (no final message, or stdout was not valid JSON):
|
|
345
357
|
{
|
|
346
358
|
echo "OpenCode review returned no assistant text (#1936: agent ended its turn with no final message)."
|
|
347
|
-
OPENCODE_DIAG=$(jq -rs '[.[] | select(.type=="step_finish")] | last | "stop reason=\(.part.reason // "?"), output tokens=\(.part.tokens.output // "?")"' /
|
|
359
|
+
OPENCODE_DIAG=$(jq -rs '[.[] | select(.type=="step_finish")] | last | "stop reason=\(.part.reason // "?"), output tokens=\(.part.tokens.output // "?")"' {run_dir}/gsd-review-opencode.json 2>/dev/null)
|
|
348
360
|
[ -n "$OPENCODE_DIAG" ] && echo "Diagnostic: $OPENCODE_DIAG"
|
|
349
361
|
echo "stderr:"
|
|
350
|
-
cat /
|
|
351
|
-
} > /
|
|
362
|
+
cat {run_dir}/gsd-review-opencode.err
|
|
363
|
+
} > {run_dir}/gsd-review-opencode.md
|
|
352
364
|
fi
|
|
353
365
|
```
|
|
354
366
|
|
|
355
367
|
**Qwen Code:**
|
|
356
368
|
```bash
|
|
357
|
-
cat /
|
|
358
|
-
if [ ! -s /
|
|
359
|
-
echo "Qwen review failed or returned empty output." > /
|
|
369
|
+
cat {run_dir}/gsd-review-prompt.md | qwen - 2>/dev/null > {run_dir}/gsd-review-qwen.md
|
|
370
|
+
if [ ! -s {run_dir}/gsd-review-qwen.md ]; then
|
|
371
|
+
echo "Qwen review failed or returned empty output." > {run_dir}/gsd-review-qwen.md
|
|
360
372
|
fi
|
|
361
373
|
```
|
|
362
374
|
|
|
@@ -371,11 +383,11 @@ fi
|
|
|
371
383
|
# need an explicit root to resolve against. rev-parse (not bare pwd) so the
|
|
372
384
|
# anchor is correct even when /gsd:review is invoked from a repo subdirectory.
|
|
373
385
|
_CURSOR_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
|
|
374
|
-
CURSOR_PROMPT_ARG="Read the file at /
|
|
375
|
-
cursor-agent -p --mode ask --trust --output-format text "$CURSOR_PROMPT_ARG" 2
|
|
376
|
-
if [ ! -s /
|
|
377
|
-
echo "Cursor review failed or returned empty output. stderr:" > /
|
|
378
|
-
cat /
|
|
386
|
+
CURSOR_PROMPT_ARG="Read the file at {run_dir}/gsd-review-prompt.md in full and carry out the review request it contains. The repository under review is at $_CURSOR_ROOT — resolve every relative file path in the review request against that absolute root. Output only the resulting markdown review. Do not edit any files."
|
|
387
|
+
cursor-agent -p --mode ask --trust --output-format text "$CURSOR_PROMPT_ARG" 2>{run_dir}/gsd-review-cursor.err > {run_dir}/gsd-review-cursor.md
|
|
388
|
+
if [ ! -s {run_dir}/gsd-review-cursor.md ]; then
|
|
389
|
+
echo "Cursor review failed or returned empty output. stderr:" > {run_dir}/gsd-review-cursor.md
|
|
390
|
+
cat {run_dir}/gsd-review-cursor.err >> {run_dir}/gsd-review-cursor.md
|
|
379
391
|
fi
|
|
380
392
|
```
|
|
381
393
|
|
|
@@ -475,7 +487,7 @@ fi
|
|
|
475
487
|
# #2176: anchor the prompt to the absolute repo root so repo-relative references
|
|
476
488
|
# in the assembled review prompt resolve even on the no---add-dir fallback, and
|
|
477
489
|
# require an explicit self-report if the reviewer still cannot read the repo.
|
|
478
|
-
_AGY_PROMPT="Read the file at /
|
|
490
|
+
_AGY_PROMPT="Read the file at {run_dir}/gsd-review-prompt.md in full and carry out the review request it contains. The repository under review is at $_AGY_WS — resolve every relative file path in the review request against that absolute root and verify claims against those files. If you cannot read files under $_AGY_WS, begin your output with the exact line REVIEWED-WITHOUT-REPO-ACCESS before the review. Output only the resulting markdown review. Do not edit any files."
|
|
479
491
|
# Capability-probe an external wall-clock killer (GNU coreutils `timeout` or the
|
|
480
492
|
# macOS Homebrew `gtimeout`). Stock macOS ships NEITHER — a bare `timeout …` would
|
|
481
493
|
# fail with rc 127 ("command not found") and silently lose the reviewer, so fall
|
|
@@ -485,20 +497,20 @@ _AGY_PROMPT="Read the file at /tmp/gsd-review-prompt-{phase}.md in full and carr
|
|
|
485
497
|
# healthy run. Mirrors the probe in scripts/base64-scan.sh.
|
|
486
498
|
_AGY_KILLER="$(command -v timeout 2>/dev/null || command -v gtimeout 2>/dev/null || true)"
|
|
487
499
|
if [ -n "$_AGY_KILLER" ]; then
|
|
488
|
-
"$_AGY_KILLER" 600 agy --print-timeout 540s "$@" -p "$_AGY_PROMPT" </dev/null 2>/dev/null > /
|
|
500
|
+
"$_AGY_KILLER" 600 agy --print-timeout 540s "$@" -p "$_AGY_PROMPT" </dev/null 2>/dev/null > {run_dir}/gsd-review-antigravity.md
|
|
489
501
|
else
|
|
490
|
-
agy --print-timeout 540s "$@" -p "$_AGY_PROMPT" </dev/null 2>/dev/null > /
|
|
502
|
+
agy --print-timeout 540s "$@" -p "$_AGY_PROMPT" </dev/null 2>/dev/null > {run_dir}/gsd-review-antigravity.md
|
|
491
503
|
fi
|
|
492
504
|
_AGY_RC=$?
|
|
493
505
|
if [ "$_AGY_RC" -ne 0 ]; then
|
|
494
|
-
: > /
|
|
506
|
+
: > {run_dir}/gsd-review-antigravity.md
|
|
495
507
|
fi
|
|
496
508
|
|
|
497
509
|
# Step 2 — transcript fallback: catches Windows agy -p stdout bug (and any future stdout-silent edge cases).
|
|
498
510
|
# Reads only lines appended AFTER the pre-flight watermark. If agy failed before writing a new response,
|
|
499
511
|
# _AGY_RESULT is empty and Step 3 fires — no stale content can leak through.
|
|
500
512
|
# Undocumented paths, verified agy 1.0.0–1.0.2. See maintainer note above if these break.
|
|
501
|
-
if [ ! -s /
|
|
513
|
+
if [ ! -s {run_dir}/gsd-review-antigravity.md ]; then
|
|
502
514
|
if [ -f "$_AGY_CACHE" ]; then
|
|
503
515
|
_AGY_CONV=$(jq -r --arg ws "$_AGY_WS" '
|
|
504
516
|
.[$ws] //
|
|
@@ -516,7 +528,7 @@ if [ ! -s /tmp/gsd-review-antigravity-{phase}.md ]; then
|
|
|
516
528
|
_AGY_RESULT=$(tail -n +"$((_AGY_SKIP + 1))" "$_AGY_TX" 2>/dev/null | \
|
|
517
529
|
jq -r 'select(.source=="MODEL" and .status=="DONE" and .type=="PLANNER_RESPONSE") | .content' \
|
|
518
530
|
2>/dev/null | tail -1)
|
|
519
|
-
[ -n "$_AGY_RESULT" ] && echo "$_AGY_RESULT" > /
|
|
531
|
+
[ -n "$_AGY_RESULT" ] && echo "$_AGY_RESULT" > {run_dir}/gsd-review-antigravity.md
|
|
520
532
|
fi
|
|
521
533
|
fi
|
|
522
534
|
fi
|
|
@@ -524,7 +536,7 @@ fi
|
|
|
524
536
|
|
|
525
537
|
# Step 3 — final guard: both approaches yielded nothing (auth error, first-run setup,
|
|
526
538
|
# path schema changed, 404'd pinned model, pre-session stall, etc.)
|
|
527
|
-
if [ ! -s /
|
|
539
|
+
if [ ! -s {run_dir}/gsd-review-antigravity.md ]; then
|
|
528
540
|
{
|
|
529
541
|
echo "Antigravity review failed or returned empty output."
|
|
530
542
|
# #2073 mode 2: a pinned model that 404s exits 0 with empty stdout AND an empty
|
|
@@ -540,7 +552,7 @@ if [ ! -s /tmp/gsd-review-antigravity-{phase}.md ]; then
|
|
|
540
552
|
fi
|
|
541
553
|
# #2073 mode 3: pre-session stall tell — no new conversation dir appeared.
|
|
542
554
|
echo "If no agy run started, that is the pre-session-stall case: check whether a new ~/.gemini/antigravity-cli/brain/<conv-id>/ dir appeared within ~30s of launch."
|
|
543
|
-
} > /
|
|
555
|
+
} > {run_dir}/gsd-review-antigravity.md
|
|
544
556
|
fi
|
|
545
557
|
|
|
546
558
|
# #2176: blind-review marker. Two tells that the reviewer ran without repo
|
|
@@ -552,15 +564,15 @@ fi
|
|
|
552
564
|
# never mis-stamped. Stamp a machine-readable marker so the Consensus Summary
|
|
553
565
|
# down-weights the review instead of counting an ungrounded verdict at full
|
|
554
566
|
# weight. (Temp file + mv, no in-place sed — BSD/GNU safe.)
|
|
555
|
-
if [ -s /
|
|
556
|
-
{ head -5 /
|
|
557
|
-
grep -qiE '(workspace|working) (directory|dir).{0,40}antigravity-cli/scratch' /
|
|
567
|
+
if [ -s {run_dir}/gsd-review-antigravity.md ] && \
|
|
568
|
+
{ head -5 {run_dir}/gsd-review-antigravity.md | grep -q 'REVIEWED-WITHOUT-REPO-ACCESS' || \
|
|
569
|
+
grep -qiE '(workspace|working) (directory|dir).{0,40}antigravity-cli/scratch' {run_dir}/gsd-review-antigravity.md; }; then
|
|
558
570
|
{
|
|
559
571
|
echo "> [reviewed-without-repo-access] This reviewer ran without visibility into the repo under review — down-weight its verdict in the Consensus Summary."
|
|
560
572
|
echo ""
|
|
561
|
-
cat /
|
|
562
|
-
} > /
|
|
563
|
-
mv /
|
|
573
|
+
cat {run_dir}/gsd-review-antigravity.md
|
|
574
|
+
} > {run_dir}/gsd-review-antigravity.md.tmp && \
|
|
575
|
+
mv {run_dir}/gsd-review-antigravity.md.tmp {run_dir}/gsd-review-antigravity.md
|
|
564
576
|
fi
|
|
565
577
|
```
|
|
566
578
|
|
|
@@ -581,22 +593,22 @@ prepare_trimmed_prompt_for_reviewer() {
|
|
|
581
593
|
[ "$REVIEWER_BUDGET" = "0" ] && return 0
|
|
582
594
|
|
|
583
595
|
PLAN_FILE_ARGS=""
|
|
584
|
-
for p in /
|
|
596
|
+
for p in {run_dir}/gsd-review-plan-*.md; do
|
|
585
597
|
[ -f "$p" ] && PLAN_FILE_ARGS="$PLAN_FILE_ARGS --plan-file $p"
|
|
586
598
|
done
|
|
587
599
|
PROJECT_ARG=""
|
|
588
|
-
[ -f "/
|
|
600
|
+
[ -f "{run_dir}/gsd-review-project.md" ] && PROJECT_ARG="--project-file {run_dir}/gsd-review-project.md"
|
|
589
601
|
CONTEXT_ARG=""
|
|
590
|
-
[ -f "/
|
|
602
|
+
[ -f "{run_dir}/gsd-review-context.md" ] && CONTEXT_ARG="--context-file {run_dir}/gsd-review-context.md"
|
|
591
603
|
RESEARCH_ARG=""
|
|
592
|
-
[ -f "/
|
|
604
|
+
[ -f "{run_dir}/gsd-review-research.md" ] && RESEARCH_ARG="--research-file {run_dir}/gsd-review-research.md"
|
|
593
605
|
REQUIREMENTS_ARG=""
|
|
594
|
-
[ -f "/
|
|
606
|
+
[ -f "{run_dir}/gsd-review-requirements.md" ] && REQUIREMENTS_ARG="--requirements-file {run_dir}/gsd-review-requirements.md"
|
|
595
607
|
|
|
596
608
|
gsd_run query prompt-budget \
|
|
597
609
|
--budget "$REVIEWER_BUDGET" \
|
|
598
|
-
--instructions-file "/
|
|
599
|
-
--roadmap-file "/
|
|
610
|
+
--instructions-file "{run_dir}/gsd-review-instructions.md" \
|
|
611
|
+
--roadmap-file "{run_dir}/gsd-review-roadmap.md" \
|
|
600
612
|
$PLAN_FILE_ARGS $PROJECT_ARG $CONTEXT_ARG $RESEARCH_ARG $REQUIREMENTS_ARG \
|
|
601
613
|
--output-prompt "$OUTPUT_PROMPT" \
|
|
602
614
|
--output-metadata "$OUTPUT_META"
|
|
@@ -610,11 +622,11 @@ if [ -z "$OLLAMA_REVIEWER_BUDGET" ] || [ "$OLLAMA_REVIEWER_BUDGET" = "null" ]; t
|
|
|
610
622
|
fi
|
|
611
623
|
|
|
612
624
|
# Apply budget trim for Ollama if a budget is configured
|
|
613
|
-
OLLAMA_PROMPT_FILE="/
|
|
625
|
+
OLLAMA_PROMPT_FILE="{run_dir}/gsd-review-prompt.md"
|
|
614
626
|
OLLAMA_SKIP=0
|
|
615
627
|
if [ -n "$OLLAMA_REVIEWER_BUDGET" ] && [ "$OLLAMA_REVIEWER_BUDGET" != "null" ] && [ "$OLLAMA_REVIEWER_BUDGET" != "0" ]; then
|
|
616
|
-
OLLAMA_TRIMMED_PROMPT="/
|
|
617
|
-
OLLAMA_TRIM_META="/
|
|
628
|
+
OLLAMA_TRIMMED_PROMPT="{run_dir}/gsd-review-prompt-ollama.md"
|
|
629
|
+
OLLAMA_TRIM_META="{run_dir}/gsd-review-prompt-ollama.metadata.json"
|
|
618
630
|
prepare_trimmed_prompt_for_reviewer "ollama" "$OLLAMA_REVIEWER_BUDGET" "$OLLAMA_TRIMMED_PROMPT" "$OLLAMA_TRIM_META"
|
|
619
631
|
OLLAMA_EXIT=$?
|
|
620
632
|
if [ $OLLAMA_EXIT -ne 0 ]; then
|
|
@@ -642,9 +654,9 @@ jq -n --rawfile content "$OLLAMA_PROMPT_FILE" \
|
|
|
642
654
|
curl -s --max-time 120 -X POST "${OLLAMA_HOST}/v1/chat/completions" \
|
|
643
655
|
-H "Content-Type: application/json" -d @- 2>/dev/null | \
|
|
644
656
|
jq -r '.choices[0].message.content // "Ollama review failed or returned empty output."' \
|
|
645
|
-
> /
|
|
646
|
-
if [ ! -s /
|
|
647
|
-
echo "Ollama review failed or returned empty output." > /
|
|
657
|
+
> {run_dir}/gsd-review-ollama.md
|
|
658
|
+
if [ ! -s {run_dir}/gsd-review-ollama.md ]; then
|
|
659
|
+
echo "Ollama review failed or returned empty output." > {run_dir}/gsd-review-ollama.md
|
|
648
660
|
fi
|
|
649
661
|
fi
|
|
650
662
|
```
|
|
@@ -658,11 +670,11 @@ if [ -z "$LM_STUDIO_REVIEWER_BUDGET" ] || [ "$LM_STUDIO_REVIEWER_BUDGET" = "null
|
|
|
658
670
|
fi
|
|
659
671
|
|
|
660
672
|
# Apply budget trim for LM Studio if a budget is configured
|
|
661
|
-
LM_STUDIO_PROMPT_FILE="/
|
|
673
|
+
LM_STUDIO_PROMPT_FILE="{run_dir}/gsd-review-prompt.md"
|
|
662
674
|
LM_STUDIO_SKIP=0
|
|
663
675
|
if [ -n "$LM_STUDIO_REVIEWER_BUDGET" ] && [ "$LM_STUDIO_REVIEWER_BUDGET" != "null" ] && [ "$LM_STUDIO_REVIEWER_BUDGET" != "0" ]; then
|
|
664
|
-
LM_STUDIO_TRIMMED_PROMPT="/
|
|
665
|
-
LM_STUDIO_TRIM_META="/
|
|
676
|
+
LM_STUDIO_TRIMMED_PROMPT="{run_dir}/gsd-review-prompt-lm_studio.md"
|
|
677
|
+
LM_STUDIO_TRIM_META="{run_dir}/gsd-review-prompt-lm_studio.metadata.json"
|
|
666
678
|
prepare_trimmed_prompt_for_reviewer "lm_studio" "$LM_STUDIO_REVIEWER_BUDGET" "$LM_STUDIO_TRIMMED_PROMPT" "$LM_STUDIO_TRIM_META"
|
|
667
679
|
LM_STUDIO_EXIT=$?
|
|
668
680
|
if [ $LM_STUDIO_EXIT -ne 0 ]; then
|
|
@@ -695,7 +707,7 @@ if [ -n "$LM_STUDIO_ACTUAL_MODEL" ] && [ "$LM_STUDIO_ACTUAL_MODEL" != "null" ] &
|
|
|
695
707
|
fi
|
|
696
708
|
LM_STUDIO_CONTENT=$(echo "$LM_STUDIO_RESPONSE" | jq -r '.choices[0].message.content // ""' 2>/dev/null || echo "")
|
|
697
709
|
if [ -n "$LM_STUDIO_CONTENT" ]; then
|
|
698
|
-
echo "$LM_STUDIO_CONTENT" > /
|
|
710
|
+
echo "$LM_STUDIO_CONTENT" > {run_dir}/gsd-review-lm_studio.md
|
|
699
711
|
else
|
|
700
712
|
echo "Warning: LM Studio returned empty content — skipping review." >&2
|
|
701
713
|
fi
|
|
@@ -711,11 +723,11 @@ if [ -z "$LLAMA_CPP_REVIEWER_BUDGET" ] || [ "$LLAMA_CPP_REVIEWER_BUDGET" = "null
|
|
|
711
723
|
fi
|
|
712
724
|
|
|
713
725
|
# Apply budget trim for llama.cpp if a budget is configured
|
|
714
|
-
LLAMA_CPP_PROMPT_FILE="/
|
|
726
|
+
LLAMA_CPP_PROMPT_FILE="{run_dir}/gsd-review-prompt.md"
|
|
715
727
|
LLAMA_CPP_SKIP=0
|
|
716
728
|
if [ -n "$LLAMA_CPP_REVIEWER_BUDGET" ] && [ "$LLAMA_CPP_REVIEWER_BUDGET" != "null" ] && [ "$LLAMA_CPP_REVIEWER_BUDGET" != "0" ]; then
|
|
717
|
-
LLAMA_CPP_TRIMMED_PROMPT="/
|
|
718
|
-
LLAMA_CPP_TRIM_META="/
|
|
729
|
+
LLAMA_CPP_TRIMMED_PROMPT="{run_dir}/gsd-review-prompt-llama_cpp.md"
|
|
730
|
+
LLAMA_CPP_TRIM_META="{run_dir}/gsd-review-prompt-llama_cpp.metadata.json"
|
|
719
731
|
prepare_trimmed_prompt_for_reviewer "llama_cpp" "$LLAMA_CPP_REVIEWER_BUDGET" "$LLAMA_CPP_TRIMMED_PROMPT" "$LLAMA_CPP_TRIM_META"
|
|
720
732
|
LLAMA_CPP_EXIT=$?
|
|
721
733
|
if [ $LLAMA_CPP_EXIT -ne 0 ]; then
|
|
@@ -744,7 +756,7 @@ LLAMA_CPP_CONTENT=$(jq -n --rawfile content "$LLAMA_CPP_PROMPT_FILE" \
|
|
|
744
756
|
-H "Content-Type: application/json" -d @- 2>/dev/null | \
|
|
745
757
|
jq -r '.choices[0].message.content // ""' 2>/dev/null || echo "")
|
|
746
758
|
if [ -n "$LLAMA_CPP_CONTENT" ]; then
|
|
747
|
-
echo "$LLAMA_CPP_CONTENT" > /
|
|
759
|
+
echo "$LLAMA_CPP_CONTENT" > {run_dir}/gsd-review-llama_cpp.md
|
|
748
760
|
else
|
|
749
761
|
echo "Warning: llama.cpp returned empty content — skipping review." >&2
|
|
750
762
|
fi
|
|
@@ -911,7 +923,11 @@ To incorporate feedback into planning:
|
|
|
911
923
|
/gsd:plan-phase {N} --reviews
|
|
912
924
|
```
|
|
913
925
|
|
|
914
|
-
Clean up temp
|
|
926
|
+
Clean up — remove the run's temp directory now that REVIEWS.md is committed:
|
|
927
|
+
|
|
928
|
+
```bash
|
|
929
|
+
rm -rf "{run_dir}"
|
|
930
|
+
```
|
|
915
931
|
</step>
|
|
916
932
|
|
|
917
933
|
</process>
|
|
@@ -76,7 +76,7 @@ Print: `◆ Spawning scanner... (runs in a subagent — no output until it retur
|
|
|
76
76
|
|
|
77
77
|
```
|
|
78
78
|
Agent(
|
|
79
|
-
prompt="Scan this codebase with focus: {focus}. Write results to
|
|
79
|
+
prompt="Scan this codebase with focus: {focus}. Write results to {codebase_dir}/. Produce only: {document_list}",
|
|
80
80
|
subagent_type="gsd-codebase-mapper",
|
|
81
81
|
model="{resolved_model}"
|
|
82
82
|
)
|
|
@@ -17,11 +17,14 @@ Valid GSD subagent types (use exact names — do not fall back to 'general-purpo
|
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; 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
|
|
20
|
+
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --default "" 2>/dev/null || echo "")
|
|
20
21
|
INIT=$(gsd_run query init.phase-op "${PHASE_ARG}")
|
|
21
22
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
22
23
|
AGENT_SKILLS_AUDITOR=$(gsd_run query agent-skills gsd-security-auditor)
|
|
23
24
|
```
|
|
24
25
|
|
|
26
|
+
**If `response_language` is set:** All user-facing questions, prompts, and explanations in this workflow MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
|
|
27
|
+
|
|
25
28
|
Parse: `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`.
|
|
26
29
|
|
|
27
30
|
```bash
|