* fix(#214): apply OpenCode write-truncation contract to all large-file writer agents Issue #214 / PR #598 fixed gsd-phase-researcher's OpenCode write-tool truncation by adding a single-Write-default + sentinel-based Write->Read->Edit incremental fallback contract to its Step 6. The root cause is upstream opencode#18108: OUTPUT_TOKEN_MAX=32000 is shared with the thinking budget, so a single oversized `write` tool call's JSON is truncated mid-payload (`JSON Parse error: Expected '}'`) and OpenCode doom-loops. The same failure affects every GSD subagent that writes a large file in one Write call. Mirror the phase-researcher write contract (adapted per output filename) into the other large-file writers: - gsd-research-synthesizer (SUMMARY.md) — extends the existing bug-222 hard-rules block with the truncation fallback as rule 6, preserving every original rule - gsd-planner (PLAN.md) - gsd-executor (SUMMARY.md) - gsd-domain-researcher (AI-SPEC.md Section 1b) - gsd-project-researcher (.planning/research/*.md) - gsd-ui-researcher (UI-SPEC.md) Each keeps the single-Write default (no behavior change for Claude Code and other non-truncating runtimes) and falls back to incremental, sentinel-based section-by-section writes only on a truncation/invalid-tool failure; never silently falls back to returning content. Locked with a parametrized prompt-contract regression test mirroring the bug-214 / bug-222 pattern across all six agents. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#214): set changeset pr to 599 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -98,6 +98,19 @@ If internal tooling with no regulated domain, "domain expert" = product owner or
|
||||
<step name="write_section_1b">
|
||||
**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation.
|
||||
|
||||
**Write contract (hard rules — must follow):**
|
||||
|
||||
Section 1b of AI-SPEC.md is the output of this step. The orchestrator reads `AI-SPEC.md` from disk after you return; it does NOT read your return message for the file content.
|
||||
|
||||
1. **Default: write the section in a single `Write` call.** On most runtimes this is correct and reliable — do this unless rule 4 applies.
|
||||
2. **Do NOT return the AI-SPEC.md content in your response.** Your return message is a brief confirmation; the content lives on disk.
|
||||
3. **Do NOT use `Bash(cat << 'EOF')` or heredoc** for file creation. Use the `Write` tool.
|
||||
4. **Large-file / truncation fallback.** Some runtimes (e.g. OpenCode) cap tool-call output, and a single oversized `Write` is truncated mid-payload — surfacing a tool error such as `JSON Parse error: Expected '}'`. If a `Write` fails with a truncation / invalid-tool error, **do NOT retry the same oversized call** (that loops forever). Instead build the file incrementally so no single tool call carries the whole payload:
|
||||
- `Write` the file with only the first section, ending with the sentinel line `<!-- gsd:write-continue -->`.
|
||||
- `Read` the file, then `Edit` it, replacing `<!-- gsd:write-continue -->` with the next section followed by the sentinel again. Repeat, one section per `Edit`.
|
||||
- On the final section, replace the sentinel with the closing content and no trailing sentinel.
|
||||
5. **If writing still fails, surface the actual error in your return message.** **Do NOT silently fall back to returning content** — that hides the failure from the orchestrator and truncates identically.
|
||||
|
||||
Update AI-SPEC.md at `ai_spec_path`. Add/update Section 1b:
|
||||
|
||||
```markdown
|
||||
|
||||
@@ -589,6 +589,19 @@ After all tasks complete, create `{phase}-{plan}-SUMMARY.md` at `.planning/phase
|
||||
|
||||
Use the Write tool to create files — never use `Bash(cat << 'EOF')` or heredoc commands for file creation.
|
||||
|
||||
**Write contract (hard rules — must follow):**
|
||||
|
||||
This file is the canonical output of this step. The orchestrator reads `.planning/phases/XX-name/{phase}-{plan}-SUMMARY.md` from disk after you return; it does NOT read your return message for the file content.
|
||||
|
||||
1. **Default: write the whole file in a single `Write` call.** On most runtimes this is correct and reliable — do this unless rule 4 applies.
|
||||
2. **Do NOT return the SUMMARY.md content in your response.** Your return message is a brief confirmation; the content lives on disk.
|
||||
3. **Do NOT use `Bash(cat << 'EOF')` or heredoc** for file creation. Use the `Write` tool.
|
||||
4. **Large-file / truncation fallback.** Some runtimes (e.g. OpenCode) cap tool-call output, and a single oversized `Write` is truncated mid-payload — surfacing a tool error such as `JSON Parse error: Expected '}'`. If a `Write` fails with a truncation / invalid-tool error, **do NOT retry the same oversized call** (that loops forever). Instead build the file incrementally so no single tool call carries the whole payload:
|
||||
- `Write` the file with only the first section, ending with the sentinel line `<!-- gsd:write-continue -->`.
|
||||
- `Read` the file, then `Edit` it, replacing `<!-- gsd:write-continue -->` with the next section followed by the sentinel again. Repeat, one section per `Edit`.
|
||||
- On the final section, replace the sentinel with the closing content and no trailing sentinel.
|
||||
5. **If writing still fails, surface the actual error in your return message.** **Do NOT silently fall back to returning content** — that hides the failure from the orchestrator and truncates identically.
|
||||
|
||||
**Use template:** @~/.claude/get-shit-done/templates/summary.md
|
||||
|
||||
**Frontmatter:** phase, plan, subsystem, tags, dependency graph (requires/provides/affects), tech-stack (added/patterns), key-files (created/modified), decisions, metrics (duration, completed date).
|
||||
|
||||
@@ -1021,6 +1021,19 @@ Use template structure for each PLAN.md.
|
||||
|
||||
**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation.
|
||||
|
||||
**Write contract (hard rules — must follow):**
|
||||
|
||||
These PLAN.md files are the canonical output of this agent. The orchestrator reads each `.planning/phases/{padded_phase}-{slug}/{padded_phase}-{NN}-PLAN.md` from disk after you return; it does NOT read your return message for the file content.
|
||||
|
||||
1. **Default: write each PLAN.md in a single `Write` call.** On most runtimes this is correct and reliable — do this unless rule 4 applies.
|
||||
2. **Do NOT return the PLAN.md content in your response.** Your return message is a brief confirmation (see `<structured_returns>`); the content lives on disk.
|
||||
3. **Do NOT use `Bash(cat << 'EOF')` or heredoc** for file creation. Use the `Write` tool.
|
||||
4. **Large-file / truncation fallback.** Some runtimes (e.g. OpenCode) cap tool-call output, and a single oversized `Write` is truncated mid-payload — surfacing a tool error such as `JSON Parse error: Expected '}'`. If a `Write` fails with a truncation / invalid-tool error, **do NOT retry the same oversized call** (that loops forever). Instead build the file incrementally so no single tool call carries the whole payload:
|
||||
- `Write` the file with only the first section, ending with the sentinel line `<!-- gsd:write-continue -->`.
|
||||
- `Read` the file, then `Edit` it, replacing `<!-- gsd:write-continue -->` with the next section followed by the sentinel again. Repeat, one section per `Edit`.
|
||||
- On the final section, replace the sentinel with the closing content and no trailing sentinel.
|
||||
5. **If writing still fails, surface the actual error in your return message.** **Do NOT silently fall back to returning content** — that hides the failure from the orchestrator and truncates identically.
|
||||
|
||||
**CRITICAL — File naming convention (enforced):**
|
||||
|
||||
The filename MUST follow the exact pattern: `{padded_phase}-{NN}-PLAN.md`
|
||||
|
||||
@@ -574,6 +574,19 @@ Run pre-submission checklist (see verification_protocol).
|
||||
|
||||
**ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation.
|
||||
|
||||
**Write contract (hard rules — must follow):**
|
||||
|
||||
These files are the canonical output of this agent. The orchestrator reads them from `.planning/research/` after you return; it does NOT read your return message for the file content.
|
||||
|
||||
1. **Default: write each file in a single `Write` call.** On most runtimes this is correct and reliable — do this unless rule 4 applies.
|
||||
2. **Do NOT return the file contents in your response.** Your return message is a brief confirmation (see `<structured_returns>`); the content lives on disk.
|
||||
3. **Do NOT use `Bash(cat << 'EOF')` or heredoc** for file creation. Use the `Write` tool.
|
||||
4. **Large-file / truncation fallback.** Some runtimes (e.g. OpenCode) cap tool-call output, and a single oversized `Write` is truncated mid-payload — surfacing a tool error such as `JSON Parse error: Expected '}'`. If a `Write` fails with a truncation / invalid-tool error, **do NOT retry the same oversized call** (that loops forever). Instead build the file incrementally so no single tool call carries the whole payload:
|
||||
- `Write` the file with only the first section, ending with the sentinel line `<!-- gsd:write-continue -->`.
|
||||
- `Read` the file, then `Edit` it, replacing `<!-- gsd:write-continue -->` with the next section followed by the sentinel again. Repeat, one section per `Edit`.
|
||||
- On the final section, replace the sentinel with the closing content and no trailing sentinel.
|
||||
5. **If writing still fails, surface the actual error in your return message.** **Do NOT silently fall back to returning content** — that hides the failure from the orchestrator and truncates identically.
|
||||
|
||||
In `.planning/research/`:
|
||||
1. **SUMMARY.md** — Always
|
||||
2. **STACK.md** — Always
|
||||
|
||||
@@ -137,6 +137,10 @@ Identify gaps that couldn't be resolved and need attention during planning.
|
||||
3. **Do NOT ask permission to write.** Writing `.planning/research/SUMMARY.md` is the explicit purpose of this agent. Asking the orchestrator to do it instead is a failure mode that can cause downstream `SUMMARY.md not found` failures.
|
||||
4. **Do NOT use `Bash(cat << 'EOF')` or heredoc** for file creation. Use the `Write` tool. In short: **never use `Bash(cat << 'EOF')` or heredoc**.
|
||||
5. **If the Write tool errors,** surface the actual error in your return message. Do not silently fall back to returning content; that hides the failure from the orchestrator.
|
||||
6. **Large-file / truncation fallback.** Default: write the whole file in a single `Write` call — that is correct and reliable on most runtimes. But some runtimes (e.g. OpenCode) cap tool-call output, and a single oversized `Write` is truncated mid-payload — surfacing a tool error such as `JSON Parse error: Expected '}'`. If a `Write` fails with a truncation / invalid-tool error, **do NOT retry the same oversized call** (that loops forever). Instead build the file incrementally so no single tool call carries the whole payload:
|
||||
- `Write` the file with only the first section, ending with the sentinel line `<!-- gsd:write-continue -->`.
|
||||
- `Read` the file, then `Edit` it, replacing `<!-- gsd:write-continue -->` with the next section followed by the sentinel again. Repeat, one section per `Edit`.
|
||||
- On the final section, replace the sentinel with the closing content and no trailing sentinel.
|
||||
|
||||
Use template: ~/.claude/get-shit-done/templates/research-project/SUMMARY.md
|
||||
|
||||
|
||||
@@ -289,6 +289,19 @@ Read template: `~/.claude/get-shit-done/templates/UI-SPEC.md`
|
||||
|
||||
Fill all sections. Write to `$PHASE_DIR/$PADDED_PHASE-UI-SPEC.md`.
|
||||
|
||||
**Write contract (hard rules — must follow):**
|
||||
|
||||
This file is the canonical output of this agent. The orchestrator reads `$PHASE_DIR/$PADDED_PHASE-UI-SPEC.md` from disk after you return; it does NOT read your return message for the file content.
|
||||
|
||||
1. **Default: write the whole file in a single `Write` call.** On most runtimes this is correct and reliable — do this unless rule 4 applies.
|
||||
2. **Do NOT return the UI-SPEC.md content in your response.** Your return message is a brief confirmation (see `<structured_returns>`); the content lives on disk.
|
||||
3. **Do NOT use `Bash(cat << 'EOF')` or heredoc** for file creation. Use the `Write` tool.
|
||||
4. **Large-file / truncation fallback.** Some runtimes (e.g. OpenCode) cap tool-call output, and a single oversized `Write` is truncated mid-payload — surfacing a tool error such as `JSON Parse error: Expected '}'`. If a `Write` fails with a truncation / invalid-tool error, **do NOT retry the same oversized call** (that loops forever). Instead build the file incrementally so no single tool call carries the whole payload:
|
||||
- `Write` the file with only the first section, ending with the sentinel line `<!-- gsd:write-continue -->`.
|
||||
- `Read` the file, then `Edit` it, replacing `<!-- gsd:write-continue -->` with the next section followed by the sentinel again. Repeat, one section per `Edit`.
|
||||
- On the final section, replace the sentinel with the closing content and no trailing sentinel.
|
||||
5. **If writing still fails, surface the actual error in your return message.** **Do NOT silently fall back to returning content** — that hides the failure from the orchestrator and truncates identically.
|
||||
|
||||
## Step 6: Commit (optional)
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user