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.
- package/.github/agents/copilot-instructions.md +39 -0
- package/.github/agents/speckit.analyze.agent.md +184 -0
- package/.github/agents/speckit.checklist.agent.md +294 -0
- package/.github/agents/speckit.clarify.agent.md +181 -0
- package/.github/agents/speckit.constitution.agent.md +84 -0
- package/.github/agents/speckit.implement.agent.md +135 -0
- package/.github/agents/speckit.plan.agent.md +90 -0
- package/.github/agents/speckit.specify.agent.md +258 -0
- package/.github/agents/speckit.tasks.agent.md +137 -0
- package/.github/agents/speckit.taskstoissues.agent.md +30 -0
- package/.github/copilot-instructions.md +257 -0
- package/.github/prompts/speckit.analyze.prompt.md +3 -0
- package/.github/prompts/speckit.checklist.prompt.md +3 -0
- package/.github/prompts/speckit.clarify.prompt.md +3 -0
- package/.github/prompts/speckit.constitution.prompt.md +3 -0
- package/.github/prompts/speckit.implement.prompt.md +3 -0
- package/.github/prompts/speckit.plan.prompt.md +3 -0
- package/.github/prompts/speckit.specify.prompt.md +3 -0
- package/.github/prompts/speckit.tasks.prompt.md +3 -0
- package/.github/prompts/speckit.taskstoissues.prompt.md +3 -0
- package/.github/workflows/ci.yml +38 -0
- package/.prettierrc +6 -0
- package/.specify/memory/constitution.md +181 -0
- package/.specify/scripts/bash/check-prerequisites.sh +166 -0
- package/.specify/scripts/bash/common.sh +156 -0
- package/.specify/scripts/bash/create-new-feature.sh +297 -0
- package/.specify/scripts/bash/setup-plan.sh +61 -0
- package/.specify/scripts/bash/update-agent-context.sh +810 -0
- package/.specify/templates/agent-file-template.md +28 -0
- package/.specify/templates/checklist-template.md +40 -0
- package/.specify/templates/constitution-template.md +50 -0
- package/.specify/templates/plan-template.md +113 -0
- package/.specify/templates/spec-template.md +115 -0
- package/.specify/templates/tasks-template.md +251 -0
- package/.vscode/mcp.json +42 -0
- package/.vscode/settings.json +19 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/LICENSE +21 -0
- package/README.md +213 -0
- package/dist/src/cli/developCommand.js +240 -0
- package/dist/src/cli/directCommands.js +143 -0
- package/dist/src/cli/envLoader.js +16 -0
- package/dist/src/cli/exportCommand.js +53 -0
- package/dist/src/cli/index.js +203 -0
- package/dist/src/cli/ioContext.js +109 -0
- package/dist/src/cli/preflight.js +57 -0
- package/dist/src/cli/statusCommand.js +110 -0
- package/dist/src/cli/workshopCommand.js +400 -0
- package/dist/src/develop/checkpointState.js +86 -0
- package/dist/src/develop/codeGenerator.js +319 -0
- package/dist/src/develop/dynamicScaffolder.js +226 -0
- package/dist/src/develop/githubMcpAdapter.js +122 -0
- package/dist/src/develop/index.js +15 -0
- package/dist/src/develop/mcpContextEnricher.js +195 -0
- package/dist/src/develop/pocScaffolder.js +542 -0
- package/dist/src/develop/ralphLoop.js +659 -0
- package/dist/src/develop/templateRegistry.js +364 -0
- package/dist/src/develop/testRunner.js +202 -0
- package/dist/src/logging/logger.js +58 -0
- package/dist/src/loop/conversationLoop.js +227 -0
- package/dist/src/loop/phaseSummarizer.js +87 -0
- package/dist/src/mcp/mcpManager.js +267 -0
- package/dist/src/mcp/mcpTransport.js +391 -0
- package/dist/src/mcp/retryPolicy.js +47 -0
- package/dist/src/mcp/webSearch.js +254 -0
- package/dist/src/phases/contextSummarizer.js +101 -0
- package/dist/src/phases/discoveryEnricher.js +156 -0
- package/dist/src/phases/phaseExtractors.js +222 -0
- package/dist/src/phases/phaseHandlers.js +328 -0
- package/dist/src/prompts/design.md +51 -0
- package/dist/src/prompts/develop-boundary.md +51 -0
- package/dist/src/prompts/develop.md +111 -0
- package/dist/src/prompts/discover.md +58 -0
- package/dist/src/prompts/ideate.md +56 -0
- package/dist/src/prompts/plan.md +51 -0
- package/dist/src/prompts/promptLoader.js +167 -0
- package/dist/src/prompts/promptLoader.ts +198 -0
- package/dist/src/prompts/select.md +47 -0
- package/dist/src/prompts/summarize/README.md +8 -0
- package/dist/src/prompts/summarize/design-summary.md +37 -0
- package/dist/src/prompts/summarize/develop-summary.md +25 -0
- package/dist/src/prompts/summarize/ideate-summary.md +27 -0
- package/dist/src/prompts/summarize/plan-summary.md +27 -0
- package/dist/src/prompts/summarize/select-summary.md +21 -0
- package/dist/src/prompts/system.md +28 -0
- package/dist/src/sessions/exportPaths.js +22 -0
- package/dist/src/sessions/exportWriter.js +406 -0
- package/dist/src/sessions/sessionManager.js +81 -0
- package/dist/src/sessions/sessionStore.js +65 -0
- package/dist/src/shared/activitySpinner.js +91 -0
- package/dist/src/shared/copilotClient.js +129 -0
- package/dist/src/shared/data/cards.json +1249 -0
- package/dist/src/shared/data/cardsLoader.js +51 -0
- package/dist/src/shared/errorClassifier.js +120 -0
- package/dist/src/shared/events.js +28 -0
- package/dist/src/shared/markdownRenderer.js +34 -0
- package/dist/src/shared/schemas/session.js +265 -0
- package/dist/src/shared/tableRenderer.js +20 -0
- package/dist/src/vendor/chalk.js +2 -0
- package/dist/src/vendor/cli-table3.js +3 -0
- package/dist/src/vendor/commander.js +2 -0
- package/dist/src/vendor/marked-terminal.js +3 -0
- package/dist/src/vendor/marked.js +2 -0
- package/dist/src/vendor/ora.js +2 -0
- package/dist/src/vendor/pino.js +2 -0
- package/dist/src/vendor/zod.js +2 -0
- package/dist/tests/e2e/developE2e.spec.js +126 -0
- package/dist/tests/e2e/developFailureE2e.spec.js +247 -0
- package/dist/tests/e2e/developPty.spec.js +75 -0
- package/dist/tests/e2e/discoveryWebSearchRelevance.spec.js +84 -0
- package/dist/tests/e2e/harness.spec.js +83 -0
- package/dist/tests/e2e/mcpLive.spec.js +120 -0
- package/dist/tests/e2e/newSession.e2e.spec.js +177 -0
- package/dist/tests/e2e/ralphLoopEnrichmentComparison.spec.js +62 -0
- package/dist/tests/e2e/workiqEnrichment.spec.js +56 -0
- package/dist/tests/e2e/zavaSimulation.spec.js +452 -0
- package/dist/tests/fixtures/test-fixture-project/src/add.js +3 -0
- package/dist/tests/fixtures/test-fixture-project/tests/failing.test.js +6 -0
- package/dist/tests/fixtures/test-fixture-project/tests/hanging.test.js +8 -0
- package/dist/tests/fixtures/test-fixture-project/tests/passing.test.js +10 -0
- package/dist/tests/fixtures/test-fixture-project/vitest.config.js +6 -0
- package/dist/tests/integration/autoStartConversation.spec.js +138 -0
- package/dist/tests/integration/defaultCommand.spec.js +147 -0
- package/dist/tests/integration/directCommandNonTty.spec.js +224 -0
- package/dist/tests/integration/directCommandTty.spec.js +151 -0
- package/dist/tests/integration/discoveryEnrichmentFlow.spec.js +175 -0
- package/dist/tests/integration/exportArtifacts.spec.js +202 -0
- package/dist/tests/integration/exportFallbackFlow.spec.js +99 -0
- package/dist/tests/integration/mcpDegradationFlow.spec.js +190 -0
- package/dist/tests/integration/mcpTransportFlow.spec.js +139 -0
- package/dist/tests/integration/newSessionFlow.spec.js +343 -0
- package/dist/tests/integration/pocGithubMcp.spec.js +186 -0
- package/dist/tests/integration/pocLocalFallback.spec.js +171 -0
- package/dist/tests/integration/pocScaffold.spec.js +163 -0
- package/dist/tests/integration/ralphLoopFlow.spec.js +359 -0
- package/dist/tests/integration/ralphLoopPartial.spec.js +368 -0
- package/dist/tests/integration/resumeAndBacktrack.spec.js +247 -0
- package/dist/tests/integration/spinnerLifecycle.spec.js +220 -0
- package/dist/tests/integration/summarizationFlow.spec.js +115 -0
- package/dist/tests/integration/testRunnerReal.spec.js +52 -0
- package/dist/tests/integration/webSearchAgent.spec.js +128 -0
- package/dist/tests/live/copilotSdkLive.spec.js +107 -0
- package/dist/tests/live/zavaFullWorkshop.spec.js +392 -0
- package/dist/tests/setup/loadEnv.js +3 -0
- package/dist/tests/unit/cli/developCommand.spec.js +567 -0
- package/dist/tests/unit/cli/directCommands.spec.js +279 -0
- package/dist/tests/unit/cli/envLoader.spec.js +58 -0
- package/dist/tests/unit/cli/ioContext.spec.js +119 -0
- package/dist/tests/unit/cli/preflight.spec.js +108 -0
- package/dist/tests/unit/cli/statusCommand.spec.js +111 -0
- package/dist/tests/unit/cli/workshopClientFallback.spec.js +80 -0
- package/dist/tests/unit/cli/workshopCommand.spec.js +329 -0
- package/dist/tests/unit/config/vitestEnvSetup.spec.js +13 -0
- package/dist/tests/unit/develop/checkpointState.spec.js +315 -0
- package/dist/tests/unit/develop/codeGenerator.spec.js +355 -0
- package/dist/tests/unit/develop/githubMcpAdapter.spec.js +231 -0
- package/dist/tests/unit/develop/mcpContextEnricher.spec.js +433 -0
- package/dist/tests/unit/develop/outputValidator.spec.js +119 -0
- package/dist/tests/unit/develop/pocScaffolder.spec.js +353 -0
- package/dist/tests/unit/develop/ralphLoop.spec.js +1248 -0
- package/dist/tests/unit/develop/templateRegistry.spec.js +85 -0
- package/dist/tests/unit/develop/testRunner.spec.js +249 -0
- package/dist/tests/unit/infraBicep.spec.js +92 -0
- package/dist/tests/unit/infraDeploy.spec.js +82 -0
- package/dist/tests/unit/infraTeardown.spec.js +63 -0
- package/dist/tests/unit/logging/logger.spec.js +43 -0
- package/dist/tests/unit/loop/conversationLoop.spec.js +592 -0
- package/dist/tests/unit/loop/phaseSummarizer.spec.js +141 -0
- package/dist/tests/unit/loop/streamingMarkdown.spec.js +147 -0
- package/dist/tests/unit/mcp/mcpManager.spec.js +279 -0
- package/dist/tests/unit/mcp/mcpTransport.spec.js +529 -0
- package/dist/tests/unit/mcp/retryPolicy.spec.js +218 -0
- package/dist/tests/unit/mcp/timeoutValidation.spec.js +46 -0
- package/dist/tests/unit/mcp/webSearch.spec.js +567 -0
- package/dist/tests/unit/phases/contextSummarizer.spec.js +140 -0
- package/dist/tests/unit/phases/discoveryEnricher.repeatCalls.spec.js +93 -0
- package/dist/tests/unit/phases/discoveryEnricher.spec.js +411 -0
- package/dist/tests/unit/phases/phaseExtractors.spec.js +352 -0
- package/dist/tests/unit/phases/phaseHandlers.spec.js +425 -0
- package/dist/tests/unit/prompts/promptLoader.spec.js +118 -0
- package/dist/tests/unit/schemas/pocSchemas.spec.js +412 -0
- package/dist/tests/unit/schemas/session.spec.js +257 -0
- package/dist/tests/unit/sessions/exportPaths.spec.js +31 -0
- package/dist/tests/unit/sessions/exportWriter.spec.js +655 -0
- package/dist/tests/unit/sessions/sessionManager.spec.js +151 -0
- package/dist/tests/unit/sessions/sessionStore.spec.js +116 -0
- package/dist/tests/unit/shared/activitySpinner.spec.js +175 -0
- package/dist/tests/unit/shared/cardsLoader.spec.js +76 -0
- package/dist/tests/unit/shared/copilotClient.spec.js +155 -0
- package/dist/tests/unit/shared/errorClassifier.spec.js +131 -0
- package/dist/tests/unit/shared/events.spec.js +55 -0
- package/dist/tests/unit/shared/markdownRenderer.spec.js +35 -0
- package/dist/tests/unit/shared/markdownRendererChunks.spec.js +70 -0
- package/dist/tests/unit/shared/tableRenderer.spec.js +34 -0
- package/dist/vitest.config.js +14 -0
- package/dist/vitest.live.config.js +18 -0
- package/docs/README.md +35 -0
- package/docs/architecture.md +169 -0
- package/docs/cli-usage.md +207 -0
- package/docs/environment.md +66 -0
- package/docs/export-format.md +146 -0
- package/docs/session-model.md +113 -0
- package/eslint.config.js +35 -0
- package/infra/deploy.sh +193 -0
- package/infra/gather-env.sh +211 -0
- package/infra/main.bicep +90 -0
- package/infra/main.bicepparam +18 -0
- package/infra/resources.bicep +134 -0
- package/infra/teardown.sh +114 -0
- package/package.json +63 -0
- package/specs/001-cli-workshop-rebuild/checklists/requirements.md +35 -0
- package/specs/001-cli-workshop-rebuild/contracts/cli.md +59 -0
- package/specs/001-cli-workshop-rebuild/contracts/export-summary-json.md +23 -0
- package/specs/001-cli-workshop-rebuild/contracts/session-json.md +30 -0
- package/specs/001-cli-workshop-rebuild/data-model.md +210 -0
- package/specs/001-cli-workshop-rebuild/plan.md +361 -0
- package/specs/001-cli-workshop-rebuild/quickstart.md +83 -0
- package/specs/001-cli-workshop-rebuild/research.md +116 -0
- package/specs/001-cli-workshop-rebuild/spec.md +240 -0
- package/specs/001-cli-workshop-rebuild/tasks.md +476 -0
- package/specs/002-poc-generation/contracts/poc-output.md +172 -0
- package/specs/002-poc-generation/contracts/ralph-loop.md +113 -0
- package/specs/002-poc-generation/data-model.md +172 -0
- package/specs/002-poc-generation/plan.md +109 -0
- package/specs/002-poc-generation/quickstart.md +97 -0
- package/specs/002-poc-generation/research.md +786 -0
- package/specs/002-poc-generation/spec.md +81 -0
- package/specs/002-poc-generation/tasks-fix.md +198 -0
- package/specs/002-poc-generation/tasks.md +252 -0
- package/specs/003-mcp-transport-integration/checklists/requirements.md +37 -0
- package/specs/003-mcp-transport-integration/contracts/context-enricher.md +220 -0
- package/specs/003-mcp-transport-integration/contracts/discovery-enricher.md +267 -0
- package/specs/003-mcp-transport-integration/contracts/github-adapter.md +149 -0
- package/specs/003-mcp-transport-integration/contracts/mcp-transport.md +288 -0
- package/specs/003-mcp-transport-integration/data-model.md +326 -0
- package/specs/003-mcp-transport-integration/plan.md +114 -0
- package/specs/003-mcp-transport-integration/quickstart.md +311 -0
- package/specs/003-mcp-transport-integration/research.md +395 -0
- package/specs/003-mcp-transport-integration/spec.md +234 -0
- package/specs/003-mcp-transport-integration/tasks.md +324 -0
- package/specs/003-next-spec-gaps.md +150 -0
- package/specs/004-dev-resume-hardening/checklists/requirements.md +37 -0
- package/specs/004-dev-resume-hardening/contracts/cli.md +160 -0
- package/specs/004-dev-resume-hardening/data-model.md +321 -0
- package/specs/004-dev-resume-hardening/plan.md +107 -0
- package/specs/004-dev-resume-hardening/quickstart.md +115 -0
- package/specs/004-dev-resume-hardening/research.md +142 -0
- package/specs/004-dev-resume-hardening/spec.md +221 -0
- package/specs/004-dev-resume-hardening/tasks.md +333 -0
- package/specs/005-ai-search-deploy/checklists/requirements.md +39 -0
- package/specs/005-ai-search-deploy/contracts/web-search-tool.md +241 -0
- package/specs/005-ai-search-deploy/data-model.md +130 -0
- package/specs/005-ai-search-deploy/plan.md +93 -0
- package/specs/005-ai-search-deploy/quickstart.md +96 -0
- package/specs/005-ai-search-deploy/research.md +187 -0
- package/specs/005-ai-search-deploy/spec.md +143 -0
- package/specs/005-ai-search-deploy/tasks.md +284 -0
- package/specs/006-workshop-extraction-fixes/checklists/requirements.md +61 -0
- package/specs/006-workshop-extraction-fixes/contracts/summarization-and-export.md +131 -0
- package/specs/006-workshop-extraction-fixes/data-model.md +149 -0
- package/specs/006-workshop-extraction-fixes/plan.md +123 -0
- package/specs/006-workshop-extraction-fixes/quickstart.md +101 -0
- package/specs/006-workshop-extraction-fixes/research.md +143 -0
- package/specs/006-workshop-extraction-fixes/spec.md +210 -0
- package/specs/006-workshop-extraction-fixes/tasks.md +316 -0
- package/src/cli/developCommand.ts +308 -0
- package/src/cli/directCommands.ts +195 -0
- package/src/cli/envLoader.ts +17 -0
- package/src/cli/exportCommand.ts +65 -0
- package/src/cli/index.ts +249 -0
- package/src/cli/ioContext.ts +139 -0
- package/src/cli/preflight.ts +86 -0
- package/src/cli/statusCommand.ts +118 -0
- package/src/cli/workshopCommand.ts +496 -0
- package/src/develop/checkpointState.ts +121 -0
- package/src/develop/codeGenerator.ts +402 -0
- package/src/develop/dynamicScaffolder.ts +284 -0
- package/src/develop/githubMcpAdapter.ts +199 -0
- package/src/develop/index.ts +34 -0
- package/src/develop/mcpContextEnricher.ts +279 -0
- package/src/develop/pocScaffolder.ts +646 -0
- package/src/develop/ralphLoop.ts +1044 -0
- package/src/develop/templateRegistry.ts +427 -0
- package/src/develop/testRunner.ts +276 -0
- package/src/logging/logger.ts +73 -0
- package/src/loop/conversationLoop.ts +355 -0
- package/src/loop/phaseSummarizer.ts +114 -0
- package/src/mcp/mcpManager.ts +365 -0
- package/src/mcp/mcpTransport.ts +562 -0
- package/src/mcp/retryPolicy.ts +87 -0
- package/src/mcp/webSearch.ts +388 -0
- package/src/originalPrompts/design_thinking.md +178 -0
- package/src/originalPrompts/design_thinking_persona.md +76 -0
- package/src/originalPrompts/document_generator_example.md +77 -0
- package/src/originalPrompts/document_generator_persona.md +47 -0
- package/src/originalPrompts/facilitator_persona.md +125 -0
- package/src/originalPrompts/guardrails.md +47 -0
- package/src/phases/contextSummarizer.ts +154 -0
- package/src/phases/discoveryEnricher.ts +223 -0
- package/src/phases/phaseExtractors.ts +247 -0
- package/src/phases/phaseHandlers.ts +450 -0
- package/src/prompts/design.md +51 -0
- package/src/prompts/develop-boundary.md +51 -0
- package/src/prompts/develop.md +111 -0
- package/src/prompts/discover.md +58 -0
- package/src/prompts/ideate.md +56 -0
- package/src/prompts/plan.md +51 -0
- package/src/prompts/promptLoader.ts +198 -0
- package/src/prompts/select.md +47 -0
- package/src/prompts/summarize/README.md +8 -0
- package/src/prompts/summarize/design-summary.md +37 -0
- package/src/prompts/summarize/develop-summary.md +25 -0
- package/src/prompts/summarize/ideate-summary.md +27 -0
- package/src/prompts/summarize/plan-summary.md +27 -0
- package/src/prompts/summarize/select-summary.md +21 -0
- package/src/prompts/system.md +28 -0
- package/src/sessions/exportPaths.ts +28 -0
- package/src/sessions/exportWriter.ts +490 -0
- package/src/sessions/sessionManager.ts +119 -0
- package/src/sessions/sessionStore.ts +69 -0
- package/src/shared/activitySpinner.ts +108 -0
- package/src/shared/copilotClient.ts +291 -0
- package/src/shared/data/cards.json +1249 -0
- package/src/shared/data/cardsLoader.ts +70 -0
- package/src/shared/errorClassifier.ts +160 -0
- package/src/shared/events.ts +103 -0
- package/src/shared/markdownRenderer.ts +44 -0
- package/src/shared/schemas/session.ts +346 -0
- package/src/shared/tableRenderer.ts +28 -0
- package/src/types/marked-terminal.d.ts +5 -0
- package/src/vendor/chalk.ts +2 -0
- package/src/vendor/cli-table3.ts +3 -0
- package/src/vendor/commander.ts +2 -0
- package/src/vendor/marked-terminal.ts +3 -0
- package/src/vendor/marked.ts +2 -0
- package/src/vendor/ora.ts +2 -0
- package/src/vendor/pino.ts +3 -0
- package/src/vendor/zod.ts +3 -0
- package/tests/e2e/developE2e.spec.ts +152 -0
- package/tests/e2e/developFailureE2e.spec.ts +289 -0
- package/tests/e2e/developPty.spec.ts +86 -0
- package/tests/e2e/discoveryWebSearchRelevance.spec.ts +103 -0
- package/tests/e2e/harness.spec.ts +104 -0
- package/tests/e2e/mcpLive.spec.ts +149 -0
- package/tests/e2e/newSession.e2e.spec.ts +245 -0
- package/tests/e2e/ralphLoopEnrichmentComparison.spec.ts +70 -0
- package/tests/e2e/workiqEnrichment.spec.ts +72 -0
- package/tests/e2e/zava-assessment/agent-interaction-script.md +258 -0
- package/tests/e2e/zava-assessment/company-profile.md +98 -0
- package/tests/e2e/zava-assessment/expected-results-checklist.md +454 -0
- package/tests/e2e/zavaSimulation.spec.ts +511 -0
- package/tests/fixtures/completedSession.json +141 -0
- package/tests/fixtures/test-fixture-project/package-lock.json +1585 -0
- package/tests/fixtures/test-fixture-project/package.json +12 -0
- package/tests/fixtures/test-fixture-project/src/add.ts +3 -0
- package/tests/fixtures/test-fixture-project/tests/failing.test.ts +7 -0
- package/tests/fixtures/test-fixture-project/tests/hanging.test.ts +9 -0
- package/tests/fixtures/test-fixture-project/tests/passing.test.ts +13 -0
- package/tests/fixtures/test-fixture-project/vitest.config.ts +7 -0
- package/tests/integration/autoStartConversation.spec.ts +168 -0
- package/tests/integration/defaultCommand.spec.ts +179 -0
- package/tests/integration/directCommandNonTty.spec.ts +260 -0
- package/tests/integration/directCommandTty.spec.ts +185 -0
- package/tests/integration/discoveryEnrichmentFlow.spec.ts +209 -0
- package/tests/integration/exportArtifacts.spec.ts +232 -0
- package/tests/integration/exportFallbackFlow.spec.ts +115 -0
- package/tests/integration/mcpDegradationFlow.spec.ts +231 -0
- package/tests/integration/mcpTransportFlow.spec.ts +178 -0
- package/tests/integration/newSessionFlow.spec.ts +406 -0
- package/tests/integration/pocGithubMcp.spec.ts +224 -0
- package/tests/integration/pocLocalFallback.spec.ts +205 -0
- package/tests/integration/pocScaffold.spec.ts +220 -0
- package/tests/integration/ralphLoopFlow.spec.ts +430 -0
- package/tests/integration/ralphLoopPartial.spec.ts +416 -0
- package/tests/integration/resumeAndBacktrack.spec.ts +278 -0
- package/tests/integration/spinnerLifecycle.spec.ts +270 -0
- package/tests/integration/summarizationFlow.spec.ts +135 -0
- package/tests/integration/testRunnerReal.spec.ts +63 -0
- package/tests/integration/webSearchAgent.spec.ts +155 -0
- package/tests/live/copilotSdkLive.spec.ts +149 -0
- package/tests/live/zavaFullWorkshop.spec.ts +515 -0
- package/tests/setup/loadEnv.ts +5 -0
- package/tests/unit/cli/developCommand.spec.ts +679 -0
- package/tests/unit/cli/directCommands.spec.ts +325 -0
- package/tests/unit/cli/envLoader.spec.ts +73 -0
- package/tests/unit/cli/ioContext.spec.ts +148 -0
- package/tests/unit/cli/preflight.spec.ts +125 -0
- package/tests/unit/cli/statusCommand.spec.ts +134 -0
- package/tests/unit/cli/workshopClientFallback.spec.ts +100 -0
- package/tests/unit/cli/workshopCommand.spec.ts +378 -0
- package/tests/unit/config/vitestEnvSetup.spec.ts +24 -0
- package/tests/unit/develop/checkpointState.spec.ts +378 -0
- package/tests/unit/develop/codeGenerator.spec.ts +447 -0
- package/tests/unit/develop/githubMcpAdapter.spec.ts +283 -0
- package/tests/unit/develop/mcpContextEnricher.spec.ts +564 -0
- package/tests/unit/develop/outputValidator.spec.ts +134 -0
- package/tests/unit/develop/pocScaffolder.spec.ts +451 -0
- package/tests/unit/develop/ralphLoop.spec.ts +1439 -0
- package/tests/unit/develop/templateRegistry.spec.ts +106 -0
- package/tests/unit/develop/testRunner.spec.ts +294 -0
- package/tests/unit/infraBicep.spec.ts +116 -0
- package/tests/unit/infraDeploy.spec.ts +102 -0
- package/tests/unit/infraTeardown.spec.ts +77 -0
- package/tests/unit/logging/logger.spec.ts +50 -0
- package/tests/unit/loop/conversationLoop.spec.ts +719 -0
- package/tests/unit/loop/phaseSummarizer.spec.ts +169 -0
- package/tests/unit/loop/streamingMarkdown.spec.ts +180 -0
- package/tests/unit/mcp/mcpManager.spec.ts +336 -0
- package/tests/unit/mcp/mcpTransport.spec.ts +689 -0
- package/tests/unit/mcp/retryPolicy.spec.ts +278 -0
- package/tests/unit/mcp/timeoutValidation.spec.ts +55 -0
- package/tests/unit/mcp/webSearch.spec.ts +718 -0
- package/tests/unit/phases/contextSummarizer.spec.ts +158 -0
- package/tests/unit/phases/discoveryEnricher.repeatCalls.spec.ts +125 -0
- package/tests/unit/phases/discoveryEnricher.spec.ts +512 -0
- package/tests/unit/phases/phaseExtractors.spec.ts +406 -0
- package/tests/unit/phases/phaseHandlers.spec.ts +483 -0
- package/tests/unit/prompts/promptLoader.spec.ts +144 -0
- package/tests/unit/schemas/pocSchemas.spec.ts +457 -0
- package/tests/unit/schemas/session.spec.ts +328 -0
- package/tests/unit/sessions/exportPaths.spec.ts +38 -0
- package/tests/unit/sessions/exportWriter.spec.ts +737 -0
- package/tests/unit/sessions/sessionManager.spec.ts +174 -0
- package/tests/unit/sessions/sessionStore.spec.ts +136 -0
- package/tests/unit/shared/activitySpinner.spec.ts +211 -0
- package/tests/unit/shared/cardsLoader.spec.ts +89 -0
- package/tests/unit/shared/copilotClient.spec.ts +185 -0
- package/tests/unit/shared/errorClassifier.spec.ts +152 -0
- package/tests/unit/shared/events.spec.ts +71 -0
- package/tests/unit/shared/markdownRenderer.spec.ts +42 -0
- package/tests/unit/shared/markdownRendererChunks.spec.ts +83 -0
- package/tests/unit/shared/tableRenderer.spec.ts +38 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +15 -0
- package/vitest.live.config.ts +19 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
# Implementation Plan: sofIA Unified Build-From-Scratch CLI
|
|
2
|
+
|
|
3
|
+
**Branch**: `001-cli-workshop-rebuild` | **Date**: 2026-02-26 | **Spec**: ./spec.md
|
|
4
|
+
**Input**: Feature specification from `specs/001-cli-workshop-rebuild/spec.md`
|
|
5
|
+
|
|
6
|
+
**Plan outputs created by this workflow**:
|
|
7
|
+
|
|
8
|
+
- Phase 0: ./research.md
|
|
9
|
+
- Phase 1: ./data-model.md, ./quickstart.md, ./contracts/*
|
|
10
|
+
|
|
11
|
+
## Summary
|
|
12
|
+
|
|
13
|
+
Build a Node.js + TypeScript GitHub Copilot SDK CLI that runs the governed workshop lifecycle for Discover → Ideate → Design → Select → Plan and captures PoC requirements for Develop, with explicit phase decision gates, repo-local session persistence, robust recovery, and deterministic automated testability (including PTY-based interactive harness). Concrete PoC repository generation and the Ralph loop are implemented in a separate feature (002-poc-generation) that consumes the session data produced here.
|
|
14
|
+
|
|
15
|
+
Transparency UX: provide a user-visible **reasoning/rationale view** as structured summaries (why we’re asking, what we inferred, what trade-offs we made), plus an **activity/telemetry stream** (phase state, tool usage, progress, retries) and an optional debug log.
|
|
16
|
+
|
|
17
|
+
Note: even though the constitution no longer forbids it, this plan does **not** include displaying raw hidden model chain-of-thought; instead it provides explicit, reviewable rationale summaries and intermediate artifacts.
|
|
18
|
+
|
|
19
|
+
## Technical Context
|
|
20
|
+
|
|
21
|
+
**Language/Version**: Node.js 20 LTS + TypeScript 5.x
|
|
22
|
+
**Primary Dependencies**: `@github/copilot-sdk`, `commander` (CLI), `@inquirer/prompts` (menus), `zod` (schemas), `pino` (logs), `ora` (spinners/activity), `marked` + `marked-terminal` (Markdown→ANSI), `chalk` (color), `cli-table3` (tables)
|
|
23
|
+
**Storage**: Repo-local files: `./.sofia/sessions/<sessionId>.json`, export bundles in `./exports/<sessionId>/`
|
|
24
|
+
**Testing**: Vitest (unit/integration), `node-pty` (interactive E2E harness), deterministic fakes for Copilot SDK sessions
|
|
25
|
+
**Target Platform**: macOS/Linux/Windows terminals (TTY and non-TTY); Node runtime only
|
|
26
|
+
**Project Type**: CLI application + library modules (agents/orchestration)
|
|
27
|
+
**Performance Goals**: First streamed output token ≤ 3 seconds in correctly configured environments; avoid blocking render loops
|
|
28
|
+
**Constraints**: No raw SDK JSON to users; no hidden chain-of-thought display; no implicit phase transitions; repo-local persistence; graceful MCP/tool degradation; interactive must be fully automatable via PTY; stdout must remain JSON-only in `--json` mode
|
|
29
|
+
**Scale/Scope**: Single-user/local facilitator runs; session sizes dominated by turn history + artifacts; support multiple sessions per repo
|
|
30
|
+
|
|
31
|
+
## CLI Rendering (Markdown, color, tables)
|
|
32
|
+
|
|
33
|
+
Goal: when possible, workshop outputs are authored in Markdown and rendered to the terminal in a readable, colorful format (headings, lists, code blocks, links, and tables at minimum).
|
|
34
|
+
|
|
35
|
+
Rendering rules:
|
|
36
|
+
|
|
37
|
+
- If `process.stdout.isTTY` and not `--json`, render Markdown to ANSI using `marked` + `marked-terminal`.
|
|
38
|
+
- **Streaming responses**: LLM text is rendered as formatted markdown incrementally during streaming using `marked` + `marked-terminal`. Each text chunk is processed through the renderer as it arrives, producing ANSI-formatted output in real time. Minor rendering artifacts from partial markdown (e.g., split headings, incomplete tables) are acceptable for responsiveness.
|
|
39
|
+
- Render tables using `cli-table3` for consistent borders/column widths (used for structured outputs like status, BXT scores; not for inline streaming).
|
|
40
|
+
- If non-TTY or `--json`, do not emit ANSI/spinners; output plain text (or raw Markdown when plain text would lose meaning).
|
|
41
|
+
- Keep activity/telemetry on stderr so stdout can remain clean for scripting.
|
|
42
|
+
|
|
43
|
+
### Visual Feedback & Activity Indicators (FR-043a/b/c)
|
|
44
|
+
|
|
45
|
+
The CLI provides continuous visual feedback during all operations via `ora` spinners and inline status summaries:
|
|
46
|
+
|
|
47
|
+
1. **"Thinking..." spinner**: Displayed during all silent gaps — after user input before LLM first token, and between tool results and next text output. Cleared when text streaming begins.
|
|
48
|
+
2. **Tool-specific spinner**: When the LLM triggers a tool call, the "Thinking..." spinner transitions to a contextual message (e.g., "⠋ Calling WorkIQ...", "⠋ Searching documentation..."). Cleared when the tool completes.
|
|
49
|
+
3. **Tool result summaries**: After each tool call completes, a one-line summary is printed below the spinner area (e.g., "✓ WorkIQ: Found 12 relevant processes"). These summaries remain visible in the output stream.
|
|
50
|
+
4. **`--debug` verbose tool output**: When `--debug` is specified, tool summaries expand to include arguments and full result details (multi-line). This reuses the existing `--debug` flag — no separate `--verbose` flag.
|
|
51
|
+
5. **Non-TTY/JSON suppression**: Spinners and tool summaries are suppressed in non-TTY and `--json` mode. Tool activity is written to stderr or the debug log only.
|
|
52
|
+
|
|
53
|
+
Spinner lifecycle in the ConversationLoop `streamResponse()` method:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
User input → Start "Thinking..." spinner
|
|
57
|
+
→ ToolCall event → Transition spinner to "⠋ <toolName>..."
|
|
58
|
+
→ ToolResult event → Stop spinner, print "✓ <toolName>: <summary>"
|
|
59
|
+
→ Restart "Thinking..." spinner (if more processing expected)
|
|
60
|
+
→ TextDelta event → Stop spinner, stream rendered markdown
|
|
61
|
+
→ Response complete → Ensure spinner stopped
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Implementation approach:
|
|
65
|
+
|
|
66
|
+
- Create `src/shared/activitySpinner.ts` module wrapping `ora` with methods: `startThinking()`, `startToolCall(toolName)`, `completeToolCall(toolName, summary)`, `stop()`, and `isActive()`.
|
|
67
|
+
- The spinner module respects `isTTY` and `isJsonMode` from the IO context.
|
|
68
|
+
- `ConversationLoop.streamResponse()` manages spinner lifecycle based on event types.
|
|
69
|
+
- `LoopIO` interface gains `writeToolSummary(toolName: string, summary: string, debug?: { args: Record<string, unknown>; result: unknown }): void` method.
|
|
70
|
+
- In `--debug` mode, `writeToolSummary()` expands the summary with args and full result details.
|
|
71
|
+
|
|
72
|
+
## Existing Assets: Prompts + Discovery Cards Dataset
|
|
73
|
+
|
|
74
|
+
This repository already contains two critical inputs that the implementation must build on.
|
|
75
|
+
|
|
76
|
+
### Original prompts (seed material)
|
|
77
|
+
|
|
78
|
+
- Location: `src/originalPrompts/`
|
|
79
|
+
- Files:
|
|
80
|
+
|
|
81
|
+
- `facilitator_persona.md`
|
|
82
|
+
- `design_thinking_persona.md`
|
|
83
|
+
- `design_thinking.md`
|
|
84
|
+
- `guardrails.md`
|
|
85
|
+
- `document_generator_persona.md`
|
|
86
|
+
- `document_generator_example.md`
|
|
87
|
+
|
|
88
|
+
Plan requirement:
|
|
89
|
+
|
|
90
|
+
- Create canonical runtime prompts under `src/prompts/` by adapting/modularizing these files (shared guardrails + per-step instructions + output schemas).
|
|
91
|
+
- Keep `src/originalPrompts/` intact as a historical reference; do not treat it as the runtime source of truth.
|
|
92
|
+
|
|
93
|
+
### Discovery Cards dataset (authoritative data)
|
|
94
|
+
|
|
95
|
+
- Dataset: `src/shared/data/cards.json`
|
|
96
|
+
- Loader (already implemented): `src/shared/data/cardsLoader.ts` (Zod validation + cached load + search)
|
|
97
|
+
|
|
98
|
+
Plan requirement:
|
|
99
|
+
|
|
100
|
+
- Use this dataset in the relevant workshop steps (Explore Cards, scoring, mapping cards→workflow steps, ideation support).
|
|
101
|
+
- Provide CLI affordances to browse categories, list cards, and search cards by keyword in interactive mode.
|
|
102
|
+
|
|
103
|
+
## MCP Integration: Runtime Wiring (Copilot SDK + MCP)
|
|
104
|
+
|
|
105
|
+
This repo’s MCP servers are configured for the development environment in `.vscode/mcp.json` and include:
|
|
106
|
+
|
|
107
|
+
- stdio servers (invoked via `npx`): `workiq`, `azure`, `context7`, `playwright`
|
|
108
|
+
- HTTP servers: `github` (`https://api.githubcopilot.com/mcp/`), `microsoftdocs/mcp` (`https://learn.microsoft.com/api/mcp`)
|
|
109
|
+
|
|
110
|
+
Plan requirement:
|
|
111
|
+
|
|
112
|
+
- Implement an `McpManager` module that:
|
|
113
|
+
- loads and validates `.vscode/mcp.json` (plus optional environment-variable overrides)
|
|
114
|
+
- connects to stdio servers via the MCP TypeScript SDK `Client` + `StdioClientTransport`
|
|
115
|
+
- connects to HTTP servers via `Client` + `StreamableHTTPClientTransport`
|
|
116
|
+
- lists tools (`client.listTools()`) and exposes them to the Copilot SDK as callable tools (namespaced as `mcp.<server>.<tool>`)
|
|
117
|
+
- classifies and surfaces errors (auth/connection/timeout/tool) without leaking secrets
|
|
118
|
+
|
|
119
|
+
Note: `.vscode/mcp.json` is a VS Code convention; the CLI must not assume Copilot SDK will auto-load it. The CLI loads it explicitly to reuse the same server inventory.
|
|
120
|
+
|
|
121
|
+
## Discovery Phase: Web Research via Copilot SDK tool-calling
|
|
122
|
+
|
|
123
|
+
The Discover phase requires web research “when possible”. To ensure this works in the CLI:
|
|
124
|
+
|
|
125
|
+
- Provide a first-class tool `web.search` (invoked via Copilot SDK tool-calling).
|
|
126
|
+
- Implement `web.search` by calling an Azure AI Foundry agent that has **Bing Search tools** configured (per “Grounding agents with Bing Search tools in Microsoft Foundry”).
|
|
127
|
+
- Configure the Foundry agent endpoint and key via environment variables (for example: `SOFIA_FOUNDRY_AGENT_ENDPOINT`, `SOFIA_FOUNDRY_AGENT_KEY`).
|
|
128
|
+
- The CLI MUST NOT log or persist these secrets; they are read at startup and used only for HTTPS calls to the agent.
|
|
129
|
+
- If the Foundry agent is not configured or returns a hard failure, degrade gracefully to a “guided research” prompt that asks the facilitator to paste links/notes.
|
|
130
|
+
|
|
131
|
+
Output contract:
|
|
132
|
+
|
|
133
|
+
- `web.search` returns structured results (title, url, snippet/summary) plus an optional `sources` list for auditability, derived from the Foundry agent’s Bing Search tool output.
|
|
134
|
+
|
|
135
|
+
## Constitution Check
|
|
136
|
+
|
|
137
|
+
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
|
138
|
+
|
|
139
|
+
Default gates for this repository (sofIA Copilot CLI) — derived from `.specify/memory/constitution.md`:
|
|
140
|
+
|
|
141
|
+
- **Outcome-first discovery**: plan ties work to a measurable business/user outcome.
|
|
142
|
+
- **Secure-by-default**: least privilege, no secrets/PII in logs or prompts.
|
|
143
|
+
- **Node.js + TypeScript**: aligns with GitHub Copilot SDK patterns used here.
|
|
144
|
+
- **MCP-first**: prefer MCP tools over ad-hoc HTTP when available.
|
|
145
|
+
- **Test-first (NON-NEGOTIABLE)**: new behavior is implemented via Red → Green → Review.
|
|
146
|
+
- **CLI transparency**: long-running steps stream progress; failures include recovery options.
|
|
147
|
+
|
|
148
|
+
If any gate cannot be met, document the exception under **Complexity Tracking** with rationale.
|
|
149
|
+
|
|
150
|
+
## Project Structure
|
|
151
|
+
|
|
152
|
+
### Documentation (this feature)
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
specs/001-cli-workshop-rebuild/
|
|
156
|
+
├── plan.md # This file (/speckit.plan command output)
|
|
157
|
+
├── research.md # Phase 0 output
|
|
158
|
+
├── data-model.md # Phase 1 output
|
|
159
|
+
├── quickstart.md # Phase 1 output
|
|
160
|
+
├── contracts/ # Phase 1 output
|
|
161
|
+
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Source Code (repository root)
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
src/
|
|
168
|
+
├── cli/ # command routing, menus, IO adapters
|
|
169
|
+
├── loop/ # ConversationLoop abstraction + streaming renderer
|
|
170
|
+
├── sessions/ # session model, persistence, backtracking, exports
|
|
171
|
+
├── phases/ # discover/ideate/design/select/plan, plus a Develop boundary module for PoC intent capture and delegation to feature 002
|
|
172
|
+
├── mcp/ # wrappers for WorkIQ/Context7/MicrosoftDocs/GitHub MCP
|
|
173
|
+
├── logging/ # redaction + pino setup + log file routing
|
|
174
|
+
├── prompts/ # canonical runtime prompts (derived from src/originalPrompts)
|
|
175
|
+
└── shared/ # shared schemas, types, card dataset loader, utilities
|
|
176
|
+
|
|
177
|
+
src/originalPrompts/ # existing seed prompts (kept for reference; not runtime source of truth)
|
|
178
|
+
|
|
179
|
+
tests/
|
|
180
|
+
├── unit/
|
|
181
|
+
├── integration/
|
|
182
|
+
└── e2e/ # PTY-driven interactive harness tests
|
|
183
|
+
|
|
184
|
+
.sofia/ # repo-local state (gitignored): sessions, temp artifacts
|
|
185
|
+
exports/ # repo-local exports (gitignored): customer artifact bundles
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Structure Decision**: Single Node.js/TypeScript CLI project at repository root with layered modules for CLI UX, conversation loop, phase orchestration, persistence, and MCP integrations.
|
|
189
|
+
|
|
190
|
+
## Agent Design: Step/Phase Coverage
|
|
191
|
+
|
|
192
|
+
The agent set is derived from the existing personas/prompts and covers the workshop pipeline end-to-end:
|
|
193
|
+
|
|
194
|
+
- Facilitator orchestrator (primary)
|
|
195
|
+
|
|
196
|
+
- Seed: `src/originalPrompts/facilitator_persona.md`
|
|
197
|
+
- Responsibilities: governed progression/decision gates, delegation to step specialists, persistence of summaries + artifacts.
|
|
198
|
+
|
|
199
|
+
- Step specialists (per phase/step)
|
|
200
|
+
|
|
201
|
+
- Seeds: `design_thinking_persona.md` + `design_thinking.md`, plus `guardrails.md` included everywhere.
|
|
202
|
+
- Output contracts: each step emits structured data for the session model (see `data-model.md`) and Markdown artifacts for export.
|
|
203
|
+
|
|
204
|
+
- Document generator
|
|
205
|
+
|
|
206
|
+
- Seed: `document_generator_persona.md` + `document_generator_example.md`
|
|
207
|
+
- Responsibilities: produce customer-ready workshop report/artifacts from session state.
|
|
208
|
+
|
|
209
|
+
- Discovery Cards support
|
|
210
|
+
|
|
211
|
+
- Data source: `src/shared/data/cards.json` via `cardsLoader.ts`
|
|
212
|
+
- Responsibilities: present cards, support scoring, map cards to workflow steps, seed ideation prompts with relevant cards.
|
|
213
|
+
|
|
214
|
+
## Phase 7: New Capabilities (Session Naming, Default Command, Auto-Start)
|
|
215
|
+
|
|
216
|
+
These additions address three new requirements clarified in Session 2026-02-27 (see spec.md Clarifications).
|
|
217
|
+
|
|
218
|
+
### 7a. Session Naming (FR-023a)
|
|
219
|
+
|
|
220
|
+
**Goal**: Auto-generate a short, human-readable session name after the first Discover exchange when `businessContext` is first captured.
|
|
221
|
+
|
|
222
|
+
**Design**:
|
|
223
|
+
|
|
224
|
+
- Add optional `name?: string` field to `workshopSessionSchema` in `src/shared/schemas/session.ts`.
|
|
225
|
+
- Update Discover phase system prompt to instruct the LLM to include a `sessionName` field in its structured JSON output alongside `businessContext`.
|
|
226
|
+
- Add `extractSessionName(response: string): string | null` extractor in `src/phases/phaseExtractors.ts`, parsing `sessionName` from the same JSON block used by `extractBusinessContext`.
|
|
227
|
+
- Update Discover handler's `extractResult()` to call `extractSessionName()` and set `session.name` when a name is found.
|
|
228
|
+
- Update `statusCommand.ts` to display the session name in table and JSON output.
|
|
229
|
+
- Update `workshopCommand.ts` to display the session name in menu/resume flows.
|
|
230
|
+
|
|
231
|
+
**Constraints**: Name is auto-generated; no user confirmation required. If the LLM omits `sessionName`, the session continues unnamed (no error).
|
|
232
|
+
|
|
233
|
+
### 7b. Default Workshop Command (FR-004 updated)
|
|
234
|
+
|
|
235
|
+
**Goal**: Running `sofia` with no subcommand starts the workshop flow (main menu). Workshop options (`--new-session`, `--phase`, `--retry`) promoted to top-level. `sofia workshop` kept as alias. `status` and `export` remain explicit subcommands.
|
|
236
|
+
|
|
237
|
+
**Design**:
|
|
238
|
+
|
|
239
|
+
- Restructure `src/cli/index.ts`:
|
|
240
|
+
- Move workshop options (`--new-session`, `--phase`, `--retry`) to `program` (top-level).
|
|
241
|
+
- Set a default action on `program` that invokes the workshop flow when no subcommand is given.
|
|
242
|
+
- Keep `program.command('workshop')` as an alias (same handler).
|
|
243
|
+
- `status` and `export` remain explicit subcommands.
|
|
244
|
+
- `--help` shows all workshop options at the top level.
|
|
245
|
+
|
|
246
|
+
**Constraints**: Must not break existing `sofia workshop`, `sofia status`, or `sofia export` commands. Direct command mode (`--session` + `--phase`) must continue working at top level.
|
|
247
|
+
|
|
248
|
+
### 7c. Auto-Start Conversation (FR-015a)
|
|
249
|
+
|
|
250
|
+
**Goal**: When a conversation phase starts (new or resumed), the ConversationLoop sends an initial message to the LLM before waiting for user input. The LLM introduces the phase and asks the first question. On resume, it summarizes progress and asks the next question.
|
|
251
|
+
|
|
252
|
+
**Design**:
|
|
253
|
+
|
|
254
|
+
- Add `initialMessage?: string` option to `ConversationLoopOptions`.
|
|
255
|
+
- Modify `ConversationLoop.run()`:
|
|
256
|
+
- If `initialMessage` is provided, send it as a system/user message to the LLM before entering the `readInput()` loop.
|
|
257
|
+
- Stream and render the LLM response as the opening greeting.
|
|
258
|
+
- Record the initial exchange in turn history.
|
|
259
|
+
- If no first token arrives within 10 seconds, treat as transient failure and apply retry logic.
|
|
260
|
+
- Add `getInitialMessage(session: WorkshopSession): string` method to the `PhaseHandler` interface.
|
|
261
|
+
- For new sessions: generates a prompt like "Introduce the [phase] phase and ask the first question."
|
|
262
|
+
- For resumed sessions: generates a prompt like "Summarize progress so far and ask the next question."
|
|
263
|
+
- Wire `getInitialMessage()` into `workshopCommand.ts` so it's passed to `ConversationLoop` at phase start.
|
|
264
|
+
- All phase handler factories must implement `getInitialMessage()`.
|
|
265
|
+
|
|
266
|
+
**Timeout**: 10 seconds for first token of auto-start greeting (per clarification).
|
|
267
|
+
|
|
268
|
+
## Post-Design Constitution Re-check (Phase 1)
|
|
269
|
+
|
|
270
|
+
- User-visible transparency is provided via rationale summaries + intermediate artifacts + activity/telemetry (not raw hidden chain-of-thought).
|
|
271
|
+
- Interactive mode never auto-advances phases; explicit decision gate required.
|
|
272
|
+
- Testability is a first-class deliverable: unit + integration + PTY E2E harness.
|
|
273
|
+
|
|
274
|
+
## Post-Design Constitution Re-check (Phase 7 additions)
|
|
275
|
+
|
|
276
|
+
- **Outcome-first**: Session naming improves facilitator UX (identify sessions at a glance). Default command reduces friction. Auto-start eliminates dead air.
|
|
277
|
+
- **Secure-by-default**: No new secrets introduced; session name is derived from business context already in the session.
|
|
278
|
+
- **Test-first**: All new behavior requires failing tests before implementation (TDD).
|
|
279
|
+
- **CLI transparency**: Auto-start greeting makes the system proactive and informative.
|
|
280
|
+
|
|
281
|
+
## Phase 8: Visual Feedback & Streaming Markdown (FR-009a, FR-043a/b/c)
|
|
282
|
+
|
|
283
|
+
These additions address requirements clarified in Session 2026-02-27 regarding visual feedback during internal operations and incremental markdown rendering.
|
|
284
|
+
|
|
285
|
+
### 8a. Incremental Streaming Markdown Rendering (FR-009a)
|
|
286
|
+
|
|
287
|
+
**Goal**: Render LLM streaming text through `marked` + `marked-terminal` incrementally during streaming, so users see formatted markdown (headings, bold, code blocks, lists) in real time rather than raw markdown syntax.
|
|
288
|
+
|
|
289
|
+
**Design**:
|
|
290
|
+
|
|
291
|
+
- Update `ConversationLoop.streamResponse()` to pass each `TextDelta` chunk through `renderMarkdown()` before writing to `io.write()`.
|
|
292
|
+
- Update `renderMarkdown()` to handle incremental rendering: process chunks through `marked` + `marked-terminal` as they arrive. Accept minor artifacts from partial markdown (split headings, incomplete tables).
|
|
293
|
+
- Ensure the full response is still captured as raw markdown for session persistence (turn history stores raw markdown, not ANSI).
|
|
294
|
+
- In non-TTY/JSON mode, chunks are written raw (no ANSI rendering), preserving existing behavior.
|
|
295
|
+
|
|
296
|
+
**Files touched**: `src/loop/conversationLoop.ts`, `src/shared/markdownRenderer.ts`
|
|
297
|
+
|
|
298
|
+
### 8b. Activity Spinner Module (FR-043a, FR-043c)
|
|
299
|
+
|
|
300
|
+
**Goal**: Provide a unified spinner module wrapping `ora` that manages "Thinking..." and tool-specific spinners with proper lifecycle management.
|
|
301
|
+
|
|
302
|
+
**Design**:
|
|
303
|
+
|
|
304
|
+
- Create `src/shared/activitySpinner.ts` with an `ActivitySpinner` class:
|
|
305
|
+
- `startThinking()`: Display "Thinking..." spinner. No-op if non-TTY/JSON.
|
|
306
|
+
- `startToolCall(toolName: string)`: Transition to "⠋ <toolName>..." spinner. If already spinning, update text in-place.
|
|
307
|
+
- `completeToolCall(toolName: string, summary: string)`: Stop spinner, print "✓ <toolName>: <summary>" line.
|
|
308
|
+
- `stop()`: Stop any active spinner.
|
|
309
|
+
- `isActive(): boolean`: Check if a spinner is currently running.
|
|
310
|
+
- Constructor accepts `{ isTTY: boolean; isJsonMode: boolean; debugMode: boolean }` — all spinner operations are no-ops when not TTY or in JSON mode.
|
|
311
|
+
- The spinner writes to stderr to avoid polluting stdout.
|
|
312
|
+
|
|
313
|
+
**Files touched**: `src/shared/activitySpinner.ts` (new)
|
|
314
|
+
|
|
315
|
+
### 8c. Tool Call Summaries & Debug Verbose Output (FR-043b)
|
|
316
|
+
|
|
317
|
+
**Goal**: After each tool call completes, display a one-line summary. In `--debug` mode, expand with full arguments and result details.
|
|
318
|
+
|
|
319
|
+
**Design**:
|
|
320
|
+
|
|
321
|
+
- Add `writeToolSummary(toolName: string, summary: string, debug?: { args: Record<string, unknown>; result: unknown }): void` method to `LoopIO` interface.
|
|
322
|
+
- Implement in `createLoopIO()` in `src/cli/ioContext.ts`:
|
|
323
|
+
- Default: prints `✓ <toolName>: <summary>` to stderr.
|
|
324
|
+
- `--debug`: additionally prints formatted JSON of args and result below the summary.
|
|
325
|
+
- Non-TTY/JSON: omit from stdout; write to stderr or debug log only.
|
|
326
|
+
- Update `ConversationLoop.streamResponse()` to call `io.writeToolSummary()` when a `ToolResult` event is received, constructing the summary from the event data.
|
|
327
|
+
|
|
328
|
+
**Files touched**: `src/loop/conversationLoop.ts`, `src/cli/ioContext.ts`
|
|
329
|
+
|
|
330
|
+
### 8d. ConversationLoop Spinner Integration (FR-043a/b/c combined)
|
|
331
|
+
|
|
332
|
+
**Goal**: Wire the `ActivitySpinner` into `ConversationLoop.streamResponse()` to manage the full spinner lifecycle across thinking, tool calls, and text streaming.
|
|
333
|
+
|
|
334
|
+
**Design**:
|
|
335
|
+
|
|
336
|
+
- `ConversationLoop` constructor accepts an `ActivitySpinner` instance (injected via options or created from IO context).
|
|
337
|
+
- In `streamResponse()`, manage spinner state based on event types:
|
|
338
|
+
1. Before sending message: call `spinner.startThinking()`.
|
|
339
|
+
2. On `ToolCall` event: call `spinner.startToolCall(event.toolName)`.
|
|
340
|
+
3. On `ToolResult` event: call `spinner.completeToolCall(event.toolName, summarize(event.result))`, then `spinner.startThinking()` if more events expected.
|
|
341
|
+
4. On first `TextDelta` event: call `spinner.stop()` (clear spinner, start streaming text).
|
|
342
|
+
5. On response complete: call `spinner.stop()` (safety net).
|
|
343
|
+
- Expose `spinner` option in `ConversationLoopOptions` to allow injection for testing (pass a no-op spinner in tests).
|
|
344
|
+
|
|
345
|
+
**Files touched**: `src/loop/conversationLoop.ts`
|
|
346
|
+
|
|
347
|
+
### Post-Design Constitution Re-check (Phase 8)
|
|
348
|
+
|
|
349
|
+
- **Outcome-first**: Visual feedback eliminates "dead terminal" anxiety — users always know the system is working. Markdown rendering improves readability of LLM outputs.
|
|
350
|
+
- **CLI transparency**: Spinners, tool summaries, and thinking indicators make internal operations visible without exposing raw SDK internals.
|
|
351
|
+
- **Test-first**: All new behavior requires failing tests before implementation (TDD). Spinner can be tested via a fake/mock `ora` or by verifying event-driven callbacks.
|
|
352
|
+
- **Secure-by-default**: Tool summaries in default mode show no sensitive data. `--debug` verbose output is opt-in and goes to stderr.
|
|
353
|
+
|
|
354
|
+
## Complexity Tracking
|
|
355
|
+
|
|
356
|
+
> **Fill ONLY if Constitution Check has violations that must be justified**
|
|
357
|
+
|
|
358
|
+
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
|
359
|
+
| --------- | ---------- | ----------------------------------- |
|
|
360
|
+
| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
|
|
361
|
+
| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Quickstart: sofIA CLI workshop rebuild
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
- Node.js 20 LTS
|
|
6
|
+
- npm
|
|
7
|
+
|
|
8
|
+
## Setup
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Run (interactive)
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Start an interactive workshop (tsx, no build required)
|
|
18
|
+
npm run start -- workshop
|
|
19
|
+
|
|
20
|
+
# Start a new session directly
|
|
21
|
+
npm run start -- workshop --new-session
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Run (non-interactive / automation)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Session status as JSON
|
|
28
|
+
npm run start -- status --session <id> --json
|
|
29
|
+
|
|
30
|
+
# Direct command mode: run a specific phase
|
|
31
|
+
npm run start -- workshop --session <id> --phase Discover --non-interactive
|
|
32
|
+
|
|
33
|
+
# With retry for transient failures
|
|
34
|
+
npm run start -- workshop --session <id> --phase Ideate --retry 3 --non-interactive
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Run (built mode)
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Build TypeScript first
|
|
41
|
+
npm run build
|
|
42
|
+
|
|
43
|
+
# Then use the compiled output
|
|
44
|
+
npm run sofia -- workshop
|
|
45
|
+
npm run sofia -- status --session <id> --json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Storage
|
|
49
|
+
|
|
50
|
+
- Session files: `.sofia/sessions/<sessionId>.json`
|
|
51
|
+
- Exports: `./exports/<sessionId>/`
|
|
52
|
+
|
|
53
|
+
## Testing
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Full suite (unit + integration + e2e)
|
|
57
|
+
npm test
|
|
58
|
+
|
|
59
|
+
# Unit tests only
|
|
60
|
+
npm run test:unit
|
|
61
|
+
|
|
62
|
+
# Integration tests only
|
|
63
|
+
npm run test:integration
|
|
64
|
+
|
|
65
|
+
# Interactive E2E (PTY)
|
|
66
|
+
npm run test:e2e
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Debug logs
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm run start -- workshop --debug --log-file .sofia/logs/dev.log
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Environment variables (optional)
|
|
76
|
+
|
|
77
|
+
| Variable | Purpose |
|
|
78
|
+
|----------|---------|
|
|
79
|
+
| `SOFIA_FOUNDRY_AGENT_ENDPOINT` | Azure AI Foundry Bing Search agent endpoint |
|
|
80
|
+
| `SOFIA_FOUNDRY_AGENT_KEY` | API key for the Foundry agent |
|
|
81
|
+
|
|
82
|
+
See [docs/environment.md](../../docs/environment.md) for details.
|
|
83
|
+
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Research: sofIA Unified Build-From-Scratch CLI
|
|
2
|
+
|
|
3
|
+
**Feature**: ./spec.md
|
|
4
|
+
**Plan**: ./plan.md
|
|
5
|
+
**Date**: 2026-02-26
|
|
6
|
+
|
|
7
|
+
This document resolves technical choices for implementing the spec in Node.js/TypeScript with the GitHub Copilot SDK, focusing on testability, recoverability, and CLI-first UX.
|
|
8
|
+
|
|
9
|
+
## Decisions
|
|
10
|
+
|
|
11
|
+
### 1) CLI command framework
|
|
12
|
+
|
|
13
|
+
- Decision: Use `commander` for command parsing and help output.
|
|
14
|
+
- Rationale: Widely used, stable, good help/version/option ergonomics; plays well with non-TTY and JSON output constraints.
|
|
15
|
+
- Alternatives considered:
|
|
16
|
+
- `yargs`: strong but heavier and less aligned with our simple command surface.
|
|
17
|
+
- `oclif`: powerful but more framework-heavy than needed for early MVP.
|
|
18
|
+
|
|
19
|
+
### 2) Interactive menus (TTY)
|
|
20
|
+
|
|
21
|
+
- Decision: Use `@inquirer/prompts` for menu-driven interactive flows.
|
|
22
|
+
- Rationale: Modern UX for prompts, consistent behavior in Node environments, easy to stub in tests via input adapters.
|
|
23
|
+
- Alternatives considered:
|
|
24
|
+
- `@clack/prompts`: very nice UX, but inquirer’s ecosystem is broader and easier to standardize.
|
|
25
|
+
- Full-screen TUI frameworks (Ink/Blessed): rejected because the spec’s out-of-scope forbids rich terminal UI, and they complicate PTY automation.
|
|
26
|
+
|
|
27
|
+
### 3) Reasoning transparency (“LLM thoughts”) UX
|
|
28
|
+
|
|
29
|
+
- Decision: Provide a **rationale view** made of structured, user-readable summaries (intent, assumptions, trade-offs, and what evidence/tools were used) plus an **Activity Stream** (tool usage, phase state, progress) and optional debug logs.
|
|
30
|
+
- Rationale: Users get transparency and auditability without relying on hidden model chain-of-thought; also keeps the CLI deterministic and safe.
|
|
31
|
+
- Alternatives considered:
|
|
32
|
+
- Full-screen TUI panes: rejected (spec out-of-scope for rich terminal UI and complicates PTY automation).
|
|
33
|
+
- Dumping raw hidden chain-of-thought: rejected (not needed for transparency; better handled as explicit summaries + artifacts).
|
|
34
|
+
|
|
35
|
+
### 4) Markdown rendering in the CLI
|
|
36
|
+
|
|
37
|
+
- Decision: Render Markdown to ANSI when possible (TTY, non-JSON) with color and table support.
|
|
38
|
+
- Rationale: Workshop artifacts are naturally Markdown; rendering improves readability while preserving exports as Markdown.
|
|
39
|
+
- Proposed libraries: `marked` + `marked-terminal`, `chalk`, `cli-table3`.
|
|
40
|
+
|
|
41
|
+
### 5) Streaming output rendering
|
|
42
|
+
|
|
43
|
+
- Decision: Implement a streaming renderer that writes incremental text to stdout immediately and supports a dedicated activity channel.
|
|
44
|
+
- Rationale: Required by spec (no full-buffer output; TTFT ≤ 3s). Enables deterministic tests by asserting event ordering and output boundaries.
|
|
45
|
+
- Alternatives considered:
|
|
46
|
+
- Buffer until completion: violates TTFT and streaming requirements.
|
|
47
|
+
|
|
48
|
+
### 6) Session persistence format and location
|
|
49
|
+
|
|
50
|
+
- Decision: Repo-local persistence at `./.sofia/sessions/<sessionId>.json` (single JSON per session), persisted after every user turn.
|
|
51
|
+
- Rationale: Matches clarified requirements; easiest to diff/debug, easiest to test; ensures recoverability across crashes.
|
|
52
|
+
- Alternatives considered:
|
|
53
|
+
- JSONL turns log: good for append-only, but spec preference is single JSON file.
|
|
54
|
+
- SQLite: robust but unnecessary complexity for MVP.
|
|
55
|
+
|
|
56
|
+
### 7) Export format
|
|
57
|
+
|
|
58
|
+
- Decision: Default export to `./exports/<sessionId>/` containing phase Markdown artifacts + `summary.json`.
|
|
59
|
+
- Rationale: Human-friendly outputs for customers + machine-readable index for tooling.
|
|
60
|
+
- Alternatives considered:
|
|
61
|
+
- ZIP: introduces archive edge cases and harder diff/review.
|
|
62
|
+
|
|
63
|
+
### 8) Testing stack
|
|
64
|
+
|
|
65
|
+
- Decision: Use Vitest for unit/integration and `node-pty` for interactive E2E harness.
|
|
66
|
+
- Rationale: Deterministic, fast, good TypeScript support; PTY harness satisfies “interactive-only manual verification is insufficient”.
|
|
67
|
+
- Alternatives considered:
|
|
68
|
+
- Jest: fine, but Vitest is faster and TypeScript-friendly.
|
|
69
|
+
- Only integration tests without PTY: violates spec.
|
|
70
|
+
|
|
71
|
+
### 9) Copilot SDK simulation for tests
|
|
72
|
+
|
|
73
|
+
- Decision: Wrap Copilot SDK interactions behind a small interface (`CopilotClient` / `ConversationSession` abstraction) with deterministic fakes for tests.
|
|
74
|
+
- Rationale: Avoid flaky network/LLM dependence; allow tests to assert control-flow and output contracts.
|
|
75
|
+
- Alternatives considered:
|
|
76
|
+
- Live Copilot calls in tests: non-deterministic and brittle.
|
|
77
|
+
|
|
78
|
+
### 10) Logging
|
|
79
|
+
|
|
80
|
+
- Decision: Use `pino` with a `--log-file <path>` (and/or `--debug`) option to enable full internal trace logs. Ensure strict redaction.
|
|
81
|
+
- Rationale: Speeds debugging; meets observability requirements; keeps user output clean.
|
|
82
|
+
- Alternatives considered:
|
|
83
|
+
- Console-only logs: risks mixing telemetry into stdout; harder to persist.
|
|
84
|
+
|
|
85
|
+
### 11) Internal event model (streaming + tools)
|
|
86
|
+
|
|
87
|
+
- Decision: Define a stable internal event model for streaming (`TextDelta`, `Activity`, `ToolCall`, `ToolResult`, `PhaseChanged`, `Error`) and adapt whatever Copilot SDK emits into these events.
|
|
88
|
+
- Rationale: Keeps the CLI deterministic and testable even if underlying SDK event shapes change; enables fakes to drive the `ConversationLoop` in tests.
|
|
89
|
+
- Alternatives considered:
|
|
90
|
+
- Binding tests directly to SDK event shapes: couples tests to external library details and increases brittleness.
|
|
91
|
+
|
|
92
|
+
### 12) `status` output contract
|
|
93
|
+
|
|
94
|
+
- Decision: `sofia status --json` outputs `{ sessionId, phase, status, updatedAt, nextAction }` as the stable minimum.
|
|
95
|
+
- Rationale: Enables scripting and CI checks; human mode stays concise.
|
|
96
|
+
- Alternatives considered:
|
|
97
|
+
- Dumping full session JSON: violates “no raw SDK JSON / no overwhelming output” intent and risks leaking sensitive fields.
|
|
98
|
+
|
|
99
|
+
### 13) MCP availability and degradation strategy
|
|
100
|
+
|
|
101
|
+
- Decision: Treat all MCP integrations as optional at runtime; when unavailable, fall back to guided prompts + local scaffolding, while preserving the governed phase flow.
|
|
102
|
+
- Rationale: Matches clarified requirement to keep working when GitHub MCP is down; keeps workshop usable offline/limited.
|
|
103
|
+
- Alternatives considered:
|
|
104
|
+
- Hard-failing on missing MCP servers: breaks workshop continuity and violates graceful degradation.
|
|
105
|
+
|
|
106
|
+
### 14) MCP runtime wiring (how the CLI uses MCP)
|
|
107
|
+
|
|
108
|
+
- Decision: Load MCP server inventory from `.vscode/mcp.json` at runtime and connect using the MCP TypeScript SDK (`Client` + transports).
|
|
109
|
+
- Rationale: Reuses the repo’s canonical MCP server list (WorkIQ, GitHub MCP, Microsoft Learn MCP, Context7, Playwright, Azure MCP) and keeps integrations consistent.
|
|
110
|
+
- Implementation note: use `StdioClientTransport` for `command` servers (npx-based) and `StreamableHTTPClientTransport` for remote HTTP MCP servers.
|
|
111
|
+
|
|
112
|
+
### 15) Web research in Discover (web search)
|
|
113
|
+
|
|
114
|
+
- Decision: Provide a `web.search` tool callable by the Copilot SDK; implement it by calling an Azure AI Foundry agent with Bing Search tools configured.
|
|
115
|
+
- Rationale: Uses a first-party, well-supported Bing Search integration as recommended for grounding agents; keeps the CLI thin and lets the Foundry agent orchestrate search.
|
|
116
|
+
- Degradation: if the Foundry agent is not configured or fails, fall back to guided prompts requesting user-provided links/notes.
|