gsd-remix 1.0.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 (554) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +939 -0
  3. package/README.zh-CN.md +876 -0
  4. package/agents/gsd-advisor-researcher.md +127 -0
  5. package/agents/gsd-ai-researcher.md +133 -0
  6. package/agents/gsd-assumptions-analyzer.md +105 -0
  7. package/agents/gsd-code-fixer.md +517 -0
  8. package/agents/gsd-code-reviewer.md +371 -0
  9. package/agents/gsd-codebase-mapper.md +781 -0
  10. package/agents/gsd-debug-session-manager.md +314 -0
  11. package/agents/gsd-debugger.md +1452 -0
  12. package/agents/gsd-doc-classifier.md +168 -0
  13. package/agents/gsd-doc-synthesizer.md +204 -0
  14. package/agents/gsd-doc-verifier.md +217 -0
  15. package/agents/gsd-doc-writer.md +615 -0
  16. package/agents/gsd-domain-researcher.md +153 -0
  17. package/agents/gsd-eval-auditor.md +191 -0
  18. package/agents/gsd-eval-planner.md +154 -0
  19. package/agents/gsd-executor.md +603 -0
  20. package/agents/gsd-framework-selector.md +160 -0
  21. package/agents/gsd-integration-checker.md +470 -0
  22. package/agents/gsd-intel-updater.md +334 -0
  23. package/agents/gsd-nyquist-auditor.md +203 -0
  24. package/agents/gsd-pattern-mapper.md +335 -0
  25. package/agents/gsd-phase-researcher.md +841 -0
  26. package/agents/gsd-plan-checker.md +978 -0
  27. package/agents/gsd-planner.md +1251 -0
  28. package/agents/gsd-project-researcher.md +677 -0
  29. package/agents/gsd-research-synthesizer.md +247 -0
  30. package/agents/gsd-roadmapper.md +688 -0
  31. package/agents/gsd-security-auditor.md +155 -0
  32. package/agents/gsd-ui-auditor.md +495 -0
  33. package/agents/gsd-ui-checker.md +309 -0
  34. package/agents/gsd-ui-researcher.md +380 -0
  35. package/agents/gsd-user-profiler.md +171 -0
  36. package/agents/gsd-verifier.md +830 -0
  37. package/bin/install.js +7062 -0
  38. package/commands/gsd/add-backlog.md +79 -0
  39. package/commands/gsd/add-phase.md +43 -0
  40. package/commands/gsd/add-tests.md +41 -0
  41. package/commands/gsd/add-todo.md +47 -0
  42. package/commands/gsd/ai-integration-phase.md +36 -0
  43. package/commands/gsd/analyze-dependencies.md +34 -0
  44. package/commands/gsd/audit-fix.md +33 -0
  45. package/commands/gsd/audit-milestone.md +36 -0
  46. package/commands/gsd/audit-uat.md +24 -0
  47. package/commands/gsd/autonomous.md +46 -0
  48. package/commands/gsd/check-todos.md +45 -0
  49. package/commands/gsd/cleanup.md +23 -0
  50. package/commands/gsd/code-review-fix.md +52 -0
  51. package/commands/gsd/code-review.md +55 -0
  52. package/commands/gsd/complete-milestone.md +136 -0
  53. package/commands/gsd/debug.md +263 -0
  54. package/commands/gsd/discuss-phase.md +69 -0
  55. package/commands/gsd/do.md +30 -0
  56. package/commands/gsd/docs-update.md +48 -0
  57. package/commands/gsd/eval-review.md +32 -0
  58. package/commands/gsd/execute-phase.md +63 -0
  59. package/commands/gsd/explore.md +27 -0
  60. package/commands/gsd/extract_learnings.md +22 -0
  61. package/commands/gsd/fast.md +30 -0
  62. package/commands/gsd/forensics.md +56 -0
  63. package/commands/gsd/from-gsd2.md +47 -0
  64. package/commands/gsd/graphify.md +201 -0
  65. package/commands/gsd/health.md +22 -0
  66. package/commands/gsd/help.md +24 -0
  67. package/commands/gsd/import.md +37 -0
  68. package/commands/gsd/inbox.md +38 -0
  69. package/commands/gsd/ingest-docs.md +42 -0
  70. package/commands/gsd/insert-phase.md +32 -0
  71. package/commands/gsd/intel.md +179 -0
  72. package/commands/gsd/join-discord.md +19 -0
  73. package/commands/gsd/list-phase-assumptions.md +46 -0
  74. package/commands/gsd/list-workspaces.md +19 -0
  75. package/commands/gsd/manager.md +40 -0
  76. package/commands/gsd/map-codebase.md +71 -0
  77. package/commands/gsd/milestone-summary.md +51 -0
  78. package/commands/gsd/new-milestone.md +44 -0
  79. package/commands/gsd/new-project.md +46 -0
  80. package/commands/gsd/new-workspace.md +44 -0
  81. package/commands/gsd/next.md +28 -0
  82. package/commands/gsd/note.md +34 -0
  83. package/commands/gsd/pause-work.md +38 -0
  84. package/commands/gsd/plan-milestone-gaps.md +34 -0
  85. package/commands/gsd/plan-phase.md +52 -0
  86. package/commands/gsd/plan-review-convergence.md +52 -0
  87. package/commands/gsd/plant-seed.md +28 -0
  88. package/commands/gsd/pr-branch.md +25 -0
  89. package/commands/gsd/profile-user.md +46 -0
  90. package/commands/gsd/progress.md +25 -0
  91. package/commands/gsd/quick.md +173 -0
  92. package/commands/gsd/reapply-patches.md +331 -0
  93. package/commands/gsd/remove-phase.md +31 -0
  94. package/commands/gsd/remove-workspace.md +26 -0
  95. package/commands/gsd/research-phase.md +195 -0
  96. package/commands/gsd/resume-work.md +40 -0
  97. package/commands/gsd/review-backlog.md +62 -0
  98. package/commands/gsd/review.md +40 -0
  99. package/commands/gsd/scan.md +26 -0
  100. package/commands/gsd/secure-phase.md +35 -0
  101. package/commands/gsd/session-report.md +19 -0
  102. package/commands/gsd/set-profile.md +12 -0
  103. package/commands/gsd/settings.md +36 -0
  104. package/commands/gsd/ship.md +23 -0
  105. package/commands/gsd/sketch-wrap-up.md +31 -0
  106. package/commands/gsd/sketch.md +49 -0
  107. package/commands/gsd/spec-phase.md +62 -0
  108. package/commands/gsd/spike-wrap-up.md +31 -0
  109. package/commands/gsd/spike.md +46 -0
  110. package/commands/gsd/stats.md +18 -0
  111. package/commands/gsd/sync-skills.md +19 -0
  112. package/commands/gsd/thread.md +227 -0
  113. package/commands/gsd/ui-phase.md +34 -0
  114. package/commands/gsd/ui-review.md +32 -0
  115. package/commands/gsd/ultraplan-phase.md +33 -0
  116. package/commands/gsd/undo.md +34 -0
  117. package/commands/gsd/update.md +37 -0
  118. package/commands/gsd/validate-phase.md +35 -0
  119. package/commands/gsd/verify-work.md +38 -0
  120. package/commands/gsd/workstreams.md +69 -0
  121. package/get-shit-done/bin/gsd-tools.cjs +1263 -0
  122. package/get-shit-done/bin/lib/artifacts.cjs +52 -0
  123. package/get-shit-done/bin/lib/audit.cjs +757 -0
  124. package/get-shit-done/bin/lib/commands.cjs +1023 -0
  125. package/get-shit-done/bin/lib/config-schema.cjs +79 -0
  126. package/get-shit-done/bin/lib/config.cjs +463 -0
  127. package/get-shit-done/bin/lib/core.cjs +1794 -0
  128. package/get-shit-done/bin/lib/docs.cjs +267 -0
  129. package/get-shit-done/bin/lib/frontmatter.cjs +379 -0
  130. package/get-shit-done/bin/lib/graphify.cjs +494 -0
  131. package/get-shit-done/bin/lib/gsd2-import.cjs +511 -0
  132. package/get-shit-done/bin/lib/init.cjs +1878 -0
  133. package/get-shit-done/bin/lib/intel.cjs +639 -0
  134. package/get-shit-done/bin/lib/learnings.cjs +378 -0
  135. package/get-shit-done/bin/lib/milestone.cjs +283 -0
  136. package/get-shit-done/bin/lib/model-profiles.cjs +71 -0
  137. package/get-shit-done/bin/lib/phase.cjs +1058 -0
  138. package/get-shit-done/bin/lib/profile-output.cjs +1080 -0
  139. package/get-shit-done/bin/lib/profile-pipeline.cjs +539 -0
  140. package/get-shit-done/bin/lib/roadmap.cjs +523 -0
  141. package/get-shit-done/bin/lib/schema-detect.cjs +238 -0
  142. package/get-shit-done/bin/lib/security.cjs +504 -0
  143. package/get-shit-done/bin/lib/state.cjs +1649 -0
  144. package/get-shit-done/bin/lib/template.cjs +226 -0
  145. package/get-shit-done/bin/lib/uat.cjs +288 -0
  146. package/get-shit-done/bin/lib/verify.cjs +1184 -0
  147. package/get-shit-done/bin/lib/workstream.cjs +495 -0
  148. package/get-shit-done/bin/repair-sdk.cjs +177 -0
  149. package/get-shit-done/contexts/dev.md +21 -0
  150. package/get-shit-done/contexts/research.md +22 -0
  151. package/get-shit-done/contexts/review.md +22 -0
  152. package/get-shit-done/references/agent-contracts.md +79 -0
  153. package/get-shit-done/references/ai-evals.md +156 -0
  154. package/get-shit-done/references/ai-frameworks.md +186 -0
  155. package/get-shit-done/references/artifact-types.md +131 -0
  156. package/get-shit-done/references/autonomous-smart-discuss.md +277 -0
  157. package/get-shit-done/references/checkpoints.md +808 -0
  158. package/get-shit-done/references/common-bug-patterns.md +114 -0
  159. package/get-shit-done/references/context-budget.md +49 -0
  160. package/get-shit-done/references/continuation-format.md +253 -0
  161. package/get-shit-done/references/debugger-philosophy.md +76 -0
  162. package/get-shit-done/references/decimal-phase-calculation.md +64 -0
  163. package/get-shit-done/references/doc-conflict-engine.md +91 -0
  164. package/get-shit-done/references/domain-probes.md +125 -0
  165. package/get-shit-done/references/executor-examples.md +110 -0
  166. package/get-shit-done/references/few-shot-examples/plan-checker.md +73 -0
  167. package/get-shit-done/references/few-shot-examples/verifier.md +109 -0
  168. package/get-shit-done/references/gate-prompts.md +100 -0
  169. package/get-shit-done/references/gates.md +70 -0
  170. package/get-shit-done/references/git-integration.md +295 -0
  171. package/get-shit-done/references/git-planning-commit.md +40 -0
  172. package/get-shit-done/references/ios-scaffold.md +123 -0
  173. package/get-shit-done/references/mandatory-initial-read.md +2 -0
  174. package/get-shit-done/references/model-profile-resolution.md +38 -0
  175. package/get-shit-done/references/model-profiles.md +145 -0
  176. package/get-shit-done/references/phase-argument-parsing.md +61 -0
  177. package/get-shit-done/references/planner-antipatterns.md +89 -0
  178. package/get-shit-done/references/planner-gap-closure.md +62 -0
  179. package/get-shit-done/references/planner-reviews.md +39 -0
  180. package/get-shit-done/references/planner-revision.md +87 -0
  181. package/get-shit-done/references/planner-source-audit.md +73 -0
  182. package/get-shit-done/references/planning-config.md +460 -0
  183. package/get-shit-done/references/project-skills-discovery.md +19 -0
  184. package/get-shit-done/references/questioning.md +162 -0
  185. package/get-shit-done/references/revision-loop.md +97 -0
  186. package/get-shit-done/references/sketch-interactivity.md +41 -0
  187. package/get-shit-done/references/sketch-theme-system.md +94 -0
  188. package/get-shit-done/references/sketch-tooling.md +45 -0
  189. package/get-shit-done/references/sketch-variant-patterns.md +81 -0
  190. package/get-shit-done/references/tdd.md +330 -0
  191. package/get-shit-done/references/thinking-models-debug.md +44 -0
  192. package/get-shit-done/references/thinking-models-execution.md +50 -0
  193. package/get-shit-done/references/thinking-models-planning.md +62 -0
  194. package/get-shit-done/references/thinking-models-research.md +50 -0
  195. package/get-shit-done/references/thinking-models-verification.md +55 -0
  196. package/get-shit-done/references/thinking-partner.md +96 -0
  197. package/get-shit-done/references/ui-brand.md +160 -0
  198. package/get-shit-done/references/universal-anti-patterns.md +63 -0
  199. package/get-shit-done/references/user-profiling.md +681 -0
  200. package/get-shit-done/references/verification-overrides.md +227 -0
  201. package/get-shit-done/references/verification-patterns.md +612 -0
  202. package/get-shit-done/references/workstream-flag.md +111 -0
  203. package/get-shit-done/templates/AI-SPEC.md +246 -0
  204. package/get-shit-done/templates/DEBUG.md +169 -0
  205. package/get-shit-done/templates/README.md +76 -0
  206. package/get-shit-done/templates/SECURITY.md +61 -0
  207. package/get-shit-done/templates/UAT.md +265 -0
  208. package/get-shit-done/templates/UI-SPEC.md +100 -0
  209. package/get-shit-done/templates/VALIDATION.md +76 -0
  210. package/get-shit-done/templates/claude-md.md +145 -0
  211. package/get-shit-done/templates/codebase/architecture.md +255 -0
  212. package/get-shit-done/templates/codebase/concerns.md +310 -0
  213. package/get-shit-done/templates/codebase/conventions.md +307 -0
  214. package/get-shit-done/templates/codebase/integrations.md +280 -0
  215. package/get-shit-done/templates/codebase/stack.md +186 -0
  216. package/get-shit-done/templates/codebase/structure.md +285 -0
  217. package/get-shit-done/templates/codebase/testing.md +480 -0
  218. package/get-shit-done/templates/config.json +56 -0
  219. package/get-shit-done/templates/context.md +352 -0
  220. package/get-shit-done/templates/continue-here.md +78 -0
  221. package/get-shit-done/templates/copilot-instructions.md +7 -0
  222. package/get-shit-done/templates/debug-subagent-prompt.md +91 -0
  223. package/get-shit-done/templates/dev-preferences.md +21 -0
  224. package/get-shit-done/templates/discovery.md +146 -0
  225. package/get-shit-done/templates/discussion-log.md +63 -0
  226. package/get-shit-done/templates/milestone-archive.md +123 -0
  227. package/get-shit-done/templates/milestone.md +115 -0
  228. package/get-shit-done/templates/phase-prompt.md +610 -0
  229. package/get-shit-done/templates/planner-subagent-prompt.md +117 -0
  230. package/get-shit-done/templates/project.md +186 -0
  231. package/get-shit-done/templates/requirements.md +231 -0
  232. package/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
  233. package/get-shit-done/templates/research-project/FEATURES.md +147 -0
  234. package/get-shit-done/templates/research-project/PITFALLS.md +200 -0
  235. package/get-shit-done/templates/research-project/STACK.md +120 -0
  236. package/get-shit-done/templates/research-project/SUMMARY.md +170 -0
  237. package/get-shit-done/templates/research.md +592 -0
  238. package/get-shit-done/templates/retrospective.md +54 -0
  239. package/get-shit-done/templates/roadmap.md +202 -0
  240. package/get-shit-done/templates/spec.md +307 -0
  241. package/get-shit-done/templates/state.md +184 -0
  242. package/get-shit-done/templates/summary-complex.md +59 -0
  243. package/get-shit-done/templates/summary-minimal.md +41 -0
  244. package/get-shit-done/templates/summary-standard.md +48 -0
  245. package/get-shit-done/templates/summary.md +248 -0
  246. package/get-shit-done/templates/user-profile.md +146 -0
  247. package/get-shit-done/templates/user-setup.md +311 -0
  248. package/get-shit-done/templates/verification-report.md +322 -0
  249. package/get-shit-done/workflows/add-phase.md +112 -0
  250. package/get-shit-done/workflows/add-tests.md +354 -0
  251. package/get-shit-done/workflows/add-todo.md +160 -0
  252. package/get-shit-done/workflows/ai-integration-phase.md +284 -0
  253. package/get-shit-done/workflows/analyze-dependencies.md +96 -0
  254. package/get-shit-done/workflows/audit-fix.md +175 -0
  255. package/get-shit-done/workflows/audit-milestone.md +340 -0
  256. package/get-shit-done/workflows/audit-uat.md +109 -0
  257. package/get-shit-done/workflows/autonomous.md +789 -0
  258. package/get-shit-done/workflows/check-todos.md +179 -0
  259. package/get-shit-done/workflows/cleanup.md +154 -0
  260. package/get-shit-done/workflows/code-review-fix.md +497 -0
  261. package/get-shit-done/workflows/code-review.md +515 -0
  262. package/get-shit-done/workflows/complete-milestone.md +847 -0
  263. package/get-shit-done/workflows/diagnose-issues.md +238 -0
  264. package/get-shit-done/workflows/discovery-phase.md +291 -0
  265. package/get-shit-done/workflows/discuss-phase-assumptions.md +670 -0
  266. package/get-shit-done/workflows/discuss-phase-power.md +308 -0
  267. package/get-shit-done/workflows/discuss-phase.md +1378 -0
  268. package/get-shit-done/workflows/do.md +110 -0
  269. package/get-shit-done/workflows/docs-update.md +1155 -0
  270. package/get-shit-done/workflows/eval-review.md +155 -0
  271. package/get-shit-done/workflows/execute-phase.md +1677 -0
  272. package/get-shit-done/workflows/execute-plan.md +533 -0
  273. package/get-shit-done/workflows/explore.md +141 -0
  274. package/get-shit-done/workflows/extract_learnings.md +242 -0
  275. package/get-shit-done/workflows/fast.md +105 -0
  276. package/get-shit-done/workflows/forensics.md +265 -0
  277. package/get-shit-done/workflows/graduation.md +195 -0
  278. package/get-shit-done/workflows/health.md +314 -0
  279. package/get-shit-done/workflows/help.md +667 -0
  280. package/get-shit-done/workflows/import.md +246 -0
  281. package/get-shit-done/workflows/inbox.md +387 -0
  282. package/get-shit-done/workflows/ingest-docs.md +328 -0
  283. package/get-shit-done/workflows/insert-phase.md +130 -0
  284. package/get-shit-done/workflows/list-phase-assumptions.md +178 -0
  285. package/get-shit-done/workflows/list-workspaces.md +56 -0
  286. package/get-shit-done/workflows/manager.md +365 -0
  287. package/get-shit-done/workflows/map-codebase.md +393 -0
  288. package/get-shit-done/workflows/milestone-summary.md +223 -0
  289. package/get-shit-done/workflows/new-milestone.md +611 -0
  290. package/get-shit-done/workflows/new-project.md +1391 -0
  291. package/get-shit-done/workflows/new-workspace.md +239 -0
  292. package/get-shit-done/workflows/next.md +220 -0
  293. package/get-shit-done/workflows/node-repair.md +92 -0
  294. package/get-shit-done/workflows/note.md +158 -0
  295. package/get-shit-done/workflows/pause-work.md +243 -0
  296. package/get-shit-done/workflows/plan-milestone-gaps.md +273 -0
  297. package/get-shit-done/workflows/plan-phase.md +1349 -0
  298. package/get-shit-done/workflows/plan-review-convergence.md +254 -0
  299. package/get-shit-done/workflows/plant-seed.md +172 -0
  300. package/get-shit-done/workflows/pr-branch.md +157 -0
  301. package/get-shit-done/workflows/profile-user.md +452 -0
  302. package/get-shit-done/workflows/progress.md +619 -0
  303. package/get-shit-done/workflows/quick.md +970 -0
  304. package/get-shit-done/workflows/remove-phase.md +155 -0
  305. package/get-shit-done/workflows/remove-workspace.md +92 -0
  306. package/get-shit-done/workflows/research-phase.md +89 -0
  307. package/get-shit-done/workflows/resume-project.md +326 -0
  308. package/get-shit-done/workflows/review.md +344 -0
  309. package/get-shit-done/workflows/scan.md +102 -0
  310. package/get-shit-done/workflows/secure-phase.md +166 -0
  311. package/get-shit-done/workflows/session-report.md +146 -0
  312. package/get-shit-done/workflows/settings.md +319 -0
  313. package/get-shit-done/workflows/ship.md +302 -0
  314. package/get-shit-done/workflows/sketch-wrap-up.md +283 -0
  315. package/get-shit-done/workflows/sketch.md +286 -0
  316. package/get-shit-done/workflows/spec-phase.md +262 -0
  317. package/get-shit-done/workflows/spike-wrap-up.md +281 -0
  318. package/get-shit-done/workflows/spike.md +362 -0
  319. package/get-shit-done/workflows/stats.md +60 -0
  320. package/get-shit-done/workflows/sync-skills.md +182 -0
  321. package/get-shit-done/workflows/transition.md +693 -0
  322. package/get-shit-done/workflows/ui-phase.md +323 -0
  323. package/get-shit-done/workflows/ui-review.md +190 -0
  324. package/get-shit-done/workflows/ultraplan-phase.md +189 -0
  325. package/get-shit-done/workflows/undo.md +314 -0
  326. package/get-shit-done/workflows/update.md +587 -0
  327. package/get-shit-done/workflows/validate-phase.md +176 -0
  328. package/get-shit-done/workflows/verify-phase.md +465 -0
  329. package/get-shit-done/workflows/verify-work.md +740 -0
  330. package/hooks/dist/gsd-check-update-worker.js +108 -0
  331. package/hooks/dist/gsd-check-update.js +64 -0
  332. package/hooks/dist/gsd-context-monitor.js +192 -0
  333. package/hooks/dist/gsd-phase-boundary.sh +28 -0
  334. package/hooks/dist/gsd-prompt-guard.js +97 -0
  335. package/hooks/dist/gsd-read-guard.js +82 -0
  336. package/hooks/dist/gsd-read-injection-scanner.js +152 -0
  337. package/hooks/dist/gsd-session-state.sh +34 -0
  338. package/hooks/dist/gsd-statusline.js +293 -0
  339. package/hooks/dist/gsd-validate-commit.sh +48 -0
  340. package/hooks/dist/gsd-workflow-guard.js +94 -0
  341. package/hooks/gsd-check-update-worker.js +108 -0
  342. package/hooks/gsd-check-update.js +64 -0
  343. package/hooks/gsd-context-monitor.js +192 -0
  344. package/hooks/gsd-phase-boundary.sh +28 -0
  345. package/hooks/gsd-prompt-guard.js +97 -0
  346. package/hooks/gsd-read-guard.js +82 -0
  347. package/hooks/gsd-read-injection-scanner.js +152 -0
  348. package/hooks/gsd-session-state.sh +34 -0
  349. package/hooks/gsd-statusline.js +293 -0
  350. package/hooks/gsd-validate-commit.sh +48 -0
  351. package/hooks/gsd-workflow-guard.js +94 -0
  352. package/package.json +59 -0
  353. package/scripts/base64-scan.sh +262 -0
  354. package/scripts/build-hooks.js +95 -0
  355. package/scripts/gen-inventory-manifest.cjs +109 -0
  356. package/scripts/prompt-injection-scan.sh +201 -0
  357. package/scripts/run-tests.cjs +33 -0
  358. package/scripts/secret-scan.sh +227 -0
  359. package/sdk/package-lock.json +1998 -0
  360. package/sdk/package.json +52 -0
  361. package/sdk/prompts/agents/gsd-executor.md +110 -0
  362. package/sdk/prompts/agents/gsd-phase-researcher.md +158 -0
  363. package/sdk/prompts/agents/gsd-plan-checker.md +160 -0
  364. package/sdk/prompts/agents/gsd-planner.md +214 -0
  365. package/sdk/prompts/agents/gsd-project-researcher.md +323 -0
  366. package/sdk/prompts/agents/gsd-research-synthesizer.md +237 -0
  367. package/sdk/prompts/agents/gsd-roadmapper.md +670 -0
  368. package/sdk/prompts/agents/gsd-verifier.md +159 -0
  369. package/sdk/prompts/templates/project.md +186 -0
  370. package/sdk/prompts/templates/requirements.md +231 -0
  371. package/sdk/prompts/templates/research-project/ARCHITECTURE.md +204 -0
  372. package/sdk/prompts/templates/research-project/FEATURES.md +147 -0
  373. package/sdk/prompts/templates/research-project/PITFALLS.md +200 -0
  374. package/sdk/prompts/templates/research-project/STACK.md +120 -0
  375. package/sdk/prompts/templates/research-project/SUMMARY.md +170 -0
  376. package/sdk/prompts/templates/roadmap.md +202 -0
  377. package/sdk/prompts/templates/state.md +175 -0
  378. package/sdk/prompts/workflows/discuss-phase.md +126 -0
  379. package/sdk/prompts/workflows/execute-plan.md +106 -0
  380. package/sdk/prompts/workflows/plan-phase.md +84 -0
  381. package/sdk/prompts/workflows/research-phase.md +45 -0
  382. package/sdk/prompts/workflows/verify-phase.md +142 -0
  383. package/sdk/src/assembled-prompts.test.ts +349 -0
  384. package/sdk/src/cli-transport.test.ts +388 -0
  385. package/sdk/src/cli-transport.ts +130 -0
  386. package/sdk/src/cli.test.ts +383 -0
  387. package/sdk/src/cli.ts +670 -0
  388. package/sdk/src/config.test.ts +168 -0
  389. package/sdk/src/config.ts +177 -0
  390. package/sdk/src/context-engine.test.ts +295 -0
  391. package/sdk/src/context-engine.ts +170 -0
  392. package/sdk/src/context-truncation.test.ts +163 -0
  393. package/sdk/src/context-truncation.ts +233 -0
  394. package/sdk/src/e2e.integration.test.ts +178 -0
  395. package/sdk/src/errors.ts +72 -0
  396. package/sdk/src/event-stream.test.ts +661 -0
  397. package/sdk/src/event-stream.ts +441 -0
  398. package/sdk/src/failure-memory.test.ts +457 -0
  399. package/sdk/src/failure-memory.ts +1324 -0
  400. package/sdk/src/golden/capture.ts +95 -0
  401. package/sdk/src/golden/fixtures/generate-slug.golden.json +1 -0
  402. package/sdk/src/golden/fixtures/profile-sample-sessions/demo-project/sample.jsonl +3 -0
  403. package/sdk/src/golden/fixtures/summary-extract-sample.md +26 -0
  404. package/sdk/src/golden/fixtures/uat-render-checkpoint-sample.md +15 -0
  405. package/sdk/src/golden/golden-integration-covered.ts +30 -0
  406. package/sdk/src/golden/golden-mutation-covered.ts +7 -0
  407. package/sdk/src/golden/golden-policy.test.ts +8 -0
  408. package/sdk/src/golden/golden-policy.ts +112 -0
  409. package/sdk/src/golden/golden.integration.test.ts +373 -0
  410. package/sdk/src/golden/init-golden-normalize.ts +15 -0
  411. package/sdk/src/golden/read-only-golden-rows.ts +77 -0
  412. package/sdk/src/golden/read-only-parity.integration.test.ts +125 -0
  413. package/sdk/src/golden/registry-canonical-commands.ts +31 -0
  414. package/sdk/src/gsd-tools.test.ts +409 -0
  415. package/sdk/src/gsd-tools.ts +595 -0
  416. package/sdk/src/headless-prompts.test.ts +159 -0
  417. package/sdk/src/index.ts +333 -0
  418. package/sdk/src/init-e2e.integration.test.ts +136 -0
  419. package/sdk/src/init-runner.test.ts +783 -0
  420. package/sdk/src/init-runner.ts +735 -0
  421. package/sdk/src/lifecycle-e2e.integration.test.ts +258 -0
  422. package/sdk/src/logger.test.ts +149 -0
  423. package/sdk/src/logger.ts +113 -0
  424. package/sdk/src/milestone-runner.test.ts +421 -0
  425. package/sdk/src/phase-prompt.test.ts +538 -0
  426. package/sdk/src/phase-prompt.ts +264 -0
  427. package/sdk/src/phase-runner-types.test.ts +421 -0
  428. package/sdk/src/phase-runner.integration.test.ts +377 -0
  429. package/sdk/src/phase-runner.test.ts +2333 -0
  430. package/sdk/src/phase-runner.ts +1203 -0
  431. package/sdk/src/plan-parser.test.ts +528 -0
  432. package/sdk/src/plan-parser.ts +427 -0
  433. package/sdk/src/prompt-builder.test.ts +306 -0
  434. package/sdk/src/prompt-builder.ts +193 -0
  435. package/sdk/src/prompt-sanitizer.test.ts +260 -0
  436. package/sdk/src/prompt-sanitizer.ts +71 -0
  437. package/sdk/src/query/QUERY-HANDLERS.md +317 -0
  438. package/sdk/src/query/audit-open.ts +722 -0
  439. package/sdk/src/query/check-auto-mode.test.ts +77 -0
  440. package/sdk/src/query/check-auto-mode.ts +50 -0
  441. package/sdk/src/query/check-completion.test.ts +113 -0
  442. package/sdk/src/query/check-completion.ts +182 -0
  443. package/sdk/src/query/check-gates.test.ts +103 -0
  444. package/sdk/src/query/check-gates.ts +112 -0
  445. package/sdk/src/query/check-ship-ready.test.ts +77 -0
  446. package/sdk/src/query/check-ship-ready.ts +103 -0
  447. package/sdk/src/query/check-verification-status.test.ts +143 -0
  448. package/sdk/src/query/check-verification-status.ts +160 -0
  449. package/sdk/src/query/commit.test.ts +202 -0
  450. package/sdk/src/query/commit.ts +301 -0
  451. package/sdk/src/query/config-gates.test.ts +89 -0
  452. package/sdk/src/query/config-gates.ts +69 -0
  453. package/sdk/src/query/config-mutation.test.ts +365 -0
  454. package/sdk/src/query/config-mutation.ts +497 -0
  455. package/sdk/src/query/config-query.test.ts +161 -0
  456. package/sdk/src/query/config-query.ts +190 -0
  457. package/sdk/src/query/context-history.test.ts +165 -0
  458. package/sdk/src/query/context-history.ts +467 -0
  459. package/sdk/src/query/decomposed-handlers.test.ts +365 -0
  460. package/sdk/src/query/detect-custom-files.ts +97 -0
  461. package/sdk/src/query/detect-phase-type.test.ts +105 -0
  462. package/sdk/src/query/detect-phase-type.ts +141 -0
  463. package/sdk/src/query/docs-init.ts +257 -0
  464. package/sdk/src/query/failure-capture.ts +58 -0
  465. package/sdk/src/query/frontmatter-array.test.ts +14 -0
  466. package/sdk/src/query/frontmatter-mutation.test.ts +259 -0
  467. package/sdk/src/query/frontmatter-mutation.ts +343 -0
  468. package/sdk/src/query/frontmatter.test.ts +281 -0
  469. package/sdk/src/query/frontmatter.ts +397 -0
  470. package/sdk/src/query/helpers.test.ts +426 -0
  471. package/sdk/src/query/helpers.ts +482 -0
  472. package/sdk/src/query/index.ts +586 -0
  473. package/sdk/src/query/init-complex.test.ts +232 -0
  474. package/sdk/src/query/init-complex.ts +578 -0
  475. package/sdk/src/query/init.test.ts +522 -0
  476. package/sdk/src/query/init.ts +1046 -0
  477. package/sdk/src/query/intel.test.ts +90 -0
  478. package/sdk/src/query/intel.ts +404 -0
  479. package/sdk/src/query/normalize-query-command.test.ts +50 -0
  480. package/sdk/src/query/normalize-query-command.ts +56 -0
  481. package/sdk/src/query/phase-lifecycle.test.ts +1126 -0
  482. package/sdk/src/query/phase-lifecycle.ts +1799 -0
  483. package/sdk/src/query/phase-list-queries.test.ts +88 -0
  484. package/sdk/src/query/phase-list-queries.ts +152 -0
  485. package/sdk/src/query/phase-ready.test.ts +65 -0
  486. package/sdk/src/query/phase-ready.ts +158 -0
  487. package/sdk/src/query/phase.test.ts +307 -0
  488. package/sdk/src/query/phase.ts +340 -0
  489. package/sdk/src/query/pipeline.test.ts +169 -0
  490. package/sdk/src/query/pipeline.ts +243 -0
  491. package/sdk/src/query/plan-execution-route.test.ts +166 -0
  492. package/sdk/src/query/plan-execution-route.ts +209 -0
  493. package/sdk/src/query/plan-task-structure.test.ts +65 -0
  494. package/sdk/src/query/plan-task-structure.ts +63 -0
  495. package/sdk/src/query/profile-extract-messages.ts +247 -0
  496. package/sdk/src/query/profile-output.ts +908 -0
  497. package/sdk/src/query/profile-questionnaire-data.ts +181 -0
  498. package/sdk/src/query/profile-sample.ts +184 -0
  499. package/sdk/src/query/profile-scan-sessions.ts +174 -0
  500. package/sdk/src/query/profile.test.ts +74 -0
  501. package/sdk/src/query/profile.ts +337 -0
  502. package/sdk/src/query/progress.test.ts +156 -0
  503. package/sdk/src/query/progress.ts +566 -0
  504. package/sdk/src/query/registry.test.ts +216 -0
  505. package/sdk/src/query/registry.ts +174 -0
  506. package/sdk/src/query/requirements-extract-from-plans.test.ts +58 -0
  507. package/sdk/src/query/requirements-extract-from-plans.ts +86 -0
  508. package/sdk/src/query/roadmap-update-plan-progress.ts +132 -0
  509. package/sdk/src/query/roadmap.test.ts +359 -0
  510. package/sdk/src/query/roadmap.ts +591 -0
  511. package/sdk/src/query/route-next-action.test.ts +61 -0
  512. package/sdk/src/query/route-next-action.ts +345 -0
  513. package/sdk/src/query/runtime-health.ts +7 -0
  514. package/sdk/src/query/schema-detect.ts +189 -0
  515. package/sdk/src/query/skill-manifest.ts +214 -0
  516. package/sdk/src/query/skills.test.ts +80 -0
  517. package/sdk/src/query/skills.ts +62 -0
  518. package/sdk/src/query/state-mutation.test.ts +450 -0
  519. package/sdk/src/query/state-mutation.ts +1444 -0
  520. package/sdk/src/query/state-project-load.ts +109 -0
  521. package/sdk/src/query/state.test.ts +347 -0
  522. package/sdk/src/query/state.ts +397 -0
  523. package/sdk/src/query/summary.test.ts +95 -0
  524. package/sdk/src/query/summary.ts +296 -0
  525. package/sdk/src/query/template.test.ts +180 -0
  526. package/sdk/src/query/template.ts +242 -0
  527. package/sdk/src/query/uat.test.ts +77 -0
  528. package/sdk/src/query/uat.ts +314 -0
  529. package/sdk/src/query/utils.test.ts +82 -0
  530. package/sdk/src/query/utils.ts +92 -0
  531. package/sdk/src/query/validate.test.ts +656 -0
  532. package/sdk/src/query/validate.ts +807 -0
  533. package/sdk/src/query/verify.test.ts +414 -0
  534. package/sdk/src/query/verify.ts +645 -0
  535. package/sdk/src/query/websearch.test.ts +31 -0
  536. package/sdk/src/query/websearch.ts +82 -0
  537. package/sdk/src/query/workspace.test.ts +119 -0
  538. package/sdk/src/query/workspace.ts +131 -0
  539. package/sdk/src/query/workstream.test.ts +51 -0
  540. package/sdk/src/query/workstream.ts +434 -0
  541. package/sdk/src/research-gate.test.ts +190 -0
  542. package/sdk/src/research-gate.ts +94 -0
  543. package/sdk/src/runtime-health.test.ts +176 -0
  544. package/sdk/src/runtime-health.ts +387 -0
  545. package/sdk/src/session-runner.test.ts +98 -0
  546. package/sdk/src/session-runner.ts +299 -0
  547. package/sdk/src/tool-scoping.test.ts +160 -0
  548. package/sdk/src/tool-scoping.ts +61 -0
  549. package/sdk/src/types.ts +917 -0
  550. package/sdk/src/workstream-utils.ts +33 -0
  551. package/sdk/src/ws-flag.test.ts +285 -0
  552. package/sdk/src/ws-transport.test.ts +161 -0
  553. package/sdk/src/ws-transport.ts +93 -0
  554. package/sdk/tsconfig.json +20 -0
@@ -0,0 +1,258 @@
1
+ /**
2
+ * E2E lifecycle integration test — proves GSD.runPhase() drives
3
+ * the full phase lifecycle: discuss → research → plan → execute → verify → advance
4
+ * after bootstrapping a real project via InitRunner.
5
+ *
6
+ * This is the capstone proof that `gsd-remix-sdk auto` works end-to-end
7
+ * without human intervention. InitRunner bootstraps the project,
8
+ * then GSD.runPhase() drives Phase 1 through the complete lifecycle.
9
+ *
10
+ * Requires Claude Code CLI (`claude`) installed and authenticated.
11
+ * Skips gracefully if CLI is unavailable.
12
+ */
13
+
14
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
15
+ import { execSync } from 'node:child_process';
16
+ import { mkdtemp, rm, readFile, stat, readdir } from 'node:fs/promises';
17
+ import { existsSync } from 'node:fs';
18
+ import { join } from 'node:path';
19
+ import { tmpdir } from 'node:os';
20
+ import { fileURLToPath } from 'node:url';
21
+
22
+ import { GSD } from './index.js';
23
+ import { InitRunner } from './init-runner.js';
24
+ import { GSDTools, resolveGsdToolsPath } from './gsd-tools.js';
25
+ import { GSDEventStream } from './event-stream.js';
26
+ import { GSDEventType, PhaseStepType } from './types.js';
27
+ import type { GSDEvent, PhaseRunnerResult, RoadmapAnalysis } from './types.js';
28
+
29
+ // ─── CLI availability check ─────────────────────────────────────────────────
30
+
31
+ let cliAvailable = false;
32
+ try {
33
+ execSync('which claude', { stdio: 'ignore' });
34
+ cliAvailable = true;
35
+ } catch {
36
+ cliAvailable = false;
37
+ }
38
+
39
+ const __dirname = fileURLToPath(new URL('.', import.meta.url));
40
+ const sdkPromptsDir = join(__dirname, '..', 'prompts');
41
+ const GSD_TOOLS_PATH = resolveGsdToolsPath(process.cwd());
42
+ const gsdToolsAvailable = existsSync(GSD_TOOLS_PATH);
43
+
44
+ // ─── Lifecycle step ordering for monotonicity check ──────────────────────────
45
+
46
+ const STEP_ORDER: Record<string, number> = {
47
+ [PhaseStepType.Discuss]: 0,
48
+ [PhaseStepType.Research]: 1,
49
+ [PhaseStepType.Plan]: 2,
50
+ [PhaseStepType.PlanCheck]: 3,
51
+ [PhaseStepType.Execute]: 4,
52
+ [PhaseStepType.Verify]: 5,
53
+ [PhaseStepType.Advance]: 6,
54
+ };
55
+
56
+ // ─── Test suite ──────────────────────────────────────────────────────────────
57
+
58
+ describe.skipIf(!cliAvailable || !gsdToolsAvailable)('E2E Lifecycle: InitRunner → GSD.runPhase() full lifecycle', () => {
59
+ let tmpDir: string;
60
+ let initSuccess: boolean = false;
61
+ let phase1Number: string | null = null;
62
+ let tools: GSDTools;
63
+
64
+ // ── Bootstrap: create temp dir, git init, run InitRunner ──────────────
65
+ beforeAll(async () => {
66
+ tmpDir = await mkdtemp(join(tmpdir(), 'gsd-remix-sdk-lifecycle-e2e-'));
67
+
68
+ // Git init (required by InitRunner and phase lifecycle)
69
+ execSync('git init', { cwd: tmpDir, stdio: 'ignore' });
70
+ execSync('git config user.email "test@test.com"', { cwd: tmpDir, stdio: 'ignore' });
71
+ execSync('git config user.name "Test"', { cwd: tmpDir, stdio: 'ignore' });
72
+
73
+ tools = new GSDTools({
74
+ projectDir: tmpDir,
75
+ gsdToolsPath: GSD_TOOLS_PATH,
76
+ timeoutMs: 30_000,
77
+ });
78
+
79
+ // Run InitRunner to bootstrap the project
80
+ const initEventStream = new GSDEventStream();
81
+ const initRunner = new InitRunner({
82
+ projectDir: tmpDir,
83
+ tools,
84
+ eventStream: initEventStream,
85
+ config: {
86
+ maxBudgetPerSession: 1.0,
87
+ maxTurnsPerSession: 15,
88
+ },
89
+ sdkPromptsDir,
90
+ });
91
+
92
+ const initResult = await initRunner.run('Build a CLI tool that converts Celsius to Fahrenheit');
93
+
94
+ // Mark init as successful if the pipeline progressed enough
95
+ const completedSteps = initResult.steps.filter(s => s.success);
96
+ initSuccess = initResult.success || completedSteps.length >= 3;
97
+
98
+ // Discover the first phase number via roadmapAnalyze
99
+ if (initSuccess) {
100
+ try {
101
+ const analysis: RoadmapAnalysis = await tools.roadmapAnalyze();
102
+ if (analysis.phases && analysis.phases.length > 0) {
103
+ // Sort by phase number and take the first
104
+ const sorted = [...analysis.phases].sort(
105
+ (a, b) => parseFloat(a.number) - parseFloat(b.number),
106
+ );
107
+ phase1Number = sorted[0]!.number;
108
+ }
109
+ } catch {
110
+ // If roadmap analyze fails, try scanning the phases dir directly
111
+ try {
112
+ const phasesDir = join(tmpDir, '.planning', 'phases');
113
+ const entries = await readdir(phasesDir);
114
+ const phaseEntries = entries
115
+ .filter(e => /^\d+/.test(e))
116
+ .sort();
117
+ if (phaseEntries.length > 0) {
118
+ // Extract the phase number (everything before the first dash)
119
+ const match = phaseEntries[0]!.match(/^(\d+)/);
120
+ if (match) {
121
+ phase1Number = match[1]!;
122
+ }
123
+ }
124
+ } catch {
125
+ // No phases dir — init didn't create one
126
+ }
127
+ }
128
+ }
129
+ }, 600_000); // 10 min for init
130
+
131
+ afterAll(async () => {
132
+ if (tmpDir) {
133
+ await rm(tmpDir, { recursive: true, force: true });
134
+ }
135
+ });
136
+
137
+ // ── Main lifecycle test ───────────────────────────────────────────────
138
+
139
+ it('GSD.runPhase() drives Phase 1 through the full lifecycle without human intervention', async () => {
140
+ // If init failed, skip — can't test lifecycle without a bootstrapped project
141
+ if (!initSuccess) {
142
+ console.warn('Skipping lifecycle test: InitRunner did not bootstrap successfully');
143
+ return;
144
+ }
145
+
146
+ // Verify ROADMAP.md exists and contains at least one phase
147
+ const roadmapPath = join(tmpDir, '.planning', 'ROADMAP.md');
148
+ const roadmapStat = await stat(roadmapPath).catch(() => null);
149
+ expect(roadmapStat).not.toBeNull();
150
+
151
+ const roadmapContent = await readFile(roadmapPath, 'utf-8');
152
+ expect(roadmapContent.length).toBeGreaterThan(0);
153
+
154
+ // Verify we discovered a phase number
155
+ expect(phase1Number).not.toBeNull();
156
+
157
+ // Verify the phase exists via initPhaseOp
158
+ const phaseOp = await tools.initPhaseOp(phase1Number!);
159
+ expect(phaseOp.phase_found).toBe(true);
160
+
161
+ // Collect all events during the phase lifecycle
162
+ const events: GSDEvent[] = [];
163
+
164
+ // Construct GSD with autoMode: true
165
+ const gsd = new GSD({
166
+ projectDir: tmpDir,
167
+ autoMode: true,
168
+ });
169
+ gsd.onEvent((e: GSDEvent) => events.push(e));
170
+
171
+ // Run the discovered first phase with tight budget to minimize cost
172
+ const result: PhaseRunnerResult = await gsd.runPhase(phase1Number!, {
173
+ maxTurnsPerStep: 10,
174
+ maxBudgetPerStep: 0.50,
175
+ });
176
+
177
+ // ── Assert: result.phaseNumber matches the discovered phase ──
178
+ expect(result.phaseNumber).toBe(phase1Number);
179
+
180
+ // ── Assert: result.phaseName is non-empty ──
181
+ expect(result.phaseName).toBeTruthy();
182
+ expect(result.phaseName.length).toBeGreaterThan(0);
183
+
184
+ // ── Assert: at least one lifecycle step was attempted ──
185
+ expect(result.steps.length).toBeGreaterThanOrEqual(1);
186
+
187
+ // ── Assert: events include PhaseStart ──
188
+ const phaseStartEvents = events.filter(e => e.type === GSDEventType.PhaseStart);
189
+ expect(phaseStartEvents.length).toBe(1);
190
+ const phaseStart = phaseStartEvents[0]!;
191
+ if (phaseStart.type === GSDEventType.PhaseStart) {
192
+ expect(phaseStart.phaseNumber).toBe(phase1Number);
193
+ expect(phaseStart.phaseName).toBeTruthy();
194
+ }
195
+
196
+ // ── Assert: events include PhaseComplete ──
197
+ const phaseCompleteEvents = events.filter(e => e.type === GSDEventType.PhaseComplete);
198
+ expect(phaseCompleteEvents.length).toBe(1);
199
+ const phaseComplete = phaseCompleteEvents[0]!;
200
+ if (phaseComplete.type === GSDEventType.PhaseComplete) {
201
+ expect(phaseComplete.phaseNumber).toBe(phase1Number);
202
+ expect(typeof phaseComplete.totalCostUsd).toBe('number');
203
+ expect(typeof phaseComplete.totalDurationMs).toBe('number');
204
+ }
205
+
206
+ // ── Assert: PhaseStepStart events show step progression ──
207
+ const stepStartEvents = events.filter(
208
+ (e): e is Extract<GSDEvent, { type: GSDEventType.PhaseStepStart }> =>
209
+ e.type === GSDEventType.PhaseStepStart,
210
+ );
211
+ expect(stepStartEvents.length).toBeGreaterThanOrEqual(1);
212
+
213
+ // Extract the step types in order
214
+ const stepTypesInOrder = stepStartEvents.map(e => e.step);
215
+
216
+ // Verify monotonic ordering: each step type should have an index >= previous
217
+ // Note: gap-closure can re-run plan+execute after verify, so we allow
218
+ // monotonicity to break only when verify triggers gap closure.
219
+ // For this tight-budget test, full gap closure is unlikely — check basic ordering.
220
+ let lastMaxOrder = -1;
221
+ for (const stepType of stepTypesInOrder) {
222
+ const order = STEP_ORDER[stepType] ?? -1;
223
+ // Track the high-water mark — steps should generally progress forward
224
+ if (order >= lastMaxOrder) {
225
+ lastMaxOrder = order;
226
+ }
227
+ }
228
+ // At least progressed past discuss (order 0) into real work
229
+ expect(lastMaxOrder).toBeGreaterThanOrEqual(1);
230
+
231
+ // ── Assert: at least one step has planResults with cost > 0 (real Agent SDK work) ──
232
+ const stepsWithCost = result.steps.filter(s => {
233
+ if (!s.planResults) return false;
234
+ return s.planResults.some(pr => pr.totalCostUsd > 0);
235
+ });
236
+ // At least one step should have incurred real cost (proves Agent SDK was invoked)
237
+ expect(stepsWithCost.length).toBeGreaterThanOrEqual(1);
238
+
239
+ // ── Assert: result cost and duration are tracked ──
240
+ expect(typeof result.totalCostUsd).toBe('number');
241
+ expect(result.totalDurationMs).toBeGreaterThan(0);
242
+
243
+ // ── Assert: each step result is properly structured ──
244
+ for (const step of result.steps) {
245
+ expect(Object.values(PhaseStepType)).toContain(step.step);
246
+ expect(typeof step.success).toBe('boolean');
247
+ expect(typeof step.durationMs).toBe('number');
248
+ }
249
+
250
+ // ── Assert: PhaseStepComplete events match step results ──
251
+ const stepCompleteEvents = events.filter(
252
+ (e): e is Extract<GSDEvent, { type: GSDEventType.PhaseStepComplete }> =>
253
+ e.type === GSDEventType.PhaseStepComplete,
254
+ );
255
+ // At least as many complete events as step results
256
+ expect(stepCompleteEvents.length).toBeGreaterThanOrEqual(result.steps.length);
257
+ }, 900_000); // 15 minute timeout: init (~4 min) + phase lifecycle (~10 min)
258
+ });
@@ -0,0 +1,149 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { Writable } from 'node:stream';
3
+ import { GSDLogger } from './logger.js';
4
+ import type { LogEntry } from './logger.js';
5
+ import { PhaseType } from './types.js';
6
+
7
+ // ─── Test output capture ─────────────────────────────────────────────────────
8
+
9
+ class BufferStream extends Writable {
10
+ lines: string[] = [];
11
+ _write(chunk: Buffer, _encoding: string, callback: () => void): void {
12
+ const str = chunk.toString();
13
+ this.lines.push(...str.split('\n').filter(l => l.length > 0));
14
+ callback();
15
+ }
16
+ }
17
+
18
+ function parseLogEntry(line: string): LogEntry {
19
+ return JSON.parse(line) as LogEntry;
20
+ }
21
+
22
+ // ─── Tests ───────────────────────────────────────────────────────────────────
23
+
24
+ describe('GSDLogger', () => {
25
+ let output: BufferStream;
26
+
27
+ beforeEach(() => {
28
+ output = new BufferStream();
29
+ });
30
+
31
+ it('outputs valid JSON on each log call', () => {
32
+ const logger = new GSDLogger({ output, level: 'debug' });
33
+ logger.info('test message');
34
+
35
+ expect(output.lines).toHaveLength(1);
36
+ expect(() => JSON.parse(output.lines[0]!)).not.toThrow();
37
+ });
38
+
39
+ it('includes required fields: timestamp, level, message', () => {
40
+ const logger = new GSDLogger({ output, level: 'debug' });
41
+ logger.info('hello world');
42
+
43
+ const entry = parseLogEntry(output.lines[0]!);
44
+ expect(entry.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T/);
45
+ expect(entry.level).toBe('info');
46
+ expect(entry.message).toBe('hello world');
47
+ });
48
+
49
+ it('filters messages below minimum log level', () => {
50
+ const logger = new GSDLogger({ output, level: 'warn' });
51
+
52
+ logger.debug('should be dropped');
53
+ logger.info('should be dropped');
54
+ logger.warn('should appear');
55
+ logger.error('should appear');
56
+
57
+ expect(output.lines).toHaveLength(2);
58
+ expect(parseLogEntry(output.lines[0]!).level).toBe('warn');
59
+ expect(parseLogEntry(output.lines[1]!).level).toBe('error');
60
+ });
61
+
62
+ it('defaults to info level filtering', () => {
63
+ const logger = new GSDLogger({ output });
64
+
65
+ logger.debug('dropped');
66
+ logger.info('kept');
67
+
68
+ expect(output.lines).toHaveLength(1);
69
+ expect(parseLogEntry(output.lines[0]!).level).toBe('info');
70
+ });
71
+
72
+ it('writes to custom output stream', () => {
73
+ const customOutput = new BufferStream();
74
+ const logger = new GSDLogger({ output: customOutput, level: 'debug' });
75
+ logger.info('custom');
76
+
77
+ expect(customOutput.lines).toHaveLength(1);
78
+ expect(output.lines).toHaveLength(0);
79
+ });
80
+
81
+ it('includes phase, plan, and sessionId context when set', () => {
82
+ const logger = new GSDLogger({
83
+ output,
84
+ level: 'debug',
85
+ phase: PhaseType.Execute,
86
+ plan: 'test-plan',
87
+ sessionId: 'sess-123',
88
+ });
89
+
90
+ logger.info('context test');
91
+
92
+ const entry = parseLogEntry(output.lines[0]!);
93
+ expect(entry.phase).toBe('execute');
94
+ expect(entry.plan).toBe('test-plan');
95
+ expect(entry.sessionId).toBe('sess-123');
96
+ });
97
+
98
+ it('includes extra data when provided', () => {
99
+ const logger = new GSDLogger({ output, level: 'debug' });
100
+ logger.info('with data', { count: 42, tool: 'Bash' });
101
+
102
+ const entry = parseLogEntry(output.lines[0]!);
103
+ expect(entry.data).toEqual({ count: 42, tool: 'Bash' });
104
+ });
105
+
106
+ it('omits optional fields when not set', () => {
107
+ const logger = new GSDLogger({ output, level: 'debug' });
108
+ logger.info('minimal');
109
+
110
+ const entry = parseLogEntry(output.lines[0]!);
111
+ expect(entry.phase).toBeUndefined();
112
+ expect(entry.plan).toBeUndefined();
113
+ expect(entry.sessionId).toBeUndefined();
114
+ expect(entry.data).toBeUndefined();
115
+ });
116
+
117
+ it('supports runtime context updates via setters', () => {
118
+ const logger = new GSDLogger({ output, level: 'debug' });
119
+
120
+ logger.info('before');
121
+ logger.setPhase(PhaseType.Research);
122
+ logger.setPlan('my-plan');
123
+ logger.setSessionId('sess-456');
124
+ logger.info('after');
125
+
126
+ const before = parseLogEntry(output.lines[0]!);
127
+ const after = parseLogEntry(output.lines[1]!);
128
+
129
+ expect(before.phase).toBeUndefined();
130
+ expect(after.phase).toBe('research');
131
+ expect(after.plan).toBe('my-plan');
132
+ expect(after.sessionId).toBe('sess-456');
133
+ });
134
+
135
+ it('emits all four log levels correctly', () => {
136
+ const logger = new GSDLogger({ output, level: 'debug' });
137
+
138
+ logger.debug('d');
139
+ logger.info('i');
140
+ logger.warn('w');
141
+ logger.error('e');
142
+
143
+ expect(output.lines).toHaveLength(4);
144
+ expect(parseLogEntry(output.lines[0]!).level).toBe('debug');
145
+ expect(parseLogEntry(output.lines[1]!).level).toBe('info');
146
+ expect(parseLogEntry(output.lines[2]!).level).toBe('warn');
147
+ expect(parseLogEntry(output.lines[3]!).level).toBe('error');
148
+ });
149
+ });
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Structured JSON logger for GSD debugging.
3
+ *
4
+ * Writes structured log entries to stderr (or configurable writable stream).
5
+ * This is a debugging facility (R019), separate from the event stream.
6
+ */
7
+
8
+ import type { Writable } from 'node:stream';
9
+ import type { PhaseType } from './types.js';
10
+
11
+ // ─── Log levels ──────────────────────────────────────────────────────────────
12
+
13
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
14
+
15
+ const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {
16
+ debug: 0,
17
+ info: 1,
18
+ warn: 2,
19
+ error: 3,
20
+ };
21
+
22
+ // ─── Log entry ───────────────────────────────────────────────────────────────
23
+
24
+ export interface LogEntry {
25
+ timestamp: string;
26
+ level: LogLevel;
27
+ phase?: PhaseType;
28
+ plan?: string;
29
+ sessionId?: string;
30
+ message: string;
31
+ data?: Record<string, unknown>;
32
+ }
33
+
34
+ // ─── Logger options ──────────────────────────────────────────────────────────
35
+
36
+ export interface GSDLoggerOptions {
37
+ /** Minimum log level to output. Default: 'info'. */
38
+ level?: LogLevel;
39
+ /** Output stream. Default: process.stderr. */
40
+ output?: Writable;
41
+ /** Phase context for all log entries. */
42
+ phase?: PhaseType;
43
+ /** Plan name context for all log entries. */
44
+ plan?: string;
45
+ /** Session ID context for all log entries. */
46
+ sessionId?: string;
47
+ }
48
+
49
+ // ─── Logger class ────────────────────────────────────────────────────────────
50
+
51
+ export class GSDLogger {
52
+ private readonly minLevel: number;
53
+ private readonly output: Writable;
54
+ private phase?: PhaseType;
55
+ private plan?: string;
56
+ private sessionId?: string;
57
+
58
+ constructor(options: GSDLoggerOptions = {}) {
59
+ this.minLevel = LOG_LEVEL_PRIORITY[options.level ?? 'info'];
60
+ this.output = options.output ?? process.stderr;
61
+ this.phase = options.phase;
62
+ this.plan = options.plan;
63
+ this.sessionId = options.sessionId;
64
+ }
65
+
66
+ /** Set phase context for subsequent log entries. */
67
+ setPhase(phase: PhaseType | undefined): void {
68
+ this.phase = phase;
69
+ }
70
+
71
+ /** Set plan context for subsequent log entries. */
72
+ setPlan(plan: string | undefined): void {
73
+ this.plan = plan;
74
+ }
75
+
76
+ /** Set session ID context for subsequent log entries. */
77
+ setSessionId(sessionId: string | undefined): void {
78
+ this.sessionId = sessionId;
79
+ }
80
+
81
+ debug(message: string, data?: Record<string, unknown>): void {
82
+ this.log('debug', message, data);
83
+ }
84
+
85
+ info(message: string, data?: Record<string, unknown>): void {
86
+ this.log('info', message, data);
87
+ }
88
+
89
+ warn(message: string, data?: Record<string, unknown>): void {
90
+ this.log('warn', message, data);
91
+ }
92
+
93
+ error(message: string, data?: Record<string, unknown>): void {
94
+ this.log('error', message, data);
95
+ }
96
+
97
+ private log(level: LogLevel, message: string, data?: Record<string, unknown>): void {
98
+ if (LOG_LEVEL_PRIORITY[level] < this.minLevel) return;
99
+
100
+ const entry: LogEntry = {
101
+ timestamp: new Date().toISOString(),
102
+ level,
103
+ message,
104
+ };
105
+
106
+ if (this.phase !== undefined) entry.phase = this.phase;
107
+ if (this.plan !== undefined) entry.plan = this.plan;
108
+ if (this.sessionId !== undefined) entry.sessionId = this.sessionId;
109
+ if (data !== undefined) entry.data = data;
110
+
111
+ this.output.write(JSON.stringify(entry) + '\n');
112
+ }
113
+ }