sofia-cli 0.1.1

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 (435) hide show
  1. package/.github/agents/copilot-instructions.md +39 -0
  2. package/.github/agents/speckit.analyze.agent.md +184 -0
  3. package/.github/agents/speckit.checklist.agent.md +294 -0
  4. package/.github/agents/speckit.clarify.agent.md +181 -0
  5. package/.github/agents/speckit.constitution.agent.md +84 -0
  6. package/.github/agents/speckit.implement.agent.md +135 -0
  7. package/.github/agents/speckit.plan.agent.md +90 -0
  8. package/.github/agents/speckit.specify.agent.md +258 -0
  9. package/.github/agents/speckit.tasks.agent.md +137 -0
  10. package/.github/agents/speckit.taskstoissues.agent.md +30 -0
  11. package/.github/copilot-instructions.md +257 -0
  12. package/.github/prompts/speckit.analyze.prompt.md +3 -0
  13. package/.github/prompts/speckit.checklist.prompt.md +3 -0
  14. package/.github/prompts/speckit.clarify.prompt.md +3 -0
  15. package/.github/prompts/speckit.constitution.prompt.md +3 -0
  16. package/.github/prompts/speckit.implement.prompt.md +3 -0
  17. package/.github/prompts/speckit.plan.prompt.md +3 -0
  18. package/.github/prompts/speckit.specify.prompt.md +3 -0
  19. package/.github/prompts/speckit.tasks.prompt.md +3 -0
  20. package/.github/prompts/speckit.taskstoissues.prompt.md +3 -0
  21. package/.github/workflows/ci.yml +38 -0
  22. package/.prettierrc +6 -0
  23. package/.specify/memory/constitution.md +181 -0
  24. package/.specify/scripts/bash/check-prerequisites.sh +166 -0
  25. package/.specify/scripts/bash/common.sh +156 -0
  26. package/.specify/scripts/bash/create-new-feature.sh +297 -0
  27. package/.specify/scripts/bash/setup-plan.sh +61 -0
  28. package/.specify/scripts/bash/update-agent-context.sh +810 -0
  29. package/.specify/templates/agent-file-template.md +28 -0
  30. package/.specify/templates/checklist-template.md +40 -0
  31. package/.specify/templates/constitution-template.md +50 -0
  32. package/.specify/templates/plan-template.md +113 -0
  33. package/.specify/templates/spec-template.md +115 -0
  34. package/.specify/templates/tasks-template.md +251 -0
  35. package/.vscode/mcp.json +42 -0
  36. package/.vscode/settings.json +19 -0
  37. package/CODE_OF_CONDUCT.md +128 -0
  38. package/LICENSE +21 -0
  39. package/README.md +213 -0
  40. package/dist/src/cli/developCommand.js +240 -0
  41. package/dist/src/cli/directCommands.js +143 -0
  42. package/dist/src/cli/envLoader.js +16 -0
  43. package/dist/src/cli/exportCommand.js +53 -0
  44. package/dist/src/cli/index.js +203 -0
  45. package/dist/src/cli/ioContext.js +109 -0
  46. package/dist/src/cli/preflight.js +57 -0
  47. package/dist/src/cli/statusCommand.js +110 -0
  48. package/dist/src/cli/workshopCommand.js +400 -0
  49. package/dist/src/develop/checkpointState.js +86 -0
  50. package/dist/src/develop/codeGenerator.js +319 -0
  51. package/dist/src/develop/dynamicScaffolder.js +226 -0
  52. package/dist/src/develop/githubMcpAdapter.js +122 -0
  53. package/dist/src/develop/index.js +15 -0
  54. package/dist/src/develop/mcpContextEnricher.js +195 -0
  55. package/dist/src/develop/pocScaffolder.js +542 -0
  56. package/dist/src/develop/ralphLoop.js +659 -0
  57. package/dist/src/develop/templateRegistry.js +364 -0
  58. package/dist/src/develop/testRunner.js +202 -0
  59. package/dist/src/logging/logger.js +58 -0
  60. package/dist/src/loop/conversationLoop.js +227 -0
  61. package/dist/src/loop/phaseSummarizer.js +87 -0
  62. package/dist/src/mcp/mcpManager.js +267 -0
  63. package/dist/src/mcp/mcpTransport.js +391 -0
  64. package/dist/src/mcp/retryPolicy.js +47 -0
  65. package/dist/src/mcp/webSearch.js +254 -0
  66. package/dist/src/phases/contextSummarizer.js +101 -0
  67. package/dist/src/phases/discoveryEnricher.js +156 -0
  68. package/dist/src/phases/phaseExtractors.js +222 -0
  69. package/dist/src/phases/phaseHandlers.js +328 -0
  70. package/dist/src/prompts/design.md +51 -0
  71. package/dist/src/prompts/develop-boundary.md +51 -0
  72. package/dist/src/prompts/develop.md +111 -0
  73. package/dist/src/prompts/discover.md +58 -0
  74. package/dist/src/prompts/ideate.md +56 -0
  75. package/dist/src/prompts/plan.md +51 -0
  76. package/dist/src/prompts/promptLoader.js +167 -0
  77. package/dist/src/prompts/promptLoader.ts +198 -0
  78. package/dist/src/prompts/select.md +47 -0
  79. package/dist/src/prompts/summarize/README.md +8 -0
  80. package/dist/src/prompts/summarize/design-summary.md +37 -0
  81. package/dist/src/prompts/summarize/develop-summary.md +25 -0
  82. package/dist/src/prompts/summarize/ideate-summary.md +27 -0
  83. package/dist/src/prompts/summarize/plan-summary.md +27 -0
  84. package/dist/src/prompts/summarize/select-summary.md +21 -0
  85. package/dist/src/prompts/system.md +28 -0
  86. package/dist/src/sessions/exportPaths.js +22 -0
  87. package/dist/src/sessions/exportWriter.js +406 -0
  88. package/dist/src/sessions/sessionManager.js +81 -0
  89. package/dist/src/sessions/sessionStore.js +65 -0
  90. package/dist/src/shared/activitySpinner.js +91 -0
  91. package/dist/src/shared/copilotClient.js +129 -0
  92. package/dist/src/shared/data/cards.json +1249 -0
  93. package/dist/src/shared/data/cardsLoader.js +51 -0
  94. package/dist/src/shared/errorClassifier.js +120 -0
  95. package/dist/src/shared/events.js +28 -0
  96. package/dist/src/shared/markdownRenderer.js +34 -0
  97. package/dist/src/shared/schemas/session.js +265 -0
  98. package/dist/src/shared/tableRenderer.js +20 -0
  99. package/dist/src/vendor/chalk.js +2 -0
  100. package/dist/src/vendor/cli-table3.js +3 -0
  101. package/dist/src/vendor/commander.js +2 -0
  102. package/dist/src/vendor/marked-terminal.js +3 -0
  103. package/dist/src/vendor/marked.js +2 -0
  104. package/dist/src/vendor/ora.js +2 -0
  105. package/dist/src/vendor/pino.js +2 -0
  106. package/dist/src/vendor/zod.js +2 -0
  107. package/dist/tests/e2e/developE2e.spec.js +126 -0
  108. package/dist/tests/e2e/developFailureE2e.spec.js +247 -0
  109. package/dist/tests/e2e/developPty.spec.js +75 -0
  110. package/dist/tests/e2e/discoveryWebSearchRelevance.spec.js +84 -0
  111. package/dist/tests/e2e/harness.spec.js +83 -0
  112. package/dist/tests/e2e/mcpLive.spec.js +120 -0
  113. package/dist/tests/e2e/newSession.e2e.spec.js +177 -0
  114. package/dist/tests/e2e/ralphLoopEnrichmentComparison.spec.js +62 -0
  115. package/dist/tests/e2e/workiqEnrichment.spec.js +56 -0
  116. package/dist/tests/e2e/zavaSimulation.spec.js +452 -0
  117. package/dist/tests/fixtures/test-fixture-project/src/add.js +3 -0
  118. package/dist/tests/fixtures/test-fixture-project/tests/failing.test.js +6 -0
  119. package/dist/tests/fixtures/test-fixture-project/tests/hanging.test.js +8 -0
  120. package/dist/tests/fixtures/test-fixture-project/tests/passing.test.js +10 -0
  121. package/dist/tests/fixtures/test-fixture-project/vitest.config.js +6 -0
  122. package/dist/tests/integration/autoStartConversation.spec.js +138 -0
  123. package/dist/tests/integration/defaultCommand.spec.js +147 -0
  124. package/dist/tests/integration/directCommandNonTty.spec.js +224 -0
  125. package/dist/tests/integration/directCommandTty.spec.js +151 -0
  126. package/dist/tests/integration/discoveryEnrichmentFlow.spec.js +175 -0
  127. package/dist/tests/integration/exportArtifacts.spec.js +202 -0
  128. package/dist/tests/integration/exportFallbackFlow.spec.js +99 -0
  129. package/dist/tests/integration/mcpDegradationFlow.spec.js +190 -0
  130. package/dist/tests/integration/mcpTransportFlow.spec.js +139 -0
  131. package/dist/tests/integration/newSessionFlow.spec.js +343 -0
  132. package/dist/tests/integration/pocGithubMcp.spec.js +186 -0
  133. package/dist/tests/integration/pocLocalFallback.spec.js +171 -0
  134. package/dist/tests/integration/pocScaffold.spec.js +163 -0
  135. package/dist/tests/integration/ralphLoopFlow.spec.js +359 -0
  136. package/dist/tests/integration/ralphLoopPartial.spec.js +368 -0
  137. package/dist/tests/integration/resumeAndBacktrack.spec.js +247 -0
  138. package/dist/tests/integration/spinnerLifecycle.spec.js +220 -0
  139. package/dist/tests/integration/summarizationFlow.spec.js +115 -0
  140. package/dist/tests/integration/testRunnerReal.spec.js +52 -0
  141. package/dist/tests/integration/webSearchAgent.spec.js +128 -0
  142. package/dist/tests/live/copilotSdkLive.spec.js +107 -0
  143. package/dist/tests/live/zavaFullWorkshop.spec.js +392 -0
  144. package/dist/tests/setup/loadEnv.js +3 -0
  145. package/dist/tests/unit/cli/developCommand.spec.js +567 -0
  146. package/dist/tests/unit/cli/directCommands.spec.js +279 -0
  147. package/dist/tests/unit/cli/envLoader.spec.js +58 -0
  148. package/dist/tests/unit/cli/ioContext.spec.js +119 -0
  149. package/dist/tests/unit/cli/preflight.spec.js +108 -0
  150. package/dist/tests/unit/cli/statusCommand.spec.js +111 -0
  151. package/dist/tests/unit/cli/workshopClientFallback.spec.js +80 -0
  152. package/dist/tests/unit/cli/workshopCommand.spec.js +329 -0
  153. package/dist/tests/unit/config/vitestEnvSetup.spec.js +13 -0
  154. package/dist/tests/unit/develop/checkpointState.spec.js +315 -0
  155. package/dist/tests/unit/develop/codeGenerator.spec.js +355 -0
  156. package/dist/tests/unit/develop/githubMcpAdapter.spec.js +231 -0
  157. package/dist/tests/unit/develop/mcpContextEnricher.spec.js +433 -0
  158. package/dist/tests/unit/develop/outputValidator.spec.js +119 -0
  159. package/dist/tests/unit/develop/pocScaffolder.spec.js +353 -0
  160. package/dist/tests/unit/develop/ralphLoop.spec.js +1248 -0
  161. package/dist/tests/unit/develop/templateRegistry.spec.js +85 -0
  162. package/dist/tests/unit/develop/testRunner.spec.js +249 -0
  163. package/dist/tests/unit/infraBicep.spec.js +92 -0
  164. package/dist/tests/unit/infraDeploy.spec.js +82 -0
  165. package/dist/tests/unit/infraTeardown.spec.js +63 -0
  166. package/dist/tests/unit/logging/logger.spec.js +43 -0
  167. package/dist/tests/unit/loop/conversationLoop.spec.js +592 -0
  168. package/dist/tests/unit/loop/phaseSummarizer.spec.js +141 -0
  169. package/dist/tests/unit/loop/streamingMarkdown.spec.js +147 -0
  170. package/dist/tests/unit/mcp/mcpManager.spec.js +279 -0
  171. package/dist/tests/unit/mcp/mcpTransport.spec.js +529 -0
  172. package/dist/tests/unit/mcp/retryPolicy.spec.js +218 -0
  173. package/dist/tests/unit/mcp/timeoutValidation.spec.js +46 -0
  174. package/dist/tests/unit/mcp/webSearch.spec.js +567 -0
  175. package/dist/tests/unit/phases/contextSummarizer.spec.js +140 -0
  176. package/dist/tests/unit/phases/discoveryEnricher.repeatCalls.spec.js +93 -0
  177. package/dist/tests/unit/phases/discoveryEnricher.spec.js +411 -0
  178. package/dist/tests/unit/phases/phaseExtractors.spec.js +352 -0
  179. package/dist/tests/unit/phases/phaseHandlers.spec.js +425 -0
  180. package/dist/tests/unit/prompts/promptLoader.spec.js +118 -0
  181. package/dist/tests/unit/schemas/pocSchemas.spec.js +412 -0
  182. package/dist/tests/unit/schemas/session.spec.js +257 -0
  183. package/dist/tests/unit/sessions/exportPaths.spec.js +31 -0
  184. package/dist/tests/unit/sessions/exportWriter.spec.js +655 -0
  185. package/dist/tests/unit/sessions/sessionManager.spec.js +151 -0
  186. package/dist/tests/unit/sessions/sessionStore.spec.js +116 -0
  187. package/dist/tests/unit/shared/activitySpinner.spec.js +175 -0
  188. package/dist/tests/unit/shared/cardsLoader.spec.js +76 -0
  189. package/dist/tests/unit/shared/copilotClient.spec.js +155 -0
  190. package/dist/tests/unit/shared/errorClassifier.spec.js +131 -0
  191. package/dist/tests/unit/shared/events.spec.js +55 -0
  192. package/dist/tests/unit/shared/markdownRenderer.spec.js +35 -0
  193. package/dist/tests/unit/shared/markdownRendererChunks.spec.js +70 -0
  194. package/dist/tests/unit/shared/tableRenderer.spec.js +34 -0
  195. package/dist/vitest.config.js +14 -0
  196. package/dist/vitest.live.config.js +18 -0
  197. package/docs/README.md +35 -0
  198. package/docs/architecture.md +169 -0
  199. package/docs/cli-usage.md +207 -0
  200. package/docs/environment.md +66 -0
  201. package/docs/export-format.md +146 -0
  202. package/docs/session-model.md +113 -0
  203. package/eslint.config.js +35 -0
  204. package/infra/deploy.sh +193 -0
  205. package/infra/gather-env.sh +211 -0
  206. package/infra/main.bicep +90 -0
  207. package/infra/main.bicepparam +18 -0
  208. package/infra/resources.bicep +134 -0
  209. package/infra/teardown.sh +114 -0
  210. package/package.json +63 -0
  211. package/specs/001-cli-workshop-rebuild/checklists/requirements.md +35 -0
  212. package/specs/001-cli-workshop-rebuild/contracts/cli.md +59 -0
  213. package/specs/001-cli-workshop-rebuild/contracts/export-summary-json.md +23 -0
  214. package/specs/001-cli-workshop-rebuild/contracts/session-json.md +30 -0
  215. package/specs/001-cli-workshop-rebuild/data-model.md +210 -0
  216. package/specs/001-cli-workshop-rebuild/plan.md +361 -0
  217. package/specs/001-cli-workshop-rebuild/quickstart.md +83 -0
  218. package/specs/001-cli-workshop-rebuild/research.md +116 -0
  219. package/specs/001-cli-workshop-rebuild/spec.md +240 -0
  220. package/specs/001-cli-workshop-rebuild/tasks.md +476 -0
  221. package/specs/002-poc-generation/contracts/poc-output.md +172 -0
  222. package/specs/002-poc-generation/contracts/ralph-loop.md +113 -0
  223. package/specs/002-poc-generation/data-model.md +172 -0
  224. package/specs/002-poc-generation/plan.md +109 -0
  225. package/specs/002-poc-generation/quickstart.md +97 -0
  226. package/specs/002-poc-generation/research.md +786 -0
  227. package/specs/002-poc-generation/spec.md +81 -0
  228. package/specs/002-poc-generation/tasks-fix.md +198 -0
  229. package/specs/002-poc-generation/tasks.md +252 -0
  230. package/specs/003-mcp-transport-integration/checklists/requirements.md +37 -0
  231. package/specs/003-mcp-transport-integration/contracts/context-enricher.md +220 -0
  232. package/specs/003-mcp-transport-integration/contracts/discovery-enricher.md +267 -0
  233. package/specs/003-mcp-transport-integration/contracts/github-adapter.md +149 -0
  234. package/specs/003-mcp-transport-integration/contracts/mcp-transport.md +288 -0
  235. package/specs/003-mcp-transport-integration/data-model.md +326 -0
  236. package/specs/003-mcp-transport-integration/plan.md +114 -0
  237. package/specs/003-mcp-transport-integration/quickstart.md +311 -0
  238. package/specs/003-mcp-transport-integration/research.md +395 -0
  239. package/specs/003-mcp-transport-integration/spec.md +234 -0
  240. package/specs/003-mcp-transport-integration/tasks.md +324 -0
  241. package/specs/003-next-spec-gaps.md +150 -0
  242. package/specs/004-dev-resume-hardening/checklists/requirements.md +37 -0
  243. package/specs/004-dev-resume-hardening/contracts/cli.md +160 -0
  244. package/specs/004-dev-resume-hardening/data-model.md +321 -0
  245. package/specs/004-dev-resume-hardening/plan.md +107 -0
  246. package/specs/004-dev-resume-hardening/quickstart.md +115 -0
  247. package/specs/004-dev-resume-hardening/research.md +142 -0
  248. package/specs/004-dev-resume-hardening/spec.md +221 -0
  249. package/specs/004-dev-resume-hardening/tasks.md +333 -0
  250. package/specs/005-ai-search-deploy/checklists/requirements.md +39 -0
  251. package/specs/005-ai-search-deploy/contracts/web-search-tool.md +241 -0
  252. package/specs/005-ai-search-deploy/data-model.md +130 -0
  253. package/specs/005-ai-search-deploy/plan.md +93 -0
  254. package/specs/005-ai-search-deploy/quickstart.md +96 -0
  255. package/specs/005-ai-search-deploy/research.md +187 -0
  256. package/specs/005-ai-search-deploy/spec.md +143 -0
  257. package/specs/005-ai-search-deploy/tasks.md +284 -0
  258. package/specs/006-workshop-extraction-fixes/checklists/requirements.md +61 -0
  259. package/specs/006-workshop-extraction-fixes/contracts/summarization-and-export.md +131 -0
  260. package/specs/006-workshop-extraction-fixes/data-model.md +149 -0
  261. package/specs/006-workshop-extraction-fixes/plan.md +123 -0
  262. package/specs/006-workshop-extraction-fixes/quickstart.md +101 -0
  263. package/specs/006-workshop-extraction-fixes/research.md +143 -0
  264. package/specs/006-workshop-extraction-fixes/spec.md +210 -0
  265. package/specs/006-workshop-extraction-fixes/tasks.md +316 -0
  266. package/src/cli/developCommand.ts +308 -0
  267. package/src/cli/directCommands.ts +195 -0
  268. package/src/cli/envLoader.ts +17 -0
  269. package/src/cli/exportCommand.ts +65 -0
  270. package/src/cli/index.ts +249 -0
  271. package/src/cli/ioContext.ts +139 -0
  272. package/src/cli/preflight.ts +86 -0
  273. package/src/cli/statusCommand.ts +118 -0
  274. package/src/cli/workshopCommand.ts +496 -0
  275. package/src/develop/checkpointState.ts +121 -0
  276. package/src/develop/codeGenerator.ts +402 -0
  277. package/src/develop/dynamicScaffolder.ts +284 -0
  278. package/src/develop/githubMcpAdapter.ts +199 -0
  279. package/src/develop/index.ts +34 -0
  280. package/src/develop/mcpContextEnricher.ts +279 -0
  281. package/src/develop/pocScaffolder.ts +646 -0
  282. package/src/develop/ralphLoop.ts +1044 -0
  283. package/src/develop/templateRegistry.ts +427 -0
  284. package/src/develop/testRunner.ts +276 -0
  285. package/src/logging/logger.ts +73 -0
  286. package/src/loop/conversationLoop.ts +355 -0
  287. package/src/loop/phaseSummarizer.ts +114 -0
  288. package/src/mcp/mcpManager.ts +365 -0
  289. package/src/mcp/mcpTransport.ts +562 -0
  290. package/src/mcp/retryPolicy.ts +87 -0
  291. package/src/mcp/webSearch.ts +388 -0
  292. package/src/originalPrompts/design_thinking.md +178 -0
  293. package/src/originalPrompts/design_thinking_persona.md +76 -0
  294. package/src/originalPrompts/document_generator_example.md +77 -0
  295. package/src/originalPrompts/document_generator_persona.md +47 -0
  296. package/src/originalPrompts/facilitator_persona.md +125 -0
  297. package/src/originalPrompts/guardrails.md +47 -0
  298. package/src/phases/contextSummarizer.ts +154 -0
  299. package/src/phases/discoveryEnricher.ts +223 -0
  300. package/src/phases/phaseExtractors.ts +247 -0
  301. package/src/phases/phaseHandlers.ts +450 -0
  302. package/src/prompts/design.md +51 -0
  303. package/src/prompts/develop-boundary.md +51 -0
  304. package/src/prompts/develop.md +111 -0
  305. package/src/prompts/discover.md +58 -0
  306. package/src/prompts/ideate.md +56 -0
  307. package/src/prompts/plan.md +51 -0
  308. package/src/prompts/promptLoader.ts +198 -0
  309. package/src/prompts/select.md +47 -0
  310. package/src/prompts/summarize/README.md +8 -0
  311. package/src/prompts/summarize/design-summary.md +37 -0
  312. package/src/prompts/summarize/develop-summary.md +25 -0
  313. package/src/prompts/summarize/ideate-summary.md +27 -0
  314. package/src/prompts/summarize/plan-summary.md +27 -0
  315. package/src/prompts/summarize/select-summary.md +21 -0
  316. package/src/prompts/system.md +28 -0
  317. package/src/sessions/exportPaths.ts +28 -0
  318. package/src/sessions/exportWriter.ts +490 -0
  319. package/src/sessions/sessionManager.ts +119 -0
  320. package/src/sessions/sessionStore.ts +69 -0
  321. package/src/shared/activitySpinner.ts +108 -0
  322. package/src/shared/copilotClient.ts +291 -0
  323. package/src/shared/data/cards.json +1249 -0
  324. package/src/shared/data/cardsLoader.ts +70 -0
  325. package/src/shared/errorClassifier.ts +160 -0
  326. package/src/shared/events.ts +103 -0
  327. package/src/shared/markdownRenderer.ts +44 -0
  328. package/src/shared/schemas/session.ts +346 -0
  329. package/src/shared/tableRenderer.ts +28 -0
  330. package/src/types/marked-terminal.d.ts +5 -0
  331. package/src/vendor/chalk.ts +2 -0
  332. package/src/vendor/cli-table3.ts +3 -0
  333. package/src/vendor/commander.ts +2 -0
  334. package/src/vendor/marked-terminal.ts +3 -0
  335. package/src/vendor/marked.ts +2 -0
  336. package/src/vendor/ora.ts +2 -0
  337. package/src/vendor/pino.ts +3 -0
  338. package/src/vendor/zod.ts +3 -0
  339. package/tests/e2e/developE2e.spec.ts +152 -0
  340. package/tests/e2e/developFailureE2e.spec.ts +289 -0
  341. package/tests/e2e/developPty.spec.ts +86 -0
  342. package/tests/e2e/discoveryWebSearchRelevance.spec.ts +103 -0
  343. package/tests/e2e/harness.spec.ts +104 -0
  344. package/tests/e2e/mcpLive.spec.ts +149 -0
  345. package/tests/e2e/newSession.e2e.spec.ts +245 -0
  346. package/tests/e2e/ralphLoopEnrichmentComparison.spec.ts +70 -0
  347. package/tests/e2e/workiqEnrichment.spec.ts +72 -0
  348. package/tests/e2e/zava-assessment/agent-interaction-script.md +258 -0
  349. package/tests/e2e/zava-assessment/company-profile.md +98 -0
  350. package/tests/e2e/zava-assessment/expected-results-checklist.md +454 -0
  351. package/tests/e2e/zavaSimulation.spec.ts +511 -0
  352. package/tests/fixtures/completedSession.json +141 -0
  353. package/tests/fixtures/test-fixture-project/package-lock.json +1585 -0
  354. package/tests/fixtures/test-fixture-project/package.json +12 -0
  355. package/tests/fixtures/test-fixture-project/src/add.ts +3 -0
  356. package/tests/fixtures/test-fixture-project/tests/failing.test.ts +7 -0
  357. package/tests/fixtures/test-fixture-project/tests/hanging.test.ts +9 -0
  358. package/tests/fixtures/test-fixture-project/tests/passing.test.ts +13 -0
  359. package/tests/fixtures/test-fixture-project/vitest.config.ts +7 -0
  360. package/tests/integration/autoStartConversation.spec.ts +168 -0
  361. package/tests/integration/defaultCommand.spec.ts +179 -0
  362. package/tests/integration/directCommandNonTty.spec.ts +260 -0
  363. package/tests/integration/directCommandTty.spec.ts +185 -0
  364. package/tests/integration/discoveryEnrichmentFlow.spec.ts +209 -0
  365. package/tests/integration/exportArtifacts.spec.ts +232 -0
  366. package/tests/integration/exportFallbackFlow.spec.ts +115 -0
  367. package/tests/integration/mcpDegradationFlow.spec.ts +231 -0
  368. package/tests/integration/mcpTransportFlow.spec.ts +178 -0
  369. package/tests/integration/newSessionFlow.spec.ts +406 -0
  370. package/tests/integration/pocGithubMcp.spec.ts +224 -0
  371. package/tests/integration/pocLocalFallback.spec.ts +205 -0
  372. package/tests/integration/pocScaffold.spec.ts +220 -0
  373. package/tests/integration/ralphLoopFlow.spec.ts +430 -0
  374. package/tests/integration/ralphLoopPartial.spec.ts +416 -0
  375. package/tests/integration/resumeAndBacktrack.spec.ts +278 -0
  376. package/tests/integration/spinnerLifecycle.spec.ts +270 -0
  377. package/tests/integration/summarizationFlow.spec.ts +135 -0
  378. package/tests/integration/testRunnerReal.spec.ts +63 -0
  379. package/tests/integration/webSearchAgent.spec.ts +155 -0
  380. package/tests/live/copilotSdkLive.spec.ts +149 -0
  381. package/tests/live/zavaFullWorkshop.spec.ts +515 -0
  382. package/tests/setup/loadEnv.ts +5 -0
  383. package/tests/unit/cli/developCommand.spec.ts +679 -0
  384. package/tests/unit/cli/directCommands.spec.ts +325 -0
  385. package/tests/unit/cli/envLoader.spec.ts +73 -0
  386. package/tests/unit/cli/ioContext.spec.ts +148 -0
  387. package/tests/unit/cli/preflight.spec.ts +125 -0
  388. package/tests/unit/cli/statusCommand.spec.ts +134 -0
  389. package/tests/unit/cli/workshopClientFallback.spec.ts +100 -0
  390. package/tests/unit/cli/workshopCommand.spec.ts +378 -0
  391. package/tests/unit/config/vitestEnvSetup.spec.ts +24 -0
  392. package/tests/unit/develop/checkpointState.spec.ts +378 -0
  393. package/tests/unit/develop/codeGenerator.spec.ts +447 -0
  394. package/tests/unit/develop/githubMcpAdapter.spec.ts +283 -0
  395. package/tests/unit/develop/mcpContextEnricher.spec.ts +564 -0
  396. package/tests/unit/develop/outputValidator.spec.ts +134 -0
  397. package/tests/unit/develop/pocScaffolder.spec.ts +451 -0
  398. package/tests/unit/develop/ralphLoop.spec.ts +1439 -0
  399. package/tests/unit/develop/templateRegistry.spec.ts +106 -0
  400. package/tests/unit/develop/testRunner.spec.ts +294 -0
  401. package/tests/unit/infraBicep.spec.ts +116 -0
  402. package/tests/unit/infraDeploy.spec.ts +102 -0
  403. package/tests/unit/infraTeardown.spec.ts +77 -0
  404. package/tests/unit/logging/logger.spec.ts +50 -0
  405. package/tests/unit/loop/conversationLoop.spec.ts +719 -0
  406. package/tests/unit/loop/phaseSummarizer.spec.ts +169 -0
  407. package/tests/unit/loop/streamingMarkdown.spec.ts +180 -0
  408. package/tests/unit/mcp/mcpManager.spec.ts +336 -0
  409. package/tests/unit/mcp/mcpTransport.spec.ts +689 -0
  410. package/tests/unit/mcp/retryPolicy.spec.ts +278 -0
  411. package/tests/unit/mcp/timeoutValidation.spec.ts +55 -0
  412. package/tests/unit/mcp/webSearch.spec.ts +718 -0
  413. package/tests/unit/phases/contextSummarizer.spec.ts +158 -0
  414. package/tests/unit/phases/discoveryEnricher.repeatCalls.spec.ts +125 -0
  415. package/tests/unit/phases/discoveryEnricher.spec.ts +512 -0
  416. package/tests/unit/phases/phaseExtractors.spec.ts +406 -0
  417. package/tests/unit/phases/phaseHandlers.spec.ts +483 -0
  418. package/tests/unit/prompts/promptLoader.spec.ts +144 -0
  419. package/tests/unit/schemas/pocSchemas.spec.ts +457 -0
  420. package/tests/unit/schemas/session.spec.ts +328 -0
  421. package/tests/unit/sessions/exportPaths.spec.ts +38 -0
  422. package/tests/unit/sessions/exportWriter.spec.ts +737 -0
  423. package/tests/unit/sessions/sessionManager.spec.ts +174 -0
  424. package/tests/unit/sessions/sessionStore.spec.ts +136 -0
  425. package/tests/unit/shared/activitySpinner.spec.ts +211 -0
  426. package/tests/unit/shared/cardsLoader.spec.ts +89 -0
  427. package/tests/unit/shared/copilotClient.spec.ts +185 -0
  428. package/tests/unit/shared/errorClassifier.spec.ts +152 -0
  429. package/tests/unit/shared/events.spec.ts +71 -0
  430. package/tests/unit/shared/markdownRenderer.spec.ts +42 -0
  431. package/tests/unit/shared/markdownRendererChunks.spec.ts +83 -0
  432. package/tests/unit/shared/tableRenderer.spec.ts +38 -0
  433. package/tsconfig.json +20 -0
  434. package/vitest.config.ts +15 -0
  435. package/vitest.live.config.ts +19 -0
@@ -0,0 +1,160 @@
1
+ # CLI Contracts: Dev Resume & Hardening
2
+
3
+ **Feature**: 004-dev-resume-hardening
4
+ **Date**: 2026-03-01
5
+
6
+ ## `sofia dev` Command Contract
7
+
8
+ ### Synopsis
9
+
10
+ ```
11
+ sofia dev --session <id> [--force] [--max-iterations <n>] [--output-dir <path>] [--debug]
12
+ ```
13
+
14
+ ### Resume Behavior (New)
15
+
16
+ | Session State | `--force` | Behavior |
17
+ | -------------------------------------------- | --------- | ---------------------------------------------- |
18
+ | `poc` undefined | N/A | Fresh run: scaffold → install → iterate from 1 |
19
+ | `poc.finalStatus` = `'success'` | `false` | Exit with "PoC already complete" message |
20
+ | `poc.finalStatus` = `'success'` | `true` | Reset poc → fresh run |
21
+ | `poc.finalStatus` = `'failed'`/`'partial'` | `false` | Resume from last iteration (default) |
22
+ | `poc.finalStatus` = `'failed'`/`'partial'` | `true` | Reset poc → fresh run |
23
+ | `poc.finalStatus` undefined + iterations > 0 | `false` | Resume from last completed iteration |
24
+ | `poc.finalStatus` undefined + iterations > 0 | `true` | Reset poc → fresh run |
25
+
26
+ ### Exit Codes
27
+
28
+ | Code | Meaning |
29
+ | ---- | -------------------------------------------------------------- |
30
+ | `0` | PoC completed successfully (tests passing) or already complete |
31
+ | `0` | PoC resumed and completed |
32
+ | `1` | Error during execution |
33
+ | `0` | User interrupted (Ctrl+C) — session saved for resume |
34
+
35
+ ### Info-Level Resume Logs (FR-007a)
36
+
37
+ All resume decisions produce info-level log messages (visible without `--debug`):
38
+
39
+ ```
40
+ Resuming session abc123 from iteration 5 (4 completed iterations found)
41
+ Re-running incomplete iteration 4 (no test results recorded)
42
+ Skipping scaffold — output directory and .sofia-metadata.json present
43
+ Re-running dependency installation (npm install)
44
+ Selected template: node-ts-vitest (matched 'typescript' in architecture notes)
45
+ ```
46
+
47
+ ### `--force` Reset Contract
48
+
49
+ When `--force` is specified:
50
+
51
+ 1. Delete output directory (`rm -rf <outputDir>`)
52
+ 2. Clear `session.poc` entirely (`session.poc = undefined`)
53
+ 3. Persist session (`store.save(session)`)
54
+ 4. Proceed with fresh scaffold → install → iterate from 1
55
+
56
+ **Post-condition**: `session.poc.iterations` is empty after first `updateSessionPoc` call.
57
+
58
+ ---
59
+
60
+ ## Template Registry Contract
61
+
62
+ ### Template Selection
63
+
64
+ ```typescript
65
+ // Input: plan's architectureNotes + dependencies
66
+ // Output: TemplateEntry
67
+ selectTemplate(registry, architectureNotes?, dependencies?): TemplateEntry
68
+ ```
69
+
70
+ **Selection rules** (first match wins, case-insensitive):
71
+
72
+ 1. Concatenate `architectureNotes` + `dependencies` into search text
73
+ 2. For each registry entry (in registration order), check if any `matchPattern` appears in search text
74
+ 3. If match found → return that entry
75
+ 4. If no match → return `node-ts-vitest` (default)
76
+
77
+ ### Registered Templates
78
+
79
+ #### `node-ts-vitest` (default)
80
+
81
+ | Field | Value |
82
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------- |
83
+ | installCommand | `npm install` |
84
+ | testCommand | `npm test -- --reporter=json` |
85
+ | matchPatterns | `typescript`, `node`, `vitest`, `ts` |
86
+ | files | `.gitignore`, `package.json`, `tsconfig.json`, `README.md`, `src/index.ts`, `tests/index.test.ts`, `.sofia-metadata.json` |
87
+
88
+ #### `python-pytest`
89
+
90
+ | Field | Value |
91
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
92
+ | installCommand | `pip install -r requirements.txt` |
93
+ | testCommand | `pytest --tb=short -q --json-report --json-report-file=-` |
94
+ | matchPatterns | `python`, `fastapi`, `flask`, `django`, `pytest` |
95
+ | files | `.gitignore`, `requirements.txt`, `pytest.ini`, `README.md`, `src/__init__.py`, `src/main.py`, `tests/test_main.py`, `.sofia-metadata.json` |
96
+
97
+ ---
98
+
99
+ ## Workshop → Dev Transition Contract
100
+
101
+ ### Plan Phase Completion Output
102
+
103
+ When the Plan phase completes in `sofia workshop`, the following message MUST be displayed:
104
+
105
+ ```markdown
106
+ ### Ready for PoC Generation
107
+
108
+ The Plan phase is complete. To generate the proof-of-concept, run:
109
+ ```
110
+
111
+ sofia dev --session <actual-session-id>
112
+
113
+ ```
114
+
115
+ This will scaffold a project matching your plan's technology stack, install dependencies,
116
+ and iteratively generate code until all tests pass.
117
+ ```
118
+
119
+ ### Interactive Mode Offer (FR-021, SHOULD)
120
+
121
+ In interactive mode, after the above message, the system SHOULD offer:
122
+
123
+ ```
124
+ ? Would you like to start PoC development now? (Y/n)
125
+ ```
126
+
127
+ - **Yes** (default): Invoke `developCommand` internally with the current session
128
+ - **No**: Save session and exit with the command displayed above
129
+
130
+ ---
131
+
132
+ ## `.sofia-metadata.json` Extended Schema
133
+
134
+ ```json
135
+ {
136
+ "sessionId": "string",
137
+ "featureSpec": "string",
138
+ "generatedAt": "ISO 8601 string",
139
+ "ideaTitle": "string",
140
+ "totalIterations": 0,
141
+ "finalStatus": "string | null",
142
+ "terminationReason": "string | null",
143
+ "techStack": {
144
+ "language": "string",
145
+ "runtime": "string",
146
+ "testRunner": "string"
147
+ },
148
+ "templateId": "string",
149
+ "todos": {
150
+ "totalInitial": 0,
151
+ "remaining": 0,
152
+ "markers": ["string"]
153
+ }
154
+ }
155
+ ```
156
+
157
+ New fields:
158
+
159
+ - `templateId`: Which template was used (for resume context)
160
+ - `todos`: TODO marker tracking (FR-022)
@@ -0,0 +1,321 @@
1
+ # Data Model: Dev Resume & Hardening
2
+
3
+ **Feature**: 004-dev-resume-hardening
4
+ **Date**: 2026-03-01
5
+
6
+ ## Entity Overview
7
+
8
+ ```
9
+ ┌──────────────────────┐ uses ┌──────────────────────┐
10
+ │ CheckpointState │◄─────────────│ developCommand.ts │
11
+ │ (runtime derived) │ │ (entry point) │
12
+ └──────────┬───────────┘ └──────────┬───────────┘
13
+ │ │
14
+ │ reads from │ passes to
15
+ ▼ ▼
16
+ ┌──────────────────────┐ ┌──────────────────────┐
17
+ │ PocDevelopmentState │◄──────────────│ RalphLoop │
18
+ │ (session.poc) │ updates │ (seeds iterations) │
19
+ │ [EXISTING SCHEMA] │ └──────────┬───────────┘
20
+ └──────────────────────┘ │
21
+ │ uses
22
+
23
+ ┌──────────────────────┐
24
+ │ TemplateRegistry │
25
+ │ (template lookup) │
26
+ └──────────┬───────────┘
27
+
28
+ │ contains
29
+
30
+ ┌──────────────────────┐
31
+ │ TemplateEntry │
32
+ │ (scaffold config) │
33
+ └──────────────────────┘
34
+ ```
35
+
36
+ ## Entity Definitions
37
+
38
+ ### CheckpointState (New — runtime-only, not persisted)
39
+
40
+ Derived from existing `session.poc` to determine resume behavior. This is NOT a new schema — it's a convenience type used by `developCommand.ts` and `RalphLoop.run()` to make resume decisions.
41
+
42
+ ```typescript
43
+ export interface CheckpointState {
44
+ /** Whether a prior PoC run exists */
45
+ hasPriorRun: boolean;
46
+ /** Number of fully completed iterations (with testResults) */
47
+ completedIterations: number;
48
+ /** Whether the last iteration was interrupted (no testResults) */
49
+ lastIterationIncomplete: boolean;
50
+ /** The iteration number to resume from */
51
+ resumeFromIteration: number;
52
+ /** Whether scaffolding can be skipped (output dir + metadata exist) */
53
+ canSkipScaffold: boolean;
54
+ /** Final status from prior run, if any */
55
+ priorFinalStatus: 'success' | 'failed' | 'partial' | undefined;
56
+ /** Prior iterations for LLM context seeding */
57
+ priorIterations: PocIteration[];
58
+ }
59
+ ```
60
+
61
+ **Derivation logic**:
62
+
63
+ ```typescript
64
+ function deriveCheckpointState(session: WorkshopSession, outputDir: string): CheckpointState {
65
+ const poc = session.poc;
66
+ if (!poc || poc.iterations.length === 0) {
67
+ return {
68
+ hasPriorRun: false,
69
+ completedIterations: 0,
70
+ lastIterationIncomplete: false,
71
+ resumeFromIteration: 1,
72
+ canSkipScaffold: false,
73
+ priorFinalStatus: undefined,
74
+ priorIterations: [],
75
+ };
76
+ }
77
+
78
+ const lastIter = poc.iterations[poc.iterations.length - 1];
79
+ const lastIncomplete = !lastIter.testResults && lastIter.outcome !== 'scaffold';
80
+ const completedIters = lastIncomplete ? poc.iterations.slice(0, -1) : poc.iterations;
81
+
82
+ const metadataExists = existsSync(join(outputDir, '.sofia-metadata.json'));
83
+
84
+ return {
85
+ hasPriorRun: true,
86
+ completedIterations: completedIters.length,
87
+ lastIterationIncomplete: lastIncomplete,
88
+ resumeFromIteration: completedIters.length + 1,
89
+ canSkipScaffold: metadataExists,
90
+ priorFinalStatus: poc.finalStatus,
91
+ priorIterations: completedIters,
92
+ };
93
+ }
94
+ ```
95
+
96
+ **Validation rules**:
97
+
98
+ - `resumeFromIteration` >= 1
99
+ - `completedIterations` >= 0
100
+ - If `lastIterationIncomplete`, the incomplete iteration is excluded from `priorIterations`
101
+ - `canSkipScaffold` requires both output directory AND `.sofia-metadata.json` to exist
102
+
103
+ ---
104
+
105
+ ### TemplateEntry (New — code-defined)
106
+
107
+ A single scaffold template configuration. Registered in the `TemplateRegistry`.
108
+
109
+ ```typescript
110
+ export interface TemplateEntry {
111
+ /** Unique template identifier */
112
+ id: string;
113
+ /** Human-readable name for logging */
114
+ displayName: string;
115
+ /** Scaffold file definitions */
116
+ files: TemplateFile[];
117
+ /** Technology stack for session state */
118
+ techStack: TechStack;
119
+ /** Command to install dependencies (e.g., 'npm install') */
120
+ installCommand: string;
121
+ /** Command to run tests with JSON output (e.g., 'npm test -- --reporter=json') */
122
+ testCommand: string;
123
+ /** Keywords to match from plan's architectureNotes/dependencies */
124
+ matchPatterns: string[];
125
+ }
126
+ ```
127
+
128
+ **Validation rules**:
129
+
130
+ - `id` must be unique within the registry
131
+ - `files` must include `.sofia-metadata.json`
132
+ - `installCommand` must be non-empty
133
+ - `testCommand` must be non-empty
134
+ - `matchPatterns` must contain at least one pattern (case-insensitive matching)
135
+
136
+ **Predefined entries**:
137
+
138
+ | id | displayName | matchPatterns | installCommand | testCommand |
139
+ | ---------------- | ----------------------------- | ---------------------------------------------------- | --------------------------------- | --------------------------------------------------------- |
140
+ | `node-ts-vitest` | TypeScript + Node.js + Vitest | `['typescript', 'node', 'vitest', 'ts']` | `npm install` | `npm test -- --reporter=json` |
141
+ | `python-pytest` | Python + pytest | `['python', 'fastapi', 'flask', 'django', 'pytest']` | `pip install -r requirements.txt` | `pytest --tb=short -q --json-report --json-report-file=-` |
142
+
143
+ ---
144
+
145
+ ### TemplateRegistry (New — code-defined)
146
+
147
+ Registry type and selection function. Simple map + match-first-wins logic.
148
+
149
+ ```typescript
150
+ export type TemplateRegistry = Map<string, TemplateEntry>;
151
+
152
+ export function selectTemplate(
153
+ registry: TemplateRegistry,
154
+ architectureNotes?: string,
155
+ dependencies?: string[],
156
+ ): TemplateEntry {
157
+ const searchText = [architectureNotes ?? '', ...(dependencies ?? [])].join(' ').toLowerCase();
158
+
159
+ for (const entry of registry.values()) {
160
+ if (entry.matchPatterns.some((p) => searchText.includes(p.toLowerCase()))) {
161
+ return entry;
162
+ }
163
+ }
164
+
165
+ // Default fallback
166
+ return registry.get('node-ts-vitest')!;
167
+ }
168
+ ```
169
+
170
+ ---
171
+
172
+ ### TestFixtureProject (New — test infrastructure)
173
+
174
+ A minimal project in `tests/fixtures/test-fixture-project/` used by testRunner integration tests. Not a runtime entity — exists only in the test suite.
175
+
176
+ ```
177
+ tests/fixtures/test-fixture-project/
178
+ ├── package.json # minimal: { "scripts": { "test": "vitest run --reporter=json" } }
179
+ ├── vitest.config.ts # minimal config
180
+ ├── src/
181
+ │ └── add.ts # function add(a, b) { return a + b; }
182
+ └── tests/
183
+ ├── passing.test.ts # test('adds numbers', () => expect(add(1,2)).toBe(3))
184
+ ├── failing.test.ts # test('fails', () => expect(1).toBe(2))
185
+ └── hanging.test.ts # test('hangs', async () => await new Promise(() => {}))
186
+ ```
187
+
188
+ **Purpose**: Enables FR-016 through FR-019 (real subprocess testing of testRunner).
189
+
190
+ ---
191
+
192
+ ### SofiaMetadata (Extended — file-system artifact)
193
+
194
+ Current schema in `.sofia-metadata.json` (pocScaffolder.ts L243-L260), extended with TODO tracking.
195
+
196
+ ```typescript
197
+ interface SofiaMetadata {
198
+ sessionId: string;
199
+ featureSpec: string;
200
+ generatedAt: string;
201
+ ideaTitle: string;
202
+ totalIterations: number;
203
+ finalStatus: string | null;
204
+ terminationReason: string | null;
205
+ techStack: {
206
+ language: string;
207
+ runtime: string;
208
+ testRunner: string;
209
+ };
210
+ // NEW: FR-022 — scaffold TODO tracking
211
+ todos?: {
212
+ totalInitial: number;
213
+ remaining: number;
214
+ markers: string[]; // e.g., ["src/main.py:12: TODO: Implement business logic"]
215
+ };
216
+ }
217
+ ```
218
+
219
+ ---
220
+
221
+ ## Existing Entities (Modified)
222
+
223
+ ### TechStack (session.ts — schema extension)
224
+
225
+ The existing `techStackSchema` may need two optional fields for template-defined commands:
226
+
227
+ ```typescript
228
+ export const techStackSchema = z.object({
229
+ language: z.string(),
230
+ framework: z.string().optional(),
231
+ testRunner: z.string(),
232
+ buildCommand: z.string().optional(),
233
+ runtime: z.string(),
234
+ // Potential additions for Feature 004:
235
+ installCommand: z.string().optional(), // 'npm install' | 'pip install -r requirements.txt'
236
+ testCommand: z.string().optional(), // full test command with reporter flags
237
+ });
238
+ ```
239
+
240
+ **Note**: These fields could live solely on `TemplateEntry` rather than in the persisted session schema. If they're only needed at scaffold/runtime and not for resume, keeping them off the session avoids schema migration. Decision: keep `installCommand` and `testCommand` on `TemplateEntry` only. The existing `testRunner` field on `TechStack` (e.g., `'npm test'`) is sufficient for session display purposes.
241
+
242
+ ### PocDevelopmentState (session.ts — no schema change)
243
+
244
+ The existing schema already supports everything needed for resume:
245
+
246
+ - `iterations: PocIteration[]` — seeded on resume
247
+ - `finalStatus?: 'success' | 'failed' | 'partial'` — undefined = resumable
248
+ - `terminationReason?` — read for status messages
249
+ - `techStack?` — preserved on resume
250
+
251
+ No schema migration required. The `.passthrough()` on `WorkshopSession` provides forward compatibility.
252
+
253
+ ## State Transitions
254
+
255
+ ### PoC Lifecycle States
256
+
257
+ ```
258
+ ┌──────────┐
259
+ first run │ No PoC │ session.poc = undefined
260
+ └────┬─────┘
261
+ │ sofia dev --session X
262
+
263
+ ┌──────────┐
264
+ │ Running │ finalStatus = undefined, iterations growing
265
+ └────┬─────┘
266
+
267
+ ┌───────────┼───────────┐
268
+ ▼ ▼ ▼
269
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
270
+ │ Success │ │ Partial │ │ Failed │
271
+ │ final= │ │ final= │ │ final= │
272
+ │'success' │ │'partial' │ │'failed' │
273
+ └──────────┘ └────┬─────┘ └────┬─────┘
274
+ │ │
275
+ ▼ ▼
276
+ ┌──────────┐ ┌──────────┐
277
+ resume │Resumable │ │Resumable │ resume
278
+ (FR-001/006) │ w/prior │ │ w/prior │ (FR-006)
279
+ └────┬─────┘ └────┬─────┘
280
+ │ │
281
+ ▼ ▼
282
+ ┌──────────┐
283
+ │ Running │ (loop continues from prior state)
284
+ └──────────┘
285
+
286
+ ┌──────────────────────────┐
287
+ │ Interrupted (SIGINT) │ finalStatus = undefined
288
+ │ iterations.length > 0 │ (directly resumable via FR-001)
289
+ └──────────────────────────┘
290
+
291
+ Any state + --force → No PoC (FR-008/009/010)
292
+ ```
293
+
294
+ ### Resume Decision Tree
295
+
296
+ ```
297
+ sofia dev --session X
298
+
299
+ ├── session.poc undefined?
300
+ │ └── YES → Fresh run (scaffold + install + iterate from 1)
301
+
302
+ ├── session.poc.finalStatus === 'success'?
303
+ │ └── YES → Display "PoC complete" message, exit (FR-005)
304
+
305
+ ├── session.poc.finalStatus === 'failed' | 'partial'?
306
+ │ └── YES → Default to resume, allow --force override (FR-006)
307
+ │ └── Resume: seed iterations, start from N+1
308
+
309
+ ├── session.poc.finalStatus undefined + iterations.length > 0?
310
+ │ └── YES → Resume (interrupted session) (FR-001)
311
+ │ ├── Last iteration has testResults?
312
+ │ │ └── YES → Start from iterations.length + 1
313
+ │ │ └── NO → Pop incomplete, start from iterations.length (FR-001a)
314
+ │ ├── Output dir exists + .sofia-metadata.json?
315
+ │ │ └── YES → Skip scaffold (FR-002)
316
+ │ │ └── NO → Re-scaffold (FR-007)
317
+ │ └── Always re-run npm install (FR-003)
318
+
319
+ └── --force flag set?
320
+ └── YES → Clear poc + delete dir → Fresh run (FR-008/009/010)
321
+ ```
@@ -0,0 +1,107 @@
1
+ # Implementation Plan: Dev Resume & Hardening
2
+
3
+ **Branch**: `004-dev-resume-hardening` | **Date**: 2026-03-01 | **Spec**: [spec.md](spec.md)
4
+ **Input**: Feature specification from `/specs/004-dev-resume-hardening/spec.md`
5
+
6
+ ## Summary
7
+
8
+ Harden the `sofia dev` command for production use by implementing resume/checkpoint support (seeding `RalphLoop.run()` from persisted `session.poc.iterations`), fixing `--force` to reset both output directory and session state, introducing a template registry for multi-language PoC scaffolding (starting with `python-pytest`), increasing `testRunner.ts` coverage from 45% to 80%+, and adding workshop→dev transition guidance. The core change is making `RalphLoop` read existing iteration state on startup instead of always starting from `iterations = []`.
9
+
10
+ ## Technical Context
11
+
12
+ **Language/Version**: TypeScript (ES2022 target) on Node.js ≥ 20 LTS, ESM (`"type": "module"`)
13
+ **Primary Dependencies**: `@github/copilot-sdk` ^0.1.28, `commander` ^11.1.0, `zod` ^4.3.6, `pino` ^8.17.2, `ora` ^7.0.1, `chalk` ^5.2.0
14
+ **Storage**: Local JSON files via `SessionStore` (atomic write-then-rename to `.sofia/sessions/<id>.json`)
15
+ **Testing**: Vitest ^4.0.18 with `@vitest/coverage-v8`; `node-pty` ^1.0.0 for PTY E2E tests
16
+ **Target Platform**: Linux/macOS/Windows CLI (Node.js LTS)
17
+ **Project Type**: CLI application
18
+ **Performance Goals**: Resume detection adds <500ms overhead to `sofia dev` startup (SC-004-007)
19
+ **Constraints**: No breaking changes to session schema (`.passthrough()` ensures forward compatibility); template registry must be extensible without modifying core scaffolder/loop logic
20
+ **Scale/Scope**: ~936 lines in `ralphLoop.ts`, ~267 lines in `testRunner.ts`, ~444 lines in `pocScaffolder.ts`, ~267 lines in `developCommand.ts`; 48 existing test files (33 unit, 11 integration, 3 E2E, 1 live)
21
+
22
+ ## Constitution Check
23
+
24
+ _GATE: Must pass before Phase 0 research. Re-check after Phase 1 design._
25
+
26
+ | Gate | Status | Evidence |
27
+ | ------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
28
+ | **Outcome-first discovery** | ✅ PASS | Resume/checkpoint directly addresses user-reported pain (lost iteration progress on interruption). SC-004-001 through SC-004-007 define measurable outcomes tied to facilitator productivity. |
29
+ | **Secure-by-default** | ✅ PASS | No new secrets, tokens, or PII handling. Resume reads existing session state from local files already governed by least-privilege. Info-level resume logs contain only iteration numbers and decision flags — no sensitive data. |
30
+ | **Node.js + TypeScript** | ✅ PASS | All implementation in TypeScript/Node.js using existing SDK patterns. Template registry extends current `PocScaffolder` without introducing new runtimes. |
31
+ | **MCP-first** | ✅ PASS | No new external integrations introduced. Template registry is code-defined (internal). Existing MCP connections (GitHub, Context7) remain unchanged. |
32
+ | **Test-first (NON-NEGOTIABLE)** | ✅ PASS | Spec mandates TDD via constitution. Every task phase starts with failing tests. US4 explicitly targets testRunner coverage from 45% → 80%+. |
33
+ | **CLI transparency** | ✅ PASS | FR-007a mandates info-level resume decision logging. FR-005/FR-006 require clear completion/status messages. FR-020 requires actionable next-step guidance with exact command. |
34
+
35
+ All gates pass. No exceptions required.
36
+
37
+ ## Project Structure
38
+
39
+ ### Documentation (this feature)
40
+
41
+ ```text
42
+ specs/004-dev-resume-hardening/
43
+ ├── plan.md # This file
44
+ ├── research.md # Phase 0 output
45
+ ├── data-model.md # Phase 1 output
46
+ ├── quickstart.md # Phase 1 output
47
+ ├── contracts/ # Phase 1 output
48
+ └── tasks.md # Phase 2 output (created by /speckit.tasks)
49
+ ```
50
+
51
+ ### Source Code (repository root)
52
+
53
+ ```text
54
+ src/
55
+ ├── cli/
56
+ │ └── developCommand.ts # Modified: resume detection, --force session reset
57
+ ├── develop/
58
+ │ ├── ralphLoop.ts # Modified: seed iterations from session, skip scaffold
59
+ │ ├── pocScaffolder.ts # Modified: extract template registry, add python-pytest
60
+ │ ├── templateRegistry.ts # New: template registry with selection logic
61
+ │ └── testRunner.ts # Unchanged (tests added, not code)
62
+ ├── phases/
63
+ │ └── phaseHandlers.ts # Modified: Plan phase → dev transition guidance
64
+ ├── sessions/
65
+ │ └── sessionManager.ts # Possibly modified: backtrack for --force poc reset
66
+ └── shared/
67
+ └── schemas/
68
+ └── session.ts # Possibly extended: TechStack install/test commands
69
+
70
+ tests/
71
+ ├── unit/
72
+ │ ├── cli/
73
+ │ │ └── developCommand.spec.ts # Extended: resume + --force scenarios
74
+ │ └── develop/
75
+ │ ├── ralphLoop.spec.ts # Extended: resume iteration seeding
76
+ │ ├── pocScaffolder.spec.ts # Extended: template registry selection
77
+ │ └── templateRegistry.spec.ts # New: registry unit tests
78
+ ├── integration/
79
+ │ ├── ralphLoopFlow.spec.ts # Extended: full resume flow
80
+ │ ├── ralphLoopPartial.spec.ts # Extended: partial resume scenarios
81
+ │ └── testRunnerReal.spec.ts # New: real fixture-based testRunner tests
82
+ ├── e2e/
83
+ │ └── developPty.spec.ts # New: PTY-based interactive E2E
84
+ └── fixtures/
85
+ └── test-fixture-project/ # New: minimal Vitest project for testRunner tests
86
+ ```
87
+
88
+ **Structure Decision**: Single project (Option 1) — consistent with existing repo layout. New files are limited to `templateRegistry.ts`, test files, and test fixture. All changes extend existing modules.
89
+
90
+ ## Complexity Tracking
91
+
92
+ > No constitution violations. All gates pass.
93
+
94
+ ## Post-Design Constitution Re-Check
95
+
96
+ _Re-evaluated after Phase 1 design artifacts (data-model.md, contracts/, quickstart.md)._
97
+
98
+ | Gate | Status | Post-Design Evidence |
99
+ | ------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
100
+ | **Outcome-first discovery** | ✅ PASS | CheckpointState derivation directly maps to resume UX outcomes. TemplateRegistry enables multi-language PoC — ties to broader workshop value. |
101
+ | **Secure-by-default** | ✅ PASS | No new data flows. CheckpointState is derived from existing session data. Template registry is code-defined, no external fetches. TODO tracking scans local files only. |
102
+ | **Node.js + TypeScript** | ✅ PASS | All new types (CheckpointState, TemplateEntry, TemplateRegistry) are TypeScript interfaces. No schema migration needed — existing Zod schemas support resume as-is. |
103
+ | **MCP-first** | ✅ PASS | No new external integrations. Feature is internal hardening. |
104
+ | **Test-first (NON-NEGOTIABLE)** | ✅ PASS | Quickstart outlines TDD workflow. TestFixtureProject entity provides real subprocess testing. Data model specifies testable derivation logic (deriveCheckpointState). |
105
+ | **CLI transparency** | ✅ PASS | Contracts define exact info-level log messages for every resume decision. Workshop→dev transition contract specifies exact command output. |
106
+
107
+ All gates pass post-design. No exceptions required.