get-shit-done-ios 0.10.0 → 0.11.0

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 (58) hide show
  1. package/agents/gsd-debugger.md +2 -2
  2. package/agents/gsd-executor.md +22 -12
  3. package/agents/gsd-phase-researcher.md +4 -4
  4. package/agents/gsd-plan-checker.md +8 -6
  5. package/agents/gsd-planner.md +25 -7
  6. package/agents/gsd-project-researcher.md +1 -1
  7. package/agents/gsd-research-synthesizer.md +1 -1
  8. package/agents/gsd-roadmapper.md +3 -0
  9. package/agents/gsd-verifier.md +7 -7
  10. package/bin/install.js +7 -7
  11. package/commands/gsd/debug.md +2 -2
  12. package/commands/gsd/discuss-phase.md +8 -5
  13. package/commands/gsd/research-phase.md +3 -3
  14. package/get-shit-done/bin/lib/core.cjs +16 -3
  15. package/get-shit-done/bin/lib/milestone.cjs +39 -2
  16. package/get-shit-done/bin/lib/phase.cjs +12 -5
  17. package/get-shit-done/bin/lib/state.cjs +2 -1
  18. package/get-shit-done/references/decimal-phase-calculation.md +4 -4
  19. package/get-shit-done/references/git-integration.md +3 -3
  20. package/get-shit-done/references/git-planning-commit.md +2 -2
  21. package/get-shit-done/references/ios-frameworks.md +16 -0
  22. package/get-shit-done/references/ios-mcp-tools.md +155 -0
  23. package/get-shit-done/references/ios-swift-guidelines.md +28 -0
  24. package/get-shit-done/references/ios-testing.md +55 -0
  25. package/get-shit-done/references/phase-argument-parsing.md +3 -3
  26. package/get-shit-done/references/planning-config.md +6 -6
  27. package/get-shit-done/templates/context.md +14 -0
  28. package/get-shit-done/workflows/add-phase.md +2 -2
  29. package/get-shit-done/workflows/add-tests.md +2 -2
  30. package/get-shit-done/workflows/add-todo.md +3 -3
  31. package/get-shit-done/workflows/audit-milestone.md +5 -5
  32. package/get-shit-done/workflows/check-todos.md +2 -2
  33. package/get-shit-done/workflows/cleanup.md +1 -1
  34. package/get-shit-done/workflows/complete-milestone.md +6 -6
  35. package/get-shit-done/workflows/diagnose-issues.md +1 -1
  36. package/get-shit-done/workflows/discuss-phase.md +86 -14
  37. package/get-shit-done/workflows/execute-phase.md +25 -9
  38. package/get-shit-done/workflows/execute-plan.md +12 -12
  39. package/get-shit-done/workflows/health.md +2 -2
  40. package/get-shit-done/workflows/insert-phase.md +2 -2
  41. package/get-shit-done/workflows/map-codebase.md +2 -2
  42. package/get-shit-done/workflows/new-milestone.md +6 -6
  43. package/get-shit-done/workflows/new-project.md +30 -7
  44. package/get-shit-done/workflows/pause-work.md +2 -2
  45. package/get-shit-done/workflows/plan-milestone-gaps.md +2 -2
  46. package/get-shit-done/workflows/plan-phase.md +9 -9
  47. package/get-shit-done/workflows/progress.md +6 -6
  48. package/get-shit-done/workflows/quick.md +4 -4
  49. package/get-shit-done/workflows/remove-phase.md +4 -4
  50. package/get-shit-done/workflows/research-phase.md +2 -2
  51. package/get-shit-done/workflows/resume-project.md +1 -1
  52. package/get-shit-done/workflows/set-profile.md +2 -2
  53. package/get-shit-done/workflows/settings.md +2 -2
  54. package/get-shit-done/workflows/transition.md +4 -4
  55. package/get-shit-done/workflows/update.md +2 -6
  56. package/get-shit-done/workflows/verify-phase.md +6 -6
  57. package/get-shit-done/workflows/verify-work.md +2 -2
  58. package/package.json +1 -1
@@ -1157,7 +1157,7 @@ mv .planning/debug/{slug}.md .planning/debug/resolved/
1157
1157
  **Check planning config using state load (commit_docs is available from the output):**
1158
1158
 
1159
1159
  ```bash
1160
- INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs state load)
1160
+ INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state load)
1161
1161
  # commit_docs is in the JSON output
1162
1162
  ```
1163
1163
 
@@ -1174,7 +1174,7 @@ Root cause: {root_cause}"
1174
1174
 
1175
1175
  Then commit planning docs via CLI (respects `commit_docs` config automatically):
1176
1176
  ```bash
1177
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs: resolve debug {slug}" --files .planning/debug/resolved/{slug}.md
1177
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: resolve debug {slug}" --files .planning/debug/resolved/{slug}.md
1178
1178
  ```
1179
1179
 
1180
1180
  Report completion and offer next steps.
@@ -28,7 +28,7 @@ Before executing, discover project context:
28
28
 
29
29
  **Project instructions:** Read `./CLAUDE.md` if it exists in the working directory. Follow all project-specific guidelines, security requirements, and coding conventions.
30
30
 
31
- **Project skills:** Check `.agents/skills/` directory if it exists:
31
+ **Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
32
32
  1. List available skills (subdirectories)
33
33
  2. Read `SKILL.md` for each skill (lightweight index ~130 lines)
34
34
  3. Load specific `rules/*.md` files as needed during implementation
@@ -44,7 +44,7 @@ This ensures project-specific patterns, conventions, and best practices are appl
44
44
  Load execution context:
45
45
 
46
46
  ```bash
47
- INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs init execute-phase "${PHASE}")
47
+ INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init execute-phase "${PHASE}")
48
48
  ```
49
49
 
50
50
  Extract from init JSON: `executor_model`, `commit_docs`, `phase_dir`, `plans`, `incomplete_plans`.
@@ -193,6 +193,16 @@ Track auto-fix attempts per task. After 3 auto-fix attempts on a single task:
193
193
  - Do NOT restart the build to find more issues
194
194
  </deviation_rules>
195
195
 
196
+ <analysis_paralysis_guard>
197
+ **During task execution, if you make 5+ consecutive Read/Grep/Glob calls without any Edit/Write/Bash action:**
198
+
199
+ STOP. State in one sentence why you haven't written anything yet. Then either:
200
+ 1. Write code (you have enough context), or
201
+ 2. Report "blocked" with the specific missing information.
202
+
203
+ Do NOT continue reading. Analysis without action is a stuck signal.
204
+ </analysis_paralysis_guard>
205
+
196
206
  <authentication_gates>
197
207
  **Auth errors during `type="auto"` execution are gates, not failures.**
198
208
 
@@ -212,7 +222,7 @@ Track auto-fix attempts per task. After 3 auto-fix attempts on a single task:
212
222
  Check if auto mode is active at executor start:
213
223
 
214
224
  ```bash
215
- AUTO_CFG=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs config-get workflow.auto_advance 2>/dev/null || echo "false")
225
+ AUTO_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.auto_advance 2>/dev/null || echo "false")
216
226
  ```
217
227
 
218
228
  Store the result for checkpoint handling below.
@@ -418,34 +428,34 @@ After SUMMARY.md, update STATE.md using gsd-tools:
418
428
 
419
429
  ```bash
420
430
  # Advance plan counter (handles edge cases automatically)
421
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs state advance-plan
431
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state advance-plan
422
432
 
423
433
  # Recalculate progress bar from disk state
424
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs state update-progress
434
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state update-progress
425
435
 
426
436
  # Record execution metrics
427
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs state record-metric \
437
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state record-metric \
428
438
  --phase "${PHASE}" --plan "${PLAN}" --duration "${DURATION}" \
429
439
  --tasks "${TASK_COUNT}" --files "${FILE_COUNT}"
430
440
 
431
441
  # Add decisions (extract from SUMMARY.md key-decisions)
432
442
  for decision in "${DECISIONS[@]}"; do
433
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs state add-decision \
443
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state add-decision \
434
444
  --phase "${PHASE}" --summary "${decision}"
435
445
  done
436
446
 
437
447
  # Update session info
438
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs state record-session \
448
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state record-session \
439
449
  --stopped-at "Completed ${PHASE}-${PLAN}-PLAN.md"
440
450
  ```
441
451
 
442
452
  ```bash
443
453
  # Update ROADMAP.md progress for this phase (plan counts, status)
444
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap update-plan-progress "${PHASE_NUMBER}"
454
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap update-plan-progress "${PHASE_NUMBER}"
445
455
 
446
456
  # Mark completed requirements from PLAN.md frontmatter
447
457
  # Extract the `requirements` array from the plan's frontmatter, then mark each complete
448
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs requirements mark-complete ${REQ_IDS}
458
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" requirements mark-complete ${REQ_IDS}
449
459
  ```
450
460
 
451
461
  **Requirement IDs:** Extract from the PLAN.md frontmatter `requirements:` field (e.g., `requirements: [AUTH-01, AUTH-02]`). Pass all IDs to `requirements mark-complete`. If the plan has no requirements field, skip this step.
@@ -463,13 +473,13 @@ node ~/.claude/get-shit-done/bin/gsd-tools.cjs requirements mark-complete ${REQ_
463
473
 
464
474
  **For blockers found during execution:**
465
475
  ```bash
466
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs state add-blocker "Blocker description"
476
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state add-blocker "Blocker description"
467
477
  ```
468
478
  </state_updates>
469
479
 
470
480
  <final_commit>
471
481
  ```bash
472
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md
482
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md
473
483
  ```
474
484
 
475
485
  Separate from per-task commits — captures execution results only.
@@ -26,7 +26,7 @@ Before researching, discover project context:
26
26
 
27
27
  **Project instructions:** Read `./CLAUDE.md` if it exists in the working directory. Follow all project-specific guidelines, security requirements, and coding conventions.
28
28
 
29
- **Project skills:** Check `.agents/skills/` directory if it exists:
29
+ **Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
30
30
  1. List available skills (subdirectories)
31
31
  2. Read `SKILL.md` for each skill (lightweight index ~130 lines)
32
32
  3. Load specific `rules/*.md` files as needed during implementation
@@ -133,7 +133,7 @@ When researching "best library for X": find what the ecosystem actually uses, do
133
133
  Check `brave_search` from init context. If `true`, use Brave Search for higher quality results:
134
134
 
135
135
  ```bash
136
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs websearch "your query" --limit 10
136
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" websearch "your query" --limit 10
137
137
  ```
138
138
 
139
139
  **Options:**
@@ -412,7 +412,7 @@ Orchestrator provides: phase number/name, description/goal, requirements, constr
412
412
 
413
413
  Load phase context using init command:
414
414
  ```bash
415
- INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs init phase-op "${PHASE}")
415
+ INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE}")
416
416
  ```
417
417
 
418
418
  Extract from init JSON: `phase_dir`, `padded_phase`, `phase_number`, `commit_docs`.
@@ -527,7 +527,7 @@ Write to: `$PHASE_DIR/$PADDED_PHASE-RESEARCH.md`
527
527
  ## Step 7: Commit Research (optional)
528
528
 
529
529
  ```bash
530
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs($PHASE): research phase domain" --files "$PHASE_DIR/$PADDED_PHASE-RESEARCH.md"
530
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs($PHASE): research phase domain" --files "$PHASE_DIR/$PADDED_PHASE-RESEARCH.md"
531
531
  ```
532
532
 
533
533
  ## Step 8: Return Structured Result
@@ -31,7 +31,7 @@ Before verifying, discover project context:
31
31
 
32
32
  **Project instructions:** Read `./CLAUDE.md` if it exists in the working directory. Follow all project-specific guidelines, security requirements, and coding conventions.
33
33
 
34
- **Project skills:** Check `.agents/skills/` directory if it exists:
34
+ **Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
35
35
  1. List available skills (subdirectories)
36
36
  2. Read `SKILL.md` for each skill (lightweight index ~130 lines)
37
37
  3. Load specific `rules/*.md` files as needed during implementation
@@ -365,7 +365,7 @@ If FAIL: return to planner with specific fixes. Same revision loop as other dime
365
365
 
366
366
  Load phase operation context:
367
367
  ```bash
368
- INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs init phase-op "${PHASE_ARG}")
368
+ INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE_ARG}")
369
369
  ```
370
370
 
371
371
  Extract from init JSON: `phase_dir`, `phase_number`, `has_plans`, `plan_count`.
@@ -376,7 +376,7 @@ Orchestrator provides CONTEXT.md content in the verification prompt. If provided
376
376
  ls "$phase_dir"/*-PLAN.md 2>/dev/null
377
377
  # Read research for Nyquist validation data
378
378
  cat "$phase_dir"/*-RESEARCH.md 2>/dev/null
379
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap get-phase "$phase_number"
379
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "$phase_number"
380
380
  ls "$phase_dir"/*-BRIEF.md 2>/dev/null
381
381
  ```
382
382
 
@@ -389,7 +389,7 @@ Use gsd-tools to validate plan structure:
389
389
  ```bash
390
390
  for plan in "$PHASE_DIR"/*-PLAN.md; do
391
391
  echo "=== $plan ==="
392
- PLAN_STRUCTURE=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify plan-structure "$plan")
392
+ PLAN_STRUCTURE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify plan-structure "$plan")
393
393
  echo "$PLAN_STRUCTURE"
394
394
  done
395
395
  ```
@@ -407,7 +407,7 @@ Map errors/warnings to verification dimensions:
407
407
  Extract must_haves from each plan using gsd-tools:
408
408
 
409
409
  ```bash
410
- MUST_HAVES=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs frontmatter get "$PLAN_PATH" --field must_haves)
410
+ MUST_HAVES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" frontmatter get "$PLAN_PATH" --field must_haves)
411
411
  ```
412
412
 
413
413
  Returns JSON: `{ truths: [...], artifacts: [...], key_links: [...] }`
@@ -445,12 +445,14 @@ Session persists | 01 | 3 | COVERED
445
445
 
446
446
  For each requirement: find covering task(s), verify action is specific, flag gaps.
447
447
 
448
+ **Exhaustive cross-check:** Also read PROJECT.md requirements (not just phase goal). Verify no PROJECT.md requirement relevant to this phase is silently dropped. Any unmapped requirement is an automatic blocker — list it explicitly in issues.
449
+
448
450
  ## Step 5: Validate Task Structure
449
451
 
450
452
  Use gsd-tools plan-structure verification (already run in Step 2):
451
453
 
452
454
  ```bash
453
- PLAN_STRUCTURE=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify plan-structure "$PLAN_PATH")
455
+ PLAN_STRUCTURE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify plan-structure "$PLAN_PATH")
454
456
  ```
455
457
 
456
458
  The `tasks` array in the result shows each task's completeness:
@@ -33,7 +33,7 @@ Before planning, discover project context:
33
33
 
34
34
  **Project instructions:** Read `./CLAUDE.md` if it exists in the working directory. Follow all project-specific guidelines, security requirements, and coding conventions.
35
35
 
36
- **Project skills:** Check `.agents/skills/` directory if it exists:
36
+ **Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
37
37
  1. List available skills (subdirectories)
38
38
  2. Read `SKILL.md` for each skill (lightweight index ~130 lines)
39
39
  3. Load specific `rules/*.md` files as needed during implementation
@@ -261,6 +261,24 @@ This prevents the "scavenger hunt" anti-pattern where executors explore the code
261
261
 
262
262
  **Why TDD gets own plan:** TDD requires RED→GREEN→REFACTOR cycles consuming 40-50% context. Embedding in multi-task plans degrades quality.
263
263
 
264
+ **Task-level TDD** (for code-producing tasks in standard plans): When a task creates or modifies production code, add tdd="true" and a <behavior> block to make test expectations explicit before implementation:
265
+
266
+ <task type="auto" tdd="true">
267
+ <n>Task: [name]</n>
268
+ <files>Sources/Feature.swift, Tests/FeatureTests.swift</files>
269
+ <behavior>
270
+ - Test 1: [expected behavior]
271
+ - Test 2: [edge case]
272
+ </behavior>
273
+ <action>[Implementation after tests pass]</action>
274
+ <verify>
275
+ <automated>swift test --filter FeatureTests</automated>
276
+ </verify>
277
+ <done>[Criteria]</done>
278
+ </task>
279
+
280
+ Exceptions where tdd="true" is not needed: type="checkpoint:*" tasks, configuration-only files, documentation, migration scripts, glue code wiring existing tested components, styling-only changes.
281
+
264
282
  ## User Setup Detection
265
283
 
266
284
  For tasks involving external services or Apple capabilities, identify human-required configuration:
@@ -943,7 +961,7 @@ Group by plan, dimension, severity.
943
961
  ### Step 6: Commit
944
962
 
945
963
  ```bash
946
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "fix($PHASE): revise plans based on checker feedback" --files .planning/phases/$PHASE-*/$PHASE-*-PLAN.md
964
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "fix($PHASE): revise plans based on checker feedback" --files .planning/phases/$PHASE-*/$PHASE-*-PLAN.md
947
965
  ```
948
966
 
949
967
  ### Step 7: Return Revision Summary
@@ -982,7 +1000,7 @@ node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "fix($PHASE): revise plans
982
1000
  Load planning context:
983
1001
 
984
1002
  ```bash
985
- INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs init plan-phase "${PHASE}")
1003
+ INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init plan-phase "${PHASE}")
986
1004
  ```
987
1005
 
988
1006
  Extract from init JSON: `planner_model`, `researcher_model`, `checker_model`, `commit_docs`, `research_enabled`, `phase_dir`, `phase_number`, `has_research`, `has_context`.
@@ -1038,7 +1056,7 @@ Apply discovery level protocol (see discovery_levels section).
1038
1056
 
1039
1057
  **Step 1 — Generate digest index:**
1040
1058
  ```bash
1041
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs history-digest
1059
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" history-digest
1042
1060
  ```
1043
1061
 
1044
1062
  **Step 2 — Select relevant phases (typically 2-4):**
@@ -1166,7 +1184,7 @@ Include all frontmatter fields.
1166
1184
  Validate each created PLAN.md using gsd-tools:
1167
1185
 
1168
1186
  ```bash
1169
- VALID=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs frontmatter validate "$PLAN_PATH" --schema plan)
1187
+ VALID=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" frontmatter validate "$PLAN_PATH" --schema plan)
1170
1188
  ```
1171
1189
 
1172
1190
  Returns JSON: `{ valid, missing, present, schema }`
@@ -1179,7 +1197,7 @@ Required plan frontmatter fields:
1179
1197
  Also validate plan structure:
1180
1198
 
1181
1199
  ```bash
1182
- STRUCTURE=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify plan-structure "$PLAN_PATH")
1200
+ STRUCTURE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify plan-structure "$PLAN_PATH")
1183
1201
  ```
1184
1202
 
1185
1203
  Returns JSON: `{ valid, errors, warnings, task_count, tasks }`
@@ -1216,7 +1234,7 @@ Plans:
1216
1234
 
1217
1235
  <step name="git_commit">
1218
1236
  ```bash
1219
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs($PHASE): create phase plan" --files .planning/phases/$PHASE-*/$PHASE-*-PLAN.md .planning/ROADMAP.md
1237
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs($PHASE): create phase plan" --files .planning/phases/$PHASE-*/$PHASE-*-PLAN.md .planning/ROADMAP.md
1220
1238
  ```
1221
1239
  </step>
1222
1240
 
@@ -118,7 +118,7 @@ Always include current year. Use iOS/Swift/SwiftUI-specific terms. Mark WebSearc
118
118
  Check `brave_search` from orchestrator context. If `true`, use Brave Search for higher quality results:
119
119
 
120
120
  ```bash
121
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs websearch "your query" --limit 10
121
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" websearch "your query" --limit 10
122
122
  ```
123
123
 
124
124
  **Options:**
@@ -131,7 +131,7 @@ Write to `.planning/research/SUMMARY.md`
131
131
  The 4 parallel researcher agents write files but do NOT commit. You commit everything together.
132
132
 
133
133
  ```bash
134
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs: complete project research" --files .planning/research/
134
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: complete project research" --files .planning/research/
135
135
  ```
136
136
 
137
137
  ## Step 8: Return Summary
@@ -188,6 +188,9 @@ Bad boundaries:
188
188
  - Partial features (half of auth, navigation without screens)
189
189
  - Artificial splits to hit a number
190
190
  - Separating permissions from the features that need them
191
+ - Putting tests in a separate phase from the feature they validate
192
+
193
+ **Test co-location rule:** Tests for a feature MUST be in the same phase as the feature implementation. Never create a separate "Testing" phase — tests are part of delivering the capability, not a downstream activity. If Phase 2 implements authentication, Phase 2 also contains the authentication tests.
191
194
 
192
195
  **Step 4: Assign Requirements**
193
196
  Map every v1 requirement to exactly one phase.
@@ -23,7 +23,7 @@ Before verifying, discover project context:
23
23
 
24
24
  **Project instructions:** Read `./CLAUDE.md` if it exists in the working directory. Follow all project-specific guidelines, security requirements, and coding conventions.
25
25
 
26
- **Project skills:** Check `.agents/skills/` directory if it exists:
26
+ **Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
27
27
  1. List available skills (subdirectories)
28
28
  2. Read `SKILL.md` for each skill (lightweight index ~130 lines)
29
29
  3. Load specific `rules/*.md` files as needed during verification
@@ -74,7 +74,7 @@ Set `is_re_verification = false`, proceed with Step 1.
74
74
  ```bash
75
75
  ls "$PHASE_DIR"/*-PLAN.md 2>/dev/null
76
76
  ls "$PHASE_DIR"/*-SUMMARY.md 2>/dev/null
77
- node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap get-phase "$PHASE_NUM"
77
+ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "$PHASE_NUM"
78
78
  grep -E "^| $PHASE_NUM" .planning/REQUIREMENTS.md 2>/dev/null
79
79
  ```
80
80
 
@@ -111,7 +111,7 @@ must_haves:
111
111
  If no must_haves in frontmatter, check for Success Criteria:
112
112
 
113
113
  ```bash
114
- PHASE_DATA=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap get-phase "$PHASE_NUM" --raw)
114
+ PHASE_DATA=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "$PHASE_NUM" --raw)
115
115
  ```
116
116
 
117
117
  Parse the `success_criteria` array from the JSON output. If non-empty:
@@ -154,7 +154,7 @@ For each truth:
154
154
  Use gsd-tools for artifact verification against must_haves in PLAN frontmatter:
155
155
 
156
156
  ```bash
157
- ARTIFACT_RESULT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify artifacts "$PLAN_PATH")
157
+ ARTIFACT_RESULT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify artifacts "$PLAN_PATH")
158
158
  ```
159
159
 
160
160
  Parse JSON result: `{ all_passed, passed, total, artifacts: [{path, exists, issues, passed}] }`
@@ -203,7 +203,7 @@ Key links are critical connections. If broken, the goal fails even with all arti
203
203
  Use gsd-tools for key link verification against must_haves in PLAN frontmatter:
204
204
 
205
205
  ```bash
206
- LINKS_RESULT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify key-links "$PLAN_PATH")
206
+ LINKS_RESULT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify key-links "$PLAN_PATH")
207
207
  ```
208
208
 
209
209
  Parse JSON result: `{ all_verified, verified, total, links: [{from, to, via, verified, detail}] }`
@@ -296,12 +296,12 @@ Identify files modified in this phase from SUMMARY.md key-files section, or extr
296
296
 
297
297
  ```bash
298
298
  # Option 1: Extract from SUMMARY frontmatter
299
- SUMMARY_FILES=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs summary-extract "$PHASE_DIR"/*-SUMMARY.md --fields key-files)
299
+ SUMMARY_FILES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" summary-extract "$PHASE_DIR"/*-SUMMARY.md --fields key-files)
300
300
 
301
301
  # Option 2: Verify commits exist (if commit hashes documented)
302
302
  COMMIT_HASHES=$(grep -oE "[a-f0-9]{7,40}" "$PHASE_DIR"/*-SUMMARY.md | head -10)
303
303
  if [ -n "$COMMIT_HASHES" ]; then
304
- COMMITS_VALID=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs verify commits $COMMIT_HASHES)
304
+ COMMITS_VALID=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify commits $COMMIT_HASHES)
305
305
  fi
306
306
 
307
307
  # Fallback: grep for files
package/bin/install.js CHANGED
@@ -780,16 +780,16 @@ function cleanupOrphanedHooks(settings) {
780
780
  console.log(` ${green}✓${reset} Removed orphaned hook registrations`);
781
781
  }
782
782
 
783
- // Fix #330: Update statusLine if it points to old statusline.js path
783
+ // Fix #330: Update statusLine if it points to old GSD statusline.js path
784
+ // Only match the specific old GSD path pattern (hooks/statusline.js),
785
+ // not third-party statusline scripts that happen to contain 'statusline.js'
784
786
  if (settings.statusLine && settings.statusLine.command &&
785
- settings.statusLine.command.includes('statusline.js') &&
786
- !settings.statusLine.command.includes('gsd-statusline.js')) {
787
- // Replace old path with new path
787
+ /hooks[\/\\]statusline\.js/.test(settings.statusLine.command)) {
788
788
  settings.statusLine.command = settings.statusLine.command.replace(
789
- /statusline\.js/,
790
- 'gsd-statusline.js'
789
+ /hooks([\/\\])statusline\.js/,
790
+ 'hooks$1gsd-statusline.js'
791
791
  );
792
- console.log(` ${green}✓${reset} Updated statusline path (statusline.js gsd-statusline.js)`);
792
+ console.log(` ${green}...Updated statusline path (hooks/statusline.js -> hooks/gsd-statusline.js)`);
793
793
  }
794
794
 
795
795
  return settings;
@@ -31,12 +31,12 @@ ls .planning/debug/*.md 2>/dev/null | grep -v resolved | head -5
31
31
  ## 0. Initialize Context
32
32
 
33
33
  ```bash
34
- INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs state load)
34
+ INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state load)
35
35
  ```
36
36
 
37
37
  Extract `commit_docs` from init JSON. Resolve debugger model:
38
38
  ```bash
39
- DEBUGGER_MODEL=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs resolve-model gsd-debugger --raw)
39
+ debugger_model=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-debugger --raw)
40
40
  ```
41
41
 
42
42
  ## 1. Check Active Sessions
@@ -10,6 +10,8 @@ allowed-tools:
10
10
  - Grep
11
11
  - AskUserQuestion
12
12
  - Task
13
+ - mcp__context7__resolve-library-id
14
+ - mcp__context7__query-docs
13
15
  ---
14
16
 
15
17
  <objective>
@@ -38,11 +40,12 @@ Context files are resolved in-workflow using `init phase-op` and roadmap/state t
38
40
  <process>
39
41
  1. Validate phase number (error if missing or not in roadmap)
40
42
  2. Check if CONTEXT.md exists (offer update/view/skip if yes)
41
- 3. **Analyze phase** — Identify domain and generate phase-specific gray areas
42
- 4. **Present gray areas** — Multi-select: which to discuss? (NO skip option)
43
- 5. **Deep-dive each area** — 4 questions per area, then offer more/next
44
- 6. **Write CONTEXT.md** — Sections match areas discussed
45
- 7. Offer next steps (research or plan)
43
+ 3. **Scout codebase** — Find reusable assets, patterns, and integration points
44
+ 4. **Analyze phase** — Identify domain and generate code-informed gray areas
45
+ 5. **Present gray areas** — Multi-select: which to discuss? (NO skip option)
46
+ 6. **Deep-dive each area** — 4 questions per area, code-informed options, Context7 for library choices
47
+ 7. **Write CONTEXT.md** Sections match areas discussed + code_context section
48
+ 8. Offer next steps (research or plan)
46
49
 
47
50
  **CRITICAL: Scope guardrail**
48
51
  - Phase boundary from ROADMAP.md is FIXED
@@ -34,20 +34,20 @@ Normalize phase input in step 1 before any directory lookups.
34
34
  ## 0. Initialize Context
35
35
 
36
36
  ```bash
37
- INIT=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs init phase-op "$ARGUMENTS")
37
+ INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "$ARGUMENTS")
38
38
  ```
39
39
 
40
40
  Extract from init JSON: `phase_dir`, `phase_number`, `phase_name`, `phase_found`, `commit_docs`, `has_research`.
41
41
 
42
42
  Resolve researcher model:
43
43
  ```bash
44
- RESEARCHER_MODEL=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs resolve-model gsd-phase-researcher --raw)
44
+ RESEARCHER_MODEL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-phase-researcher --raw)
45
45
  ```
46
46
 
47
47
  ## 1. Validate Phase
48
48
 
49
49
  ```bash
50
- PHASE_INFO=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap get-phase "${phase_number}")
50
+ PHASE_INFO=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "${phase_number}")
51
51
  ```
52
52
 
53
53
  **If `found` is false:** Error and exit. **If `found` is true:** Extract `phase_number`, `phase_name`, `goal` from JSON.
@@ -69,6 +69,7 @@ function loadConfig(cwd) {
69
69
  research: true,
70
70
  plan_checker: true,
71
71
  verifier: true,
72
+ nyquist_validation: false,
72
73
  parallelization: true,
73
74
  brave_search: false,
74
75
  };
@@ -104,6 +105,8 @@ function loadConfig(cwd) {
104
105
  verifier: get('verifier', { section: 'workflow', field: 'verifier' }) ?? defaults.verifier,
105
106
  parallelization,
106
107
  brave_search: get('brave_search') ?? defaults.brave_search,
108
+ nyquist_validation: get('nyquist_validation', { section: 'workflow', field: 'nyquist_validation' }) ?? defaults.nyquist_validation,
109
+ model_overrides: parsed.model_overrides || null,
107
110
  };
108
111
  } catch {
109
112
  return defaults;
@@ -378,11 +381,21 @@ function generateSlugInternal(text) {
378
381
  function getMilestoneInfo(cwd) {
379
382
  try {
380
383
  const roadmap = fs.readFileSync(path.join(cwd, '.planning', 'ROADMAP.md'), 'utf-8');
381
- const versionMatch = roadmap.match(/v(\d+\.\d+)/);
382
- const nameMatch = roadmap.match(/## .*v\d+\.\d+[:\s]+([^\n(]+)/);
384
+ // Strip <details>...</details> blocks so shipped milestones don't interfere
385
+ const cleaned = roadmap.replace(/<details>[\s\S]*?<\/details>/gi, '');
386
+ // Extract version and name from the same ## heading for consistency
387
+ const headingMatch = cleaned.match(/## .*v(\d+\.\d+)[:\s]+([^\n(]+)/);
388
+ if (headingMatch) {
389
+ return {
390
+ version: 'v' + headingMatch[1],
391
+ name: headingMatch[2].trim(),
392
+ };
393
+ }
394
+ // Fallback: try bare version match
395
+ const versionMatch = cleaned.match(/v(\d+\.\d+)/);
383
396
  return {
384
397
  version: versionMatch ? versionMatch[0] : 'v1.0',
385
- name: nameMatch ? nameMatch[1].trim() : 'milestone',
398
+ name: 'milestone',
386
399
  };
387
400
  } catch {
388
401
  return { version: 'v1.0', name: 'milestone' };
@@ -92,6 +92,30 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
92
92
  // Ensure archive directory exists
93
93
  fs.mkdirSync(archiveDir, { recursive: true });
94
94
 
95
+ // Extract milestone phase numbers from ROADMAP.md to scope stats to current milestone only.
96
+ const milestonePhaseNums = new Set();
97
+ if (fs.existsSync(roadmapPath)) {
98
+ try {
99
+ const roadmapContent = fs.readFileSync(roadmapPath, 'utf-8');
100
+ const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:/gi;
101
+ let phaseMatch;
102
+ while ((phaseMatch = phasePattern.exec(roadmapContent)) !== null) {
103
+ milestonePhaseNums.add(phaseMatch[1]);
104
+ }
105
+ } catch {}
106
+ }
107
+
108
+ const normalizedPhaseNums = new Set(
109
+ [...milestonePhaseNums].map(num => (num.replace(/^0+/, '') || '0').toLowerCase())
110
+ );
111
+
112
+ function isDirInMilestone(dirName) {
113
+ if (normalizedPhaseNums.size === 0) return true;
114
+ const m = dirName.match(/^0*(\d+[A-Za-z]?(?:\.\d+)*)/);
115
+ if (!m) return false;
116
+ return normalizedPhaseNums.has(m[1].toLowerCase());
117
+ }
118
+
95
119
  // Gather stats from phases
96
120
  let phaseCount = 0;
97
121
  let totalPlans = 0;
@@ -103,6 +127,7 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
103
127
  const dirs = entries.filter(e => e.isDirectory()).map(e => e.name).sort();
104
128
 
105
129
  for (const dir of dirs) {
130
+ if (!isDirInMilestone(dir)) continue;
106
131
  phaseCount++;
107
132
  const phaseFiles = fs.readdirSync(path.join(phasesDir, dir));
108
133
  const plans = phaseFiles.filter(f => f.endsWith('-PLAN.md') || f === 'PLAN.md');
@@ -150,7 +175,16 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
150
175
 
151
176
  if (fs.existsSync(milestonesPath)) {
152
177
  const existing = fs.readFileSync(milestonesPath, 'utf-8');
153
- fs.writeFileSync(milestonesPath, existing + '\n' + milestoneEntry, 'utf-8');
178
+ // Insert after the header line(s) for reverse chronological order (newest first)
179
+ const headerMatch = existing.match(/^(#{1,3}\s+[^\n]*\n\n?)/);
180
+ if (headerMatch) {
181
+ const header = headerMatch[1];
182
+ const rest = existing.slice(header.length);
183
+ fs.writeFileSync(milestonesPath, header + milestoneEntry + rest, 'utf-8');
184
+ } else {
185
+ // No recognizable header — prepend the entry
186
+ fs.writeFileSync(milestonesPath, milestoneEntry + existing, 'utf-8');
187
+ }
154
188
  } else {
155
189
  fs.writeFileSync(milestonesPath, `# Milestones\n\n${milestoneEntry}`, 'utf-8');
156
190
  }
@@ -182,10 +216,13 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
182
216
 
183
217
  const phaseEntries = fs.readdirSync(phasesDir, { withFileTypes: true });
184
218
  const phaseDirNames = phaseEntries.filter(e => e.isDirectory()).map(e => e.name);
219
+ let archivedCount = 0;
185
220
  for (const dir of phaseDirNames) {
221
+ if (!isDirInMilestone(dir)) continue;
186
222
  fs.renameSync(path.join(phasesDir, dir), path.join(phaseArchiveDir, dir));
223
+ archivedCount++;
187
224
  }
188
- phasesArchived = phaseDirNames.length > 0;
225
+ phasesArchived = archivedCount > 0;
189
226
  } catch {}
190
227
  }
191
228
 
@@ -193,6 +193,11 @@ function cmdFindPhase(cwd, phase, raw) {
193
193
  }
194
194
  }
195
195
 
196
+ function extractObjective(content) {
197
+ const m = content.match(/<objective>\s*\n?\s*(.+)/);
198
+ return m ? m[1].trim() : null;
199
+ }
200
+
196
201
  function cmdPhasePlanIndex(cwd, phase, raw) {
197
202
  if (!phase) {
198
203
  error('phase required for phase-plan-index');
@@ -243,8 +248,9 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
243
248
  const fm = extractFrontmatter(content);
244
249
 
245
250
  // Count tasks (## Task N patterns)
246
- const taskMatches = content.match(/##\s*Task\s*\d+/gi) || [];
247
- const taskCount = taskMatches.length;
251
+ const xmlTasks = content.match(/<task[\s>]/gi) || [];
252
+ const mdTasks = content.match(/##\s*Task\s*\d+/gi) || [];
253
+ const taskCount = xmlTasks.length || mdTasks.length;
248
254
 
249
255
  // Parse wave as integer
250
256
  const wave = parseInt(fm.wave, 10) || 1;
@@ -261,8 +267,9 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
261
267
 
262
268
  // Parse files-modified
263
269
  let filesModified = [];
264
- if (fm['files-modified']) {
265
- filesModified = Array.isArray(fm['files-modified']) ? fm['files-modified'] : [fm['files-modified']];
270
+ const fmFiles = fm['files_modified'] || fm['files-modified'];
271
+ if (fmFiles) {
272
+ filesModified = Array.isArray(fmFiles) ? fmFiles : [fmFiles];
266
273
  }
267
274
 
268
275
  const hasSummary = completedPlanIds.has(planId);
@@ -274,7 +281,7 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
274
281
  id: planId,
275
282
  wave,
276
283
  autonomous,
277
- objective: fm.objective || null,
284
+ objective: extractObjective(content) || fm.objective || null,
278
285
  files_modified: filesModified,
279
286
  task_count: taskCount,
280
287
  has_summary: hasSummary,