@opengsd/gsd-core 1.7.0-rc.6 → 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 +31 -3
- package/agents/gsd-planner.md +29 -36
- package/agents/gsd-security-auditor.md +13 -15
- package/agents/gsd-verifier.md +2 -2
- package/bin/install.js +1157 -84
- package/commands/gsd/ai-integration-phase.md +1 -1
- package/commands/gsd/mempalace-capture.md +31 -1
- 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/commands/gsd/surface.md +6 -6
- package/gsd-core/bin/gsd-tools.cjs +1866 -2434
- 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 +341 -49
- package/gsd-core/bin/lib/audit.cjs +7 -6
- 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 +157 -88
- package/gsd-core/bin/lib/capability-writer.cjs +6 -1
- package/gsd-core/bin/lib/check-command-router.cjs +129 -26
- 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/clock.cjs +19 -0
- package/gsd-core/bin/lib/command-aliases.cjs +14 -0
- package/gsd-core/bin/lib/commands.cjs +129 -13
- package/gsd-core/bin/lib/config-loader.cjs +20 -4
- package/gsd-core/bin/lib/config.cjs +81 -18
- package/gsd-core/bin/lib/core-utils.cjs +14 -3
- package/gsd-core/bin/lib/decisions.cjs +32 -8
- package/gsd-core/bin/lib/docs.cjs +6 -0
- package/gsd-core/bin/lib/drift.cjs +4 -4
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +14 -2
- package/gsd-core/bin/lib/frontmatter.cjs +22 -0
- package/gsd-core/bin/lib/gap-checker.cjs +17 -2
- package/gsd-core/bin/lib/gsd2-import.cjs +2 -1
- package/gsd-core/bin/lib/init.cjs +138 -60
- package/gsd-core/bin/lib/install-engine.cjs +301 -25
- package/gsd-core/bin/lib/install-profiles.cjs +239 -1
- package/gsd-core/bin/lib/installer-migration-authoring.cjs +2 -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 +45 -6
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +449 -0
- package/gsd-core/bin/lib/markdown-table.cjs +698 -0
- package/gsd-core/bin/lib/milestone.cjs +463 -43
- 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-command-router.cjs +50 -2
- package/gsd-core/bin/lib/phase-id.cjs +26 -4
- package/gsd-core/bin/lib/phase-lifecycle.cjs +62 -36
- package/gsd-core/bin/lib/phase-locator.cjs +23 -2
- package/gsd-core/bin/lib/phase.cjs +636 -72
- package/gsd-core/bin/lib/plan-scan.cjs +73 -2
- package/gsd-core/bin/lib/roadmap-parser.cjs +225 -17
- package/gsd-core/bin/lib/roadmap.cjs +113 -52
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +14 -7
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +3 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +24 -9
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +41 -17
- package/gsd-core/bin/lib/schema-detect.cjs +2 -1
- package/gsd-core/bin/lib/security.cjs +1 -1
- package/gsd-core/bin/lib/shell-command-projection.cjs +61 -25
- package/gsd-core/bin/lib/smart-entry.cjs +73 -7
- package/gsd-core/bin/lib/state-document.cjs +7 -4
- package/gsd-core/bin/lib/state-transition.cjs +122 -46
- package/gsd-core/bin/lib/state.cjs +456 -137
- package/gsd-core/bin/lib/surface.cjs +53 -11
- package/gsd-core/bin/lib/template.cjs +2 -1
- package/gsd-core/bin/lib/uat.cjs +474 -13
- package/gsd-core/bin/lib/ui-safety-gate.cjs +23 -1
- 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 +224 -25
- package/gsd-core/bin/lib/workstream.cjs +3 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +1 -1
- package/gsd-core/bin/lib/write-set.cjs +38 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -2
- package/gsd-core/references/api-coverage.md +37 -7
- package/gsd-core/references/checkpoints.md +13 -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 +4 -2
- 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 +27 -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 +30 -37
- package/gsd-core/workflows/execute-plan.md +15 -4
- package/gsd-core/workflows/fast.md +8 -22
- 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 +33 -5
- package/gsd-core/workflows/quick.md +21 -7
- package/gsd-core/workflows/remove-workspace.md +3 -0
- package/gsd-core/workflows/review.md +123 -68
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +4 -1
- package/gsd-core/workflows/settings-integrations.md +3 -0
- package/gsd-core/workflows/settings.md +3 -0
- package/gsd-core/workflows/ship.md +58 -5
- package/gsd-core/workflows/sketch.md +3 -0
- package/gsd-core/workflows/smart-entry.md +3 -0
- package/gsd-core/workflows/spec-phase.md +1 -1
- package/gsd-core/workflows/spike.md +7 -1
- package/gsd-core/workflows/transition.md +1 -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 +252 -17
- package/hooks/gsd-context-monitor.js +27 -9
- package/hooks/gsd-statusline.js +252 -17
- package/package.json +8 -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/ci-test-scope.cjs +39 -1
- package/scripts/gen-adr-index.cjs +526 -0
- package/scripts/gen-golden-install-parity-zcode.cjs +35 -45
- package/scripts/gen-install-tree-fixtures.cjs +75 -0
- package/scripts/gen-test-timings.cjs +201 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -1
- package/scripts/lint-portable-timeout.cjs +140 -0
- package/scripts/lint-table-schema-drift.cjs +157 -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 +31 -1
- 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/skills/gsd-surface/SKILL.md +6 -6
- package/vscode/package.json +1 -1
|
@@ -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">
|
|
@@ -255,21 +267,23 @@ shell-interpolated). Exact invocation in `gsd-core/references/reviewer-instances
|
|
|
255
267
|
|
|
256
268
|
For each selected CLI, invoke in sequence (not parallel — avoid rate limits):
|
|
257
269
|
|
|
270
|
+
**Timeout guidance (#2194):** prompt-fed source-grounded reviews are slow — measured ~570s for Codex at `xhigh` effort and ~525s for headless Claude on a large plan set. Each of the Gemini / Claude / Codex blocks below MUST be invoked with a high Bash `timeout:` — at least `900000` (15 min), and `1200000` (20 min) for Codex `xhigh` or headless Claude — so a lane is not killed mid-review. On Claude Code, raise the host cap via `BASH_MAX_TIMEOUT_MS` if a review can exceed it. A silent empty output after a long run is a **timeout kill, not a crash** — the Codex `0xc0000142` misdiagnosis persisted because the empty-output branches below cannot distinguish the two; treat an empty result on a slow lane as a dropped lane and re-run with more time rather than diagnosing a CLI/sandbox failure. A cross-AI review that silently drops a lane is blind in one eye.
|
|
271
|
+
|
|
258
272
|
**Gemini:**
|
|
259
273
|
```bash
|
|
260
274
|
if [ -n "$GEMINI_MODEL" ] && [ "$GEMINI_MODEL" != "null" ]; then
|
|
261
|
-
cat /
|
|
275
|
+
cat {run_dir}/gsd-review-prompt.md | gemini -m "$GEMINI_MODEL" -p - 2>/dev/null > {run_dir}/gsd-review-gemini.md
|
|
262
276
|
else
|
|
263
|
-
cat /
|
|
277
|
+
cat {run_dir}/gsd-review-prompt.md | gemini -p - 2>/dev/null > {run_dir}/gsd-review-gemini.md
|
|
264
278
|
fi
|
|
265
279
|
```
|
|
266
280
|
|
|
267
281
|
**Claude (separate session):**
|
|
268
282
|
```bash
|
|
269
283
|
if [ -n "$CLAUDE_MODEL" ] && [ "$CLAUDE_MODEL" != "null" ]; then
|
|
270
|
-
cat /
|
|
284
|
+
cat {run_dir}/gsd-review-prompt.md | claude --model "$CLAUDE_MODEL" -p - 2>/dev/null > {run_dir}/gsd-review-claude.md
|
|
271
285
|
else
|
|
272
|
-
cat /
|
|
286
|
+
cat {run_dir}/gsd-review-prompt.md | claude -p - 2>/dev/null > {run_dir}/gsd-review-claude.md
|
|
273
287
|
fi
|
|
274
288
|
```
|
|
275
289
|
|
|
@@ -284,13 +298,13 @@ fi
|
|
|
284
298
|
# stdout redirect would append that noise to a non-empty file — slipping past the
|
|
285
299
|
# `[ ! -s … ]` empty-output guard as a silently polluted review.
|
|
286
300
|
if [ -n "$CODEX_MODEL" ] && [ "$CODEX_MODEL" != "null" ]; then
|
|
287
|
-
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
|
|
288
302
|
else
|
|
289
|
-
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
|
|
290
304
|
fi
|
|
291
|
-
if [ ! -s /
|
|
292
|
-
echo "Codex review failed or returned empty output. stderr:" > /
|
|
293
|
-
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
|
|
294
308
|
fi
|
|
295
309
|
```
|
|
296
310
|
|
|
@@ -299,7 +313,7 @@ fi
|
|
|
299
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.
|
|
300
314
|
|
|
301
315
|
```bash
|
|
302
|
-
coderabbit review --prompt-only 2>/dev/null > /
|
|
316
|
+
coderabbit review --prompt-only 2>/dev/null > {run_dir}/gsd-review-coderabbit.md
|
|
303
317
|
```
|
|
304
318
|
|
|
305
319
|
**OpenCode (via GitHub Copilot):**
|
|
@@ -331,30 +345,30 @@ if [ -n "$OPENCODE_MODEL" ] && [ "$OPENCODE_MODEL" != "null" ]; then
|
|
|
331
345
|
else
|
|
332
346
|
set --
|
|
333
347
|
fi
|
|
334
|
-
cat /
|
|
335
|
-
# Reconstruct the review from the assistant text parts
|
|
336
|
-
#
|
|
337
|
-
#
|
|
338
|
-
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)
|
|
339
353
|
if [ -n "$OPENCODE_REVIEW" ]; then
|
|
340
|
-
printf '%s\n' "$OPENCODE_REVIEW" > /
|
|
354
|
+
printf '%s\n' "$OPENCODE_REVIEW" > {run_dir}/gsd-review-opencode.md
|
|
341
355
|
else
|
|
342
|
-
# No assistant text (
|
|
356
|
+
# No assistant text (no final message, or stdout was not valid JSON):
|
|
343
357
|
{
|
|
344
358
|
echo "OpenCode review returned no assistant text (#1936: agent ended its turn with no final message)."
|
|
345
|
-
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)
|
|
346
360
|
[ -n "$OPENCODE_DIAG" ] && echo "Diagnostic: $OPENCODE_DIAG"
|
|
347
361
|
echo "stderr:"
|
|
348
|
-
cat /
|
|
349
|
-
} > /
|
|
362
|
+
cat {run_dir}/gsd-review-opencode.err
|
|
363
|
+
} > {run_dir}/gsd-review-opencode.md
|
|
350
364
|
fi
|
|
351
365
|
```
|
|
352
366
|
|
|
353
367
|
**Qwen Code:**
|
|
354
368
|
```bash
|
|
355
|
-
cat /
|
|
356
|
-
if [ ! -s /
|
|
357
|
-
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
|
|
358
372
|
fi
|
|
359
373
|
```
|
|
360
374
|
|
|
@@ -364,11 +378,16 @@ fi
|
|
|
364
378
|
# prompt as an ARGUMENT, not stdin. A full review prompt can exceed the OS argument limit, so
|
|
365
379
|
# reference the prompt file by path rather than inlining it. Capture stderr so a failure is
|
|
366
380
|
# diagnosable instead of a silent empty result.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
381
|
+
# #2176: same absolute-root anchor as the Antigravity block — cursor-agent runs
|
|
382
|
+
# in the repo cwd, but repo-relative references in the assembled prompt still
|
|
383
|
+
# need an explicit root to resolve against. rev-parse (not bare pwd) so the
|
|
384
|
+
# anchor is correct even when /gsd:review is invoked from a repo subdirectory.
|
|
385
|
+
_CURSOR_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
|
|
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
|
|
372
391
|
fi
|
|
373
392
|
```
|
|
374
393
|
|
|
@@ -456,7 +475,19 @@ if [ -n "$AGY_MODEL" ] && [ "$AGY_MODEL" != "null" ]; then
|
|
|
456
475
|
else
|
|
457
476
|
set --
|
|
458
477
|
fi
|
|
459
|
-
|
|
478
|
+
# #2176: grant the reviewer the repo under review. Without --add-dir, agy's
|
|
479
|
+
# permission context never receives the cwd repo — the agent anchors on its own
|
|
480
|
+
# ~/.gemini/antigravity-cli/scratch dir and reviews the plan text in isolation
|
|
481
|
+
# (the exact failure the Review Instructions forbid). Capability-probed like the
|
|
482
|
+
# Codex bypass flag so an older agy without --add-dir still runs; the prompt
|
|
483
|
+
# anchor below keeps absolute-path reads possible on that fallback.
|
|
484
|
+
if agy --help 2>/dev/null | grep -q -- '--add-dir'; then
|
|
485
|
+
set -- "$@" --add-dir "$_AGY_WS"
|
|
486
|
+
fi
|
|
487
|
+
# #2176: anchor the prompt to the absolute repo root so repo-relative references
|
|
488
|
+
# in the assembled review prompt resolve even on the no---add-dir fallback, and
|
|
489
|
+
# require an explicit self-report if the reviewer still cannot read the repo.
|
|
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."
|
|
460
491
|
# Capability-probe an external wall-clock killer (GNU coreutils `timeout` or the
|
|
461
492
|
# macOS Homebrew `gtimeout`). Stock macOS ships NEITHER — a bare `timeout …` would
|
|
462
493
|
# fail with rc 127 ("command not found") and silently lose the reviewer, so fall
|
|
@@ -466,20 +497,20 @@ _AGY_PROMPT="Read the file at /tmp/gsd-review-prompt-{phase}.md in full and carr
|
|
|
466
497
|
# healthy run. Mirrors the probe in scripts/base64-scan.sh.
|
|
467
498
|
_AGY_KILLER="$(command -v timeout 2>/dev/null || command -v gtimeout 2>/dev/null || true)"
|
|
468
499
|
if [ -n "$_AGY_KILLER" ]; then
|
|
469
|
-
"$_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
|
|
470
501
|
else
|
|
471
|
-
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
|
|
472
503
|
fi
|
|
473
504
|
_AGY_RC=$?
|
|
474
505
|
if [ "$_AGY_RC" -ne 0 ]; then
|
|
475
|
-
: > /
|
|
506
|
+
: > {run_dir}/gsd-review-antigravity.md
|
|
476
507
|
fi
|
|
477
508
|
|
|
478
509
|
# Step 2 — transcript fallback: catches Windows agy -p stdout bug (and any future stdout-silent edge cases).
|
|
479
510
|
# Reads only lines appended AFTER the pre-flight watermark. If agy failed before writing a new response,
|
|
480
511
|
# _AGY_RESULT is empty and Step 3 fires — no stale content can leak through.
|
|
481
512
|
# Undocumented paths, verified agy 1.0.0–1.0.2. See maintainer note above if these break.
|
|
482
|
-
if [ ! -s /
|
|
513
|
+
if [ ! -s {run_dir}/gsd-review-antigravity.md ]; then
|
|
483
514
|
if [ -f "$_AGY_CACHE" ]; then
|
|
484
515
|
_AGY_CONV=$(jq -r --arg ws "$_AGY_WS" '
|
|
485
516
|
.[$ws] //
|
|
@@ -497,7 +528,7 @@ if [ ! -s /tmp/gsd-review-antigravity-{phase}.md ]; then
|
|
|
497
528
|
_AGY_RESULT=$(tail -n +"$((_AGY_SKIP + 1))" "$_AGY_TX" 2>/dev/null | \
|
|
498
529
|
jq -r 'select(.source=="MODEL" and .status=="DONE" and .type=="PLANNER_RESPONSE") | .content' \
|
|
499
530
|
2>/dev/null | tail -1)
|
|
500
|
-
[ -n "$_AGY_RESULT" ] && echo "$_AGY_RESULT" > /
|
|
531
|
+
[ -n "$_AGY_RESULT" ] && echo "$_AGY_RESULT" > {run_dir}/gsd-review-antigravity.md
|
|
501
532
|
fi
|
|
502
533
|
fi
|
|
503
534
|
fi
|
|
@@ -505,7 +536,7 @@ fi
|
|
|
505
536
|
|
|
506
537
|
# Step 3 — final guard: both approaches yielded nothing (auth error, first-run setup,
|
|
507
538
|
# path schema changed, 404'd pinned model, pre-session stall, etc.)
|
|
508
|
-
if [ ! -s /
|
|
539
|
+
if [ ! -s {run_dir}/gsd-review-antigravity.md ]; then
|
|
509
540
|
{
|
|
510
541
|
echo "Antigravity review failed or returned empty output."
|
|
511
542
|
# #2073 mode 2: a pinned model that 404s exits 0 with empty stdout AND an empty
|
|
@@ -521,7 +552,27 @@ if [ ! -s /tmp/gsd-review-antigravity-{phase}.md ]; then
|
|
|
521
552
|
fi
|
|
522
553
|
# #2073 mode 3: pre-session stall tell — no new conversation dir appeared.
|
|
523
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."
|
|
524
|
-
} > /
|
|
555
|
+
} > {run_dir}/gsd-review-antigravity.md
|
|
556
|
+
fi
|
|
557
|
+
|
|
558
|
+
# #2176: blind-review marker. Two tells that the reviewer ran without repo
|
|
559
|
+
# access: the prompt's mandated REVIEWED-WITHOUT-REPO-ACCESS self-report in the
|
|
560
|
+
# first lines of output, or the agent DECLARING the scratch dir as its
|
|
561
|
+
# workspace. Both patterns are anchored — the self-report to the head of the
|
|
562
|
+
# file, the scratch tell to a workspace-declaration phrasing — so a grounded
|
|
563
|
+
# review that merely QUOTES these strings (e.g. reviewing this very file) is
|
|
564
|
+
# never mis-stamped. Stamp a machine-readable marker so the Consensus Summary
|
|
565
|
+
# down-weights the review instead of counting an ungrounded verdict at full
|
|
566
|
+
# weight. (Temp file + mv, no in-place sed — BSD/GNU safe.)
|
|
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
|
|
570
|
+
{
|
|
571
|
+
echo "> [reviewed-without-repo-access] This reviewer ran without visibility into the repo under review — down-weight its verdict in the Consensus Summary."
|
|
572
|
+
echo ""
|
|
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
|
|
525
576
|
fi
|
|
526
577
|
```
|
|
527
578
|
|
|
@@ -542,22 +593,22 @@ prepare_trimmed_prompt_for_reviewer() {
|
|
|
542
593
|
[ "$REVIEWER_BUDGET" = "0" ] && return 0
|
|
543
594
|
|
|
544
595
|
PLAN_FILE_ARGS=""
|
|
545
|
-
for p in /
|
|
596
|
+
for p in {run_dir}/gsd-review-plan-*.md; do
|
|
546
597
|
[ -f "$p" ] && PLAN_FILE_ARGS="$PLAN_FILE_ARGS --plan-file $p"
|
|
547
598
|
done
|
|
548
599
|
PROJECT_ARG=""
|
|
549
|
-
[ -f "/
|
|
600
|
+
[ -f "{run_dir}/gsd-review-project.md" ] && PROJECT_ARG="--project-file {run_dir}/gsd-review-project.md"
|
|
550
601
|
CONTEXT_ARG=""
|
|
551
|
-
[ -f "/
|
|
602
|
+
[ -f "{run_dir}/gsd-review-context.md" ] && CONTEXT_ARG="--context-file {run_dir}/gsd-review-context.md"
|
|
552
603
|
RESEARCH_ARG=""
|
|
553
|
-
[ -f "/
|
|
604
|
+
[ -f "{run_dir}/gsd-review-research.md" ] && RESEARCH_ARG="--research-file {run_dir}/gsd-review-research.md"
|
|
554
605
|
REQUIREMENTS_ARG=""
|
|
555
|
-
[ -f "/
|
|
606
|
+
[ -f "{run_dir}/gsd-review-requirements.md" ] && REQUIREMENTS_ARG="--requirements-file {run_dir}/gsd-review-requirements.md"
|
|
556
607
|
|
|
557
608
|
gsd_run query prompt-budget \
|
|
558
609
|
--budget "$REVIEWER_BUDGET" \
|
|
559
|
-
--instructions-file "/
|
|
560
|
-
--roadmap-file "/
|
|
610
|
+
--instructions-file "{run_dir}/gsd-review-instructions.md" \
|
|
611
|
+
--roadmap-file "{run_dir}/gsd-review-roadmap.md" \
|
|
561
612
|
$PLAN_FILE_ARGS $PROJECT_ARG $CONTEXT_ARG $RESEARCH_ARG $REQUIREMENTS_ARG \
|
|
562
613
|
--output-prompt "$OUTPUT_PROMPT" \
|
|
563
614
|
--output-metadata "$OUTPUT_META"
|
|
@@ -571,11 +622,11 @@ if [ -z "$OLLAMA_REVIEWER_BUDGET" ] || [ "$OLLAMA_REVIEWER_BUDGET" = "null" ]; t
|
|
|
571
622
|
fi
|
|
572
623
|
|
|
573
624
|
# Apply budget trim for Ollama if a budget is configured
|
|
574
|
-
OLLAMA_PROMPT_FILE="/
|
|
625
|
+
OLLAMA_PROMPT_FILE="{run_dir}/gsd-review-prompt.md"
|
|
575
626
|
OLLAMA_SKIP=0
|
|
576
627
|
if [ -n "$OLLAMA_REVIEWER_BUDGET" ] && [ "$OLLAMA_REVIEWER_BUDGET" != "null" ] && [ "$OLLAMA_REVIEWER_BUDGET" != "0" ]; then
|
|
577
|
-
OLLAMA_TRIMMED_PROMPT="/
|
|
578
|
-
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"
|
|
579
630
|
prepare_trimmed_prompt_for_reviewer "ollama" "$OLLAMA_REVIEWER_BUDGET" "$OLLAMA_TRIMMED_PROMPT" "$OLLAMA_TRIM_META"
|
|
580
631
|
OLLAMA_EXIT=$?
|
|
581
632
|
if [ $OLLAMA_EXIT -ne 0 ]; then
|
|
@@ -603,9 +654,9 @@ jq -n --rawfile content "$OLLAMA_PROMPT_FILE" \
|
|
|
603
654
|
curl -s --max-time 120 -X POST "${OLLAMA_HOST}/v1/chat/completions" \
|
|
604
655
|
-H "Content-Type: application/json" -d @- 2>/dev/null | \
|
|
605
656
|
jq -r '.choices[0].message.content // "Ollama review failed or returned empty output."' \
|
|
606
|
-
> /
|
|
607
|
-
if [ ! -s /
|
|
608
|
-
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
|
|
609
660
|
fi
|
|
610
661
|
fi
|
|
611
662
|
```
|
|
@@ -619,11 +670,11 @@ if [ -z "$LM_STUDIO_REVIEWER_BUDGET" ] || [ "$LM_STUDIO_REVIEWER_BUDGET" = "null
|
|
|
619
670
|
fi
|
|
620
671
|
|
|
621
672
|
# Apply budget trim for LM Studio if a budget is configured
|
|
622
|
-
LM_STUDIO_PROMPT_FILE="/
|
|
673
|
+
LM_STUDIO_PROMPT_FILE="{run_dir}/gsd-review-prompt.md"
|
|
623
674
|
LM_STUDIO_SKIP=0
|
|
624
675
|
if [ -n "$LM_STUDIO_REVIEWER_BUDGET" ] && [ "$LM_STUDIO_REVIEWER_BUDGET" != "null" ] && [ "$LM_STUDIO_REVIEWER_BUDGET" != "0" ]; then
|
|
625
|
-
LM_STUDIO_TRIMMED_PROMPT="/
|
|
626
|
-
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"
|
|
627
678
|
prepare_trimmed_prompt_for_reviewer "lm_studio" "$LM_STUDIO_REVIEWER_BUDGET" "$LM_STUDIO_TRIMMED_PROMPT" "$LM_STUDIO_TRIM_META"
|
|
628
679
|
LM_STUDIO_EXIT=$?
|
|
629
680
|
if [ $LM_STUDIO_EXIT -ne 0 ]; then
|
|
@@ -656,7 +707,7 @@ if [ -n "$LM_STUDIO_ACTUAL_MODEL" ] && [ "$LM_STUDIO_ACTUAL_MODEL" != "null" ] &
|
|
|
656
707
|
fi
|
|
657
708
|
LM_STUDIO_CONTENT=$(echo "$LM_STUDIO_RESPONSE" | jq -r '.choices[0].message.content // ""' 2>/dev/null || echo "")
|
|
658
709
|
if [ -n "$LM_STUDIO_CONTENT" ]; then
|
|
659
|
-
echo "$LM_STUDIO_CONTENT" > /
|
|
710
|
+
echo "$LM_STUDIO_CONTENT" > {run_dir}/gsd-review-lm_studio.md
|
|
660
711
|
else
|
|
661
712
|
echo "Warning: LM Studio returned empty content — skipping review." >&2
|
|
662
713
|
fi
|
|
@@ -672,11 +723,11 @@ if [ -z "$LLAMA_CPP_REVIEWER_BUDGET" ] || [ "$LLAMA_CPP_REVIEWER_BUDGET" = "null
|
|
|
672
723
|
fi
|
|
673
724
|
|
|
674
725
|
# Apply budget trim for llama.cpp if a budget is configured
|
|
675
|
-
LLAMA_CPP_PROMPT_FILE="/
|
|
726
|
+
LLAMA_CPP_PROMPT_FILE="{run_dir}/gsd-review-prompt.md"
|
|
676
727
|
LLAMA_CPP_SKIP=0
|
|
677
728
|
if [ -n "$LLAMA_CPP_REVIEWER_BUDGET" ] && [ "$LLAMA_CPP_REVIEWER_BUDGET" != "null" ] && [ "$LLAMA_CPP_REVIEWER_BUDGET" != "0" ]; then
|
|
678
|
-
LLAMA_CPP_TRIMMED_PROMPT="/
|
|
679
|
-
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"
|
|
680
731
|
prepare_trimmed_prompt_for_reviewer "llama_cpp" "$LLAMA_CPP_REVIEWER_BUDGET" "$LLAMA_CPP_TRIMMED_PROMPT" "$LLAMA_CPP_TRIM_META"
|
|
681
732
|
LLAMA_CPP_EXIT=$?
|
|
682
733
|
if [ $LLAMA_CPP_EXIT -ne 0 ]; then
|
|
@@ -705,7 +756,7 @@ LLAMA_CPP_CONTENT=$(jq -n --rawfile content "$LLAMA_CPP_PROMPT_FILE" \
|
|
|
705
756
|
-H "Content-Type: application/json" -d @- 2>/dev/null | \
|
|
706
757
|
jq -r '.choices[0].message.content // ""' 2>/dev/null || echo "")
|
|
707
758
|
if [ -n "$LLAMA_CPP_CONTENT" ]; then
|
|
708
|
-
echo "$LLAMA_CPP_CONTENT" > /
|
|
759
|
+
echo "$LLAMA_CPP_CONTENT" > {run_dir}/gsd-review-llama_cpp.md
|
|
709
760
|
else
|
|
710
761
|
echo "Warning: llama.cpp returned empty content — skipping review." >&2
|
|
711
762
|
fi
|
|
@@ -835,7 +886,7 @@ trimmed_reviewers: # only present if at least one reviewer was trimmed
|
|
|
835
886
|
|
|
836
887
|
## Consensus Summary
|
|
837
888
|
|
|
838
|
-
{synthesize common concerns across all reviewers. CodeRabbit is a diff-only reviewer (it never received the source-grounding prompt), so do not weight its verdict as a grounded plan review — fold in its diff findings, but base plan-level consensus on the prompt-fed reviewers.}
|
|
889
|
+
{synthesize common concerns across all reviewers. CodeRabbit is a diff-only reviewer (it never received the source-grounding prompt), so do not weight its verdict as a grounded plan review — fold in its diff findings, but base plan-level consensus on the prompt-fed reviewers. A reviewer output carrying the `[reviewed-without-repo-access]` marker (or beginning with `REVIEWED-WITHOUT-REPO-ACCESS`) ran without repo access (#2176) — treat it the same way: note its concerns, but do not count its verdict at full consensus weight.}
|
|
839
890
|
|
|
840
891
|
### Agreed Strengths
|
|
841
892
|
{strengths mentioned by 2+ reviewers}
|
|
@@ -872,7 +923,11 @@ To incorporate feedback into planning:
|
|
|
872
923
|
/gsd:plan-phase {N} --reviews
|
|
873
924
|
```
|
|
874
925
|
|
|
875
|
-
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
|
+
```
|
|
876
931
|
</step>
|
|
877
932
|
|
|
878
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
|
|
@@ -108,7 +111,7 @@ Agent(
|
|
|
108
111
|
"<files_to_read>{PLAN, SUMMARY, impl files, SECURITY.md}</files_to_read>" +
|
|
109
112
|
"<threat_register>{threat register}</threat_register>" +
|
|
110
113
|
"<config>asvs_level: {SECURITY_ASVS}, block_on: {SECURITY_BLOCK_ON}</config>" +
|
|
111
|
-
"<constraints>Never modify implementation files. Verify mitigations exist — do not scan for new threats. Escalate implementation gaps.</constraints>" +
|
|
114
|
+
"<constraints>Never modify implementation files. Verify mitigations exist — do not scan for new threats. Escalate implementation gaps. Return a structured verdict only — do NOT write SECURITY.md (the orchestrator owns the file write).</constraints>" +
|
|
112
115
|
"${AGENT_SKILLS_AUDITOR}",
|
|
113
116
|
subagent_type="gsd-security-auditor",
|
|
114
117
|
model="{AUDITOR_MODEL}",
|
|
@@ -43,6 +43,7 @@ Ensure config exists and resolve the active config path (flat vs workstream, #22
|
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
45
|
_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
|
|
46
|
+
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --default "" 2>/dev/null || echo "")
|
|
46
47
|
gsd_run query config-ensure-section
|
|
47
48
|
if [[ -z "${GSD_CONFIG_PATH:-}" ]]; then
|
|
48
49
|
if [[ -f .planning/active-workstream ]]; then
|
|
@@ -54,6 +55,8 @@ if [[ -z "${GSD_CONFIG_PATH:-}" ]]; then
|
|
|
54
55
|
fi
|
|
55
56
|
```
|
|
56
57
|
|
|
58
|
+
**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.
|
|
59
|
+
|
|
57
60
|
Store `$GSD_CONFIG_PATH`. Every subsequent read/write uses it.
|
|
58
61
|
</step>
|
|
59
62
|
|
|
@@ -13,6 +13,7 @@ Ensure config exists and load current state:
|
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
_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
|
|
16
|
+
RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --default "" 2>/dev/null || echo "")
|
|
16
17
|
gsd_run query config-ensure-section
|
|
17
18
|
INIT=$(gsd_run query state.load)
|
|
18
19
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
@@ -27,6 +28,8 @@ if [[ -z "${GSD_CONFIG_PATH:-}" ]]; then
|
|
|
27
28
|
fi
|
|
28
29
|
```
|
|
29
30
|
|
|
31
|
+
**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.
|
|
32
|
+
|
|
30
33
|
Creates `config.json` (at the resolved path) with defaults if missing. `INIT` still holds `state.load` output for any step that needs STATE fields.
|
|
31
34
|
Store `$GSD_CONFIG_PATH` — all subsequent reads and writes use this path, not a hardcoded `.planning/config.json`, so active-workstream installs target the correct file (#2282).
|
|
32
35
|
</step>
|