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,511 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end interactive simulation with Zava Industries script.
|
|
3
|
+
*
|
|
4
|
+
* This test simulates a complete workshop session using the Zava Industries
|
|
5
|
+
* agent interaction script. It exercises the full code path:
|
|
6
|
+
* - All 6 workshop phases (Discover → Ideate → Design → Select → Plan → Develop)
|
|
7
|
+
* - ConversationLoop with post-phase summarization
|
|
8
|
+
* - Phase boundary enforcement
|
|
9
|
+
* - Context summarization across phases
|
|
10
|
+
* - Export with conversation fallback
|
|
11
|
+
*
|
|
12
|
+
* Uses a fake CopilotClient that returns scripted LLM responses with
|
|
13
|
+
* embedded JSON blocks for structured data extraction.
|
|
14
|
+
*/
|
|
15
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
16
|
+
import { mkdtemp, rm, readFile, readdir } from 'node:fs/promises';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
import { tmpdir } from 'node:os';
|
|
19
|
+
|
|
20
|
+
import { ConversationLoop } from '../../src/loop/conversationLoop.js';
|
|
21
|
+
import type { LoopIO } from '../../src/loop/conversationLoop.js';
|
|
22
|
+
import type { CopilotClient, ConversationSession, SessionOptions } from '../../src/shared/copilotClient.js';
|
|
23
|
+
import type { WorkshopSession, PhaseValue } from '../../src/shared/schemas/session.js';
|
|
24
|
+
import { createPhaseHandler, getPhaseOrder } from '../../src/phases/phaseHandlers.js';
|
|
25
|
+
import { exportSession } from '../../src/sessions/exportWriter.js';
|
|
26
|
+
import { buildSummarizedContext, renderSummarizedContext } from '../../src/phases/contextSummarizer.js';
|
|
27
|
+
|
|
28
|
+
// ── Zava scripted responses ─────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
const ZAVA_USER_INPUTS: Record<PhaseValue, string[]> = {
|
|
31
|
+
Discover: [
|
|
32
|
+
'We are Zava Industries, a mid-premium fashion company based in Milan. Our biggest challenge is speed in trend analysis.',
|
|
33
|
+
"I'd like to focus on Trend Intelligence and Signal Aggregation.",
|
|
34
|
+
'done',
|
|
35
|
+
],
|
|
36
|
+
Ideate: [
|
|
37
|
+
'I love these ideas: TrendLens, TrendPulse Dashboard, AutoBrief Generator, Celebrity Impact Tracker, Trend Predictor.',
|
|
38
|
+
'done',
|
|
39
|
+
],
|
|
40
|
+
Design: [
|
|
41
|
+
'TrendLens feasibility=3, value=5. TrendPulse feasibility=4, value=5. AutoBrief feasibility=4, value=3.',
|
|
42
|
+
'done',
|
|
43
|
+
],
|
|
44
|
+
Select: [
|
|
45
|
+
'I want to proceed with TrendPulse Dashboard with integrated TrendLens.',
|
|
46
|
+
'done',
|
|
47
|
+
],
|
|
48
|
+
Plan: [
|
|
49
|
+
'Azure Functions backend, Azure Cognitive Services for image analysis, React frontend. 4 week PoC.',
|
|
50
|
+
'done',
|
|
51
|
+
],
|
|
52
|
+
Develop: [
|
|
53
|
+
'TypeScript + Node.js backend, React dashboard. Must run locally for PoC.',
|
|
54
|
+
'done',
|
|
55
|
+
],
|
|
56
|
+
Complete: [],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// LLM responses that include JSON blocks for extraction
|
|
60
|
+
const ZAVA_LLM_RESPONSES: Record<PhaseValue, string[]> = {
|
|
61
|
+
Discover: [
|
|
62
|
+
`Great! Let me help you explore Zava Industries' challenges.
|
|
63
|
+
|
|
64
|
+
\`\`\`json
|
|
65
|
+
{
|
|
66
|
+
"businessDescription": "Zava Industries is a mid-premium fashion company based in Milan specializing in trend-driven clothing for ages 20-55",
|
|
67
|
+
"challenges": ["Speed of trend analysis", "Manual data gathering", "Scattered data across tools", "Slow trend-to-retail cycle"],
|
|
68
|
+
"constraints": ["Azure-based infrastructure"],
|
|
69
|
+
"successMetrics": [{"name": "Trend detection lead time", "value": "<1 week"}, {"name": "Collection hit rate", "value": "50%+"}]
|
|
70
|
+
}
|
|
71
|
+
\`\`\`
|
|
72
|
+
|
|
73
|
+
I understand your situation. Let's map out your workflow.`,
|
|
74
|
+
|
|
75
|
+
`Excellent choice! Here's the workflow map:
|
|
76
|
+
|
|
77
|
+
\`\`\`json
|
|
78
|
+
{
|
|
79
|
+
"activities": [
|
|
80
|
+
{"id": "s1", "name": "Social Media Scanning"},
|
|
81
|
+
{"id": "s2", "name": "Celebrity Monitoring"},
|
|
82
|
+
{"id": "s3", "name": "Runway Tracking"},
|
|
83
|
+
{"id": "s4", "name": "Competitor Analysis"},
|
|
84
|
+
{"id": "s5", "name": "Signal Consolidation"},
|
|
85
|
+
{"id": "s6", "name": "Trend Scoring"},
|
|
86
|
+
{"id": "s7", "name": "Design Brief Creation"},
|
|
87
|
+
{"id": "s8", "name": "Designer Feedback Loop"}
|
|
88
|
+
],
|
|
89
|
+
"edges": [
|
|
90
|
+
{"fromStepId": "s1", "toStepId": "s5"},
|
|
91
|
+
{"fromStepId": "s2", "toStepId": "s5"},
|
|
92
|
+
{"fromStepId": "s3", "toStepId": "s5"},
|
|
93
|
+
{"fromStepId": "s4", "toStepId": "s5"},
|
|
94
|
+
{"fromStepId": "s5", "toStepId": "s6"},
|
|
95
|
+
{"fromStepId": "s6", "toStepId": "s7"},
|
|
96
|
+
{"fromStepId": "s7", "toStepId": "s8"}
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
\`\`\``,
|
|
100
|
+
|
|
101
|
+
`Great! The Discover phase is complete. Let's move on.`,
|
|
102
|
+
],
|
|
103
|
+
Ideate: [
|
|
104
|
+
`Here are the AI-powered ideas based on Zava's workflow:
|
|
105
|
+
|
|
106
|
+
\`\`\`json
|
|
107
|
+
[
|
|
108
|
+
{"id": "idea-1", "title": "TrendLens", "description": "AI visual analyzer for social media and celebrity photos extracting fashion attributes in near-real-time", "workflowStepIds": ["s1", "s2", "s3"]},
|
|
109
|
+
{"id": "idea-2", "title": "TrendPulse Dashboard", "description": "Unified real-time dashboard aggregating all trend signals with scores and lifecycle indicators", "workflowStepIds": ["s5", "s6"]},
|
|
110
|
+
{"id": "idea-3", "title": "AutoBrief Generator", "description": "AI that creates design briefs from detected trends including visual mood boards", "workflowStepIds": ["s7", "s8"]},
|
|
111
|
+
{"id": "idea-4", "title": "Celebrity Impact Tracker", "description": "AI correlating celebrity outfit appearances with social media engagement spikes", "workflowStepIds": ["s2"]},
|
|
112
|
+
{"id": "idea-5", "title": "Trend Predictor", "description": "Predictive model estimating trend lifecycle and commercial potential", "workflowStepIds": ["s6"]}
|
|
113
|
+
]
|
|
114
|
+
\`\`\`
|
|
115
|
+
|
|
116
|
+
These ideas address your core bottleneck of manual trend analysis.`,
|
|
117
|
+
`Great selection! Let's proceed to Design.`,
|
|
118
|
+
],
|
|
119
|
+
Design: [
|
|
120
|
+
`Here's the evaluation using a feasibility-value matrix:
|
|
121
|
+
|
|
122
|
+
\`\`\`json
|
|
123
|
+
{
|
|
124
|
+
"ideas": [
|
|
125
|
+
{"ideaId": "idea-1", "feasibility": 3, "value": 5, "risks": ["Social media API limits", "Fashion-domain CV accuracy"], "dataNeeded": ["Social media images", "Runway photos"]},
|
|
126
|
+
{"ideaId": "idea-2", "feasibility": 4, "value": 5, "risks": ["Change management", "Data integration complexity"], "dataNeeded": ["All source feeds", "Historical sales data"]},
|
|
127
|
+
{"ideaId": "idea-3", "feasibility": 4, "value": 3, "risks": ["Design quality expectations"], "dataNeeded": ["Trend data", "Existing briefs"]},
|
|
128
|
+
{"ideaId": "idea-4", "feasibility": 3, "value": 4, "risks": ["Celebrity data availability"], "dataNeeded": ["Celebrity feeds", "Social engagement data"]},
|
|
129
|
+
{"ideaId": "idea-5", "feasibility": 2, "value": 5, "risks": ["Historical data requirements"], "dataNeeded": ["Multi-year trend data"]}
|
|
130
|
+
],
|
|
131
|
+
"method": "feasibility-value-matrix"
|
|
132
|
+
}
|
|
133
|
+
\`\`\`
|
|
134
|
+
|
|
135
|
+
\`\`\`mermaid
|
|
136
|
+
graph TD
|
|
137
|
+
A[Social Media APIs] --> B[TrendLens Vision AI]
|
|
138
|
+
B --> C[Signal Store]
|
|
139
|
+
D[Celebrity Feeds] --> B
|
|
140
|
+
E[Runway Data] --> B
|
|
141
|
+
C --> F[TrendPulse Dashboard]
|
|
142
|
+
F --> G[Trend Scoring Engine]
|
|
143
|
+
G --> H[Design Brief Generator]
|
|
144
|
+
\`\`\``,
|
|
145
|
+
`The Design phase is complete. Let's select the best idea.`,
|
|
146
|
+
],
|
|
147
|
+
Select: [
|
|
148
|
+
`Based on the evaluation, I recommend **TrendPulse Dashboard with integrated TrendLens**:
|
|
149
|
+
|
|
150
|
+
\`\`\`json
|
|
151
|
+
{
|
|
152
|
+
"ideaId": "idea-2",
|
|
153
|
+
"selectionRationale": "TrendPulse Dashboard has the best combined feasibility (4) and value (5) score. Integrating TrendLens visual AI gives it unique competitive advantage. It addresses the core bottleneck of manual data gathering and slow consolidation.",
|
|
154
|
+
"confirmedByUser": true,
|
|
155
|
+
"confirmedAt": "2026-03-04T07:00:00Z"
|
|
156
|
+
}
|
|
157
|
+
\`\`\``,
|
|
158
|
+
`Selection confirmed. Moving to Planning.`,
|
|
159
|
+
],
|
|
160
|
+
Plan: [
|
|
161
|
+
`Here's the implementation plan:
|
|
162
|
+
|
|
163
|
+
\`\`\`json
|
|
164
|
+
{
|
|
165
|
+
"milestones": [
|
|
166
|
+
{"id": "m1", "title": "Foundation & Data Pipeline", "items": ["Set up Azure Functions project", "Create Instagram API connector", "Set up Cosmos DB schema"]},
|
|
167
|
+
{"id": "m2", "title": "Visual AI Integration", "items": ["Integrate Azure Cognitive Services", "Build fashion attribute extractor", "Create trend signal storage"]},
|
|
168
|
+
{"id": "m3", "title": "Dashboard & Scoring", "items": ["Build React dashboard", "Implement trend frequency charts", "Add scoring algorithm"]},
|
|
169
|
+
{"id": "m4", "title": "Integration & Testing", "items": ["Connect all components", "Run with 100+ test images", "Measure accuracy against 70% target"]}
|
|
170
|
+
],
|
|
171
|
+
"architectureNotes": "Azure Functions + Azure Cognitive Services + Cosmos DB + React. TypeScript throughout.",
|
|
172
|
+
"dependencies": ["Instagram Graph API access", "Azure Cognitive Services subscription", "Cosmos DB instance"]
|
|
173
|
+
}
|
|
174
|
+
\`\`\``,
|
|
175
|
+
`The Plan phase is complete. Ready for PoC development.`,
|
|
176
|
+
],
|
|
177
|
+
Develop: [
|
|
178
|
+
`PoC requirements captured:
|
|
179
|
+
|
|
180
|
+
\`\`\`json
|
|
181
|
+
{
|
|
182
|
+
"repoSource": "local",
|
|
183
|
+
"techStack": {
|
|
184
|
+
"language": "TypeScript",
|
|
185
|
+
"runtime": "Node.js 22",
|
|
186
|
+
"testRunner": "vitest",
|
|
187
|
+
"framework": "React + Azure Functions",
|
|
188
|
+
"buildCommand": "npm run build"
|
|
189
|
+
},
|
|
190
|
+
"iterations": []
|
|
191
|
+
}
|
|
192
|
+
\`\`\``,
|
|
193
|
+
`PoC specification complete. Run \`sofia dev\` to generate the code.`,
|
|
194
|
+
],
|
|
195
|
+
Complete: [],
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// ── Test infrastructure ──────────────────────────────────────────────────────
|
|
199
|
+
|
|
200
|
+
function createScriptedClient(phase: PhaseValue): CopilotClient {
|
|
201
|
+
let responseIndex = 0;
|
|
202
|
+
const responses = ZAVA_LLM_RESPONSES[phase];
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
createSession: vi.fn().mockImplementation(async (_opts?: SessionOptions) => {
|
|
206
|
+
return {
|
|
207
|
+
send: vi.fn().mockImplementation(async function* () {
|
|
208
|
+
const text = responses[Math.min(responseIndex, responses.length - 1)];
|
|
209
|
+
responseIndex++;
|
|
210
|
+
yield { type: 'TextDelta' as const, text };
|
|
211
|
+
}),
|
|
212
|
+
} as unknown as ConversationSession;
|
|
213
|
+
}),
|
|
214
|
+
} as unknown as CopilotClient;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function createScriptedIO(phase: PhaseValue): LoopIO {
|
|
218
|
+
const inputs = [...ZAVA_USER_INPUTS[phase]];
|
|
219
|
+
let inputIndex = 0;
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
write: vi.fn(),
|
|
223
|
+
writeActivity: vi.fn(),
|
|
224
|
+
writeToolSummary: vi.fn(),
|
|
225
|
+
readInput: vi.fn().mockImplementation(async () => {
|
|
226
|
+
if (inputIndex < inputs.length) {
|
|
227
|
+
return inputs[inputIndex++];
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}),
|
|
231
|
+
showDecisionGate: vi.fn().mockResolvedValue({ choice: 'continue' }),
|
|
232
|
+
isJsonMode: false,
|
|
233
|
+
isTTY: false,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ── Test suite ───────────────────────────────────────────────────────────────
|
|
238
|
+
|
|
239
|
+
describe('Zava Industries E2E Simulation', () => {
|
|
240
|
+
let tmpDir: string;
|
|
241
|
+
|
|
242
|
+
beforeEach(async () => {
|
|
243
|
+
tmpDir = await mkdtemp(join(tmpdir(), 'sofia-zava-e2e-'));
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
afterEach(async () => {
|
|
247
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('completes a full 6-phase workshop and produces complete export', async () => {
|
|
251
|
+
let session: WorkshopSession = {
|
|
252
|
+
sessionId: 'zava-e2e-sim',
|
|
253
|
+
schemaVersion: '1.0.0',
|
|
254
|
+
createdAt: new Date().toISOString(),
|
|
255
|
+
updatedAt: new Date().toISOString(),
|
|
256
|
+
phase: 'Discover',
|
|
257
|
+
status: 'Active',
|
|
258
|
+
participants: [],
|
|
259
|
+
artifacts: { generatedFiles: [] },
|
|
260
|
+
turns: [],
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const phases = getPhaseOrder(); // Discover, Ideate, Design, Select, Plan, Develop
|
|
264
|
+
|
|
265
|
+
for (const phase of phases) {
|
|
266
|
+
session.phase = phase;
|
|
267
|
+
|
|
268
|
+
// Create a client that returns scripted responses for this phase
|
|
269
|
+
const client = createScriptedClient(phase);
|
|
270
|
+
const io = createScriptedIO(phase);
|
|
271
|
+
|
|
272
|
+
// Create and preload the handler
|
|
273
|
+
const handler = createPhaseHandler(phase);
|
|
274
|
+
await handler._preload();
|
|
275
|
+
|
|
276
|
+
const initialMessage = handler.getInitialMessage?.(session);
|
|
277
|
+
|
|
278
|
+
const loop = new ConversationLoop({
|
|
279
|
+
client,
|
|
280
|
+
io,
|
|
281
|
+
session,
|
|
282
|
+
phaseHandler: handler,
|
|
283
|
+
initialMessage,
|
|
284
|
+
onSessionUpdate: async (updated) => {
|
|
285
|
+
session = updated;
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
session = await loop.run();
|
|
290
|
+
session.updatedAt = new Date().toISOString();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ── Verify structured data extraction ──────────────────────────────
|
|
294
|
+
|
|
295
|
+
// Discover phase
|
|
296
|
+
expect(session.businessContext).toBeDefined();
|
|
297
|
+
expect(session.businessContext!.businessDescription).toContain('Zava Industries');
|
|
298
|
+
expect(session.businessContext!.challenges.length).toBeGreaterThan(0);
|
|
299
|
+
expect(session.workflow).toBeDefined();
|
|
300
|
+
expect(session.workflow!.activities.length).toBeGreaterThanOrEqual(6);
|
|
301
|
+
expect(session.workflow!.edges.length).toBeGreaterThan(0);
|
|
302
|
+
|
|
303
|
+
// Ideate phase
|
|
304
|
+
expect(session.ideas).toBeDefined();
|
|
305
|
+
expect(session.ideas!.length).toBeGreaterThanOrEqual(3);
|
|
306
|
+
expect(session.ideas!.some((i) => i.title.includes('TrendLens'))).toBe(true);
|
|
307
|
+
expect(session.ideas!.some((i) => i.title.includes('TrendPulse'))).toBe(true);
|
|
308
|
+
|
|
309
|
+
// Design phase
|
|
310
|
+
expect(session.evaluation).toBeDefined();
|
|
311
|
+
expect(session.evaluation!.method).toBe('feasibility-value-matrix');
|
|
312
|
+
expect(session.evaluation!.ideas.length).toBeGreaterThanOrEqual(3);
|
|
313
|
+
|
|
314
|
+
// Select phase
|
|
315
|
+
expect(session.selection).toBeDefined();
|
|
316
|
+
expect(session.selection!.ideaId).toBe('idea-2');
|
|
317
|
+
expect(session.selection!.confirmedByUser).toBe(true);
|
|
318
|
+
|
|
319
|
+
// Plan phase
|
|
320
|
+
expect(session.plan).toBeDefined();
|
|
321
|
+
expect(session.plan!.milestones.length).toBeGreaterThanOrEqual(3);
|
|
322
|
+
expect(session.plan!.architectureNotes).toContain('Azure');
|
|
323
|
+
|
|
324
|
+
// Develop phase
|
|
325
|
+
expect(session.poc).toBeDefined();
|
|
326
|
+
expect(session.poc!.repoSource).toBe('local');
|
|
327
|
+
expect(session.poc!.techStack).toBeDefined();
|
|
328
|
+
expect(session.poc!.techStack!.language).toBe('TypeScript');
|
|
329
|
+
|
|
330
|
+
// ── Verify conversation turns captured ──────────────────────────────
|
|
331
|
+
|
|
332
|
+
expect(session.turns).toBeDefined();
|
|
333
|
+
expect(session.turns!.length).toBeGreaterThan(0);
|
|
334
|
+
|
|
335
|
+
for (const phase of phases) {
|
|
336
|
+
const phaseTurns = session.turns!.filter((t) => t.phase === phase);
|
|
337
|
+
expect(phaseTurns.length).toBeGreaterThan(0);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// ── Verify context summarization works ──────────────────────────────
|
|
341
|
+
|
|
342
|
+
const ctx = buildSummarizedContext(session);
|
|
343
|
+
expect(ctx.businessSummary).toContain('Zava');
|
|
344
|
+
expect(ctx.ideaSummaries).toBeDefined();
|
|
345
|
+
expect(ctx.evaluationSummary).toBeDefined();
|
|
346
|
+
expect(ctx.selectionSummary).toContain('idea-2');
|
|
347
|
+
expect(ctx.planMilestones).toBeDefined();
|
|
348
|
+
|
|
349
|
+
const rendered = renderSummarizedContext(ctx);
|
|
350
|
+
expect(rendered).toContain('Prior Phase Context');
|
|
351
|
+
expect(rendered).toContain('Zava');
|
|
352
|
+
|
|
353
|
+
// ── Export and verify all 6 phase files generated ───────────────────
|
|
354
|
+
|
|
355
|
+
await exportSession(session, tmpDir);
|
|
356
|
+
const files = await readdir(tmpDir);
|
|
357
|
+
|
|
358
|
+
expect(files).toContain('discover.md');
|
|
359
|
+
expect(files).toContain('ideate.md');
|
|
360
|
+
expect(files).toContain('design.md');
|
|
361
|
+
expect(files).toContain('select.md');
|
|
362
|
+
expect(files).toContain('plan.md');
|
|
363
|
+
expect(files).toContain('develop.md');
|
|
364
|
+
expect(files).toContain('summary.json');
|
|
365
|
+
|
|
366
|
+
// Verify summary.json
|
|
367
|
+
const summaryRaw = await readFile(join(tmpDir, 'summary.json'), 'utf-8');
|
|
368
|
+
const summary = JSON.parse(summaryRaw);
|
|
369
|
+
expect(summary.files.filter((f: { path: string }) => f.path.endsWith('.md')).length).toBe(6);
|
|
370
|
+
expect(summary.highlights).toBeDefined();
|
|
371
|
+
expect(summary.highlights.length).toBeGreaterThan(0);
|
|
372
|
+
expect(summary.highlights.some((h: string) => h.includes('Zava'))).toBe(true);
|
|
373
|
+
|
|
374
|
+
// Verify export files have content
|
|
375
|
+
for (const phase of phases) {
|
|
376
|
+
const content = await readFile(join(tmpDir, `${phase.toLowerCase()}.md`), 'utf-8');
|
|
377
|
+
expect(content.length).toBeGreaterThan(50);
|
|
378
|
+
expect(content).toContain(`# ${phase} Phase`);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Verify ideate.md has both structured ideas and conversation
|
|
382
|
+
const ideateContent = await readFile(join(tmpDir, 'ideate.md'), 'utf-8');
|
|
383
|
+
expect(ideateContent).toContain('## Ideas');
|
|
384
|
+
expect(ideateContent).toContain('TrendLens');
|
|
385
|
+
expect(ideateContent).toContain('## Conversation');
|
|
386
|
+
|
|
387
|
+
// Verify design.md has evaluation data
|
|
388
|
+
const designContent = await readFile(join(tmpDir, 'design.md'), 'utf-8');
|
|
389
|
+
expect(designContent).toContain('## Evaluation');
|
|
390
|
+
expect(designContent).toContain('feasibility-value-matrix');
|
|
391
|
+
}, 30000); // 30 second timeout
|
|
392
|
+
|
|
393
|
+
it('phase boundary instruction is injected into system prompts', async () => {
|
|
394
|
+
const session: WorkshopSession = {
|
|
395
|
+
sessionId: 'boundary-test',
|
|
396
|
+
schemaVersion: '1.0.0',
|
|
397
|
+
createdAt: new Date().toISOString(),
|
|
398
|
+
updatedAt: new Date().toISOString(),
|
|
399
|
+
phase: 'Ideate',
|
|
400
|
+
status: 'Active',
|
|
401
|
+
participants: [],
|
|
402
|
+
artifacts: { generatedFiles: [] },
|
|
403
|
+
turns: [],
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
const capturedPrompts: string[] = [];
|
|
407
|
+
const client: CopilotClient = {
|
|
408
|
+
createSession: vi.fn().mockImplementation(async (opts?: SessionOptions) => {
|
|
409
|
+
if (opts?.systemPrompt) capturedPrompts.push(opts.systemPrompt);
|
|
410
|
+
return {
|
|
411
|
+
send: vi.fn().mockImplementation(async function* () {
|
|
412
|
+
yield { type: 'TextDelta' as const, text: 'Response' };
|
|
413
|
+
}),
|
|
414
|
+
} as unknown as ConversationSession;
|
|
415
|
+
}),
|
|
416
|
+
} as unknown as CopilotClient;
|
|
417
|
+
|
|
418
|
+
const io: LoopIO = {
|
|
419
|
+
write: vi.fn(),
|
|
420
|
+
writeActivity: vi.fn(),
|
|
421
|
+
writeToolSummary: vi.fn(),
|
|
422
|
+
readInput: vi.fn().mockResolvedValue(null),
|
|
423
|
+
showDecisionGate: vi.fn().mockResolvedValue({ choice: 'continue' }),
|
|
424
|
+
isJsonMode: false,
|
|
425
|
+
isTTY: false,
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
const handler = createPhaseHandler('Ideate');
|
|
429
|
+
await handler._preload();
|
|
430
|
+
|
|
431
|
+
const loop = new ConversationLoop({
|
|
432
|
+
client,
|
|
433
|
+
io,
|
|
434
|
+
session,
|
|
435
|
+
phaseHandler: handler,
|
|
436
|
+
initialMessage: 'Start ideation.',
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
await loop.run();
|
|
440
|
+
|
|
441
|
+
// First captured prompt should be for the conversation (contains boundary)
|
|
442
|
+
expect(capturedPrompts[0]).toContain('You are in the Ideate phase');
|
|
443
|
+
expect(capturedPrompts[0]).toContain('Do NOT introduce or begin the next phase');
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
it('summarization fallback activates when inline extraction returns empty', async () => {
|
|
447
|
+
const session: WorkshopSession = {
|
|
448
|
+
sessionId: 'summarize-fallback-test',
|
|
449
|
+
schemaVersion: '1.0.0',
|
|
450
|
+
createdAt: new Date().toISOString(),
|
|
451
|
+
updatedAt: new Date().toISOString(),
|
|
452
|
+
phase: 'Ideate',
|
|
453
|
+
status: 'Active',
|
|
454
|
+
participants: [],
|
|
455
|
+
artifacts: { generatedFiles: [] },
|
|
456
|
+
turns: [],
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
let callCount = 0;
|
|
460
|
+
const client: CopilotClient = {
|
|
461
|
+
createSession: vi.fn().mockImplementation(async () => ({
|
|
462
|
+
send: vi.fn().mockImplementation(async function* () {
|
|
463
|
+
callCount++;
|
|
464
|
+
if (callCount <= 2) {
|
|
465
|
+
// Main conversation — no JSON blocks (extraction will fail)
|
|
466
|
+
yield { type: 'TextDelta' as const, text: 'Here are some creative ideas for your fashion business.' };
|
|
467
|
+
} else {
|
|
468
|
+
// Summarization call — returns proper JSON
|
|
469
|
+
yield {
|
|
470
|
+
type: 'TextDelta' as const,
|
|
471
|
+
text: '```json\n[{"id":"idea-1","title":"TrendLens","description":"Visual AI","workflowStepIds":["s1"]}]\n```',
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
}),
|
|
475
|
+
})),
|
|
476
|
+
} as unknown as CopilotClient;
|
|
477
|
+
|
|
478
|
+
const io: LoopIO = {
|
|
479
|
+
write: vi.fn(),
|
|
480
|
+
writeActivity: vi.fn(),
|
|
481
|
+
writeToolSummary: vi.fn(),
|
|
482
|
+
readInput: vi.fn()
|
|
483
|
+
.mockResolvedValueOnce('brainstorm ideas')
|
|
484
|
+
.mockResolvedValue(null),
|
|
485
|
+
showDecisionGate: vi.fn().mockResolvedValue({ choice: 'continue' }),
|
|
486
|
+
isJsonMode: false,
|
|
487
|
+
isTTY: false,
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
const handler = createPhaseHandler('Ideate');
|
|
491
|
+
await handler._preload();
|
|
492
|
+
|
|
493
|
+
const loop = new ConversationLoop({
|
|
494
|
+
client,
|
|
495
|
+
io,
|
|
496
|
+
session,
|
|
497
|
+
phaseHandler: handler,
|
|
498
|
+
initialMessage: 'Start ideation.',
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
const result = await loop.run();
|
|
502
|
+
|
|
503
|
+
// Summarization should have been invoked (3+ createSession calls)
|
|
504
|
+
expect(callCount).toBeGreaterThanOrEqual(3);
|
|
505
|
+
|
|
506
|
+
// Ideas should be populated via summarization fallback
|
|
507
|
+
expect(result.ideas).toBeDefined();
|
|
508
|
+
expect(result.ideas!.length).toBeGreaterThanOrEqual(1);
|
|
509
|
+
expect(result.ideas![0].title).toBe('TrendLens');
|
|
510
|
+
});
|
|
511
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sessionId": "fixture-session-001",
|
|
3
|
+
"schemaVersion": "1.0.0",
|
|
4
|
+
"createdAt": "2026-01-15T09:00:00Z",
|
|
5
|
+
"updatedAt": "2026-01-15T11:30:00Z",
|
|
6
|
+
"name": "ACME AI Delivery Tracker Workshop",
|
|
7
|
+
"phase": "Develop",
|
|
8
|
+
"status": "Active",
|
|
9
|
+
"participants": [
|
|
10
|
+
{ "id": "p1", "displayName": "Alice Facilitator", "role": "Facilitator" },
|
|
11
|
+
{ "id": "p2", "displayName": "Bob Customer", "role": "Attendee" }
|
|
12
|
+
],
|
|
13
|
+
"businessContext": {
|
|
14
|
+
"businessDescription": "ACME Logistics Corp provides last-mile delivery services for e-commerce.",
|
|
15
|
+
"challenges": [
|
|
16
|
+
"Delivery delays due to poor route optimization",
|
|
17
|
+
"Customer satisfaction dropping due to lack of real-time tracking",
|
|
18
|
+
"High fuel costs from inefficient routing"
|
|
19
|
+
],
|
|
20
|
+
"constraints": ["Must integrate with existing SAP ERP system", "GDPR compliance required"],
|
|
21
|
+
"successMetrics": [
|
|
22
|
+
{ "name": "On-time delivery rate", "value": "95", "unit": "%" },
|
|
23
|
+
{ "name": "Customer satisfaction score", "value": "4.5", "unit": "/5" }
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
"topic": {
|
|
27
|
+
"topicArea": "Last-mile delivery optimization",
|
|
28
|
+
"scopeNotes": "Focus on AI-powered route optimization and real-time tracking"
|
|
29
|
+
},
|
|
30
|
+
"workflow": {
|
|
31
|
+
"activities": [
|
|
32
|
+
{ "id": "a1", "name": "Order Received" },
|
|
33
|
+
{ "id": "a2", "name": "Route Planning" },
|
|
34
|
+
{ "id": "a3", "name": "Delivery Execution" },
|
|
35
|
+
{ "id": "a4", "name": "Proof of Delivery" }
|
|
36
|
+
],
|
|
37
|
+
"edges": [
|
|
38
|
+
{ "fromStepId": "a1", "toStepId": "a2" },
|
|
39
|
+
{ "fromStepId": "a2", "toStepId": "a3" },
|
|
40
|
+
{ "fromStepId": "a3", "toStepId": "a4" }
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"ideas": [
|
|
44
|
+
{
|
|
45
|
+
"id": "idea-1",
|
|
46
|
+
"title": "AI-Powered Route Optimizer",
|
|
47
|
+
"description": "Use machine learning to optimize delivery routes in real-time based on traffic, weather, and package priority.",
|
|
48
|
+
"workflowStepIds": ["a2", "a3"],
|
|
49
|
+
"aspirationalScope": "Reduce delivery times by 20% and fuel costs by 15%",
|
|
50
|
+
"assumptions": ["Traffic data available via API", "Driver apps can receive updated routes"]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "idea-2",
|
|
54
|
+
"title": "Predictive Delivery Window",
|
|
55
|
+
"description": "Predict accurate 1-hour delivery windows for customers using AI.",
|
|
56
|
+
"workflowStepIds": ["a3"],
|
|
57
|
+
"aspirationalScope": "95% accuracy on delivery time predictions"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"evaluation": {
|
|
61
|
+
"ideas": [
|
|
62
|
+
{
|
|
63
|
+
"ideaId": "idea-1",
|
|
64
|
+
"feasibility": 8,
|
|
65
|
+
"value": 9,
|
|
66
|
+
"risks": ["Data quality dependency", "Driver adoption"],
|
|
67
|
+
"dataNeeded": ["Historical delivery data", "Traffic API access"],
|
|
68
|
+
"humanValue": ["Reduces driver stress", "Improves work-life balance"],
|
|
69
|
+
"kpisInfluenced": ["On-time delivery rate", "Fuel costs"]
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"ideaId": "idea-2",
|
|
73
|
+
"feasibility": 7,
|
|
74
|
+
"value": 8,
|
|
75
|
+
"risks": ["Last-mile unpredictability"],
|
|
76
|
+
"dataNeeded": ["Historical delivery times", "Traffic patterns"],
|
|
77
|
+
"humanValue": ["Customer peace of mind"],
|
|
78
|
+
"kpisInfluenced": ["Customer satisfaction score"]
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"method": "feasibility-value-matrix"
|
|
82
|
+
},
|
|
83
|
+
"selection": {
|
|
84
|
+
"ideaId": "idea-1",
|
|
85
|
+
"selectionRationale": "Highest feasibility-value score. Directly addresses the primary business challenge of route inefficiency and has clear ROI through fuel cost reduction.",
|
|
86
|
+
"confirmedByUser": true,
|
|
87
|
+
"confirmedAt": "2026-01-15T11:00:00Z"
|
|
88
|
+
},
|
|
89
|
+
"plan": {
|
|
90
|
+
"milestones": [
|
|
91
|
+
{
|
|
92
|
+
"id": "m1",
|
|
93
|
+
"title": "Data Pipeline Setup",
|
|
94
|
+
"items": [
|
|
95
|
+
"Ingest historical delivery data from CSV",
|
|
96
|
+
"Connect to traffic API (mocked for PoC)",
|
|
97
|
+
"Data normalization and feature engineering"
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"id": "m2",
|
|
102
|
+
"title": "Route Optimization Model",
|
|
103
|
+
"items": [
|
|
104
|
+
"Implement nearest-neighbor heuristic baseline",
|
|
105
|
+
"Add traffic-weighted distance calculation",
|
|
106
|
+
"Expose optimization as TypeScript function"
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "m3",
|
|
111
|
+
"title": "REST API & Demo",
|
|
112
|
+
"items": [
|
|
113
|
+
"Simple Express server exposing /optimize-route endpoint",
|
|
114
|
+
"Sample data for 5 delivery stops",
|
|
115
|
+
"README with curl examples"
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
"architectureNotes": "Node.js 20 + TypeScript. Simple in-process route optimizer (no external ML service for PoC). Express for HTTP layer. Vitest for testing. Dependencies: express, typescript, vitest.",
|
|
120
|
+
"dependencies": ["express", "typescript", "vitest", "@types/express", "@types/node"]
|
|
121
|
+
},
|
|
122
|
+
"artifacts": {
|
|
123
|
+
"generatedFiles": []
|
|
124
|
+
},
|
|
125
|
+
"turns": [
|
|
126
|
+
{
|
|
127
|
+
"phase": "Discover",
|
|
128
|
+
"sequence": 1,
|
|
129
|
+
"role": "user",
|
|
130
|
+
"content": "We are ACME Logistics and we struggle with delivery route optimization.",
|
|
131
|
+
"timestamp": "2026-01-15T09:05:00Z"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"phase": "Plan",
|
|
135
|
+
"sequence": 10,
|
|
136
|
+
"role": "assistant",
|
|
137
|
+
"content": "Here is the implementation plan for the AI-Powered Route Optimizer PoC.",
|
|
138
|
+
"timestamp": "2026-01-15T11:25:00Z"
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
}
|