diff --git a/get-shit-done/references/verification-patterns.md b/get-shit-done/references/verification-patterns.md
new file mode 100644
index 000000000..fde7bdeca
--- /dev/null
+++ b/get-shit-done/references/verification-patterns.md
@@ -0,0 +1,595 @@
+# Verification Patterns
+
+How to verify different types of artifacts are real implementations, not stubs or placeholders.
+
+
+**Existence ≠ Implementation**
+
+A file existing does not mean the feature works. Verification must check:
+1. **Exists** - File is present at expected path
+2. **Substantive** - Content is real implementation, not placeholder
+3. **Wired** - Connected to the rest of the system
+4. **Functional** - Actually works when invoked
+
+Levels 1-3 can be checked programmatically. Level 4 often requires human verification.
+
+
+
+
+## Universal Stub Patterns
+
+These patterns indicate placeholder code regardless of file type:
+
+**Comment-based stubs:**
+```bash
+# Grep patterns for stub comments
+grep -E "(TODO|FIXME|XXX|HACK|PLACEHOLDER)" "$file"
+grep -E "implement|add later|coming soon|will be" "$file" -i
+grep -E "// \.\.\.|/\* \.\.\. \*/|# \.\.\." "$file"
+```
+
+**Placeholder text in output:**
+```bash
+# UI placeholder patterns
+grep -E "placeholder|lorem ipsum|coming soon|under construction" "$file" -i
+grep -E "sample|example|test data|dummy" "$file" -i
+grep -E "\[.*\]|<.*>|\{.*\}" "$file" # Template brackets left in
+```
+
+**Empty or trivial implementations:**
+```bash
+# Functions that do nothing
+grep -E "return null|return undefined|return \{\}|return \[\]" "$file"
+grep -E "pass$|\.\.\.|\bnothing\b" "$file"
+grep -E "console\.(log|warn|error).*only" "$file" # Log-only functions
+```
+
+**Hardcoded values where dynamic expected:**
+```bash
+# Hardcoded IDs, counts, or content
+grep -E "id.*=.*['\"].*['\"]" "$file" # Hardcoded string IDs
+grep -E "count.*=.*\d+|length.*=.*\d+" "$file" # Hardcoded counts
+grep -E "\\\$\d+\.\d{2}|\d+ items" "$file" # Hardcoded display values
+```
+
+
+
+
+
+## React/Next.js Components
+
+**Existence check:**
+```bash
+# File exists and exports component
+[ -f "$component_path" ] && grep -E "export (default |)function|export const.*=.*\(" "$component_path"
+```
+
+**Substantive check:**
+```bash
+# Returns actual JSX, not placeholder
+grep -E "return.*<" "$component_path" | grep -v "return.*null" | grep -v "placeholder" -i
+
+# Has meaningful content (not just wrapper div)
+grep -E "<[A-Z][a-zA-Z]+|className=|onClick=|onChange=" "$component_path"
+
+# Uses props or state (not static)
+grep -E "props\.|useState|useEffect|useContext|\{.*\}" "$component_path"
+```
+
+**Stub patterns specific to React:**
+```javascript
+// RED FLAGS - These are stubs:
+return Component
+return Placeholder
+return {/* TODO */}
+return Coming soon
+return null
+return <>>
+
+// Also stubs - empty handlers:
+onClick={() => {}}
+onChange={() => console.log('clicked')}
+onSubmit={(e) => e.preventDefault()} // Only prevents default, does nothing
+```
+
+**Wiring check:**
+```bash
+# Component imports what it needs
+grep -E "^import.*from" "$component_path"
+
+# Props are actually used (not just received)
+# Look for destructuring or props.X usage
+grep -E "\{ .* \}.*props|\bprops\.[a-zA-Z]+" "$component_path"
+
+# API calls exist (for data-fetching components)
+grep -E "fetch\(|axios\.|useSWR|useQuery|getServerSideProps|getStaticProps" "$component_path"
+```
+
+**Functional verification (human required):**
+- Does the component render visible content?
+- Do interactive elements respond to clicks?
+- Does data load and display?
+- Do error states show appropriately?
+
+
+
+
+
+## API Routes (Next.js App Router / Express / etc.)
+
+**Existence check:**
+```bash
+# Route file exists
+[ -f "$route_path" ]
+
+# Exports HTTP method handlers (Next.js App Router)
+grep -E "export (async )?(function|const) (GET|POST|PUT|PATCH|DELETE)" "$route_path"
+
+# Or Express-style handlers
+grep -E "\.(get|post|put|patch|delete)\(" "$route_path"
+```
+
+**Substantive check:**
+```bash
+# Has actual logic, not just return statement
+wc -l "$route_path" # More than 10-15 lines suggests real implementation
+
+# Interacts with data source
+grep -E "prisma\.|db\.|mongoose\.|sql|query|find|create|update|delete" "$route_path" -i
+
+# Has error handling
+grep -E "try|catch|throw|error|Error" "$route_path"
+
+# Returns meaningful response
+grep -E "Response\.json|res\.json|res\.send|return.*\{" "$route_path" | grep -v "message.*not implemented" -i
+```
+
+**Stub patterns specific to API routes:**
+```typescript
+// RED FLAGS - These are stubs:
+export async function POST() {
+ return Response.json({ message: "Not implemented" })
+}
+
+export async function GET() {
+ return Response.json([]) // Empty array with no DB query
+}
+
+export async function PUT() {
+ return new Response() // Empty response
+}
+
+// Console log only:
+export async function POST(req) {
+ console.log(await req.json())
+ return Response.json({ ok: true })
+}
+```
+
+**Wiring check:**
+```bash
+# Imports database/service clients
+grep -E "^import.*prisma|^import.*db|^import.*client" "$route_path"
+
+# Actually uses request body (for POST/PUT)
+grep -E "req\.json\(\)|req\.body|request\.json\(\)" "$route_path"
+
+# Validates input (not just trusting request)
+grep -E "schema\.parse|validate|zod|yup|joi" "$route_path"
+```
+
+**Functional verification (human or automated):**
+- Does GET return real data from database?
+- Does POST actually create a record?
+- Does error response have correct status code?
+- Are auth checks actually enforced?
+
+
+
+
+
+## Database Schema (Prisma / Drizzle / SQL)
+
+**Existence check:**
+```bash
+# Schema file exists
+[ -f "prisma/schema.prisma" ] || [ -f "drizzle/schema.ts" ] || [ -f "src/db/schema.sql" ]
+
+# Model/table is defined
+grep -E "^model $model_name|CREATE TABLE $table_name|export const $table_name" "$schema_path"
+```
+
+**Substantive check:**
+```bash
+# Has expected fields (not just id)
+grep -A 20 "model $model_name" "$schema_path" | grep -E "^\s+\w+\s+\w+"
+
+# Has relationships if expected
+grep -E "@relation|REFERENCES|FOREIGN KEY" "$schema_path"
+
+# Has appropriate field types (not all String)
+grep -A 20 "model $model_name" "$schema_path" | grep -E "Int|DateTime|Boolean|Float|Decimal|Json"
+```
+
+**Stub patterns specific to schemas:**
+```prisma
+// RED FLAGS - These are stubs:
+model User {
+ id String @id
+ // TODO: add fields
+}
+
+model Message {
+ id String @id
+ content String // Only one real field
+}
+
+// Missing critical fields:
+model Order {
+ id String @id
+ // No: userId, items, total, status, createdAt
+}
+```
+
+**Wiring check:**
+```bash
+# Migrations exist and are applied
+ls prisma/migrations/ 2>/dev/null | wc -l # Should be > 0
+npx prisma migrate status 2>/dev/null | grep -v "pending"
+
+# Client is generated
+[ -d "node_modules/.prisma/client" ]
+```
+
+**Functional verification:**
+```bash
+# Can query the table (automated)
+npx prisma db execute --stdin <<< "SELECT COUNT(*) FROM $table_name"
+```
+
+
+
+
+
+## Custom Hooks and Utilities
+
+**Existence check:**
+```bash
+# File exists and exports function
+[ -f "$hook_path" ] && grep -E "export (default )?(function|const)" "$hook_path"
+```
+
+**Substantive check:**
+```bash
+# Hook uses React hooks (for custom hooks)
+grep -E "useState|useEffect|useCallback|useMemo|useRef|useContext" "$hook_path"
+
+# Has meaningful return value
+grep -E "return \{|return \[" "$hook_path"
+
+# More than trivial length
+[ $(wc -l < "$hook_path") -gt 10 ]
+```
+
+**Stub patterns specific to hooks:**
+```typescript
+// RED FLAGS - These are stubs:
+export function useAuth() {
+ return { user: null, login: () => {}, logout: () => {} }
+}
+
+export function useCart() {
+ const [items, setItems] = useState([])
+ return { items, addItem: () => console.log('add'), removeItem: () => {} }
+}
+
+// Hardcoded return:
+export function useUser() {
+ return { name: "Test User", email: "test@example.com" }
+}
+```
+
+**Wiring check:**
+```bash
+# Hook is actually imported somewhere
+grep -r "import.*$hook_name" src/ --include="*.tsx" --include="*.ts" | grep -v "$hook_path"
+
+# Hook is actually called
+grep -r "$hook_name()" src/ --include="*.tsx" --include="*.ts" | grep -v "$hook_path"
+```
+
+
+
+
+
+## Environment Variables and Configuration
+
+**Existence check:**
+```bash
+# .env file exists
+[ -f ".env" ] || [ -f ".env.local" ]
+
+# Required variable is defined
+grep -E "^$VAR_NAME=" .env .env.local 2>/dev/null
+```
+
+**Substantive check:**
+```bash
+# Variable has actual value (not placeholder)
+grep -E "^$VAR_NAME=.+" .env .env.local 2>/dev/null | grep -v "your-.*-here|xxx|placeholder|TODO" -i
+
+# Value looks valid for type:
+# - URLs should start with http
+# - Keys should be long enough
+# - Booleans should be true/false
+```
+
+**Stub patterns specific to env:**
+```bash
+# RED FLAGS - These are stubs:
+DATABASE_URL=your-database-url-here
+STRIPE_SECRET_KEY=sk_test_xxx
+API_KEY=placeholder
+NEXT_PUBLIC_API_URL=http://localhost:3000 # Still pointing to localhost in prod
+```
+
+**Wiring check:**
+```bash
+# Variable is actually used in code
+grep -r "process\.env\.$VAR_NAME|env\.$VAR_NAME" src/ --include="*.ts" --include="*.tsx"
+
+# Variable is in validation schema (if using zod/etc for env)
+grep -E "$VAR_NAME" src/env.ts src/env.mjs 2>/dev/null
+```
+
+
+
+
+
+## Wiring Verification Patterns
+
+Wiring verification checks that components actually communicate. This is where most stubs hide.
+
+### Pattern: Component → API
+
+**Check:** Does the component actually call the API?
+
+```bash
+# Find the fetch/axios call
+grep -E "fetch\(['\"].*$api_path|axios\.(get|post).*$api_path" "$component_path"
+
+# Verify it's not commented out
+grep -E "fetch\(|axios\." "$component_path" | grep -v "^.*//.*fetch"
+
+# Check the response is used
+grep -E "await.*fetch|\.then\(|setData|setState" "$component_path"
+```
+
+**Red flags:**
+```typescript
+// Fetch exists but response ignored:
+fetch('/api/messages') // No await, no .then, no assignment
+
+// Fetch in comment:
+// fetch('/api/messages').then(r => r.json()).then(setMessages)
+
+// Fetch to wrong endpoint:
+fetch('/api/message') // Typo - should be /api/messages
+```
+
+### Pattern: API → Database
+
+**Check:** Does the API route actually query the database?
+
+```bash
+# Find the database call
+grep -E "prisma\.$model|db\.query|Model\.find" "$route_path"
+
+# Verify it's awaited
+grep -E "await.*prisma|await.*db\." "$route_path"
+
+# Check result is returned
+grep -E "return.*json.*data|res\.json.*result" "$route_path"
+```
+
+**Red flags:**
+```typescript
+// Query exists but result not returned:
+await prisma.message.findMany()
+return Response.json({ ok: true }) // Returns static, not query result
+
+// Query not awaited:
+const messages = prisma.message.findMany() // Missing await
+return Response.json(messages) // Returns Promise, not data
+```
+
+### Pattern: Form → Handler
+
+**Check:** Does the form submission actually do something?
+
+```bash
+# Find onSubmit handler
+grep -E "onSubmit=\{|handleSubmit" "$component_path"
+
+# Check handler has content
+grep -A 10 "onSubmit.*=" "$component_path" | grep -E "fetch|axios|mutate|dispatch"
+
+# Verify not just preventDefault
+grep -A 5 "onSubmit" "$component_path" | grep -v "only.*preventDefault" -i
+```
+
+**Red flags:**
+```typescript
+// Handler only prevents default:
+onSubmit={(e) => e.preventDefault()}
+
+// Handler only logs:
+const handleSubmit = (data) => {
+ console.log(data)
+}
+
+// Handler is empty:
+onSubmit={() => {}}
+```
+
+### Pattern: State → Render
+
+**Check:** Does the component render state, not hardcoded content?
+
+```bash
+# Find state usage in JSX
+grep -E "\{.*messages.*\}|\{.*data.*\}|\{.*items.*\}" "$component_path"
+
+# Check map/render of state
+grep -E "\.map\(|\.filter\(|\.reduce\(" "$component_path"
+
+# Verify dynamic content
+grep -E "\{[a-zA-Z_]+\." "$component_path" # Variable interpolation
+```
+
+**Red flags:**
+```tsx
+// Hardcoded instead of state:
+return
+
Message 1
+
Message 2
+
+
+// State exists but not rendered:
+const [messages, setMessages] = useState([])
+return No messages
// Always shows "no messages"
+
+// Wrong state rendered:
+const [messages, setMessages] = useState([])
+return {otherData.map(...)}
// Uses different data
+```
+
+
+
+
+
+## Quick Verification Checklist
+
+For each artifact type, run through this checklist:
+
+### Component Checklist
+- [ ] File exists at expected path
+- [ ] Exports a function/const component
+- [ ] Returns JSX (not null/empty)
+- [ ] No placeholder text in render
+- [ ] Uses props or state (not static)
+- [ ] Event handlers have real implementations
+- [ ] Imports resolve correctly
+- [ ] Used somewhere in the app
+
+### API Route Checklist
+- [ ] File exists at expected path
+- [ ] Exports HTTP method handlers
+- [ ] Handlers have more than 5 lines
+- [ ] Queries database or service
+- [ ] Returns meaningful response (not empty/placeholder)
+- [ ] Has error handling
+- [ ] Validates input
+- [ ] Called from frontend
+
+### Schema Checklist
+- [ ] Model/table defined
+- [ ] Has all expected fields
+- [ ] Fields have appropriate types
+- [ ] Relationships defined if needed
+- [ ] Migrations exist and applied
+- [ ] Client generated
+
+### Hook/Utility Checklist
+- [ ] File exists at expected path
+- [ ] Exports function
+- [ ] Has meaningful implementation (not empty returns)
+- [ ] Used somewhere in the app
+- [ ] Return values consumed
+
+### Wiring Checklist
+- [ ] Component → API: fetch/axios call exists and uses response
+- [ ] API → Database: query exists and result returned
+- [ ] Form → Handler: onSubmit calls API/mutation
+- [ ] State → Render: state variables appear in JSX
+
+
+
+
+
+## Automated Verification Approach
+
+For the verification subagent, use this pattern:
+
+```bash
+# 1. Check existence
+check_exists() {
+ [ -f "$1" ] && echo "EXISTS: $1" || echo "MISSING: $1"
+}
+
+# 2. Check for stub patterns
+check_stubs() {
+ local file="$1"
+ local stubs=$(grep -c -E "TODO|FIXME|placeholder|not implemented" "$file" 2>/dev/null || echo 0)
+ [ "$stubs" -gt 0 ] && echo "STUB_PATTERNS: $stubs in $file"
+}
+
+# 3. Check wiring (component calls API)
+check_wiring() {
+ local component="$1"
+ local api_path="$2"
+ grep -q "$api_path" "$component" && echo "WIRED: $component → $api_path" || echo "NOT_WIRED: $component → $api_path"
+}
+
+# 4. Check substantive (more than N lines, has expected patterns)
+check_substantive() {
+ local file="$1"
+ local min_lines="$2"
+ local pattern="$3"
+ local lines=$(wc -l < "$file" 2>/dev/null || echo 0)
+ local has_pattern=$(grep -c -E "$pattern" "$file" 2>/dev/null || echo 0)
+ [ "$lines" -ge "$min_lines" ] && [ "$has_pattern" -gt 0 ] && echo "SUBSTANTIVE: $file" || echo "THIN: $file ($lines lines, $has_pattern matches)"
+}
+```
+
+Run these checks against each must-have artifact. Aggregate results into VERIFICATION.md.
+
+
+
+
+
+## When to Require Human Verification
+
+Some things can't be verified programmatically. Flag these for human testing:
+
+**Always human:**
+- Visual appearance (does it look right?)
+- User flow completion (can you actually do the thing?)
+- Real-time behavior (WebSocket, SSE)
+- External service integration (Stripe, email sending)
+- Error message clarity (is the message helpful?)
+- Performance feel (does it feel fast?)
+
+**Human if uncertain:**
+- Complex wiring that grep can't trace
+- Dynamic behavior depending on state
+- Edge cases and error states
+- Mobile responsiveness
+- Accessibility
+
+**Format for human verification request:**
+```markdown
+## Human Verification Required
+
+### 1. Chat message sending
+**Test:** Type a message and click Send
+**Expected:** Message appears in list, input clears
+**Check:** Does message persist after refresh?
+
+### 2. Error handling
+**Test:** Disconnect network, try to send
+**Expected:** Error message appears, message not lost
+**Check:** Can retry after reconnect?
+```
+
+
diff --git a/get-shit-done/templates/subagent-verify-prompt.md b/get-shit-done/templates/subagent-verify-prompt.md
new file mode 100644
index 000000000..a0b123b8a
--- /dev/null
+++ b/get-shit-done/templates/subagent-verify-prompt.md
@@ -0,0 +1,216 @@
+# Subagent Verify Prompt Template
+
+Template for spawning a verification subagent from execute-phase.md.
+
+---
+
+## Template
+
+```markdown
+
+Verify Phase {phase_number} achieved its GOAL, not just completed its TASKS.
+
+Your job: Goal-backward verification. Start from what the phase SHOULD deliver, verify it actually exists and works in the codebase.
+
+**Critical mindset:** Do NOT trust SUMMARY.md claims. SUMMARYs document what Claude SAID it did. You verify what ACTUALLY exists in the code. These often differ.
+
+
+
+@~/.claude/get-shit-done/workflows/verify-phase.md
+@~/.claude/get-shit-done/templates/verification-report.md
+@~/.claude/get-shit-done/references/verification-patterns.md
+@~/.claude/get-shit-done/references/goal-backward.md
+
+
+
+**Phase being verified:**
+- Phase: {phase_number} - {phase_name}
+- Phase goal: {phase_goal_from_roadmap}
+- Phase directory: .planning/phases/{phase_dir}/
+
+**Must-haves to verify:**
+{must_haves_yaml_from_plan_frontmatter}
+
+**If must_haves not in frontmatter, derive from:**
+- Phase goal (above)
+- @.planning/ROADMAP.md (phase description)
+- @.planning/REQUIREMENTS.md (requirements mapped to this phase)
+
+**Context for verification:**
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/REQUIREMENTS.md (if exists)
+@.planning/phases/{phase_dir}/*-SUMMARY.md (claims to verify against)
+
+
+
+
+## Step 1: Establish Must-Haves
+
+**If must_haves provided in context above:** Use them directly.
+
+**If must_haves NOT provided:** Derive using goal-backward process:
+1. State the phase goal
+2. Ask: "What must be TRUE for this goal to be achieved?" (3-7 observable truths)
+3. For each truth: "What must EXIST?" (concrete artifacts)
+4. For each artifact: "What must be WIRED?" (connections between artifacts)
+5. Identify key links (critical connections most likely to be stubs)
+
+Document your derived must-haves before proceeding.
+
+## Step 2: Verify Observable Truths
+
+For each truth, determine if it's achievable given the codebase state.
+
+A truth is:
+- ✓ VERIFIED: Codebase makes this truth achievable
+- ✗ FAILED: Codebase prevents this truth (missing/stub code)
+- ? UNCERTAIN: Can't verify programmatically (needs human)
+
+## Step 3: Verify Required Artifacts
+
+For each artifact, check three levels:
+
+**Level 1 - Exists:**
+```bash
+[ -f "{artifact_path}" ] && echo "EXISTS" || echo "MISSING"
+```
+
+**Level 2 - Substantive:**
+- Is it more than a stub? (check line count, grep for stub patterns)
+- Does it have expected exports/structure?
+- Are there TODO/placeholder comments?
+
+Use patterns from verification-patterns.md.
+
+**Level 3 - Wired:**
+- Is it imported somewhere?
+- Is it called/used?
+- Does data flow through it?
+
+## Step 4: Verify Key Links
+
+Key links are the critical connections. For each:
+
+```bash
+# Check if A calls B
+grep -E "{pattern_for_call}" "{file_A}"
+
+# Check if the call uses the response
+grep -A 5 "{call_pattern}" "{file_A}" | grep -E "await|then|set"
+```
+
+Key links are where stubs hide. A component might exist and an API might exist, but the component doesn't actually call the API.
+
+## Step 5: Check Requirements Coverage
+
+If REQUIREMENTS.md exists and has requirements mapped to this phase:
+- For each requirement, determine if the codebase satisfies it
+- A requirement is BLOCKED if any supporting artifact is missing/stub
+
+## Step 6: Scan for Anti-Patterns
+
+Run stub detection across all phase-related files:
+
+```bash
+# Find all files modified in this phase (from SUMMARYs)
+# Then scan for anti-patterns
+
+grep -r -E "TODO|FIXME|placeholder|not implemented" {phase_files} -i
+grep -r -E "return null|return \{\}|return \[\]" {phase_files}
+grep -r -E "console\.log\(.*\)" {phase_files} | grep -v "error\|warn"
+```
+
+## Step 7: Generate Report
+
+Create `.planning/phases/{phase_dir}/{phase}-VERIFICATION.md` using the verification-report.md template.
+
+Include:
+- All truths with status and evidence
+- All artifacts with status and details
+- All key links with status and details
+- Requirements coverage
+- Anti-patterns found
+- Human verification needs
+- Gap summary with fix recommendations
+
+
+
+
+
+**DO NOT trust SUMMARY claims.** SUMMARYs say "implemented chat component" — you verify the component actually renders messages, not a placeholder.
+
+**DO NOT assume existence = implementation.** A file existing is level 1. You need level 2 (substantive) and level 3 (wired) verification.
+
+**DO NOT skip key link verification.** This is where 80% of stubs hide. The pieces exist but aren't connected.
+
+**DO generate fix plans if gaps found.** Don't just report "this is broken" — recommend specific fix plans with tasks.
+
+**DO flag for human verification when uncertain.** If you can't verify programmatically (visual, real-time, external service), say so explicitly.
+
+**DO keep verification fast.** Use grep/file checks, not running the app. Goal is structural verification, not functional testing.
+
+
+
+
+
+
+- [ ] Must-haves established (from frontmatter or derived)
+- [ ] All truths verified with evidence
+- [ ] All artifacts checked (exists + substantive + wired)
+- [ ] All key links traced
+- [ ] Requirements coverage assessed
+- [ ] Anti-patterns scanned
+- [ ] VERIFICATION.md created with full report
+- [ ] Fix plans recommended if gaps found
+- [ ] Human verification items listed if uncertain
+
+```
+
+---
+
+## Usage
+
+The execute-phase orchestrator fills this template and spawns a subagent:
+
+```typescript
+Task(
+ prompt: filled_template,
+ subagent_type: "general-purpose",
+ description: "Verify phase {X} goal achievement"
+)
+```
+
+The subagent:
+1. Loads the verification workflow and references
+2. Establishes must-haves (from frontmatter or derived)
+3. Runs verification checks against codebase
+4. Creates VERIFICATION.md report
+5. Returns status to orchestrator
+
+The orchestrator then:
+- If `passed`: Proceeds to update_roadmap
+- If `gaps_found`: Creates fix plans, executes them, re-verifies
+- If `human_needed`: Presents human verification items to user
+
+---
+
+## Template Variables
+
+| Variable | Source | Example |
+|----------|--------|---------|
+| `{phase_number}` | From execute-phase | `03` |
+| `{phase_name}` | From ROADMAP.md | `chat-interface` |
+| `{phase_goal_from_roadmap}` | From ROADMAP.md phase description | `Working chat interface where users can send and receive messages` |
+| `{phase_dir}` | From filesystem | `03-chat-interface` |
+| `{must_haves_yaml_from_plan_frontmatter}` | From PLAN.md frontmatter | YAML block with truths, artifacts, key_links |
diff --git a/get-shit-done/templates/verification-report.md b/get-shit-done/templates/verification-report.md
new file mode 100644
index 000000000..ec57cbd40
--- /dev/null
+++ b/get-shit-done/templates/verification-report.md
@@ -0,0 +1,322 @@
+# Verification Report Template
+
+Template for `.planning/phases/XX-name/{phase}-VERIFICATION.md` — phase goal verification results.
+
+---
+
+## File Template
+
+```markdown
+---
+phase: XX-name
+verified: YYYY-MM-DDTHH:MM:SSZ
+status: passed | gaps_found | human_needed
+score: N/M must-haves verified
+---
+
+# Phase {X}: {Name} Verification Report
+
+**Phase Goal:** {goal from ROADMAP.md}
+**Verified:** {timestamp}
+**Status:** {passed | gaps_found | human_needed}
+
+## Goal Achievement
+
+### Observable Truths
+
+| # | Truth | Status | Evidence |
+|---|-------|--------|----------|
+| 1 | {truth from must_haves} | ✓ VERIFIED | {what confirmed it} |
+| 2 | {truth from must_haves} | ✗ FAILED | {what's wrong} |
+| 3 | {truth from must_haves} | ? UNCERTAIN | {why can't verify} |
+
+**Score:** {N}/{M} truths verified
+
+### Required Artifacts
+
+| Artifact | Expected | Status | Details |
+|----------|----------|--------|---------|
+| `src/components/Chat.tsx` | Message list component | ✓ EXISTS + SUBSTANTIVE | Exports ChatList, renders Message[], no stubs |
+| `src/app/api/chat/route.ts` | Message CRUD | ✗ STUB | File exists but POST returns placeholder |
+| `prisma/schema.prisma` | Message model | ✓ EXISTS + SUBSTANTIVE | Model defined with all fields |
+
+**Artifacts:** {N}/{M} verified
+
+### Key Link Verification
+
+| From | To | Via | Status | Details |
+|------|----|----|--------|---------|
+| Chat.tsx | /api/chat | fetch in useEffect | ✓ WIRED | Line 23: `fetch('/api/chat')` with response handling |
+| ChatInput | /api/chat POST | onSubmit handler | ✗ NOT WIRED | onSubmit only calls console.log |
+| /api/chat POST | database | prisma.message.create | ✗ NOT WIRED | Returns hardcoded response, no DB call |
+
+**Wiring:** {N}/{M} connections verified
+
+## Requirements Coverage
+
+| Requirement | Status | Blocking Issue |
+|-------------|--------|----------------|
+| {REQ-01}: {description} | ✓ SATISFIED | - |
+| {REQ-02}: {description} | ✗ BLOCKED | API route is stub |
+| {REQ-03}: {description} | ? NEEDS HUMAN | Can't verify WebSocket programmatically |
+
+**Coverage:** {N}/{M} requirements satisfied
+
+## Anti-Patterns Found
+
+| File | Line | Pattern | Severity | Impact |
+|------|------|---------|----------|--------|
+| src/app/api/chat/route.ts | 12 | `// TODO: implement` | ⚠️ Warning | Indicates incomplete |
+| src/components/Chat.tsx | 45 | `return
Placeholder
` | 🛑 Blocker | Renders no content |
+| src/hooks/useChat.ts | - | File missing | 🛑 Blocker | Expected hook doesn't exist |
+
+**Anti-patterns:** {N} found ({blockers} blockers, {warnings} warnings)
+
+## Human Verification Required
+
+{If no human verification needed:}
+None — all verifiable items checked programmatically.
+
+{If human verification needed:}
+
+### 1. {Test Name}
+**Test:** {What to do}
+**Expected:** {What should happen}
+**Why human:** {Why can't verify programmatically}
+
+### 2. {Test Name}
+**Test:** {What to do}
+**Expected:** {What should happen}
+**Why human:** {Why can't verify programmatically}
+
+## Gaps Summary
+
+{If no gaps:}
+**No gaps found.** Phase goal achieved. Ready to proceed.
+
+{If gaps found:}
+
+### Critical Gaps (Block Progress)
+
+1. **{Gap name}**
+ - Missing: {what's missing}
+ - Impact: {why this blocks the goal}
+ - Fix: {what needs to happen}
+
+2. **{Gap name}**
+ - Missing: {what's missing}
+ - Impact: {why this blocks the goal}
+ - Fix: {what needs to happen}
+
+### Non-Critical Gaps (Can Defer)
+
+1. **{Gap name}**
+ - Issue: {what's wrong}
+ - Impact: {limited impact because...}
+ - Recommendation: {fix now or defer}
+
+## Recommended Fix Plans
+
+{If gaps found, generate fix plan recommendations:}
+
+### {phase}-{next}-PLAN.md: {Fix Name}
+
+**Objective:** {What this fixes}
+
+**Tasks:**
+1. {Task to fix gap 1}
+2. {Task to fix gap 2}
+3. {Verification task}
+
+**Estimated scope:** {Small / Medium}
+
+---
+
+### {phase}-{next+1}-PLAN.md: {Fix Name}
+
+**Objective:** {What this fixes}
+
+**Tasks:**
+1. {Task}
+2. {Task}
+
+**Estimated scope:** {Small / Medium}
+
+---
+
+## Verification Metadata
+
+**Verification approach:** Goal-backward (derived from phase goal)
+**Must-haves source:** {PLAN.md frontmatter | derived from ROADMAP.md goal}
+**Automated checks:** {N} passed, {M} failed
+**Human checks required:** {N}
+**Total verification time:** {duration}
+
+---
+*Verified: {timestamp}*
+*Verifier: Claude (subagent)*
+```
+
+---
+
+## Guidelines
+
+**Status values:**
+- `passed` — All must-haves verified, no blockers
+- `gaps_found` — One or more critical gaps found
+- `human_needed` — Automated checks pass but human verification required
+
+**Evidence types:**
+- For EXISTS: "File at path, exports X"
+- For SUBSTANTIVE: "N lines, has patterns X, Y, Z"
+- For WIRED: "Line N: code that connects A to B"
+- For FAILED: "Missing because X" or "Stub because Y"
+
+**Severity levels:**
+- 🛑 Blocker: Prevents goal achievement, must fix
+- ⚠️ Warning: Indicates incomplete but doesn't block
+- ℹ️ Info: Notable but not problematic
+
+**Fix plan generation:**
+- Only generate if gaps_found
+- Group related fixes into single plans
+- Keep to 2-3 tasks per plan
+- Include verification task in each plan
+
+---
+
+## Example
+
+```markdown
+---
+phase: 03-chat
+verified: 2025-01-15T14:30:00Z
+status: gaps_found
+score: 2/5 must-haves verified
+---
+
+# Phase 3: Chat Interface Verification Report
+
+**Phase Goal:** Working chat interface where users can send and receive messages
+**Verified:** 2025-01-15T14:30:00Z
+**Status:** gaps_found
+
+## Goal Achievement
+
+### Observable Truths
+
+| # | Truth | Status | Evidence |
+|---|-------|--------|----------|
+| 1 | User can see existing messages | ✗ FAILED | Component renders placeholder, not message data |
+| 2 | User can type a message | ✓ VERIFIED | Input field exists with onChange handler |
+| 3 | User can send a message | ✗ FAILED | onSubmit handler is console.log only |
+| 4 | Sent message appears in list | ✗ FAILED | No state update after send |
+| 5 | Messages persist across refresh | ? UNCERTAIN | Can't verify - send doesn't work |
+
+**Score:** 1/5 truths verified
+
+### Required Artifacts
+
+| Artifact | Expected | Status | Details |
+|----------|----------|--------|---------|
+| `src/components/Chat.tsx` | Message list component | ✗ STUB | Returns `Chat will be here
` |
+| `src/components/ChatInput.tsx` | Message input | ✓ EXISTS + SUBSTANTIVE | Form with input, submit button, handlers |
+| `src/app/api/chat/route.ts` | Message CRUD | ✗ STUB | GET returns [], POST returns { ok: true } |
+| `prisma/schema.prisma` | Message model | ✓ EXISTS + SUBSTANTIVE | Message model with id, content, userId, createdAt |
+
+**Artifacts:** 2/4 verified
+
+### Key Link Verification
+
+| From | To | Via | Status | Details |
+|------|----|----|--------|---------|
+| Chat.tsx | /api/chat GET | fetch | ✗ NOT WIRED | No fetch call in component |
+| ChatInput | /api/chat POST | onSubmit | ✗ NOT WIRED | Handler only logs, doesn't fetch |
+| /api/chat GET | database | prisma.message.findMany | ✗ NOT WIRED | Returns hardcoded [] |
+| /api/chat POST | database | prisma.message.create | ✗ NOT WIRED | Returns { ok: true }, no DB call |
+
+**Wiring:** 0/4 connections verified
+
+## Requirements Coverage
+
+| Requirement | Status | Blocking Issue |
+|-------------|--------|----------------|
+| CHAT-01: User can send message | ✗ BLOCKED | API POST is stub |
+| CHAT-02: User can view messages | ✗ BLOCKED | Component is placeholder |
+| CHAT-03: Messages persist | ✗ BLOCKED | No database integration |
+
+**Coverage:** 0/3 requirements satisfied
+
+## Anti-Patterns Found
+
+| File | Line | Pattern | Severity | Impact |
+|------|------|---------|----------|--------|
+| src/components/Chat.tsx | 8 | `Chat will be here
` | 🛑 Blocker | No actual content |
+| src/app/api/chat/route.ts | 5 | `return Response.json([])` | 🛑 Blocker | Hardcoded empty |
+| src/app/api/chat/route.ts | 12 | `// TODO: save to database` | ⚠️ Warning | Incomplete |
+
+**Anti-patterns:** 3 found (2 blockers, 1 warning)
+
+## Human Verification Required
+
+None needed until automated gaps are fixed.
+
+## Gaps Summary
+
+### Critical Gaps (Block Progress)
+
+1. **Chat component is placeholder**
+ - Missing: Actual message list rendering
+ - Impact: Users see "Chat will be here" instead of messages
+ - Fix: Implement Chat.tsx to fetch and render messages
+
+2. **API routes are stubs**
+ - Missing: Database integration in GET and POST
+ - Impact: No data persistence, no real functionality
+ - Fix: Wire prisma calls in route handlers
+
+3. **No wiring between frontend and backend**
+ - Missing: fetch calls in components
+ - Impact: Even if API worked, UI wouldn't call it
+ - Fix: Add useEffect fetch in Chat, onSubmit fetch in ChatInput
+
+## Recommended Fix Plans
+
+### 03-04-PLAN.md: Implement Chat API
+
+**Objective:** Wire API routes to database
+
+**Tasks:**
+1. Implement GET /api/chat with prisma.message.findMany
+2. Implement POST /api/chat with prisma.message.create
+3. Verify: API returns real data, POST creates records
+
+**Estimated scope:** Small
+
+---
+
+### 03-05-PLAN.md: Implement Chat UI
+
+**Objective:** Wire Chat component to API
+
+**Tasks:**
+1. Implement Chat.tsx with useEffect fetch and message rendering
+2. Wire ChatInput onSubmit to POST /api/chat
+3. Verify: Messages display, new messages appear after send
+
+**Estimated scope:** Small
+
+---
+
+## Verification Metadata
+
+**Verification approach:** Goal-backward (derived from phase goal)
+**Must-haves source:** 03-01-PLAN.md frontmatter
+**Automated checks:** 2 passed, 8 failed
+**Human checks required:** 0 (blocked by automated failures)
+**Total verification time:** 2 min
+
+---
+*Verified: 2025-01-15T14:30:00Z*
+*Verifier: Claude (subagent)*
+```
diff --git a/get-shit-done/workflows/verify-phase.md b/get-shit-done/workflows/verify-phase.md
new file mode 100644
index 000000000..d50506bb1
--- /dev/null
+++ b/get-shit-done/workflows/verify-phase.md
@@ -0,0 +1,629 @@
+
+Verify phase goal achievement through goal-backward analysis. Check that the codebase actually delivers what the phase promised, not just that tasks were completed.
+
+This workflow is executed by a verification subagent spawned from execute-phase.md.
+
+
+
+**Task completion ≠ Goal achievement**
+
+A task "create chat component" can be marked complete when the component is a placeholder. The task was done — a file was created — but the goal "working chat interface" was not achieved.
+
+Goal-backward verification starts from the outcome and works backwards:
+1. What must be TRUE for the goal to be achieved?
+2. What must EXIST for those truths to hold?
+3. What must be WIRED for those artifacts to function?
+
+Then verify each level against the actual codebase.
+
+
+
+**Load these references:**
+- ~/.claude/get-shit-done/references/goal-backward.md (derivation process)
+- ~/.claude/get-shit-done/references/verification-patterns.md (detection patterns)
+- ~/.claude/get-shit-done/templates/verification-report.md (output format)
+
+
+
+
+
+**Gather all verification context:**
+
+```bash
+# Phase directory
+PHASE_DIR=$(ls -d .planning/phases/${PHASE_ARG}* 2>/dev/null | head -1)
+
+# Phase goal from ROADMAP
+grep -A 5 "Phase ${PHASE_NUM}" .planning/ROADMAP.md
+
+# Requirements mapped to this phase
+grep -E "^| ${PHASE_NUM}" .planning/REQUIREMENTS.md 2>/dev/null
+
+# All SUMMARY files (claims to verify)
+ls "$PHASE_DIR"/*-SUMMARY.md 2>/dev/null
+
+# All PLAN files (for must_haves in frontmatter)
+ls "$PHASE_DIR"/*-PLAN.md 2>/dev/null
+```
+
+**Extract phase goal:** Parse ROADMAP.md for this phase's goal/description. This is the outcome to verify, not the tasks.
+
+**Extract requirements:** If REQUIREMENTS.md exists, find requirements mapped to this phase. These become additional verification targets.
+
+
+
+**Determine what must be verified.**
+
+**Option A: Must-haves in PLAN frontmatter**
+
+Check if any PLAN.md has `must_haves` in frontmatter:
+
+```bash
+grep -l "must_haves:" "$PHASE_DIR"/*-PLAN.md 2>/dev/null
+```
+
+If found, extract and use:
+```yaml
+must_haves:
+ truths:
+ - "User can see existing messages"
+ - "User can send a message"
+ artifacts:
+ - path: "src/components/Chat.tsx"
+ provides: "Message list rendering"
+ key_links:
+ - from: "Chat.tsx"
+ to: "api/chat"
+ via: "fetch in useEffect"
+```
+
+**Option B: Derive from phase goal**
+
+If no must_haves in frontmatter, derive using goal-backward process:
+
+1. **State the goal:** Take phase goal from ROADMAP.md
+
+2. **Derive truths:** Ask "What must be TRUE for this goal to be achieved?"
+ - List 3-7 observable behaviors from user perspective
+ - Each truth should be testable by a human using the app
+
+3. **Derive artifacts:** For each truth, ask "What must EXIST?"
+ - Map truths to concrete files (components, routes, schemas)
+ - Be specific: `src/components/Chat.tsx`, not "chat component"
+
+4. **Derive key links:** For each artifact, ask "What must be CONNECTED?"
+ - Identify critical wiring (component calls API, API queries DB)
+ - These are where stubs hide
+
+5. **Document derived must-haves** before proceeding to verification.
+
+See ~/.claude/get-shit-done/references/goal-backward.md for detailed derivation guidance.
+
+
+
+**For each observable truth, determine if codebase enables it.**
+
+A truth is achievable if the supporting artifacts exist, are substantive, and are wired correctly.
+
+**Verification status:**
+- ✓ VERIFIED: All supporting artifacts pass all checks
+- ✗ FAILED: One or more supporting artifacts missing, stub, or unwired
+- ? UNCERTAIN: Can't verify programmatically (needs human)
+
+**For each truth:**
+
+1. Identify supporting artifacts (which files make this truth possible?)
+2. Check artifact status (see verify_artifacts step)
+3. Check wiring status (see verify_wiring step)
+4. Determine truth status based on supporting infrastructure
+
+**Example:**
+
+Truth: "User can see existing messages"
+
+Supporting artifacts:
+- Chat.tsx (renders messages)
+- /api/chat GET (provides messages)
+- Message model (defines schema)
+
+If Chat.tsx is a stub → Truth FAILED
+If /api/chat GET returns hardcoded [] → Truth FAILED
+If Chat.tsx exists, is substantive, calls API, renders response → Truth VERIFIED
+
+
+
+**For each required artifact, verify three levels:**
+
+### Level 1: Existence
+
+```bash
+check_exists() {
+ local path="$1"
+ if [ -f "$path" ]; then
+ echo "EXISTS"
+ elif [ -d "$path" ]; then
+ echo "EXISTS (directory)"
+ else
+ echo "MISSING"
+ fi
+}
+```
+
+If MISSING → artifact fails, record and continue to next artifact.
+
+### Level 2: Substantive
+
+Check that the file has real implementation, not a stub.
+
+**Line count check:**
+```bash
+check_length() {
+ local path="$1"
+ local min_lines="$2"
+ local lines=$(wc -l < "$path" 2>/dev/null || echo 0)
+ [ "$lines" -ge "$min_lines" ] && echo "SUBSTANTIVE ($lines lines)" || echo "THIN ($lines lines)"
+}
+```
+
+Minimum lines by type:
+- Component: 15+ lines
+- API route: 10+ lines
+- Hook/util: 10+ lines
+- Schema model: 5+ lines
+
+**Stub pattern check:**
+```bash
+check_stubs() {
+ local path="$1"
+
+ # Universal stub patterns
+ local stubs=$(grep -c -E "TODO|FIXME|placeholder|not implemented|coming soon" "$path" 2>/dev/null || echo 0)
+
+ # Empty returns
+ local empty=$(grep -c -E "return null|return undefined|return \{\}|return \[\]" "$path" 2>/dev/null || echo 0)
+
+ # Placeholder content
+ local placeholder=$(grep -c -E "will be here|placeholder|lorem ipsum" "$path" 2>/dev/null || echo 0)
+
+ local total=$((stubs + empty + placeholder))
+ [ "$total" -gt 0 ] && echo "STUB_PATTERNS ($total found)" || echo "NO_STUBS"
+}
+```
+
+**Export check (for components/hooks):**
+```bash
+check_exports() {
+ local path="$1"
+ grep -E "^export (default )?(function|const|class)" "$path" && echo "HAS_EXPORTS" || echo "NO_EXPORTS"
+}
+```
+
+**Combine level 2 results:**
+- SUBSTANTIVE: Adequate length + no stubs + has exports
+- STUB: Too short OR has stub patterns OR no exports
+- PARTIAL: Mixed signals (length OK but has some stubs)
+
+### Level 3: Wired
+
+Check that the artifact is connected to the system.
+
+**Import check (is it used?):**
+```bash
+check_imported() {
+ local artifact_name="$1"
+ local search_path="${2:-src/}"
+
+ # Find imports of this artifact
+ local imports=$(grep -r "import.*$artifact_name" "$search_path" --include="*.ts" --include="*.tsx" 2>/dev/null | wc -l)
+
+ [ "$imports" -gt 0 ] && echo "IMPORTED ($imports times)" || echo "NOT_IMPORTED"
+}
+```
+
+**Usage check (is it called?):**
+```bash
+check_used() {
+ local artifact_name="$1"
+ local search_path="${2:-src/}"
+
+ # Find usages (function calls, component renders, etc.)
+ local uses=$(grep -r "$artifact_name" "$search_path" --include="*.ts" --include="*.tsx" 2>/dev/null | grep -v "import" | wc -l)
+
+ [ "$uses" -gt 0 ] && echo "USED ($uses times)" || echo "NOT_USED"
+}
+```
+
+**Combine level 3 results:**
+- WIRED: Imported AND used
+- ORPHANED: Exists but not imported/used
+- PARTIAL: Imported but not used (or vice versa)
+
+### Final artifact status
+
+| Exists | Substantive | Wired | Status |
+|--------|-------------|-------|--------|
+| ✓ | ✓ | ✓ | ✓ VERIFIED |
+| ✓ | ✓ | ✗ | ⚠️ ORPHANED |
+| ✓ | ✗ | - | ✗ STUB |
+| ✗ | - | - | ✗ MISSING |
+
+Record status and evidence for each artifact.
+
+
+
+**Verify key links between artifacts.**
+
+Key links are critical connections. If broken, the goal fails even with all artifacts present.
+
+### Pattern: Component → API
+
+Check if component actually calls the API:
+
+```bash
+verify_component_api_link() {
+ local component="$1"
+ local api_path="$2"
+
+ # Check for fetch/axios call to the API
+ local has_call=$(grep -E "fetch\(['\"].*$api_path|axios\.(get|post).*$api_path" "$component" 2>/dev/null)
+
+ if [ -n "$has_call" ]; then
+ # Check if response is used
+ local uses_response=$(grep -A 5 "fetch\|axios" "$component" | grep -E "await|\.then|setData|setState" 2>/dev/null)
+
+ if [ -n "$uses_response" ]; then
+ echo "WIRED: $component → $api_path (call + response handling)"
+ else
+ echo "PARTIAL: $component → $api_path (call exists but response not used)"
+ fi
+ else
+ echo "NOT_WIRED: $component → $api_path (no call found)"
+ fi
+}
+```
+
+### Pattern: API → Database
+
+Check if API route queries database:
+
+```bash
+verify_api_db_link() {
+ local route="$1"
+ local model="$2"
+
+ # Check for Prisma/DB call
+ local has_query=$(grep -E "prisma\.$model|db\.$model|$model\.(find|create|update|delete)" "$route" 2>/dev/null)
+
+ if [ -n "$has_query" ]; then
+ # Check if result is returned
+ local returns_result=$(grep -E "return.*json.*\w+|res\.json\(\w+" "$route" 2>/dev/null)
+
+ if [ -n "$returns_result" ]; then
+ echo "WIRED: $route → database ($model)"
+ else
+ echo "PARTIAL: $route → database (query exists but result not returned)"
+ fi
+ else
+ echo "NOT_WIRED: $route → database (no query for $model)"
+ fi
+}
+```
+
+### Pattern: Form → Handler
+
+Check if form submission does something:
+
+```bash
+verify_form_handler_link() {
+ local component="$1"
+
+ # Find onSubmit handler
+ local has_handler=$(grep -E "onSubmit=\{|handleSubmit" "$component" 2>/dev/null)
+
+ if [ -n "$has_handler" ]; then
+ # Check if handler has real implementation
+ local handler_content=$(grep -A 10 "onSubmit.*=" "$component" | grep -E "fetch|axios|mutate|dispatch" 2>/dev/null)
+
+ if [ -n "$handler_content" ]; then
+ echo "WIRED: form → handler (has API call)"
+ else
+ # Check for stub patterns
+ local is_stub=$(grep -A 5 "onSubmit" "$component" | grep -E "console\.log|preventDefault\(\)$|\{\}" 2>/dev/null)
+ if [ -n "$is_stub" ]; then
+ echo "STUB: form → handler (only logs or empty)"
+ else
+ echo "PARTIAL: form → handler (exists but unclear implementation)"
+ fi
+ fi
+ else
+ echo "NOT_WIRED: form → handler (no onSubmit found)"
+ fi
+}
+```
+
+### Pattern: State → Render
+
+Check if state is actually rendered:
+
+```bash
+verify_state_render_link() {
+ local component="$1"
+ local state_var="$2"
+
+ # Check if state variable exists
+ local has_state=$(grep -E "useState.*$state_var|\[$state_var," "$component" 2>/dev/null)
+
+ if [ -n "$has_state" ]; then
+ # Check if state is used in JSX
+ local renders_state=$(grep -E "\{.*$state_var.*\}|\{$state_var\." "$component" 2>/dev/null)
+
+ if [ -n "$renders_state" ]; then
+ echo "WIRED: state → render ($state_var displayed)"
+ else
+ echo "NOT_WIRED: state → render ($state_var exists but not displayed)"
+ fi
+ else
+ echo "N/A: state → render (no state var $state_var)"
+ fi
+}
+```
+
+### Aggregate key link results
+
+For each key link in must_haves:
+- Run appropriate verification function
+- Record status and evidence
+- WIRED / PARTIAL / STUB / NOT_WIRED
+
+
+
+**Check requirements coverage if REQUIREMENTS.md exists.**
+
+```bash
+# Find requirements mapped to this phase
+grep -E "Phase ${PHASE_NUM}" .planning/REQUIREMENTS.md 2>/dev/null
+```
+
+For each requirement:
+1. Parse requirement description
+2. Identify which truths/artifacts support it
+3. Determine status based on supporting infrastructure
+
+**Requirement status:**
+- ✓ SATISFIED: All supporting truths verified
+- ✗ BLOCKED: One or more supporting truths failed
+- ? NEEDS HUMAN: Can't verify requirement programmatically
+
+
+
+**Scan for anti-patterns across phase files.**
+
+Identify files modified in this phase:
+```bash
+# Extract files from SUMMARY.md
+grep -E "^\- \`" "$PHASE_DIR"/*-SUMMARY.md | sed 's/.*`\([^`]*\)`.*/\1/' | sort -u
+```
+
+Run anti-pattern detection:
+```bash
+scan_antipatterns() {
+ local files="$@"
+
+ echo "## Anti-Patterns Found"
+ echo ""
+
+ for file in $files; do
+ [ -f "$file" ] || continue
+
+ # TODO/FIXME comments
+ grep -n -E "TODO|FIXME|XXX|HACK" "$file" 2>/dev/null | while read line; do
+ echo "| $file | $(echo $line | cut -d: -f1) | TODO/FIXME | ⚠️ Warning |"
+ done
+
+ # Placeholder content
+ grep -n -E "placeholder|coming soon|will be here" "$file" -i 2>/dev/null | while read line; do
+ echo "| $file | $(echo $line | cut -d: -f1) | Placeholder | 🛑 Blocker |"
+ done
+
+ # Empty implementations
+ grep -n -E "return null|return \{\}|return \[\]|=> \{\}" "$file" 2>/dev/null | while read line; do
+ echo "| $file | $(echo $line | cut -d: -f1) | Empty return | ⚠️ Warning |"
+ done
+
+ # Console.log only implementations
+ grep -n -B 2 -A 2 "console\.log" "$file" 2>/dev/null | grep -E "^\s*(const|function|=>)" | while read line; do
+ echo "| $file | - | Log-only function | ⚠️ Warning |"
+ done
+ done
+}
+```
+
+Categorize findings:
+- 🛑 Blocker: Prevents goal achievement (placeholder renders, empty handlers)
+- ⚠️ Warning: Indicates incomplete (TODO comments, console.log)
+- ℹ️ Info: Notable but not problematic
+
+
+
+**Flag items that need human verification.**
+
+Some things can't be verified programmatically:
+
+**Always needs human:**
+- Visual appearance (does it look right?)
+- User flow completion (can you do the full task?)
+- Real-time behavior (WebSocket, SSE updates)
+- External service integration (payments, email)
+- Performance feel (does it feel fast?)
+- Error message clarity
+
+**Needs human if uncertain:**
+- Complex wiring that grep can't trace
+- Dynamic behavior depending on state
+- Edge cases and error states
+
+**Format for human verification:**
+```markdown
+## Human Verification Required
+
+### 1. {Test Name}
+**Test:** {What to do}
+**Expected:** {What should happen}
+**Why human:** {Why can't verify programmatically}
+```
+
+
+
+**Calculate overall verification status.**
+
+**Status: passed**
+- All truths VERIFIED
+- All artifacts pass level 1-3
+- All key links WIRED
+- No blocker anti-patterns
+- (Human verification items are OK — will be prompted)
+
+**Status: gaps_found**
+- One or more truths FAILED
+- OR one or more artifacts MISSING/STUB
+- OR one or more key links NOT_WIRED
+- OR blocker anti-patterns found
+
+**Status: human_needed**
+- All automated checks pass
+- BUT items flagged for human verification
+- Can't determine goal achievement without human
+
+**Calculate score:**
+```
+score = (verified_truths / total_truths)
+```
+
+
+
+**If gaps_found, recommend fix plans.**
+
+Group related gaps into fix plans:
+
+1. **Identify gap clusters:**
+ - API stub + component not wired → "Wire frontend to backend"
+ - Multiple artifacts missing → "Complete core implementation"
+ - Wiring issues only → "Connect existing components"
+
+2. **Generate plan recommendations:**
+
+```markdown
+### {phase}-{next}-PLAN.md: {Fix Name}
+
+**Objective:** {What this fixes}
+
+**Tasks:**
+1. {Task to fix gap 1}
+ - Files: {files to modify}
+ - Action: {specific fix}
+ - Verify: {how to confirm fix}
+
+2. {Task to fix gap 2}
+ - Files: {files to modify}
+ - Action: {specific fix}
+ - Verify: {how to confirm fix}
+
+3. Re-verify phase goal
+ - Run verification again
+ - Confirm all must-haves pass
+
+**Estimated scope:** {Small / Medium}
+```
+
+3. **Keep plans focused:**
+ - 2-3 tasks per plan
+ - Single concern per plan
+ - Include verification task
+
+4. **Order by dependency:**
+ - Fix missing artifacts before wiring
+ - Fix stubs before integration
+ - Verify after all fixes
+
+
+
+**Generate VERIFICATION.md using template.**
+
+```bash
+REPORT_PATH="$PHASE_DIR/${PHASE_NUM}-VERIFICATION.md"
+```
+
+Fill template sections:
+1. **Frontmatter:** phase, verified timestamp, status, score
+2. **Goal Achievement:** Truth verification table
+3. **Required Artifacts:** Artifact verification table
+4. **Key Link Verification:** Wiring verification table
+5. **Requirements Coverage:** If REQUIREMENTS.md exists
+6. **Anti-Patterns Found:** Scan results table
+7. **Human Verification Required:** Items needing human
+8. **Gaps Summary:** Critical and non-critical gaps
+9. **Recommended Fix Plans:** If gaps_found
+10. **Verification Metadata:** Approach, timing, counts
+
+See ~/.claude/get-shit-done/templates/verification-report.md for complete template.
+
+
+
+**Return results to execute-phase orchestrator.**
+
+**Return format:**
+
+```markdown
+## Verification Complete
+
+**Status:** {passed | gaps_found | human_needed}
+**Score:** {N}/{M} must-haves verified
+**Report:** .planning/phases/{phase_dir}/{phase}-VERIFICATION.md
+
+{If passed:}
+All must-haves verified. Phase goal achieved. Ready to proceed.
+
+{If gaps_found:}
+### Gaps Found
+
+{N} critical gaps blocking goal achievement:
+1. {Gap 1 summary}
+2. {Gap 2 summary}
+
+### Recommended Fixes
+
+{N} fix plans recommended:
+1. {phase}-{next}-PLAN.md: {name}
+2. {phase}-{next+1}-PLAN.md: {name}
+
+{If human_needed:}
+### Human Verification Required
+
+{N} items need human testing:
+1. {Item 1}
+2. {Item 2}
+
+Automated checks passed. Awaiting human verification.
+```
+
+The orchestrator will:
+- If `passed`: Continue to update_roadmap
+- If `gaps_found`: Create and execute fix plans, then re-verify
+- If `human_needed`: Present items to user, collect responses
+
+
+
+
+
+- [ ] Must-haves established (from frontmatter or derived)
+- [ ] All truths verified with status and evidence
+- [ ] All artifacts checked at all three levels
+- [ ] All key links verified
+- [ ] Requirements coverage assessed (if applicable)
+- [ ] Anti-patterns scanned and categorized
+- [ ] Human verification items identified
+- [ ] Overall status determined
+- [ ] Fix plans generated (if gaps_found)
+- [ ] VERIFICATION.md created with complete report
+- [ ] Results returned to orchestrator
+