@bhargavvc/sdd-cc 1.30.1 → 1.35.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 (242) hide show
  1. package/README.ja-JP.md +144 -110
  2. package/README.ko-KR.md +143 -107
  3. package/README.md +183 -112
  4. package/README.pt-BR.md +90 -52
  5. package/README.zh-CN.md +141 -101
  6. package/agents/sdd-advisor-researcher.md +23 -0
  7. package/agents/sdd-ai-researcher.md +133 -0
  8. package/agents/sdd-code-fixer.md +516 -0
  9. package/agents/sdd-code-reviewer.md +355 -0
  10. package/agents/sdd-codebase-mapper.md +3 -3
  11. package/agents/sdd-debugger.md +17 -5
  12. package/agents/sdd-doc-verifier.md +201 -0
  13. package/agents/sdd-doc-writer.md +602 -0
  14. package/agents/sdd-domain-researcher.md +153 -0
  15. package/agents/sdd-eval-auditor.md +164 -0
  16. package/agents/sdd-eval-planner.md +154 -0
  17. package/agents/sdd-executor.md +87 -4
  18. package/agents/sdd-framework-selector.md +160 -0
  19. package/agents/sdd-intel-updater.md +314 -0
  20. package/agents/sdd-nyquist-auditor.md +1 -1
  21. package/agents/sdd-phase-researcher.md +71 -4
  22. package/agents/sdd-plan-checker.md +100 -6
  23. package/agents/sdd-planner.md +145 -206
  24. package/agents/sdd-project-researcher.md +25 -2
  25. package/agents/sdd-research-synthesizer.md +3 -3
  26. package/agents/sdd-roadmapper.md +6 -6
  27. package/agents/sdd-security-auditor.md +128 -0
  28. package/agents/sdd-ui-auditor.md +43 -3
  29. package/agents/sdd-ui-checker.md +5 -5
  30. package/agents/sdd-ui-researcher.md +27 -4
  31. package/agents/sdd-user-profiler.md +2 -2
  32. package/agents/sdd-verifier.md +142 -22
  33. package/bin/install.js +2145 -545
  34. package/commands/sdd/add-backlog.md +5 -5
  35. package/commands/sdd/add-tests.md +2 -2
  36. package/commands/sdd/ai-integration-phase.md +36 -0
  37. package/commands/sdd/analyze-dependencies.md +34 -0
  38. package/commands/sdd/audit-fix.md +33 -0
  39. package/commands/sdd/autonomous.md +7 -2
  40. package/commands/sdd/cleanup.md +5 -0
  41. package/commands/sdd/code-review-fix.md +52 -0
  42. package/commands/sdd/code-review.md +55 -0
  43. package/commands/sdd/complete-milestone.md +6 -6
  44. package/commands/sdd/debug.md +22 -9
  45. package/commands/sdd/discuss-phase.md +7 -2
  46. package/commands/sdd/do.md +1 -1
  47. package/commands/sdd/docs-update.md +48 -0
  48. package/commands/sdd/eval-review.md +32 -0
  49. package/commands/sdd/execute-phase.md +4 -0
  50. package/commands/sdd/explore.md +27 -0
  51. package/commands/sdd/fast.md +2 -2
  52. package/commands/sdd/from-sdd2.md +45 -0
  53. package/commands/sdd/help.md +2 -0
  54. package/commands/sdd/import.md +36 -0
  55. package/commands/sdd/intel.md +179 -0
  56. package/commands/sdd/join-discord.md +2 -1
  57. package/commands/sdd/manager.md +1 -0
  58. package/commands/sdd/map-codebase.md +3 -3
  59. package/commands/sdd/new-milestone.md +1 -1
  60. package/commands/sdd/new-project.md +5 -1
  61. package/commands/sdd/new-workspace.md +1 -1
  62. package/commands/sdd/next.md +2 -0
  63. package/commands/sdd/plan-milestone-gaps.md +2 -2
  64. package/commands/sdd/plan-phase.md +6 -1
  65. package/commands/sdd/plant-seed.md +1 -1
  66. package/commands/sdd/profile-user.md +1 -1
  67. package/commands/sdd/quick.md +5 -3
  68. package/commands/sdd/reapply-patches.md +230 -42
  69. package/commands/sdd/research-phase.md +3 -3
  70. package/commands/sdd/review-backlog.md +1 -0
  71. package/commands/sdd/review.md +6 -3
  72. package/commands/sdd/scan.md +26 -0
  73. package/commands/sdd/secure-phase.md +35 -0
  74. package/commands/sdd/ship.md +1 -1
  75. package/commands/sdd/thread.md +5 -5
  76. package/commands/sdd/undo.md +34 -0
  77. package/commands/sdd/verify-work.md +1 -1
  78. package/commands/sdd/workstreams.md +17 -11
  79. package/hooks/dist/sdd-check-update.js +33 -8
  80. package/hooks/dist/sdd-context-monitor.js +17 -8
  81. package/hooks/dist/sdd-phase-boundary.sh +27 -0
  82. package/hooks/dist/sdd-prompt-guard.js +1 -0
  83. package/hooks/dist/sdd-read-guard.js +82 -0
  84. package/hooks/dist/sdd-session-state.sh +33 -0
  85. package/hooks/dist/sdd-statusline.js +137 -15
  86. package/hooks/dist/sdd-validate-commit.sh +47 -0
  87. package/hooks/dist/sdd-workflow-guard.js +4 -4
  88. package/hooks/sdd-check-update.js +139 -0
  89. package/hooks/sdd-context-monitor.js +165 -0
  90. package/hooks/sdd-phase-boundary.sh +27 -0
  91. package/hooks/sdd-prompt-guard.js +97 -0
  92. package/hooks/sdd-read-guard.js +82 -0
  93. package/hooks/sdd-session-state.sh +33 -0
  94. package/hooks/sdd-statusline.js +241 -0
  95. package/hooks/sdd-validate-commit.sh +47 -0
  96. package/hooks/sdd-workflow-guard.js +94 -0
  97. package/package.json +3 -3
  98. package/scripts/build-hooks.js +18 -7
  99. package/scripts/prompt-injection-scan.sh +1 -0
  100. package/scripts/rebrand-gsd-to-sdd.sh +221 -220
  101. package/scripts/run-tests.cjs +5 -1
  102. package/scripts/sync-upstream.sh +1 -1
  103. package/sdd/bin/lib/commands.cjs +79 -17
  104. package/sdd/bin/lib/config.cjs +90 -48
  105. package/sdd/bin/lib/core.cjs +452 -87
  106. package/sdd/bin/lib/docs.cjs +267 -0
  107. package/sdd/bin/lib/frontmatter.cjs +381 -336
  108. package/sdd/bin/lib/init.cjs +110 -16
  109. package/sdd/bin/lib/intel.cjs +660 -0
  110. package/sdd/bin/lib/learnings.cjs +378 -0
  111. package/sdd/bin/lib/milestone.cjs +42 -11
  112. package/sdd/bin/lib/model-profiles.cjs +17 -15
  113. package/sdd/bin/lib/phase.cjs +367 -288
  114. package/sdd/bin/lib/profile-output.cjs +106 -10
  115. package/sdd/bin/lib/roadmap.cjs +146 -115
  116. package/sdd/bin/lib/schema-detect.cjs +238 -0
  117. package/sdd/bin/lib/sdd2-import.cjs +511 -0
  118. package/sdd/bin/lib/security.cjs +124 -3
  119. package/sdd/bin/lib/state.cjs +648 -264
  120. package/sdd/bin/lib/template.cjs +8 -4
  121. package/sdd/bin/lib/verify.cjs +209 -28
  122. package/sdd/bin/lib/workstream.cjs +7 -3
  123. package/sdd/bin/sdd-tools.cjs +184 -12
  124. package/sdd/contexts/dev.md +21 -0
  125. package/sdd/contexts/research.md +22 -0
  126. package/sdd/contexts/review.md +22 -0
  127. package/sdd/references/agent-contracts.md +79 -0
  128. package/sdd/references/ai-evals.md +156 -0
  129. package/sdd/references/ai-frameworks.md +186 -0
  130. package/sdd/references/artifact-types.md +113 -0
  131. package/sdd/references/common-bug-patterns.md +114 -0
  132. package/sdd/references/context-budget.md +49 -0
  133. package/sdd/references/continuation-format.md +25 -25
  134. package/sdd/references/domain-probes.md +125 -0
  135. package/sdd/references/few-shot-examples/plan-checker.md +73 -0
  136. package/sdd/references/few-shot-examples/verifier.md +109 -0
  137. package/sdd/references/gate-prompts.md +100 -0
  138. package/sdd/references/gates.md +70 -0
  139. package/sdd/references/git-integration.md +1 -1
  140. package/sdd/references/ios-scaffold.md +123 -0
  141. package/sdd/references/model-profile-resolution.md +2 -0
  142. package/sdd/references/model-profiles.md +24 -18
  143. package/sdd/references/planner-gap-closure.md +62 -0
  144. package/sdd/references/planner-reviews.md +39 -0
  145. package/sdd/references/planner-revision.md +87 -0
  146. package/sdd/references/planning-config.md +252 -0
  147. package/sdd/references/revision-loop.md +97 -0
  148. package/sdd/references/thinking-models-debug.md +44 -0
  149. package/sdd/references/thinking-models-execution.md +50 -0
  150. package/sdd/references/thinking-models-planning.md +62 -0
  151. package/sdd/references/thinking-models-research.md +50 -0
  152. package/sdd/references/thinking-models-verification.md +55 -0
  153. package/sdd/references/thinking-partner.md +96 -0
  154. package/sdd/references/ui-brand.md +4 -4
  155. package/sdd/references/universal-anti-patterns.md +63 -0
  156. package/sdd/references/verification-overrides.md +227 -0
  157. package/sdd/references/workstream-flag.md +56 -3
  158. package/sdd/templates/AI-SPEC.md +246 -0
  159. package/sdd/templates/DEBUG.md +1 -1
  160. package/sdd/templates/SECURITY.md +61 -0
  161. package/sdd/templates/UAT.md +4 -4
  162. package/sdd/templates/VALIDATION.md +4 -4
  163. package/sdd/templates/claude-md.md +32 -9
  164. package/sdd/templates/config.json +4 -0
  165. package/sdd/templates/debug-subagent-prompt.md +1 -1
  166. package/sdd/templates/dev-preferences.md +1 -1
  167. package/sdd/templates/discovery.md +2 -2
  168. package/sdd/templates/phase-prompt.md +1 -1
  169. package/sdd/templates/planner-subagent-prompt.md +3 -3
  170. package/sdd/templates/project.md +1 -1
  171. package/sdd/templates/research.md +1 -1
  172. package/sdd/templates/state.md +2 -2
  173. package/sdd/workflows/add-phase.md +8 -8
  174. package/sdd/workflows/add-tests.md +12 -9
  175. package/sdd/workflows/add-todo.md +5 -3
  176. package/sdd/workflows/ai-integration-phase.md +284 -0
  177. package/sdd/workflows/analyze-dependencies.md +96 -0
  178. package/sdd/workflows/audit-fix.md +157 -0
  179. package/sdd/workflows/audit-milestone.md +11 -11
  180. package/sdd/workflows/audit-uat.md +2 -2
  181. package/sdd/workflows/autonomous.md +195 -27
  182. package/sdd/workflows/check-todos.md +12 -10
  183. package/sdd/workflows/cleanup.md +2 -0
  184. package/sdd/workflows/code-review-fix.md +497 -0
  185. package/sdd/workflows/code-review.md +515 -0
  186. package/sdd/workflows/complete-milestone.md +56 -22
  187. package/sdd/workflows/diagnose-issues.md +10 -3
  188. package/sdd/workflows/discovery-phase.md +5 -3
  189. package/sdd/workflows/discuss-phase-assumptions.md +24 -6
  190. package/sdd/workflows/discuss-phase-power.md +291 -0
  191. package/sdd/workflows/discuss-phase.md +173 -21
  192. package/sdd/workflows/do.md +23 -21
  193. package/sdd/workflows/docs-update.md +1155 -0
  194. package/sdd/workflows/eval-review.md +155 -0
  195. package/sdd/workflows/execute-phase.md +594 -38
  196. package/sdd/workflows/execute-plan.md +67 -96
  197. package/sdd/workflows/explore.md +139 -0
  198. package/sdd/workflows/fast.md +5 -5
  199. package/sdd/workflows/forensics.md +2 -2
  200. package/sdd/workflows/health.md +4 -4
  201. package/sdd/workflows/help.md +122 -119
  202. package/sdd/workflows/import.md +276 -0
  203. package/sdd/workflows/inbox.md +387 -0
  204. package/sdd/workflows/insert-phase.md +7 -7
  205. package/sdd/workflows/list-phase-assumptions.md +4 -4
  206. package/sdd/workflows/list-workspaces.md +2 -2
  207. package/sdd/workflows/manager.md +35 -32
  208. package/sdd/workflows/map-codebase.md +7 -5
  209. package/sdd/workflows/milestone-summary.md +2 -2
  210. package/sdd/workflows/new-milestone.md +17 -9
  211. package/sdd/workflows/new-project.md +50 -25
  212. package/sdd/workflows/new-workspace.md +7 -5
  213. package/sdd/workflows/next.md +67 -11
  214. package/sdd/workflows/note.md +9 -7
  215. package/sdd/workflows/pause-work.md +75 -12
  216. package/sdd/workflows/plan-milestone-gaps.md +8 -8
  217. package/sdd/workflows/plan-phase.md +294 -42
  218. package/sdd/workflows/plant-seed.md +6 -3
  219. package/sdd/workflows/pr-branch.md +42 -14
  220. package/sdd/workflows/profile-user.md +9 -7
  221. package/sdd/workflows/progress.md +45 -45
  222. package/sdd/workflows/quick.md +195 -47
  223. package/sdd/workflows/remove-phase.md +6 -6
  224. package/sdd/workflows/remove-workspace.md +3 -1
  225. package/sdd/workflows/research-phase.md +2 -2
  226. package/sdd/workflows/resume-project.md +12 -12
  227. package/sdd/workflows/review.md +109 -9
  228. package/sdd/workflows/scan.md +102 -0
  229. package/sdd/workflows/secure-phase.md +166 -0
  230. package/sdd/workflows/session-report.md +2 -2
  231. package/sdd/workflows/settings.md +38 -12
  232. package/sdd/workflows/ship.md +21 -9
  233. package/sdd/workflows/stats.md +1 -1
  234. package/sdd/workflows/transition.md +23 -23
  235. package/sdd/workflows/ui-phase.md +15 -7
  236. package/sdd/workflows/ui-review.md +29 -4
  237. package/sdd/workflows/undo.md +314 -0
  238. package/sdd/workflows/update.md +171 -20
  239. package/sdd/workflows/validate-phase.md +6 -4
  240. package/sdd/workflows/verify-phase.md +210 -6
  241. package/sdd/workflows/verify-work.md +83 -9
  242. package/sdd/commands/sdd/workstreams.md +0 -63
@@ -4,7 +4,7 @@
4
4
 
5
5
  const fs = require('fs');
6
6
  const path = require('path');
7
- const { normalizePhaseName, findPhaseInternal, generateSlugInternal, normalizeMd, toPosixPath, output, error } = require('./core.cjs');
7
+ const { normalizePhaseName, findPhaseInternal, generateSlugInternal, normalizeMd, toPosixPath, planningDir, output, error } = require('./core.cjs');
8
8
  const { reconstructFrontmatter } = require('./frontmatter.cjs');
9
9
 
10
10
  function cmdTemplateSelect(cwd, planPath, raw) {
@@ -131,6 +131,10 @@ function cmdTemplateFill(cwd, templateType, options, raw) {
131
131
  must_haves: { truths: [], artifacts: [], key_links: [] },
132
132
  ...fields,
133
133
  };
134
+ const planBase = planningDir(cwd);
135
+ const projectRef = toPosixPath(path.relative(cwd, path.join(planBase, 'PROJECT.md')));
136
+ const roadmapRef = toPosixPath(path.relative(cwd, path.join(planBase, 'ROADMAP.md')));
137
+ const stateRef = toPosixPath(path.relative(cwd, path.join(planBase, 'STATE.md')));
134
138
  body = [
135
139
  `# Phase ${options.phase} Plan ${planNum}: [Title]`,
136
140
  '',
@@ -140,9 +144,9 @@ function cmdTemplateFill(cwd, templateType, options, raw) {
140
144
  '- **Output:** [Concrete deliverable]',
141
145
  '',
142
146
  '## Context',
143
- '@.planning/PROJECT.md',
144
- '@.planning/ROADMAP.md',
145
- '@.planning/STATE.md',
147
+ `@${projectRef}`,
148
+ `@${roadmapRef}`,
149
+ `@${stateRef}`,
146
150
  '',
147
151
  '## Tasks',
148
152
  '',
@@ -5,7 +5,7 @@
5
5
  const fs = require('fs');
6
6
  const path = require('path');
7
7
  const os = require('os');
8
- const { safeReadFile, loadConfig, normalizePhaseName, execGit, findPhaseInternal, getMilestoneInfo, stripShippedMilestones, extractCurrentMilestone, planningDir, planningRoot, output, error, checkAgentsInstalled } = require('./core.cjs');
8
+ const { safeReadFile, loadConfig, normalizePhaseName, escapeRegex, execGit, findPhaseInternal, getMilestoneInfo, stripShippedMilestones, extractCurrentMilestone, planningDir, output, error, checkAgentsInstalled, CONFIG_DEFAULTS } = require('./core.cjs');
9
9
  const { extractFrontmatter, parseMustHavesBlock } = require('./frontmatter.cjs');
10
10
  const { writeStateMd } = require('./state.cjs');
11
11
 
@@ -534,11 +534,10 @@ function cmdValidateHealth(cwd, options, raw) {
534
534
  }
535
535
 
536
536
  const planBase = planningDir(cwd);
537
- const planRoot = planningRoot(cwd);
538
- const projectPath = path.join(planRoot, 'PROJECT.md');
537
+ const projectPath = path.join(planBase, 'PROJECT.md');
539
538
  const roadmapPath = path.join(planBase, 'ROADMAP.md');
540
539
  const statePath = path.join(planBase, 'STATE.md');
541
- const configPath = path.join(planRoot, 'config.json');
540
+ const configPath = path.join(planBase, 'config.json');
542
541
  const phasesDir = path.join(planBase, 'phases');
543
542
 
544
543
  const errors = [];
@@ -556,7 +555,7 @@ function cmdValidateHealth(cwd, options, raw) {
556
555
 
557
556
  // ─── Check 1: .planning/ exists ───────────────────────────────────────────
558
557
  if (!fs.existsSync(planBase)) {
559
- addIssue('error', 'E001', '.planning/ directory not found', 'Run /sdd:new-project to initialize');
558
+ addIssue('error', 'E001', '.planning/ directory not found', 'Run /sdd-new-project to initialize');
560
559
  output({
561
560
  status: 'broken',
562
561
  errors,
@@ -569,7 +568,7 @@ function cmdValidateHealth(cwd, options, raw) {
569
568
 
570
569
  // ─── Check 2: PROJECT.md exists and has required sections ─────────────────
571
570
  if (!fs.existsSync(projectPath)) {
572
- addIssue('error', 'E002', 'PROJECT.md not found', 'Run /sdd:new-project to create');
571
+ addIssue('error', 'E002', 'PROJECT.md not found', 'Run /sdd-new-project to create');
573
572
  } else {
574
573
  const content = fs.readFileSync(projectPath, 'utf-8');
575
574
  const requiredSections = ['## What This Is', '## Core Value', '## Requirements'];
@@ -582,12 +581,12 @@ function cmdValidateHealth(cwd, options, raw) {
582
581
 
583
582
  // ─── Check 3: ROADMAP.md exists ───────────────────────────────────────────
584
583
  if (!fs.existsSync(roadmapPath)) {
585
- addIssue('error', 'E003', 'ROADMAP.md not found', 'Run /sdd:new-milestone to create roadmap');
584
+ addIssue('error', 'E003', 'ROADMAP.md not found', 'Run /sdd-new-milestone to create roadmap');
586
585
  }
587
586
 
588
587
  // ─── Check 4: STATE.md exists and references valid phases ─────────────────
589
588
  if (!fs.existsSync(statePath)) {
590
- addIssue('error', 'E004', 'STATE.md not found', 'Run /sdd:health --repair to regenerate', true);
589
+ addIssue('error', 'E004', 'STATE.md not found', 'Run /sdd-health --repair to regenerate', true);
591
590
  repairs.push('regenerateState');
592
591
  } else {
593
592
  const stateContent = fs.readFileSync(statePath, 'utf-8');
@@ -614,7 +613,7 @@ function cmdValidateHealth(cwd, options, raw) {
614
613
  'warning',
615
614
  'W002',
616
615
  `STATE.md references phase ${ref}, but only phases ${[...diskPhases].sort().join(', ')} exist`,
617
- 'Review STATE.md manually before changing it; /sdd:health --repair will not overwrite an existing STATE.md for phase mismatches'
616
+ 'Review STATE.md manually before changing it; /sdd-health --repair will not overwrite an existing STATE.md for phase mismatches'
618
617
  );
619
618
  }
620
619
  }
@@ -623,7 +622,7 @@ function cmdValidateHealth(cwd, options, raw) {
623
622
 
624
623
  // ─── Check 5: config.json valid JSON + valid schema ───────────────────────
625
624
  if (!fs.existsSync(configPath)) {
626
- addIssue('warning', 'W003', 'config.json not found', 'Run /sdd:health --repair to create with defaults', true);
625
+ addIssue('warning', 'W003', 'config.json not found', 'Run /sdd-health --repair to create with defaults', true);
627
626
  repairs.push('createConfig');
628
627
  } else {
629
628
  try {
@@ -635,7 +634,7 @@ function cmdValidateHealth(cwd, options, raw) {
635
634
  addIssue('warning', 'W004', `config.json: invalid model_profile "${parsed.model_profile}"`, `Valid values: ${validProfiles.join(', ')}`);
636
635
  }
637
636
  } catch (err) {
638
- addIssue('error', 'E005', `config.json: JSON parse error - ${err.message}`, 'Run /sdd:health --repair to reset to defaults', true);
637
+ addIssue('error', 'E005', `config.json: JSON parse error - ${err.message}`, 'Run /sdd-health --repair to reset to defaults', true);
639
638
  repairs.push('resetConfig');
640
639
  }
641
640
  }
@@ -646,9 +645,13 @@ function cmdValidateHealth(cwd, options, raw) {
646
645
  const configRaw = fs.readFileSync(configPath, 'utf-8');
647
646
  const configParsed = JSON.parse(configRaw);
648
647
  if (configParsed.workflow && configParsed.workflow.nyquist_validation === undefined) {
649
- addIssue('warning', 'W008', 'config.json: workflow.nyquist_validation absent (defaults to enabled but agents may skip)', 'Run /sdd:health --repair to add key', true);
648
+ addIssue('warning', 'W008', 'config.json: workflow.nyquist_validation absent (defaults to enabled but agents may skip)', 'Run /sdd-health --repair to add key', true);
650
649
  if (!repairs.includes('addNyquistKey')) repairs.push('addNyquistKey');
651
650
  }
651
+ if (configParsed.workflow && configParsed.workflow.ai_integration_phase === undefined) {
652
+ addIssue('warning', 'W016', 'config.json: workflow.ai_integration_phase absent (defaults to enabled — run /sdd-ai-integration-phase before planning AI system phases)', 'Run /sdd-health --repair to add key', true);
653
+ if (!repairs.includes('addAiIntegrationPhaseKey')) repairs.push('addAiIntegrationPhaseKey');
654
+ }
652
655
  } catch { /* intentionally empty */ }
653
656
  }
654
657
 
@@ -693,7 +696,7 @@ function cmdValidateHealth(cwd, options, raw) {
693
696
  const researchFile = phaseFiles.find(f => f.endsWith('-RESEARCH.md'));
694
697
  const researchContent = fs.readFileSync(path.join(phasesDir, e.name, researchFile), 'utf-8');
695
698
  if (researchContent.includes('## Validation Architecture')) {
696
- addIssue('warning', 'W009', `Phase ${e.name}: has Validation Architecture in RESEARCH.md but no VALIDATION.md`, 'Re-run /sdd:plan-phase with --research to regenerate');
699
+ addIssue('warning', 'W009', `Phase ${e.name}: has Validation Architecture in RESEARCH.md but no VALIDATION.md`, 'Re-run /sdd-plan-phase with --research to regenerate');
697
700
  }
698
701
  }
699
702
  }
@@ -740,10 +743,24 @@ function cmdValidateHealth(cwd, options, raw) {
740
743
  }
741
744
  } catch { /* intentionally empty */ }
742
745
 
746
+ // Build a set of phases explicitly marked not-yet-started in the ROADMAP
747
+ // summary list (- [ ] **Phase N:**). These phases are intentionally absent
748
+ // from disk -- W006 must not fire for them (#2009).
749
+ const notStartedPhases = new Set();
750
+ const uncheckedPattern = /-\s*\[\s\]\s*\*{0,2}Phase\s+(\d+[A-Z]?(?:\.\d+)*)[:\s*]/gi;
751
+ let um;
752
+ while ((um = uncheckedPattern.exec(roadmapContent)) !== null) {
753
+ notStartedPhases.add(um[1]);
754
+ // Also add zero-padded variant so 1 and 01 both match
755
+ notStartedPhases.add(String(parseInt(um[1], 10)).padStart(2, '0'));
756
+ }
757
+
743
758
  // Phases in ROADMAP but not on disk
744
759
  for (const p of roadmapPhases) {
745
760
  const padded = String(parseInt(p, 10)).padStart(2, '0');
746
761
  if (!diskPhases.has(p) && !diskPhases.has(padded)) {
762
+ // Skip phases explicitly flagged as not-yet-started in the summary list
763
+ if (notStartedPhases.has(p) || notStartedPhases.has(padded)) continue;
747
764
  addIssue('warning', 'W006', `Phase ${p} in ROADMAP.md but no directory on disk`, 'Create phase directory or remove from roadmap');
748
765
  }
749
766
  }
@@ -757,6 +774,71 @@ function cmdValidateHealth(cwd, options, raw) {
757
774
  }
758
775
  }
759
776
 
777
+ // ─── Check 9: STATE.md / ROADMAP.md cross-validation ─────────────────────
778
+ if (fs.existsSync(statePath) && fs.existsSync(roadmapPath)) {
779
+ try {
780
+ const stateContent = fs.readFileSync(statePath, 'utf-8');
781
+ const roadmapContentFull = fs.readFileSync(roadmapPath, 'utf-8');
782
+
783
+ // Extract current phase from STATE.md
784
+ const currentPhaseMatch = stateContent.match(/\*\*Current Phase:\*\*\s*(\S+)/i) ||
785
+ stateContent.match(/Current Phase:\s*(\S+)/i);
786
+ if (currentPhaseMatch) {
787
+ const statePhase = currentPhaseMatch[1].replace(/^0+/, '');
788
+ // Check if ROADMAP shows this phase as already complete
789
+ const phaseCheckboxRe = new RegExp(`-\\s*\\[x\\].*Phase\\s+0*${escapeRegex(statePhase)}[:\\s]`, 'i');
790
+ if (phaseCheckboxRe.test(roadmapContentFull)) {
791
+ // STATE says "current" but ROADMAP says "complete" — divergence
792
+ const stateStatus = stateContent.match(/\*\*Status:\*\*\s*(.+)/i);
793
+ const statusVal = stateStatus ? stateStatus[1].trim().toLowerCase() : '';
794
+ if (statusVal !== 'complete' && statusVal !== 'done') {
795
+ addIssue('warning', 'W011',
796
+ `STATE.md says current phase is ${statePhase} (status: ${statusVal || 'unknown'}) but ROADMAP.md shows it as [x] complete — state files may be out of sync`,
797
+ 'Run /sdd-progress to re-derive current position, or manually update STATE.md');
798
+ }
799
+ }
800
+ }
801
+ } catch { /* intentionally empty — cross-validation is advisory */ }
802
+ }
803
+
804
+ // ─── Check 10: Config field validation ────────────────────────────────────
805
+ if (fs.existsSync(configPath)) {
806
+ try {
807
+ const configRaw = fs.readFileSync(configPath, 'utf-8');
808
+ const configParsed = JSON.parse(configRaw);
809
+
810
+ // Validate branching_strategy
811
+ const validStrategies = ['none', 'phase', 'milestone'];
812
+ if (configParsed.branching_strategy && !validStrategies.includes(configParsed.branching_strategy)) {
813
+ addIssue('warning', 'W012',
814
+ `config.json: invalid branching_strategy "${configParsed.branching_strategy}"`,
815
+ `Valid values: ${validStrategies.join(', ')}`);
816
+ }
817
+
818
+ // Validate context_window is a positive integer
819
+ if (configParsed.context_window !== undefined) {
820
+ const cw = configParsed.context_window;
821
+ if (typeof cw !== 'number' || cw <= 0 || !Number.isInteger(cw)) {
822
+ addIssue('warning', 'W013',
823
+ `config.json: context_window should be a positive integer, got "${cw}"`,
824
+ 'Set to 200000 (default) or 1000000 (for 1M models)');
825
+ }
826
+ }
827
+
828
+ // Validate branch templates have required placeholders
829
+ if (configParsed.phase_branch_template && !configParsed.phase_branch_template.includes('{phase}')) {
830
+ addIssue('warning', 'W014',
831
+ 'config.json: phase_branch_template missing {phase} placeholder',
832
+ 'Template must include {phase} for phase number substitution');
833
+ }
834
+ if (configParsed.milestone_branch_template && !configParsed.milestone_branch_template.includes('{milestone}')) {
835
+ addIssue('warning', 'W015',
836
+ 'config.json: milestone_branch_template missing {milestone} placeholder',
837
+ 'Template must include {milestone} for version substitution');
838
+ }
839
+ } catch { /* parse error already caught in Check 5 */ }
840
+ }
841
+
760
842
  // ─── Perform repairs if requested ─────────────────────────────────────────
761
843
  const repairActions = [];
762
844
  if (options.repair && repairs.length > 0) {
@@ -766,21 +848,21 @@ function cmdValidateHealth(cwd, options, raw) {
766
848
  case 'createConfig':
767
849
  case 'resetConfig': {
768
850
  const defaults = {
769
- model_profile: 'balanced',
770
- commit_docs: true,
771
- search_gitignored: false,
772
- branching_strategy: 'none',
773
- phase_branch_template: 'sdd/phase-{phase}-{slug}',
774
- milestone_branch_template: 'sdd/{milestone}-{slug}',
775
- quick_branch_template: null,
851
+ model_profile: CONFIG_DEFAULTS.model_profile,
852
+ commit_docs: CONFIG_DEFAULTS.commit_docs,
853
+ search_gitignored: CONFIG_DEFAULTS.search_gitignored,
854
+ branching_strategy: CONFIG_DEFAULTS.branching_strategy,
855
+ phase_branch_template: CONFIG_DEFAULTS.phase_branch_template,
856
+ milestone_branch_template: CONFIG_DEFAULTS.milestone_branch_template,
857
+ quick_branch_template: CONFIG_DEFAULTS.quick_branch_template,
776
858
  workflow: {
777
- research: true,
778
- plan_check: true,
779
- verifier: true,
780
- nyquist_validation: true,
859
+ research: CONFIG_DEFAULTS.research,
860
+ plan_check: CONFIG_DEFAULTS.plan_checker,
861
+ verifier: CONFIG_DEFAULTS.verifier,
862
+ nyquist_validation: CONFIG_DEFAULTS.nyquist_validation,
781
863
  },
782
- parallelization: true,
783
- brave_search: false,
864
+ parallelization: CONFIG_DEFAULTS.parallelization,
865
+ brave_search: CONFIG_DEFAULTS.brave_search,
784
866
  };
785
867
  fs.writeFileSync(configPath, JSON.stringify(defaults, null, 2), 'utf-8');
786
868
  repairActions.push({ action: repair, success: true, path: 'config.json' });
@@ -796,15 +878,18 @@ function cmdValidateHealth(cwd, options, raw) {
796
878
  }
797
879
  // Generate minimal STATE.md from ROADMAP.md structure
798
880
  const milestone = getMilestoneInfo(cwd);
881
+ const projectRef = path
882
+ .relative(cwd, path.join(planningDir(cwd), 'PROJECT.md'))
883
+ .split(path.sep).join('/');
799
884
  let stateContent = `# Session State\n\n`;
800
885
  stateContent += `## Project Reference\n\n`;
801
- stateContent += `See: .planning/PROJECT.md\n\n`;
886
+ stateContent += `See: ${projectRef}\n\n`;
802
887
  stateContent += `## Position\n\n`;
803
888
  stateContent += `**Milestone:** ${milestone.version} ${milestone.name}\n`;
804
889
  stateContent += `**Current phase:** (determining...)\n`;
805
890
  stateContent += `**Status:** Resuming\n\n`;
806
891
  stateContent += `## Session Log\n\n`;
807
- stateContent += `- ${new Date().toISOString().split('T')[0]}: STATE.md regenerated by /sdd:health --repair\n`;
892
+ stateContent += `- ${new Date().toISOString().split('T')[0]}: STATE.md regenerated by /sdd-health --repair\n`;
808
893
  writeStateMd(statePath, stateContent, cwd);
809
894
  repairActions.push({ action: repair, success: true, path: 'STATE.md' });
810
895
  break;
@@ -826,6 +911,23 @@ function cmdValidateHealth(cwd, options, raw) {
826
911
  }
827
912
  break;
828
913
  }
914
+ case 'addAiIntegrationPhaseKey': {
915
+ if (fs.existsSync(configPath)) {
916
+ try {
917
+ const configRaw = fs.readFileSync(configPath, 'utf-8');
918
+ const configParsed = JSON.parse(configRaw);
919
+ if (!configParsed.workflow) configParsed.workflow = {};
920
+ if (configParsed.workflow.ai_integration_phase === undefined) {
921
+ configParsed.workflow.ai_integration_phase = true;
922
+ fs.writeFileSync(configPath, JSON.stringify(configParsed, null, 2), 'utf-8');
923
+ }
924
+ repairActions.push({ action: repair, success: true, path: 'config.json' });
925
+ } catch (err) {
926
+ repairActions.push({ action: repair, success: false, error: err.message });
927
+ }
928
+ }
929
+ break;
930
+ }
829
931
  }
830
932
  } catch (err) {
831
933
  repairActions.push({ action: repair, success: false, error: err.message });
@@ -874,6 +976,84 @@ function cmdValidateAgents(cwd, raw) {
874
976
  }, raw);
875
977
  }
876
978
 
979
+ // ─── Schema Drift Detection ──────────────────────────────────────────────────
980
+
981
+ function cmdVerifySchemaDrift(cwd, phaseArg, skipFlag, raw) {
982
+ const { detectSchemaFiles, checkSchemaDrift } = require('./schema-detect.cjs');
983
+
984
+ if (!phaseArg) {
985
+ error('Usage: verify schema-drift <phase> [--skip]');
986
+ return;
987
+ }
988
+
989
+ // Find phase directory
990
+ const pDir = planningDir(cwd);
991
+ const phasesDir = path.join(pDir, 'phases');
992
+ if (!fs.existsSync(phasesDir)) {
993
+ output({ drift_detected: false, blocking: false, message: 'No phases directory' }, raw);
994
+ return;
995
+ }
996
+
997
+ // Find matching phase directory
998
+ let phaseDir = null;
999
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
1000
+ for (const entry of entries) {
1001
+ if (entry.isDirectory() && entry.name.includes(phaseArg)) {
1002
+ phaseDir = path.join(phasesDir, entry.name);
1003
+ break;
1004
+ }
1005
+ }
1006
+
1007
+ // Also try exact match
1008
+ if (!phaseDir) {
1009
+ const exact = path.join(phasesDir, phaseArg);
1010
+ if (fs.existsSync(exact)) phaseDir = exact;
1011
+ }
1012
+
1013
+ if (!phaseDir) {
1014
+ output({ drift_detected: false, blocking: false, message: `Phase directory not found: ${phaseArg}` }, raw);
1015
+ return;
1016
+ }
1017
+
1018
+ // Collect files_modified from all PLAN.md files in the phase
1019
+ const allFiles = [];
1020
+ const planFiles = fs.readdirSync(phaseDir).filter(f => f.endsWith('-PLAN.md'));
1021
+ for (const pf of planFiles) {
1022
+ const content = fs.readFileSync(path.join(phaseDir, pf), 'utf-8');
1023
+ // Extract files_modified from frontmatter
1024
+ const fmMatch = content.match(/files_modified:\s*\[([^\]]*)\]/);
1025
+ if (fmMatch) {
1026
+ const files = fmMatch[1].split(',').map(f => f.trim()).filter(Boolean);
1027
+ allFiles.push(...files);
1028
+ }
1029
+ }
1030
+
1031
+ // Collect execution log from SUMMARY.md files
1032
+ let executionLog = '';
1033
+ const summaryFiles = fs.readdirSync(phaseDir).filter(f => f.endsWith('-SUMMARY.md'));
1034
+ for (const sf of summaryFiles) {
1035
+ executionLog += fs.readFileSync(path.join(phaseDir, sf), 'utf-8') + '\n';
1036
+ }
1037
+
1038
+ // Also check git commit messages for push evidence
1039
+ const gitLog = execGit(cwd, ['log', '--oneline', '--all', '-50']);
1040
+ if (gitLog.exitCode === 0) {
1041
+ executionLog += '\n' + gitLog.stdout;
1042
+ }
1043
+
1044
+ const result = checkSchemaDrift(allFiles, executionLog, { skipCheck: !!skipFlag });
1045
+
1046
+ output({
1047
+ drift_detected: result.driftDetected,
1048
+ blocking: result.blocking,
1049
+ schema_files: result.schemaFiles,
1050
+ orms: result.orms,
1051
+ unpushed_orms: result.unpushedOrms,
1052
+ message: result.message,
1053
+ skipped: result.skipped || false,
1054
+ }, raw);
1055
+ }
1056
+
877
1057
  module.exports = {
878
1058
  cmdVerifySummary,
879
1059
  cmdVerifyPlanStructure,
@@ -885,4 +1065,5 @@ module.exports = {
885
1065
  cmdValidateConsistency,
886
1066
  cmdValidateHealth,
887
1067
  cmdValidateAgents,
1068
+ cmdVerifySchemaDrift,
888
1069
  };
@@ -78,7 +78,7 @@ function cmdWorkstreamCreate(cwd, name, options, raw) {
78
78
 
79
79
  const baseDir = planningRoot(cwd);
80
80
  if (!fs.existsSync(baseDir)) {
81
- error('.planning/ directory not found — run /sdd:new-project first');
81
+ error('.planning/ directory not found — run /sdd-new-project first');
82
82
  }
83
83
 
84
84
  const wsRoot = path.join(baseDir, 'workstreams');
@@ -339,9 +339,13 @@ function cmdWorkstreamComplete(cwd, name, options, raw) {
339
339
  // ─── Active Workstream Commands ──────────────────────────────────────────────
340
340
 
341
341
  function cmdWorkstreamSet(cwd, name, raw) {
342
- if (!name) {
342
+ if (!name || name === '--clear') {
343
+ if (name !== '--clear') {
344
+ error('Workstream name required. Usage: workstream set <name> (or workstream set --clear to unset)');
345
+ }
346
+ const previous = getActiveWorkstream(cwd);
343
347
  setActiveWorkstream(cwd, null);
344
- output({ active: null, cleared: true }, raw);
348
+ output({ active: null, cleared: true, previous: previous || null }, raw);
345
349
  return;
346
350
  }
347
351