fix(gsd): remove STATE.md update instructions from all prompts (#983)

* fix(gsd): clear all caches after discuss dispatch so picker sees new CONTEXT files

guided-flow.ts called only invalidateStateCache() after waitForIdle(),
leaving dirEntryCache stale. resolveSliceFile("CONTEXT") missed files
written during the discuss session, keeping the just-discussed slice
recommended and preventing the allDiscussed exit gate from firing.

Swap to invalidateAllCaches() at both call sites (discuss loop and
queue reorder), matching the pattern used throughout auto.ts.

Fixes #977

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(gsd): remove STATE.md update instructions from all prompts (#978)

STATE.md is a derived runtime file rebuilt by auto.ts after every unit.
Prompts telling LLMs to update it caused git staging errors when the
LLM ran `git add .gsd/` and hit the gitignore barrier, leaving sessions
stuck. Removed redundant STATE.md instructions from 13 prompts, made
commit instructions explicit about which files to stage, and switched
bootstrap `nativeAddPaths` to `nativeAddAll` to respect .gitignore in
the CLI fallback path.

Closes #978

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
TÂCHES 2026-03-17 17:27:40 -06:00 committed by GitHub
parent dfc41e105d
commit fc44ea3fbe
17 changed files with 15 additions and 33 deletions

View file

@ -640,7 +640,7 @@ export async function buildPlanSlicePrompt(
const prefs = loadEffectiveGSDPreferences();
const commitDocsEnabled = prefs?.preferences?.git?.commit_docs !== false;
const commitInstruction = commitDocsEnabled
? `Commit: \`docs(${sid}): add slice plan\``
? `Commit the plan files only: \`git add ${relSlicePath(base, mid, sid)}/ .gsd/DECISIONS.md .gitignore && git commit -m "docs(${sid}): add slice plan"\`. Do not stage .gsd/STATE.md or other runtime files — the system manages those.`
: "Do not commit — planning docs are not tracked in git for this project.";
return loadPrompt("plan-slice", {
workingDirectory: base,
@ -1080,7 +1080,7 @@ export async function buildReassessRoadmapPrompt(
const reassessPrefs = loadEffectiveGSDPreferences();
const reassessCommitDocsEnabled = reassessPrefs?.preferences?.git?.commit_docs !== false;
const reassessCommitInstruction = reassessCommitDocsEnabled
? `Commit: \`docs(${mid}): reassess roadmap after ${completedSliceId}\``
? `Commit: \`docs(${mid}): reassess roadmap after ${completedSliceId}\`. Stage only the .gsd/milestones/ files you changed — do not stage .gsd/STATE.md or other runtime files.`
: "Do not commit — planning docs are not tracked in git for this project.";
return loadPrompt("reassess-roadmap", {

View file

@ -105,7 +105,7 @@ import { GSDError, GSD_ARTIFACT_MISSING } from "./errors.js";
import { join } from "node:path";
import { sep as pathSep } from "node:path";
import { readdirSync, readFileSync, existsSync, mkdirSync, writeFileSync, renameSync, unlinkSync, statSync } from "node:fs";
import { nativeIsRepo, nativeInit, nativeAddPaths, nativeCommit } from "./native-git-bridge.js";
import { nativeIsRepo, nativeInit, nativeAddAll, nativeCommit } from "./native-git-bridge.js";
import {
autoCommitCurrentBranch,
captureIntegrationBranch,
@ -702,7 +702,7 @@ export async function startAuto(
// Only commit .gsd/ init when commit_docs is not explicitly false
if (commitDocs !== false) {
try {
nativeAddPaths(base, [".gsd", ".gitignore"]);
nativeAddAll(base);
nativeCommit(base, "chore: init gsd");
} catch { /* nothing to commit */ }
}

View file

@ -24,7 +24,7 @@ import {
import { randomInt } from "node:crypto";
import { join } from "node:path";
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, rmSync, unlinkSync } from "node:fs";
import { nativeIsRepo, nativeInit, nativeAddPaths, nativeCommit } from "./native-git-bridge.js";
import { nativeIsRepo, nativeInit, nativeAddPaths, nativeAddAll, nativeCommit } from "./native-git-bridge.js";
import { ensureGitignore, ensurePreferences, untrackRuntimeFiles } from "./gitignore.js";
import { loadEffectiveGSDPreferences } from "./preferences.js";
import { detectProjectState } from "./detection.js";
@ -40,7 +40,7 @@ function buildDocsCommitInstruction(message: string): string {
const prefs = loadEffectiveGSDPreferences();
const commitDocsEnabled = prefs?.preferences?.git?.commit_docs !== false;
return commitDocsEnabled
? `Commit: \`${message}\``
? `Commit: \`${message}\`. Stage only the .gsd/milestones/, .gsd/PROJECT.md, .gsd/REQUIREMENTS.md, .gsd/DECISIONS.md, and .gitignore files you changed — do not stage .gsd/STATE.md or other runtime files.`
: "Do not commit — planning docs are not tracked in git for this project.";
}

View file

@ -24,7 +24,6 @@ Then:
7. Update `.gsd/REQUIREMENTS.md` if any requirement status transitions were validated in step 5.
8. Update `.gsd/PROJECT.md` to reflect milestone completion and current project state.
9. Do not commit manually — the system auto-commits your changes after this unit completes.
10. Update `.gsd/STATE.md`
**Important:** Do NOT skip the success criteria and definition of done verification (steps 3-4). The milestone summary must reflect actual verified outcomes, not assumed success. If any criterion was not met, document it clearly in the summary and do not mark the milestone as passing verification.

View file

@ -30,7 +30,6 @@ Then:
9. Mark {{sliceId}} done in `{{roadmapPath}}` (change `[ ]` to `[x]`)
10. Do not run git commands — the system commits your changes and handles any merge after this unit succeeds.
11. Update `.gsd/PROJECT.md` if it exists — refresh current state if needed.
12. Update `.gsd/STATE.md`
**You MUST do ALL THREE before finishing: (1) write `{{sliceSummaryPath}}`, (2) write `{{sliceUatPath}}`, (3) mark {{sliceId}} as `[x]` in `{{roadmapPath}}`. The unit will not be marked complete if any of these files are missing.**

View file

@ -50,8 +50,7 @@ Use these templates exactly:
4. Write `{{contextPath}}` (using Context template) — preserve the specification's exact terminology, emphasis, and specific framing. Do not paraphrase domain-specific language into generics. Document assumptions under an "Assumptions" section.
5. Write `{{roadmapPath}}` (using Roadmap template) — decompose into demoable vertical slices with checkboxes, risk, depends, demo sentences, proof strategy, verification classes, milestone definition of done, requirement coverage, and a boundary map. If the milestone crosses multiple runtime boundaries, include an explicit final integration slice.
6. Seed `.gsd/DECISIONS.md` (using Decisions template)
7. Update `.gsd/STATE.md`
8. {{commitInstruction}}
7. {{commitInstruction}}
9. Say exactly: "Milestone {{milestoneId}} ready."
**For multi-milestone**, write in this order:
@ -70,8 +69,7 @@ Use these templates exactly:
# M003: Title
```
Each context file should be rich enough that a future agent — with no memory of this conversation — can understand the intent, constraints, dependencies, what the milestone unlocks, and what "done" looks like.
8. Update `.gsd/STATE.md`
9. {{multiMilestoneCommitInstruction}}
8. {{multiMilestoneCommitInstruction}}
10. Say exactly: "Milestone {{milestoneId}} ready."
## Critical Rules

View file

@ -200,8 +200,7 @@ When writing context.md, preserve the user's exact terminology, emphasis, and sp
4. Write `{{contextPath}}` — use the **Context** output template below. Preserve key risks, unknowns, existing codebase constraints, integration points, and relevant requirements surfaced during discussion.
5. Write `{{roadmapPath}}` — use the **Roadmap** output template below. Decompose into demoable vertical slices with checkboxes, risk, depends, demo sentences, proof strategy, verification classes, milestone definition of done, requirement coverage, and a boundary map. If the milestone crosses multiple runtime boundaries, include an explicit final integration slice that proves the assembled system works end-to-end in a real environment.
6. Seed `.gsd/DECISIONS.md` — use the **Decisions** output template below. Append rows for any architectural or pattern decisions made during discussion.
7. Update `.gsd/STATE.md`
8. {{commitInstruction}}
7. {{commitInstruction}}
After writing the files, say exactly: "Milestone {{milestoneId}} ready." — nothing else. Auto-mode will start automatically.
@ -270,8 +269,7 @@ For single-milestone projects, do NOT write this file — it is only for multi-m
#### Phase 4: Finalize
7. Update `.gsd/STATE.md`
8. {{multiMilestoneCommitInstruction}}
7. {{multiMilestoneCommitInstruction}}
After writing the files, say exactly: "Milestone M001 ready." — nothing else. Auto-mode will start automatically.

View file

@ -65,7 +65,6 @@ Then:
15. Write `{{taskSummaryPath}}`
16. Mark {{taskId}} done in `{{planPath}}` (change `[ ]` to `[x]`)
17. Do not run git commands — the system reads your task summary after completion and creates a meaningful commit from it (type inferred from title, message from your one-liner, key files from frontmatter). Write a clear, specific one-liner in the summary — it becomes the commit message.
18. Update `.gsd/STATE.md`
All work stays in your working directory: `{{workingDirectory}}`.

View file

@ -1,3 +1,3 @@
Complete slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Your working directory is `{{workingDirectory}}` — all file operations must use this path. All tasks are done. Your slice summary is the primary record of what was built — downstream agents (reassess-roadmap, future slice researchers) read it to understand what this slice delivered and what to watch out for. Use the **Slice Summary** and **UAT** output templates below. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during completion, without relaxing required verification or artifact rules. Write `{{sliceId}}-SUMMARY.md` (compress task summaries), write `{{sliceId}}-UAT.md`, and fill the `UAT Type` plus `Not Proven By This UAT` sections explicitly so the artifact states what class of acceptance it covers and what still remains unproven. Review task summaries for `key_decisions` and ensure any significant ones are in `.gsd/DECISIONS.md`. Mark the slice checkbox done in the roadmap, update STATE.md, update milestone summary, Do not commit or merge manually — the system handles this after the unit completes.
Complete slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Your working directory is `{{workingDirectory}}` — all file operations must use this path. All tasks are done. Your slice summary is the primary record of what was built — downstream agents (reassess-roadmap, future slice researchers) read it to understand what this slice delivered and what to watch out for. Use the **Slice Summary** and **UAT** output templates below. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during completion, without relaxing required verification or artifact rules. Write `{{sliceId}}-SUMMARY.md` (compress task summaries), write `{{sliceId}}-UAT.md`, and fill the `UAT Type` plus `Not Proven By This UAT` sections explicitly so the artifact states what class of acceptance it covers and what still remains unproven. Review task summaries for `key_decisions` and ensure any significant ones are in `.gsd/DECISIONS.md`. Mark the slice checkbox done in the roadmap, update milestone summary, Do not commit or merge manually — the system handles this after the unit completes.
{{inlinedTemplates}}

View file

@ -26,6 +26,5 @@ Plan milestone {{milestoneId}} ("{{milestoneTitle}}"). Read `.gsd/DECISIONS.md`
After writing the roadmap, analyze the slices and their boundary maps for external service dependencies (third-party APIs, SaaS platforms, cloud providers, databases requiring credentials, OAuth providers, etc.). If this milestone requires any external API keys or secrets, use the **Secrets Manifest** output template below for the expected format and write `{{secretsOutputPath}}` listing every predicted secret as an H3 section with the Service name, a direct Dashboard URL to the console page where the key is created, a Format hint showing what the key looks like, Status set to `pending`, and Destination (`dotenv`, `vercel`, or `convex`). Include numbered step-by-step guidance for obtaining each key. If this milestone does not require any external API keys or secrets, skip this step entirely — do not create an empty manifest.
**You MUST update `.gsd/STATE.md`** after writing the roadmap (and secrets manifest if applicable). This is required for auto-mode to continue.
{{inlinedTemplates}}

View file

@ -25,7 +25,6 @@ Then:
4. Order by risk (high-risk first)
5. Write `{{outputPath}}` with checkboxes, risk, depends, demo sentences, proof strategy, verification classes, milestone definition of done, **requirement coverage**, and a boundary map. Write success criteria as observable truths, not implementation tasks. If the milestone crosses multiple runtime boundaries, include an explicit final integration slice that proves the assembled system works end-to-end in a real environment
6. If planning produced structural decisions (e.g. slice ordering rationale, technology choices, scope exclusions), append them to `.gsd/DECISIONS.md` (use the **Decisions** output template from the inlined context above if the file doesn't exist yet)
7. Update `.gsd/STATE.md`
## Requirement Mapping Rules

View file

@ -60,7 +60,6 @@ Then:
- **Feature completeness:** Every task produces real, user-facing progress — not just internal scaffolding.
9. If planning produced structural decisions, append them to `.gsd/DECISIONS.md`
10. {{commitInstruction}}
11. Update `.gsd/STATE.md`
The slice directory and tasks/ subdirectory already exist. Do NOT mkdir. All work stays in your working directory: `{{workingDirectory}}`.

View file

@ -39,10 +39,4 @@ You are executing a GSD quick task — a lightweight, focused unit of work outsi
- <what was tested/verified>
```
8. Update `.gsd/STATE.md` — add or update the "Quick Tasks Completed" table:
- If the section doesn't exist, create it after "### Blockers/Concerns"
- Table format: `| # | Description | Date | Commit | Directory |`
- Add a row: `| {{taskNum}} | {{description}} | {{date}} | <commit-hash> | [{{taskNum}}-{{slug}}](./quick/{{taskNum}}-{{slug}}/) |`
- Update the "Last activity" line
When done, say: "Quick task {{taskNum}} complete."

View file

@ -44,7 +44,6 @@ Consider these captures when rewriting the remaining tasks — they represent th
- Update the Files Likely Touched section if the replan changes which files are affected
5. If any incomplete task had a `T0x-PLAN.md`, remove or rewrite it to match the new task description.
6. Do not commit manually — the system auto-commits your changes after this unit completes.
7. Update `.gsd/STATE.md`
**You MUST write `{{replanPath}}` and the updated slice plan before finishing.**

View file

@ -25,7 +25,6 @@ An override was issued by the user that changes a fundamental decision or approa
- Milestone context files are reference only — do not modify them.
4. Mark all active overrides as resolved: change `**Scope:** active` to `**Scope:** resolved` in `{{overridesPath}}`
5. Do not commit manually — the system auto-commits your changes after this unit completes.
6. Update `.gsd/STATE.md`
**You MUST update the relevant documents AND mark overrides as resolved in `{{overridesPath}}` before finishing.**

View file

@ -114,7 +114,7 @@ In all modes, slices commit sequentially on the active branch; there are no per-
- **Tasks** are single-context-window units of work (T01, T02, ...)
- Checkboxes in roadmap and plan files track completion (`[ ]``[x]`)
- Summaries compress prior work - read them instead of re-reading all task details
- `STATE.md` is the quick-glance status file - keep it updated after changes
- `STATE.md` is a system-managed status file — rebuilt automatically after each unit completes
### Artifact Templates

View file

@ -40,11 +40,11 @@ async function main(): Promise<void> {
const result = loadPromptFromWorktree("plan-slice", { ...BASE_VARS, commitInstruction });
assertTrue(result.includes("docs(S01): add slice plan"), "commit step present when commit_docs is not false");
assertTrue(result.includes("Update `.gsd/STATE.md`"), "STATE.md update step present");
assertTrue(!result.includes("Update `.gsd/STATE.md`"), "STATE.md update step removed — system rebuilds it");
assertTrue(!result.includes("{{commitInstruction}}"), "no unresolved placeholder");
}
// ─── commit_docs=false: no commit step, only STATE.md update ────────────
// ─── commit_docs=false: no commit step ──────────────────────────────────
console.log("\n=== plan-slice prompt: commit_docs=false ===");
{
const commitInstruction = "Do not commit — planning docs are not tracked in git for this project.";
@ -52,7 +52,7 @@ async function main(): Promise<void> {
assertTrue(!result.includes("docs(S01): add slice plan"), "commit step absent when commit_docs=false");
assertTrue(result.includes("Do not commit"), "no-commit instruction present");
assertTrue(result.includes("Update `.gsd/STATE.md`"), "STATE.md update step still present");
assertTrue(!result.includes("Update `.gsd/STATE.md`"), "STATE.md update step removed — system rebuilds it");
assertTrue(!result.includes("{{commitInstruction}}"), "no unresolved placeholder");
}