@prodara/compiler 0.1.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/README.md +204 -0
- package/dist/agent/agent.d.ts +10 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +122 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/api-client.d.ts +29 -0
- package/dist/agent/api-client.d.ts.map +1 -0
- package/dist/agent/api-client.js +167 -0
- package/dist/agent/api-client.js.map +1 -0
- package/dist/agent/index.d.ts +5 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +3 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/party.d.ts +48 -0
- package/dist/agent/party.d.ts.map +1 -0
- package/dist/agent/party.js +79 -0
- package/dist/agent/party.js.map +1 -0
- package/dist/agent/types.d.ts +35 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/audit/audit.d.ts +32 -0
- package/dist/audit/audit.d.ts.map +1 -0
- package/dist/audit/audit.js +120 -0
- package/dist/audit/audit.js.map +1 -0
- package/dist/audit/index.d.ts +3 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +2 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/audit/types.d.ts +25 -0
- package/dist/audit/types.d.ts.map +1 -0
- package/dist/audit/types.js +5 -0
- package/dist/audit/types.js.map +1 -0
- package/dist/binder/binder.d.ts +34 -0
- package/dist/binder/binder.d.ts.map +1 -0
- package/dist/binder/binder.js +202 -0
- package/dist/binder/binder.js.map +1 -0
- package/dist/binder/index.d.ts +3 -0
- package/dist/binder/index.d.ts.map +1 -0
- package/dist/binder/index.js +2 -0
- package/dist/binder/index.js.map +1 -0
- package/dist/build-state/build-state.d.ts +40 -0
- package/dist/build-state/build-state.d.ts.map +1 -0
- package/dist/build-state/build-state.js +180 -0
- package/dist/build-state/build-state.js.map +1 -0
- package/dist/build-state/index.d.ts +3 -0
- package/dist/build-state/index.d.ts.map +1 -0
- package/dist/build-state/index.js +2 -0
- package/dist/build-state/index.js.map +1 -0
- package/dist/checker/index.d.ts +5 -0
- package/dist/checker/index.d.ts.map +1 -0
- package/dist/checker/index.js +3 -0
- package/dist/checker/index.js.map +1 -0
- package/dist/checker/type-checker.d.ts +8 -0
- package/dist/checker/type-checker.d.ts.map +1 -0
- package/dist/checker/type-checker.js +136 -0
- package/dist/checker/type-checker.js.map +1 -0
- package/dist/checker/validator.d.ts +8 -0
- package/dist/checker/validator.d.ts.map +1 -0
- package/dist/checker/validator.js +251 -0
- package/dist/checker/validator.js.map +1 -0
- package/dist/cli/agent-setup.d.ts +27 -0
- package/dist/cli/agent-setup.d.ts.map +1 -0
- package/dist/cli/agent-setup.js +829 -0
- package/dist/cli/agent-setup.js.map +1 -0
- package/dist/cli/analyze.d.ts +28 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +188 -0
- package/dist/cli/analyze.js.map +1 -0
- package/dist/cli/checklist.d.ts +27 -0
- package/dist/cli/checklist.d.ts.map +1 -0
- package/dist/cli/checklist.js +153 -0
- package/dist/cli/checklist.js.map +1 -0
- package/dist/cli/compile.d.ts +26 -0
- package/dist/cli/compile.d.ts.map +1 -0
- package/dist/cli/compile.js +112 -0
- package/dist/cli/compile.js.map +1 -0
- package/dist/cli/dashboard.d.ts +19 -0
- package/dist/cli/dashboard.d.ts.map +1 -0
- package/dist/cli/dashboard.js +73 -0
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/cli/explain.d.ts +23 -0
- package/dist/cli/explain.d.ts.map +1 -0
- package/dist/cli/explain.js +144 -0
- package/dist/cli/explain.js.map +1 -0
- package/dist/cli/git.d.ts +14 -0
- package/dist/cli/git.d.ts.map +1 -0
- package/dist/cli/git.js +44 -0
- package/dist/cli/git.js.map +1 -0
- package/dist/cli/lifecycle.d.ts +28 -0
- package/dist/cli/lifecycle.d.ts.map +1 -0
- package/dist/cli/lifecycle.js +82 -0
- package/dist/cli/lifecycle.js.map +1 -0
- package/dist/cli/main.d.ts +10 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +1072 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/notify.d.ts +13 -0
- package/dist/cli/notify.d.ts.map +1 -0
- package/dist/cli/notify.js +36 -0
- package/dist/cli/notify.js.map +1 -0
- package/dist/cli/starters.d.ts +12 -0
- package/dist/cli/starters.d.ts.map +1 -0
- package/dist/cli/starters.js +439 -0
- package/dist/cli/starters.js.map +1 -0
- package/dist/config/config.d.ts +194 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +434 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +5 -0
- package/dist/config/index.js.map +1 -0
- package/dist/diagnostics/diagnostic.d.ts +44 -0
- package/dist/diagnostics/diagnostic.d.ts.map +1 -0
- package/dist/diagnostics/diagnostic.js +44 -0
- package/dist/diagnostics/diagnostic.js.map +1 -0
- package/dist/diagnostics/index.d.ts +4 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/diagnostics/index.js +3 -0
- package/dist/diagnostics/index.js.map +1 -0
- package/dist/diagnostics/reporter.d.ts +43 -0
- package/dist/diagnostics/reporter.d.ts.map +1 -0
- package/dist/diagnostics/reporter.js +74 -0
- package/dist/diagnostics/reporter.js.map +1 -0
- package/dist/discovery/discovery.d.ts +6 -0
- package/dist/discovery/discovery.d.ts.map +1 -0
- package/dist/discovery/discovery.js +66 -0
- package/dist/discovery/discovery.js.map +1 -0
- package/dist/discovery/index.d.ts +2 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +2 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/doc-gen/doc-gen-types.d.ts +174 -0
- package/dist/doc-gen/doc-gen-types.d.ts.map +1 -0
- package/dist/doc-gen/doc-gen-types.js +7 -0
- package/dist/doc-gen/doc-gen-types.js.map +1 -0
- package/dist/doc-gen/doc-renderer.d.ts +17 -0
- package/dist/doc-gen/doc-renderer.d.ts.map +1 -0
- package/dist/doc-gen/doc-renderer.js +65 -0
- package/dist/doc-gen/doc-renderer.js.map +1 -0
- package/dist/doc-gen/format-helpers.d.ts +18 -0
- package/dist/doc-gen/format-helpers.d.ts.map +1 -0
- package/dist/doc-gen/format-helpers.js +92 -0
- package/dist/doc-gen/format-helpers.js.map +1 -0
- package/dist/doc-gen/index.d.ts +5 -0
- package/dist/doc-gen/index.d.ts.map +1 -0
- package/dist/doc-gen/index.js +5 -0
- package/dist/doc-gen/index.js.map +1 -0
- package/dist/doc-gen/link-resolver.d.ts +10 -0
- package/dist/doc-gen/link-resolver.d.ts.map +1 -0
- package/dist/doc-gen/link-resolver.js +87 -0
- package/dist/doc-gen/link-resolver.js.map +1 -0
- package/dist/doc-gen/mermaid-renderers.d.ts +12 -0
- package/dist/doc-gen/mermaid-renderers.d.ts.map +1 -0
- package/dist/doc-gen/mermaid-renderers.js +197 -0
- package/dist/doc-gen/mermaid-renderers.js.map +1 -0
- package/dist/doc-gen/module-renderer.d.ts +6 -0
- package/dist/doc-gen/module-renderer.d.ts.map +1 -0
- package/dist/doc-gen/module-renderer.js +54 -0
- package/dist/doc-gen/module-renderer.js.map +1 -0
- package/dist/doc-gen/product-renderer.d.ts +6 -0
- package/dist/doc-gen/product-renderer.d.ts.map +1 -0
- package/dist/doc-gen/product-renderer.js +101 -0
- package/dist/doc-gen/product-renderer.js.map +1 -0
- package/dist/doc-gen/section-renderers.d.ts +20 -0
- package/dist/doc-gen/section-renderers.d.ts.map +1 -0
- package/dist/doc-gen/section-renderers.js +357 -0
- package/dist/doc-gen/section-renderers.js.map +1 -0
- package/dist/doc-gen/string-resolver.d.ts +8 -0
- package/dist/doc-gen/string-resolver.d.ts.map +1 -0
- package/dist/doc-gen/string-resolver.js +47 -0
- package/dist/doc-gen/string-resolver.js.map +1 -0
- package/dist/doc-gen/surface-ascii.d.ts +7 -0
- package/dist/doc-gen/surface-ascii.d.ts.map +1 -0
- package/dist/doc-gen/surface-ascii.js +87 -0
- package/dist/doc-gen/surface-ascii.js.map +1 -0
- package/dist/drift/drift.d.ts +16 -0
- package/dist/drift/drift.d.ts.map +1 -0
- package/dist/drift/drift.js +149 -0
- package/dist/drift/drift.js.map +1 -0
- package/dist/drift/index.d.ts +3 -0
- package/dist/drift/index.d.ts.map +1 -0
- package/dist/drift/index.js +2 -0
- package/dist/drift/index.js.map +1 -0
- package/dist/extensions/index.d.ts +6 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +7 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/loader.d.ts +21 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +101 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/marketplace.d.ts +22 -0
- package/dist/extensions/marketplace.d.ts.map +1 -0
- package/dist/extensions/marketplace.js +40 -0
- package/dist/extensions/marketplace.js.map +1 -0
- package/dist/extensions/registry.d.ts +45 -0
- package/dist/extensions/registry.d.ts.map +1 -0
- package/dist/extensions/registry.js +82 -0
- package/dist/extensions/registry.js.map +1 -0
- package/dist/extensions/types.d.ts +41 -0
- package/dist/extensions/types.d.ts.map +1 -0
- package/dist/extensions/types.js +5 -0
- package/dist/extensions/types.js.map +1 -0
- package/dist/generator/contracts.d.ts +67 -0
- package/dist/generator/contracts.d.ts.map +1 -0
- package/dist/generator/contracts.js +94 -0
- package/dist/generator/contracts.js.map +1 -0
- package/dist/generator/index.d.ts +3 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +2 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/governance/governance.d.ts +24 -0
- package/dist/governance/governance.d.ts.map +1 -0
- package/dist/governance/governance.js +238 -0
- package/dist/governance/governance.js.map +1 -0
- package/dist/governance/index.d.ts +3 -0
- package/dist/governance/index.d.ts.map +1 -0
- package/dist/governance/index.js +2 -0
- package/dist/governance/index.js.map +1 -0
- package/dist/governance/types.d.ts +14 -0
- package/dist/governance/types.d.ts.map +1 -0
- package/dist/governance/types.js +5 -0
- package/dist/governance/types.js.map +1 -0
- package/dist/graph/builder.d.ts +10 -0
- package/dist/graph/builder.d.ts.map +1 -0
- package/dist/graph/builder.js +573 -0
- package/dist/graph/builder.js.map +1 -0
- package/dist/graph/graph-types.d.ts +64 -0
- package/dist/graph/graph-types.d.ts.map +1 -0
- package/dist/graph/graph-types.js +29 -0
- package/dist/graph/graph-types.js.map +1 -0
- package/dist/graph/index.d.ts +8 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +5 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/serializer.d.ts +9 -0
- package/dist/graph/serializer.d.ts.map +1 -0
- package/dist/graph/serializer.js +31 -0
- package/dist/graph/serializer.js.map +1 -0
- package/dist/graph/validator.d.ts +14 -0
- package/dist/graph/validator.d.ts.map +1 -0
- package/dist/graph/validator.js +96 -0
- package/dist/graph/validator.js.map +1 -0
- package/dist/implement/implement.d.ts +30 -0
- package/dist/implement/implement.d.ts.map +1 -0
- package/dist/implement/implement.js +299 -0
- package/dist/implement/implement.js.map +1 -0
- package/dist/implement/index.d.ts +3 -0
- package/dist/implement/index.d.ts.map +1 -0
- package/dist/implement/index.js +2 -0
- package/dist/implement/index.js.map +1 -0
- package/dist/implement/types.d.ts +41 -0
- package/dist/implement/types.d.ts.map +1 -0
- package/dist/implement/types.js +5 -0
- package/dist/implement/types.js.map +1 -0
- package/dist/incremental/incremental-spec.d.ts +12 -0
- package/dist/incremental/incremental-spec.d.ts.map +1 -0
- package/dist/incremental/incremental-spec.js +100 -0
- package/dist/incremental/incremental-spec.js.map +1 -0
- package/dist/incremental/index.d.ts +3 -0
- package/dist/incremental/index.d.ts.map +1 -0
- package/dist/incremental/index.js +5 -0
- package/dist/incremental/index.js.map +1 -0
- package/dist/incremental/types.d.ts +28 -0
- package/dist/incremental/types.d.ts.map +1 -0
- package/dist/incremental/types.js +7 -0
- package/dist/incremental/types.js.map +1 -0
- package/dist/index.d.ts +106 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +106 -0
- package/dist/index.js.map +1 -0
- package/dist/lexer/index.d.ts +6 -0
- package/dist/lexer/index.d.ts.map +1 -0
- package/dist/lexer/index.js +5 -0
- package/dist/lexer/index.js.map +1 -0
- package/dist/lexer/keywords.d.ts +3 -0
- package/dist/lexer/keywords.d.ts.map +1 -0
- package/dist/lexer/keywords.js +142 -0
- package/dist/lexer/keywords.js.map +1 -0
- package/dist/lexer/lexer.d.ts +19 -0
- package/dist/lexer/lexer.d.ts.map +1 -0
- package/dist/lexer/lexer.js +286 -0
- package/dist/lexer/lexer.js.map +1 -0
- package/dist/lexer/source.d.ts +13 -0
- package/dist/lexer/source.d.ts.map +1 -0
- package/dist/lexer/source.js +59 -0
- package/dist/lexer/source.js.map +1 -0
- package/dist/lexer/tokens.d.ts +157 -0
- package/dist/lexer/tokens.d.ts.map +1 -0
- package/dist/lexer/tokens.js +173 -0
- package/dist/lexer/tokens.js.map +1 -0
- package/dist/orchestrator/index.d.ts +5 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/index.js +3 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/orchestrator.d.ts +14 -0
- package/dist/orchestrator/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator.js +129 -0
- package/dist/orchestrator/orchestrator.js.map +1 -0
- package/dist/orchestrator/pipeline.d.ts +31 -0
- package/dist/orchestrator/pipeline.d.ts.map +1 -0
- package/dist/orchestrator/pipeline.js +290 -0
- package/dist/orchestrator/pipeline.js.map +1 -0
- package/dist/orchestrator/types.d.ts +60 -0
- package/dist/orchestrator/types.d.ts.map +1 -0
- package/dist/orchestrator/types.js +8 -0
- package/dist/orchestrator/types.js.map +1 -0
- package/dist/parser/ast.d.ts +502 -0
- package/dist/parser/ast.d.ts.map +1 -0
- package/dist/parser/ast.js +7 -0
- package/dist/parser/ast.js.map +1 -0
- package/dist/parser/expressions.d.ts +18 -0
- package/dist/parser/expressions.d.ts.map +1 -0
- package/dist/parser/expressions.js +230 -0
- package/dist/parser/expressions.js.map +1 -0
- package/dist/parser/index.d.ts +4 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +2 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/parser.d.ts +83 -0
- package/dist/parser/parser.d.ts.map +1 -0
- package/dist/parser/parser.js +2149 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/planner/differ.d.ts +4 -0
- package/dist/planner/differ.d.ts.map +1 -0
- package/dist/planner/differ.js +96 -0
- package/dist/planner/differ.js.map +1 -0
- package/dist/planner/index.d.ts +7 -0
- package/dist/planner/index.d.ts.map +1 -0
- package/dist/planner/index.js +5 -0
- package/dist/planner/index.js.map +1 -0
- package/dist/planner/plan-types.d.ts +26 -0
- package/dist/planner/plan-types.d.ts.map +1 -0
- package/dist/planner/plan-types.js +5 -0
- package/dist/planner/plan-types.js.map +1 -0
- package/dist/planner/planner.d.ts +8 -0
- package/dist/planner/planner.d.ts.map +1 -0
- package/dist/planner/planner.js +83 -0
- package/dist/planner/planner.js.map +1 -0
- package/dist/planner/propagator.d.ts +4 -0
- package/dist/planner/propagator.d.ts.map +1 -0
- package/dist/planner/propagator.js +45 -0
- package/dist/planner/propagator.js.map +1 -0
- package/dist/planner/semantic-diff.d.ts +27 -0
- package/dist/planner/semantic-diff.d.ts.map +1 -0
- package/dist/planner/semantic-diff.js +253 -0
- package/dist/planner/semantic-diff.js.map +1 -0
- package/dist/presets/index.d.ts +3 -0
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +5 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/presets/loader.d.ts +28 -0
- package/dist/presets/loader.d.ts.map +1 -0
- package/dist/presets/loader.js +99 -0
- package/dist/presets/loader.js.map +1 -0
- package/dist/presets/types.d.ts +21 -0
- package/dist/presets/types.d.ts.map +1 -0
- package/dist/presets/types.js +5 -0
- package/dist/presets/types.js.map +1 -0
- package/dist/proposal/index.d.ts +3 -0
- package/dist/proposal/index.d.ts.map +1 -0
- package/dist/proposal/index.js +7 -0
- package/dist/proposal/index.js.map +1 -0
- package/dist/proposal/proposal.d.ts +9 -0
- package/dist/proposal/proposal.d.ts.map +1 -0
- package/dist/proposal/proposal.js +169 -0
- package/dist/proposal/proposal.js.map +1 -0
- package/dist/proposal/types.d.ts +15 -0
- package/dist/proposal/types.d.ts.map +1 -0
- package/dist/proposal/types.js +5 -0
- package/dist/proposal/types.js.map +1 -0
- package/dist/registry/index.d.ts +3 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +2 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/resolution.d.ts +39 -0
- package/dist/registry/resolution.d.ts.map +1 -0
- package/dist/registry/resolution.js +70 -0
- package/dist/registry/resolution.js.map +1 -0
- package/dist/reviewers/adversarial.d.ts +3 -0
- package/dist/reviewers/adversarial.d.ts.map +1 -0
- package/dist/reviewers/adversarial.js +111 -0
- package/dist/reviewers/adversarial.js.map +1 -0
- package/dist/reviewers/architecture.d.ts +3 -0
- package/dist/reviewers/architecture.d.ts.map +1 -0
- package/dist/reviewers/architecture.js +71 -0
- package/dist/reviewers/architecture.js.map +1 -0
- package/dist/reviewers/code-quality.d.ts +3 -0
- package/dist/reviewers/code-quality.d.ts.map +1 -0
- package/dist/reviewers/code-quality.js +72 -0
- package/dist/reviewers/code-quality.js.map +1 -0
- package/dist/reviewers/edge-case.d.ts +3 -0
- package/dist/reviewers/edge-case.d.ts.map +1 -0
- package/dist/reviewers/edge-case.js +107 -0
- package/dist/reviewers/edge-case.js.map +1 -0
- package/dist/reviewers/index.d.ts +21 -0
- package/dist/reviewers/index.d.ts.map +1 -0
- package/dist/reviewers/index.js +39 -0
- package/dist/reviewers/index.js.map +1 -0
- package/dist/reviewers/prompt-loader.d.ts +24 -0
- package/dist/reviewers/prompt-loader.d.ts.map +1 -0
- package/dist/reviewers/prompt-loader.js +67 -0
- package/dist/reviewers/prompt-loader.js.map +1 -0
- package/dist/reviewers/quality.d.ts +3 -0
- package/dist/reviewers/quality.d.ts.map +1 -0
- package/dist/reviewers/quality.js +76 -0
- package/dist/reviewers/quality.js.map +1 -0
- package/dist/reviewers/reviewer.d.ts +39 -0
- package/dist/reviewers/reviewer.d.ts.map +1 -0
- package/dist/reviewers/reviewer.js +149 -0
- package/dist/reviewers/reviewer.js.map +1 -0
- package/dist/reviewers/security.d.ts +3 -0
- package/dist/reviewers/security.d.ts.map +1 -0
- package/dist/reviewers/security.js +87 -0
- package/dist/reviewers/security.js.map +1 -0
- package/dist/reviewers/specification.d.ts +3 -0
- package/dist/reviewers/specification.d.ts.map +1 -0
- package/dist/reviewers/specification.js +79 -0
- package/dist/reviewers/specification.js.map +1 -0
- package/dist/reviewers/test-quality.d.ts +3 -0
- package/dist/reviewers/test-quality.d.ts.map +1 -0
- package/dist/reviewers/test-quality.js +88 -0
- package/dist/reviewers/test-quality.js.map +1 -0
- package/dist/reviewers/types.d.ts +32 -0
- package/dist/reviewers/types.d.ts.map +1 -0
- package/dist/reviewers/types.js +5 -0
- package/dist/reviewers/types.js.map +1 -0
- package/dist/reviewers/ux.d.ts +3 -0
- package/dist/reviewers/ux.d.ts.map +1 -0
- package/dist/reviewers/ux.js +94 -0
- package/dist/reviewers/ux.js.map +1 -0
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/resolution.d.ts +30 -0
- package/dist/runtime/resolution.d.ts.map +1 -0
- package/dist/runtime/resolution.js +59 -0
- package/dist/runtime/resolution.js.map +1 -0
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +2 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/test-runner.d.ts +18 -0
- package/dist/testing/test-runner.d.ts.map +1 -0
- package/dist/testing/test-runner.js +131 -0
- package/dist/testing/test-runner.js.map +1 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +127 -0
- package/dist/types.js.map +1 -0
- package/dist/validation/index.d.ts +3 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +2 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/types.d.ts +16 -0
- package/dist/validation/types.d.ts.map +1 -0
- package/dist/validation/types.js +5 -0
- package/dist/validation/types.js.map +1 -0
- package/dist/validation/validation.d.ts +8 -0
- package/dist/validation/validation.d.ts.map +1 -0
- package/dist/validation/validation.js +101 -0
- package/dist/validation/validation.js.map +1 -0
- package/dist/verification/index.d.ts +3 -0
- package/dist/verification/index.d.ts.map +1 -0
- package/dist/verification/index.js +5 -0
- package/dist/verification/index.js.map +1 -0
- package/dist/verification/types.d.ts +14 -0
- package/dist/verification/types.d.ts.map +1 -0
- package/dist/verification/types.js +5 -0
- package/dist/verification/types.js.map +1 -0
- package/dist/verification/verify.d.ts +7 -0
- package/dist/verification/verify.d.ts.map +1 -0
- package/dist/verification/verify.js +127 -0
- package/dist/verification/verify.js.map +1 -0
- package/dist/workflow/clarify.d.ts +7 -0
- package/dist/workflow/clarify.d.ts.map +1 -0
- package/dist/workflow/clarify.js +165 -0
- package/dist/workflow/clarify.js.map +1 -0
- package/dist/workflow/engine.d.ts +19 -0
- package/dist/workflow/engine.d.ts.map +1 -0
- package/dist/workflow/engine.js +265 -0
- package/dist/workflow/engine.js.map +1 -0
- package/dist/workflow/index.d.ts +6 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +7 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/types.d.ts +95 -0
- package/dist/workflow/types.d.ts.map +1 -0
- package/dist/workflow/types.js +18 -0
- package/dist/workflow/types.js.map +1 -0
- package/package.json +63 -0
package/dist/cli/main.js
ADDED
|
@@ -0,0 +1,1072 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Prodara Compiler — CLI Entry Point
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, watch } from 'node:fs';
|
|
7
|
+
import { resolve, dirname, join, relative } from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { compile } from './compile.js';
|
|
10
|
+
import { runPipeline } from '../orchestrator/pipeline.js';
|
|
11
|
+
import { formatDiagnosticsJson, formatDiagnosticsHuman } from '../diagnostics/reporter.js';
|
|
12
|
+
import { discoverFiles } from '../discovery/discovery.js';
|
|
13
|
+
import { loadConfig, CONFIG_FILENAME } from '../config/config.js';
|
|
14
|
+
import { buildIncrementalSpec, serializeIncrementalSpec } from '../incremental/incremental-spec.js';
|
|
15
|
+
import { semanticDiff, formatSemanticDiffHuman } from '../planner/semantic-diff.js';
|
|
16
|
+
import { readPreviousGraph } from '../build-state/build-state.js';
|
|
17
|
+
import { detectDrift, formatDriftHuman } from '../drift/drift.js';
|
|
18
|
+
import { getStarterTemplate, listStarterTemplates } from './starters.js';
|
|
19
|
+
import { explainNode, collectAllNodeIds, formatExplanation, getDiagnosticInfo } from './explain.js';
|
|
20
|
+
import { registerShutdownHandlers, setActiveRoot, clearActiveRoot } from './lifecycle.js';
|
|
21
|
+
import { generateSlashCommands, writeSlashCommands, isValidAgentId, listSupportedAgents, getAgentConfig } from './agent-setup.js';
|
|
22
|
+
import { createProposal, listProposals, applyProposal, archiveProposal } from '../proposal/proposal.js';
|
|
23
|
+
import { generateChecklist, formatChecklistHuman } from './checklist.js';
|
|
24
|
+
import { analyzeGraph, formatAnalysisHuman } from './analyze.js';
|
|
25
|
+
import { installExtension, removeExtension, listInstalledExtensions } from '../extensions/loader.js';
|
|
26
|
+
import { loadPresets, installPreset, removePreset } from '../presets/loader.js';
|
|
27
|
+
import { autoCommit } from './git.js';
|
|
28
|
+
import { buildNotificationMessage, sendNotification } from './notify.js';
|
|
29
|
+
import { collectDashboardData, formatDashboard } from './dashboard.js';
|
|
30
|
+
import { generateDocs, writeDocs } from '../doc-gen/index.js';
|
|
31
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
32
|
+
const __dirname = dirname(__filename);
|
|
33
|
+
export function createProgram() {
|
|
34
|
+
const pkg = JSON.parse(readFileSync(resolve(__dirname, '../../package.json'), 'utf-8'));
|
|
35
|
+
const program = new Command();
|
|
36
|
+
program
|
|
37
|
+
.name('prodara')
|
|
38
|
+
.description('The Prodara compiler — compile .prd specifications into a validated Product Graph')
|
|
39
|
+
.version(pkg.version);
|
|
40
|
+
// -----------------------------------------------------------------------
|
|
41
|
+
// build (default command)
|
|
42
|
+
// -----------------------------------------------------------------------
|
|
43
|
+
program
|
|
44
|
+
.command('build', { isDefault: true })
|
|
45
|
+
.description('Full build pipeline: compile → workflow → review → verify')
|
|
46
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
47
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
48
|
+
.option('--headless', 'Use API driver instead of prompt files')
|
|
49
|
+
.option('--no-implement', 'Skip implementation phase')
|
|
50
|
+
.option('--no-review', 'Skip review phase')
|
|
51
|
+
.option('--max-review-loops <n>', 'Override max review iterations', parseInt)
|
|
52
|
+
.option('--auto-clarify', 'Override ambiguity threshold to low')
|
|
53
|
+
.option('--auto-commit', 'Auto-commit changes after successful build')
|
|
54
|
+
.option('--notify', 'Send desktop notification on build completion')
|
|
55
|
+
.option('--party', 'Run multi-agent party mode review')
|
|
56
|
+
.action((path, opts) => {
|
|
57
|
+
const root = resolve(path);
|
|
58
|
+
registerShutdownHandlers();
|
|
59
|
+
setActiveRoot(root);
|
|
60
|
+
const { config: baseConfig } = loadConfig(root);
|
|
61
|
+
// Apply CLI overrides to config
|
|
62
|
+
const config = applyCliOverrides(baseConfig, opts);
|
|
63
|
+
const pipelineOpts = {
|
|
64
|
+
headless: opts.headless ?? false,
|
|
65
|
+
noImplement: opts.implement === false,
|
|
66
|
+
noReview: opts.review === false,
|
|
67
|
+
onProgress: (phase, index, total) => {
|
|
68
|
+
if (opts.format !== 'json') {
|
|
69
|
+
process.stderr.write(`[${index + 1}/${total}] ${phase}...\n`);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
const result = runPipeline(root, config, pipelineOpts);
|
|
74
|
+
if (opts.format === 'json') {
|
|
75
|
+
process.stdout.write(JSON.stringify({
|
|
76
|
+
status: result.status,
|
|
77
|
+
phases: result.phases.map((p) => ({ phase: p.phase, status: p.status, detail: p.detail, duration_ms: p.duration_ms })),
|
|
78
|
+
duration_ms: result.duration_ms,
|
|
79
|
+
}, null, 2) + '\n');
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
for (const p of result.phases) {
|
|
83
|
+
const icon = p.status === 'ok' ? '✓' : p.status === 'warn' ? '⚠' : p.status === 'error' ? '✗' : '○';
|
|
84
|
+
process.stdout.write(` ${icon} ${p.phase}: ${p.detail}\n`);
|
|
85
|
+
}
|
|
86
|
+
process.stdout.write(`\nBuild ${result.status} (${result.duration_ms}ms)\n`);
|
|
87
|
+
}
|
|
88
|
+
clearActiveRoot();
|
|
89
|
+
// Auto-commit after successful build
|
|
90
|
+
if (opts.autoCommit && result.status === 'success') {
|
|
91
|
+
/* v8 ignore next -- graph always exists when status is success */
|
|
92
|
+
const hash = autoCommit(root, result.graph?.product.name ?? 'unknown', result.phases.length);
|
|
93
|
+
if (hash && opts.format !== 'json') {
|
|
94
|
+
process.stdout.write(`Auto-committed: ${hash}\n`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Desktop notification
|
|
98
|
+
if (opts.notify) {
|
|
99
|
+
const msg = buildNotificationMessage(
|
|
100
|
+
/* v8 ignore next -- graph always exists when status is success */
|
|
101
|
+
result.graph?.product.name ?? 'unknown', result.status === 'success', result.phases.filter(p => p.status === 'error').length);
|
|
102
|
+
sendNotification(msg.title, msg.message).catch(() => { });
|
|
103
|
+
}
|
|
104
|
+
process.exitCode = result.status === 'success' ? 0 : 1;
|
|
105
|
+
});
|
|
106
|
+
// -----------------------------------------------------------------------
|
|
107
|
+
// init
|
|
108
|
+
// -----------------------------------------------------------------------
|
|
109
|
+
program
|
|
110
|
+
.command('init')
|
|
111
|
+
.description('Scaffold a new Prodara project')
|
|
112
|
+
.argument('[path]', 'Directory to initialize', '.')
|
|
113
|
+
.option('--name <name>', 'Product name', 'my_app')
|
|
114
|
+
.option('--template <template>', 'Starter template: minimal | saas | marketplace | internal-tool | api')
|
|
115
|
+
.option('--ai <agent>', 'Configure AI agent slash commands (e.g. copilot, claude, cursor)')
|
|
116
|
+
.option('--ai-commands-dir <dir>', 'Custom directory for slash commands (use with --ai generic)')
|
|
117
|
+
.action((path, opts) => {
|
|
118
|
+
const root = resolve(path);
|
|
119
|
+
const appPrd = join(root, 'app.prd');
|
|
120
|
+
const configFile = join(root, CONFIG_FILENAME);
|
|
121
|
+
const prodaraDir = join(root, '.prodara');
|
|
122
|
+
if (existsSync(appPrd)) {
|
|
123
|
+
process.stderr.write(`Already initialized: ${appPrd} exists\n`);
|
|
124
|
+
process.exitCode = 1;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
mkdirSync(root, { recursive: true });
|
|
128
|
+
mkdirSync(prodaraDir, { recursive: true });
|
|
129
|
+
mkdirSync(join(prodaraDir, 'runs'), { recursive: true });
|
|
130
|
+
mkdirSync(join(prodaraDir, 'reviewers'), { recursive: true });
|
|
131
|
+
if (opts.template) {
|
|
132
|
+
const tmpl = getStarterTemplate(opts.template, opts.name);
|
|
133
|
+
if (!tmpl) {
|
|
134
|
+
const available = listStarterTemplates().map(t => t.name).join(', ');
|
|
135
|
+
process.stderr.write(`Unknown template: ${opts.template}\n`);
|
|
136
|
+
process.stderr.write(`Available templates: ${available}\n`);
|
|
137
|
+
process.exitCode = 1;
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
for (const f of tmpl.files) {
|
|
141
|
+
const filePath = join(root, f.path);
|
|
142
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
143
|
+
writeFileSync(filePath, f.content, 'utf-8');
|
|
144
|
+
}
|
|
145
|
+
process.stdout.write(`Initialized Prodara project in ${root} (template: ${tmpl.name})\n`);
|
|
146
|
+
for (const f of tmpl.files) {
|
|
147
|
+
process.stdout.write(` Created ${f.path}\n`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
writeFileSync(appPrd, `product ${opts.name} {
|
|
152
|
+
title: "${opts.name.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase())}"
|
|
153
|
+
version: "0.1.0"
|
|
154
|
+
modules: [core]
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
module core {
|
|
158
|
+
|
|
159
|
+
entity item {
|
|
160
|
+
id: uuid
|
|
161
|
+
title: string
|
|
162
|
+
done: boolean = false
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
`, 'utf-8');
|
|
167
|
+
process.stdout.write(`Initialized Prodara project in ${root}\n`);
|
|
168
|
+
process.stdout.write(` Created app.prd\n`);
|
|
169
|
+
}
|
|
170
|
+
writeFileSync(configFile, JSON.stringify({
|
|
171
|
+
phases: {},
|
|
172
|
+
reviewFix: { maxIterations: 3 },
|
|
173
|
+
reviewers: {},
|
|
174
|
+
validation: { lint: null, typecheck: null, test: null, build: null },
|
|
175
|
+
audit: { enabled: true, path: '.prodara/runs/' },
|
|
176
|
+
}, null, 2) + '\n', 'utf-8');
|
|
177
|
+
process.stdout.write(` Created ${CONFIG_FILENAME}\n`);
|
|
178
|
+
process.stdout.write(` Created .prodara/\n`);
|
|
179
|
+
// Slash command generation
|
|
180
|
+
if (opts.ai) {
|
|
181
|
+
if (!isValidAgentId(opts.ai)) {
|
|
182
|
+
const supported = listSupportedAgents().join(', ');
|
|
183
|
+
process.stderr.write(`Unknown AI agent: ${opts.ai}\n`);
|
|
184
|
+
process.stderr.write(`Supported agents: ${supported}\n`);
|
|
185
|
+
process.exitCode = 1;
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const agentId = opts.ai;
|
|
189
|
+
if (agentId === 'generic' && !opts.aiCommandsDir) {
|
|
190
|
+
process.stderr.write(`--ai generic requires --ai-commands-dir <dir>\n`);
|
|
191
|
+
process.exitCode = 1;
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const commands = generateSlashCommands(agentId, root, opts.name, opts.aiCommandsDir);
|
|
195
|
+
writeSlashCommands(commands);
|
|
196
|
+
const agentConfig = getAgentConfig(agentId);
|
|
197
|
+
/* v8 ignore next -- triple fallback for command dir */
|
|
198
|
+
const commandsDir = opts.aiCommandsDir ?? agentConfig?.commandsDir ?? '.ai/commands';
|
|
199
|
+
process.stdout.write(` Created slash commands in ${commandsDir}/\n`);
|
|
200
|
+
for (const cmd of commands) {
|
|
201
|
+
const rel = relative(root, cmd.path);
|
|
202
|
+
process.stdout.write(` ${rel}\n`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
process.stdout.write(`\nRun \`prodara build\` to compile.\n`);
|
|
206
|
+
process.exitCode = 0;
|
|
207
|
+
});
|
|
208
|
+
// -----------------------------------------------------------------------
|
|
209
|
+
// validate
|
|
210
|
+
// -----------------------------------------------------------------------
|
|
211
|
+
program
|
|
212
|
+
.command('validate')
|
|
213
|
+
.description('Parse and validate .prd files without building a graph')
|
|
214
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
215
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
216
|
+
.action((path, opts) => {
|
|
217
|
+
const root = resolve(path);
|
|
218
|
+
const result = compile(root, { stopAfter: 'validate' });
|
|
219
|
+
outputDiagnostics(result.diagnostics, opts.format);
|
|
220
|
+
process.exitCode = result.diagnostics.hasErrors ? 1 : 0;
|
|
221
|
+
});
|
|
222
|
+
// -----------------------------------------------------------------------
|
|
223
|
+
// graph
|
|
224
|
+
// -----------------------------------------------------------------------
|
|
225
|
+
program
|
|
226
|
+
.command('graph')
|
|
227
|
+
.description('Compile .prd files and output the Product Graph')
|
|
228
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
229
|
+
.option('--format <format>', 'Output format: human | json', 'json')
|
|
230
|
+
.option('--output <file>', 'Write graph to file instead of stdout')
|
|
231
|
+
.action((path, opts) => {
|
|
232
|
+
const root = resolve(path);
|
|
233
|
+
const result = compile(root, { stopAfter: 'graph' });
|
|
234
|
+
if (result.diagnostics.hasErrors) {
|
|
235
|
+
outputDiagnostics(result.diagnostics, opts.format === 'json' ? 'json' : 'human');
|
|
236
|
+
process.exitCode = 1;
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (result.graphJson) {
|
|
240
|
+
if (opts.output) {
|
|
241
|
+
writeFileSync(resolve(opts.output), result.graphJson, 'utf-8');
|
|
242
|
+
if (opts.format !== 'json') {
|
|
243
|
+
process.stderr.write(`Graph written to ${opts.output}\n`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
process.stdout.write(result.graphJson + '\n');
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (result.diagnostics.warnings.length > 0) {
|
|
251
|
+
outputDiagnostics(result.diagnostics, opts.format === 'json' ? 'json' : 'human');
|
|
252
|
+
}
|
|
253
|
+
process.exitCode = 0;
|
|
254
|
+
});
|
|
255
|
+
// -----------------------------------------------------------------------
|
|
256
|
+
// plan
|
|
257
|
+
// -----------------------------------------------------------------------
|
|
258
|
+
program
|
|
259
|
+
.command('plan')
|
|
260
|
+
.description('Compile and produce an incremental plan')
|
|
261
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
262
|
+
.option('--format <format>', 'Output format: human | json', 'json')
|
|
263
|
+
.action((path, opts) => {
|
|
264
|
+
const root = resolve(path);
|
|
265
|
+
const result = compile(root, { stopAfter: 'plan' });
|
|
266
|
+
if (result.diagnostics.hasErrors) {
|
|
267
|
+
outputDiagnostics(result.diagnostics, opts.format === 'json' ? 'json' : 'human');
|
|
268
|
+
process.exitCode = 1;
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (result.planJson) {
|
|
272
|
+
process.stdout.write(result.planJson + '\n');
|
|
273
|
+
}
|
|
274
|
+
process.exitCode = 0;
|
|
275
|
+
});
|
|
276
|
+
// -----------------------------------------------------------------------
|
|
277
|
+
// test
|
|
278
|
+
// -----------------------------------------------------------------------
|
|
279
|
+
program
|
|
280
|
+
.command('test')
|
|
281
|
+
.description('Run spec tests defined in .prd files')
|
|
282
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
283
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
284
|
+
.action((path, opts) => {
|
|
285
|
+
const root = resolve(path);
|
|
286
|
+
const result = compile(root, { stopAfter: 'test' });
|
|
287
|
+
if (result.testResults) {
|
|
288
|
+
if (opts.format === 'json') {
|
|
289
|
+
process.stdout.write(JSON.stringify(result.testResults, null, 2) + '\n');
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
const r = result.testResults;
|
|
293
|
+
process.stdout.write(`Tests: ${r.totalPassed} passed, ${r.totalFailed} failed\n`);
|
|
294
|
+
for (const t of r.results) {
|
|
295
|
+
const icon = t.passed ? '✓' : '✗';
|
|
296
|
+
process.stdout.write(` ${icon} ${t.name}\n`);
|
|
297
|
+
for (const f of t.failures) {
|
|
298
|
+
process.stdout.write(` ${f}\n`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (result.diagnostics.hasErrors) {
|
|
304
|
+
outputDiagnostics(result.diagnostics, opts.format === 'json' ? 'json' : 'human');
|
|
305
|
+
process.exitCode = 1;
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
process.exitCode = result.testResults?.totalFailed ? 1 : 0;
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
// -----------------------------------------------------------------------
|
|
312
|
+
// diff
|
|
313
|
+
// -----------------------------------------------------------------------
|
|
314
|
+
program
|
|
315
|
+
.command('diff')
|
|
316
|
+
.description('Show incremental spec (diff) between current and previous graph')
|
|
317
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
318
|
+
.option('--format <format>', 'Output format: human | json', 'json')
|
|
319
|
+
.option('--semantic', 'Show human-readable semantic diff summary')
|
|
320
|
+
.action((path, opts) => {
|
|
321
|
+
const root = resolve(path);
|
|
322
|
+
const result = compile(root, { stopAfter: 'plan', writeBuild: false });
|
|
323
|
+
if (result.diagnostics.hasErrors || !result.graph || !result.plan) {
|
|
324
|
+
outputDiagnostics(result.diagnostics, opts.format === 'json' ? 'json' : 'human');
|
|
325
|
+
process.exitCode = 1;
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
if (opts.semantic) {
|
|
329
|
+
const prevGraph = readPreviousGraph(root);
|
|
330
|
+
if (!prevGraph) {
|
|
331
|
+
process.stdout.write('No previous graph found — nothing to diff.\n');
|
|
332
|
+
process.exitCode = 0;
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const semDiff = semanticDiff(prevGraph, result.graph);
|
|
336
|
+
if (opts.format === 'json') {
|
|
337
|
+
process.stdout.write(JSON.stringify(semDiff, null, 2) + '\n');
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
process.stdout.write(formatSemanticDiffHuman(semDiff) + '\n');
|
|
341
|
+
}
|
|
342
|
+
process.exitCode = 0;
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
const spec = buildIncrementalSpec(result.plan, result.graph);
|
|
346
|
+
if (opts.format === 'json') {
|
|
347
|
+
process.stdout.write(serializeIncrementalSpec(spec) + '\n');
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
const s = spec.summary;
|
|
351
|
+
process.stdout.write(`Incremental Spec Summary:\n`);
|
|
352
|
+
process.stdout.write(` Added: ${s.addedCount}\n`);
|
|
353
|
+
process.stdout.write(` Removed: ${s.removedCount}\n`);
|
|
354
|
+
process.stdout.write(` Modified: ${s.modifiedCount}\n`);
|
|
355
|
+
process.stdout.write(` Impacted: ${s.impactedCount}\n`);
|
|
356
|
+
process.stdout.write(` Tasks: ${s.taskCount}\n`);
|
|
357
|
+
if (s.affectedModules.length > 0) {
|
|
358
|
+
process.stdout.write(` Modules: ${s.affectedModules.join(', ')}\n`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
process.exitCode = 0;
|
|
362
|
+
});
|
|
363
|
+
// -----------------------------------------------------------------------
|
|
364
|
+
// doctor
|
|
365
|
+
// -----------------------------------------------------------------------
|
|
366
|
+
program
|
|
367
|
+
.command('doctor')
|
|
368
|
+
.description('Check compiler installation and workspace health')
|
|
369
|
+
.argument('[path]', 'Directory to check', '.')
|
|
370
|
+
.action((path) => {
|
|
371
|
+
const root = resolve(path);
|
|
372
|
+
const files = discoverFiles(root);
|
|
373
|
+
process.stdout.write(`Prodara Compiler v${pkg.version}\n`);
|
|
374
|
+
process.stdout.write(`Node.js ${process.version}\n`);
|
|
375
|
+
process.stdout.write(`Workspace: ${root}\n`);
|
|
376
|
+
process.stdout.write(`Found ${files.length} .prd file(s)\n`);
|
|
377
|
+
for (const f of files) {
|
|
378
|
+
process.stdout.write(` ${f}\n`);
|
|
379
|
+
}
|
|
380
|
+
process.exitCode = 0;
|
|
381
|
+
});
|
|
382
|
+
// -----------------------------------------------------------------------
|
|
383
|
+
// drift
|
|
384
|
+
// -----------------------------------------------------------------------
|
|
385
|
+
program
|
|
386
|
+
.command('drift')
|
|
387
|
+
.description('Detect whether .prd specifications have drifted from last build')
|
|
388
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
389
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
390
|
+
.action((path, opts) => {
|
|
391
|
+
const root = resolve(path);
|
|
392
|
+
const result = detectDrift(root);
|
|
393
|
+
if (opts.format === 'json') {
|
|
394
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
process.stdout.write(formatDriftHuman(result) + '\n');
|
|
398
|
+
}
|
|
399
|
+
process.exitCode = result.status === 'drifted' ? 1 : 0;
|
|
400
|
+
});
|
|
401
|
+
// -----------------------------------------------------------------------
|
|
402
|
+
// watch
|
|
403
|
+
// -----------------------------------------------------------------------
|
|
404
|
+
program
|
|
405
|
+
.command('watch')
|
|
406
|
+
.description('Watch .prd files and re-compile on changes')
|
|
407
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
408
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
409
|
+
.action((path, opts) => {
|
|
410
|
+
const root = resolve(path);
|
|
411
|
+
registerShutdownHandlers();
|
|
412
|
+
setActiveRoot(root);
|
|
413
|
+
process.stdout.write(`Watching ${root} for .prd changes...\n`);
|
|
414
|
+
const runBuild = () => {
|
|
415
|
+
const { config } = loadConfig(root);
|
|
416
|
+
const result = compile(root, { stopAfter: 'test' });
|
|
417
|
+
outputDiagnostics(result.diagnostics, opts.format);
|
|
418
|
+
if (!result.diagnostics.hasErrors) {
|
|
419
|
+
process.stdout.write('Build OK\n');
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
// Initial build
|
|
423
|
+
runBuild();
|
|
424
|
+
// Watch for changes
|
|
425
|
+
try {
|
|
426
|
+
/* v8 ignore start */
|
|
427
|
+
const watcher = watch(root, { recursive: true }, (_event, filename) => {
|
|
428
|
+
if (filename && filename.endsWith('.prd')) {
|
|
429
|
+
process.stdout.write(`\nChanged: ${filename}\n`);
|
|
430
|
+
runBuild();
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
// Keep the process alive
|
|
434
|
+
process.on('SIGINT', () => {
|
|
435
|
+
watcher.close();
|
|
436
|
+
clearActiveRoot();
|
|
437
|
+
process.exit(130);
|
|
438
|
+
});
|
|
439
|
+
/* v8 ignore stop */
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
process.stderr.write('Error: fs.watch not available\n');
|
|
443
|
+
process.exitCode = 1;
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
// -----------------------------------------------------------------------
|
|
447
|
+
// explain
|
|
448
|
+
// -----------------------------------------------------------------------
|
|
449
|
+
program
|
|
450
|
+
.command('explain')
|
|
451
|
+
.description('Explain a node in the product graph by ID (e.g. core.entity.user)')
|
|
452
|
+
.argument('<node-id>', 'Node ID to explain')
|
|
453
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
454
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
455
|
+
.action((nodeId, path, opts) => {
|
|
456
|
+
const root = resolve(path);
|
|
457
|
+
const result = compile(root, { stopAfter: 'graph', writeBuild: false });
|
|
458
|
+
if (result.diagnostics.hasErrors || !result.graph) {
|
|
459
|
+
/* v8 ignore next -- error-path format ternary */
|
|
460
|
+
outputDiagnostics(result.diagnostics, opts.format === 'json' ? 'json' : 'human');
|
|
461
|
+
process.exitCode = 1;
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
const explanation = explainNode(result.graph, nodeId);
|
|
465
|
+
if (!explanation) {
|
|
466
|
+
process.stderr.write(`Node not found: ${nodeId}\n`);
|
|
467
|
+
const allIds = collectAllNodeIds(result.graph);
|
|
468
|
+
if (allIds.size > 0) {
|
|
469
|
+
const matches = [...allIds].filter(id => id.includes(/* v8 ignore next -- pop() on non-empty array */ nodeId.split('.').pop() ?? ''));
|
|
470
|
+
if (matches.length > 0) {
|
|
471
|
+
process.stderr.write(`Did you mean: ${matches.slice(0, 5).join(', ')}?\n`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
process.exitCode = 1;
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
if (opts.format === 'json') {
|
|
478
|
+
process.stdout.write(JSON.stringify(explanation, null, 2) + '\n');
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
process.stdout.write(formatExplanation(explanation) + '\n');
|
|
482
|
+
}
|
|
483
|
+
process.exitCode = 0;
|
|
484
|
+
});
|
|
485
|
+
// -----------------------------------------------------------------------
|
|
486
|
+
// why
|
|
487
|
+
// -----------------------------------------------------------------------
|
|
488
|
+
program
|
|
489
|
+
.command('why')
|
|
490
|
+
.description('Explain why a diagnostic code was reported')
|
|
491
|
+
.argument('<code>', 'Diagnostic code (e.g. PRD1001)')
|
|
492
|
+
.action((code) => {
|
|
493
|
+
const info = getDiagnosticInfo(code);
|
|
494
|
+
if (!info) {
|
|
495
|
+
process.stderr.write(`Unknown diagnostic code: ${code}\n`);
|
|
496
|
+
process.exitCode = 1;
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
process.stdout.write(`${code}: ${info.title}\n`);
|
|
500
|
+
process.stdout.write(` Phase: ${info.phase}\n`);
|
|
501
|
+
process.stdout.write(` Severity: ${info.severity}\n`);
|
|
502
|
+
process.stdout.write(` ${info.description}\n`);
|
|
503
|
+
process.exitCode = 0;
|
|
504
|
+
});
|
|
505
|
+
// -----------------------------------------------------------------------
|
|
506
|
+
// propose
|
|
507
|
+
// -----------------------------------------------------------------------
|
|
508
|
+
program
|
|
509
|
+
.command('propose')
|
|
510
|
+
.description('Create a new change proposal')
|
|
511
|
+
.argument('<description>', 'Brief description of the proposed change')
|
|
512
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
513
|
+
.action((description, path) => {
|
|
514
|
+
const root = resolve(path);
|
|
515
|
+
try {
|
|
516
|
+
const proposal = createProposal(description, root);
|
|
517
|
+
process.stdout.write(`Created change proposal: ${proposal.name}\n`);
|
|
518
|
+
process.stdout.write(` Directory: ${relative(root, proposal.path)}/\n`);
|
|
519
|
+
process.stdout.write(` delta.prd: Edit to define specification changes\n`);
|
|
520
|
+
process.stdout.write(` proposal.md: Document motivation and scope\n`);
|
|
521
|
+
process.stdout.write(` tasks.md: Track implementation tasks\n`);
|
|
522
|
+
process.exitCode = 0;
|
|
523
|
+
}
|
|
524
|
+
catch (e) {
|
|
525
|
+
process.stderr.write(`${e.message}\n`);
|
|
526
|
+
process.exitCode = 1;
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
// -----------------------------------------------------------------------
|
|
530
|
+
// changes
|
|
531
|
+
// -----------------------------------------------------------------------
|
|
532
|
+
program
|
|
533
|
+
.command('changes')
|
|
534
|
+
.description('List active change proposals')
|
|
535
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
536
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
537
|
+
.action((path, opts) => {
|
|
538
|
+
const root = resolve(path);
|
|
539
|
+
const proposals = listProposals(root);
|
|
540
|
+
if (opts.format === 'json') {
|
|
541
|
+
process.stdout.write(JSON.stringify(proposals, null, 2) + '\n');
|
|
542
|
+
}
|
|
543
|
+
else if (proposals.length === 0) {
|
|
544
|
+
process.stdout.write('No active change proposals.\n');
|
|
545
|
+
process.stdout.write('Run `prodara propose "<description>"` to create one.\n');
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
process.stdout.write(`Active change proposals (${proposals.length}):\n\n`);
|
|
549
|
+
for (const p of proposals) {
|
|
550
|
+
/* v8 ignore next -- proposal status ternary */
|
|
551
|
+
const icon = p.status === 'proposed' ? '○' : p.status === 'in-progress' ? '◐' : '●';
|
|
552
|
+
process.stdout.write(` ${icon} ${p.name} [${p.status}]\n`);
|
|
553
|
+
process.stdout.write(` ${p.description}\n`);
|
|
554
|
+
process.stdout.write(` Created: ${p.created}\n\n`);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
process.exitCode = 0;
|
|
558
|
+
});
|
|
559
|
+
// -----------------------------------------------------------------------
|
|
560
|
+
// apply
|
|
561
|
+
// -----------------------------------------------------------------------
|
|
562
|
+
program
|
|
563
|
+
.command('apply')
|
|
564
|
+
.description('Apply a change proposal (compile its delta.prd)')
|
|
565
|
+
.argument('<change>', 'Name of the change proposal')
|
|
566
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
567
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
568
|
+
.action((change, path, opts) => {
|
|
569
|
+
const root = resolve(path);
|
|
570
|
+
try {
|
|
571
|
+
const proposal = applyProposal(change, root);
|
|
572
|
+
const deltaPath = join(proposal.path, 'delta.prd');
|
|
573
|
+
if (!existsSync(deltaPath)) {
|
|
574
|
+
process.stderr.write(`No delta.prd found in proposal: ${change}\n`);
|
|
575
|
+
process.exitCode = 1;
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
// Compile the project to validate delta alongside main specs
|
|
579
|
+
const result = compile(root, { stopAfter: 'graph', writeBuild: false });
|
|
580
|
+
if (result.diagnostics.hasErrors) {
|
|
581
|
+
/* v8 ignore next -- error-path format ternary */
|
|
582
|
+
outputDiagnostics(result.diagnostics, opts.format === 'json' ? 'json' : 'human');
|
|
583
|
+
process.exitCode = 1;
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
process.stdout.write(`Applied change proposal: ${proposal.name}\n`);
|
|
587
|
+
process.stdout.write(` Status: ${proposal.status}\n`);
|
|
588
|
+
if (result.graph) {
|
|
589
|
+
const prevGraph = readPreviousGraph(root);
|
|
590
|
+
if (prevGraph) {
|
|
591
|
+
const diff = semanticDiff(prevGraph, result.graph);
|
|
592
|
+
if (opts.format === 'json') {
|
|
593
|
+
process.stdout.write(JSON.stringify(diff, null, 2) + '\n');
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
process.stdout.write(formatSemanticDiffHuman(diff) + '\n');
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
process.exitCode = 0;
|
|
601
|
+
}
|
|
602
|
+
catch (e) {
|
|
603
|
+
process.stderr.write(`${e.message}\n`);
|
|
604
|
+
process.exitCode = 1;
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
// -----------------------------------------------------------------------
|
|
608
|
+
// archive
|
|
609
|
+
// -----------------------------------------------------------------------
|
|
610
|
+
program
|
|
611
|
+
.command('archive')
|
|
612
|
+
.description('Archive a completed change proposal')
|
|
613
|
+
.argument('<change>', 'Name of the change proposal')
|
|
614
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
615
|
+
.action((change, path) => {
|
|
616
|
+
const root = resolve(path);
|
|
617
|
+
try {
|
|
618
|
+
const proposal = archiveProposal(change, root);
|
|
619
|
+
process.stdout.write(`Archived change proposal: ${proposal.name}\n`);
|
|
620
|
+
process.stdout.write(` Moved to: ${relative(root, proposal.path)}/\n`);
|
|
621
|
+
process.exitCode = 0;
|
|
622
|
+
}
|
|
623
|
+
catch (e) {
|
|
624
|
+
process.stderr.write(`${e.message}\n`);
|
|
625
|
+
process.exitCode = 1;
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
// -----------------------------------------------------------------------
|
|
629
|
+
// clarify
|
|
630
|
+
// -----------------------------------------------------------------------
|
|
631
|
+
program
|
|
632
|
+
.command('clarify')
|
|
633
|
+
.description('Run the clarify phase to identify specification ambiguities')
|
|
634
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
635
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
636
|
+
.option('--auto', 'Auto-resolve high-confidence questions')
|
|
637
|
+
.option('--output <file>', 'Write questions to a file')
|
|
638
|
+
.action(async (path, opts) => {
|
|
639
|
+
const root = resolve(path);
|
|
640
|
+
const result = compile(root, { stopAfter: 'plan', writeBuild: false });
|
|
641
|
+
if (result.diagnostics.hasErrors || !result.graph || !result.plan) {
|
|
642
|
+
/* v8 ignore next -- error-path format ternary */
|
|
643
|
+
outputDiagnostics(result.diagnostics, opts.format === 'json' ? 'json' : 'human');
|
|
644
|
+
process.exitCode = 1;
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
const { config } = loadConfig(root);
|
|
648
|
+
const spec = buildIncrementalSpec(result.plan, result.graph);
|
|
649
|
+
const { runClarifyPhase, autoResolveClarifications } = await import('../workflow/clarify.js');
|
|
650
|
+
const clarifyResult = runClarifyPhase(result.graph, spec, config.phases.clarify);
|
|
651
|
+
/* v8 ignore next -- clarify always returns data */
|
|
652
|
+
let questions = clarifyResult.data?.questions ?? [];
|
|
653
|
+
if (opts.auto && clarifyResult.data) {
|
|
654
|
+
const resolved = autoResolveClarifications(clarifyResult.data.questions, config.phases.clarify.ambiguityThreshold, result.graph);
|
|
655
|
+
questions = resolved.needsInput;
|
|
656
|
+
if (opts.format !== 'json') {
|
|
657
|
+
process.stdout.write(`Auto-resolved ${resolved.autoResolved.length} question(s)\n\n`);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
if (opts.format === 'json') {
|
|
661
|
+
const output = JSON.stringify({ questions, total: questions.length }, null, 2);
|
|
662
|
+
if (opts.output) {
|
|
663
|
+
writeFileSync(resolve(opts.output), output + '\n', 'utf-8');
|
|
664
|
+
process.stdout.write(`Questions written to ${opts.output}\n`);
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
process.stdout.write(output + '\n');
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
else {
|
|
671
|
+
if (questions.length === 0) {
|
|
672
|
+
process.stdout.write('No ambiguities found in the specification.\n');
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
process.stdout.write(`Found ${questions.length} ambiguity question(s):\n\n`);
|
|
676
|
+
for (let i = 0; i < questions.length; i++) {
|
|
677
|
+
const q = questions[i];
|
|
678
|
+
process.stdout.write(` ${i + 1}. [${q.category}] ${q.question}\n`);
|
|
679
|
+
process.stdout.write(` Priority: ${q.priority} | Confidence: ${q.confidence}\n`);
|
|
680
|
+
process.stdout.write('\n');
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
if (opts.output) {
|
|
684
|
+
const output = questions.map((q, i) => `${i + 1}. [${q.category}] ${q.question}`).join('\n');
|
|
685
|
+
writeFileSync(resolve(opts.output), output + '\n', 'utf-8');
|
|
686
|
+
process.stdout.write(`Questions written to ${opts.output}\n`);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
process.exitCode = 0;
|
|
690
|
+
});
|
|
691
|
+
// -----------------------------------------------------------------------
|
|
692
|
+
// checklist
|
|
693
|
+
// -----------------------------------------------------------------------
|
|
694
|
+
program
|
|
695
|
+
.command('checklist')
|
|
696
|
+
.description('Generate a quality validation checklist')
|
|
697
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
698
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
699
|
+
.option('--output <file>', 'Write checklist to a file')
|
|
700
|
+
.action((path, opts) => {
|
|
701
|
+
const root = resolve(path);
|
|
702
|
+
const result = compile(root, { stopAfter: 'graph', writeBuild: false });
|
|
703
|
+
if (result.diagnostics.hasErrors || !result.graph) {
|
|
704
|
+
/* v8 ignore next -- error-path format ternary */
|
|
705
|
+
outputDiagnostics(result.diagnostics, opts.format === 'json' ? 'json' : 'human');
|
|
706
|
+
process.exitCode = 1;
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
const { config } = loadConfig(root);
|
|
710
|
+
const checklist = generateChecklist(result.graph, config);
|
|
711
|
+
if (opts.format === 'json') {
|
|
712
|
+
const output = JSON.stringify(checklist, null, 2);
|
|
713
|
+
if (opts.output) {
|
|
714
|
+
writeFileSync(resolve(opts.output), output + '\n', 'utf-8');
|
|
715
|
+
process.stdout.write(`Checklist written to ${opts.output}\n`);
|
|
716
|
+
}
|
|
717
|
+
else {
|
|
718
|
+
process.stdout.write(output + '\n');
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
const output = formatChecklistHuman(checklist);
|
|
723
|
+
if (opts.output) {
|
|
724
|
+
writeFileSync(resolve(opts.output), output + '\n', 'utf-8');
|
|
725
|
+
process.stdout.write(`Checklist written to ${opts.output}\n`);
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
process.stdout.write(output + '\n');
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
process.exitCode = 0;
|
|
732
|
+
});
|
|
733
|
+
// -----------------------------------------------------------------------
|
|
734
|
+
// analyze
|
|
735
|
+
// -----------------------------------------------------------------------
|
|
736
|
+
program
|
|
737
|
+
.command('analyze')
|
|
738
|
+
.description('Run cross-spec consistency and coverage analysis')
|
|
739
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
740
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
741
|
+
.option('--threshold <n>', 'Cross-module coupling threshold', parseInt)
|
|
742
|
+
.action((path, opts) => {
|
|
743
|
+
const root = resolve(path);
|
|
744
|
+
const result = compile(root, { stopAfter: 'graph', writeBuild: false });
|
|
745
|
+
if (result.diagnostics.hasErrors || !result.graph) {
|
|
746
|
+
/* v8 ignore next -- error-path format ternary */
|
|
747
|
+
outputDiagnostics(result.diagnostics, opts.format === 'json' ? 'json' : 'human');
|
|
748
|
+
process.exitCode = 1;
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
const analysis = analyzeGraph(result.graph, { couplingThreshold: opts.threshold ?? 5 });
|
|
752
|
+
if (opts.format === 'json') {
|
|
753
|
+
process.stdout.write(JSON.stringify(analysis, null, 2) + '\n');
|
|
754
|
+
}
|
|
755
|
+
else {
|
|
756
|
+
process.stdout.write(formatAnalysisHuman(analysis) + '\n');
|
|
757
|
+
}
|
|
758
|
+
process.exitCode = 0;
|
|
759
|
+
});
|
|
760
|
+
// -----------------------------------------------------------------------
|
|
761
|
+
// onboard
|
|
762
|
+
// -----------------------------------------------------------------------
|
|
763
|
+
program
|
|
764
|
+
.command('onboard')
|
|
765
|
+
.description('Generate a guided project walkthrough for new team members')
|
|
766
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
767
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
768
|
+
.option('--output <file>', 'Write onboarding doc to a file')
|
|
769
|
+
.action((path, opts) => {
|
|
770
|
+
const root = resolve(path);
|
|
771
|
+
const result = compile(root, { stopAfter: 'graph', writeBuild: false });
|
|
772
|
+
if (result.diagnostics.hasErrors || !result.graph) {
|
|
773
|
+
/* v8 ignore next -- error-path format ternary */
|
|
774
|
+
outputDiagnostics(result.diagnostics, opts.format === 'json' ? 'json' : 'human');
|
|
775
|
+
process.exitCode = 1;
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
const graph = result.graph;
|
|
779
|
+
const getArray = (mod, key) =>
|
|
780
|
+
/* v8 ignore next -- modules always have array properties */
|
|
781
|
+
(Array.isArray(mod[key]) ? mod[key] : []);
|
|
782
|
+
const entityCount = graph.modules.reduce((sum, m) => sum + getArray(m, 'entities').length, 0);
|
|
783
|
+
const workflowCount = graph.modules.reduce((sum, m) => sum + getArray(m, 'workflows').length, 0);
|
|
784
|
+
const surfaceCount = graph.modules.reduce((sum, m) => sum + getArray(m, 'surfaces').length, 0);
|
|
785
|
+
if (opts.format === 'json') {
|
|
786
|
+
const data = {
|
|
787
|
+
product: graph.product.name,
|
|
788
|
+
version: graph.product.version,
|
|
789
|
+
modules: graph.modules.map(m => ({
|
|
790
|
+
name: m.name,
|
|
791
|
+
entities: getArray(m, 'entities').map(e => e.name),
|
|
792
|
+
workflows: getArray(m, 'workflows').map(w => w.name),
|
|
793
|
+
surfaces: getArray(m, 'surfaces').map(s => s.name),
|
|
794
|
+
})),
|
|
795
|
+
stats: { modules: graph.modules.length, entities: entityCount, workflows: workflowCount, surfaces: surfaceCount },
|
|
796
|
+
};
|
|
797
|
+
const output = JSON.stringify(data, null, 2);
|
|
798
|
+
if (opts.output) {
|
|
799
|
+
writeFileSync(resolve(opts.output), output + '\n', 'utf-8');
|
|
800
|
+
process.stdout.write(`Onboarding doc written to ${opts.output}\n`);
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
process.stdout.write(output + '\n');
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
else {
|
|
807
|
+
const lines = [];
|
|
808
|
+
lines.push(`# Welcome to ${graph.product.name}`);
|
|
809
|
+
lines.push('');
|
|
810
|
+
lines.push('## Product Overview');
|
|
811
|
+
lines.push('');
|
|
812
|
+
lines.push(`**${graph.product.name}** v${graph.product.version}`);
|
|
813
|
+
lines.push('');
|
|
814
|
+
lines.push(`## Modules (${graph.modules.length} module${ /* v8 ignore next -- singular module case */graph.modules.length !== 1 ? 's' : ''})`);
|
|
815
|
+
lines.push('');
|
|
816
|
+
for (const mod of graph.modules) {
|
|
817
|
+
lines.push(`### ${mod.name}`);
|
|
818
|
+
const ents = getArray(mod, 'entities');
|
|
819
|
+
const wfs = getArray(mod, 'workflows');
|
|
820
|
+
const surfs = getArray(mod, 'surfaces');
|
|
821
|
+
if (ents.length > 0)
|
|
822
|
+
lines.push(`- Entities: ${ents.map(e => e.name).join(', ')}`);
|
|
823
|
+
if (wfs.length > 0)
|
|
824
|
+
lines.push(`- Workflows: ${wfs.map(w => w.name).join(', ')}`);
|
|
825
|
+
if (surfs.length > 0)
|
|
826
|
+
lines.push(`- Surfaces: ${surfs.map(s => s.name).join(', ')}`);
|
|
827
|
+
lines.push('');
|
|
828
|
+
}
|
|
829
|
+
lines.push('## Architecture');
|
|
830
|
+
lines.push('');
|
|
831
|
+
lines.push(`- ${entityCount} entities, ${workflowCount} workflows, ${surfaceCount} surfaces`);
|
|
832
|
+
lines.push(`- ${graph.edges.length} relationships in the product graph`);
|
|
833
|
+
lines.push('');
|
|
834
|
+
lines.push('## Getting Started');
|
|
835
|
+
lines.push('');
|
|
836
|
+
lines.push('1. Run `prodara validate` to check specs');
|
|
837
|
+
lines.push('2. Run `prodara plan` to see the implementation plan');
|
|
838
|
+
lines.push('3. Run `prodara build` to compile and implement');
|
|
839
|
+
lines.push('4. Use `prodara explain <node-id>` to understand any graph node');
|
|
840
|
+
lines.push('');
|
|
841
|
+
const output = lines.join('\n');
|
|
842
|
+
if (opts.output) {
|
|
843
|
+
writeFileSync(resolve(opts.output), output + '\n', 'utf-8');
|
|
844
|
+
process.stdout.write(`Onboarding doc written to ${opts.output}\n`);
|
|
845
|
+
}
|
|
846
|
+
else {
|
|
847
|
+
process.stdout.write(output + '\n');
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
process.exitCode = 0;
|
|
851
|
+
});
|
|
852
|
+
// -----------------------------------------------------------------------
|
|
853
|
+
// history
|
|
854
|
+
// -----------------------------------------------------------------------
|
|
855
|
+
program
|
|
856
|
+
.command('history')
|
|
857
|
+
.description('Browse past build runs')
|
|
858
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
859
|
+
.option('--format <format>', 'Output format: human | json', 'human')
|
|
860
|
+
.option('--last <n>', 'Show last N builds', parseInt)
|
|
861
|
+
.option('--status <status>', 'Filter by outcome: success | failure')
|
|
862
|
+
.action(async (path, opts) => {
|
|
863
|
+
const root = resolve(path);
|
|
864
|
+
const { config } = loadConfig(root);
|
|
865
|
+
const { listAuditRecords } = await import('../audit/audit.js');
|
|
866
|
+
const recordPaths = listAuditRecords(root, config.audit);
|
|
867
|
+
let records = recordPaths
|
|
868
|
+
.map(p => JSON.parse(readFileSync(p, 'utf-8')))
|
|
869
|
+
.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
870
|
+
// Filter by status
|
|
871
|
+
if (opts.status) {
|
|
872
|
+
records = records.filter(r => r.outcome === opts.status);
|
|
873
|
+
}
|
|
874
|
+
// Limit results
|
|
875
|
+
const limit = opts.last ?? 10;
|
|
876
|
+
records = records.slice(0, limit);
|
|
877
|
+
if (opts.format === 'json') {
|
|
878
|
+
process.stdout.write(JSON.stringify(records, null, 2) + '\n');
|
|
879
|
+
}
|
|
880
|
+
else if (records.length === 0) {
|
|
881
|
+
process.stdout.write('No build history recorded.\n');
|
|
882
|
+
process.stdout.write('Run `prodara build` to create a build record.\n');
|
|
883
|
+
}
|
|
884
|
+
else {
|
|
885
|
+
process.stdout.write(`Build History (last ${records.length}):\n\n`);
|
|
886
|
+
for (const r of records) {
|
|
887
|
+
const icon = r.outcome === 'success' ? '✓' : '✗';
|
|
888
|
+
const date = new Date(r.timestamp).toLocaleString();
|
|
889
|
+
const phaseSummary = r.phases.map(p => `${p.name}:${p.status}`).join(' ');
|
|
890
|
+
process.stdout.write(` ${icon} ${date} — ${r.outcome}\n`);
|
|
891
|
+
if (phaseSummary) {
|
|
892
|
+
process.stdout.write(` Phases: ${phaseSummary}\n`);
|
|
893
|
+
}
|
|
894
|
+
process.stdout.write('\n');
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
process.exitCode = 0;
|
|
898
|
+
});
|
|
899
|
+
// ---------------------------------------------------------------------------
|
|
900
|
+
// Extension management
|
|
901
|
+
// ---------------------------------------------------------------------------
|
|
902
|
+
const ext = program
|
|
903
|
+
.command('extension')
|
|
904
|
+
.description('Manage Prodara extensions');
|
|
905
|
+
ext
|
|
906
|
+
.command('list')
|
|
907
|
+
.description('List installed extensions')
|
|
908
|
+
.argument('[path]', 'Project root directory', '.')
|
|
909
|
+
.action((path) => {
|
|
910
|
+
const root = resolve(path);
|
|
911
|
+
const extensions = listInstalledExtensions(root);
|
|
912
|
+
if (extensions.length === 0) {
|
|
913
|
+
process.stdout.write('No extensions installed.\n');
|
|
914
|
+
}
|
|
915
|
+
else {
|
|
916
|
+
process.stdout.write(`Installed extensions (${extensions.length}):\n\n`);
|
|
917
|
+
for (const ext of extensions) {
|
|
918
|
+
const caps = ext.manifest.capabilities.map(c => c.kind).join(', ');
|
|
919
|
+
process.stdout.write(` ${ext.manifest.name}@${ext.manifest.version} — ${ext.manifest.description}\n`);
|
|
920
|
+
process.stdout.write(` Capabilities: ${caps}\n\n`);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
process.exitCode = 0;
|
|
924
|
+
});
|
|
925
|
+
ext
|
|
926
|
+
.command('add')
|
|
927
|
+
.description('Install an extension from a manifest JSON file')
|
|
928
|
+
.argument('<manifest-path>', 'Path to prodara-extension.json')
|
|
929
|
+
.argument('[path]', 'Project root directory', '.')
|
|
930
|
+
.action((manifestPath, path) => {
|
|
931
|
+
const root = resolve(path);
|
|
932
|
+
const manifest = JSON.parse(readFileSync(resolve(manifestPath), 'utf-8'));
|
|
933
|
+
const installed = installExtension(root, manifest.name, manifest);
|
|
934
|
+
process.stdout.write(`Installed extension "${manifest.name}" at ${installed.path}\n`);
|
|
935
|
+
process.exitCode = 0;
|
|
936
|
+
});
|
|
937
|
+
ext
|
|
938
|
+
.command('remove')
|
|
939
|
+
.description('Remove an installed extension')
|
|
940
|
+
.argument('<name>', 'Extension name')
|
|
941
|
+
.argument('[path]', 'Project root directory', '.')
|
|
942
|
+
.action((name, path) => {
|
|
943
|
+
const root = resolve(path);
|
|
944
|
+
removeExtension(root, name);
|
|
945
|
+
process.stdout.write(`Removed extension "${name}".\n`);
|
|
946
|
+
process.exitCode = 0;
|
|
947
|
+
});
|
|
948
|
+
// ---------------------------------------------------------------------------
|
|
949
|
+
// Preset management
|
|
950
|
+
// ---------------------------------------------------------------------------
|
|
951
|
+
const pst = program
|
|
952
|
+
.command('preset')
|
|
953
|
+
.description('Manage Prodara presets');
|
|
954
|
+
pst
|
|
955
|
+
.command('list')
|
|
956
|
+
.description('List installed presets')
|
|
957
|
+
.argument('[path]', 'Project root directory', '.')
|
|
958
|
+
.action((path) => {
|
|
959
|
+
const root = resolve(path);
|
|
960
|
+
const presets = loadPresets(root);
|
|
961
|
+
if (presets.length === 0) {
|
|
962
|
+
process.stdout.write('No presets installed.\n');
|
|
963
|
+
}
|
|
964
|
+
else {
|
|
965
|
+
process.stdout.write(`Installed presets (${presets.length}):\n\n`);
|
|
966
|
+
for (const p of presets) {
|
|
967
|
+
process.stdout.write(` ${p.manifest.name}@${p.manifest.version} — ${p.manifest.description}\n`);
|
|
968
|
+
process.stdout.write(` Priority: ${p.priority}\n\n`);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
process.exitCode = 0;
|
|
972
|
+
});
|
|
973
|
+
pst
|
|
974
|
+
.command('add')
|
|
975
|
+
.description('Install a preset from a manifest JSON file')
|
|
976
|
+
.argument('<manifest-path>', 'Path to prodara-preset.json')
|
|
977
|
+
.argument('[path]', 'Project root directory', '.')
|
|
978
|
+
.action((manifestPath, path) => {
|
|
979
|
+
const root = resolve(path);
|
|
980
|
+
const manifest = JSON.parse(readFileSync(resolve(manifestPath), 'utf-8'));
|
|
981
|
+
const installed = installPreset(root, manifest.name, manifest);
|
|
982
|
+
process.stdout.write(`Installed preset "${manifest.name}" at ${installed.path}\n`);
|
|
983
|
+
process.exitCode = 0;
|
|
984
|
+
});
|
|
985
|
+
pst
|
|
986
|
+
.command('remove')
|
|
987
|
+
.description('Remove an installed preset')
|
|
988
|
+
.argument('<name>', 'Preset name')
|
|
989
|
+
.argument('[path]', 'Project root directory', '.')
|
|
990
|
+
.action((name, path) => {
|
|
991
|
+
const root = resolve(path);
|
|
992
|
+
removePreset(root, name);
|
|
993
|
+
process.stdout.write(`Removed preset "${name}".\n`);
|
|
994
|
+
process.exitCode = 0;
|
|
995
|
+
});
|
|
996
|
+
// ---------------------------------------------------------------------------
|
|
997
|
+
// docs
|
|
998
|
+
// ---------------------------------------------------------------------------
|
|
999
|
+
program
|
|
1000
|
+
.command('docs')
|
|
1001
|
+
.description('Generate human-readable markdown docs from .prd specifications')
|
|
1002
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
1003
|
+
.option('--output <dir>', 'Output directory (relative to project root)')
|
|
1004
|
+
.action((path, opts) => {
|
|
1005
|
+
const root = resolve(path);
|
|
1006
|
+
const result = compile(root, { stopAfter: 'graph', writeBuild: false });
|
|
1007
|
+
if (result.diagnostics.hasErrors || !result.graph) {
|
|
1008
|
+
outputDiagnostics(result.diagnostics, 'human');
|
|
1009
|
+
process.exitCode = 1;
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
const { config } = loadConfig(root);
|
|
1013
|
+
const docsConfig = opts.output
|
|
1014
|
+
? { ...config.docs, outputDir: opts.output }
|
|
1015
|
+
: config.docs;
|
|
1016
|
+
const files = generateDocs(result.graph, docsConfig, root);
|
|
1017
|
+
writeDocs(files, docsConfig.outputDir, root);
|
|
1018
|
+
process.stdout.write(`Generated ${files.length} doc file(s) in ${docsConfig.outputDir}/\n`);
|
|
1019
|
+
process.exitCode = 0;
|
|
1020
|
+
});
|
|
1021
|
+
// ---------------------------------------------------------------------------
|
|
1022
|
+
// Dashboard
|
|
1023
|
+
// ---------------------------------------------------------------------------
|
|
1024
|
+
program
|
|
1025
|
+
.command('dashboard')
|
|
1026
|
+
.description('Show project overview dashboard')
|
|
1027
|
+
.argument('[path]', 'Directory containing .prd files', '.')
|
|
1028
|
+
.action((path) => {
|
|
1029
|
+
const root = resolve(path);
|
|
1030
|
+
const result = compile(root, {});
|
|
1031
|
+
const data = collectDashboardData(root, result);
|
|
1032
|
+
process.stdout.write(formatDashboard(data) + '\n');
|
|
1033
|
+
process.exitCode = 0;
|
|
1034
|
+
});
|
|
1035
|
+
return program;
|
|
1036
|
+
}
|
|
1037
|
+
// Entry point — only runs when executed directly
|
|
1038
|
+
/* v8 ignore next 3 */
|
|
1039
|
+
if (process.argv[1] && resolve(process.argv[1]).includes('main')) {
|
|
1040
|
+
createProgram().parse();
|
|
1041
|
+
}
|
|
1042
|
+
// -----------------------------------------------------------------------
|
|
1043
|
+
// Helpers
|
|
1044
|
+
// -----------------------------------------------------------------------
|
|
1045
|
+
export function outputDiagnostics(bag, format) {
|
|
1046
|
+
if (format === 'json') {
|
|
1047
|
+
process.stdout.write(formatDiagnosticsJson(bag) + '\n');
|
|
1048
|
+
}
|
|
1049
|
+
else {
|
|
1050
|
+
const text = formatDiagnosticsHuman(bag);
|
|
1051
|
+
if (text.length > 0) {
|
|
1052
|
+
process.stderr.write(text + '\n');
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
export function applyCliOverrides(config, opts) {
|
|
1057
|
+
let result = config;
|
|
1058
|
+
if (opts.maxReviewLoops !== undefined && opts.maxReviewLoops > 0) {
|
|
1059
|
+
result = {
|
|
1060
|
+
...result,
|
|
1061
|
+
reviewFix: { ...result.reviewFix, maxIterations: opts.maxReviewLoops },
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
if (opts.autoClarify) {
|
|
1065
|
+
result = {
|
|
1066
|
+
...result,
|
|
1067
|
+
phases: { ...result.phases, clarify: { ...result.phases.clarify, ambiguityThreshold: 'low' } },
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
return result;
|
|
1071
|
+
}
|
|
1072
|
+
//# sourceMappingURL=main.js.map
|