spectra-cli 4.1.1 → 4.2.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 +1 -1
- package/dist/adapters/go-adapter.d.ts.map +1 -1
- package/dist/adapters/go-adapter.js +2 -0
- package/dist/adapters/go-adapter.js.map +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/java-adapter.d.ts.map +1 -1
- package/dist/adapters/java-adapter.js +2 -0
- package/dist/adapters/java-adapter.js.map +1 -1
- package/dist/adapters/language-adapter.d.ts +47 -9
- package/dist/adapters/language-adapter.d.ts.map +1 -1
- package/dist/adapters/python-adapter.d.ts +34 -6
- package/dist/adapters/python-adapter.d.ts.map +1 -1
- package/dist/adapters/python-adapter.js +157 -59
- package/dist/adapters/python-adapter.js.map +1 -1
- package/dist/adapters/ts-js-adapter.d.ts +13 -5
- package/dist/adapters/ts-js-adapter.d.ts.map +1 -1
- package/dist/adapters/ts-js-adapter.js +55 -14
- package/dist/adapters/ts-js-adapter.js.map +1 -1
- package/dist/batch/batch-orchestrator.d.ts +30 -4
- package/dist/batch/batch-orchestrator.d.ts.map +1 -1
- package/dist/batch/batch-orchestrator.js +284 -7
- package/dist/batch/batch-orchestrator.js.map +1 -1
- package/dist/batch/delta-regenerator.d.ts +2 -2
- package/dist/batch/delta-regenerator.d.ts.map +1 -1
- package/dist/batch/delta-regenerator.js.map +1 -1
- package/dist/batch/module-grouper.d.ts +2 -2
- package/dist/batch/module-grouper.d.ts.map +1 -1
- package/dist/batch/module-grouper.js +1 -1
- package/dist/batch/module-grouper.js.map +1 -1
- package/dist/cli/commands/graph.js +1 -1
- package/dist/cli/commands/graph.js.map +1 -1
- package/dist/cli/commands/index.d.ts +8 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +274 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/query.d.ts.map +1 -1
- package/dist/cli/commands/query.js +3 -1
- package/dist/cli/commands/query.js.map +1 -1
- package/dist/cli/index.js +9 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/parse-args.d.ts +13 -1
- package/dist/cli/utils/parse-args.d.ts.map +1 -1
- package/dist/cli/utils/parse-args.js +79 -2
- package/dist/cli/utils/parse-args.js.map +1 -1
- package/dist/core/ast-analyzer.d.ts.map +1 -1
- package/dist/core/ast-analyzer.js +79 -5
- package/dist/core/ast-analyzer.js.map +1 -1
- package/dist/core/import-resolver.d.ts +90 -0
- package/dist/core/import-resolver.d.ts.map +1 -0
- package/dist/core/import-resolver.js +273 -0
- package/dist/core/import-resolver.js.map +1 -0
- package/dist/core/query-mappers/base-mapper.d.ts +13 -0
- package/dist/core/query-mappers/base-mapper.d.ts.map +1 -1
- package/dist/core/query-mappers/go-mapper.d.ts +68 -0
- package/dist/core/query-mappers/go-mapper.d.ts.map +1 -1
- package/dist/core/query-mappers/go-mapper.js +421 -0
- package/dist/core/query-mappers/go-mapper.js.map +1 -1
- package/dist/core/query-mappers/java-mapper.d.ts +196 -0
- package/dist/core/query-mappers/java-mapper.d.ts.map +1 -1
- package/dist/core/query-mappers/java-mapper.js +600 -0
- package/dist/core/query-mappers/java-mapper.js.map +1 -1
- package/dist/core/query-mappers/python-mapper.d.ts +55 -0
- package/dist/core/query-mappers/python-mapper.d.ts.map +1 -1
- package/dist/core/query-mappers/python-mapper.js +273 -0
- package/dist/core/query-mappers/python-mapper.js.map +1 -1
- package/dist/core/query-mappers/typescript-mapper.d.ts +102 -0
- package/dist/core/query-mappers/typescript-mapper.d.ts.map +1 -1
- package/dist/core/query-mappers/typescript-mapper.js +470 -0
- package/dist/core/query-mappers/typescript-mapper.js.map +1 -1
- package/dist/core/single-spec-orchestrator.d.ts.map +1 -1
- package/dist/core/single-spec-orchestrator.js +146 -9
- package/dist/core/single-spec-orchestrator.js.map +1 -1
- package/dist/core/tree-sitter-analyzer.d.ts +6 -0
- package/dist/core/tree-sitter-analyzer.d.ts.map +1 -1
- package/dist/core/tree-sitter-analyzer.js +33 -1
- package/dist/core/tree-sitter-analyzer.js.map +1 -1
- package/dist/core/tree-sitter-fallback.d.ts +7 -4
- package/dist/core/tree-sitter-fallback.d.ts.map +1 -1
- package/dist/core/tree-sitter-fallback.js +157 -12
- package/dist/core/tree-sitter-fallback.js.map +1 -1
- package/dist/extraction/extraction-types.d.ts +25 -25
- package/dist/generator/index-generator.d.ts +3 -3
- package/dist/generator/index-generator.d.ts.map +1 -1
- package/dist/generator/index-generator.js +1 -1
- package/dist/generator/index-generator.js.map +1 -1
- package/dist/graph/directory-graph.d.ts +14 -4
- package/dist/graph/directory-graph.d.ts.map +1 -1
- package/dist/graph/directory-graph.js +71 -128
- package/dist/graph/directory-graph.js.map +1 -1
- package/dist/graph/mermaid-renderer.d.ts +8 -5
- package/dist/graph/mermaid-renderer.d.ts.map +1 -1
- package/dist/graph/mermaid-renderer.js +3 -3
- package/dist/graph/mermaid-renderer.js.map +1 -1
- package/dist/graph/topological-sort.d.ts +13 -6
- package/dist/graph/topological-sort.d.ts.map +1 -1
- package/dist/graph/topological-sort.js +2 -2
- package/dist/graph/topological-sort.js.map +1 -1
- package/dist/knowledge-graph/call-resolver.d.ts +64 -0
- package/dist/knowledge-graph/call-resolver.d.ts.map +1 -0
- package/dist/knowledge-graph/call-resolver.js +323 -0
- package/dist/knowledge-graph/call-resolver.js.map +1 -0
- package/dist/knowledge-graph/import-resolver.d.ts +114 -0
- package/dist/knowledge-graph/import-resolver.d.ts.map +1 -0
- package/dist/knowledge-graph/import-resolver.js +537 -0
- package/dist/knowledge-graph/import-resolver.js.map +1 -0
- package/dist/knowledge-graph/incremental.d.ts +110 -0
- package/dist/knowledge-graph/incremental.d.ts.map +1 -0
- package/dist/knowledge-graph/incremental.js +410 -0
- package/dist/knowledge-graph/incremental.js.map +1 -0
- package/dist/knowledge-graph/index.d.ts +74 -0
- package/dist/knowledge-graph/index.d.ts.map +1 -0
- package/dist/knowledge-graph/index.js +156 -0
- package/dist/knowledge-graph/index.js.map +1 -0
- package/dist/knowledge-graph/module-derivation.d.ts +238 -0
- package/dist/knowledge-graph/module-derivation.d.ts.map +1 -0
- package/dist/knowledge-graph/module-derivation.js +418 -0
- package/dist/knowledge-graph/module-derivation.js.map +1 -0
- package/dist/knowledge-graph/persistence.d.ts +270 -0
- package/dist/knowledge-graph/persistence.d.ts.map +1 -0
- package/dist/knowledge-graph/persistence.js +226 -0
- package/dist/knowledge-graph/persistence.js.map +1 -0
- package/dist/knowledge-graph/query-helpers.d.ts +164 -0
- package/dist/knowledge-graph/query-helpers.d.ts.map +1 -0
- package/dist/knowledge-graph/query-helpers.js +394 -0
- package/dist/knowledge-graph/query-helpers.js.map +1 -0
- package/dist/knowledge-graph/unified-graph.d.ts +310 -0
- package/dist/knowledge-graph/unified-graph.d.ts.map +1 -0
- package/dist/knowledge-graph/unified-graph.js +182 -0
- package/dist/knowledge-graph/unified-graph.js.map +1 -0
- package/dist/mcp/agent-context-tools.d.ts +104 -0
- package/dist/mcp/agent-context-tools.d.ts.map +1 -0
- package/dist/mcp/agent-context-tools.js +854 -0
- package/dist/mcp/agent-context-tools.js.map +1 -0
- package/dist/mcp/graph-tools.d.ts +20 -0
- package/dist/mcp/graph-tools.d.ts.map +1 -1
- package/dist/mcp/graph-tools.js +71 -11
- package/dist/mcp/graph-tools.js.map +1 -1
- package/dist/mcp/lib/response-helpers.d.ts +67 -0
- package/dist/mcp/lib/response-helpers.d.ts.map +1 -0
- package/dist/mcp/lib/response-helpers.js +103 -0
- package/dist/mcp/lib/response-helpers.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +9 -10
- package/dist/mcp/server.js.map +1 -1
- package/dist/models/call-site.d.ts +68 -0
- package/dist/models/call-site.d.ts.map +1 -0
- package/dist/models/call-site.js +60 -0
- package/dist/models/call-site.js.map +1 -0
- package/dist/models/code-skeleton.d.ts +78 -6
- package/dist/models/code-skeleton.d.ts.map +1 -1
- package/dist/models/code-skeleton.js +29 -0
- package/dist/models/code-skeleton.js.map +1 -1
- package/dist/models/drift-item.d.ts +4 -4
- package/dist/models/module-spec.d.ts +155 -94
- package/dist/models/module-spec.d.ts.map +1 -1
- package/dist/panoramic/adr-decision-pipeline.d.ts +53 -0
- package/dist/panoramic/adr-decision-pipeline.d.ts.map +1 -0
- package/dist/panoramic/adr-decision-pipeline.js +685 -0
- package/dist/panoramic/adr-decision-pipeline.js.map +1 -0
- package/dist/panoramic/api-surface-generator.d.ts +56 -0
- package/dist/panoramic/api-surface-generator.d.ts.map +1 -0
- package/dist/panoramic/api-surface-generator.js +1671 -0
- package/dist/panoramic/api-surface-generator.js.map +1 -0
- package/dist/panoramic/architecture-ir-builder.d.ts +19 -0
- package/dist/panoramic/architecture-ir-builder.d.ts.map +1 -0
- package/dist/panoramic/architecture-ir-builder.js +561 -0
- package/dist/panoramic/architecture-ir-builder.js.map +1 -0
- package/dist/panoramic/architecture-ir-exporters.d.ts +7 -0
- package/dist/panoramic/architecture-ir-exporters.d.ts.map +1 -0
- package/dist/panoramic/architecture-ir-exporters.js +183 -0
- package/dist/panoramic/architecture-ir-exporters.js.map +1 -0
- package/dist/panoramic/architecture-ir-generator.d.ts +36 -0
- package/dist/panoramic/architecture-ir-generator.d.ts.map +1 -0
- package/dist/panoramic/architecture-ir-generator.js +51 -0
- package/dist/panoramic/architecture-ir-generator.js.map +1 -0
- package/dist/panoramic/architecture-ir-mermaid-adapter.d.ts +6 -0
- package/dist/panoramic/architecture-ir-mermaid-adapter.d.ts.map +1 -0
- package/dist/panoramic/architecture-ir-mermaid-adapter.js +98 -0
- package/dist/panoramic/architecture-ir-mermaid-adapter.js.map +1 -0
- package/dist/panoramic/architecture-ir-model.d.ts +87 -0
- package/dist/panoramic/architecture-ir-model.d.ts.map +1 -0
- package/dist/panoramic/architecture-ir-model.js +20 -0
- package/dist/panoramic/architecture-ir-model.js.map +1 -0
- package/dist/panoramic/architecture-narrative.d.ts +68 -0
- package/dist/panoramic/architecture-narrative.d.ts.map +1 -0
- package/dist/panoramic/architecture-narrative.js +401 -0
- package/dist/panoramic/architecture-narrative.js.map +1 -0
- package/dist/panoramic/architecture-overview-generator.d.ts +31 -0
- package/dist/panoramic/architecture-overview-generator.d.ts.map +1 -0
- package/dist/panoramic/architecture-overview-generator.js +454 -0
- package/dist/panoramic/architecture-overview-generator.js.map +1 -0
- package/dist/panoramic/architecture-overview-model.d.ts +77 -0
- package/dist/panoramic/architecture-overview-model.d.ts.map +1 -0
- package/dist/panoramic/architecture-overview-model.js +31 -0
- package/dist/panoramic/architecture-overview-model.js.map +1 -0
- package/dist/panoramic/batch-project-docs.d.ts.map +1 -1
- package/dist/panoramic/batch-project-docs.js +4 -2
- package/dist/panoramic/batch-project-docs.js.map +1 -1
- package/dist/panoramic/builders/component-view-builder.d.ts +25 -1
- package/dist/panoramic/builders/component-view-builder.d.ts.map +1 -1
- package/dist/panoramic/builders/component-view-builder.js +83 -3
- package/dist/panoramic/builders/component-view-builder.js.map +1 -1
- package/dist/panoramic/builders/doc-graph-builder.d.ts +2 -2
- package/dist/panoramic/builders/doc-graph-builder.d.ts.map +1 -1
- package/dist/panoramic/builders/doc-graph-builder.js.map +1 -1
- package/dist/panoramic/component-view-builder.d.ts +17 -0
- package/dist/panoramic/component-view-builder.d.ts.map +1 -0
- package/dist/panoramic/component-view-builder.js +652 -0
- package/dist/panoramic/component-view-builder.js.map +1 -0
- package/dist/panoramic/component-view-model.d.ts +127 -0
- package/dist/panoramic/component-view-model.d.ts.map +1 -0
- package/dist/panoramic/component-view-model.js +65 -0
- package/dist/panoramic/component-view-model.js.map +1 -0
- package/dist/panoramic/config-reference-generator.d.ts +78 -0
- package/dist/panoramic/config-reference-generator.d.ts.map +1 -0
- package/dist/panoramic/config-reference-generator.js +199 -0
- package/dist/panoramic/config-reference-generator.js.map +1 -0
- package/dist/panoramic/coverage-auditor.d.ts +95 -0
- package/dist/panoramic/coverage-auditor.d.ts.map +1 -0
- package/dist/panoramic/coverage-auditor.js +290 -0
- package/dist/panoramic/coverage-auditor.js.map +1 -0
- package/dist/panoramic/cross-package-analyzer.d.ts +112 -0
- package/dist/panoramic/cross-package-analyzer.d.ts.map +1 -0
- package/dist/panoramic/cross-package-analyzer.js +258 -0
- package/dist/panoramic/cross-package-analyzer.js.map +1 -0
- package/dist/panoramic/data-model-generator.d.ts +528 -0
- package/dist/panoramic/data-model-generator.d.ts.map +1 -0
- package/dist/panoramic/data-model-generator.js +647 -0
- package/dist/panoramic/data-model-generator.js.map +1 -0
- package/dist/panoramic/doc-graph-builder.d.ts +80 -0
- package/dist/panoramic/doc-graph-builder.d.ts.map +1 -0
- package/dist/panoramic/doc-graph-builder.js +352 -0
- package/dist/panoramic/doc-graph-builder.js.map +1 -0
- package/dist/panoramic/docs-bundle-manifest-reader.d.ts +26 -0
- package/dist/panoramic/docs-bundle-manifest-reader.d.ts.map +1 -0
- package/dist/panoramic/docs-bundle-manifest-reader.js +106 -0
- package/dist/panoramic/docs-bundle-manifest-reader.js.map +1 -0
- package/dist/panoramic/docs-bundle-orchestrator.d.ts +14 -0
- package/dist/panoramic/docs-bundle-orchestrator.d.ts.map +1 -0
- package/dist/panoramic/docs-bundle-orchestrator.js +538 -0
- package/dist/panoramic/docs-bundle-orchestrator.js.map +1 -0
- package/dist/panoramic/docs-bundle-profiles.d.ts +4 -0
- package/dist/panoramic/docs-bundle-profiles.d.ts.map +1 -0
- package/dist/panoramic/docs-bundle-profiles.js +82 -0
- package/dist/panoramic/docs-bundle-profiles.js.map +1 -0
- package/dist/panoramic/docs-bundle-types.d.ts +94 -0
- package/dist/panoramic/docs-bundle-types.d.ts.map +1 -0
- package/dist/panoramic/docs-bundle-types.js +10 -0
- package/dist/panoramic/docs-bundle-types.js.map +1 -0
- package/dist/panoramic/docs-quality-evaluator.d.ts +31 -0
- package/dist/panoramic/docs-quality-evaluator.d.ts.map +1 -0
- package/dist/panoramic/docs-quality-evaluator.js +941 -0
- package/dist/panoramic/docs-quality-evaluator.js.map +1 -0
- package/dist/panoramic/docs-quality-model.d.ts +125 -0
- package/dist/panoramic/docs-quality-model.d.ts.map +1 -0
- package/dist/panoramic/docs-quality-model.js +166 -0
- package/dist/panoramic/docs-quality-model.js.map +1 -0
- package/dist/panoramic/dynamic-scenarios-builder.d.ts +18 -0
- package/dist/panoramic/dynamic-scenarios-builder.d.ts.map +1 -0
- package/dist/panoramic/dynamic-scenarios-builder.js +316 -0
- package/dist/panoramic/dynamic-scenarios-builder.js.map +1 -0
- package/dist/panoramic/event-surface-generator.d.ts +52 -0
- package/dist/panoramic/event-surface-generator.d.ts.map +1 -0
- package/dist/panoramic/event-surface-generator.js +507 -0
- package/dist/panoramic/event-surface-generator.js.map +1 -0
- package/dist/panoramic/generator-registry.d.ts +1 -1
- package/dist/panoramic/generator-registry.d.ts.map +1 -1
- package/dist/panoramic/generator-registry.js +5 -2
- package/dist/panoramic/generator-registry.js.map +1 -1
- package/dist/panoramic/generators/cross-package-analyzer.d.ts +5 -5
- package/dist/panoramic/generators/cross-package-analyzer.d.ts.map +1 -1
- package/dist/panoramic/generators/cross-package-analyzer.js +1 -1
- package/dist/panoramic/generators/cross-package-analyzer.js.map +1 -1
- package/dist/panoramic/generators/data-model-generator.d.ts +27 -27
- package/dist/panoramic/graph/confidence-mapper.d.ts +18 -0
- package/dist/panoramic/graph/confidence-mapper.d.ts.map +1 -1
- package/dist/panoramic/graph/confidence-mapper.js +26 -0
- package/dist/panoramic/graph/confidence-mapper.js.map +1 -1
- package/dist/panoramic/graph/graph-builder.d.ts.map +1 -1
- package/dist/panoramic/graph/graph-builder.js +78 -0
- package/dist/panoramic/graph/graph-builder.js.map +1 -1
- package/dist/panoramic/graph/graph-paths.d.ts +8 -0
- package/dist/panoramic/graph/graph-paths.d.ts.map +1 -1
- package/dist/panoramic/graph/graph-paths.js +10 -0
- package/dist/panoramic/graph/graph-paths.js.map +1 -1
- package/dist/panoramic/graph/graph-query.d.ts +33 -2
- package/dist/panoramic/graph/graph-query.d.ts.map +1 -1
- package/dist/panoramic/graph/graph-query.js +69 -19
- package/dist/panoramic/graph/graph-query.js.map +1 -1
- package/dist/panoramic/graph/graph-types.d.ts +32 -3
- package/dist/panoramic/graph/graph-types.d.ts.map +1 -1
- package/dist/panoramic/hyperedges/schema.d.ts +6 -6
- package/dist/panoramic/interface-surface-generator.d.ts +50 -0
- package/dist/panoramic/interface-surface-generator.d.ts.map +1 -0
- package/dist/panoramic/interface-surface-generator.js +388 -0
- package/dist/panoramic/interface-surface-generator.js.map +1 -0
- package/dist/panoramic/interfaces.d.ts +2 -2
- package/dist/panoramic/mock-readme-generator.d.ts +90 -0
- package/dist/panoramic/mock-readme-generator.d.ts.map +1 -0
- package/dist/panoramic/mock-readme-generator.js +111 -0
- package/dist/panoramic/mock-readme-generator.js.map +1 -0
- package/dist/panoramic/models/component-view-model.d.ts +1 -1
- package/dist/panoramic/models/component-view-model.d.ts.map +1 -1
- package/dist/panoramic/models/component-view-model.js.map +1 -1
- package/dist/panoramic/narrative-provenance-adapter.d.ts +8 -0
- package/dist/panoramic/narrative-provenance-adapter.d.ts.map +1 -0
- package/dist/panoramic/narrative-provenance-adapter.js +99 -0
- package/dist/panoramic/narrative-provenance-adapter.js.map +1 -0
- package/dist/panoramic/parser-registry.d.ts +1 -1
- package/dist/panoramic/parser-registry.js +1 -1
- package/dist/panoramic/parsers/types.d.ts +6 -6
- package/dist/panoramic/pattern-hints-generator.d.ts +28 -0
- package/dist/panoramic/pattern-hints-generator.d.ts.map +1 -0
- package/dist/panoramic/pattern-hints-generator.js +218 -0
- package/dist/panoramic/pattern-hints-generator.js.map +1 -0
- package/dist/panoramic/pattern-hints-model.d.ts +89 -0
- package/dist/panoramic/pattern-hints-model.d.ts.map +1 -0
- package/dist/panoramic/pattern-hints-model.js +61 -0
- package/dist/panoramic/pattern-hints-model.js.map +1 -0
- package/dist/panoramic/pattern-knowledge-base.d.ts +31 -0
- package/dist/panoramic/pattern-knowledge-base.d.ts.map +1 -0
- package/dist/panoramic/pattern-knowledge-base.js +407 -0
- package/dist/panoramic/pattern-knowledge-base.js.map +1 -0
- package/dist/panoramic/pipelines/coverage-auditor.d.ts.map +1 -1
- package/dist/panoramic/pipelines/coverage-auditor.js +4 -2
- package/dist/panoramic/pipelines/coverage-auditor.js.map +1 -1
- package/dist/panoramic/pipelines/docs-bundle-orchestrator.js +13 -6
- package/dist/panoramic/pipelines/docs-bundle-orchestrator.js.map +1 -1
- package/dist/panoramic/pipelines/product-ux-docs.d.ts +5 -0
- package/dist/panoramic/pipelines/product-ux-docs.d.ts.map +1 -1
- package/dist/panoramic/pipelines/product-ux-docs.js +34 -6
- package/dist/panoramic/pipelines/product-ux-docs.js.map +1 -1
- package/dist/panoramic/product-ux-docs.d.ts +104 -0
- package/dist/panoramic/product-ux-docs.d.ts.map +1 -0
- package/dist/panoramic/product-ux-docs.js +817 -0
- package/dist/panoramic/product-ux-docs.js.map +1 -0
- package/dist/panoramic/qa/__tests__/citation.test.d.ts +2 -0
- package/dist/panoramic/qa/__tests__/citation.test.d.ts.map +1 -0
- package/dist/panoramic/qa/__tests__/citation.test.js +193 -0
- package/dist/panoramic/qa/__tests__/citation.test.js.map +1 -0
- package/dist/panoramic/qa/__tests__/debt-context.test.d.ts +2 -0
- package/dist/panoramic/qa/__tests__/debt-context.test.d.ts.map +1 -0
- package/dist/panoramic/qa/__tests__/debt-context.test.js +154 -0
- package/dist/panoramic/qa/__tests__/debt-context.test.js.map +1 -0
- package/dist/panoramic/qa/__tests__/graph-retriever.test.d.ts +2 -0
- package/dist/panoramic/qa/__tests__/graph-retriever.test.d.ts.map +1 -0
- package/dist/panoramic/qa/__tests__/graph-retriever.test.js +148 -0
- package/dist/panoramic/qa/__tests__/graph-retriever.test.js.map +1 -0
- package/dist/panoramic/qa/__tests__/index.test.d.ts +2 -0
- package/dist/panoramic/qa/__tests__/index.test.d.ts.map +1 -0
- package/dist/panoramic/qa/__tests__/index.test.js +246 -0
- package/dist/panoramic/qa/__tests__/index.test.js.map +1 -0
- package/dist/panoramic/qa/__tests__/llm-caller.test.d.ts +2 -0
- package/dist/panoramic/qa/__tests__/llm-caller.test.d.ts.map +1 -0
- package/dist/panoramic/qa/__tests__/llm-caller.test.js +168 -0
- package/dist/panoramic/qa/__tests__/llm-caller.test.js.map +1 -0
- package/dist/panoramic/qa/__tests__/prompt-builder.test.d.ts +2 -0
- package/dist/panoramic/qa/__tests__/prompt-builder.test.d.ts.map +1 -0
- package/dist/panoramic/qa/__tests__/prompt-builder.test.js +150 -0
- package/dist/panoramic/qa/__tests__/prompt-builder.test.js.map +1 -0
- package/dist/panoramic/qa/__tests__/qa-integration.test.d.ts +2 -0
- package/dist/panoramic/qa/__tests__/qa-integration.test.d.ts.map +1 -0
- package/dist/panoramic/qa/__tests__/qa-integration.test.js +296 -0
- package/dist/panoramic/qa/__tests__/qa-integration.test.js.map +1 -0
- package/dist/panoramic/qa/__tests__/rag-reranker.test.d.ts +2 -0
- package/dist/panoramic/qa/__tests__/rag-reranker.test.d.ts.map +1 -0
- package/dist/panoramic/qa/__tests__/rag-reranker.test.js +136 -0
- package/dist/panoramic/qa/__tests__/rag-reranker.test.js.map +1 -0
- package/dist/panoramic/qa/index.d.ts.map +1 -1
- package/dist/panoramic/qa/index.js +10 -3
- package/dist/panoramic/qa/index.js.map +1 -1
- package/dist/panoramic/runtime-topology-generator.d.ts +77 -0
- package/dist/panoramic/runtime-topology-generator.d.ts.map +1 -0
- package/dist/panoramic/runtime-topology-generator.js +676 -0
- package/dist/panoramic/runtime-topology-generator.js.map +1 -0
- package/dist/panoramic/runtime-topology-model.d.ts +145 -0
- package/dist/panoramic/runtime-topology-model.d.ts.map +1 -0
- package/dist/panoramic/runtime-topology-model.js +300 -0
- package/dist/panoramic/runtime-topology-model.js.map +1 -0
- package/dist/panoramic/troubleshooting-generator.d.ts +51 -0
- package/dist/panoramic/troubleshooting-generator.d.ts.map +1 -0
- package/dist/panoramic/troubleshooting-generator.js +451 -0
- package/dist/panoramic/troubleshooting-generator.js.map +1 -0
- package/dist/panoramic/utils/text-segmenter.d.ts +15 -0
- package/dist/panoramic/utils/text-segmenter.d.ts.map +1 -1
- package/dist/panoramic/utils/text-segmenter.js +38 -0
- package/dist/panoramic/utils/text-segmenter.js.map +1 -1
- package/dist/panoramic/workspace-index-generator.d.ts +148 -0
- package/dist/panoramic/workspace-index-generator.d.ts.map +1 -0
- package/dist/panoramic/workspace-index-generator.js +497 -0
- package/dist/panoramic/workspace-index-generator.js.map +1 -0
- package/dist/runtime-bootstrap.d.ts +9 -0
- package/dist/runtime-bootstrap.d.ts.map +1 -0
- package/dist/runtime-bootstrap.js +33 -0
- package/dist/runtime-bootstrap.js.map +1 -0
- package/dist/utils/file-scanner.js +1 -1
- package/dist/utils/file-scanner.js.map +1 -1
- package/package.json +12 -2
- package/plugins/spec-driver/.claude-plugin/plugin.json +1 -1
- package/plugins/spec-driver/README.md +18 -1
- package/plugins/spec-driver/agents/implement.md +20 -1
- package/plugins/spec-driver/agents/plan.md +20 -1
- package/plugins/spec-driver/agents/quality-review.md +20 -1
- package/plugins/spec-driver/agents/spec-review.md +20 -1
- package/plugins/spec-driver/agents/verify.md +20 -1
- package/plugins/spec-driver/docs/customization.md +134 -0
- package/plugins/spec-driver/docs/spectra-mcp-integration.md +165 -0
- package/plugins/spec-driver/lib/preference-rules.mjs +96 -0
- package/plugins/spec-driver/scripts/postinstall.sh +1 -1
- package/plugins/spec-driver/scripts/sync-preference-rules.mjs +148 -0
- package/plugins/spec-driver/skills/spec-driver-feature/SKILL.md +10 -0
- package/plugins/spec-driver/skills/spec-driver-fix/SKILL.md +10 -0
- package/plugins/spec-driver/skills/spec-driver-implement/SKILL.md +10 -0
- package/plugins/spec-driver/skills/spec-driver-refactor/SKILL.md +10 -0
- package/plugins/spec-driver/skills/spec-driver-story/SKILL.md +10 -0
- package/plugins/spec-driver/templates/preference-rules.md +39 -0
- package/plugins/spectra/.claude-plugin/plugin.json +1 -1
- package/plugins/spectra/README.md +48 -1
- package/plugins/spectra/hooks/post-commit.sh +40 -0
- package/templates/product-overview.hbs +1 -1
|
@@ -0,0 +1,685 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR 决策流水线
|
|
3
|
+
*
|
|
4
|
+
* 基于项目级结构化输出、模块 spec、current-spec、增量 spec 与 git 提交历史,
|
|
5
|
+
* 生成候选 ADR 草稿与索引。该流水线优先使用确定性证据匹配,避免把 ADR 草稿
|
|
6
|
+
* 变成“看起来合理”的纯 LLM 幻觉文本。
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from 'node:fs';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { spawnSync } from 'node:child_process';
|
|
11
|
+
import { loadTemplate } from './utils/template-loader.js';
|
|
12
|
+
export function generateBatchAdrDocs(options) {
|
|
13
|
+
const corpus = buildAdrCorpus(options);
|
|
14
|
+
const warnings = new Set();
|
|
15
|
+
const candidates = buildAdrCandidates(corpus);
|
|
16
|
+
if (candidates.length === 0) {
|
|
17
|
+
warnings.add('未识别到足够稳定的 ADR 候选信号,已仅生成空索引。');
|
|
18
|
+
}
|
|
19
|
+
const drafts = candidates
|
|
20
|
+
.sort((left, right) => right.score - left.score || left.title.localeCompare(right.title))
|
|
21
|
+
.slice(0, 4)
|
|
22
|
+
.map((candidate, index) => finalizeDraft(index + 1, candidate));
|
|
23
|
+
const adrDir = path.join(options.outputDir, 'docs', 'adr');
|
|
24
|
+
const writtenFiles = [];
|
|
25
|
+
for (const draft of drafts) {
|
|
26
|
+
const markdown = renderAdrDraft(draft);
|
|
27
|
+
const baseName = `${draft.decisionId.toLowerCase()}-${draft.slug}`;
|
|
28
|
+
const mdPath = path.join(adrDir, `${baseName}.md`);
|
|
29
|
+
const jsonPath = path.join(adrDir, `${baseName}.json`);
|
|
30
|
+
fs.mkdirSync(adrDir, { recursive: true });
|
|
31
|
+
fs.writeFileSync(mdPath, markdown, 'utf-8');
|
|
32
|
+
fs.writeFileSync(jsonPath, JSON.stringify(draft, null, 2), 'utf-8');
|
|
33
|
+
writtenFiles.push(mdPath, jsonPath);
|
|
34
|
+
}
|
|
35
|
+
const index = {
|
|
36
|
+
title: `ADR 决策索引: ${corpus.projectName}`,
|
|
37
|
+
generatedAt: new Date().toISOString(),
|
|
38
|
+
projectName: corpus.projectName,
|
|
39
|
+
summary: buildIndexSummary(corpus, drafts),
|
|
40
|
+
draftCount: drafts.length,
|
|
41
|
+
warnings: [...warnings],
|
|
42
|
+
drafts,
|
|
43
|
+
};
|
|
44
|
+
fs.mkdirSync(adrDir, { recursive: true });
|
|
45
|
+
const indexMarkdown = renderAdrIndex(index);
|
|
46
|
+
const indexMarkdownPath = path.join(adrDir, 'index.md');
|
|
47
|
+
const indexJsonPath = path.join(adrDir, 'index.json');
|
|
48
|
+
fs.writeFileSync(indexMarkdownPath, indexMarkdown, 'utf-8');
|
|
49
|
+
fs.writeFileSync(indexJsonPath, JSON.stringify(index, null, 2), 'utf-8');
|
|
50
|
+
writtenFiles.push(indexMarkdownPath, indexJsonPath);
|
|
51
|
+
return {
|
|
52
|
+
index,
|
|
53
|
+
drafts,
|
|
54
|
+
warnings: [...warnings],
|
|
55
|
+
writtenFiles,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function renderAdrDraft(draft) {
|
|
59
|
+
const template = loadTemplate('adr-draft.hbs', import.meta.url);
|
|
60
|
+
return template(draft);
|
|
61
|
+
}
|
|
62
|
+
function renderAdrIndex(output) {
|
|
63
|
+
const template = loadTemplate('adr-index.hbs', import.meta.url);
|
|
64
|
+
return template(output);
|
|
65
|
+
}
|
|
66
|
+
function buildAdrCorpus(options) {
|
|
67
|
+
const entries = [];
|
|
68
|
+
const projectName = options.architectureNarrative.projectName;
|
|
69
|
+
entries.push({
|
|
70
|
+
sourceType: 'architecture-narrative',
|
|
71
|
+
label: 'executive-summary',
|
|
72
|
+
path: path.join(options.outputDir, 'architecture-narrative.md'),
|
|
73
|
+
text: [
|
|
74
|
+
...options.architectureNarrative.executiveSummary,
|
|
75
|
+
...options.architectureNarrative.observations,
|
|
76
|
+
].join('\n'),
|
|
77
|
+
});
|
|
78
|
+
for (const module of options.architectureNarrative.keyModules) {
|
|
79
|
+
entries.push({
|
|
80
|
+
sourceType: 'architecture-narrative',
|
|
81
|
+
label: `module:${module.sourceTarget}`,
|
|
82
|
+
path: path.join(options.outputDir, 'architecture-narrative.md'),
|
|
83
|
+
text: [
|
|
84
|
+
module.sourceTarget,
|
|
85
|
+
module.displayName,
|
|
86
|
+
module.intentSummary,
|
|
87
|
+
module.businessSummary,
|
|
88
|
+
module.dependencySummary,
|
|
89
|
+
...module.keySymbols.map((symbol) => `${symbol.kind}:${symbol.name}:${symbol.note}`),
|
|
90
|
+
...module.keyMethods.map((method) => `${method.kind}:${method.name}:${method.note}`),
|
|
91
|
+
].join('\n'),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (options.patternHints) {
|
|
95
|
+
entries.push({
|
|
96
|
+
sourceType: 'pattern-hints',
|
|
97
|
+
label: 'pattern-summary',
|
|
98
|
+
path: path.join(options.outputDir, 'pattern-hints.md'),
|
|
99
|
+
text: options.patternHints.model.matchedPatterns
|
|
100
|
+
.map((hint) => [
|
|
101
|
+
hint.patternName,
|
|
102
|
+
hint.summary,
|
|
103
|
+
hint.explanation,
|
|
104
|
+
...hint.matchedSignals,
|
|
105
|
+
].join('\n'))
|
|
106
|
+
.join('\n\n'),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (options.architectureOverview) {
|
|
110
|
+
entries.push({
|
|
111
|
+
sourceType: 'architecture-overview',
|
|
112
|
+
label: 'overview-summary',
|
|
113
|
+
path: path.join(options.outputDir, 'architecture-overview.md'),
|
|
114
|
+
text: [
|
|
115
|
+
options.architectureOverview.title,
|
|
116
|
+
summarizeArchitectureSection(options.architectureOverview.systemContext),
|
|
117
|
+
summarizeArchitectureSection(options.architectureOverview.deploymentView),
|
|
118
|
+
summarizeArchitectureSection(options.architectureOverview.layeredView),
|
|
119
|
+
].filter(Boolean).join('\n'),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
for (const filePath of collectMarkdownEvidenceFiles(options.projectRoot)) {
|
|
123
|
+
const normalized = normalizeProjectPath(filePath, options.projectRoot);
|
|
124
|
+
const lower = normalized.toLowerCase();
|
|
125
|
+
let sourceType = 'spec';
|
|
126
|
+
if (lower.endsWith('/current-spec.md')) {
|
|
127
|
+
sourceType = 'current-spec';
|
|
128
|
+
}
|
|
129
|
+
else if (lower.endsWith('/blueprint.md')) {
|
|
130
|
+
sourceType = 'blueprint';
|
|
131
|
+
}
|
|
132
|
+
entries.push({
|
|
133
|
+
sourceType,
|
|
134
|
+
label: normalized,
|
|
135
|
+
path: normalized,
|
|
136
|
+
text: readTrimmed(filePath, 24_000),
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
for (const sourcePath of collectSourcePathSignals(options.projectRoot)) {
|
|
140
|
+
entries.push({
|
|
141
|
+
sourceType: 'source-path',
|
|
142
|
+
label: sourcePath,
|
|
143
|
+
path: sourcePath,
|
|
144
|
+
text: sourcePath,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
const commits = loadRecentGitCommits(options.projectRoot);
|
|
148
|
+
for (const commit of commits) {
|
|
149
|
+
entries.push({
|
|
150
|
+
sourceType: 'commit',
|
|
151
|
+
label: commit.sha.slice(0, 7),
|
|
152
|
+
text: [commit.subject, commit.body].filter(Boolean).join('\n'),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
projectName,
|
|
157
|
+
projectRoot: options.projectRoot,
|
|
158
|
+
architectureNarrative: options.architectureNarrative,
|
|
159
|
+
architectureOverview: options.architectureOverview,
|
|
160
|
+
patternHints: options.patternHints,
|
|
161
|
+
commits,
|
|
162
|
+
entries,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function buildAdrCandidates(corpus) {
|
|
166
|
+
const candidates = [
|
|
167
|
+
buildCliHostedRuntimeCandidate(corpus),
|
|
168
|
+
buildStreamJsonProtocolCandidate(corpus),
|
|
169
|
+
buildRegistryExtensibilityCandidate(corpus),
|
|
170
|
+
buildDeterministicFactsCandidate(corpus),
|
|
171
|
+
buildCurrentSpecFactSourceCandidate(corpus),
|
|
172
|
+
buildAppendOnlySessionCandidate(corpus),
|
|
173
|
+
buildContainerizedRuntimeCandidate(corpus),
|
|
174
|
+
buildModularSeparationCandidate(corpus),
|
|
175
|
+
].filter((candidate) => candidate !== null);
|
|
176
|
+
if (candidates.length >= 2) {
|
|
177
|
+
return candidates;
|
|
178
|
+
}
|
|
179
|
+
const fallback = buildGenericCoreSeparationCandidate(corpus);
|
|
180
|
+
return fallback ? [...candidates, fallback] : candidates;
|
|
181
|
+
}
|
|
182
|
+
function buildCliHostedRuntimeCandidate(corpus) {
|
|
183
|
+
const evidence = matchEvidence(corpus, [
|
|
184
|
+
'claude code cli',
|
|
185
|
+
'subprocess',
|
|
186
|
+
'transport',
|
|
187
|
+
'stdin/stdout',
|
|
188
|
+
'cli 子进程',
|
|
189
|
+
'subprocesscli',
|
|
190
|
+
'subprocess_cli',
|
|
191
|
+
], 4);
|
|
192
|
+
if (evidence.length < 2) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
key: 'cli-hosted-runtime',
|
|
197
|
+
score: 98 + evidence.length,
|
|
198
|
+
title: '使用 CLI 作为宿主执行引擎',
|
|
199
|
+
category: 'runtime',
|
|
200
|
+
confidence: 'high',
|
|
201
|
+
inferred: false,
|
|
202
|
+
summary: '将宿主语言 SDK/工具层建立在现有 CLI runtime 之上,而不是重复实现 agent loop。',
|
|
203
|
+
decision: '以 CLI 子进程作为主执行引擎,宿主侧负责参数封装、回调桥接、消息解析与本地扩展接入。',
|
|
204
|
+
context: [
|
|
205
|
+
'代码和文档证据反复指向 CLI transport / subprocess transport,而不是直接 HTTP 模型客户端。',
|
|
206
|
+
'这种结构通常用于复用现有 agent loop、工具生态与权限/插件体系,减少宿主 SDK 自行实现运行时的成本。',
|
|
207
|
+
],
|
|
208
|
+
consequences: [
|
|
209
|
+
'宿主层可以专注于类型系统、回调与本地扩展,而不必复制完整 runtime。',
|
|
210
|
+
'与 CLI 版本和协议的兼容性会成为关键约束,需要保持 transport 与消息解析层稳定。',
|
|
211
|
+
],
|
|
212
|
+
alternatives: [
|
|
213
|
+
'直接构建独立的 HTTP / SDK runtime,完全绕过 CLI。',
|
|
214
|
+
'把 agent loop 内嵌在当前宿主进程中,不再依赖外部可执行程序。',
|
|
215
|
+
],
|
|
216
|
+
evidence,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function buildStreamJsonProtocolCandidate(corpus) {
|
|
220
|
+
const evidence = matchEvidence(corpus, [
|
|
221
|
+
'stream-json',
|
|
222
|
+
'message parser',
|
|
223
|
+
'control_request',
|
|
224
|
+
'control response',
|
|
225
|
+
'json',
|
|
226
|
+
'stdin',
|
|
227
|
+
'stdout',
|
|
228
|
+
'message_parser',
|
|
229
|
+
'控制协议',
|
|
230
|
+
], 4);
|
|
231
|
+
if (evidence.length < 2) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
key: 'stream-json-protocol',
|
|
236
|
+
score: 94 + evidence.length,
|
|
237
|
+
title: '使用 JSON 流式控制协议连接宿主与运行时',
|
|
238
|
+
category: 'protocol',
|
|
239
|
+
confidence: 'high',
|
|
240
|
+
inferred: false,
|
|
241
|
+
summary: '在宿主层与运行时之间统一使用 JSON 消息流,维持双向控制和消息扩展能力。',
|
|
242
|
+
decision: '宿主与执行引擎之间通过 JSON over stdin/stdout 的流式协议交换初始化、控制请求、控制响应和消息事件。',
|
|
243
|
+
context: [
|
|
244
|
+
'项目中同时出现 message parser、streaming、stdin/stdout 与 control request/response 等证据,说明通信协议是架构核心而不是实现细节。',
|
|
245
|
+
'使用结构化协议有助于让 hook、工具权限、MCP 与 session 控制落到同一条消息总线上。',
|
|
246
|
+
],
|
|
247
|
+
consequences: [
|
|
248
|
+
'消息类型、字段兼容性和缓冲容错会成为运行时稳定性的关键。',
|
|
249
|
+
'协议一旦扩展,宿主侧 parser 与 transport 需要同步演进。',
|
|
250
|
+
],
|
|
251
|
+
alternatives: [
|
|
252
|
+
'使用一次性命令调用或纯文本 stdout 解析。',
|
|
253
|
+
'宿主与运行时只交换单向消息,不保留 control request/response 语义。',
|
|
254
|
+
],
|
|
255
|
+
evidence,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function buildRegistryExtensibilityCandidate(corpus) {
|
|
259
|
+
const evidence = matchEvidence(corpus, [
|
|
260
|
+
'generatorregistry',
|
|
261
|
+
'parserregistry',
|
|
262
|
+
'languageadapterregistry',
|
|
263
|
+
'documentgenerator',
|
|
264
|
+
'artifactparser',
|
|
265
|
+
'注册中心',
|
|
266
|
+
'registry',
|
|
267
|
+
], 5);
|
|
268
|
+
if (evidence.length < 2) {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
return {
|
|
272
|
+
key: 'registry-extensibility',
|
|
273
|
+
score: 91 + evidence.length,
|
|
274
|
+
title: '使用 Registry 统一扩展生成器、解析器与语言适配器',
|
|
275
|
+
category: 'extensibility',
|
|
276
|
+
confidence: 'high',
|
|
277
|
+
inferred: false,
|
|
278
|
+
summary: '把生成器、解析器和适配器收敛到统一注册中心,避免能力扩展散落在分支逻辑里。',
|
|
279
|
+
decision: '通过 Registry 抽象统一管理 DocumentGenerator、ArtifactParser 与 LanguageAdapter 的发现、启停和按上下文过滤。',
|
|
280
|
+
context: [
|
|
281
|
+
'当前仓库的 panoramic 能力已经演化为多生成器、多解析器、多语言适配的组合系统。',
|
|
282
|
+
'如果没有统一注册/过滤机制,新增文档类型和解析链路会快速失控,并增加 batch 编排复杂度。',
|
|
283
|
+
],
|
|
284
|
+
consequences: [
|
|
285
|
+
'扩展点更稳定,batch/CLI/MCP 可以共享同一套能力发现逻辑。',
|
|
286
|
+
'Registry 自身会成为横切层,需要额外保证幂等初始化、冲突检测和可观察性。',
|
|
287
|
+
],
|
|
288
|
+
alternatives: [
|
|
289
|
+
'在 CLI 或 batch 中硬编码每类生成器/解析器调用顺序。',
|
|
290
|
+
'按语言或文档类型拆散到多套互不共享的发现机制。',
|
|
291
|
+
],
|
|
292
|
+
evidence,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
function buildDeterministicFactsCandidate(corpus) {
|
|
296
|
+
const evidence = matchEvidence(corpus, [
|
|
297
|
+
'ast-only',
|
|
298
|
+
'fallback',
|
|
299
|
+
'low confidence',
|
|
300
|
+
'静默降级',
|
|
301
|
+
'graceful degradation',
|
|
302
|
+
'confidence',
|
|
303
|
+
'结构化事实',
|
|
304
|
+
'deterministic',
|
|
305
|
+
], 4);
|
|
306
|
+
if (evidence.length < 2) {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
key: 'deterministic-facts',
|
|
311
|
+
score: 89 + evidence.length,
|
|
312
|
+
title: '优先保留确定性事实层并对 LLM 增强做诚实降级',
|
|
313
|
+
category: 'quality',
|
|
314
|
+
confidence: 'high',
|
|
315
|
+
inferred: false,
|
|
316
|
+
summary: '把结构化事实抽取与 narrative 增强分层,LLM 不可用时仍保留 AST/规则输出。',
|
|
317
|
+
decision: '将 API、配置、依赖图、模块签名等确定性事实保留在 parser/graph 层;LLM 仅用于 explanation、summary 与 narrative,失败时静默降级为 AST-only / low-confidence 输出。',
|
|
318
|
+
context: [
|
|
319
|
+
'当前产品明确区分结构化事实与 narrative 输出,并把低置信度和降级路径作为一等能力暴露。',
|
|
320
|
+
'这类工具链如果让 LLM 直接决定 canonical facts,会把文档体系变成不可验证的文本生成器。',
|
|
321
|
+
],
|
|
322
|
+
consequences: [
|
|
323
|
+
'输出质量更可控,coverage audit 和 drift 检测仍能基于确定性事实运行。',
|
|
324
|
+
'当 LLM 不可用时,文档可读性会下降,但不会完全失去可用性。',
|
|
325
|
+
],
|
|
326
|
+
alternatives: [
|
|
327
|
+
'让 LLM 直接生成或决定 API / 配置 / 依赖等结构事实。',
|
|
328
|
+
'在增强失败时终止整次文档生成,而不是保留保守输出。',
|
|
329
|
+
],
|
|
330
|
+
evidence,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
function buildCurrentSpecFactSourceCandidate(corpus) {
|
|
334
|
+
const evidence = matchEvidence(corpus, [
|
|
335
|
+
'current-spec',
|
|
336
|
+
'产品规范活文档',
|
|
337
|
+
'事实源',
|
|
338
|
+
'spec-driver-sync',
|
|
339
|
+
'product facts',
|
|
340
|
+
], 4).filter((entry) => entry.sourceType === 'current-spec' || entry.sourceType === 'spec' || entry.sourceType === 'commit');
|
|
341
|
+
if (evidence.length < 1) {
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
key: 'current-spec-fact-source',
|
|
346
|
+
score: 86 + evidence.length,
|
|
347
|
+
title: '将 current-spec 作为产品文档的上游事实源',
|
|
348
|
+
category: 'product-facts',
|
|
349
|
+
confidence: 'high',
|
|
350
|
+
inferred: false,
|
|
351
|
+
summary: '先用 Spec Driver 聚合产品级事实,再派生 README、产品概览和对外文档,减少事实漂移。',
|
|
352
|
+
decision: '把 `current-spec.md` 作为产品/文档层的规范化事实源之一,优先消费聚合后的产品语义而不是重复从代码和增量 spec 中猜测产品定位。',
|
|
353
|
+
context: [
|
|
354
|
+
'当前仓库同时存在 reverse-spec 与 spec-driver,两者的职责边界之一就是“事实聚合”和“文档派生”分层。',
|
|
355
|
+
'没有产品级事实源时,对外文档会在 README、spec 和实现之间反复漂移。',
|
|
356
|
+
],
|
|
357
|
+
consequences: [
|
|
358
|
+
'README / product overview / feature brief 可以共享同一套产品事实摘要。',
|
|
359
|
+
'需要保证 sync 链路的及时性,否则 current-spec 会成为过时缓存。',
|
|
360
|
+
],
|
|
361
|
+
alternatives: [
|
|
362
|
+
'每次生成对外文档都直接从增量 spec 与代码重新拼接产品语义。',
|
|
363
|
+
'完全依赖 README 或 issue 文本作为产品事实来源。',
|
|
364
|
+
],
|
|
365
|
+
evidence,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function buildAppendOnlySessionCandidate(corpus) {
|
|
369
|
+
const evidence = matchEvidence(corpus, [
|
|
370
|
+
'append-only',
|
|
371
|
+
'session_mutations',
|
|
372
|
+
'rename_session',
|
|
373
|
+
'tag_session',
|
|
374
|
+
'追加式',
|
|
375
|
+
'append only',
|
|
376
|
+
], 4);
|
|
377
|
+
if (evidence.length < 2) {
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
key: 'append-only-session-metadata',
|
|
382
|
+
score: 84 + evidence.length,
|
|
383
|
+
title: '对会话元数据采用 append-only 更新策略',
|
|
384
|
+
category: 'storage',
|
|
385
|
+
confidence: 'medium',
|
|
386
|
+
inferred: false,
|
|
387
|
+
summary: '通过追加元数据记录而非重写整份 transcript,降低并发写风险并保持读取兼容性。',
|
|
388
|
+
decision: '会话标题、标签等变更采用 append-only 元数据行追加,并在读取时应用最后一条记录生效的规则。',
|
|
389
|
+
context: [
|
|
390
|
+
'会话 transcript 往往体积较大,且运行时可能同时读取尾部或追加新消息。',
|
|
391
|
+
'全量重写 transcript 成本高,也更容易在并发场景下损坏或产生竞争。',
|
|
392
|
+
],
|
|
393
|
+
consequences: [
|
|
394
|
+
'写路径更轻,兼容 tail-read/re-append 场景。',
|
|
395
|
+
'读取端需要承担“最后一条生效”的合并逻辑。',
|
|
396
|
+
],
|
|
397
|
+
alternatives: [
|
|
398
|
+
'每次修改标题或标签都整文件重写 transcript。',
|
|
399
|
+
'把会话元数据迁到独立数据库或索引服务中维护。',
|
|
400
|
+
],
|
|
401
|
+
evidence,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
function buildContainerizedRuntimeCandidate(corpus) {
|
|
405
|
+
const deploymentAvailable = corpus.architectureOverview?.deploymentView?.available ?? false;
|
|
406
|
+
const evidence = deploymentAvailable
|
|
407
|
+
? matchEvidence(corpus, ['docker', 'compose', 'deployment', 'runtime-topology', 'container'], 4)
|
|
408
|
+
: [];
|
|
409
|
+
if (!deploymentAvailable || evidence.length < 2) {
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
412
|
+
return {
|
|
413
|
+
key: 'containerized-runtime-boundary',
|
|
414
|
+
score: 82 + evidence.length,
|
|
415
|
+
title: '使用容器化部署边界表达运行时拓扑',
|
|
416
|
+
category: 'deployment',
|
|
417
|
+
confidence: 'medium',
|
|
418
|
+
inferred: false,
|
|
419
|
+
summary: '通过 Dockerfile / Compose 等制品显式建模服务、端口和依赖,而不是把运行时假设隐含在脚本里。',
|
|
420
|
+
decision: '将服务镜像、端口、环境变量和依赖关系显式维护为容器化运行时拓扑,并把部署视图作为架构文档的一等组成部分。',
|
|
421
|
+
context: [
|
|
422
|
+
'项目已经暴露出可解析的 Docker / Compose 运行时制品,说明部署边界是系统结构的一部分。',
|
|
423
|
+
'当部署事实没有结构化表达时,架构文档很难稳定覆盖服务关系与运维约束。',
|
|
424
|
+
],
|
|
425
|
+
consequences: [
|
|
426
|
+
'运行时和部署约束更易被文档、审计和后续工具消费。',
|
|
427
|
+
'部署视图将依赖制品完整性;缺少 Docker/Compose 时需要降级说明。',
|
|
428
|
+
],
|
|
429
|
+
alternatives: [
|
|
430
|
+
'仅在 README 或脚本里零散描述运行时与部署方式。',
|
|
431
|
+
'不把部署事实纳入架构文档主链路。',
|
|
432
|
+
],
|
|
433
|
+
evidence,
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
function buildModularSeparationCandidate(corpus) {
|
|
437
|
+
const coreModules = corpus.architectureNarrative.keyModules.filter((module) => module.role === 'core');
|
|
438
|
+
if (coreModules.length < 2) {
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
const evidence = coreModules
|
|
442
|
+
.slice(0, 3)
|
|
443
|
+
.map((module) => evidenceFromModule(module))
|
|
444
|
+
.filter((entry) => entry !== null);
|
|
445
|
+
return {
|
|
446
|
+
key: 'modular-surface-separation',
|
|
447
|
+
score: 78 + evidence.length,
|
|
448
|
+
title: '按核心职责拆分模块边界,而不是把主流程堆叠在单一入口中',
|
|
449
|
+
category: 'modularity',
|
|
450
|
+
confidence: 'medium',
|
|
451
|
+
inferred: true,
|
|
452
|
+
summary: '把核心职责拆成多个聚焦模块,有助于让主流程、支撑能力和验证层分别演化。',
|
|
453
|
+
decision: `将核心能力优先拆分到 ${coreModules.slice(0, 3).map((module) => `\`${module.sourceTarget}\``).join('、')} 等职责明确的模块中,再由高层入口聚合。`,
|
|
454
|
+
context: [
|
|
455
|
+
'当前项目的关键模块已经呈现出相对清晰的职责分离,而不是所有能力都堆在同一目录或同一入口文件。',
|
|
456
|
+
'这类结构更有利于后续为不同文档视图、运行时路径或测试层提供稳定边界。',
|
|
457
|
+
],
|
|
458
|
+
consequences: [
|
|
459
|
+
'模块级文档和组件级文档更容易建立阅读路径与责任边界。',
|
|
460
|
+
'如果聚合层过薄或缺少索引,阅读者仍可能感到跳转成本高,需要额外 narrative/overview 支撑。',
|
|
461
|
+
],
|
|
462
|
+
alternatives: [
|
|
463
|
+
'把主流程、支撑能力和验证代码集中在单一模块或入口文件中。',
|
|
464
|
+
'依赖目录命名约定而不显式维护职责边界。',
|
|
465
|
+
],
|
|
466
|
+
evidence,
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
function buildGenericCoreSeparationCandidate(corpus) {
|
|
470
|
+
const module = corpus.architectureNarrative.keyModules[0];
|
|
471
|
+
if (!module) {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
const evidence = [evidenceFromModule(module)].filter((item) => item !== null);
|
|
475
|
+
return {
|
|
476
|
+
key: 'core-separation-fallback',
|
|
477
|
+
score: 60,
|
|
478
|
+
title: '围绕核心模块维持聚焦职责边界',
|
|
479
|
+
category: 'modularity',
|
|
480
|
+
confidence: 'medium',
|
|
481
|
+
inferred: true,
|
|
482
|
+
summary: '即便缺少更多产品/历史上下文,当前输出也显示系统围绕少数核心模块组织主流程。',
|
|
483
|
+
decision: `优先围绕 \`${module.sourceTarget}\` 一类核心模块组织主链路,并避免把支撑逻辑无边界地扩散到所有文件。`,
|
|
484
|
+
context: [
|
|
485
|
+
'当前可见证据有限,但架构叙事仍指向了若干核心模块与导出符号。',
|
|
486
|
+
],
|
|
487
|
+
consequences: [
|
|
488
|
+
'可以为后续 component view / dynamic scenarios 留出更稳定的分析入口。',
|
|
489
|
+
],
|
|
490
|
+
alternatives: [
|
|
491
|
+
'在证据不足的情况下完全放弃候选 ADR 输出。',
|
|
492
|
+
],
|
|
493
|
+
evidence,
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
function finalizeDraft(index, candidate) {
|
|
497
|
+
const decisionId = `ADR-${String(index).padStart(4, '0')}`;
|
|
498
|
+
const slug = slugify(candidate.title);
|
|
499
|
+
const sourceTypes = uniqueSorted(candidate.evidence.map((item) => item.sourceType));
|
|
500
|
+
return {
|
|
501
|
+
decisionId,
|
|
502
|
+
slug,
|
|
503
|
+
title: candidate.title,
|
|
504
|
+
status: 'proposed',
|
|
505
|
+
category: candidate.category,
|
|
506
|
+
confidence: candidate.confidence,
|
|
507
|
+
inferred: candidate.inferred,
|
|
508
|
+
sourceTypes,
|
|
509
|
+
summary: candidate.summary,
|
|
510
|
+
decision: candidate.decision,
|
|
511
|
+
context: candidate.context,
|
|
512
|
+
consequences: candidate.consequences,
|
|
513
|
+
alternatives: candidate.alternatives,
|
|
514
|
+
evidence: candidate.evidence,
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
function buildIndexSummary(corpus, drafts) {
|
|
518
|
+
const lines = [
|
|
519
|
+
`本批次基于 ${drafts.length} 个候选 ADR 草稿组织决策索引,输入事实主要来自架构叙事、模式提示、现有 spec/current-spec 与近期提交历史。`,
|
|
520
|
+
];
|
|
521
|
+
if (corpus.patternHints?.model.matchedPatterns.length) {
|
|
522
|
+
lines.push(`模式提示中识别到 ${corpus.patternHints.model.matchedPatterns.length} 条可用模式证据,可作为 ADR 背景的结构化补充。`);
|
|
523
|
+
}
|
|
524
|
+
if (corpus.commits.length > 0) {
|
|
525
|
+
lines.push(`已纳入最近 ${Math.min(corpus.commits.length, 20)} 条 git 提交标题作为演进证据。`);
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
lines.push('未检测到可读取的 git 提交历史,部分 ADR 仅基于当前代码与文档结构推断。');
|
|
529
|
+
}
|
|
530
|
+
return lines;
|
|
531
|
+
}
|
|
532
|
+
function evidenceFromModule(module) {
|
|
533
|
+
const excerpt = [module.intentSummary, module.businessSummary, module.dependencySummary]
|
|
534
|
+
.filter(Boolean)
|
|
535
|
+
.join(' ')
|
|
536
|
+
.trim();
|
|
537
|
+
if (!excerpt) {
|
|
538
|
+
return null;
|
|
539
|
+
}
|
|
540
|
+
return {
|
|
541
|
+
sourceType: 'architecture-narrative',
|
|
542
|
+
label: module.sourceTarget,
|
|
543
|
+
path: 'architecture-narrative.md',
|
|
544
|
+
excerpt,
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
function summarizeArchitectureSection(section) {
|
|
548
|
+
if (!section) {
|
|
549
|
+
return '';
|
|
550
|
+
}
|
|
551
|
+
const parts = [
|
|
552
|
+
section.title,
|
|
553
|
+
section.description ?? '',
|
|
554
|
+
...section.nodes.slice(0, 4).map((node) => `${node.kind}:${node.label}`),
|
|
555
|
+
...section.edges.slice(0, 4).map((edge) => `${edge.from}->${edge.to}:${edge.relation}`),
|
|
556
|
+
section.missingReason ?? '',
|
|
557
|
+
].filter(Boolean);
|
|
558
|
+
return parts.join(' | ');
|
|
559
|
+
}
|
|
560
|
+
function matchEvidence(corpus, keywords, limit) {
|
|
561
|
+
const loweredKeywords = keywords.map((item) => item.toLowerCase());
|
|
562
|
+
const matchedItems = corpus.entries
|
|
563
|
+
.map((entry) => {
|
|
564
|
+
const loweredText = entry.text.toLowerCase();
|
|
565
|
+
const score = loweredKeywords.reduce((sum, keyword) => (loweredText.includes(keyword) ? sum + 1 : sum), 0);
|
|
566
|
+
if (score === 0) {
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
return {
|
|
570
|
+
score,
|
|
571
|
+
evidence: {
|
|
572
|
+
sourceType: entry.sourceType,
|
|
573
|
+
label: entry.label,
|
|
574
|
+
path: entry.path,
|
|
575
|
+
excerpt: summarizeEvidenceText(entry.text, loweredKeywords),
|
|
576
|
+
},
|
|
577
|
+
};
|
|
578
|
+
})
|
|
579
|
+
.filter((item) => item !== null);
|
|
580
|
+
return matchedItems
|
|
581
|
+
.sort((left, right) => right.score - left.score || left.evidence.label.localeCompare(right.evidence.label))
|
|
582
|
+
.slice(0, limit)
|
|
583
|
+
.map((item) => item.evidence);
|
|
584
|
+
}
|
|
585
|
+
function summarizeEvidenceText(text, loweredKeywords) {
|
|
586
|
+
const normalized = text.replace(/\r/g, '');
|
|
587
|
+
const lines = normalized.split('\n').map((line) => line.trim()).filter(Boolean);
|
|
588
|
+
const matchedLine = lines.find((line) => {
|
|
589
|
+
const lowered = line.toLowerCase();
|
|
590
|
+
return loweredKeywords.some((keyword) => lowered.includes(keyword));
|
|
591
|
+
});
|
|
592
|
+
const source = matchedLine ?? lines[0] ?? normalized;
|
|
593
|
+
return source.length > 240 ? `${source.slice(0, 237)}...` : source;
|
|
594
|
+
}
|
|
595
|
+
function collectMarkdownEvidenceFiles(projectRoot) {
|
|
596
|
+
const specsDir = path.join(projectRoot, 'specs');
|
|
597
|
+
if (!fs.existsSync(specsDir)) {
|
|
598
|
+
return [];
|
|
599
|
+
}
|
|
600
|
+
const results = [];
|
|
601
|
+
walkDirectory(specsDir, (filePath) => {
|
|
602
|
+
const relative = normalizeProjectPath(filePath, projectRoot).toLowerCase();
|
|
603
|
+
if (relative.endsWith('/current-spec.md')
|
|
604
|
+
|| relative.endsWith('/blueprint.md')
|
|
605
|
+
|| relative.endsWith('/spec.md')) {
|
|
606
|
+
results.push(filePath);
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
return results.sort((left, right) => left.localeCompare(right));
|
|
610
|
+
}
|
|
611
|
+
function collectSourcePathSignals(projectRoot) {
|
|
612
|
+
const results = [];
|
|
613
|
+
walkDirectory(projectRoot, (filePath) => {
|
|
614
|
+
const relative = normalizeProjectPath(filePath, projectRoot);
|
|
615
|
+
const lower = relative.toLowerCase();
|
|
616
|
+
if (lower.startsWith('.git/')
|
|
617
|
+
|| lower.startsWith('node_modules/')
|
|
618
|
+
|| lower.startsWith('dist/')
|
|
619
|
+
|| lower.startsWith('coverage/')
|
|
620
|
+
|| lower.startsWith('specs/')
|
|
621
|
+
|| lower.startsWith('.reverse-spec')) {
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
results.push(relative);
|
|
625
|
+
});
|
|
626
|
+
return results.sort((left, right) => left.localeCompare(right));
|
|
627
|
+
}
|
|
628
|
+
function walkDirectory(dir, onFile) {
|
|
629
|
+
if (!fs.existsSync(dir)) {
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
633
|
+
if (entry.isSymbolicLink()) {
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
636
|
+
const fullPath = path.join(dir, entry.name);
|
|
637
|
+
if (entry.isDirectory()) {
|
|
638
|
+
walkDirectory(fullPath, onFile);
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
if (entry.isFile()) {
|
|
642
|
+
onFile(fullPath);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
function loadRecentGitCommits(projectRoot) {
|
|
647
|
+
const result = spawnSync('git', ['-C', projectRoot, 'log', '--no-color', '--pretty=format:%H%x1f%s%x1f%b%x1e', '-n', '20'], { encoding: 'utf-8' });
|
|
648
|
+
if (result.status !== 0 || !result.stdout) {
|
|
649
|
+
return [];
|
|
650
|
+
}
|
|
651
|
+
return result.stdout
|
|
652
|
+
.split('\x1e')
|
|
653
|
+
.map((chunk) => chunk.trim())
|
|
654
|
+
.filter(Boolean)
|
|
655
|
+
.map((chunk) => {
|
|
656
|
+
const [sha, subject, body] = chunk.split('\x1f');
|
|
657
|
+
return {
|
|
658
|
+
sha: sha ?? '',
|
|
659
|
+
subject: subject ?? '',
|
|
660
|
+
body: body ?? '',
|
|
661
|
+
};
|
|
662
|
+
})
|
|
663
|
+
.filter((entry) => entry.sha && entry.subject);
|
|
664
|
+
}
|
|
665
|
+
function normalizeProjectPath(filePath, projectRoot) {
|
|
666
|
+
const relative = path.relative(projectRoot, filePath);
|
|
667
|
+
return relative.split(path.sep).join('/');
|
|
668
|
+
}
|
|
669
|
+
function readTrimmed(filePath, maxLength) {
|
|
670
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
671
|
+
const normalized = content.replace(/\r/g, '');
|
|
672
|
+
return normalized.length > maxLength ? normalized.slice(0, maxLength) : normalized;
|
|
673
|
+
}
|
|
674
|
+
function slugify(value) {
|
|
675
|
+
return value
|
|
676
|
+
.toLowerCase()
|
|
677
|
+
.replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-')
|
|
678
|
+
.replace(/-+/g, '-')
|
|
679
|
+
.replace(/^-|-$/g, '')
|
|
680
|
+
.slice(0, 80);
|
|
681
|
+
}
|
|
682
|
+
function uniqueSorted(items) {
|
|
683
|
+
return [...new Set(items)].sort((left, right) => left.localeCompare(right));
|
|
684
|
+
}
|
|
685
|
+
//# sourceMappingURL=adr-decision-pipeline.js.map
|