Merge pull request #2111 from gsd-build/feat/1978-prompt-thinning

feat(agents): context-window-aware prompt thinning for sub-200K models
This commit is contained in:
Tom Boucher
2026-04-11 10:38:18 -04:00
committed by GitHub
6 changed files with 352 additions and 39 deletions

View File

@@ -213,6 +213,10 @@ Track auto-fix attempts per task. After 3 auto-fix attempts on a single task:
- STOP fixing — document remaining issues in SUMMARY.md under "Deferred Issues"
- Continue to the next task (or return checkpoint if blocked)
- Do NOT restart the build to find more issues
**Extended examples and edge case guide:**
For detailed deviation rule examples, checkpoint examples, and edge case decision guidance:
@~/.claude/get-shit-done/references/executor-examples.md
</deviation_rules>
<analysis_paralysis_guard>

View File

@@ -284,17 +284,9 @@ When a plan creates new interfaces consumed by subsequent tasks:
This prevents the "scavenger hunt" anti-pattern where executors explore the codebase to understand contracts. They receive the contracts in the plan itself.
## Specificity Examples
## Specificity
| TOO VAGUE | JUST RIGHT |
|-----------|------------|
| "Add authentication" | "Add JWT auth with refresh rotation using jose library, store in httpOnly cookie, 15min access / 7day refresh" |
| "Create the API" | "Create POST /api/projects endpoint accepting {name, description}, validates name length 3-50 chars, returns 201 with project object" |
| "Style the dashboard" | "Add Tailwind classes to Dashboard.tsx: grid layout (3 cols on lg, 1 on mobile), card shadows, hover states on action buttons" |
| "Handle errors" | "Wrap API calls in try/catch, return {error: string} on 4xx/5xx, show toast via sonner on client" |
| "Set up the database" | "Add User and Project models to schema.prisma with UUID ids, email unique constraint, createdAt/updatedAt timestamps, run prisma db push" |
**Test:** Could a different Claude instance execute without asking clarifying questions? If not, add specificity.
**Test:** Could a different Claude instance execute without asking clarifying questions? If not, add specificity. See @~/.claude/get-shit-done/references/planner-antipatterns.md for vague-vs-specific comparison table.
## TDD Detection
@@ -758,36 +750,10 @@ When Claude tries CLI/API and gets auth error → creates checkpoint → user au
**DON'T:** Ask human to do work Claude can automate, mix multiple verifications, place checkpoints before automation completes.
## Anti-Patterns
## Anti-Patterns and Extended Examples
**Bad - Asking human to automate:**
```xml
<task type="checkpoint:human-action">
<action>Deploy to Vercel</action>
<instructions>Visit vercel.com, import repo, click deploy...</instructions>
</task>
```
Why bad: Vercel has a CLI. Claude should run `vercel --yes`.
**Bad - Too many checkpoints:**
```xml
<task type="auto">Create schema</task>
<task type="checkpoint:human-verify">Check schema</task>
<task type="auto">Create API</task>
<task type="checkpoint:human-verify">Check API</task>
```
Why bad: Verification fatigue. Combine into one checkpoint at end.
**Good - Single verification checkpoint:**
```xml
<task type="auto">Create schema</task>
<task type="auto">Create API</task>
<task type="auto">Create UI</task>
<task type="checkpoint:human-verify">
<what-built>Complete auth flow (schema + API + UI)</what-built>
<how-to-verify>Test full flow: register, login, access protected page</how-to-verify>
</task>
```
For checkpoint anti-patterns, specificity comparison tables, context section anti-patterns, and scope reduction patterns:
@~/.claude/get-shit-done/references/planner-antipatterns.md
</checkpoints>

View File

@@ -0,0 +1,110 @@
# Executor Extended Examples
> Reference file for gsd-executor agent. Loaded on-demand via `@` reference.
> For sub-200K context windows, this content is stripped from the agent prompt and available here for on-demand loading.
## Deviation Rule Examples
### Rule 1 — Auto-fix bugs
**Examples of Rule 1 triggers:**
- Wrong queries returning incorrect data
- Logic errors in conditionals
- Type errors and type mismatches
- Null pointer exceptions / undefined access
- Broken validation (accepts invalid input)
- Security vulnerabilities (XSS, SQL injection)
- Race conditions in async code
- Memory leaks from uncleaned resources
### Rule 2 — Auto-add missing critical functionality
**Examples of Rule 2 triggers:**
- Missing error handling (unhandled promise rejections, no try/catch on I/O)
- No input validation on user-facing endpoints
- Missing null checks before property access
- No auth on protected routes
- Missing authorization checks (user can access other users' data)
- No CSRF/CORS configuration
- No rate limiting on public endpoints
- Missing DB indexes on frequently queried columns
- No error logging (failures silently swallowed)
### Rule 3 — Auto-fix blocking issues
**Examples of Rule 3 triggers:**
- Missing dependency not in package.json
- Wrong types preventing compilation
- Broken imports (wrong path, wrong export name)
- Missing env var required at runtime
- DB connection error (wrong URL, missing credentials)
- Build config error (wrong entry point, missing loader)
- Missing referenced file (import points to non-existent module)
- Circular dependency preventing module load
### Rule 4 — Ask about architectural changes
**Examples of Rule 4 triggers:**
- New DB table (not just adding a column)
- Major schema changes (renaming tables, changing relationships)
- New service layer (adding a queue, cache, or message bus)
- Switching libraries/frameworks (e.g., replacing Express with Fastify)
- Changing auth approach (switching from session to JWT)
- New infrastructure (adding Redis, S3, etc.)
- Breaking API changes (removing or renaming endpoints)
## Edge Case Decision Guide
| Scenario | Rule | Rationale |
|----------|------|-----------|
| Missing validation on input | Rule 2 | Security requirement |
| Crashes on null input | Rule 1 | Bug — incorrect behavior |
| Need new database table | Rule 4 | Architectural decision |
| Need new column on existing table | Rule 1 or 2 | Depends on context |
| Pre-existing linting warnings | Out of scope | Not caused by current task |
| Unrelated test failures | Out of scope | Not caused by current task |
**Decision heuristic:** "Does this affect correctness, security, or ability to complete the current task?"
- YES → Rules 1-3 (fix automatically)
- MAYBE → Rule 4 (ask the user)
- NO → Out of scope (log to deferred-items.md)
## Checkpoint Examples
### Good checkpoint placement
```xml
<!-- Automate everything, then verify at the end -->
<task type="auto">Create database schema</task>
<task type="auto">Create API endpoints</task>
<task type="auto">Create UI components</task>
<task type="checkpoint:human-verify">
<what-built>Complete auth flow (schema + API + UI)</what-built>
<how-to-verify>
1. Visit http://localhost:3000/register
2. Create account with test@example.com
3. Log in with those credentials
4. Verify dashboard loads with user name
</how-to-verify>
</task>
```
### Bad checkpoint placement
```xml
<!-- Too many checkpoints — causes verification fatigue -->
<task type="auto">Create schema</task>
<task type="checkpoint:human-verify">Check schema</task>
<task type="auto">Create API</task>
<task type="checkpoint:human-verify">Check API</task>
<task type="auto">Create UI</task>
<task type="checkpoint:human-verify">Check UI</task>
```
### Auth gate handling
When an auth error occurs during `type="auto"` execution:
1. Recognize it as an auth gate (not a bug) — indicators: "Not authenticated", "401", "403", "Please run X login"
2. STOP the current task
3. Return a `checkpoint:human-action` with exact auth steps
4. In SUMMARY.md, document auth gates as normal flow, not deviations

View File

@@ -0,0 +1,89 @@
# Planner Anti-Patterns and Specificity Examples
> Reference file for gsd-planner agent. Loaded on-demand via `@` reference.
> For sub-200K context windows, this content is stripped from the agent prompt and available here for on-demand loading.
## Checkpoint Anti-Patterns
### Bad — Asking human to automate
```xml
<task type="checkpoint:human-action">
<action>Deploy to Vercel</action>
<instructions>Visit vercel.com, import repo, click deploy...</instructions>
</task>
```
**Why bad:** Vercel has a CLI. Claude should run `vercel --yes`. Never ask the user to do what Claude can automate via CLI/API.
### Bad — Too many checkpoints
```xml
<task type="auto">Create schema</task>
<task type="checkpoint:human-verify">Check schema</task>
<task type="auto">Create API</task>
<task type="checkpoint:human-verify">Check API</task>
```
**Why bad:** Verification fatigue. Users should not be asked to verify every small step. Combine into one checkpoint at the end of meaningful work.
### Good — Single verification checkpoint
```xml
<task type="auto">Create schema</task>
<task type="auto">Create API</task>
<task type="auto">Create UI</task>
<task type="checkpoint:human-verify">
<what-built>Complete auth flow (schema + API + UI)</what-built>
<how-to-verify>Test full flow: register, login, access protected page</how-to-verify>
</task>
```
### Bad — Mixing checkpoints with implementation
A plan should not interleave multiple checkpoint types with implementation tasks. Checkpoints belong at natural verification boundaries, not scattered throughout.
## Specificity Examples
| TOO VAGUE | JUST RIGHT |
|-----------|------------|
| "Add authentication" | "Add JWT auth with refresh rotation using jose library, store in httpOnly cookie, 15min access / 7day refresh" |
| "Create the API" | "Create POST /api/projects endpoint accepting {name, description}, validates name length 3-50 chars, returns 201 with project object" |
| "Style the dashboard" | "Add Tailwind classes to Dashboard.tsx: grid layout (3 cols on lg, 1 on mobile), card shadows, hover states on action buttons" |
| "Handle errors" | "Wrap API calls in try/catch, return {error: string} on 4xx/5xx, show toast via sonner on client" |
| "Set up the database" | "Add User and Project models to schema.prisma with UUID ids, email unique constraint, createdAt/updatedAt timestamps, run prisma db push" |
**Specificity test:** Could a different Claude instance execute the task without asking clarifying questions? If not, add more detail.
## Context Section Anti-Patterns
### Bad — Reflexive SUMMARY chaining
```markdown
<context>
@.planning/phases/01-foundation/01-01-SUMMARY.md
@.planning/phases/01-foundation/01-02-SUMMARY.md <!-- Does Plan 02 actually need Plan 01's output? -->
@.planning/phases/01-foundation/01-03-SUMMARY.md <!-- Chain grows, context bloats -->
</context>
```
**Why bad:** Plans are often independent. Reflexive chaining (02 refs 01, 03 refs 02...) wastes context. Only reference prior SUMMARY files when the plan genuinely uses types/exports from that prior plan or a decision from it affects the current plan.
### Good — Selective context
```markdown
<context>
@.planning/PROJECT.md
@.planning/STATE.md
@.planning/phases/01-foundation/01-01-SUMMARY.md <!-- Uses User type defined in Plan 01 -->
</context>
```
## Scope Reduction Anti-Patterns
**Prohibited language in task actions:**
- "v1", "v2", "simplified version", "static for now", "hardcoded for now"
- "future enhancement", "placeholder", "basic version", "minimal implementation"
- "will be wired later", "dynamic in future phase", "skip for now"
If a decision from CONTEXT.md says "display cost calculated from billing table in impulses", the plan must deliver exactly that. Not "static label /min" as a "v1". If the phase is too complex, recommend a phase split instead of silently reducing scope.

View File

@@ -95,6 +95,12 @@ When `CONTEXT_WINDOW >= 500000` (1M-class models), subagent prompts include rich
- Verifier agents receive all PLAN.md, SUMMARY.md, CONTEXT.md files plus REQUIREMENTS.md
- This enables cross-phase awareness and history-aware verification
When `CONTEXT_WINDOW < 200000` (sub-200K models), subagent prompts are thinned to reduce static overhead:
- Executor agents omit extended deviation rule examples and checkpoint examples from inline prompt — load on-demand via @~/.claude/get-shit-done/references/executor-examples.md
- Planner agents omit extended anti-pattern lists and specificity examples from inline prompt — load on-demand via @~/.claude/get-shit-done/references/planner-antipatterns.md
- Core rules and decision logic remain inline; only verbose examples and edge-case lists are extracted
- This reduces executor static overhead by ~40% while preserving behavioral correctness
**If `phase_found` is false:** Error — phase directory not found.
**If `plan_count` is 0:** Error — no plans found in phase.
**If `state_exists` is false but `.planning/` exists:** Offer reconstruct or continue.
@@ -468,6 +474,7 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
@~/.claude/get-shit-done/templates/summary.md
@~/.claude/get-shit-done/references/checkpoints.md
@~/.claude/get-shit-done/references/tdd.md
${CONTEXT_WINDOW < 200000 ? '' : '@~/.claude/get-shit-done/references/executor-examples.md'}
</execution_context>
<files_to_read>

View File

@@ -0,0 +1,137 @@
'use strict';
/**
* Prompt Thinning Tests (#1978)
*
* Validates context-window-aware prompt thinning for sub-200K models.
* When CONTEXT_WINDOW < 200000, agent prompts strip extended examples
* and anti-pattern lists, referencing them as @-required_reading files instead.
*/
const { test, describe } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('fs');
const path = require('path');
const EXECUTE_PHASE = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'execute-phase.md');
const EXECUTOR_AGENT = path.join(__dirname, '..', 'agents', 'gsd-executor.md');
const PLANNER_AGENT = path.join(__dirname, '..', 'agents', 'gsd-planner.md');
const EXECUTOR_EXAMPLES_REF = path.join(__dirname, '..', 'get-shit-done', 'references', 'executor-examples.md');
const PLANNER_ANTIPATTERNS_REF = path.join(__dirname, '..', 'get-shit-done', 'references', 'planner-antipatterns.md');
describe('prompt thinning — sub-200K context window support (#1978)', () => {
describe('execute-phase.md — thinning conditional', () => {
test('has a CONTEXT_WINDOW < 200000 thinning conditional', () => {
const content = fs.readFileSync(EXECUTE_PHASE, 'utf-8');
assert.ok(
content.includes('CONTEXT_WINDOW < 200000') || content.includes('CONTEXT_WINDOW< 200000'),
'execute-phase.md must contain a CONTEXT_WINDOW < 200000 conditional for prompt thinning'
);
});
test('preserves the existing CONTEXT_WINDOW >= 500000 enrichment conditional', () => {
const content = fs.readFileSync(EXECUTE_PHASE, 'utf-8');
assert.ok(
content.includes('CONTEXT_WINDOW >= 500000'),
'execute-phase.md must preserve the existing 500K enrichment conditional'
);
});
test('thinning block references executor-examples.md for on-demand loading', () => {
const content = fs.readFileSync(EXECUTE_PHASE, 'utf-8');
assert.ok(
content.includes('executor-examples.md'),
'execute-phase.md thinning block must reference executor-examples.md'
);
});
});
describe('gsd-executor.md — reference to extracted examples', () => {
test('references executor-examples.md for extended examples', () => {
const content = fs.readFileSync(EXECUTOR_AGENT, 'utf-8');
assert.ok(
content.includes('executor-examples.md'),
'gsd-executor.md must reference executor-examples.md for extended deviation/checkpoint examples'
);
});
});
describe('gsd-planner.md — reference to extracted anti-patterns', () => {
test('references planner-antipatterns.md for extended anti-patterns', () => {
const content = fs.readFileSync(PLANNER_AGENT, 'utf-8');
assert.ok(
content.includes('planner-antipatterns.md'),
'gsd-planner.md must reference planner-antipatterns.md for extended checkpoint anti-patterns and specificity examples'
);
});
});
describe('executor-examples.md — extracted reference file', () => {
test('file exists', () => {
assert.ok(
fs.existsSync(EXECUTOR_EXAMPLES_REF),
'get-shit-done/references/executor-examples.md must exist'
);
});
test('contains deviation rule examples', () => {
const content = fs.readFileSync(EXECUTOR_EXAMPLES_REF, 'utf-8');
assert.ok(
content.includes('Rule 1') || content.includes('RULE 1'),
'executor-examples.md must contain deviation rule examples'
);
});
test('contains checkpoint examples', () => {
const content = fs.readFileSync(EXECUTOR_EXAMPLES_REF, 'utf-8');
assert.ok(
content.includes('checkpoint') || content.includes('Checkpoint'),
'executor-examples.md must contain checkpoint examples'
);
});
test('contains edge case examples', () => {
const content = fs.readFileSync(EXECUTOR_EXAMPLES_REF, 'utf-8');
assert.ok(
content.includes('Edge case') || content.includes('edge case') || content.includes('Edge Case'),
'executor-examples.md must contain edge case guidance'
);
});
});
describe('planner-antipatterns.md — extracted reference file', () => {
test('file exists', () => {
assert.ok(
fs.existsSync(PLANNER_ANTIPATTERNS_REF),
'get-shit-done/references/planner-antipatterns.md must exist'
);
});
test('contains checkpoint anti-patterns', () => {
const content = fs.readFileSync(PLANNER_ANTIPATTERNS_REF, 'utf-8');
assert.ok(
content.includes('anti-pattern') || content.includes('Anti-Pattern') || content.includes('Bad'),
'planner-antipatterns.md must contain checkpoint anti-pattern examples'
);
});
test('contains specificity examples', () => {
const content = fs.readFileSync(PLANNER_ANTIPATTERNS_REF, 'utf-8');
assert.ok(
content.includes('TOO VAGUE') || content.includes('Specificity') || content.includes('specificity'),
'planner-antipatterns.md must contain specificity examples'
);
});
});
describe('three-tier consistency', () => {
test('thinning tier (< 200K), standard tier (200K-500K), and enrichment tier (>= 500K) all coexist', () => {
const content = fs.readFileSync(EXECUTE_PHASE, 'utf-8');
const hasThinning = content.includes('CONTEXT_WINDOW < 200000');
const hasEnrichment = content.includes('CONTEXT_WINDOW >= 500000');
assert.ok(hasThinning, 'must have thinning conditional (< 200K)');
assert.ok(hasEnrichment, 'must have enrichment conditional (>= 500K)');
});
});
});