@contractspec/bundle.workspace 1.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/_virtual/rolldown_runtime.js +36 -0
- package/dist/adapters/ai.d.ts +12 -0
- package/dist/adapters/ai.d.ts.map +1 -0
- package/dist/adapters/ai.js +83 -0
- package/dist/adapters/ai.js.map +1 -0
- package/dist/adapters/factory.d.ts +29 -0
- package/dist/adapters/factory.d.ts.map +1 -0
- package/dist/adapters/factory.js +37 -0
- package/dist/adapters/factory.js.map +1 -0
- package/dist/adapters/fs.d.ts +11 -0
- package/dist/adapters/fs.d.ts.map +1 -0
- package/dist/adapters/fs.js +131 -0
- package/dist/adapters/fs.js.map +1 -0
- package/dist/adapters/git.d.ts +11 -0
- package/dist/adapters/git.d.ts.map +1 -0
- package/dist/adapters/git.js +55 -0
- package/dist/adapters/git.js.map +1 -0
- package/dist/adapters/index.d.ts +7 -0
- package/dist/adapters/index.js +7 -0
- package/dist/adapters/logger.d.ts +18 -0
- package/dist/adapters/logger.d.ts.map +1 -0
- package/dist/adapters/logger.js +81 -0
- package/dist/adapters/logger.js.map +1 -0
- package/dist/adapters/watcher.d.ts +11 -0
- package/dist/adapters/watcher.d.ts.map +1 -0
- package/dist/adapters/watcher.js +74 -0
- package/dist/adapters/watcher.js.map +1 -0
- package/dist/adapters/workspace.d.ts +148 -0
- package/dist/adapters/workspace.d.ts.map +1 -0
- package/dist/adapters/workspace.js +275 -0
- package/dist/adapters/workspace.js.map +1 -0
- package/dist/ai/agents/claude-code-agent.d.ts +22 -0
- package/dist/ai/agents/claude-code-agent.d.ts.map +1 -0
- package/dist/ai/agents/claude-code-agent.js +182 -0
- package/dist/ai/agents/claude-code-agent.js.map +1 -0
- package/dist/ai/agents/cursor-agent.d.ts +68 -0
- package/dist/ai/agents/cursor-agent.d.ts.map +1 -0
- package/dist/ai/agents/cursor-agent.js +436 -0
- package/dist/ai/agents/cursor-agent.js.map +1 -0
- package/dist/ai/agents/index.js +5 -0
- package/dist/ai/agents/openai-codex-agent.d.ts +22 -0
- package/dist/ai/agents/openai-codex-agent.d.ts.map +1 -0
- package/dist/ai/agents/openai-codex-agent.js +167 -0
- package/dist/ai/agents/openai-codex-agent.js.map +1 -0
- package/dist/ai/agents/orchestrator.d.ts +50 -0
- package/dist/ai/agents/orchestrator.d.ts.map +1 -0
- package/dist/ai/agents/orchestrator.js +143 -0
- package/dist/ai/agents/orchestrator.js.map +1 -0
- package/dist/ai/agents/simple-agent.d.ts +17 -0
- package/dist/ai/agents/simple-agent.d.ts.map +1 -0
- package/dist/ai/agents/simple-agent.js +92 -0
- package/dist/ai/agents/simple-agent.js.map +1 -0
- package/dist/ai/agents/types.d.ts +36 -0
- package/dist/ai/agents/types.d.ts.map +1 -0
- package/dist/ai/client.d.ts +83 -0
- package/dist/ai/client.d.ts.map +1 -0
- package/dist/ai/client.js +163 -0
- package/dist/ai/client.js.map +1 -0
- package/dist/ai/index.d.ts +17 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +28 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/prompts/code-generation.d.ts +26 -0
- package/dist/ai/prompts/code-generation.d.ts.map +1 -0
- package/dist/ai/prompts/code-generation.js +143 -0
- package/dist/ai/prompts/code-generation.js.map +1 -0
- package/dist/ai/prompts/index.d.ts +10 -0
- package/dist/ai/prompts/index.d.ts.map +1 -0
- package/dist/ai/prompts/index.js +13 -0
- package/dist/ai/prompts/index.js.map +1 -0
- package/dist/ai/prompts/spec-creation.d.ts +29 -0
- package/dist/ai/prompts/spec-creation.d.ts.map +1 -0
- package/dist/ai/prompts/spec-creation.js +111 -0
- package/dist/ai/prompts/spec-creation.js.map +1 -0
- package/dist/ai/providers.d.ts +29 -0
- package/dist/ai/providers.d.ts.map +1 -0
- package/dist/ai/providers.js +39 -0
- package/dist/ai/providers.js.map +1 -0
- package/dist/formatters/index.d.ts +11 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +19 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/formatters/json.d.ts +89 -0
- package/dist/formatters/json.d.ts.map +1 -0
- package/dist/formatters/json.js +72 -0
- package/dist/formatters/json.js.map +1 -0
- package/dist/formatters/sarif.d.ts +101 -0
- package/dist/formatters/sarif.d.ts.map +1 -0
- package/dist/formatters/sarif.js +163 -0
- package/dist/formatters/sarif.js.map +1 -0
- package/dist/formatters/text.d.ts +35 -0
- package/dist/formatters/text.d.ts.map +1 -0
- package/dist/formatters/text.js +209 -0
- package/dist/formatters/text.js.map +1 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +204 -0
- package/dist/index.js.map +1 -0
- package/dist/ports/ai.d.ts +59 -0
- package/dist/ports/ai.d.ts.map +1 -0
- package/dist/ports/fs.d.ts +81 -0
- package/dist/ports/fs.d.ts.map +1 -0
- package/dist/ports/git.d.ts +33 -0
- package/dist/ports/git.d.ts.map +1 -0
- package/dist/ports/index.d.ts +5 -0
- package/dist/ports/logger.d.ts +88 -0
- package/dist/ports/logger.d.ts.map +1 -0
- package/dist/ports/watcher.d.ts +52 -0
- package/dist/ports/watcher.d.ts.map +1 -0
- package/dist/services/agent-guide/adapters/claude-code.d.ts +35 -0
- package/dist/services/agent-guide/adapters/claude-code.d.ts.map +1 -0
- package/dist/services/agent-guide/adapters/claude-code.js +144 -0
- package/dist/services/agent-guide/adapters/claude-code.js.map +1 -0
- package/dist/services/agent-guide/adapters/cursor-cli.d.ts +39 -0
- package/dist/services/agent-guide/adapters/cursor-cli.d.ts.map +1 -0
- package/dist/services/agent-guide/adapters/cursor-cli.js +135 -0
- package/dist/services/agent-guide/adapters/cursor-cli.js.map +1 -0
- package/dist/services/agent-guide/adapters/generic-mcp.d.ts +53 -0
- package/dist/services/agent-guide/adapters/generic-mcp.d.ts.map +1 -0
- package/dist/services/agent-guide/adapters/generic-mcp.js +159 -0
- package/dist/services/agent-guide/adapters/generic-mcp.js.map +1 -0
- package/dist/services/agent-guide/adapters/index.d.ts +23 -0
- package/dist/services/agent-guide/adapters/index.d.ts.map +1 -0
- package/dist/services/agent-guide/adapters/index.js +31 -0
- package/dist/services/agent-guide/adapters/index.js.map +1 -0
- package/dist/services/agent-guide/agent-guide-service.d.ts +56 -0
- package/dist/services/agent-guide/agent-guide-service.d.ts.map +1 -0
- package/dist/services/agent-guide/agent-guide-service.js +147 -0
- package/dist/services/agent-guide/agent-guide-service.js.map +1 -0
- package/dist/services/agent-guide/index.d.ts +6 -0
- package/dist/services/agent-guide/index.js +5 -0
- package/dist/services/agent-guide/types.d.ts +58 -0
- package/dist/services/agent-guide/types.d.ts.map +1 -0
- package/dist/services/build.d.ts +59 -0
- package/dist/services/build.d.ts.map +1 -0
- package/dist/services/build.js +140 -0
- package/dist/services/build.js.map +1 -0
- package/dist/services/ci-check/ci-check-service.d.ts +16 -0
- package/dist/services/ci-check/ci-check-service.d.ts.map +1 -0
- package/dist/services/ci-check/ci-check-service.js +392 -0
- package/dist/services/ci-check/ci-check-service.js.map +1 -0
- package/dist/services/ci-check/index.d.ts +2 -0
- package/dist/services/ci-check/index.js +2 -0
- package/dist/services/ci-check/types.d.ts +143 -0
- package/dist/services/ci-check/types.d.ts.map +1 -0
- package/dist/services/ci-check/types.js +29 -0
- package/dist/services/ci-check/types.js.map +1 -0
- package/dist/services/clean.d.ts +41 -0
- package/dist/services/clean.d.ts.map +1 -0
- package/dist/services/clean.js +72 -0
- package/dist/services/clean.js.map +1 -0
- package/dist/services/config.d.ts +26 -0
- package/dist/services/config.d.ts.map +1 -0
- package/dist/services/config.js +77 -0
- package/dist/services/config.js.map +1 -0
- package/dist/services/deps.d.ts +53 -0
- package/dist/services/deps.d.ts.map +1 -0
- package/dist/services/deps.js +62 -0
- package/dist/services/deps.js.map +1 -0
- package/dist/services/diff.d.ts +34 -0
- package/dist/services/diff.d.ts.map +1 -0
- package/dist/services/diff.js +34 -0
- package/dist/services/diff.js.map +1 -0
- package/dist/services/doctor/checks/ai.js +119 -0
- package/dist/services/doctor/checks/ai.js.map +1 -0
- package/dist/services/doctor/checks/cli.js +147 -0
- package/dist/services/doctor/checks/cli.js.map +1 -0
- package/dist/services/doctor/checks/config.js +171 -0
- package/dist/services/doctor/checks/config.js.map +1 -0
- package/dist/services/doctor/checks/deps.js +247 -0
- package/dist/services/doctor/checks/deps.js.map +1 -0
- package/dist/services/doctor/checks/index.js +6 -0
- package/dist/services/doctor/checks/mcp.js +145 -0
- package/dist/services/doctor/checks/mcp.js.map +1 -0
- package/dist/services/doctor/checks/workspace.js +244 -0
- package/dist/services/doctor/checks/workspace.js.map +1 -0
- package/dist/services/doctor/doctor-service.d.ts +24 -0
- package/dist/services/doctor/doctor-service.d.ts.map +1 -0
- package/dist/services/doctor/doctor-service.js +116 -0
- package/dist/services/doctor/doctor-service.js.map +1 -0
- package/dist/services/doctor/index.d.ts +2 -0
- package/dist/services/doctor/index.js +2 -0
- package/dist/services/doctor/types.d.ts +118 -0
- package/dist/services/doctor/types.d.ts.map +1 -0
- package/dist/services/doctor/types.js +27 -0
- package/dist/services/doctor/types.js.map +1 -0
- package/dist/services/impact/formatters.d.ts +27 -0
- package/dist/services/impact/formatters.d.ts.map +1 -0
- package/dist/services/impact/formatters.js +111 -0
- package/dist/services/impact/formatters.js.map +1 -0
- package/dist/services/impact/impact-detection-service.d.ts +22 -0
- package/dist/services/impact/impact-detection-service.d.ts.map +1 -0
- package/dist/services/impact/impact-detection-service.js +96 -0
- package/dist/services/impact/impact-detection-service.js.map +1 -0
- package/dist/services/impact/index.d.ts +11 -0
- package/dist/services/impact/index.d.ts.map +1 -0
- package/dist/services/impact/index.js +16 -0
- package/dist/services/impact/index.js.map +1 -0
- package/dist/services/impact/types.d.ts +58 -0
- package/dist/services/impact/types.d.ts.map +1 -0
- package/dist/services/implementation/discovery.d.ts +30 -0
- package/dist/services/implementation/discovery.d.ts.map +1 -0
- package/dist/services/implementation/discovery.js +144 -0
- package/dist/services/implementation/discovery.js.map +1 -0
- package/dist/services/implementation/index.d.ts +3 -0
- package/dist/services/implementation/index.js +2 -0
- package/dist/services/implementation/resolver.d.ts +44 -0
- package/dist/services/implementation/resolver.d.ts.map +1 -0
- package/dist/services/implementation/resolver.js +224 -0
- package/dist/services/implementation/resolver.js.map +1 -0
- package/dist/services/implementation/types.d.ts +79 -0
- package/dist/services/implementation/types.d.ts.map +1 -0
- package/dist/services/index.d.ts +60 -0
- package/dist/services/index.js +57 -0
- package/dist/services/integrity-diagram.d.ts +36 -0
- package/dist/services/integrity-diagram.d.ts.map +1 -0
- package/dist/services/integrity-diagram.js +275 -0
- package/dist/services/integrity-diagram.js.map +1 -0
- package/dist/services/integrity.d.ts +134 -0
- package/dist/services/integrity.d.ts.map +1 -0
- package/dist/services/integrity.js +272 -0
- package/dist/services/integrity.js.map +1 -0
- package/dist/services/list.d.ts +31 -0
- package/dist/services/list.d.ts.map +1 -0
- package/dist/services/list.js +36 -0
- package/dist/services/list.js.map +1 -0
- package/dist/services/openapi/export-service.d.ts +53 -0
- package/dist/services/openapi/export-service.d.ts.map +1 -0
- package/dist/services/openapi/export-service.js +50 -0
- package/dist/services/openapi/export-service.js.map +1 -0
- package/dist/services/openapi/import-service.d.ts +17 -0
- package/dist/services/openapi/import-service.d.ts.map +1 -0
- package/dist/services/openapi/import-service.js +74 -0
- package/dist/services/openapi/import-service.js.map +1 -0
- package/dist/services/openapi/index.d.ts +5 -0
- package/dist/services/openapi/index.js +4 -0
- package/dist/services/openapi/sync-service.d.ts +17 -0
- package/dist/services/openapi/sync-service.d.ts.map +1 -0
- package/dist/services/openapi/sync-service.js +120 -0
- package/dist/services/openapi/sync-service.js.map +1 -0
- package/dist/services/openapi/types.d.ts +162 -0
- package/dist/services/openapi/types.d.ts.map +1 -0
- package/dist/services/openapi/validate-service.d.ts +16 -0
- package/dist/services/openapi/validate-service.d.ts.map +1 -0
- package/dist/services/openapi/validate-service.js +130 -0
- package/dist/services/openapi/validate-service.js.map +1 -0
- package/dist/services/quickstart/dependencies.d.ts +31 -0
- package/dist/services/quickstart/dependencies.d.ts.map +1 -0
- package/dist/services/quickstart/dependencies.js +57 -0
- package/dist/services/quickstart/dependencies.js.map +1 -0
- package/dist/services/quickstart/index.js +2 -0
- package/dist/services/quickstart/quickstart-service.d.ts +20 -0
- package/dist/services/quickstart/quickstart-service.d.ts.map +1 -0
- package/dist/services/quickstart/quickstart-service.js +196 -0
- package/dist/services/quickstart/quickstart-service.js.map +1 -0
- package/dist/services/quickstart/types.d.ts +81 -0
- package/dist/services/quickstart/types.d.ts.map +1 -0
- package/dist/services/regenerator.d.ts +18 -0
- package/dist/services/regenerator.d.ts.map +1 -0
- package/dist/services/regenerator.js +23 -0
- package/dist/services/regenerator.js.map +1 -0
- package/dist/services/registry.d.ts +53 -0
- package/dist/services/registry.d.ts.map +1 -0
- package/dist/services/registry.js +74 -0
- package/dist/services/registry.js.map +1 -0
- package/dist/services/setup/config-generators.d.ts +42 -0
- package/dist/services/setup/config-generators.d.ts.map +1 -0
- package/dist/services/setup/config-generators.js +238 -0
- package/dist/services/setup/config-generators.js.map +1 -0
- package/dist/services/setup/file-merger.d.ts +27 -0
- package/dist/services/setup/file-merger.d.ts.map +1 -0
- package/dist/services/setup/file-merger.js +61 -0
- package/dist/services/setup/file-merger.js.map +1 -0
- package/dist/services/setup/index.js +4 -0
- package/dist/services/setup/setup-service.d.ts +12 -0
- package/dist/services/setup/setup-service.d.ts.map +1 -0
- package/dist/services/setup/setup-service.js +96 -0
- package/dist/services/setup/setup-service.js.map +1 -0
- package/dist/services/setup/targets/agents-md.js +47 -0
- package/dist/services/setup/targets/agents-md.js.map +1 -0
- package/dist/services/setup/targets/cli-config.js +60 -0
- package/dist/services/setup/targets/cli-config.js.map +1 -0
- package/dist/services/setup/targets/cursor-rules.js +48 -0
- package/dist/services/setup/targets/cursor-rules.js.map +1 -0
- package/dist/services/setup/targets/mcp-claude.js +60 -0
- package/dist/services/setup/targets/mcp-claude.js.map +1 -0
- package/dist/services/setup/targets/mcp-cursor.js +59 -0
- package/dist/services/setup/targets/mcp-cursor.js.map +1 -0
- package/dist/services/setup/targets/vscode-settings.js +63 -0
- package/dist/services/setup/targets/vscode-settings.js.map +1 -0
- package/dist/services/setup/types.d.ts +85 -0
- package/dist/services/setup/types.d.ts.map +1 -0
- package/dist/services/setup/types.js +27 -0
- package/dist/services/setup/types.js.map +1 -0
- package/dist/services/sync.d.ts +41 -0
- package/dist/services/sync.d.ts.map +1 -0
- package/dist/services/sync.js +63 -0
- package/dist/services/sync.js.map +1 -0
- package/dist/services/test.d.ts +15 -0
- package/dist/services/test.d.ts.map +1 -0
- package/dist/services/test.js +30 -0
- package/dist/services/test.js.map +1 -0
- package/dist/services/validate-implementation.d.ts +32 -0
- package/dist/services/validate-implementation.d.ts.map +1 -0
- package/dist/services/validate-implementation.js +64 -0
- package/dist/services/validate-implementation.js.map +1 -0
- package/dist/services/validate.d.ts +41 -0
- package/dist/services/validate.d.ts.map +1 -0
- package/dist/services/validate.js +48 -0
- package/dist/services/validate.js.map +1 -0
- package/dist/services/verification-cache/adapters/filesystem.d.ts +46 -0
- package/dist/services/verification-cache/adapters/filesystem.d.ts.map +1 -0
- package/dist/services/verification-cache/adapters/filesystem.js +120 -0
- package/dist/services/verification-cache/adapters/filesystem.js.map +1 -0
- package/dist/services/verification-cache/adapters/in-memory.d.ts +27 -0
- package/dist/services/verification-cache/adapters/in-memory.d.ts.map +1 -0
- package/dist/services/verification-cache/adapters/in-memory.js +46 -0
- package/dist/services/verification-cache/adapters/in-memory.js.map +1 -0
- package/dist/services/verification-cache/adapters/index.d.ts +3 -0
- package/dist/services/verification-cache/adapters/index.js +3 -0
- package/dist/services/verification-cache/adapters/workspace-state.d.ts +49 -0
- package/dist/services/verification-cache/adapters/workspace-state.d.ts.map +1 -0
- package/dist/services/verification-cache/adapters/workspace-state.js +91 -0
- package/dist/services/verification-cache/adapters/workspace-state.js.map +1 -0
- package/dist/services/verification-cache/cache-service.d.ts +70 -0
- package/dist/services/verification-cache/cache-service.d.ts.map +1 -0
- package/dist/services/verification-cache/cache-service.js +256 -0
- package/dist/services/verification-cache/cache-service.js.map +1 -0
- package/dist/services/verification-cache/index.d.ts +6 -0
- package/dist/services/verification-cache/index.js +6 -0
- package/dist/services/verification-cache/types.d.ts +124 -0
- package/dist/services/verification-cache/types.d.ts.map +1 -0
- package/dist/services/verification-cache/types.js +16 -0
- package/dist/services/verification-cache/types.js.map +1 -0
- package/dist/services/verify/ai-verifier.d.ts +25 -0
- package/dist/services/verify/ai-verifier.d.ts.map +1 -0
- package/dist/services/verify/ai-verifier.js +403 -0
- package/dist/services/verify/ai-verifier.js.map +1 -0
- package/dist/services/verify/behavior-verifier.d.ts +12 -0
- package/dist/services/verify/behavior-verifier.d.ts.map +1 -0
- package/dist/services/verify/behavior-verifier.js +186 -0
- package/dist/services/verify/behavior-verifier.js.map +1 -0
- package/dist/services/verify/index.d.ts +5 -0
- package/dist/services/verify/index.js +4 -0
- package/dist/services/verify/structure-verifier.d.ts +12 -0
- package/dist/services/verify/structure-verifier.d.ts.map +1 -0
- package/dist/services/verify/structure-verifier.js +196 -0
- package/dist/services/verify/structure-verifier.js.map +1 -0
- package/dist/services/verify/types.d.ts +137 -0
- package/dist/services/verify/types.d.ts.map +1 -0
- package/dist/services/verify/verify-service.d.ts +60 -0
- package/dist/services/verify/verify-service.d.ts.map +1 -0
- package/dist/services/verify/verify-service.js +204 -0
- package/dist/services/verify/verify-service.js.map +1 -0
- package/dist/services/watch.d.ts +25 -0
- package/dist/services/watch.d.ts.map +1 -0
- package/dist/services/watch.js +32 -0
- package/dist/services/watch.js.map +1 -0
- package/dist/services/workspace-info.d.ts +62 -0
- package/dist/services/workspace-info.d.ts.map +1 -0
- package/dist/services/workspace-info.js +103 -0
- package/dist/services/workspace-info.js.map +1 -0
- package/dist/templates/app-config.template.d.ts +7 -0
- package/dist/templates/app-config.template.d.ts.map +1 -0
- package/dist/templates/app-config.template.js +107 -0
- package/dist/templates/app-config.template.js.map +1 -0
- package/dist/templates/data-view.template.d.ts +7 -0
- package/dist/templates/data-view.template.d.ts.map +1 -0
- package/dist/templates/data-view.template.js +70 -0
- package/dist/templates/data-view.template.js.map +1 -0
- package/dist/templates/event.template.d.ts +11 -0
- package/dist/templates/event.template.d.ts.map +1 -0
- package/dist/templates/event.template.js +40 -0
- package/dist/templates/event.template.js.map +1 -0
- package/dist/templates/experiment.template.d.ts +7 -0
- package/dist/templates/experiment.template.d.ts.map +1 -0
- package/dist/templates/experiment.template.js +89 -0
- package/dist/templates/experiment.template.js.map +1 -0
- package/dist/templates/handler.template.d.ts +16 -0
- package/dist/templates/handler.template.d.ts.map +1 -0
- package/dist/templates/handler.template.js +100 -0
- package/dist/templates/handler.template.js.map +1 -0
- package/dist/templates/index.d.ts +21 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +37 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/integration.template.d.ts +7 -0
- package/dist/templates/integration.template.d.ts.map +1 -0
- package/dist/templates/integration.template.js +160 -0
- package/dist/templates/integration.template.js.map +1 -0
- package/dist/templates/knowledge.template.d.ts +7 -0
- package/dist/templates/knowledge.template.d.ts.map +1 -0
- package/dist/templates/knowledge.template.js +75 -0
- package/dist/templates/knowledge.template.js.map +1 -0
- package/dist/templates/migration.template.d.ts +7 -0
- package/dist/templates/migration.template.d.ts.map +1 -0
- package/dist/templates/migration.template.js +62 -0
- package/dist/templates/migration.template.js.map +1 -0
- package/dist/templates/operation.template.d.ts +11 -0
- package/dist/templates/operation.template.d.ts.map +1 -0
- package/dist/templates/operation.template.js +105 -0
- package/dist/templates/operation.template.js.map +1 -0
- package/dist/templates/presentation.template.d.ts +11 -0
- package/dist/templates/presentation.template.d.ts.map +1 -0
- package/dist/templates/presentation.template.js +80 -0
- package/dist/templates/presentation.template.js.map +1 -0
- package/dist/templates/telemetry.template.d.ts +7 -0
- package/dist/templates/telemetry.template.d.ts.map +1 -0
- package/dist/templates/telemetry.template.js +91 -0
- package/dist/templates/telemetry.template.js.map +1 -0
- package/dist/templates/workflow-runner.template.d.ts +16 -0
- package/dist/templates/workflow-runner.template.d.ts.map +1 -0
- package/dist/templates/workflow-runner.template.js +50 -0
- package/dist/templates/workflow-runner.template.js.map +1 -0
- package/dist/templates/workflow.template.d.ts +7 -0
- package/dist/templates/workflow.template.d.ts.map +1 -0
- package/dist/templates/workflow.template.js +69 -0
- package/dist/templates/workflow.template.js.map +1 -0
- package/dist/types/config.d.ts +34 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types.d.ts +324 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { FsAdapter } from "../ports/fs.js";
|
|
2
|
+
import { LoggerAdapter } from "../ports/logger.js";
|
|
3
|
+
import { SpecScanResult, WorkspaceConfig } from "@contractspec/module.workspace";
|
|
4
|
+
|
|
5
|
+
//#region src/services/build.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Build target types.
|
|
9
|
+
*/
|
|
10
|
+
type BuildTarget = 'handler' | 'component' | 'test';
|
|
11
|
+
/**
|
|
12
|
+
* Options for building from a spec.
|
|
13
|
+
*/
|
|
14
|
+
interface BuildSpecOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Which artifacts to generate.
|
|
17
|
+
*/
|
|
18
|
+
targets?: BuildTarget[];
|
|
19
|
+
/**
|
|
20
|
+
* Override output directory.
|
|
21
|
+
*/
|
|
22
|
+
outputDir?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Whether to overwrite existing files.
|
|
25
|
+
*/
|
|
26
|
+
overwrite?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Skip writing files (dry run).
|
|
29
|
+
*/
|
|
30
|
+
dryRun?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Result of a single build target.
|
|
34
|
+
*/
|
|
35
|
+
interface BuildTargetResult {
|
|
36
|
+
target: BuildTarget;
|
|
37
|
+
outputPath: string;
|
|
38
|
+
success: boolean;
|
|
39
|
+
skipped?: boolean;
|
|
40
|
+
error?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Result of building from a spec.
|
|
44
|
+
*/
|
|
45
|
+
interface BuildSpecResult {
|
|
46
|
+
specPath: string;
|
|
47
|
+
specInfo: SpecScanResult;
|
|
48
|
+
results: BuildTargetResult[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build implementation files from a spec.
|
|
52
|
+
*/
|
|
53
|
+
declare function buildSpec(specPath: string, adapters: {
|
|
54
|
+
fs: FsAdapter;
|
|
55
|
+
logger: LoggerAdapter;
|
|
56
|
+
}, config: WorkspaceConfig, options?: BuildSpecOptions): Promise<BuildSpecResult>;
|
|
57
|
+
//#endregion
|
|
58
|
+
export { BuildSpecOptions, BuildSpecResult, BuildTarget, BuildTargetResult, buildSpec };
|
|
59
|
+
//# sourceMappingURL=build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","names":[],"sources":["../../src/services/build.ts"],"sourcesContent":[],"mappings":";;;;;;AAwEA;;;AAGU,KArDE,WAAA,GAqDF,SAAA,GAAA,WAAA,GAAA,MAAA;;;;AAEA,UAlDO,gBAAA,CAkDP;;;;YA9CE;;;;;;;;;;;;;;;;;UAqBK,iBAAA;UACP;;;;;;;;;UAUO,eAAA;;YAEL;WACD;;;;;iBAMW,SAAA;MAEJ;UAAmB;WAC3B,2BACC,mBACR,QAAQ"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { generateComponentTemplate, generateHandlerTemplate, generateTestTemplate, inferSpecTypeFromFilePath, scanSpecSource } from "@contractspec/module.workspace";
|
|
2
|
+
|
|
3
|
+
//#region src/services/build.ts
|
|
4
|
+
/**
|
|
5
|
+
* Build/scaffold service for generating implementation files from specs.
|
|
6
|
+
*
|
|
7
|
+
* Uses templates from @contractspec/module.workspace to generate
|
|
8
|
+
* handler, component, and test skeletons without requiring AI.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Build implementation files from a spec.
|
|
12
|
+
*/
|
|
13
|
+
async function buildSpec(specPath, adapters, config, options = {}) {
|
|
14
|
+
const { fs, logger } = adapters;
|
|
15
|
+
const { targets = detectDefaultTargets(specPath), outputDir = config.outputDir, overwrite = false, dryRun = false } = options;
|
|
16
|
+
const specCode = await fs.readFile(specPath);
|
|
17
|
+
const specInfo = scanSpecSource(specCode, specPath);
|
|
18
|
+
const specType = inferSpecTypeFromFilePath(specPath);
|
|
19
|
+
logger.info(`Building from spec: ${specPath}`, { specType });
|
|
20
|
+
const results = [];
|
|
21
|
+
for (const target of targets) try {
|
|
22
|
+
const result = await buildTarget(target, specPath, specCode, specInfo, specType, {
|
|
23
|
+
fs,
|
|
24
|
+
logger
|
|
25
|
+
}, outputDir, overwrite, dryRun);
|
|
26
|
+
results.push(result);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
results.push({
|
|
29
|
+
target,
|
|
30
|
+
outputPath: "",
|
|
31
|
+
success: false,
|
|
32
|
+
error: error instanceof Error ? error.message : String(error)
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
specPath,
|
|
37
|
+
specInfo,
|
|
38
|
+
results
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Build a single target from a spec.
|
|
43
|
+
*/
|
|
44
|
+
async function buildTarget(target, specPath, _specCode, specInfo, specType, adapters, outputDir, overwrite, dryRun) {
|
|
45
|
+
const { fs, logger } = adapters;
|
|
46
|
+
let code;
|
|
47
|
+
let outputPath;
|
|
48
|
+
switch (target) {
|
|
49
|
+
case "handler": {
|
|
50
|
+
if (specType !== "operation") return {
|
|
51
|
+
target,
|
|
52
|
+
outputPath: "",
|
|
53
|
+
success: false,
|
|
54
|
+
skipped: true,
|
|
55
|
+
error: `Handler generation only supported for operation specs (got ${specType})`
|
|
56
|
+
};
|
|
57
|
+
const kind = specInfo.kind === "command" || specInfo.kind === "query" ? specInfo.kind : "command";
|
|
58
|
+
code = generateHandlerTemplate(specInfo.key ?? "unknown", kind);
|
|
59
|
+
outputPath = resolveOutputPath(specPath, outputDir, "handlers", specInfo.key ?? "unknown", ".handler.ts", adapters.fs);
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
case "component":
|
|
63
|
+
if (specType !== "presentation") return {
|
|
64
|
+
target,
|
|
65
|
+
outputPath: "",
|
|
66
|
+
success: false,
|
|
67
|
+
skipped: true,
|
|
68
|
+
error: `Component generation only supported for presentation specs (got ${specType})`
|
|
69
|
+
};
|
|
70
|
+
code = generateComponentTemplate(specInfo.key ?? "unknown", specInfo.description ?? "");
|
|
71
|
+
outputPath = resolveOutputPath(specPath, outputDir, "components", specInfo.key ?? "unknown", ".tsx", adapters.fs);
|
|
72
|
+
break;
|
|
73
|
+
case "test": {
|
|
74
|
+
const testType = specType === "operation" ? "handler" : "component";
|
|
75
|
+
code = generateTestTemplate(specInfo.key ?? "unknown", testType);
|
|
76
|
+
outputPath = resolveOutputPath(specPath, outputDir, "__tests__", specInfo.key ?? "unknown", ".test.ts", adapters.fs);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
default: return {
|
|
80
|
+
target,
|
|
81
|
+
outputPath: "",
|
|
82
|
+
success: false,
|
|
83
|
+
error: `Unknown target: ${target}`
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (await fs.exists(outputPath) && !overwrite) return {
|
|
87
|
+
target,
|
|
88
|
+
outputPath,
|
|
89
|
+
success: false,
|
|
90
|
+
skipped: true,
|
|
91
|
+
error: "File already exists (use overwrite option)"
|
|
92
|
+
};
|
|
93
|
+
if (dryRun) {
|
|
94
|
+
logger.info(`[dry-run] Would write: ${outputPath}`);
|
|
95
|
+
return {
|
|
96
|
+
target,
|
|
97
|
+
outputPath,
|
|
98
|
+
success: true
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const dirPath = fs.dirname(outputPath);
|
|
102
|
+
await fs.mkdir(dirPath);
|
|
103
|
+
await fs.writeFile(outputPath, code);
|
|
104
|
+
logger.info(`Generated: ${outputPath}`);
|
|
105
|
+
return {
|
|
106
|
+
target,
|
|
107
|
+
outputPath,
|
|
108
|
+
success: true
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Detect default targets based on spec type.
|
|
113
|
+
*/
|
|
114
|
+
function detectDefaultTargets(specPath) {
|
|
115
|
+
switch (inferSpecTypeFromFilePath(specPath)) {
|
|
116
|
+
case "operation": return ["handler"];
|
|
117
|
+
case "presentation": return ["component"];
|
|
118
|
+
default: return [];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Resolve output path for generated file.
|
|
123
|
+
*/
|
|
124
|
+
function resolveOutputPath(specPath, outputDir, subdir, specName, extension, fs) {
|
|
125
|
+
const sanitizedName = toKebabCase(specName.split(".").pop() ?? "unknown");
|
|
126
|
+
let baseDir;
|
|
127
|
+
if (outputDir.startsWith(".")) baseDir = fs.resolve(fs.dirname(specPath), "..", outputDir, subdir);
|
|
128
|
+
else baseDir = fs.resolve(outputDir, subdir);
|
|
129
|
+
return fs.join(baseDir, `${sanitizedName}${extension}`);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Convert string to kebab-case.
|
|
133
|
+
*/
|
|
134
|
+
function toKebabCase(str) {
|
|
135
|
+
return str.replace(/\./g, "-").replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
//#endregion
|
|
139
|
+
export { buildSpec };
|
|
140
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","names":["results: BuildTargetResult[]","code: string","outputPath: string","baseDir: string"],"sources":["../../src/services/build.ts"],"sourcesContent":["/**\n * Build/scaffold service for generating implementation files from specs.\n *\n * Uses templates from @contractspec/module.workspace to generate\n * handler, component, and test skeletons without requiring AI.\n */\n\nimport {\n generateComponentTemplate,\n generateHandlerTemplate,\n generateTestTemplate,\n inferSpecTypeFromFilePath,\n scanSpecSource,\n type SpecScanResult,\n type WorkspaceConfig,\n} from '@contractspec/module.workspace';\nimport type { FsAdapter } from '../ports/fs';\nimport type { LoggerAdapter } from '../ports/logger';\n\n/**\n * Build target types.\n */\nexport type BuildTarget = 'handler' | 'component' | 'test';\n\n/**\n * Options for building from a spec.\n */\nexport interface BuildSpecOptions {\n /**\n * Which artifacts to generate.\n */\n targets?: BuildTarget[];\n\n /**\n * Override output directory.\n */\n outputDir?: string;\n\n /**\n * Whether to overwrite existing files.\n */\n overwrite?: boolean;\n\n /**\n * Skip writing files (dry run).\n */\n dryRun?: boolean;\n}\n\n/**\n * Result of a single build target.\n */\nexport interface BuildTargetResult {\n target: BuildTarget;\n outputPath: string;\n success: boolean;\n skipped?: boolean;\n error?: string;\n}\n\n/**\n * Result of building from a spec.\n */\nexport interface BuildSpecResult {\n specPath: string;\n specInfo: SpecScanResult;\n results: BuildTargetResult[];\n}\n\n/**\n * Build implementation files from a spec.\n */\nexport async function buildSpec(\n specPath: string,\n adapters: { fs: FsAdapter; logger: LoggerAdapter },\n config: WorkspaceConfig,\n options: BuildSpecOptions = {}\n): Promise<BuildSpecResult> {\n const { fs, logger } = adapters;\n const {\n targets = detectDefaultTargets(specPath),\n outputDir = config.outputDir,\n overwrite = false,\n dryRun = false,\n } = options;\n\n // Read and scan spec\n const specCode = await fs.readFile(specPath);\n const specInfo = scanSpecSource(specCode, specPath);\n const specType = inferSpecTypeFromFilePath(specPath);\n\n logger.info(`Building from spec: ${specPath}`, { specType });\n\n const results: BuildTargetResult[] = [];\n\n for (const target of targets) {\n try {\n const result = await buildTarget(\n target,\n specPath,\n specCode,\n specInfo,\n specType,\n { fs, logger },\n outputDir,\n overwrite,\n dryRun\n );\n results.push(result);\n } catch (error) {\n results.push({\n target,\n outputPath: '',\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return {\n specPath,\n specInfo,\n results,\n };\n}\n\n/**\n * Build a single target from a spec.\n */\nasync function buildTarget(\n target: BuildTarget,\n specPath: string,\n _specCode: string,\n specInfo: SpecScanResult,\n specType: string,\n adapters: { fs: FsAdapter; logger: LoggerAdapter },\n outputDir: string,\n overwrite: boolean,\n dryRun: boolean\n): Promise<BuildTargetResult> {\n const { fs, logger } = adapters;\n\n let code: string;\n let outputPath: string;\n\n switch (target) {\n case 'handler': {\n if (specType !== 'operation') {\n return {\n target,\n outputPath: '',\n success: false,\n skipped: true,\n error: `Handler generation only supported for operation specs (got ${specType})`,\n };\n }\n\n const kind =\n specInfo.kind === 'command' || specInfo.kind === 'query'\n ? specInfo.kind\n : 'command';\n\n code = generateHandlerTemplate(specInfo.key ?? 'unknown', kind);\n outputPath = resolveOutputPath(\n specPath,\n outputDir,\n 'handlers',\n specInfo.key ?? 'unknown',\n '.handler.ts',\n adapters.fs\n );\n break;\n }\n\n case 'component': {\n if (specType !== 'presentation') {\n return {\n target,\n outputPath: '',\n success: false,\n skipped: true,\n error: `Component generation only supported for presentation specs (got ${specType})`,\n };\n }\n\n code = generateComponentTemplate(\n specInfo.key ?? 'unknown',\n specInfo.description ?? ''\n );\n outputPath = resolveOutputPath(\n specPath,\n outputDir,\n 'components',\n specInfo.key ?? 'unknown',\n '.tsx',\n adapters.fs\n );\n break;\n }\n\n case 'test': {\n const testType = specType === 'operation' ? 'handler' : 'component';\n code = generateTestTemplate(specInfo.key ?? 'unknown', testType);\n outputPath = resolveOutputPath(\n specPath,\n outputDir,\n '__tests__',\n specInfo.key ?? 'unknown',\n '.test.ts',\n adapters.fs\n );\n break;\n }\n\n default:\n return {\n target,\n outputPath: '',\n success: false,\n error: `Unknown target: ${target}`,\n };\n }\n\n // Check if file exists\n const exists = await fs.exists(outputPath);\n if (exists && !overwrite) {\n return {\n target,\n outputPath,\n success: false,\n skipped: true,\n error: 'File already exists (use overwrite option)',\n };\n }\n\n if (dryRun) {\n logger.info(`[dry-run] Would write: ${outputPath}`);\n return {\n target,\n outputPath,\n success: true,\n };\n }\n\n // Ensure directory exists\n const dirPath = fs.dirname(outputPath);\n await fs.mkdir(dirPath);\n\n // Write file\n await fs.writeFile(outputPath, code);\n logger.info(`Generated: ${outputPath}`);\n\n return {\n target,\n outputPath,\n success: true,\n };\n}\n\n/**\n * Detect default targets based on spec type.\n */\nfunction detectDefaultTargets(specPath: string): BuildTarget[] {\n const specType = inferSpecTypeFromFilePath(specPath);\n\n switch (specType) {\n case 'operation':\n return ['handler'];\n case 'presentation':\n return ['component'];\n default:\n return [];\n }\n}\n\n/**\n * Resolve output path for generated file.\n */\nfunction resolveOutputPath(\n specPath: string,\n outputDir: string,\n subdir: string,\n specName: string,\n extension: string,\n fs: FsAdapter\n): string {\n const sanitizedName = toKebabCase(specName.split('.').pop() ?? 'unknown');\n\n let baseDir: string;\n if (outputDir.startsWith('.')) {\n // Relative to spec file location\n baseDir = fs.resolve(fs.dirname(specPath), '..', outputDir, subdir);\n } else {\n // Absolute or relative to cwd\n baseDir = fs.resolve(outputDir, subdir);\n }\n\n return fs.join(baseDir, `${sanitizedName}${extension}`);\n}\n\n/**\n * Convert string to kebab-case.\n */\nfunction toKebabCase(str: string): string {\n return str\n .replace(/\\./g, '-')\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .toLowerCase();\n}\n"],"mappings":";;;;;;;;;;;;AAwEA,eAAsB,UACpB,UACA,UACA,QACA,UAA4B,EAAE,EACJ;CAC1B,MAAM,EAAE,IAAI,WAAW;CACvB,MAAM,EACJ,UAAU,qBAAqB,SAAS,EACxC,YAAY,OAAO,WACnB,YAAY,OACZ,SAAS,UACP;CAGJ,MAAM,WAAW,MAAM,GAAG,SAAS,SAAS;CAC5C,MAAM,WAAW,eAAe,UAAU,SAAS;CACnD,MAAM,WAAW,0BAA0B,SAAS;AAEpD,QAAO,KAAK,uBAAuB,YAAY,EAAE,UAAU,CAAC;CAE5D,MAAMA,UAA+B,EAAE;AAEvC,MAAK,MAAM,UAAU,QACnB,KAAI;EACF,MAAM,SAAS,MAAM,YACnB,QACA,UACA,UACA,UACA,UACA;GAAE;GAAI;GAAQ,EACd,WACA,WACA,OACD;AACD,UAAQ,KAAK,OAAO;UACb,OAAO;AACd,UAAQ,KAAK;GACX;GACA,YAAY;GACZ,SAAS;GACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GAC9D,CAAC;;AAIN,QAAO;EACL;EACA;EACA;EACD;;;;;AAMH,eAAe,YACb,QACA,UACA,WACA,UACA,UACA,UACA,WACA,WACA,QAC4B;CAC5B,MAAM,EAAE,IAAI,WAAW;CAEvB,IAAIC;CACJ,IAAIC;AAEJ,SAAQ,QAAR;EACE,KAAK,WAAW;AACd,OAAI,aAAa,YACf,QAAO;IACL;IACA,YAAY;IACZ,SAAS;IACT,SAAS;IACT,OAAO,8DAA8D,SAAS;IAC/E;GAGH,MAAM,OACJ,SAAS,SAAS,aAAa,SAAS,SAAS,UAC7C,SAAS,OACT;AAEN,UAAO,wBAAwB,SAAS,OAAO,WAAW,KAAK;AAC/D,gBAAa,kBACX,UACA,WACA,YACA,SAAS,OAAO,WAChB,eACA,SAAS,GACV;AACD;;EAGF,KAAK;AACH,OAAI,aAAa,eACf,QAAO;IACL;IACA,YAAY;IACZ,SAAS;IACT,SAAS;IACT,OAAO,mEAAmE,SAAS;IACpF;AAGH,UAAO,0BACL,SAAS,OAAO,WAChB,SAAS,eAAe,GACzB;AACD,gBAAa,kBACX,UACA,WACA,cACA,SAAS,OAAO,WAChB,QACA,SAAS,GACV;AACD;EAGF,KAAK,QAAQ;GACX,MAAM,WAAW,aAAa,cAAc,YAAY;AACxD,UAAO,qBAAqB,SAAS,OAAO,WAAW,SAAS;AAChE,gBAAa,kBACX,UACA,WACA,aACA,SAAS,OAAO,WAChB,YACA,SAAS,GACV;AACD;;EAGF,QACE,QAAO;GACL;GACA,YAAY;GACZ,SAAS;GACT,OAAO,mBAAmB;GAC3B;;AAKL,KADe,MAAM,GAAG,OAAO,WAAW,IAC5B,CAAC,UACb,QAAO;EACL;EACA;EACA,SAAS;EACT,SAAS;EACT,OAAO;EACR;AAGH,KAAI,QAAQ;AACV,SAAO,KAAK,0BAA0B,aAAa;AACnD,SAAO;GACL;GACA;GACA,SAAS;GACV;;CAIH,MAAM,UAAU,GAAG,QAAQ,WAAW;AACtC,OAAM,GAAG,MAAM,QAAQ;AAGvB,OAAM,GAAG,UAAU,YAAY,KAAK;AACpC,QAAO,KAAK,cAAc,aAAa;AAEvC,QAAO;EACL;EACA;EACA,SAAS;EACV;;;;;AAMH,SAAS,qBAAqB,UAAiC;AAG7D,SAFiB,0BAA0B,SAAS,EAEpD;EACE,KAAK,YACH,QAAO,CAAC,UAAU;EACpB,KAAK,eACH,QAAO,CAAC,YAAY;EACtB,QACE,QAAO,EAAE;;;;;;AAOf,SAAS,kBACP,UACA,WACA,QACA,UACA,WACA,IACQ;CACR,MAAM,gBAAgB,YAAY,SAAS,MAAM,IAAI,CAAC,KAAK,IAAI,UAAU;CAEzE,IAAIC;AACJ,KAAI,UAAU,WAAW,IAAI,CAE3B,WAAU,GAAG,QAAQ,GAAG,QAAQ,SAAS,EAAE,MAAM,WAAW,OAAO;KAGnE,WAAU,GAAG,QAAQ,WAAW,OAAO;AAGzC,QAAO,GAAG,KAAK,SAAS,GAAG,gBAAgB,YAAY;;;;;AAMzD,SAAS,YAAY,KAAqB;AACxC,QAAO,IACJ,QAAQ,OAAO,IAAI,CACnB,QAAQ,mBAAmB,QAAQ,CACnC,aAAa"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FsAdapter } from "../../ports/fs.js";
|
|
2
|
+
import { LoggerAdapter } from "../../ports/logger.js";
|
|
3
|
+
import { CICheckOptions, CICheckResult } from "./types.js";
|
|
4
|
+
|
|
5
|
+
//#region src/services/ci-check/ci-check-service.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Run all CI checks and return structured results.
|
|
9
|
+
*/
|
|
10
|
+
declare function runCIChecks(adapters: {
|
|
11
|
+
fs: FsAdapter;
|
|
12
|
+
logger: LoggerAdapter;
|
|
13
|
+
}, options?: CICheckOptions): Promise<CICheckResult>;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { runCIChecks };
|
|
16
|
+
//# sourceMappingURL=ci-check-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci-check-service.d.ts","names":[],"sources":["../../../src/services/ci-check/ci-check-service.ts"],"sourcesContent":[],"mappings":";;;;;;;;;iBA+BsB,WAAA;MACJ;UAAmB;aAC1B,iBACR,QAAQ"}
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { validateImplementationFiles } from "../validate-implementation.js";
|
|
2
|
+
import { analyzeDeps } from "../deps.js";
|
|
3
|
+
import { loadWorkspaceConfig } from "../config.js";
|
|
4
|
+
import { analyzeIntegrity } from "../integrity.js";
|
|
5
|
+
import { runDoctor } from "../doctor/doctor-service.js";
|
|
6
|
+
import { resolveAllImplementations } from "../implementation/resolver.js";
|
|
7
|
+
import { isFeatureFile, validateSpecStructure } from "@contractspec/module.workspace";
|
|
8
|
+
|
|
9
|
+
//#region src/services/ci-check/ci-check-service.ts
|
|
10
|
+
/**
|
|
11
|
+
* CI Check service.
|
|
12
|
+
*
|
|
13
|
+
* Orchestrates all validation checks for CI/CD pipelines.
|
|
14
|
+
* Returns structured results suitable for multiple output formats.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Run all CI checks and return structured results.
|
|
18
|
+
*/
|
|
19
|
+
async function runCIChecks(adapters, options = {}) {
|
|
20
|
+
const startTime = Date.now();
|
|
21
|
+
const { fs, logger } = adapters;
|
|
22
|
+
const issues = [];
|
|
23
|
+
const categorySummaries = [];
|
|
24
|
+
const checksToRun = getChecksToRun(options);
|
|
25
|
+
logger.info("Starting CI checks...", { checks: checksToRun });
|
|
26
|
+
const specFiles = (await fs.glob({ pattern: options.pattern })).filter((f) => !isFeatureFile(f) && !f.includes(".test.") && !f.includes(".spec."));
|
|
27
|
+
if (checksToRun.includes("structure")) {
|
|
28
|
+
const categoryStart = Date.now();
|
|
29
|
+
const structureIssues = await runStructureChecks(adapters, specFiles);
|
|
30
|
+
issues.push(...structureIssues);
|
|
31
|
+
categorySummaries.push(createCategorySummary("structure", structureIssues, Date.now() - categoryStart));
|
|
32
|
+
}
|
|
33
|
+
if (checksToRun.includes("integrity")) {
|
|
34
|
+
const categoryStart = Date.now();
|
|
35
|
+
const integrityIssues = await runIntegrityChecks(adapters, options);
|
|
36
|
+
issues.push(...integrityIssues);
|
|
37
|
+
categorySummaries.push(createCategorySummary("integrity", integrityIssues, Date.now() - categoryStart));
|
|
38
|
+
}
|
|
39
|
+
if (checksToRun.includes("deps")) {
|
|
40
|
+
const categoryStart = Date.now();
|
|
41
|
+
const depsIssues = await runDepsChecks(adapters, options);
|
|
42
|
+
issues.push(...depsIssues);
|
|
43
|
+
categorySummaries.push(createCategorySummary("deps", depsIssues, Date.now() - categoryStart));
|
|
44
|
+
}
|
|
45
|
+
if (checksToRun.includes("doctor")) {
|
|
46
|
+
const categoryStart = Date.now();
|
|
47
|
+
const doctorIssues = await runDoctorChecks(adapters, options);
|
|
48
|
+
issues.push(...doctorIssues);
|
|
49
|
+
categorySummaries.push(createCategorySummary("doctor", doctorIssues, Date.now() - categoryStart));
|
|
50
|
+
}
|
|
51
|
+
if (checksToRun.includes("handlers") || options.checkHandlers) {
|
|
52
|
+
const categoryStart = Date.now();
|
|
53
|
+
const handlerIssues = await runHandlerChecks(adapters, specFiles);
|
|
54
|
+
issues.push(...handlerIssues);
|
|
55
|
+
categorySummaries.push(createCategorySummary("handlers", handlerIssues, Date.now() - categoryStart));
|
|
56
|
+
}
|
|
57
|
+
if (checksToRun.includes("tests") || options.checkTests) {
|
|
58
|
+
const categoryStart = Date.now();
|
|
59
|
+
const testIssues = await runTestChecks(adapters, specFiles);
|
|
60
|
+
issues.push(...testIssues);
|
|
61
|
+
categorySummaries.push(createCategorySummary("tests", testIssues, Date.now() - categoryStart));
|
|
62
|
+
}
|
|
63
|
+
if (checksToRun.includes("implementation")) {
|
|
64
|
+
const categoryStart = Date.now();
|
|
65
|
+
const implIssues = await runImplementationChecks(adapters, specFiles, options);
|
|
66
|
+
issues.push(...implIssues);
|
|
67
|
+
categorySummaries.push(createCategorySummary("implementation", implIssues, Date.now() - categoryStart));
|
|
68
|
+
}
|
|
69
|
+
const totalErrors = issues.filter((i) => i.severity === "error").length;
|
|
70
|
+
const totalWarnings = issues.filter((i) => i.severity === "warning").length;
|
|
71
|
+
const totalNotes = issues.filter((i) => i.severity === "note").length;
|
|
72
|
+
const success = options.failOnWarnings ? totalErrors === 0 && totalWarnings === 0 : totalErrors === 0;
|
|
73
|
+
const gitInfo = await getGitInfo(fs);
|
|
74
|
+
const result = {
|
|
75
|
+
success,
|
|
76
|
+
totalErrors,
|
|
77
|
+
totalWarnings,
|
|
78
|
+
totalNotes,
|
|
79
|
+
issues,
|
|
80
|
+
categories: categorySummaries,
|
|
81
|
+
durationMs: Date.now() - startTime,
|
|
82
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
83
|
+
...gitInfo
|
|
84
|
+
};
|
|
85
|
+
logger.info("CI checks complete", {
|
|
86
|
+
success,
|
|
87
|
+
errors: totalErrors,
|
|
88
|
+
warnings: totalWarnings,
|
|
89
|
+
durationMs: result.durationMs
|
|
90
|
+
});
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Determine which checks to run based on options.
|
|
95
|
+
*/
|
|
96
|
+
function getChecksToRun(options) {
|
|
97
|
+
const allCategories = [
|
|
98
|
+
"structure",
|
|
99
|
+
"integrity",
|
|
100
|
+
"deps",
|
|
101
|
+
"doctor"
|
|
102
|
+
];
|
|
103
|
+
if (options.checkHandlers) allCategories.push("handlers");
|
|
104
|
+
if (options.checkTests) allCategories.push("tests");
|
|
105
|
+
if (options.implementation) allCategories.push("implementation");
|
|
106
|
+
if (options.checks && options.checks.length > 0) return options.checks;
|
|
107
|
+
if (options.skip && options.skip.length > 0) return allCategories.filter((c) => !options.skip?.includes(c));
|
|
108
|
+
return allCategories;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Run spec structure validation checks.
|
|
112
|
+
*/
|
|
113
|
+
async function runStructureChecks(adapters, specFiles) {
|
|
114
|
+
const { fs } = adapters;
|
|
115
|
+
const issues = [];
|
|
116
|
+
for (const file of specFiles) {
|
|
117
|
+
const result = validateSpecStructure(await fs.readFile(file), file);
|
|
118
|
+
for (const error of result.errors) issues.push({
|
|
119
|
+
ruleId: "spec-structure-error",
|
|
120
|
+
severity: "error",
|
|
121
|
+
message: error,
|
|
122
|
+
category: "structure",
|
|
123
|
+
file
|
|
124
|
+
});
|
|
125
|
+
for (const warning of result.warnings) issues.push({
|
|
126
|
+
ruleId: "spec-structure-warning",
|
|
127
|
+
severity: "warning",
|
|
128
|
+
message: warning,
|
|
129
|
+
category: "structure",
|
|
130
|
+
file
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return issues;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Run integrity analysis checks.
|
|
137
|
+
*/
|
|
138
|
+
async function runIntegrityChecks(adapters, options) {
|
|
139
|
+
const issues = [];
|
|
140
|
+
const result = await analyzeIntegrity(adapters, {
|
|
141
|
+
pattern: options.pattern,
|
|
142
|
+
all: true
|
|
143
|
+
});
|
|
144
|
+
for (const issue of result.issues) issues.push({
|
|
145
|
+
ruleId: `integrity-${issue.type}`,
|
|
146
|
+
severity: issue.severity === "error" ? "error" : "warning",
|
|
147
|
+
message: issue.message,
|
|
148
|
+
category: "integrity",
|
|
149
|
+
file: issue.file,
|
|
150
|
+
context: {
|
|
151
|
+
specKey: issue.specKey,
|
|
152
|
+
specType: issue.specType,
|
|
153
|
+
featureKey: issue.featureKey,
|
|
154
|
+
ref: issue.ref
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
return issues;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Run dependency analysis checks.
|
|
161
|
+
*/
|
|
162
|
+
async function runDepsChecks(adapters, options) {
|
|
163
|
+
const issues = [];
|
|
164
|
+
const result = await analyzeDeps(adapters, { pattern: options.pattern });
|
|
165
|
+
for (const cycle of result.cycles) issues.push({
|
|
166
|
+
ruleId: "deps-circular",
|
|
167
|
+
severity: "error",
|
|
168
|
+
message: `Circular dependency detected: ${cycle.join(" → ")}`,
|
|
169
|
+
category: "deps",
|
|
170
|
+
context: { cycle }
|
|
171
|
+
});
|
|
172
|
+
for (const item of result.missing) for (const missing of item.missing) issues.push({
|
|
173
|
+
ruleId: "deps-missing",
|
|
174
|
+
severity: "error",
|
|
175
|
+
message: `Missing dependency: ${item.contract} requires ${missing}`,
|
|
176
|
+
category: "deps",
|
|
177
|
+
context: {
|
|
178
|
+
contract: item.contract,
|
|
179
|
+
missing
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
return issues;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Run doctor checks (skipping AI in CI).
|
|
186
|
+
*/
|
|
187
|
+
async function runDoctorChecks(adapters, options) {
|
|
188
|
+
const issues = [];
|
|
189
|
+
const result = await runDoctor(adapters, {
|
|
190
|
+
workspaceRoot: options.workspaceRoot ?? process.cwd(),
|
|
191
|
+
skipAi: true,
|
|
192
|
+
categories: [
|
|
193
|
+
"cli",
|
|
194
|
+
"config",
|
|
195
|
+
"deps",
|
|
196
|
+
"workspace"
|
|
197
|
+
]
|
|
198
|
+
});
|
|
199
|
+
for (const check of result.checks) if (check.status === "fail") issues.push({
|
|
200
|
+
ruleId: `doctor-${check.category}-${check.name.toLowerCase().replace(/\s+/g, "-")}`,
|
|
201
|
+
severity: "error",
|
|
202
|
+
message: `${check.name}: ${check.message}`,
|
|
203
|
+
category: "doctor",
|
|
204
|
+
context: { details: check.details }
|
|
205
|
+
});
|
|
206
|
+
else if (check.status === "warn") issues.push({
|
|
207
|
+
ruleId: `doctor-${check.category}-${check.name.toLowerCase().replace(/\s+/g, "-")}`,
|
|
208
|
+
severity: "warning",
|
|
209
|
+
message: `${check.name}: ${check.message}`,
|
|
210
|
+
category: "doctor",
|
|
211
|
+
context: { details: check.details }
|
|
212
|
+
});
|
|
213
|
+
return issues;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Run handler implementation checks.
|
|
217
|
+
*/
|
|
218
|
+
async function runHandlerChecks(adapters, specFiles) {
|
|
219
|
+
const { fs } = adapters;
|
|
220
|
+
const issues = [];
|
|
221
|
+
const config = await loadWorkspaceConfig(fs);
|
|
222
|
+
for (const specFile of specFiles) {
|
|
223
|
+
if (!specFile.includes(".operation.")) continue;
|
|
224
|
+
const result = await validateImplementationFiles(specFile, { fs }, config, {
|
|
225
|
+
checkHandlers: true,
|
|
226
|
+
outputDir: config.outputDir
|
|
227
|
+
});
|
|
228
|
+
for (const error of result.errors) issues.push({
|
|
229
|
+
ruleId: "handler-missing",
|
|
230
|
+
severity: "warning",
|
|
231
|
+
message: error,
|
|
232
|
+
category: "handlers",
|
|
233
|
+
file: specFile
|
|
234
|
+
});
|
|
235
|
+
for (const warning of result.warnings) issues.push({
|
|
236
|
+
ruleId: "handler-warning",
|
|
237
|
+
severity: "warning",
|
|
238
|
+
message: warning,
|
|
239
|
+
category: "handlers",
|
|
240
|
+
file: specFile
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
return issues;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Run test coverage checks.
|
|
247
|
+
*/
|
|
248
|
+
async function runTestChecks(adapters, specFiles) {
|
|
249
|
+
const { fs } = adapters;
|
|
250
|
+
const issues = [];
|
|
251
|
+
const config = await loadWorkspaceConfig(fs);
|
|
252
|
+
for (const specFile of specFiles) {
|
|
253
|
+
if (!specFile.includes(".operation.")) continue;
|
|
254
|
+
const result = await validateImplementationFiles(specFile, { fs }, config, {
|
|
255
|
+
checkTests: true,
|
|
256
|
+
outputDir: config.outputDir
|
|
257
|
+
});
|
|
258
|
+
for (const error of result.errors) issues.push({
|
|
259
|
+
ruleId: "test-missing",
|
|
260
|
+
severity: "warning",
|
|
261
|
+
message: error,
|
|
262
|
+
category: "tests",
|
|
263
|
+
file: specFile
|
|
264
|
+
});
|
|
265
|
+
for (const warning of result.warnings) issues.push({
|
|
266
|
+
ruleId: "test-warning",
|
|
267
|
+
severity: "warning",
|
|
268
|
+
message: warning,
|
|
269
|
+
category: "tests",
|
|
270
|
+
file: specFile
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
return issues;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Run implementation verification checks.
|
|
277
|
+
*/
|
|
278
|
+
async function runImplementationChecks(adapters, specFiles, options) {
|
|
279
|
+
const { fs } = adapters;
|
|
280
|
+
const issues = [];
|
|
281
|
+
const config = await loadWorkspaceConfig(fs);
|
|
282
|
+
const implOptions = options.implementation ?? {};
|
|
283
|
+
const results = await resolveAllImplementations(specFiles.filter((f) => f.includes(".operation.")), { fs }, config, { computeHashes: implOptions.useCache ?? true });
|
|
284
|
+
for (const result of results) {
|
|
285
|
+
if (implOptions.requireImplemented && result.status === "missing") issues.push({
|
|
286
|
+
ruleId: "impl-missing",
|
|
287
|
+
severity: "error",
|
|
288
|
+
message: `Spec ${result.specKey} has no implementation`,
|
|
289
|
+
category: "implementation",
|
|
290
|
+
file: result.specPath,
|
|
291
|
+
context: {
|
|
292
|
+
specKey: result.specKey,
|
|
293
|
+
specVersion: result.specVersion,
|
|
294
|
+
status: result.status
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
else if (result.status === "missing") issues.push({
|
|
298
|
+
ruleId: "impl-missing",
|
|
299
|
+
severity: "warning",
|
|
300
|
+
message: `Spec ${result.specKey} has no implementation`,
|
|
301
|
+
category: "implementation",
|
|
302
|
+
file: result.specPath,
|
|
303
|
+
context: {
|
|
304
|
+
specKey: result.specKey,
|
|
305
|
+
specVersion: result.specVersion,
|
|
306
|
+
status: result.status
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
if (!implOptions.allowPartial && result.status === "partial") {
|
|
310
|
+
const missingImpls = result.implementations.filter((i) => !i.exists && i.type !== "test").map((i) => i.path);
|
|
311
|
+
issues.push({
|
|
312
|
+
ruleId: "impl-partial",
|
|
313
|
+
severity: "warning",
|
|
314
|
+
message: `Spec ${result.specKey} has partial implementation: missing ${missingImpls.join(", ")}`,
|
|
315
|
+
category: "implementation",
|
|
316
|
+
file: result.specPath,
|
|
317
|
+
context: {
|
|
318
|
+
specKey: result.specKey,
|
|
319
|
+
specVersion: result.specVersion,
|
|
320
|
+
status: result.status,
|
|
321
|
+
missingFiles: missingImpls
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
const missingTests = result.implementations.filter((i) => !i.exists && i.type === "test");
|
|
326
|
+
if (missingTests.length > 0) issues.push({
|
|
327
|
+
ruleId: "impl-missing-tests",
|
|
328
|
+
severity: "note",
|
|
329
|
+
message: `Spec ${result.specKey} missing test files: ${missingTests.map((t) => t.path).join(", ")}`,
|
|
330
|
+
category: "implementation",
|
|
331
|
+
file: result.specPath,
|
|
332
|
+
context: {
|
|
333
|
+
specKey: result.specKey,
|
|
334
|
+
missingTests: missingTests.map((t) => t.path)
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
return issues;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Create a category summary from issues.
|
|
342
|
+
*/
|
|
343
|
+
function createCategorySummary(category, issues, durationMs) {
|
|
344
|
+
const categoryLabels = {
|
|
345
|
+
structure: "Spec Structure Validation",
|
|
346
|
+
integrity: "Contract Integrity Analysis",
|
|
347
|
+
deps: "Dependency Analysis",
|
|
348
|
+
doctor: "Installation Health",
|
|
349
|
+
handlers: "Handler Implementation",
|
|
350
|
+
tests: "Test Coverage",
|
|
351
|
+
implementation: "Implementation Verification"
|
|
352
|
+
};
|
|
353
|
+
const errors = issues.filter((i) => i.severity === "error").length;
|
|
354
|
+
const warnings = issues.filter((i) => i.severity === "warning").length;
|
|
355
|
+
const notes = issues.filter((i) => i.severity === "note").length;
|
|
356
|
+
return {
|
|
357
|
+
category,
|
|
358
|
+
label: categoryLabels[category],
|
|
359
|
+
errors,
|
|
360
|
+
warnings,
|
|
361
|
+
notes,
|
|
362
|
+
passed: errors === 0,
|
|
363
|
+
durationMs
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Get git information if available.
|
|
368
|
+
*/
|
|
369
|
+
async function getGitInfo(fs) {
|
|
370
|
+
try {
|
|
371
|
+
const gitHeadPath = ".git/HEAD";
|
|
372
|
+
if (!await fs.exists(gitHeadPath)) return {};
|
|
373
|
+
const headContent = await fs.readFile(gitHeadPath);
|
|
374
|
+
const refMatch = headContent.match(/^ref: (.+)$/m);
|
|
375
|
+
if (refMatch) {
|
|
376
|
+
const branch = refMatch[1]?.replace("refs/heads/", "");
|
|
377
|
+
const refPath = `.git/${refMatch[1]}`;
|
|
378
|
+
if (await fs.exists(refPath)) return {
|
|
379
|
+
commitSha: (await fs.readFile(refPath)).trim(),
|
|
380
|
+
branch
|
|
381
|
+
};
|
|
382
|
+
return { branch };
|
|
383
|
+
}
|
|
384
|
+
return { commitSha: headContent.trim() };
|
|
385
|
+
} catch {
|
|
386
|
+
return {};
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
//#endregion
|
|
391
|
+
export { runCIChecks };
|
|
392
|
+
//# sourceMappingURL=ci-check-service.js.map
|