@tekyzinc/gsd-t 2.45.11 → 2.50.10

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +26 -5
  3. package/bin/debug-ledger.js +193 -0
  4. package/bin/gsd-t.js +259 -1
  5. package/commands/gsd-t-complete-milestone.md +2 -1
  6. package/commands/gsd-t-debug.md +48 -2
  7. package/commands/gsd-t-doc-ripple.md +148 -0
  8. package/commands/gsd-t-execute.md +102 -5
  9. package/commands/gsd-t-help.md +25 -2
  10. package/commands/gsd-t-integrate.md +41 -1
  11. package/commands/gsd-t-qa.md +26 -5
  12. package/commands/gsd-t-quick.md +39 -1
  13. package/commands/gsd-t-test-sync.md +26 -1
  14. package/commands/gsd-t-verify.md +8 -2
  15. package/commands/gsd-t-wave.md +57 -0
  16. package/docs/GSD-T-README.md +84 -1
  17. package/docs/architecture.md +9 -1
  18. package/docs/framework-comparison-scorecard.md +160 -0
  19. package/docs/requirements.md +33 -0
  20. package/examples/rules/desktop.ini +2 -0
  21. package/package.json +2 -2
  22. package/templates/CLAUDE-global.md +82 -4
  23. package/templates/stacks/_security.md +243 -0
  24. package/templates/stacks/desktop.ini +2 -0
  25. package/templates/stacks/docker.md +202 -0
  26. package/templates/stacks/firebase.md +166 -0
  27. package/templates/stacks/flutter.md +205 -0
  28. package/templates/stacks/github-actions.md +201 -0
  29. package/templates/stacks/graphql.md +216 -0
  30. package/templates/stacks/neo4j.md +218 -0
  31. package/templates/stacks/nextjs.md +184 -0
  32. package/templates/stacks/node-api.md +196 -0
  33. package/templates/stacks/playwright.md +528 -0
  34. package/templates/stacks/postgresql.md +225 -0
  35. package/templates/stacks/python.md +243 -0
  36. package/templates/stacks/react-native.md +216 -0
  37. package/templates/stacks/react.md +293 -0
  38. package/templates/stacks/redux.md +193 -0
  39. package/templates/stacks/rest-api.md +202 -0
  40. package/templates/stacks/supabase.md +188 -0
  41. package/templates/stacks/tailwind.md +169 -0
  42. package/templates/stacks/typescript.md +176 -0
  43. package/templates/stacks/vite.md +176 -0
  44. package/templates/stacks/vue.md +189 -0
  45. package/templates/stacks/zustand.md +203 -0
@@ -8,6 +8,22 @@ To give this debug session a fresh context window and prevent compaction, always
8
8
 
9
9
  **If you are the orchestrating agent** (you received the slash command directly):
10
10
 
11
+ **Stack Rules Detection (before spawning subagent):**
12
+ Run via Bash to detect project stack and collect matching rules:
13
+ `GSD_T_DIR=$(npm root -g 2>/dev/null)/@tekyzinc/gsd-t; STACKS_DIR="$GSD_T_DIR/templates/stacks"; STACK_RULES=""; if [ -d "$STACKS_DIR" ]; then for f in "$STACKS_DIR"/_*.md; do [ -f "$f" ] && STACK_RULES="${STACK_RULES}$(cat "$f")"$'\n\n'; done; if [ -f "package.json" ]; then grep -q '"react-native"' package.json 2>/dev/null && [ -f "$STACKS_DIR/react-native.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/react-native.md")"$'\n\n'; grep -q '"react"' package.json 2>/dev/null && ! grep -q '"react-native"' package.json 2>/dev/null && [ -f "$STACKS_DIR/react.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/react.md")"$'\n\n'; grep -q '"next"' package.json 2>/dev/null && [ -f "$STACKS_DIR/nextjs.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/nextjs.md")"$'\n\n'; grep -q '"vue"' package.json 2>/dev/null && [ -f "$STACKS_DIR/vue.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/vue.md")"$'\n\n'; (grep -q '"typescript"' package.json 2>/dev/null || [ -f "tsconfig.json" ]) && [ -f "$STACKS_DIR/typescript.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/typescript.md")"$'\n\n'; grep -qE '"(express|fastify|hono|koa)"' package.json 2>/dev/null && [ -f "$STACKS_DIR/node-api.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/node-api.md")"$'\n\n'; grep -q '"tailwindcss"' package.json 2>/dev/null && [ -f "$STACKS_DIR/tailwind.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/tailwind.md")"$'\n\n'; grep -q '"vite"' package.json 2>/dev/null && [ -f "$STACKS_DIR/vite.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/vite.md")"$'\n\n'; grep -q '"@supabase/supabase-js"' package.json 2>/dev/null && [ -f "$STACKS_DIR/supabase.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/supabase.md")"$'\n\n'; grep -q '"firebase"' package.json 2>/dev/null && [ -f "$STACKS_DIR/firebase.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/firebase.md")"$'\n\n'; grep -qE '"(graphql|@apollo/client|urql)"' package.json 2>/dev/null && [ -f "$STACKS_DIR/graphql.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/graphql.md")"$'\n\n'; grep -q '"zustand"' package.json 2>/dev/null && [ -f "$STACKS_DIR/zustand.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/zustand.md")"$'\n\n'; grep -q '"@reduxjs/toolkit"' package.json 2>/dev/null && [ -f "$STACKS_DIR/redux.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/redux.md")"$'\n\n'; grep -q '"neo4j-driver"' package.json 2>/dev/null && [ -f "$STACKS_DIR/neo4j.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/neo4j.md")"$'\n\n'; grep -qE '"(pg|prisma|drizzle-orm|knex)"' package.json 2>/dev/null && [ -f "$STACKS_DIR/postgresql.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/postgresql.md")"$'\n\n'; grep -qE '"(express|fastify|hono|koa)"' package.json 2>/dev/null && [ -f "$STACKS_DIR/rest-api.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/rest-api.md")"$'\n\n'; fi; ([ -f "requirements.txt" ] || [ -f "pyproject.toml" ] || [ -f "Pipfile" ]) && [ -f "$STACKS_DIR/python.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/python.md")"$'\n\n'; ([ -f "requirements.txt" ] && grep -q "psycopg" requirements.txt 2>/dev/null || [ -f "pyproject.toml" ] && grep -q "psycopg" pyproject.toml 2>/dev/null) && [ -f "$STACKS_DIR/postgresql.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/postgresql.md")"$'\n\n'; ([ -f "requirements.txt" ] && grep -q "neo4j" requirements.txt 2>/dev/null) && [ -f "$STACKS_DIR/neo4j.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/neo4j.md")"$'\n\n'; [ -f "pubspec.yaml" ] && [ -f "$STACKS_DIR/flutter.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/flutter.md")"$'\n\n'; [ -f "Dockerfile" ] && [ -f "$STACKS_DIR/docker.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/docker.md")"$'\n\n'; [ -d ".github/workflows" ] && [ -f "$STACKS_DIR/github-actions.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/github-actions.md")"$'\n\n'; ([ -f "playwright.config.ts" ] || [ -f "playwright.config.js" ]) && [ -f "$STACKS_DIR/playwright.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/playwright.md")"$'\n\n'; [ -f "go.mod" ] && [ -f "$STACKS_DIR/go.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/go.md")"$'\n\n'; [ -f "Cargo.toml" ] && [ -f "$STACKS_DIR/rust.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/rust.md")"$'\n\n'; fi`
14
+
15
+ If STACK_RULES is non-empty, append to the subagent prompt:
16
+ ```
17
+ ## Stack Rules (MANDATORY — violations fail this task)
18
+
19
+ {STACK_RULES}
20
+
21
+ These standards have the same enforcement weight as contract compliance.
22
+ Violations are task failures, not warnings.
23
+ ```
24
+
25
+ If STACK_RULES is empty (no templates/stacks/ dir or no matches), skip silently.
26
+
11
27
  **OBSERVABILITY LOGGING (MANDATORY):**
12
28
  Before spawning — run via Bash:
13
29
  `T_START=$(date +%s) && DT_START=$(date +"%Y-%m-%d %H:%M") && TOK_START=${CLAUDE_CONTEXT_TOKENS_USED:-0} && TOK_MAX=${CLAUDE_CONTEXT_TOKENS_MAX:-200000}`
@@ -215,7 +231,16 @@ When you encounter unexpected situations during the fix:
215
231
  3. **Blocker (missing file, wrong API response)** → Fix blocker and continue. Log if non-trivial.
216
232
  4. **Architectural change required to fix correctly** → STOP. Explain what exists, what needs to change, what breaks, and a migration path. Wait for user approval. Never self-approve.
217
233
 
218
- **3-attempt limit**: If your fix doesn't work after 3 attempts within this session, treat it as a loop. Do NOT keep trying the same approach. Log the attempt to `.gsd-t/progress.md` Decision Log with a `[failure]` prefix, then return to Step 1.5 and run Deep Research Mode before any further attempts. Present findings and options to the user before proceeding.
234
+ **3-attempt limit**: If your fix doesn't work after 3 attempts within this session, treat it as a loop. Do NOT keep trying the same approach. Before entering Deep Research Mode, first try the headless debug-loop:
235
+ 1. Write current failure context to `.gsd-t/debug-state.jsonl` via appendEntry
236
+ 2. Log: "Delegating to headless debug-loop (3 in-context attempts exhausted)"
237
+ 3. Run: `gsd-t headless --debug-loop --max-iterations 10`
238
+ 4. Check exit code:
239
+ - 0: Tests pass, continue
240
+ - 1/4: Log to `.gsd-t/deferred-items.md`, then enter Deep Research Mode
241
+ - 3: Report error, stop
242
+
243
+ If the debug-loop also fails (exit 1/4), log the attempt to `.gsd-t/progress.md` Decision Log with a `[failure]` prefix, return to Step 1.5 and run Deep Research Mode before any further attempts. Present findings and options to the user before proceeding.
219
244
 
220
245
  ### Solo Mode
221
246
  1. Reproduce the issue — **reproduction script must exist before step 2** (see Step 2.5)
@@ -288,7 +313,8 @@ Before committing, ensure the fix is solid:
288
313
  d. Report ALL results: "Unit: X/Y pass | E2E: X/Y pass"
289
314
  3. **Verify passing**: All tests must pass. If any fail, fix before proceeding (up to 2 attempts)
290
315
  4. **If the project has a UI but no E2E specs cover the fixed area**: WRITE THEM.
291
- 5. **Regression check**: Confirm the fix doesn't break any adjacent functionality
316
+ 5. **Functional test quality**: Every E2E assertion must verify an action produced the correct outcome (state changed, data loaded, content updated) — not just that elements exist. Tests that only check `isVisible`/`toBeEnabled` are shallow layout tests and don't catch real bugs. If a test would pass on an empty HTML page with the right IDs, rewrite it.
317
+ 6. **Regression check**: Confirm the fix doesn't break any adjacent functionality
292
318
 
293
319
  Commit: `[debug] Fix {description} — root cause: {explanation}`
294
320
 
@@ -302,6 +328,26 @@ Signal type is always `debug-invoked` for debug sessions.
302
328
  Emit task_complete event — run via Bash:
303
329
  `node ~/.claude/scripts/gsd-t-event-writer.js --type task_complete --command gsd-t-debug --reasoning "signal_type=debug-invoked, domain={domain}" --outcome {success|failure} || true`
304
330
 
331
+ ## Step 6: Doc-Ripple (Automated)
332
+
333
+ After all work is committed but before reporting completion:
334
+
335
+ 1. Run threshold check — read `git diff --name-only HEAD~1` and evaluate against doc-ripple-contract.md trigger conditions
336
+ 2. If SKIP: log "Doc-ripple: SKIP — {reason}" and proceed to completion
337
+ 3. If FIRE: spawn doc-ripple agent:
338
+
339
+ ⚙ [{model}] gsd-t-doc-ripple → blast radius analysis + parallel updates
340
+
341
+ Task subagent (general-purpose, model: sonnet):
342
+ "Execute the doc-ripple workflow per commands/gsd-t-doc-ripple.md.
343
+ Git diff context: {files changed list}
344
+ Command that triggered: debug
345
+ Produce manifest at .gsd-t/doc-ripple-manifest.md.
346
+ Update all affected documents.
347
+ Report: 'Doc-ripple: {N} checked, {N} updated, {N} skipped'"
348
+
349
+ 4. After doc-ripple returns, verify manifest exists and report summary inline
350
+
305
351
  $ARGUMENTS
306
352
 
307
353
  ## Auto-Clear
@@ -0,0 +1,148 @@
1
+ # GSD-T: Doc-Ripple — Automated Document Ripple Enforcement
2
+
3
+ You are the doc-ripple agent. You identify and update all downstream documents after code changes. You are spawned by execute, integrate, quick, debug, and wave after primary work is committed.
4
+
5
+ ## Step 1: Load Context
6
+
7
+ Read:
8
+ 1. `CLAUDE.md` — project conventions and Pre-Commit Gate (project-specific extensions)
9
+ 2. `.gsd-t/contracts/doc-ripple-contract.md` — trigger conditions, manifest format, update protocol
10
+ 3. `.gsd-t/contracts/pre-commit-gate.md` — the gate checklist you cross-reference
11
+
12
+ Run via Bash:
13
+ `git diff --name-only HEAD~1 2>/dev/null || git diff --cached --name-only`
14
+
15
+ Store the changed file list for Steps 2–3.
16
+
17
+ ## Step 2: Threshold Check
18
+
19
+ Evaluate the changed file list against trigger conditions from `doc-ripple-contract.md`.
20
+
21
+ Output exactly:
22
+ ```
23
+ DOC-RIPPLE THRESHOLD: {FIRE|SKIP}
24
+ Files changed: {N} across {N} directories
25
+ Cross-cutting signals: {list or "none"}
26
+ Reason: {brief explanation}
27
+ ```
28
+
29
+ **If SKIP**: log the decision, output `Doc-ripple: SKIP — {reason}`, and stop. No manifest. No updates.
30
+
31
+ **If FIRE**: proceed to Step 3.
32
+
33
+ ## Step 3: Blast Radius Analysis
34
+
35
+ For each changed file, classify its type: source, test, contract, template, command, doc, config.
36
+
37
+ Cross-reference `.gsd-t/contracts/pre-commit-gate.md` gate checklist:
38
+ - API endpoint/shape changed → api-contract.md, Swagger spec, CLAUDE.md, README.md
39
+ - Database schema changed → schema-contract.md, docs/schema.md
40
+ - UI component interface changed → component-contract.md
41
+ - New files or directories added → owning domain scope.md
42
+ - Requirement implemented or changed → docs/requirements.md
43
+ - Component or data flow changed → docs/architecture.md
44
+ - Any file modified → .gsd-t/progress.md (Decision Log entry)
45
+ - Architectural decision made → .gsd-t/progress.md (with rationale)
46
+ - Tech debt discovered or fixed → .gsd-t/techdebt.md
47
+ - New convention established → CLAUDE.md or domain constraints.md
48
+ - Command file added/changed → GSD-T-README.md, README.md, templates/CLAUDE-global.md, commands/gsd-t-help.md
49
+ - Command added/removed → all 4 above + package.json version + bin/gsd-t.js count
50
+ - Wave flow changed → gsd-t-wave.md, GSD-T-README.md, README.md
51
+ - Template changed → verify gsd-t-init output
52
+
53
+ Build the final list: `{ document, status (UPDATED|SKIPPED), action, reason }`.
54
+
55
+ ## Step 4: Generate Manifest
56
+
57
+ Write `.gsd-t/doc-ripple-manifest.md` (overwrite):
58
+
59
+ ```markdown
60
+ # Doc-Ripple Manifest — {date}
61
+
62
+ ## Trigger
63
+ - Command: {triggering command}
64
+ - Files changed: {N}
65
+ - Threshold: FIRE — {reason}
66
+
67
+ ## Blast Radius
68
+
69
+ | Document | Status | Action | Reason |
70
+ |----------|--------|--------|--------|
71
+ | {path} | {UPDATED|SKIPPED} | {action} | {reason} |
72
+
73
+ ## Summary
74
+ - Documents checked: {N}
75
+ - Documents updated: {N}
76
+ - Documents skipped (already current): {N}
77
+ ```
78
+
79
+ ## Step 5: Update Documents
80
+
81
+ Count documents marked UPDATED.
82
+
83
+ **Fewer than 3 updates — inline:**
84
+ For each document: read current content → determine minimal edit → apply via Edit tool (not Write) → verify after edit.
85
+
86
+ **3 or more updates — parallel subagents:**
87
+
88
+ For each document or logical group:
89
+
90
+ ⚙ [haiku] gsd-t-doc-ripple → update {document}
91
+ (Use sonnet for docs/architecture.md and docs/requirements.md — these need reasoning.)
92
+
93
+ **OBSERVABILITY LOGGING (MANDATORY) — for each subagent spawn:**
94
+
95
+ Before spawning — run via Bash:
96
+ `T_START=$(date +%s) && DT_START=$(date +"%Y-%m-%d %H:%M") && TOK_START=${CLAUDE_CONTEXT_TOKENS_USED:-0} && TOK_MAX=${CLAUDE_CONTEXT_TOKENS_MAX:-200000}`
97
+
98
+ After subagent returns — run via Bash:
99
+ `T_END=$(date +%s) && DT_END=$(date +"%Y-%m-%d %H:%M") && TOK_END=${CLAUDE_CONTEXT_TOKENS_USED:-0} && DURATION=$((T_END-T_START))`
100
+
101
+ Compute tokens:
102
+ - No compaction (TOK_END >= TOK_START): `TOKENS=$((TOK_END-TOK_START))`, COMPACTED=null
103
+ - Compaction detected (TOK_END < TOK_START): `TOKENS=$(((TOK_MAX-TOK_START)+TOK_END))`, COMPACTED=$DT_END
104
+
105
+ Compute context utilization:
106
+ `if [ "${CLAUDE_CONTEXT_TOKENS_MAX:-0}" -gt 0 ]; then CTX_PCT=$(echo "scale=1; ${CLAUDE_CONTEXT_TOKENS_USED:-0} * 100 / ${CLAUDE_CONTEXT_TOKENS_MAX}" | bc); else CTX_PCT="N/A"; fi`
107
+
108
+ Alert thresholds:
109
+ - CTX_PCT >= 85: `echo "🔴 CRITICAL: Context at ${CTX_PCT}% — compaction likely. Task MUST be split."`
110
+ - CTX_PCT >= 70: `echo "⚠️ WARNING: Context at ${CTX_PCT}% — approaching compaction threshold. Consider splitting."`
111
+
112
+ Append to `.gsd-t/token-log.md` (create with header `| Datetime-start | Datetime-end | Command | Step | Model | Duration(s) | Notes | Tokens | Compacted | Domain | Task | Ctx% |` if missing):
113
+ `| {DT_START} | {DT_END} | gsd-t-doc-ripple | Step 5 | {model} | {DURATION}s | update:{document} | {TOKENS} | {COMPACTED} | doc-ripple | — | {CTX_PCT} |`
114
+
115
+ **Each document-update subagent prompt:**
116
+ ```
117
+ Task subagent (general-purpose, model: {haiku|sonnet}):
118
+ "Update a single document as part of doc-ripple enforcement.
119
+
120
+ Document to update: {path}
121
+ Action: {action from manifest}
122
+ Reason: {reason from manifest}
123
+ Git diff context (changed files): {file list}
124
+
125
+ Instructions:
126
+ 1. Read the current document
127
+ 2. Apply the minimal edit — add/update only the affected section
128
+ 3. Use the Edit tool (not Write) — preserve all existing content
129
+ 4. Re-read after edit to confirm correctness
130
+ 5. Report: 'Updated {document} — {one-line summary of change}'"
131
+ ```
132
+
133
+ ## Step 6: Report Summary
134
+
135
+ Output:
136
+ ```
137
+ Doc-ripple: {N} checked, {N} updated, {N} skipped
138
+ ```
139
+
140
+ List each updated document with a one-line summary of what changed.
141
+
142
+ If any update failed, list it under `Failures:` and flag for manual review.
143
+
144
+ $ARGUMENTS
145
+
146
+ ## Auto-Clear
147
+
148
+ All work is written to project files. Execute `/clear` to free the context window for the next command.
@@ -119,6 +119,22 @@ Run via Bash:
119
119
  If rules fire: inject up to 10 lines of rule warnings into each task subagent prompt (concise format: `RULE: {name} — {description}`). These inform the subagent of known patterns — non-blocking.
120
120
  If no rules fire: log "No active rules for {domain-name}" and continue.
121
121
 
122
+ **Stack Rules Detection (before spawning subagent):**
123
+ Run via Bash to detect project stack and collect matching rules:
124
+ `GSD_T_DIR=$(npm root -g 2>/dev/null)/@tekyzinc/gsd-t; STACKS_DIR="$GSD_T_DIR/templates/stacks"; STACK_RULES=""; if [ -d "$STACKS_DIR" ]; then for f in "$STACKS_DIR"/_*.md; do [ -f "$f" ] && STACK_RULES="${STACK_RULES}$(cat "$f")"$'\n\n'; done; if [ -f "package.json" ]; then grep -q '"react-native"' package.json 2>/dev/null && [ -f "$STACKS_DIR/react-native.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/react-native.md")"$'\n\n'; grep -q '"react"' package.json 2>/dev/null && ! grep -q '"react-native"' package.json 2>/dev/null && [ -f "$STACKS_DIR/react.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/react.md")"$'\n\n'; grep -q '"next"' package.json 2>/dev/null && [ -f "$STACKS_DIR/nextjs.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/nextjs.md")"$'\n\n'; grep -q '"vue"' package.json 2>/dev/null && [ -f "$STACKS_DIR/vue.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/vue.md")"$'\n\n'; (grep -q '"typescript"' package.json 2>/dev/null || [ -f "tsconfig.json" ]) && [ -f "$STACKS_DIR/typescript.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/typescript.md")"$'\n\n'; grep -qE '"(express|fastify|hono|koa)"' package.json 2>/dev/null && [ -f "$STACKS_DIR/node-api.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/node-api.md")"$'\n\n'; grep -qE '"(express|fastify|hono|koa)"' package.json 2>/dev/null && [ -f "$STACKS_DIR/rest-api.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/rest-api.md")"$'\n\n'; grep -q '"tailwindcss"' package.json 2>/dev/null && [ -f "$STACKS_DIR/tailwind.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/tailwind.md")"$'\n\n'; grep -q '"vite"' package.json 2>/dev/null && [ -f "$STACKS_DIR/vite.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/vite.md")"$'\n\n'; grep -q '"@supabase/supabase-js"' package.json 2>/dev/null && [ -f "$STACKS_DIR/supabase.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/supabase.md")"$'\n\n'; grep -q '"firebase"' package.json 2>/dev/null && [ -f "$STACKS_DIR/firebase.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/firebase.md")"$'\n\n'; grep -qE '"(graphql|@apollo/client|urql)"' package.json 2>/dev/null && [ -f "$STACKS_DIR/graphql.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/graphql.md")"$'\n\n'; grep -q '"zustand"' package.json 2>/dev/null && [ -f "$STACKS_DIR/zustand.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/zustand.md")"$'\n\n'; grep -q '"@reduxjs/toolkit"' package.json 2>/dev/null && [ -f "$STACKS_DIR/redux.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/redux.md")"$'\n\n'; grep -q '"neo4j-driver"' package.json 2>/dev/null && [ -f "$STACKS_DIR/neo4j.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/neo4j.md")"$'\n\n'; grep -qE '"(pg|prisma|drizzle-orm|knex)"' package.json 2>/dev/null && [ -f "$STACKS_DIR/postgresql.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/postgresql.md")"$'\n\n'; fi; ([ -f "requirements.txt" ] || [ -f "pyproject.toml" ] || [ -f "Pipfile" ]) && [ -f "$STACKS_DIR/python.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/python.md")"$'\n\n'; ([ -f "requirements.txt" ] && grep -q "psycopg" requirements.txt 2>/dev/null || [ -f "pyproject.toml" ] && grep -q "psycopg" pyproject.toml 2>/dev/null) && [ -f "$STACKS_DIR/postgresql.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/postgresql.md")"$'\n\n'; ([ -f "requirements.txt" ] && grep -q "neo4j" requirements.txt 2>/dev/null) && [ -f "$STACKS_DIR/neo4j.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/neo4j.md")"$'\n\n'; [ -f "pubspec.yaml" ] && [ -f "$STACKS_DIR/flutter.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/flutter.md")"$'\n\n'; [ -f "Dockerfile" ] && [ -f "$STACKS_DIR/docker.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/docker.md")"$'\n\n'; [ -d ".github/workflows" ] && [ -f "$STACKS_DIR/github-actions.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/github-actions.md")"$'\n\n'; ([ -f "playwright.config.ts" ] || [ -f "playwright.config.js" ]) && [ -f "$STACKS_DIR/playwright.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/playwright.md")"$'\n\n'; [ -f "go.mod" ] && [ -f "$STACKS_DIR/go.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/go.md")"$'\n\n'; [ -f "Cargo.toml" ] && [ -f "$STACKS_DIR/rust.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/rust.md")"$'\n\n'; fi`
125
+
126
+ If STACK_RULES is non-empty, append to the subagent prompt:
127
+ ```
128
+ ## Stack Rules (MANDATORY — violations fail this task)
129
+
130
+ {STACK_RULES}
131
+
132
+ These standards have the same enforcement weight as contract compliance.
133
+ Violations are task failures, not warnings.
134
+ ```
135
+
136
+ If STACK_RULES is empty (no templates/stacks/ dir or no matches), skip silently.
137
+
122
138
  **Domain task-dispatcher (lightweight — sequences tasks, passes summaries):**
123
139
 
124
140
  For each task in `.gsd-t/domains/{domain-name}/tasks.md` (in order, skip completed):
@@ -150,6 +166,9 @@ Task subagent (general-purpose, model: sonnet, mode: bypassPermissions):
150
166
  ## Prior Task Summaries (most recent first, max 5)
151
167
  {contents of task-{N}-summary.md files — 10-20 lines each}
152
168
 
169
+ ## Stack Rules
170
+ {STACK_RULES if non-empty — omit entire section if empty}
171
+
153
172
  ## Instructions
154
173
 
155
174
  Execute the task above:
@@ -168,6 +187,26 @@ Execute the task above:
168
187
  - If the project has a UI but no Playwright E2E specs exist for the features being
169
188
  touched: WRITE THEM. A placeholder spec is not sufficient — write real E2E tests
170
189
  that exercise the actual UI functionality being built or changed.
190
+ - **FUNCTIONAL E2E TESTS — NOT LAYOUT TESTS (MANDATORY)**:
191
+ E2E tests that only check element existence (isVisible, isEnabled, toBeAttached)
192
+ are LAYOUT tests, not functional tests. Layout tests pass even when every feature
193
+ is broken. Every Playwright spec MUST verify functional behavior:
194
+ a. **State changes**: After an action (click, type, submit), assert the app STATE
195
+ changed — not just that the button was clickable. Example: clicking a tab must
196
+ load different content; verify the content changed, not just that the tab exists.
197
+ b. **Data flow**: Form submissions must verify data arrived (API call made, response
198
+ rendered, list updated). Don't just assert the form rendered.
199
+ c. **Navigation/routing**: Tab/page switches must verify the NEW content loaded.
200
+ Assert on content unique to the destination, not the navigation element itself.
201
+ d. **Interactive widgets**: Terminals must accept input and produce output. Editors
202
+ must save changes. Panels must load their functional content after opening.
203
+ e. **Network integration**: If a feature requires WebSocket/API connection, verify
204
+ the connection status changes (e.g., "Disconnected" → "Connected") and that
205
+ messages flow through the connection.
206
+ f. **Error recovery**: Don't just check error messages render — verify the app
207
+ recovers (retry button works, form can be resubmitted, etc.).
208
+ A test that would pass on an empty HTML page with the right element IDs is useless.
209
+ Every assertion must prove the FEATURE WORKS, not that the ELEMENT EXISTS.
171
210
  7. Run ALL test suites — this is NOT optional, not conditional, not "if applicable":
172
211
  a. Detect configured test runners: check for vitest/jest config, playwright.config.*, cypress.config.*
173
212
  b. Run EVERY detected suite. Unit tests alone are NEVER sufficient when E2E exists.
@@ -187,8 +226,15 @@ Execute the task above:
187
226
  b. E2E tests: check for playwright.config.* or cypress.config.* — if found, run the FULL E2E suite
188
227
  c. NEVER skip E2E when a config file exists. Running only unit tests is a QA FAILURE.
189
228
  d. Read .gsd-t/contracts/ for contract definitions. Check contract compliance.
190
- Report format: "Unit: X/Y pass | E2E: X/Y pass (or N/A if no config) | Contract: compliant/violations"'
191
- If QA fails, fix before proceeding. Append issues to .gsd-t/qa-issues.md.
229
+ e. AUDIT E2E test quality: Review each Playwright spec if any test only checks
230
+ element existence (isVisible, toBeAttached, toBeEnabled) without verifying functional
231
+ behavior (state changes, data loaded, content updated after actions), flag it as
232
+ "SHALLOW TEST — needs functional assertions" in the gap report. A test suite where
233
+ every spec passes but no feature actually works is a QA FAILURE.
234
+ Report format: "Unit: X/Y pass | E2E: X/Y pass (or N/A if no config) | Contract: compliant/violations | Shallow tests: N (list) | Stack rules: compliant/N violations"
235
+ f. Validate compliance with Stack Rules (if injected in the work subagent's prompt).
236
+ Stack rule violations have the same severity as contract violations — report as failures, not warnings.'
237
+ If QA fails OR shallow tests are found, fix before proceeding. Append issues to .gsd-t/qa-issues.md.
192
238
  12. Write task summary to .gsd-t/domains/{domain-name}/task-{task-id}-summary.md:
193
239
  ## Task {task-id} Summary — {domain-name}
194
240
  - **Status**: PASS | FAIL
@@ -198,8 +244,15 @@ Execute the task above:
198
244
  - **Notes**: {10-20 lines max — key decisions, patterns, warnings}
199
245
 
200
246
  Deviation rules:
201
- - Bug blocking progress → fix, max 3 attempts; if still blocked, log to
202
- .gsd-t/deferred-items.md and stop (report FAIL in summary)
247
+ - Bug blocking progress → fix, max 3 attempts; after fix attempt 2 fails:
248
+ 1. Write current failure context to .gsd-t/debug-state.jsonl via appendEntry
249
+ 2. Log: "Delegating to headless debug-loop (2 in-context attempts exhausted)"
250
+ 3. Run: `gsd-t headless --debug-loop --max-iterations 15`
251
+ 4. Check exit code:
252
+ - 0: Tests pass, continue with task
253
+ - 1/4: Log to .gsd-t/deferred-items.md and stop (report FAIL in summary)
254
+ - 3: Report error, stop
255
+ If still blocked after debug-loop, log to .gsd-t/deferred-items.md and stop (report FAIL in summary)
203
256
  - Missing dependency → add minimum needed, document in commit message
204
257
  - Non-trivial blocker → log to .gsd-t/deferred-items.md
205
258
  - Architectural change required → write NEEDS-APPROVAL to .gsd-t/deferred-items.md,
@@ -275,10 +328,11 @@ RULES FOR ALL TEAMMATES:
275
328
  - **Destructive Action Guard**: NEVER drop tables, remove columns, delete data, replace architecture patterns, or remove working modules without messaging the lead first. The lead must get user approval before any destructive action proceeds.
276
329
  - Only modify files listed in your domain's scope.md
277
330
  - Implement interfaces EXACTLY as specified in contracts
278
- - **Write comprehensive tests with every task** — no feature code without test code:
331
+ - **Write comprehensive FUNCTIONAL tests with every task** — no feature code without test code:
279
332
  - Unit/integration tests: happy path + edge cases + error cases for every new/changed function
280
333
  - Playwright E2E specs (if UI/routes/flows/modes changed): new specs for new features, cover all modes/flags, form validation, empty/loading/error states, common edge cases
281
334
  - Tests are part of the deliverable, not a follow-up
335
+ - **E2E tests MUST be functional, not layout tests**: Every assertion must verify an action produced the correct outcome (state changed, data loaded, content updated) — NOT just that an element is visible/clickable. A test that passes on an empty HTML shell with correct IDs is worthless. See the Functional E2E Test Requirements in the solo mode instructions above.
282
336
  - If a task is marked BLOCKED, message the lead and wait
283
337
  - Run the Pre-Commit Gate checklist from CLAUDE.md BEFORE every commit — update all affected docs
284
338
  - **Commit immediately after each task**: `feat({domain}/task-{N}): {description}` — do NOT batch commits
@@ -399,6 +453,29 @@ After all merges complete (whether all passed, some rolled back, or errors occur
399
453
  Cleanup is not optional — orphaned worktrees waste disk space and can confuse subsequent executions. Always run cleanup, even if earlier steps failed.
400
454
  ```
401
455
 
456
+ ## Step 3.5: Orchestrator Context Self-Check (MANDATORY)
457
+
458
+ After EVERY domain completes (and after every checkpoint), the orchestrator MUST check its own context utilization:
459
+
460
+ Run via Bash:
461
+ `if [ "${CLAUDE_CONTEXT_TOKENS_MAX:-0}" -gt 0 ]; then CTX_PCT=$(echo "scale=1; ${CLAUDE_CONTEXT_TOKENS_USED:-0} * 100 / ${CLAUDE_CONTEXT_TOKENS_MAX}" | bc); else CTX_PCT="N/A"; fi && echo "Orchestrator context: ${CTX_PCT}%"`
462
+
463
+ **If CTX_PCT >= 70:**
464
+ 1. **Save checkpoint to disk** — update `.gsd-t/progress.md` with:
465
+ - Which domains are complete, which remain
466
+ - Current wave, next domain to execute
467
+ - Any checkpoint results
468
+ 2. **Instruct user**: Output exactly:
469
+ ```
470
+ ⚠️ Orchestrator context at {CTX_PCT}% — approaching limit.
471
+ Progress saved. Run `/clear` then `/user:gsd-t-execute` to continue from the next domain.
472
+ ```
473
+ 3. **STOP execution.** Do NOT spawn another domain subagent. The next session will resume from saved state.
474
+
475
+ **If CTX_PCT < 70:** Continue normally to the next domain/wave.
476
+
477
+ This prevents the orchestrator from running out of context mid-milestone, which causes session breaks and summary-based recovery.
478
+
402
479
  ## Step 4: Checkpoint Handling
403
480
 
404
481
  When a checkpoint is reached (solo or team):
@@ -451,6 +528,26 @@ When all tasks in all domains are complete:
451
528
 
452
529
  **Level 1–2**: Report completion summary and recommend proceeding to integrate phase. Wait for confirmation.
453
530
 
531
+ ## Step 7: Doc-Ripple (Automated)
532
+
533
+ After all work is committed but before reporting completion:
534
+
535
+ 1. Run threshold check — read `git diff --name-only HEAD~1` and evaluate against doc-ripple-contract.md trigger conditions
536
+ 2. If SKIP: log "Doc-ripple: SKIP — {reason}" and proceed to completion
537
+ 3. If FIRE: spawn doc-ripple agent:
538
+
539
+ ⚙ [{model}] gsd-t-doc-ripple → blast radius analysis + parallel updates
540
+
541
+ Task subagent (general-purpose, model: sonnet):
542
+ "Execute the doc-ripple workflow per commands/gsd-t-doc-ripple.md.
543
+ Git diff context: {files changed list}
544
+ Command that triggered: execute
545
+ Produce manifest at .gsd-t/doc-ripple-manifest.md.
546
+ Update all affected documents.
547
+ Report: 'Doc-ripple: {N} checked, {N} updated, {N} skipped'"
548
+
549
+ 4. After doc-ripple returns, verify manifest exists and report summary inline
550
+
454
551
  ## Document Ripple
455
552
 
456
553
  Execute modifies source code, so the Pre-Commit Gate (referenced in Step 9) covers document updates. For clarity, the key documents affected by execution:
@@ -38,6 +38,7 @@ MILESTONE WORKFLOW [auto] = in wave
38
38
  execute [auto] Run tasks (solo or team mode)
39
39
  test-sync [auto] Sync tests with code changes
40
40
  qa [auto] QA agent — test generation, execution, gap reporting
41
+ doc-ripple [auto] Automated document ripple — update docs after code changes
41
42
  integrate [auto] Wire domains together at boundaries
42
43
  verify [auto] Run quality gates → auto-invokes complete-milestone
43
44
  complete-milestone [auto] Archive milestone + git tag (auto-invoked by verify)
@@ -64,6 +65,12 @@ UTILITIES Manual
64
65
  triage-and-merge Auto-review, merge, and publish GitHub branches
65
66
  global-change Apply file changes across all registered GSD-T projects
66
67
 
68
+ HEADLESS (CI/CD) CLI
69
+ ───────────────────────────────────────────────────────────────────────────────
70
+ headless exec Run any GSD-T command non-interactively via claude -p
71
+ headless query Read project state without LLM (<100ms)
72
+ headless --debug-loop Compaction-proof test-fix-retest loop (fresh sessions)
73
+
67
74
  BACKLOG Manual
68
75
  ───────────────────────────────────────────────────────────────────────────────
69
76
  backlog-add Capture item, auto-categorize, append to backlog
@@ -251,6 +258,7 @@ Use these when user asks for help on a specific command:
251
258
  - **Use when**: Ready to implement
252
259
  - **Note (M22)**: Task-level fresh dispatch (one subagent per task, ~10-20% context each). Team mode uses worktree isolation (`isolation: "worktree"`) — zero file conflicts. Adaptive replanning between domain completions.
253
260
  - **Note (M26)**: Active rule injection — evaluates declarative rules from rules.jsonl before dispatching each domain's tasks. Fires matching rules as warnings in subagent prompts.
261
+ - **Note (M29)**: Stack Rules Engine — auto-detects project tech stack from manifest files and injects mandatory best-practice rules into each task subagent prompt. Universal rules (`_security.md`) always apply; stack-specific rules layer on top. Violations are task failures (same weight as contract violations).
254
262
 
255
263
  ### test-sync
256
264
  - **Summary**: Keep tests aligned with code changes
@@ -264,6 +272,12 @@ Use these when user asks for help on a specific command:
264
272
  - **Creates**: Contract test skeletons, acceptance tests, edge case tests, test audit reports
265
273
  - **Use when**: Automatically spawned — never needs manual invocation. Standalone use for ad-hoc test audits.
266
274
 
275
+ ### doc-ripple
276
+ - **Summary**: Automated document ripple — identifies and updates all downstream docs after code changes
277
+ - **Auto-invoked**: Yes (after primary work in execute, integrate, quick, debug, wave)
278
+ - **Creates**: `.gsd-t/doc-ripple-manifest.md`
279
+ - **Use when**: Automatically spawned — never needs manual invocation. Standalone use for ad-hoc doc sync audits.
280
+
267
281
  ### integrate
268
282
  - **Summary**: Wire domains together at their boundaries
269
283
  - **Auto-invoked**: Yes (in wave, after execute)
@@ -332,11 +346,20 @@ Use these when user asks for help on a specific command:
332
346
  - **Use when**: Reviewing process health, first-pass rates, ELO trends, anomaly flags, or comparing signal distributions across projects
333
347
 
334
348
  ### debug
335
- - **Summary**: Systematic debugging with persistent state
349
+ - **Summary**: Systematic debugging with persistent state; delegates to `gsd-t headless --debug-loop` after 2 failed in-context fix attempts
336
350
  - **Auto-invoked**: No
337
- - **Creates**: Debug session state
351
+ - **Creates**: Debug session state, `.gsd-t/debug-state.jsonl` (when delegating to headless loop)
338
352
  - **Use when**: Tracking down a bug methodically
339
353
 
354
+ ### headless --debug-loop
355
+ - **Summary**: Compaction-proof automated test-fix-retest loop — each iteration is a fresh `claude -p` session; a cumulative ledger (`.gsd-t/debug-state.jsonl`) preserves all hypothesis/fix/learning history; anti-repetition preamble prevents retrying failed approaches
356
+ - **Auto-invoked**: Yes — by `execute`, `test-sync`, `verify`, `debug`, and `wave` after 2 failed in-context fix attempts
357
+ - **Flags**: `--max-iterations=N` (default 20), `--test-cmd=CMD`, `--fix-scope=PATTERN`, `--json`, `--log`
358
+ - **Escalation**: sonnet (iterations 1–5) → opus (6–15) → STOP with diagnostic summary (16–20)
359
+ - **Exit codes**: `0` pass · `1` max iterations · `2` compaction error · `3` process error · `4` needs human
360
+ - **Creates**: `.gsd-t/debug-state.jsonl`, optional `.gsd-t/headless-{ts}.log`
361
+ - **Use when**: Running automated fix loops in CI, or delegated from in-context commands that exhausted fix attempts
362
+
340
363
  ### promote-debt
341
364
  - **Summary**: Convert techdebt.md items into milestones
342
365
  - **Auto-invoked**: No
@@ -62,6 +62,22 @@ If rolled-back domains exist, report them to the user (or if Level 3: log to `.g
62
62
 
63
63
  ## Step 3: Wire Integration Points
64
64
 
65
+ **Stack Rules Detection (before spawning subagent):**
66
+ Run via Bash to detect project stack and collect matching rules:
67
+ `GSD_T_DIR=$(npm root -g 2>/dev/null)/@tekyzinc/gsd-t; STACKS_DIR="$GSD_T_DIR/templates/stacks"; STACK_RULES=""; if [ -d "$STACKS_DIR" ]; then for f in "$STACKS_DIR"/_*.md; do [ -f "$f" ] && STACK_RULES="${STACK_RULES}$(cat "$f")"$'\n\n'; done; if [ -f "package.json" ]; then grep -q '"react"' package.json 2>/dev/null && [ -f "$STACKS_DIR/react.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/react.md")"$'\n\n'; (grep -q '"typescript"' package.json 2>/dev/null || [ -f "tsconfig.json" ]) && [ -f "$STACKS_DIR/typescript.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/typescript.md")"$'\n\n'; grep -qE '"(express|fastify|hono|koa)"' package.json 2>/dev/null && [ -f "$STACKS_DIR/node-api.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/node-api.md")"$'\n\n'; fi; [ -f "requirements.txt" ] || [ -f "pyproject.toml" ] && [ -f "$STACKS_DIR/python.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/python.md")"$'\n\n'; [ -f "go.mod" ] && [ -f "$STACKS_DIR/go.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/go.md")"$'\n\n'; [ -f "Cargo.toml" ] && [ -f "$STACKS_DIR/rust.md" ] && STACK_RULES="${STACK_RULES}$(cat "$STACKS_DIR/rust.md")"$'\n\n'; fi`
68
+
69
+ If STACK_RULES is non-empty, append to the subagent prompt:
70
+ ```
71
+ ## Stack Rules (MANDATORY — violations fail this task)
72
+
73
+ {STACK_RULES}
74
+
75
+ These standards have the same enforcement weight as contract compliance.
76
+ Violations are task failures, not warnings.
77
+ ```
78
+
79
+ If STACK_RULES is empty (no templates/stacks/ dir or no matches), skip silently.
80
+
65
81
  Work through each integration point in `integration-points.md`. If integration work spans multiple domains with independent tasks, use the **task-level dispatch pattern** (per fresh-dispatch-contract.md): spawn one Task subagent per integration task, passing only the relevant contracts, the specific integration point to wire, and summaries from prior integration tasks (max 5, 10-20 lines each). This prevents context accumulation across integration tasks.
66
82
 
67
83
  **Multi-domain integration merging**: If integration work itself requires merging domain outputs that weren't merged during execute (e.g., domains executed in separate waves and integration needs to combine them), use the Sequential Merge Protocol from `.gsd-t/contracts/worktree-isolation-contract.md`:
@@ -126,7 +142,10 @@ Run ALL configured test suites — detect and run every one:
126
142
  a. Unit tests (vitest/jest/mocha): run the full suite
127
143
  b. E2E tests: check for playwright.config.* or cypress.config.* — if found, run the FULL E2E suite
128
144
  c. NEVER skip E2E when a config file exists. Running only unit tests is a QA FAILURE.
129
- Report: 'Unit: X/Y pass | E2E: X/Y pass (or N/A if no config) | Boundary: pass/fail by contract'"
145
+ d. AUDIT E2E test quality: Review each Playwright spec if any test only checks element existence
146
+ (isVisible, toBeAttached, toBeEnabled) without verifying functional behavior (state changes,
147
+ data loaded, content updated after actions), flag it as 'SHALLOW TEST — needs functional assertions'.
148
+ Report: 'Unit: X/Y pass | E2E: X/Y pass (or N/A if no config) | Boundary: pass/fail by contract | Shallow tests: N'"
130
149
  ```
131
150
 
132
151
  **OBSERVABILITY LOGGING (MANDATORY):**
@@ -176,8 +195,29 @@ After integration and doc ripple, verify everything works together:
176
195
  c. Unit tests alone are NEVER sufficient when E2E exists
177
196
  d. Report: "Unit: X/Y pass | E2E: X/Y pass"
178
197
  3. **Verify passing**: All tests must pass. If any fail, fix before proceeding (up to 2 attempts)
198
+ 4. **Functional test quality**: Spot-check E2E specs — every assertion must verify functional behavior (state changed, data loaded, content updated after action), not just element existence. Shallow tests that would pass on an empty HTML page are not acceptable.
179
199
  5. **Smoke test results**: Ensure the Step 4 smoke test results are still valid after any fixes
180
200
 
201
+ ## Step 7.5: Doc-Ripple (Automated)
202
+
203
+ After all integration work is committed but before reporting completion:
204
+
205
+ 1. Run threshold check — read `git diff --name-only HEAD~1` and evaluate against doc-ripple-contract.md trigger conditions
206
+ 2. If SKIP: log "Doc-ripple: SKIP — {reason}" and proceed to completion
207
+ 3. If FIRE: spawn doc-ripple agent:
208
+
209
+ ⚙ [{model}] gsd-t-doc-ripple → blast radius analysis + parallel updates
210
+
211
+ Task subagent (general-purpose, model: sonnet):
212
+ "Execute the doc-ripple workflow per commands/gsd-t-doc-ripple.md.
213
+ Git diff context: {files changed list}
214
+ Command that triggered: integrate
215
+ Produce manifest at .gsd-t/doc-ripple-manifest.md.
216
+ Update all affected documents.
217
+ Report: 'Doc-ripple: {N} checked, {N} updated, {N} skipped'"
218
+
219
+ 4. After doc-ripple returns, verify manifest exists and report summary inline
220
+
181
221
  ## Step 8: Handle Integration Issues
182
222
 
183
223
  For each issue found:
@@ -81,13 +81,16 @@ Your behavior depends on which phase spawned you:
81
81
 
82
82
  ### During Verify
83
83
  **Trigger**: Lead invokes verify phase
84
- **Action**: Full test audit
84
+ **Action**: Full test audit + shallow test detection
85
85
 
86
86
  1. Run ALL tests — contract tests, acceptance tests, edge case tests, existing project tests
87
87
  2. Coverage audit: For every contract, confirm tests exist and pass
88
88
  3. For every new feature/mode/flow, confirm Playwright specs cover happy path, error states, edge cases
89
- 4. Gap report: List any untested contracts or code paths
90
- 5. Report: `QA: {pass|fail} {N} contract tests, {N} acceptance tests, {N} edge case tests. Gaps: {list or "none"}`
89
+ 4. **Shallow test audit**: Read every Playwright spec file. For each `test()` block, check whether the assertions verify functional behavior (state changes, data flow, content updates after actions) or only check element existence (isVisible, toBeAttached, toBeEnabled). Flag any test that would pass on an empty HTML shell as `SHALLOW — needs functional assertions`.
90
+ 5. Gap report: List any untested contracts, code paths, AND shallow tests
91
+ 6. Report: `QA: {pass|fail} — {N} contract tests, {N} acceptance tests, {N} edge case tests. Gaps: {list or "none"}. Shallow E2E tests: {N} (list or "none")`
92
+
93
+ **Shallow tests block verification.** A passing E2E suite where tests don't actually verify feature behavior is equivalent to a failing suite.
91
94
 
92
95
  ### During Quick
93
96
  **Trigger**: Lead runs a quick task
@@ -189,10 +192,28 @@ For each table in `schema-contract.md`:
189
192
  For each component in `component-contract.md`:
190
193
  - Each `## ComponentName` → one `test.describe` block
191
194
  - `Props:` → renders with required props, handles missing optional props
192
- - `Events:` → event handlers fire correctly
193
- - API references → verify correct API calls made
195
+ - `Events:` → event handlers fire correctly AND produce the expected state change
196
+ - API references → verify correct API calls made AND responses rendered correctly
194
197
  - Auto-generate: empty form, partial form, network error handling
195
198
 
199
+ ### Functional E2E Test Standard (MANDATORY for all Playwright specs)
200
+
201
+ **E2E tests that only verify element existence are LAYOUT tests, not functional tests. Layout tests pass even when every feature is broken. This is a QA failure.**
202
+
203
+ Every Playwright spec MUST verify functional behavior — that actions produce the correct outcome:
204
+
205
+ | Test Pattern | WRONG (layout test) | RIGHT (functional test) |
206
+ |---|---|---|
207
+ | Tab switching | `expect(tab).toBeVisible()` | Click tab → assert NEW content loaded (text, data unique to that tab) |
208
+ | Form submit | `expect(submitBtn).toBeEnabled()` | Fill form → submit → assert success message AND data persisted (API call, list updated) |
209
+ | Terminal/editor | `expect(terminal).toBeAttached()` | Open terminal → type command → assert output appears |
210
+ | WebSocket | `expect(statusBadge).toBeVisible()` | Wait for connection → assert status text changes to "Connected" → send message → assert response |
211
+ | Navigation | `expect(link).toHaveAttribute('href')` | Click link → assert URL changed AND destination content rendered |
212
+ | Toggle/mode | `expect(toggle).toBeVisible()` | Click toggle → assert the EFFECT (dark mode CSS applied, panel expanded with content, feature enabled) |
213
+ | Error state | `expect(errorDiv).toBeVisible()` | Trigger error → assert message content → assert recovery action works |
214
+
215
+ **Rule: If a test would pass on an empty HTML shell with the right element IDs, it is not a functional test. Every assertion must prove the feature works, not that the element exists.**
216
+
196
217
  ## Test File Conventions
197
218
 
198
219
  - **Location**: Project's test directory (detected from `playwright.config.*` or `package.json`)