@ktpartners/dgs-platform 2.6.2

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 (256) hide show
  1. package/LICENSE +38 -0
  2. package/README.md +851 -0
  3. package/agents/dgs-codebase-cross-analyzer.md +183 -0
  4. package/agents/dgs-codebase-mapper.md +782 -0
  5. package/agents/dgs-codebase-synthesizer.md +156 -0
  6. package/agents/dgs-debugger.md +1256 -0
  7. package/agents/dgs-executor.md +550 -0
  8. package/agents/dgs-integration-checker.md +481 -0
  9. package/agents/dgs-nyquist-auditor.md +178 -0
  10. package/agents/dgs-phase-researcher.md +563 -0
  11. package/agents/dgs-phase-verifier.md +450 -0
  12. package/agents/dgs-plan-checker.md +708 -0
  13. package/agents/dgs-planner.md +1324 -0
  14. package/agents/dgs-project-researcher.md +631 -0
  15. package/agents/dgs-research-synthesizer.md +249 -0
  16. package/agents/dgs-roadmapper.md +652 -0
  17. package/agents/dgs-verifier.md +607 -0
  18. package/bin/install.js +2073 -0
  19. package/commands/dgs/add-doc.md +45 -0
  20. package/commands/dgs/add-idea.md +38 -0
  21. package/commands/dgs/add-phase.md +43 -0
  22. package/commands/dgs/add-repo.md +54 -0
  23. package/commands/dgs/add-tests.md +41 -0
  24. package/commands/dgs/add-todo.md +47 -0
  25. package/commands/dgs/approve-spec.md +38 -0
  26. package/commands/dgs/audit-milestone.md +36 -0
  27. package/commands/dgs/audit-phase.md +37 -0
  28. package/commands/dgs/cancel-job.md +23 -0
  29. package/commands/dgs/capture-principle.md +143 -0
  30. package/commands/dgs/check-todos.md +45 -0
  31. package/commands/dgs/cleanup.md +18 -0
  32. package/commands/dgs/complete-milestone.md +136 -0
  33. package/commands/dgs/complete-project.md +70 -0
  34. package/commands/dgs/consolidate-ideas.md +50 -0
  35. package/commands/dgs/create-milestone-job.md +37 -0
  36. package/commands/dgs/debug.md +164 -0
  37. package/commands/dgs/develop-idea.md +53 -0
  38. package/commands/dgs/discuss-idea.md +41 -0
  39. package/commands/dgs/discuss-phase.md +83 -0
  40. package/commands/dgs/execute-phase.md +41 -0
  41. package/commands/dgs/fast.md +38 -0
  42. package/commands/dgs/find-related-ideas.md +43 -0
  43. package/commands/dgs/health.md +28 -0
  44. package/commands/dgs/help.md +22 -0
  45. package/commands/dgs/import-spec.md +36 -0
  46. package/commands/dgs/init-product.md +28 -0
  47. package/commands/dgs/insert-phase.md +32 -0
  48. package/commands/dgs/join-discord.md +18 -0
  49. package/commands/dgs/list-docs.md +40 -0
  50. package/commands/dgs/list-ideas.md +42 -0
  51. package/commands/dgs/list-jobs.md +22 -0
  52. package/commands/dgs/list-phase-assumptions.md +46 -0
  53. package/commands/dgs/list-projects.md +57 -0
  54. package/commands/dgs/list-specs.md +40 -0
  55. package/commands/dgs/map-codebase.md +92 -0
  56. package/commands/dgs/new-milestone.md +44 -0
  57. package/commands/dgs/new-project.md +42 -0
  58. package/commands/dgs/node-repair.md +26 -0
  59. package/commands/dgs/overlap-check.md +20 -0
  60. package/commands/dgs/pause-work.md +38 -0
  61. package/commands/dgs/plan-milestone-gaps.md +34 -0
  62. package/commands/dgs/plan-phase.md +44 -0
  63. package/commands/dgs/progress.md +24 -0
  64. package/commands/dgs/quick.md +41 -0
  65. package/commands/dgs/reactivate-project.md +70 -0
  66. package/commands/dgs/reapply-patches.md +110 -0
  67. package/commands/dgs/refine-spec.md +38 -0
  68. package/commands/dgs/reject-idea.md +43 -0
  69. package/commands/dgs/remove-doc.md +44 -0
  70. package/commands/dgs/remove-phase.md +31 -0
  71. package/commands/dgs/remove-repo.md +69 -0
  72. package/commands/dgs/research-idea.md +43 -0
  73. package/commands/dgs/research-phase.md +189 -0
  74. package/commands/dgs/restore-idea.md +45 -0
  75. package/commands/dgs/resume-work.md +40 -0
  76. package/commands/dgs/rollback-job.md +24 -0
  77. package/commands/dgs/run-job.md +35 -0
  78. package/commands/dgs/search.md +40 -0
  79. package/commands/dgs/set-profile.md +34 -0
  80. package/commands/dgs/settings.md +38 -0
  81. package/commands/dgs/switch-project.md +58 -0
  82. package/commands/dgs/undo-consolidation.md +42 -0
  83. package/commands/dgs/update-idea.md +44 -0
  84. package/commands/dgs/update.md +37 -0
  85. package/commands/dgs/validate-phase.md +35 -0
  86. package/commands/dgs/verify-work.md +39 -0
  87. package/commands/dgs/write-spec.md +49 -0
  88. package/deliver-great-systems/.planning/phases/09-backend-wiring-and-error-handling/09-01-SUMMARY.md +84 -0
  89. package/deliver-great-systems/.planning/phases/09-backend-wiring-and-error-handling/09-02-SUMMARY.md +86 -0
  90. package/deliver-great-systems/.planning/phases/10-v1-to-v2-migration-flow/10-01-SUMMARY.md +85 -0
  91. package/deliver-great-systems/bin/dgs-tools.cjs +1444 -0
  92. package/deliver-great-systems/bin/lib/auto-test.cjs +1365 -0
  93. package/deliver-great-systems/bin/lib/commands.cjs +570 -0
  94. package/deliver-great-systems/bin/lib/config.cjs +417 -0
  95. package/deliver-great-systems/bin/lib/conflict-agent.cjs +1063 -0
  96. package/deliver-great-systems/bin/lib/conflict-agent.test.cjs +554 -0
  97. package/deliver-great-systems/bin/lib/context.cjs +929 -0
  98. package/deliver-great-systems/bin/lib/context.test.cjs +693 -0
  99. package/deliver-great-systems/bin/lib/core.cjs +744 -0
  100. package/deliver-great-systems/bin/lib/core.test.cjs +822 -0
  101. package/deliver-great-systems/bin/lib/docs.cjs +919 -0
  102. package/deliver-great-systems/bin/lib/docs.test.cjs +211 -0
  103. package/deliver-great-systems/bin/lib/execution.cjs +705 -0
  104. package/deliver-great-systems/bin/lib/execution.test.cjs +1472 -0
  105. package/deliver-great-systems/bin/lib/frontmatter.cjs +324 -0
  106. package/deliver-great-systems/bin/lib/ideas.cjs +1406 -0
  107. package/deliver-great-systems/bin/lib/ideas.test.cjs +1417 -0
  108. package/deliver-great-systems/bin/lib/identity.cjs +125 -0
  109. package/deliver-great-systems/bin/lib/init.cjs +1114 -0
  110. package/deliver-great-systems/bin/lib/init.test.cjs +1271 -0
  111. package/deliver-great-systems/bin/lib/jobs.cjs +2015 -0
  112. package/deliver-great-systems/bin/lib/jobs.test.cjs +2619 -0
  113. package/deliver-great-systems/bin/lib/merge-conflicts.cjs +654 -0
  114. package/deliver-great-systems/bin/lib/merge-conflicts.test.cjs +370 -0
  115. package/deliver-great-systems/bin/lib/migration.cjs +352 -0
  116. package/deliver-great-systems/bin/lib/migration.test.cjs +582 -0
  117. package/deliver-great-systems/bin/lib/milestone.cjs +243 -0
  118. package/deliver-great-systems/bin/lib/overlap.cjs +437 -0
  119. package/deliver-great-systems/bin/lib/overlap.test.cjs +747 -0
  120. package/deliver-great-systems/bin/lib/path-audit.test.cjs +384 -0
  121. package/deliver-great-systems/bin/lib/paths.cjs +144 -0
  122. package/deliver-great-systems/bin/lib/paths.test.cjs +486 -0
  123. package/deliver-great-systems/bin/lib/phase.cjs +910 -0
  124. package/deliver-great-systems/bin/lib/projects.cjs +691 -0
  125. package/deliver-great-systems/bin/lib/projects.test.cjs +871 -0
  126. package/deliver-great-systems/bin/lib/repos.cjs +1432 -0
  127. package/deliver-great-systems/bin/lib/repos.test.cjs +1882 -0
  128. package/deliver-great-systems/bin/lib/roadmap.cjs +305 -0
  129. package/deliver-great-systems/bin/lib/search.cjs +570 -0
  130. package/deliver-great-systems/bin/lib/specs.cjs +1303 -0
  131. package/deliver-great-systems/bin/lib/state.cjs +893 -0
  132. package/deliver-great-systems/bin/lib/template.cjs +228 -0
  133. package/deliver-great-systems/bin/lib/test-helpers.cjs +291 -0
  134. package/deliver-great-systems/bin/lib/verify.cjs +796 -0
  135. package/deliver-great-systems/references/checkpoints.md +776 -0
  136. package/deliver-great-systems/references/conflict-resolution.md +66 -0
  137. package/deliver-great-systems/references/context-tiers.md +166 -0
  138. package/deliver-great-systems/references/continuation-format.md +249 -0
  139. package/deliver-great-systems/references/decimal-phase-calculation.md +67 -0
  140. package/deliver-great-systems/references/git-integration.md +250 -0
  141. package/deliver-great-systems/references/git-planning-commit.md +40 -0
  142. package/deliver-great-systems/references/model-profile-resolution.md +36 -0
  143. package/deliver-great-systems/references/model-profiles.md +95 -0
  144. package/deliver-great-systems/references/phase-argument-parsing.md +61 -0
  145. package/deliver-great-systems/references/planning-config.md +224 -0
  146. package/deliver-great-systems/references/questioning.md +162 -0
  147. package/deliver-great-systems/references/spec-review-loop.md +177 -0
  148. package/deliver-great-systems/references/tdd.md +265 -0
  149. package/deliver-great-systems/references/ui-brand.md +160 -0
  150. package/deliver-great-systems/references/verification-patterns.md +612 -0
  151. package/deliver-great-systems/templates/DEBUG.md +166 -0
  152. package/deliver-great-systems/templates/UAT.md +251 -0
  153. package/deliver-great-systems/templates/VALIDATION.md +95 -0
  154. package/deliver-great-systems/templates/claude-md.md +74 -0
  155. package/deliver-great-systems/templates/codebase/architecture.md +257 -0
  156. package/deliver-great-systems/templates/codebase/concerns.md +312 -0
  157. package/deliver-great-systems/templates/codebase/conventions.md +309 -0
  158. package/deliver-great-systems/templates/codebase/integrations.md +282 -0
  159. package/deliver-great-systems/templates/codebase/stack.md +188 -0
  160. package/deliver-great-systems/templates/codebase/structure.md +287 -0
  161. package/deliver-great-systems/templates/codebase/testing.md +482 -0
  162. package/deliver-great-systems/templates/config.json +38 -0
  163. package/deliver-great-systems/templates/context.md +354 -0
  164. package/deliver-great-systems/templates/continue-here.md +80 -0
  165. package/deliver-great-systems/templates/debug-subagent-prompt.md +93 -0
  166. package/deliver-great-systems/templates/discovery.md +148 -0
  167. package/deliver-great-systems/templates/milestone-archive.md +125 -0
  168. package/deliver-great-systems/templates/milestone.md +117 -0
  169. package/deliver-great-systems/templates/phase-prompt.md +615 -0
  170. package/deliver-great-systems/templates/planner-subagent-prompt.md +119 -0
  171. package/deliver-great-systems/templates/project.md +186 -0
  172. package/deliver-great-systems/templates/requirements.md +233 -0
  173. package/deliver-great-systems/templates/research-project/ARCHITECTURE.md +206 -0
  174. package/deliver-great-systems/templates/research-project/FEATURES.md +149 -0
  175. package/deliver-great-systems/templates/research-project/PITFALLS.md +202 -0
  176. package/deliver-great-systems/templates/research-project/STACK.md +122 -0
  177. package/deliver-great-systems/templates/research-project/SUMMARY.md +172 -0
  178. package/deliver-great-systems/templates/research.md +554 -0
  179. package/deliver-great-systems/templates/retrospective.md +54 -0
  180. package/deliver-great-systems/templates/roadmap.md +204 -0
  181. package/deliver-great-systems/templates/state.md +178 -0
  182. package/deliver-great-systems/templates/summary-complex.md +59 -0
  183. package/deliver-great-systems/templates/summary-minimal.md +41 -0
  184. package/deliver-great-systems/templates/summary-standard.md +48 -0
  185. package/deliver-great-systems/templates/summary.md +253 -0
  186. package/deliver-great-systems/templates/user-setup.md +313 -0
  187. package/deliver-great-systems/templates/verification-report.md +324 -0
  188. package/deliver-great-systems/workflows/add-doc.md +151 -0
  189. package/deliver-great-systems/workflows/add-idea.md +96 -0
  190. package/deliver-great-systems/workflows/add-phase.md +120 -0
  191. package/deliver-great-systems/workflows/add-tests.md +359 -0
  192. package/deliver-great-systems/workflows/add-todo.md +162 -0
  193. package/deliver-great-systems/workflows/approve-spec.md +194 -0
  194. package/deliver-great-systems/workflows/audit-milestone.md +364 -0
  195. package/deliver-great-systems/workflows/audit-phase.md +462 -0
  196. package/deliver-great-systems/workflows/cancel-job.md +108 -0
  197. package/deliver-great-systems/workflows/check-todos.md +181 -0
  198. package/deliver-great-systems/workflows/cleanup.md +247 -0
  199. package/deliver-great-systems/workflows/codereview.md +526 -0
  200. package/deliver-great-systems/workflows/complete-milestone.md +1298 -0
  201. package/deliver-great-systems/workflows/consolidate-ideas.md +365 -0
  202. package/deliver-great-systems/workflows/create-milestone-job.md +177 -0
  203. package/deliver-great-systems/workflows/develop-idea.md +544 -0
  204. package/deliver-great-systems/workflows/diagnose-issues.md +231 -0
  205. package/deliver-great-systems/workflows/discovery-phase.md +301 -0
  206. package/deliver-great-systems/workflows/discuss-idea.md +263 -0
  207. package/deliver-great-systems/workflows/discuss-phase.md +733 -0
  208. package/deliver-great-systems/workflows/execute-phase.md +571 -0
  209. package/deliver-great-systems/workflows/execute-plan.md +592 -0
  210. package/deliver-great-systems/workflows/find-related-ideas.md +271 -0
  211. package/deliver-great-systems/workflows/health.md +173 -0
  212. package/deliver-great-systems/workflows/help.md +997 -0
  213. package/deliver-great-systems/workflows/import-spec.md +381 -0
  214. package/deliver-great-systems/workflows/init-product.md +767 -0
  215. package/deliver-great-systems/workflows/insert-phase.md +138 -0
  216. package/deliver-great-systems/workflows/list-docs.md +119 -0
  217. package/deliver-great-systems/workflows/list-ideas.md +154 -0
  218. package/deliver-great-systems/workflows/list-jobs.md +89 -0
  219. package/deliver-great-systems/workflows/list-phase-assumptions.md +192 -0
  220. package/deliver-great-systems/workflows/list-specs.md +101 -0
  221. package/deliver-great-systems/workflows/map-codebase.md +621 -0
  222. package/deliver-great-systems/workflows/new-milestone.md +591 -0
  223. package/deliver-great-systems/workflows/new-project.md +1113 -0
  224. package/deliver-great-systems/workflows/node-repair.md +94 -0
  225. package/deliver-great-systems/workflows/overlap-check.md +86 -0
  226. package/deliver-great-systems/workflows/pause-work.md +134 -0
  227. package/deliver-great-systems/workflows/plan-milestone-gaps.md +306 -0
  228. package/deliver-great-systems/workflows/plan-phase.md +698 -0
  229. package/deliver-great-systems/workflows/progress.md +386 -0
  230. package/deliver-great-systems/workflows/quick.md +845 -0
  231. package/deliver-great-systems/workflows/refine-spec.md +275 -0
  232. package/deliver-great-systems/workflows/reject-idea.md +109 -0
  233. package/deliver-great-systems/workflows/remove-doc.md +117 -0
  234. package/deliver-great-systems/workflows/remove-phase.md +163 -0
  235. package/deliver-great-systems/workflows/research-idea.md +325 -0
  236. package/deliver-great-systems/workflows/research-phase.md +81 -0
  237. package/deliver-great-systems/workflows/restore-idea.md +101 -0
  238. package/deliver-great-systems/workflows/resume-project.md +311 -0
  239. package/deliver-great-systems/workflows/rollback-job.md +130 -0
  240. package/deliver-great-systems/workflows/run-job.md +498 -0
  241. package/deliver-great-systems/workflows/search.md +130 -0
  242. package/deliver-great-systems/workflows/set-profile.md +83 -0
  243. package/deliver-great-systems/workflows/settings.md +470 -0
  244. package/deliver-great-systems/workflows/transition.md +563 -0
  245. package/deliver-great-systems/workflows/undo-consolidation.md +155 -0
  246. package/deliver-great-systems/workflows/update-idea.md +157 -0
  247. package/deliver-great-systems/workflows/update.md +242 -0
  248. package/deliver-great-systems/workflows/validate-phase.md +177 -0
  249. package/deliver-great-systems/workflows/verify-phase.md +253 -0
  250. package/deliver-great-systems/workflows/verify-work.md +671 -0
  251. package/deliver-great-systems/workflows/write-spec.md +450 -0
  252. package/hooks/dist/dgs-check-update.js +62 -0
  253. package/hooks/dist/dgs-context-monitor.js +141 -0
  254. package/hooks/dist/dgs-statusline.js +115 -0
  255. package/package.json +60 -0
  256. package/scripts/build-hooks.js +43 -0
@@ -0,0 +1,1444 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * DGS Tools — CLI utility for DGS workflow operations
5
+ *
6
+ * Replaces repetitive inline bash patterns across ~50 DGS command/workflow/agent files.
7
+ * Centralizes: config parsing, model resolution, phase lookup, git commits, summary verification.
8
+ *
9
+ * Usage: node dgs-tools.cjs <command> [args] [--raw]
10
+ *
11
+ * Atomic Commands:
12
+ * state load Load project config + state
13
+ * state update <field> <value> Update a STATE.md field
14
+ * state get [section] Get STATE.md content or section
15
+ * state patch --field val ... Batch update STATE.md fields
16
+ * state archive-quick-tasks Archive excess quick task rows to HISTORY.md
17
+ * resolve-model <agent-type> Get model for agent based on profile
18
+ * find-phase <phase> Find phase directory by number
19
+ * commit <message> [--files f1 f2] Commit planning docs
20
+ * verify-summary <path> Verify a SUMMARY.md file
21
+ * generate-slug <text> Convert text to URL-safe slug
22
+ * current-timestamp [format] Get timestamp (full|date|filename)
23
+ * list-todos [area] Count and enumerate pending todos
24
+ * verify-path-exists <path> Check file/directory existence
25
+ * config-ensure-section Initialize .planning/config.json
26
+ * review-config Load review config with defaults
27
+ * check-config-gitignore Check if config.json needs .gitignore
28
+ * history-digest Aggregate all SUMMARY.md data
29
+ * summary-extract <path> [--fields] Extract structured data from SUMMARY.md
30
+ * state-snapshot Structured parse of STATE.md
31
+ * phase-plan-index <phase> Index plans with waves and status
32
+ * websearch <query> Search web via Brave API (if configured)
33
+ * [--limit N] [--freshness day|week|month]
34
+ *
35
+ * Phase Operations:
36
+ * phase next-decimal <phase> Calculate next decimal phase number
37
+ * phase add <description> Append new phase to roadmap + create dir
38
+ * phase insert <after> <description> Insert decimal phase after existing
39
+ * phase remove <phase> [--force] Remove phase, renumber all subsequent
40
+ * phase complete <phase> Mark phase done, update state + roadmap
41
+ *
42
+ * Roadmap Operations:
43
+ * roadmap get-phase <phase> Extract phase section from ROADMAP.md
44
+ * roadmap analyze Full roadmap parse with disk status
45
+ * roadmap update-plan-progress <N> Update progress table row from disk (PLAN vs SUMMARY counts)
46
+ *
47
+ * Requirements Operations:
48
+ * requirements mark-complete <ids> Mark requirement IDs as complete in REQUIREMENTS.md
49
+ * Accepts: REQ-01,REQ-02 or REQ-01 REQ-02 or [REQ-01, REQ-02]
50
+ *
51
+ * Milestone Operations:
52
+ * milestone complete <version> Archive milestone, create MILESTONES.md
53
+ * [--name <name>]
54
+ * [--archive-phases] Move phase dirs to milestones/vX.Y-phases/
55
+ *
56
+ * Validation:
57
+ * validate consistency Check phase numbering, disk/roadmap sync
58
+ * validate health [--repair] Check .planning/ integrity, optionally repair
59
+ *
60
+ * Progress:
61
+ * progress [json|table|bar] Render progress in various formats
62
+ *
63
+ * Todos:
64
+ * todo complete <filename> Move todo from pending to completed
65
+ *
66
+ * Scaffolding:
67
+ * scaffold context --phase <N> Create CONTEXT.md template
68
+ * scaffold uat --phase <N> Create UAT.md template
69
+ * scaffold verification --phase <N> Create VERIFICATION.md template
70
+ * scaffold phase-dir --phase <N> Create phase directory
71
+ * --name <name>
72
+ *
73
+ * Context:
74
+ * context load-tier <name> Get file list for a context tier
75
+ * [--phase N] [--idea N] [--spec N] Scope-specific enrichment
76
+ *
77
+ * Frontmatter CRUD:
78
+ * frontmatter get <file> [--field k] Extract frontmatter as JSON
79
+ * frontmatter set <file> --field k Update single frontmatter field
80
+ * --value jsonVal
81
+ * frontmatter merge <file> Merge JSON into frontmatter
82
+ * --data '{json}'
83
+ * frontmatter validate <file> Validate required fields
84
+ * --schema plan|summary|verification
85
+ *
86
+ * Verification Suite:
87
+ * verify plan-structure <file> Check PLAN.md structure + tasks
88
+ * verify phase-completeness <phase> Check all plans have summaries
89
+ * verify references <file> Check @-refs + paths resolve
90
+ * verify commits <h1> [h2] ... Batch verify commit hashes
91
+ * verify artifacts <plan-file> Check must_haves.artifacts
92
+ * verify key-links <plan-file> Check must_haves.key_links
93
+ *
94
+ * Template Fill:
95
+ * template fill summary --phase N Create pre-filled SUMMARY.md
96
+ * [--plan M] [--name "..."]
97
+ * [--fields '{json}']
98
+ * template fill plan --phase N Create pre-filled PLAN.md
99
+ * [--plan M] [--type execute|tdd]
100
+ * [--wave N] [--fields '{json}']
101
+ * template fill verification Create pre-filled VERIFICATION.md
102
+ * --phase N [--fields '{json}']
103
+ *
104
+ * State Progression:
105
+ * state advance-plan Increment plan counter
106
+ * state record-metric --phase N Record execution metrics
107
+ * --plan M --duration Xmin
108
+ * [--tasks N] [--files N]
109
+ * state update-progress Recalculate progress bar
110
+ * state add-decision --summary "..." Add decision to STATE.md
111
+ * [--phase N] [--rationale "..."]
112
+ * state add-blocker --text "..." Add blocker
113
+ * state resolve-blocker --text "..." Remove blocker
114
+ * state record-session Update session continuity
115
+ * --stopped-at "..."
116
+ * [--resume-file path]
117
+ *
118
+ * Projects Operations:
119
+ * projects create <name> Create new project subfolder
120
+ * [--repos "repo1,repo2"]
121
+ * projects switch <name> Switch active project context
122
+ * projects list List all projects with status
123
+ * projects complete [--slug name] Mark project as completed
124
+ * projects regenerate Re-derive PROJECTS.md from disk
125
+ *
126
+ * Overlap Detection:
127
+ * overlap check Check for cross-project repo/file overlaps
128
+ *
129
+ * Merge Conflict Resolution:
130
+ * merge-conflicts detect Detect conflicted files after failed merge
131
+ * [--phase-dir <dir>]
132
+ * merge-conflicts context <file> Assemble resolution context for a file
133
+ * [--phase-dir <dir>]
134
+ * merge-conflicts resolved <file> Record resolution outcome
135
+ * --phase-dir <dir>
136
+ * --resolution '{json}'
137
+ * merge-conflicts summary Aggregate all resolutions
138
+ * --phase-dir <dir>
139
+ *
140
+ * Conflict Resolution Agent:
141
+ * conflict-agent run Run automated conflict resolution
142
+ * --phase-dir <dir>
143
+ * conflict-agent resolve-file <file> Resolve a single file (retry/escalation)
144
+ * --phase-dir <dir> [--hint <text>]
145
+ *
146
+ * Multi-Repo Commit:
147
+ * commit preflight <repo1> [repo2] Check repos are clean before execution
148
+ * commit detect-manual <repo> Detect if repo changes were manually resolved
149
+ * --files f1 f2 [--prior-sha SHA]
150
+ * commit --multi-repo Per-repo commit with project-prefixed messages
151
+ * --type <type> --project <slug>
152
+ * --phase <N> --plan <M>
153
+ * --desc <description>
154
+ * --repos <repo1,repo2>
155
+ * [--phase-dir <dir>] Phase directory for context
156
+ * [--retry --prior-results '[]'] Retry failed repos from prior commit
157
+ *
158
+ * Repo Operations:
159
+ * repos list List all registered repos as JSON
160
+ * repos add <path> Register a new repo
161
+ * [--name N] [--desc D]
162
+ * repos remove <name> Unregister a repo
163
+ * [--force]
164
+ * repos validate Check all repo paths exist on disk
165
+ * repos resolve <filepath> Resolve file path to owning repo
166
+ * repos init-product [name] Initialize product folder structure
167
+ * repos scan-tags <phase-dir> Scan plan files for <repos> tags
168
+ * repos auto-populate <plan-file> Auto-populate <repos> tags from <files> paths
169
+ * repos validate-consistency <plan> Validate <repos>/<files> consistency
170
+ * repos migrate <slug> Migrate v1 install to v2 structure
171
+ *
172
+ * Ideas Operations:
173
+ * ideas create --title T --body B Create new idea with auto-assigned ID
174
+ * [--tags "t1,t2"]
175
+ * ideas update --id N --field F Update idea field (title, body, tags)
176
+ * --value V
177
+ * ideas append-note --id N --note T Append timestamped note to idea
178
+ * ideas list [--state S] [--tag T] List ideas grouped by state
179
+ * [--orphan-check]
180
+ * ideas reject --id N [--reason R] Reject idea (move to rejected/)
181
+ * ideas restore --id N Restore idea to pending
182
+ * ideas move-state --id N --to S Move idea to target state
183
+ * ideas discuss-save --id N Save structured discussion entry
184
+ * --entry '{json}' JSON: { date, keyInsights, refinedProblem, refinedApproach, openQuestions, decision }
185
+ * ideas research-save --id N Save structured research log entry
186
+ * --entry '{json}' JSON: { date, summary, keyFindings, recommendation, documentLink, outcome }
187
+ * ideas find-related --id N Find ideas related to anchor idea by tag overlap
188
+ * [--threshold high|medium|low] Filter by minimum match level (default: medium)
189
+ * ideas undo-consolidation --id N Undo consolidation: restore sources, delete result
190
+ *
191
+ * Specs Operations:
192
+ * specs create --title T --body B [--source-document PATH] Create new spec
193
+ * [--source-ideas "f1,f2"]
194
+ * specs list [--status S] List all specs with status
195
+ * specs update-status --id N --status S Update spec status
196
+ * specs append-review --id N --entry T Append review history entry
197
+ * specs finalize --id N Finalize spec and move ideas to done
198
+ *
199
+ * Docs Operations:
200
+ * docs add --source <path> --scope <product|idea|spec> [--scope-id <id>] Add document to scope
201
+ * docs list [--scope <filter>] List all documents
202
+ * docs remove --scope <product|idea|spec> [--scope-id <id>] --slug <slug> Remove document
203
+ * docs move --slug <slug> --from-scope <scope> [--from-id <id>] --to-scope <scope> [--to-id <id>] Move document
204
+ * docs check-duplicate --scope <scope> [--scope-id <id>] --slug <slug> Check if slug exists
205
+ *
206
+ * Identity:
207
+ * identity resolve Resolve git identity (name + email)
208
+ *
209
+ * Jobs:
210
+ * jobs parse <file> Parse job file into structured JSON
211
+ * jobs update-step <file> <index> Update step status in job file
212
+ * <status> [--timestamp ts]
213
+ * [--error "msg"]
214
+ * jobs move <file> <target-dir> Move job file to target directory
215
+ * jobs insert-gap-fix-section Insert gap-fix section marker + steps
216
+ * <file> <after-index> <cycle>
217
+ * <version> <phases-json>
218
+ * jobs insert-phase-gap-fix Insert phase-level gap-fix steps
219
+ * <file> <after-index> <cycle>
220
+ * <phase-number>
221
+ * jobs create-milestone [version] Generate milestone job from roadmap
222
+ * [--no-check] Omit audit/complete steps
223
+ * jobs milestone-preview [version] Preview milestone job without writing
224
+ * [--no-check] Omit audit/complete steps
225
+ * jobs record-start-shas <file> Record starting commit SHAs into job file
226
+ * jobs rollback <version> Roll back code repos to pre-job SHAs
227
+ *
228
+ * Search Operations:
229
+ * search <query> [--flags] Search across ideas, specs, docs, projects
230
+ * [--ideas-only] [--specs-only] [--docs-only]
231
+ * [--include-rejected] [--tags "t1,t2"]
232
+ * [--max-per-type N]
233
+ *
234
+ * Compound Commands (workflow-specific initialization):
235
+ * init execute-phase <phase> All context for execute-phase workflow
236
+ * init plan-phase <phase> All context for plan-phase workflow
237
+ * init new-project All context for new-project workflow
238
+ * init new-milestone All context for new-milestone workflow
239
+ * init quick <description> All context for quick workflow
240
+ * init resume All context for resume-project workflow
241
+ * init verify-work <phase> All context for verify-work workflow
242
+ * init phase-op <phase> Generic phase operation context
243
+ * init todos [area] All context for todo workflows
244
+ * init milestone-op All context for milestone operations
245
+ * init map-codebase All context for map-codebase workflow
246
+ * init progress All context for progress workflow
247
+ */
248
+
249
+ const { error } = require('./lib/core.cjs');
250
+ const state = require('./lib/state.cjs');
251
+ const phase = require('./lib/phase.cjs');
252
+ const roadmap = require('./lib/roadmap.cjs');
253
+ const verify = require('./lib/verify.cjs');
254
+ const config = require('./lib/config.cjs');
255
+ const template = require('./lib/template.cjs');
256
+ const milestone = require('./lib/milestone.cjs');
257
+ const commands = require('./lib/commands.cjs');
258
+ const init = require('./lib/init.cjs');
259
+ const frontmatter = require('./lib/frontmatter.cjs');
260
+ const repos = require('./lib/repos.cjs');
261
+ const projects = require('./lib/projects.cjs');
262
+ const execution = require('./lib/execution.cjs');
263
+ const overlap = require('./lib/overlap.cjs');
264
+ const ideas = require('./lib/ideas.cjs');
265
+ const specs = require('./lib/specs.cjs');
266
+ const docs = require('./lib/docs.cjs');
267
+ const search = require('./lib/search.cjs');
268
+ const jobs = require('./lib/jobs.cjs');
269
+ const mergeConflicts = require('./lib/merge-conflicts.cjs');
270
+ const conflictAgent = require('./lib/conflict-agent.cjs');
271
+ const { requireGitIdentity, formatAuthorString, cmdIdentityResolve } = require('./lib/identity.cjs');
272
+
273
+ // ─── Identity Gate ────────────────────────────────────────────────────────────
274
+
275
+ /**
276
+ * Enforces git identity for write commands. Calls requireGitIdentity() and
277
+ * converts thrown errors into clean CLI error output via error().
278
+ * Read-only commands must NOT call this.
279
+ *
280
+ * @returns {string} Formatted author string (e.g., "Name <email>" or "Name")
281
+ */
282
+ function gateIdentity() {
283
+ try {
284
+ const identity = requireGitIdentity();
285
+ return formatAuthorString(identity);
286
+ } catch (e) {
287
+ error(e.message);
288
+ }
289
+ }
290
+
291
+ // ─── CLI Router ───────────────────────────────────────────────────────────────
292
+
293
+ async function main() {
294
+ const args = process.argv.slice(2);
295
+ const rawIndex = args.indexOf('--raw');
296
+ const raw = rawIndex !== -1;
297
+ if (rawIndex !== -1) args.splice(rawIndex, 1);
298
+
299
+ const command = args[0];
300
+ const cwd = process.cwd();
301
+
302
+ if (!command) {
303
+ error('Usage: dgs-tools <command> [args] [--raw]\nCommands: state, resolve-model, find-phase, commit, verify-summary, verify, frontmatter, template, generate-slug, current-timestamp, list-todos, verify-path-exists, config-ensure-section, repos, projects, overlap, merge-conflicts, conflict-agent, init');
304
+ }
305
+
306
+ switch (command) {
307
+ case 'state': {
308
+ const subcommand = args[1];
309
+ // Gate write subcommands
310
+ if (subcommand && subcommand !== 'load' && subcommand !== 'get') {
311
+ gateIdentity();
312
+ }
313
+ if (subcommand === 'update') {
314
+ state.cmdStateUpdate(cwd, args[2], args[3]);
315
+ } else if (subcommand === 'get') {
316
+ state.cmdStateGet(cwd, args[2], raw);
317
+ } else if (subcommand === 'patch') {
318
+ const patches = {};
319
+ for (let i = 2; i < args.length; i += 2) {
320
+ const key = args[i].replace(/^--/, '');
321
+ const value = args[i + 1];
322
+ if (key && value !== undefined) {
323
+ patches[key] = value;
324
+ }
325
+ }
326
+ state.cmdStatePatch(cwd, patches, raw);
327
+ } else if (subcommand === 'advance-plan') {
328
+ state.cmdStateAdvancePlan(cwd, raw);
329
+ } else if (subcommand === 'record-metric') {
330
+ const phaseIdx = args.indexOf('--phase');
331
+ const planIdx = args.indexOf('--plan');
332
+ const durationIdx = args.indexOf('--duration');
333
+ const tasksIdx = args.indexOf('--tasks');
334
+ const filesIdx = args.indexOf('--files');
335
+ state.cmdStateRecordMetric(cwd, {
336
+ phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null,
337
+ plan: planIdx !== -1 ? args[planIdx + 1] : null,
338
+ duration: durationIdx !== -1 ? args[durationIdx + 1] : null,
339
+ tasks: tasksIdx !== -1 ? args[tasksIdx + 1] : null,
340
+ files: filesIdx !== -1 ? args[filesIdx + 1] : null,
341
+ }, raw);
342
+ } else if (subcommand === 'update-progress') {
343
+ state.cmdStateUpdateProgress(cwd, raw);
344
+ } else if (subcommand === 'add-decision') {
345
+ const phaseIdx = args.indexOf('--phase');
346
+ const summaryIdx = args.indexOf('--summary');
347
+ const rationaleIdx = args.indexOf('--rationale');
348
+ state.cmdStateAddDecision(cwd, {
349
+ phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null,
350
+ summary: summaryIdx !== -1 ? args[summaryIdx + 1] : null,
351
+ rationale: rationaleIdx !== -1 ? args[rationaleIdx + 1] : '',
352
+ }, raw);
353
+ } else if (subcommand === 'add-blocker') {
354
+ const textIdx = args.indexOf('--text');
355
+ state.cmdStateAddBlocker(cwd, textIdx !== -1 ? args[textIdx + 1] : null, raw);
356
+ } else if (subcommand === 'resolve-blocker') {
357
+ const textIdx = args.indexOf('--text');
358
+ state.cmdStateResolveBlocker(cwd, textIdx !== -1 ? args[textIdx + 1] : null, raw);
359
+ } else if (subcommand === 'record-session') {
360
+ const stoppedIdx = args.indexOf('--stopped-at');
361
+ const resumeIdx = args.indexOf('--resume-file');
362
+ state.cmdStateRecordSession(cwd, {
363
+ stopped_at: stoppedIdx !== -1 ? args[stoppedIdx + 1] : null,
364
+ resume_file: resumeIdx !== -1 ? args[resumeIdx + 1] : 'None',
365
+ }, raw);
366
+ } else if (subcommand === 'archive-quick-tasks') {
367
+ state.cmdStateArchiveQuickTasks(cwd, raw);
368
+ } else {
369
+ state.cmdStateLoad(cwd, raw);
370
+ }
371
+ break;
372
+ }
373
+
374
+ case 'resolve-model': {
375
+ commands.cmdResolveModel(cwd, args[1], raw);
376
+ break;
377
+ }
378
+
379
+ case 'find-phase': {
380
+ phase.cmdFindPhase(cwd, args[1], raw);
381
+ break;
382
+ }
383
+
384
+ case 'commit': {
385
+ gateIdentity();
386
+ // Check for preflight subcommand
387
+ if (args[1] === 'preflight') {
388
+ const repoNames = args.slice(2);
389
+ execution.cmdCommitPreflight(cwd, repoNames, raw);
390
+ break;
391
+ }
392
+
393
+ // Check for detect-manual subcommand
394
+ if (args[1] === 'detect-manual') {
395
+ const repoName = args[2];
396
+ const filesIdx = args.indexOf('--files');
397
+ const expectedFiles = filesIdx !== -1 ? args.slice(filesIdx + 1).filter(a => !a.startsWith('--')) : [];
398
+ const priorShaIdx = args.indexOf('--prior-sha');
399
+ const priorSha = priorShaIdx !== -1 ? args[priorShaIdx + 1] : undefined;
400
+ const result = execution.detectManualResolution(cwd, repoName, expectedFiles, priorSha);
401
+ if (raw) {
402
+ console.log(JSON.stringify(result));
403
+ } else {
404
+ console.log(`Resolution: ${result.resolved ? 'YES' : 'NO'} (${result.reason})`);
405
+ }
406
+ break;
407
+ }
408
+
409
+ // Check for --multi-repo flag
410
+ const multiRepoIdx = args.indexOf('--multi-repo');
411
+ if (multiRepoIdx !== -1) {
412
+ const typeIdx = args.indexOf('--type');
413
+ const projectIdx = args.indexOf('--project');
414
+ const phaseIdx = args.indexOf('--phase');
415
+ const planIdx = args.indexOf('--plan');
416
+ const descIdx = args.indexOf('--desc');
417
+ const reposIdx = args.indexOf('--repos');
418
+ const retryIdx = args.indexOf('--retry');
419
+ const priorResultsIdx = args.indexOf('--prior-results');
420
+ const phaseDirIdx = args.indexOf('--phase-dir');
421
+ execution.cmdCommitMultiRepo(cwd, {
422
+ type: typeIdx !== -1 ? args[typeIdx + 1] : 'feat',
423
+ project: projectIdx !== -1 ? args[projectIdx + 1] : null,
424
+ phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null,
425
+ plan: planIdx !== -1 ? args[planIdx + 1] : null,
426
+ description: descIdx !== -1 ? args[descIdx + 1] : null,
427
+ repos: reposIdx !== -1 ? args[reposIdx + 1].split(',') : null,
428
+ retry: retryIdx !== -1,
429
+ priorResults: priorResultsIdx !== -1 ? JSON.parse(args[priorResultsIdx + 1]) : null,
430
+ phaseDir: phaseDirIdx !== -1 ? args[phaseDirIdx + 1] : null,
431
+ }, raw);
432
+ break;
433
+ }
434
+
435
+ // Existing single-repo commit logic
436
+ const amend = args.includes('--amend');
437
+ const message = args[1];
438
+ // Parse --files flag (collect args after --files, stopping at other flags)
439
+ const filesIndex = args.indexOf('--files');
440
+ const files = filesIndex !== -1 ? args.slice(filesIndex + 1).filter(a => !a.startsWith('--')) : [];
441
+ // Parse --phase-dir flag (available for context, passed through if supported)
442
+ const phaseDirIdx = args.indexOf('--phase-dir');
443
+ const phaseDir = phaseDirIdx !== -1 ? args[phaseDirIdx + 1] : null;
444
+ commands.cmdCommit(cwd, message, files, raw, amend);
445
+ break;
446
+ }
447
+
448
+ case 'verify-summary': {
449
+ const summaryPath = args[1];
450
+ const countIndex = args.indexOf('--check-count');
451
+ const checkCount = countIndex !== -1 ? parseInt(args[countIndex + 1], 10) : 2;
452
+ verify.cmdVerifySummary(cwd, summaryPath, checkCount, raw);
453
+ break;
454
+ }
455
+
456
+ case 'template': {
457
+ const subcommand = args[1];
458
+ // Gate write subcommand and capture author string
459
+ let author = null;
460
+ if (subcommand === 'fill') {
461
+ author = gateIdentity();
462
+ }
463
+ if (subcommand === 'select') {
464
+ template.cmdTemplateSelect(cwd, args[2], raw);
465
+ } else if (subcommand === 'fill') {
466
+ const templateType = args[2];
467
+ const phaseIdx = args.indexOf('--phase');
468
+ const planIdx = args.indexOf('--plan');
469
+ const nameIdx = args.indexOf('--name');
470
+ const typeIdx = args.indexOf('--type');
471
+ const waveIdx = args.indexOf('--wave');
472
+ const fieldsIdx = args.indexOf('--fields');
473
+ template.cmdTemplateFill(cwd, templateType, {
474
+ phase: phaseIdx !== -1 ? args[phaseIdx + 1] : null,
475
+ plan: planIdx !== -1 ? args[planIdx + 1] : null,
476
+ name: nameIdx !== -1 ? args[nameIdx + 1] : null,
477
+ type: typeIdx !== -1 ? args[typeIdx + 1] : 'execute',
478
+ wave: waveIdx !== -1 ? args[waveIdx + 1] : '1',
479
+ fields: fieldsIdx !== -1 ? JSON.parse(args[fieldsIdx + 1]) : {},
480
+ author,
481
+ }, raw);
482
+ } else {
483
+ error('Unknown template subcommand. Available: select, fill');
484
+ }
485
+ break;
486
+ }
487
+
488
+ case 'frontmatter': {
489
+ const subcommand = args[1];
490
+ const file = args[2];
491
+ // Gate write subcommands
492
+ if (subcommand === 'set' || subcommand === 'merge') {
493
+ gateIdentity();
494
+ }
495
+ if (subcommand === 'get') {
496
+ const fieldIdx = args.indexOf('--field');
497
+ frontmatter.cmdFrontmatterGet(cwd, file, fieldIdx !== -1 ? args[fieldIdx + 1] : null, raw);
498
+ } else if (subcommand === 'set') {
499
+ const fieldIdx = args.indexOf('--field');
500
+ const valueIdx = args.indexOf('--value');
501
+ frontmatter.cmdFrontmatterSet(cwd, file, fieldIdx !== -1 ? args[fieldIdx + 1] : null, valueIdx !== -1 ? args[valueIdx + 1] : undefined, raw);
502
+ } else if (subcommand === 'merge') {
503
+ const dataIdx = args.indexOf('--data');
504
+ frontmatter.cmdFrontmatterMerge(cwd, file, dataIdx !== -1 ? args[dataIdx + 1] : null, raw);
505
+ } else if (subcommand === 'validate') {
506
+ const schemaIdx = args.indexOf('--schema');
507
+ frontmatter.cmdFrontmatterValidate(cwd, file, schemaIdx !== -1 ? args[schemaIdx + 1] : null, raw);
508
+ } else {
509
+ error('Unknown frontmatter subcommand. Available: get, set, merge, validate');
510
+ }
511
+ break;
512
+ }
513
+
514
+ case 'verify': {
515
+ const subcommand = args[1];
516
+ if (subcommand === 'plan-structure') {
517
+ verify.cmdVerifyPlanStructure(cwd, args[2], raw);
518
+ } else if (subcommand === 'phase-completeness') {
519
+ verify.cmdVerifyPhaseCompleteness(cwd, args[2], raw);
520
+ } else if (subcommand === 'references') {
521
+ verify.cmdVerifyReferences(cwd, args[2], raw);
522
+ } else if (subcommand === 'commits') {
523
+ verify.cmdVerifyCommits(cwd, args.slice(2), raw);
524
+ } else if (subcommand === 'artifacts') {
525
+ verify.cmdVerifyArtifacts(cwd, args[2], raw);
526
+ } else if (subcommand === 'key-links') {
527
+ verify.cmdVerifyKeyLinks(cwd, args[2], raw);
528
+ } else {
529
+ error('Unknown verify subcommand. Available: plan-structure, phase-completeness, references, commits, artifacts, key-links');
530
+ }
531
+ break;
532
+ }
533
+
534
+ case 'generate-slug': {
535
+ commands.cmdGenerateSlug(args[1], raw);
536
+ break;
537
+ }
538
+
539
+ case 'current-timestamp': {
540
+ commands.cmdCurrentTimestamp(args[1] || 'full', raw);
541
+ break;
542
+ }
543
+
544
+ case 'list-todos': {
545
+ commands.cmdListTodos(cwd, args[1], raw);
546
+ break;
547
+ }
548
+
549
+ case 'verify-path-exists': {
550
+ commands.cmdVerifyPathExists(cwd, args[1], raw);
551
+ break;
552
+ }
553
+
554
+ case 'config-ensure-section': {
555
+ config.cmdConfigEnsureSection(cwd, raw);
556
+ break;
557
+ }
558
+
559
+ case 'config-set': {
560
+ config.cmdConfigSet(cwd, args[1], args[2], raw);
561
+ break;
562
+ }
563
+
564
+ case 'config-get': {
565
+ config.cmdConfigGet(cwd, args[1], raw);
566
+ break;
567
+ }
568
+
569
+ case 'review-config': {
570
+ const result = config.loadReviewConfig(cwd);
571
+ const { output: out } = require('./lib/core.cjs');
572
+ out(result, raw);
573
+ break;
574
+ }
575
+
576
+ case 'check-config-gitignore': {
577
+ const result = config.checkConfigGitignore(cwd);
578
+ const { output: out } = require('./lib/core.cjs');
579
+ out(result, raw);
580
+ break;
581
+ }
582
+
583
+ case 'history-digest': {
584
+ commands.cmdHistoryDigest(cwd, raw);
585
+ break;
586
+ }
587
+
588
+ case 'phases': {
589
+ const subcommand = args[1];
590
+ if (subcommand === 'list') {
591
+ const typeIndex = args.indexOf('--type');
592
+ const phaseIndex = args.indexOf('--phase');
593
+ const options = {
594
+ type: typeIndex !== -1 ? args[typeIndex + 1] : null,
595
+ phase: phaseIndex !== -1 ? args[phaseIndex + 1] : null,
596
+ includeArchived: args.includes('--include-archived'),
597
+ };
598
+ phase.cmdPhasesList(cwd, options, raw);
599
+ } else {
600
+ error('Unknown phases subcommand. Available: list');
601
+ }
602
+ break;
603
+ }
604
+
605
+ case 'roadmap': {
606
+ const subcommand = args[1];
607
+ if (subcommand === 'get-phase') {
608
+ roadmap.cmdRoadmapGetPhase(cwd, args[2], raw);
609
+ } else if (subcommand === 'analyze') {
610
+ roadmap.cmdRoadmapAnalyze(cwd, raw);
611
+ } else if (subcommand === 'update-plan-progress') {
612
+ roadmap.cmdRoadmapUpdatePlanProgress(cwd, args[2], raw);
613
+ } else {
614
+ error('Unknown roadmap subcommand. Available: get-phase, analyze, update-plan-progress');
615
+ }
616
+ break;
617
+ }
618
+
619
+ case 'repos': {
620
+ const subcommand = args[1];
621
+ // Gate write subcommands
622
+ if (subcommand === 'init-product' || subcommand === 'add' || subcommand === 'remove' || subcommand === 'migrate') {
623
+ gateIdentity();
624
+ }
625
+ if (subcommand === 'list') {
626
+ repos.cmdReposList(cwd, raw);
627
+ } else if (subcommand === 'add') {
628
+ const repoPath = args[2];
629
+ const nameIdx = args.indexOf('--name');
630
+ const descIdx = args.indexOf('--desc');
631
+ repos.cmdReposAdd(cwd, repoPath, {
632
+ name: nameIdx !== -1 ? args[nameIdx + 1] : null,
633
+ desc: descIdx !== -1 ? args[descIdx + 1] : null,
634
+ }, raw);
635
+ } else if (subcommand === 'remove') {
636
+ const forceFlag = args.includes('--force');
637
+ repos.cmdReposRemove(cwd, args[2], { force: forceFlag }, raw);
638
+ } else if (subcommand === 'validate') {
639
+ repos.cmdReposValidate(cwd, raw);
640
+ } else if (subcommand === 'resolve') {
641
+ repos.cmdReposResolve(cwd, args[2], raw);
642
+ } else if (subcommand === 'init-product') {
643
+ const layoutIdx = args.indexOf('--layout');
644
+ const layoutFlag = layoutIdx !== -1 ? args[layoutIdx + 1] : null;
645
+ // productName is first positional arg after subcommand, skip --layout and its value
646
+ let productName = null;
647
+ for (let i = 2; i < args.length; i++) {
648
+ if (args[i] === '--layout') { i++; continue; } // skip --layout and its value
649
+ productName = args[i];
650
+ break;
651
+ }
652
+ repos.cmdReposInitProduct(cwd, { productName, layout: layoutFlag }, raw);
653
+ } else if (subcommand === 'detect-layout') {
654
+ repos.cmdDetectLayout(cwd, raw);
655
+ } else if (subcommand === 'scan-tags') {
656
+ const phaseDir = args[2];
657
+ repos.cmdReposScanTags(cwd, phaseDir, raw);
658
+ } else if (subcommand === 'auto-populate') {
659
+ const planFile = args[2];
660
+ repos.cmdReposAutoPopulate(cwd, planFile, raw);
661
+ } else if (subcommand === 'validate-consistency') {
662
+ const planFile = args[2];
663
+ repos.cmdReposValidateConsistency(cwd, planFile, raw);
664
+ } else if (subcommand === 'migrate') {
665
+ const migrationMod = require('./lib/migration.cjs');
666
+ const slug = args[2];
667
+ if (!slug) error('Usage: repos migrate <slug>');
668
+ migrationMod.cmdMigrateV1ToV2(cwd, slug, raw);
669
+ } else {
670
+ error('Unknown repos subcommand. Available: list, add, remove, validate, resolve, init-product, detect-layout, scan-tags, auto-populate, validate-consistency, migrate');
671
+ }
672
+ break;
673
+ }
674
+
675
+ case 'projects': {
676
+ const subcommand = args[1];
677
+ // Gate write subcommands
678
+ if (subcommand === 'create' || subcommand === 'switch' || subcommand === 'complete' || subcommand === 'reactivate') {
679
+ gateIdentity();
680
+ }
681
+ if (subcommand === 'create') {
682
+ const name = args[2];
683
+ const reposIdx = args.indexOf('--repos');
684
+ projects.cmdProjectsCreate(cwd, name, {
685
+ initial_repos: reposIdx !== -1 ? args[reposIdx + 1] : null,
686
+ }, raw);
687
+ } else if (subcommand === 'switch') {
688
+ projects.cmdProjectsSwitch(cwd, args[2], raw);
689
+ } else if (subcommand === 'list') {
690
+ projects.cmdProjectsList(cwd, raw);
691
+ } else if (subcommand === 'complete') {
692
+ const slugIdx = args.indexOf('--slug');
693
+ projects.cmdProjectsComplete(cwd, {
694
+ slug: slugIdx !== -1 ? args[slugIdx + 1] : null,
695
+ }, raw);
696
+ } else if (subcommand === 'reactivate') {
697
+ const slugIdx = args.indexOf('--slug');
698
+ const setCurrent = args.includes('--set-current');
699
+ projects.cmdProjectsReactivate(cwd, {
700
+ slug: slugIdx !== -1 ? args[slugIdx + 1] : null,
701
+ set_current: setCurrent,
702
+ }, raw);
703
+ } else if (subcommand === 'regenerate') {
704
+ projects.cmdProjectsRegenerate(cwd, raw);
705
+ } else {
706
+ error('Unknown projects subcommand. Available: create, switch, list, complete, reactivate, regenerate');
707
+ }
708
+ break;
709
+ }
710
+
711
+ case 'overlap': {
712
+ const subcommand = args[1];
713
+ if (subcommand === 'check') {
714
+ overlap.cmdOverlapCheck(cwd, raw);
715
+ } else {
716
+ error('Unknown overlap subcommand. Available: check');
717
+ }
718
+ break;
719
+ }
720
+
721
+ case 'requirements': {
722
+ const subcommand = args[1];
723
+ // Gate write subcommand
724
+ if (subcommand === 'mark-complete') {
725
+ gateIdentity();
726
+ }
727
+ if (subcommand === 'mark-complete') {
728
+ milestone.cmdRequirementsMarkComplete(cwd, args.slice(2), raw);
729
+ } else {
730
+ error('Unknown requirements subcommand. Available: mark-complete');
731
+ }
732
+ break;
733
+ }
734
+
735
+ case 'phase': {
736
+ const subcommand = args[1];
737
+ // Gate write subcommands
738
+ if (subcommand === 'add' || subcommand === 'insert' || subcommand === 'remove' || subcommand === 'complete') {
739
+ gateIdentity();
740
+ }
741
+ if (subcommand === 'next-decimal') {
742
+ phase.cmdPhaseNextDecimal(cwd, args[2], raw);
743
+ } else if (subcommand === 'add') {
744
+ phase.cmdPhaseAdd(cwd, args.slice(2).join(' '), raw);
745
+ } else if (subcommand === 'insert') {
746
+ phase.cmdPhaseInsert(cwd, args[2], args.slice(3).join(' '), raw);
747
+ } else if (subcommand === 'remove') {
748
+ const forceFlag = args.includes('--force');
749
+ phase.cmdPhaseRemove(cwd, args[2], { force: forceFlag }, raw);
750
+ } else if (subcommand === 'complete') {
751
+ phase.cmdPhaseComplete(cwd, args[2], raw);
752
+ } else {
753
+ error('Unknown phase subcommand. Available: next-decimal, add, insert, remove, complete');
754
+ }
755
+ break;
756
+ }
757
+
758
+ case 'milestone': {
759
+ gateIdentity();
760
+ const subcommand = args[1];
761
+ if (subcommand === 'complete') {
762
+ const nameIndex = args.indexOf('--name');
763
+ const archivePhases = args.includes('--archive-phases');
764
+ // Collect --name value (everything after --name until next flag or end)
765
+ let milestoneName = null;
766
+ if (nameIndex !== -1) {
767
+ const nameArgs = [];
768
+ for (let i = nameIndex + 1; i < args.length; i++) {
769
+ if (args[i].startsWith('--')) break;
770
+ nameArgs.push(args[i]);
771
+ }
772
+ milestoneName = nameArgs.join(' ') || null;
773
+ }
774
+ milestone.cmdMilestoneComplete(cwd, args[2], { name: milestoneName, archivePhases }, raw);
775
+ } else {
776
+ error('Unknown milestone subcommand. Available: complete');
777
+ }
778
+ break;
779
+ }
780
+
781
+ case 'validate': {
782
+ const subcommand = args[1];
783
+ if (subcommand === 'consistency') {
784
+ verify.cmdValidateConsistency(cwd, raw);
785
+ } else if (subcommand === 'health') {
786
+ const repairFlag = args.includes('--repair');
787
+ verify.cmdValidateHealth(cwd, { repair: repairFlag }, raw);
788
+ } else {
789
+ error('Unknown validate subcommand. Available: consistency, health');
790
+ }
791
+ break;
792
+ }
793
+
794
+ case 'progress': {
795
+ const subcommand = args[1] || 'json';
796
+ commands.cmdProgressRender(cwd, subcommand, raw);
797
+ break;
798
+ }
799
+
800
+ case 'todo': {
801
+ const subcommand = args[1];
802
+ // Gate write subcommand
803
+ if (subcommand === 'complete') {
804
+ gateIdentity();
805
+ }
806
+ if (subcommand === 'complete') {
807
+ commands.cmdTodoComplete(cwd, args[2], raw);
808
+ } else {
809
+ error('Unknown todo subcommand. Available: complete');
810
+ }
811
+ break;
812
+ }
813
+
814
+ case 'scaffold': {
815
+ gateIdentity();
816
+ const scaffoldType = args[1];
817
+ const phaseIndex = args.indexOf('--phase');
818
+ const nameIndex = args.indexOf('--name');
819
+ const scaffoldOptions = {
820
+ phase: phaseIndex !== -1 ? args[phaseIndex + 1] : null,
821
+ name: nameIndex !== -1 ? args.slice(nameIndex + 1).join(' ') : null,
822
+ };
823
+ commands.cmdScaffold(cwd, scaffoldType, scaffoldOptions, raw);
824
+ break;
825
+ }
826
+
827
+ case 'init': {
828
+ const workflow = args[1];
829
+ switch (workflow) {
830
+ case 'execute-phase':
831
+ init.cmdInitExecutePhase(cwd, args[2], raw);
832
+ break;
833
+ case 'plan-phase':
834
+ init.cmdInitPlanPhase(cwd, args[2], raw);
835
+ break;
836
+ case 'new-project':
837
+ init.cmdInitNewProject(cwd, raw);
838
+ break;
839
+ case 'new-milestone':
840
+ init.cmdInitNewMilestone(cwd, raw);
841
+ break;
842
+ case 'quick':
843
+ init.cmdInitQuick(cwd, args.slice(2).join(' '), raw);
844
+ break;
845
+ case 'resume':
846
+ init.cmdInitResume(cwd, raw);
847
+ break;
848
+ case 'verify-work':
849
+ init.cmdInitVerifyWork(cwd, args[2], raw);
850
+ break;
851
+ case 'audit-phase':
852
+ init.cmdInitAuditPhase(cwd, args[2], raw);
853
+ break;
854
+ case 'phase-op':
855
+ init.cmdInitPhaseOp(cwd, args[2], raw);
856
+ break;
857
+ case 'todos':
858
+ init.cmdInitTodos(cwd, args[2], raw);
859
+ break;
860
+ case 'milestone-op':
861
+ init.cmdInitMilestoneOp(cwd, raw);
862
+ break;
863
+ case 'map-codebase': {
864
+ const onlyIdx = args.indexOf('--only');
865
+ let onlyRepo = null;
866
+ if (onlyIdx !== -1) {
867
+ onlyRepo = args[onlyIdx + 1] || null;
868
+ if (!onlyRepo || onlyRepo.startsWith('--')) {
869
+ error('--only requires a repo name argument');
870
+ }
871
+ } else if (args[2] && !args[2].startsWith('--')) {
872
+ // Positional argument: /dgs:map-codebase <repo-name>
873
+ onlyRepo = args[2];
874
+ }
875
+ init.cmdInitMapCodebase(cwd, onlyRepo, raw);
876
+ break;
877
+ }
878
+ case 'progress':
879
+ init.cmdInitProgress(cwd, raw);
880
+ break;
881
+ default:
882
+ error(`Unknown init workflow: ${workflow}\nAvailable: execute-phase, plan-phase, new-project, new-milestone, quick, resume, verify-work, audit-phase, phase-op, todos, milestone-op, map-codebase, progress`);
883
+ }
884
+ break;
885
+ }
886
+
887
+ case 'phase-plan-index': {
888
+ phase.cmdPhasePlanIndex(cwd, args[1], raw);
889
+ break;
890
+ }
891
+
892
+ case 'state-snapshot': {
893
+ state.cmdStateSnapshot(cwd, raw);
894
+ break;
895
+ }
896
+
897
+ case 'summary-extract': {
898
+ const summaryPath = args[1];
899
+ const fieldsIndex = args.indexOf('--fields');
900
+ const fields = fieldsIndex !== -1 ? args[fieldsIndex + 1].split(',') : null;
901
+ commands.cmdSummaryExtract(cwd, summaryPath, fields, raw);
902
+ break;
903
+ }
904
+
905
+ case 'websearch': {
906
+ const query = args[1];
907
+ const limitIdx = args.indexOf('--limit');
908
+ const freshnessIdx = args.indexOf('--freshness');
909
+ await commands.cmdWebsearch(query, {
910
+ limit: limitIdx !== -1 ? parseInt(args[limitIdx + 1], 10) : 10,
911
+ freshness: freshnessIdx !== -1 ? args[freshnessIdx + 1] : null,
912
+ }, raw);
913
+ break;
914
+ }
915
+
916
+ case 'ideas': {
917
+ const subcommand = args[1];
918
+ // Gate write subcommands and capture author string for authorship fields
919
+ let author = null;
920
+ if (subcommand !== 'list') {
921
+ author = gateIdentity();
922
+ }
923
+ if (subcommand === 'create') {
924
+ const titleIdx = args.indexOf('--title');
925
+ const bodyIdx = args.indexOf('--body');
926
+ const tagsIdx = args.indexOf('--tags');
927
+ ideas.cmdIdeasCreate(cwd,
928
+ titleIdx !== -1 ? args[titleIdx + 1] : null,
929
+ bodyIdx !== -1 ? args[bodyIdx + 1] : null,
930
+ tagsIdx !== -1 ? args[tagsIdx + 1] : null,
931
+ raw,
932
+ author
933
+ );
934
+ } else if (subcommand === 'update') {
935
+ const idIdx = args.indexOf('--id');
936
+ const fieldIdx = args.indexOf('--field');
937
+ const valueIdx = args.indexOf('--value');
938
+ ideas.cmdIdeasUpdate(cwd,
939
+ idIdx !== -1 ? args[idIdx + 1] : null,
940
+ fieldIdx !== -1 ? args[fieldIdx + 1] : null,
941
+ valueIdx !== -1 ? args[valueIdx + 1] : null,
942
+ raw,
943
+ author
944
+ );
945
+ } else if (subcommand === 'append-note') {
946
+ const idIdx = args.indexOf('--id');
947
+ const noteIdx = args.indexOf('--note');
948
+ ideas.cmdIdeasAppendNote(cwd,
949
+ idIdx !== -1 ? args[idIdx + 1] : null,
950
+ noteIdx !== -1 ? args[noteIdx + 1] : null,
951
+ raw,
952
+ author
953
+ );
954
+ } else if (subcommand === 'list') {
955
+ const stateIdx = args.indexOf('--state');
956
+ const tagIdx = args.indexOf('--tag');
957
+ const authorIdx = args.indexOf('--author');
958
+ const orphanCheck = args.includes('--orphan-check');
959
+ const consolidatedFlag = args.includes('--consolidated');
960
+ const allFlag = args.includes('--all');
961
+ ideas.cmdIdeasList(cwd, {
962
+ state: stateIdx !== -1 ? args[stateIdx + 1] : null,
963
+ tag: tagIdx !== -1 ? args[tagIdx + 1] : null,
964
+ author: authorIdx !== -1 ? args[authorIdx + 1] : null,
965
+ include_orphan_check: orphanCheck,
966
+ include_consolidated: consolidatedFlag,
967
+ show_all: allFlag,
968
+ }, raw);
969
+ } else if (subcommand === 'reject') {
970
+ const idIdx = args.indexOf('--id');
971
+ const reasonIdx = args.indexOf('--reason');
972
+ ideas.cmdIdeasReject(cwd,
973
+ idIdx !== -1 ? args[idIdx + 1] : null,
974
+ reasonIdx !== -1 ? args[reasonIdx + 1] : null,
975
+ raw,
976
+ author
977
+ );
978
+ } else if (subcommand === 'restore') {
979
+ const idIdx = args.indexOf('--id');
980
+ ideas.cmdIdeasRestore(cwd,
981
+ idIdx !== -1 ? args[idIdx + 1] : null,
982
+ raw,
983
+ author
984
+ );
985
+ } else if (subcommand === 'move-state') {
986
+ const idIdx = args.indexOf('--id');
987
+ const toIdx = args.indexOf('--to');
988
+ ideas.cmdIdeasMoveState(cwd,
989
+ idIdx !== -1 ? args[idIdx + 1] : null,
990
+ toIdx !== -1 ? args[toIdx + 1] : null,
991
+ raw,
992
+ author
993
+ );
994
+ } else if (subcommand === 'discuss-save') {
995
+ const idIdx = args.indexOf('--id');
996
+ const entryIdx = args.indexOf('--entry');
997
+ ideas.cmdIdeasDiscussSave(cwd,
998
+ idIdx !== -1 ? args[idIdx + 1] : null,
999
+ entryIdx !== -1 ? args[entryIdx + 1] : null,
1000
+ raw,
1001
+ author
1002
+ );
1003
+ } else if (subcommand === 'research-save') {
1004
+ const idIdx = args.indexOf('--id');
1005
+ const entryIdx = args.indexOf('--entry');
1006
+ ideas.cmdIdeasResearchSave(cwd,
1007
+ idIdx !== -1 ? args[idIdx + 1] : null,
1008
+ entryIdx !== -1 ? args[entryIdx + 1] : null,
1009
+ raw,
1010
+ author
1011
+ );
1012
+ } else if (subcommand === 'consolidate') {
1013
+ const idsIdx = args.indexOf('--ids');
1014
+ const titleIdx = args.indexOf('--title');
1015
+ const bodyIdx = args.indexOf('--body');
1016
+ const tagsIdx = args.indexOf('--tags');
1017
+ const discussionIdx = args.indexOf('--discussion');
1018
+ const researchIdx = args.indexOf('--research');
1019
+ ideas.cmdIdeasConsolidate(cwd, {
1020
+ ids: idsIdx !== -1 ? args[idsIdx + 1] : null,
1021
+ title: titleIdx !== -1 ? args[titleIdx + 1] : null,
1022
+ body: bodyIdx !== -1 ? args[bodyIdx + 1] : null,
1023
+ tags: tagsIdx !== -1 ? args[tagsIdx + 1] : null,
1024
+ discussion: discussionIdx !== -1 ? args[discussionIdx + 1] : null,
1025
+ research: researchIdx !== -1 ? args[researchIdx + 1] : null,
1026
+ }, raw, author);
1027
+ } else if (subcommand === 'find-related') {
1028
+ const idIdx = args.indexOf('--id');
1029
+ const thresholdIdx = args.indexOf('--threshold');
1030
+ ideas.cmdIdeasFindRelated(cwd, {
1031
+ id: idIdx !== -1 ? args[idIdx + 1] : null,
1032
+ threshold: thresholdIdx !== -1 ? args[thresholdIdx + 1] : 'medium',
1033
+ }, raw);
1034
+ } else if (subcommand === 'undo-consolidation') {
1035
+ const idIdx = args.indexOf('--id');
1036
+ ideas.cmdIdeasUndoConsolidation(cwd,
1037
+ idIdx !== -1 ? args[idIdx + 1] : null,
1038
+ raw,
1039
+ author
1040
+ );
1041
+ } else {
1042
+ error('Unknown ideas subcommand: ' + subcommand);
1043
+ }
1044
+ break;
1045
+ }
1046
+
1047
+ case 'specs': {
1048
+ const subcommand = args[1];
1049
+ // Gate write subcommands and capture author string for authorship fields
1050
+ let author = null;
1051
+ if (subcommand !== 'list' && subcommand !== 'validate') {
1052
+ author = gateIdentity();
1053
+ }
1054
+ if (subcommand === 'create') {
1055
+ const titleIdx = args.indexOf('--title');
1056
+ const bodyIdx = args.indexOf('--body');
1057
+ const sourceIdeasIdx = args.indexOf('--source-ideas');
1058
+ const sourceDocIdx = args.indexOf('--source-document');
1059
+ specs.cmdSpecsCreate(cwd, {
1060
+ title: titleIdx !== -1 ? args[titleIdx + 1] : null,
1061
+ source_ideas: sourceIdeasIdx !== -1 ? args[sourceIdeasIdx + 1].split(',').map(s => s.trim()) : [],
1062
+ body: bodyIdx !== -1 ? args[bodyIdx + 1] : '',
1063
+ source_document: sourceDocIdx !== -1 ? args[sourceDocIdx + 1] : null,
1064
+ author,
1065
+ }, raw);
1066
+ } else if (subcommand === 'list') {
1067
+ const statusIdx = args.indexOf('--status');
1068
+ const authorIdx = args.indexOf('--author');
1069
+ specs.cmdSpecsList(cwd, {
1070
+ status: statusIdx !== -1 ? args[statusIdx + 1] : null,
1071
+ author: authorIdx !== -1 ? args[authorIdx + 1] : null,
1072
+ }, raw);
1073
+ } else if (subcommand === 'update-status') {
1074
+ const idIdx = args.indexOf('--id');
1075
+ const statusIdx = args.indexOf('--status');
1076
+ specs.cmdSpecsUpdateStatus(cwd,
1077
+ idIdx !== -1 ? args[idIdx + 1] : null,
1078
+ statusIdx !== -1 ? args[statusIdx + 1] : null,
1079
+ raw,
1080
+ author
1081
+ );
1082
+ } else if (subcommand === 'append-review') {
1083
+ const idIdx = args.indexOf('--id');
1084
+ const entryIdx = args.indexOf('--entry');
1085
+ specs.cmdSpecsAppendReviewHistory(cwd,
1086
+ idIdx !== -1 ? args[idIdx + 1] : null,
1087
+ entryIdx !== -1 ? args[entryIdx + 1] : null,
1088
+ raw,
1089
+ author
1090
+ );
1091
+ } else if (subcommand === 'finalize') {
1092
+ const idIdx = args.indexOf('--id');
1093
+ specs.cmdSpecsFinalize(cwd,
1094
+ idIdx !== -1 ? args[idIdx + 1] : null,
1095
+ raw,
1096
+ author
1097
+ );
1098
+ } else if (subcommand === 'set-status') {
1099
+ const idIdx = args.indexOf('--id');
1100
+ const statusIdx = args.indexOf('--status');
1101
+ specs.cmdSpecsSetStatus(cwd,
1102
+ idIdx !== -1 ? args[idIdx + 1] : null,
1103
+ statusIdx !== -1 ? args[statusIdx + 1] : null,
1104
+ raw,
1105
+ author
1106
+ );
1107
+ } else if (subcommand === 'validate') {
1108
+ const idIdx = args.indexOf('--id');
1109
+ specs.cmdSpecsValidate(cwd,
1110
+ idIdx !== -1 ? args[idIdx + 1] : null,
1111
+ raw
1112
+ );
1113
+ } else if (subcommand === 'add-log-entry') {
1114
+ const idIdx = args.indexOf('--id');
1115
+ const dateIdx = args.indexOf('--date');
1116
+ const versionIdx = args.indexOf('--version');
1117
+ const actionIdx = args.indexOf('--action');
1118
+ const summaryIdx = args.indexOf('--summary');
1119
+ specs.cmdSpecsAddLogEntry(cwd,
1120
+ idIdx !== -1 ? args[idIdx + 1] : null,
1121
+ dateIdx !== -1 ? args[dateIdx + 1] : null,
1122
+ versionIdx !== -1 ? args[versionIdx + 1] : null,
1123
+ actionIdx !== -1 ? args[actionIdx + 1] : null,
1124
+ summaryIdx !== -1 ? args[summaryIdx + 1] : null,
1125
+ raw,
1126
+ author
1127
+ );
1128
+ } else if (subcommand === 'link-milestone') {
1129
+ const idIdx = args.indexOf('--id');
1130
+ const milestoneIdx = args.indexOf('--milestone');
1131
+ specs.cmdSpecsLinkMilestone(cwd,
1132
+ idIdx !== -1 ? args[idIdx + 1] : null,
1133
+ milestoneIdx !== -1 ? args[milestoneIdx + 1] : null,
1134
+ raw,
1135
+ author
1136
+ );
1137
+ } else {
1138
+ error('Unknown specs subcommand: ' + (subcommand || '(none)') + '. Available: create, list, update-status, append-review, finalize, set-status, validate, add-log-entry, link-milestone');
1139
+ }
1140
+ break;
1141
+ }
1142
+
1143
+ case 'docs': {
1144
+ const subcommand = args[1];
1145
+ // Gate write subcommands and capture author string for authorship fields
1146
+ let author = null;
1147
+ if (subcommand !== 'list' && subcommand !== 'check-duplicate') {
1148
+ author = gateIdentity();
1149
+ }
1150
+ if (subcommand === 'add') {
1151
+ const sourceIdx = args.indexOf('--source');
1152
+ const scopeIdx = args.indexOf('--scope');
1153
+ const scopeIdIdx = args.indexOf('--scope-id');
1154
+ docs.cmdDocsAdd(cwd,
1155
+ sourceIdx !== -1 ? args[sourceIdx + 1] : null,
1156
+ scopeIdx !== -1 ? args[scopeIdx + 1] : null,
1157
+ scopeIdIdx !== -1 ? args[scopeIdIdx + 1] : null,
1158
+ raw,
1159
+ author
1160
+ );
1161
+ } else if (subcommand === 'list') {
1162
+ const scopeIdx = args.indexOf('--scope');
1163
+ docs.cmdDocsList(cwd,
1164
+ scopeIdx !== -1 ? args[scopeIdx + 1] : null,
1165
+ raw
1166
+ );
1167
+ } else if (subcommand === 'remove') {
1168
+ const scopeIdx = args.indexOf('--scope');
1169
+ const scopeIdIdx = args.indexOf('--scope-id');
1170
+ const slugIdx = args.indexOf('--slug');
1171
+ docs.cmdDocsRemove(cwd,
1172
+ scopeIdx !== -1 ? args[scopeIdx + 1] : null,
1173
+ scopeIdIdx !== -1 ? args[scopeIdIdx + 1] : null,
1174
+ slugIdx !== -1 ? args[slugIdx + 1] : null,
1175
+ raw
1176
+ );
1177
+ } else if (subcommand === 'move') {
1178
+ const slugIdx = args.indexOf('--slug');
1179
+ const fromScopeIdx = args.indexOf('--from-scope');
1180
+ const fromIdIdx = args.indexOf('--from-id');
1181
+ const toScopeIdx = args.indexOf('--to-scope');
1182
+ const toIdIdx = args.indexOf('--to-id');
1183
+ docs.cmdDocsMove(cwd,
1184
+ slugIdx !== -1 ? args[slugIdx + 1] : null,
1185
+ fromScopeIdx !== -1 ? args[fromScopeIdx + 1] : null,
1186
+ fromIdIdx !== -1 ? args[fromIdIdx + 1] : null,
1187
+ toScopeIdx !== -1 ? args[toScopeIdx + 1] : null,
1188
+ toIdIdx !== -1 ? args[toIdIdx + 1] : null,
1189
+ raw
1190
+ );
1191
+ } else if (subcommand === 'check-duplicate') {
1192
+ const scopeIdx = args.indexOf('--scope');
1193
+ const scopeIdIdx = args.indexOf('--scope-id');
1194
+ const slugIdx = args.indexOf('--slug');
1195
+ const scope = scopeIdx !== -1 ? args[scopeIdx + 1] : null;
1196
+ const scopeId = scopeIdIdx !== -1 ? args[scopeIdIdx + 1] : null;
1197
+ const slug = slugIdx !== -1 ? args[slugIdx + 1] : null;
1198
+ if (!scope || !slug) {
1199
+ error('scope and slug required for docs check-duplicate');
1200
+ }
1201
+ const docsDir = docs.resolveDocsDir(cwd, scope, scopeId);
1202
+ const docPath = require('path').join(docsDir, slug);
1203
+ const exists = require('fs').existsSync(docPath);
1204
+ const { output: out } = require('./lib/core.cjs');
1205
+ out({ exists, path: exists ? docPath : null }, raw);
1206
+ } else {
1207
+ error('Unknown docs subcommand: ' + (subcommand || '(none)') + '. Available: add, list, remove, move, check-duplicate');
1208
+ }
1209
+ break;
1210
+ }
1211
+
1212
+ case 'search': {
1213
+ const query = args[1];
1214
+ const ideasOnly = args.includes('--ideas-only');
1215
+ const specsOnly = args.includes('--specs-only');
1216
+ const docsOnly = args.includes('--docs-only');
1217
+ const includeRejected = args.includes('--include-rejected');
1218
+ const tagsIdx = args.indexOf('--tags');
1219
+ const maxIdx = args.indexOf('--max-per-type');
1220
+ search.cmdSearch(cwd, query, {
1221
+ ideas_only: ideasOnly,
1222
+ specs_only: specsOnly,
1223
+ docs_only: docsOnly,
1224
+ include_rejected: includeRejected,
1225
+ tags: tagsIdx !== -1 ? args[tagsIdx + 1] : null,
1226
+ max_per_type: maxIdx !== -1 ? args[maxIdx + 1] : 5,
1227
+ }, raw);
1228
+ break;
1229
+ }
1230
+
1231
+ case 'identity': {
1232
+ const sub = args[1];
1233
+ if (sub === 'resolve') {
1234
+ cmdIdentityResolve(cwd, raw);
1235
+ } else {
1236
+ error('Unknown identity command: ' + sub);
1237
+ }
1238
+ break;
1239
+ }
1240
+
1241
+ case 'merge-conflicts': {
1242
+ const subcommand = args[1];
1243
+ const phaseDirIdx = args.indexOf('--phase-dir');
1244
+ const phaseDir = phaseDirIdx !== -1 ? args[phaseDirIdx + 1] : null;
1245
+
1246
+ if (subcommand === 'detect') {
1247
+ mergeConflicts.cmdMergeConflictsDetect(cwd, phaseDir, raw);
1248
+ } else if (subcommand === 'context') {
1249
+ const file = args[2];
1250
+ if (!file) error('File path required. Usage: merge-conflicts context <file> [--phase-dir <dir>]');
1251
+ mergeConflicts.cmdMergeConflictsContext(cwd, file, phaseDir, raw);
1252
+ } else if (subcommand === 'resolved') {
1253
+ gateIdentity();
1254
+ const file = args[2];
1255
+ if (!file) error('File path required. Usage: merge-conflicts resolved <file> --phase-dir <dir> --resolution \'{"strategy":"..."}\'');
1256
+ if (!phaseDir) error('--phase-dir required for resolved command');
1257
+ const resIdx = args.indexOf('--resolution');
1258
+ const resolution = resIdx !== -1 ? args[resIdx + 1] : null;
1259
+ if (!resolution) error('--resolution required. Pass JSON: --resolution \'{"strategy":"ours","description":"...","confidence":"HIGH"}\'');
1260
+ mergeConflicts.cmdMergeConflictsResolved(cwd, file, phaseDir, resolution, raw);
1261
+ } else if (subcommand === 'summary') {
1262
+ if (!phaseDir) error('--phase-dir required for summary command');
1263
+ mergeConflicts.cmdMergeConflictsSummary(cwd, phaseDir, raw);
1264
+ } else {
1265
+ error('Unknown merge-conflicts subcommand: ' + (subcommand || '(none)') + '. Available: detect, context, resolved, summary');
1266
+ }
1267
+ break;
1268
+ }
1269
+
1270
+ case 'conflict-agent': {
1271
+ const subcommand = args[1];
1272
+ gateIdentity();
1273
+ const phaseDirIdx = args.indexOf('--phase-dir');
1274
+ const phaseDir = phaseDirIdx !== -1 ? args[phaseDirIdx + 1] : null;
1275
+ const learningsIdx = args.indexOf('--learnings');
1276
+ const learningsFile = learningsIdx !== -1 ? args[learningsIdx + 1] : null;
1277
+ const hintIdx = args.indexOf('--hint');
1278
+ const hint = hintIdx !== -1 ? args[hintIdx + 1] : null;
1279
+
1280
+ if (subcommand === 'run') {
1281
+ if (!phaseDir) error('--phase-dir required for conflict-agent run');
1282
+ conflictAgent.cmdConflictAgentRun(cwd, phaseDir, raw, learningsFile);
1283
+ } else if (subcommand === 'resolve-file') {
1284
+ const file = args[2];
1285
+ if (!file) error('File path required. Usage: conflict-agent resolve-file <file> --phase-dir <dir> [--hint <text>]');
1286
+ if (!phaseDir) error('--phase-dir required for resolve-file command');
1287
+ conflictAgent.cmdConflictAgentResolveFile(cwd, file, phaseDir, raw, hint);
1288
+ } else {
1289
+ error('Unknown conflict-agent subcommand: ' + (subcommand || '(none)') + '. Available: run, resolve-file');
1290
+ }
1291
+ break;
1292
+ }
1293
+
1294
+ case 'jobs': {
1295
+ const subcommand = args[1];
1296
+ if (subcommand === 'parse') {
1297
+ if (!args[2]) error('Usage: jobs parse <file>');
1298
+ jobs.cmdJobsParse(cwd, args[2], raw);
1299
+ } else if (subcommand === 'update-step') {
1300
+ if (!args[2] || args[3] === undefined || !args[4]) {
1301
+ error('Usage: jobs update-step <file> <step-index> <status> [--timestamp <ts>] [--error "msg"]');
1302
+ }
1303
+ const timestampIdx = args.indexOf('--timestamp');
1304
+ const errorIdx = args.indexOf('--error');
1305
+ const timestampVal = timestampIdx !== -1 ? args[timestampIdx + 1] : undefined;
1306
+ const errorVal = errorIdx !== -1 ? args[errorIdx + 1] : undefined;
1307
+ jobs.cmdJobsUpdateStep(cwd, args[2], args[3], args[4], { timestamp: timestampVal, error: errorVal }, raw);
1308
+ } else if (subcommand === 'move') {
1309
+ if (!args[2] || !args[3]) error('Usage: jobs move <file> <target-dir>');
1310
+ jobs.cmdJobsMove(cwd, args[2], args[3], raw);
1311
+ } else if (subcommand === 'create-milestone') {
1312
+ const noCheckIdx = args.indexOf('--no-check');
1313
+ const check = noCheckIdx === -1;
1314
+ // Version is the first positional arg after subcommand that doesn't start with --
1315
+ let version = null;
1316
+ for (let i = 2; i < args.length; i++) {
1317
+ if (!args[i].startsWith('--')) { version = args[i]; break; }
1318
+ }
1319
+ try {
1320
+ const result = jobs.cmdJobsCreateMilestone(cwd, version, check, raw);
1321
+ const { output: out } = require('./lib/core.cjs');
1322
+ out(result, raw);
1323
+ } catch (err) {
1324
+ error(err.message);
1325
+ }
1326
+ } else if (subcommand === 'milestone-preview') {
1327
+ const noCheckIdx = args.indexOf('--no-check');
1328
+ const check = noCheckIdx === -1;
1329
+ let version = null;
1330
+ for (let i = 2; i < args.length; i++) {
1331
+ if (!args[i].startsWith('--')) { version = args[i]; break; }
1332
+ }
1333
+ try {
1334
+ const result = jobs.cmdJobsMilestonePreview(cwd, version, check, raw);
1335
+ const { output: out } = require('./lib/core.cjs');
1336
+ out(result, raw);
1337
+ } catch (err) {
1338
+ error(err.message);
1339
+ }
1340
+ } else if (subcommand === 'find-job') {
1341
+ if (!args[2]) error('Usage: jobs find-job <version>');
1342
+ jobs.cmdJobsFindJob(cwd, args[2], raw);
1343
+ } else if (subcommand === 'update-header') {
1344
+ if (!args[2] || !args[3] || !args[4]) {
1345
+ error('Usage: jobs update-header <file> <field> <value>');
1346
+ }
1347
+ jobs.cmdJobsUpdateHeader(cwd, args[2], args[3], args[4], raw);
1348
+ } else if (subcommand === 'insert-steps') {
1349
+ if (!args[2] || args[3] === undefined || !args[4]) {
1350
+ error('Usage: jobs insert-steps <file> <after-index> <steps-json>');
1351
+ }
1352
+ jobs.cmdJobsInsertSteps(cwd, args[2], args[3], args[4], raw);
1353
+ } else if (subcommand === 'insert-gap-fix-section') {
1354
+ if (!args[2] || args[3] === undefined || args[4] === undefined || !args[5] || !args[6]) {
1355
+ error('Usage: jobs insert-gap-fix-section <file> <after-index> <cycle> <version> <phases-json>');
1356
+ }
1357
+ jobs.cmdJobsInsertGapFixSection(cwd, args[2], args[3], args[4], args[5], args[6], raw);
1358
+ } else if (subcommand === 'insert-phase-gap-fix') {
1359
+ if (!args[2] || args[3] === undefined || args[4] === undefined || !args[5]) {
1360
+ error('Usage: jobs insert-phase-gap-fix <file> <after-index> <cycle> <phase-number>');
1361
+ }
1362
+ jobs.cmdJobsInsertPhaseGapFix(cwd, args[2], args[3], args[4], args[5], raw);
1363
+ } else if (subcommand === 'list-jobs') {
1364
+ jobs.cmdJobsListJobs(cwd, raw);
1365
+ } else if (subcommand === 'cancel-job') {
1366
+ if (!args[2]) error('Usage: jobs cancel-job <version>');
1367
+ jobs.cmdJobsCancelJob(cwd, args[2], raw);
1368
+ } else if (subcommand === 'health') {
1369
+ jobs.cmdJobsHealthCheck(cwd, raw);
1370
+ } else if (subcommand === 'dry-run') {
1371
+ if (!args[2]) error('Usage: jobs dry-run <version>');
1372
+ jobs.cmdJobsDryRun(cwd, args[2], raw);
1373
+ } else if (subcommand === 'generate-summary') {
1374
+ if (!args[2]) error('Usage: jobs generate-summary <version>');
1375
+ jobs.cmdJobsGenerateSummary(cwd, args[2], raw);
1376
+ } else if (subcommand === 'record-start-shas') {
1377
+ if (!args[2]) error('Usage: jobs record-start-shas <file>');
1378
+ jobs.cmdJobsRecordStartShas(cwd, args[2], raw);
1379
+ } else if (subcommand === 'rollback') {
1380
+ if (!args[2]) error('Usage: jobs rollback <version>');
1381
+ jobs.cmdJobsRollback(cwd, args[2], raw);
1382
+ } else {
1383
+ error('Unknown jobs subcommand: ' + (subcommand || '(none)') + '. Available: parse, update-step, move, find-job, update-header, insert-steps, insert-gap-fix-section, insert-phase-gap-fix, create-milestone, milestone-preview, list-jobs, cancel-job, health, dry-run, generate-summary, record-start-shas, rollback');
1384
+ }
1385
+ break;
1386
+ }
1387
+
1388
+ case 'auto-test': {
1389
+ const subCmd = args[1];
1390
+ const autoTest = require('./lib/auto-test.cjs');
1391
+ const cwdFlagIdx = args.indexOf('--cwd');
1392
+ const testCwd = cwdFlagIdx !== -1 ? args[cwdFlagIdx + 1] : undefined;
1393
+ switch (subCmd) {
1394
+ case 'collect':
1395
+ autoTest.cmdCollectTestCommands(cwd, args[2], raw);
1396
+ break;
1397
+ case 'run': {
1398
+ const timeoutIdx = args.indexOf('--timeout');
1399
+ const timeout_ms = timeoutIdx !== -1 ? parseInt(args[timeoutIdx + 1], 10) : undefined;
1400
+ autoTest.cmdRunTestSuite(cwd, args[2], raw, { timeout_ms, testCwd });
1401
+ break;
1402
+ }
1403
+ case 'map': {
1404
+ const timeoutIdx = args.indexOf('--timeout');
1405
+ const timeout_ms = timeoutIdx !== -1 ? parseInt(args[timeoutIdx + 1], 10) : undefined;
1406
+ autoTest.cmdMapResults(cwd, args[2], raw, { timeout_ms, testCwd });
1407
+ break;
1408
+ }
1409
+ case 'check-diagnosis':
1410
+ autoTest.cmdCheckDiagnosis(cwd, args[2], raw);
1411
+ break;
1412
+ case 'rerun':
1413
+ autoTest.cmdRerunFailed(cwd, args[2], raw, { testCwd });
1414
+ break;
1415
+ default:
1416
+ error(`Unknown auto-test command: ${subCmd}. Available: collect, run, map, check-diagnosis, rerun`);
1417
+ }
1418
+ break;
1419
+ }
1420
+
1421
+ case 'phase-uat-status': {
1422
+ const autoTest = require('./lib/auto-test.cjs');
1423
+ autoTest.cmdPhaseUatStatus(cwd, args[1], raw);
1424
+ break;
1425
+ }
1426
+
1427
+ case 'context': {
1428
+ const context = require('./lib/context.cjs');
1429
+ const subCmd = args[1];
1430
+ if (subCmd === 'load-tier') {
1431
+ if (!args[2]) error('Usage: context load-tier <tier-name> [--phase N] [--idea N] [--spec N]');
1432
+ context.cmdContextLoadTier(cwd, args[2], args.slice(3), raw);
1433
+ } else {
1434
+ error('Unknown context command: ' + (subCmd || '(none)') + '. Available: load-tier');
1435
+ }
1436
+ break;
1437
+ }
1438
+
1439
+ default:
1440
+ error(`Unknown command: ${command}`);
1441
+ }
1442
+ }
1443
+
1444
+ main();