fix(#571): forbid Write in doc-writer fix mode; add workflow truncation guard

* fix(#571): forbid Write in doc-writer fix mode; add workflow truncation guard

gsd-doc-writer in fix mode only had Write in its tools list, so when
correcting a specific failing claim it would re-emit the whole file with
only the lines it had in context — truncating untracked docs with no git
recovery path.

Fix 1 (root cause): add Edit to the agent tools frontmatter and rewrite
fix_mode instructions to mandate Edit for surgical corrections and
explicitly forbid Write on existing files. Also reinforced in
critical_rules.

Fix 2 (safety net): add a post-fix line-count guard in the fix_loop step
of docs-update.md. If the file shrank by >90% after a fix agent runs,
the orchestrator restores the file from the existing_content it captured
before dispatch and logs a WARNING. This makes the previously
unrecoverable case recoverable.

Regression test: tests/bug-571-doc-writer-fix-mode-edit-only.test.cjs
covers both the agent contract and the workflow guard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: add changeset for fix #571

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(#571): address codex adversarial review findings

- Quote {doc_path} in shell snippets to handle paths with spaces (#SECURITY)
- Clarify corrupted doc re-verification vs re-fix distinction (#CORRECTNESS)
- Strengthen regression tests with structural ordering assertions (#REGRESSION)
- Move docs-update.md from global ALLOWLIST to SIZE_ONLY_WORKFLOWS so
  injection scanning still runs while only the 50K size finding is exempt (#SECURITY)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-01 09:44:58 -04:00
committed by GitHub
parent 2ba6b69d53
commit c2ebb1ba16
5 changed files with 242 additions and 9 deletions

View File

@@ -1,7 +1,7 @@
---
name: gsd-doc-writer
description: Writes and updates project documentation. Spawned with a doc_assignment block specifying doc type, mode (create/update/supplement), and project context.
tools: Read, Bash, Grep, Glob, Write
tools: Read, Bash, Grep, Glob, Write, Edit
color: purple
# hooks:
# PostToolUse:
@@ -93,12 +93,12 @@ Correct specific failing claims identified by the gsd-doc-verifier. ONLY modify
1. Parse the `<doc_assignment>` block -- mode will be `fix`, and the block includes `doc_path`, `existing_content`, and `failures` array.
2. Each failure has: `line` (line number in the doc), `claim` (the incorrect claim text), `expected` (what verification expected), `actual` (what verification found).
3. For each failure:
a. Locate the line in existing_content.
a. Locate the exact text of the incorrect claim in `existing_content`.
b. Explore the codebase using Read, Grep, Glob to find the correct value.
c. Replace ONLY the incorrect claim with the verified-correct value.
d. If the correct value cannot be determined, replace the claim with a `<!-- VERIFY: {claim} -->` marker.
4. Write the corrected file using the Write tool.
5. Ensure the GSD marker `<!-- generated-by: gsd-doc-writer -->` remains on the first line.
c. Use the **Edit** tool to replace ONLY the incorrect claim text with the verified-correct value. Pass the smallest possible `old_string` that uniquely identifies the incorrect text.
d. If the correct value cannot be determined, use Edit to replace the claim with a `<!-- VERIFY: {claim} -->` marker.
4. **NEVER use the Write tool on an existing file in fix mode.** Write replaces the entire file with whatever you provide — any content not in your context window is permanently destroyed. There is no recovery if the file is untracked. Edit makes targeted replacements and is the only safe tool for fix mode.
5. After all Edit calls, verify the GSD marker `<!-- generated-by: gsd-doc-writer -->` is still present on the first line. If it was removed by an Edit, use Edit to restore it.
Fix mode must correct ONLY the lines listed in the failures array. Do not modify, reorder, rephrase, or "improve" any other content in the file. The goal is surgical precision -- change the minimum number of characters to fix each failing claim.
</fix_mode>
@@ -597,6 +597,7 @@ change — only location and metadata change.
3. Include the GSD marker `<!-- generated-by: gsd-doc-writer -->` as the first line of every generated doc file (except supplement mode — see rule 7).
4. Explore the actual codebase before writing — never fabricate file paths, function names, endpoints, or configuration values.
8. Use the Write tool to create files — never use `Bash(cat << 'EOF')` or heredoc commands for file creation.
9. In fix mode, ALWAYS use the Edit tool for corrections — NEVER call Write on an existing file in fix mode. Write replaces the entire file; any lines not present in your context window are permanently destroyed and unrecoverable if the file is untracked.
5. Use `<!-- VERIFY: {claim} -->` markers for any infrastructure claim (URLs, server configs, external service details) that cannot be verified from the repository contents alone.
6. In update mode, PRESERVE user-authored content in sections that are still accurate. Only rewrite inaccurate or missing sections.
7. In supplement mode, NEVER modify existing content. Only append missing sections. Do NOT add the GSD marker to hand-written files.