spectra-cli 4.1.1 → 4.3.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 +12 -5
- package/dist/.spectra-build-meta.json +9 -0
- 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 +42 -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 +168 -61
- 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 +74 -5
- package/dist/batch/batch-orchestrator.d.ts.map +1 -1
- package/dist/batch/batch-orchestrator.js +583 -70
- 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 +21 -28
- package/dist/batch/delta-regenerator.js.map +1 -1
- package/dist/batch/module-grouper.d.ts +9 -2
- package/dist/batch/module-grouper.d.ts.map +1 -1
- package/dist/batch/module-grouper.js +3 -1
- package/dist/batch/module-grouper.js.map +1 -1
- package/dist/batch/regen-plan.d.ts +78 -0
- package/dist/batch/regen-plan.d.ts.map +1 -0
- package/dist/batch/regen-plan.js +93 -0
- package/dist/batch/regen-plan.js.map +1 -0
- package/dist/cli/commands/batch.d.ts.map +1 -1
- package/dist/cli/commands/batch.js +36 -8
- package/dist/cli/commands/batch.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/commands/scaffold-kb.d.ts +9 -0
- package/dist/cli/commands/scaffold-kb.d.ts.map +1 -0
- package/dist/cli/commands/scaffold-kb.js +179 -0
- package/dist/cli/commands/scaffold-kb.js.map +1 -0
- package/dist/cli/index.js +33 -14
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/error-handler.d.ts +0 -6
- package/dist/cli/utils/error-handler.d.ts.map +1 -1
- package/dist/cli/utils/error-handler.js +0 -13
- package/dist/cli/utils/error-handler.js.map +1 -1
- package/dist/cli/utils/parse-args.d.ts +55 -3
- package/dist/cli/utils/parse-args.d.ts.map +1 -1
- package/dist/cli/utils/parse-args.js +176 -13
- package/dist/cli/utils/parse-args.js.map +1 -1
- package/dist/cli/version-meta.d.ts +16 -0
- package/dist/cli/version-meta.d.ts.map +1 -0
- package/dist/cli/version-meta.js +28 -0
- package/dist/cli/version-meta.js.map +1 -0
- package/dist/core/ast-analyzer.d.ts.map +1 -1
- package/dist/core/ast-analyzer.js +75 -5
- package/dist/core/ast-analyzer.js.map +1 -1
- package/dist/core/import-resolver.d.ts +93 -0
- package/dist/core/import-resolver.d.ts.map +1 -0
- package/dist/core/import-resolver.js +414 -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 +21 -0
- package/dist/core/single-spec-orchestrator.d.ts.map +1 -1
- package/dist/core/single-spec-orchestrator.js +187 -23
- package/dist/core/single-spec-orchestrator.js.map +1 -1
- package/dist/core/skeleton-hash.d.ts +33 -0
- package/dist/core/skeleton-hash.d.ts.map +1 -0
- package/dist/core/skeleton-hash.js +76 -0
- package/dist/core/skeleton-hash.js.map +1 -0
- package/dist/core/tree-sitter-analyzer.d.ts +7 -0
- package/dist/core/tree-sitter-analyzer.d.ts.map +1 -1
- package/dist/core/tree-sitter-analyzer.js +32 -1
- package/dist/core/tree-sitter-analyzer.js.map +1 -1
- package/dist/core/tree-sitter-fallback.d.ts +12 -4
- package/dist/core/tree-sitter-fallback.d.ts.map +1 -1
- package/dist/core/tree-sitter-fallback.js +160 -12
- package/dist/core/tree-sitter-fallback.js.map +1 -1
- package/dist/extraction/extraction-types.d.ts +25 -25
- package/dist/extraction/image-extractor.d.ts.map +1 -1
- package/dist/extraction/image-extractor.js +3 -1
- package/dist/extraction/image-extractor.js.map +1 -1
- package/dist/extraction/markdown-extractor.d.ts.map +1 -1
- package/dist/extraction/markdown-extractor.js +3 -1
- package/dist/extraction/markdown-extractor.js.map +1 -1
- package/dist/generator/frontmatter.d.ts +5 -0
- package/dist/generator/frontmatter.d.ts.map +1 -1
- package/dist/generator/frontmatter.js +4 -0
- package/dist/generator/frontmatter.js.map +1 -1
- 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/kb-mcp/index.d.ts +14 -0
- package/dist/kb-mcp/index.d.ts.map +1 -0
- package/dist/kb-mcp/index.js +24 -0
- package/dist/kb-mcp/index.js.map +1 -0
- package/dist/kb-mcp/lib/kb-error.d.ts +21 -0
- package/dist/kb-mcp/lib/kb-error.d.ts.map +1 -0
- package/dist/kb-mcp/lib/kb-error.js +28 -0
- package/dist/kb-mcp/lib/kb-error.js.map +1 -0
- package/dist/kb-mcp/lib/kb-locator.d.ts +58 -0
- package/dist/kb-mcp/lib/kb-locator.d.ts.map +1 -0
- package/dist/kb-mcp/lib/kb-locator.js +85 -0
- package/dist/kb-mcp/lib/kb-locator.js.map +1 -0
- package/dist/kb-mcp/lib/result-merger.d.ts +35 -0
- package/dist/kb-mcp/lib/result-merger.d.ts.map +1 -0
- package/dist/kb-mcp/lib/result-merger.js +64 -0
- package/dist/kb-mcp/lib/result-merger.js.map +1 -0
- package/dist/kb-mcp/server.d.ts +12 -0
- package/dist/kb-mcp/server.d.ts.map +1 -0
- package/dist/kb-mcp/server.js +29 -0
- package/dist/kb-mcp/server.js.map +1 -0
- package/dist/kb-mcp/tools/kb-api-lookup.d.ts +28 -0
- package/dist/kb-mcp/tools/kb-api-lookup.d.ts.map +1 -0
- package/dist/kb-mcp/tools/kb-api-lookup.js +237 -0
- package/dist/kb-mcp/tools/kb-api-lookup.js.map +1 -0
- package/dist/kb-mcp/tools/kb-doc-lookup.d.ts +20 -0
- package/dist/kb-mcp/tools/kb-doc-lookup.d.ts.map +1 -0
- package/dist/kb-mcp/tools/kb-doc-lookup.js +92 -0
- package/dist/kb-mcp/tools/kb-doc-lookup.js.map +1 -0
- package/dist/kb-mcp/tools/kb-search.d.ts +23 -0
- package/dist/kb-mcp/tools/kb-search.d.ts.map +1 -0
- package/dist/kb-mcp/tools/kb-search.js +126 -0
- package/dist/kb-mcp/tools/kb-search.js.map +1 -0
- 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 +39 -0
- package/dist/knowledge-graph/import-resolver.d.ts.map +1 -0
- package/dist/knowledge-graph/import-resolver.js +214 -0
- package/dist/knowledge-graph/import-resolver.js.map +1 -0
- package/dist/knowledge-graph/incremental.d.ts +131 -0
- package/dist/knowledge-graph/incremental.d.ts.map +1 -0
- package/dist/knowledge-graph/incremental.js +432 -0
- package/dist/knowledge-graph/incremental.js.map +1 -0
- package/dist/knowledge-graph/index.d.ts +85 -0
- package/dist/knowledge-graph/index.d.ts.map +1 -0
- package/dist/knowledge-graph/index.js +198 -0
- package/dist/knowledge-graph/index.js.map +1 -0
- package/dist/knowledge-graph/module-derivation.d.ts +252 -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 +310 -0
- package/dist/knowledge-graph/persistence.d.ts.map +1 -0
- package/dist/knowledge-graph/persistence.js +280 -0
- package/dist/knowledge-graph/persistence.js.map +1 -0
- package/dist/knowledge-graph/query-helpers.d.ts +191 -0
- package/dist/knowledge-graph/query-helpers.d.ts.map +1 -0
- package/dist/knowledge-graph/query-helpers.js +559 -0
- package/dist/knowledge-graph/query-helpers.js.map +1 -0
- package/dist/knowledge-graph/relativize.d.ts +51 -0
- package/dist/knowledge-graph/relativize.d.ts.map +1 -0
- package/dist/knowledge-graph/relativize.js +104 -0
- package/dist/knowledge-graph/relativize.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 +53 -0
- package/dist/mcp/agent-context-tools.d.ts.map +1 -0
- package/dist/mcp/agent-context-tools.js +806 -0
- package/dist/mcp/agent-context-tools.js.map +1 -0
- package/dist/mcp/file-nav-tools.d.ts +42 -0
- package/dist/mcp/file-nav-tools.d.ts.map +1 -0
- package/dist/mcp/file-nav-tools.js +318 -0
- package/dist/mcp/file-nav-tools.js.map +1 -0
- package/dist/mcp/graph-tools.d.ts +22 -0
- package/dist/mcp/graph-tools.d.ts.map +1 -1
- package/dist/mcp/graph-tools.js +204 -133
- package/dist/mcp/graph-tools.js.map +1 -1
- package/dist/mcp/lib/file-nav-helpers.d.ts +128 -0
- package/dist/mcp/lib/file-nav-helpers.d.ts.map +1 -0
- package/dist/mcp/lib/file-nav-helpers.js +305 -0
- package/dist/mcp/lib/file-nav-helpers.js.map +1 -0
- 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/lib/telemetry.d.ts +69 -0
- package/dist/mcp/lib/telemetry.d.ts.map +1 -0
- package/dist/mcp/lib/telemetry.js +113 -0
- package/dist/mcp/lib/telemetry.js.map +1 -0
- package/dist/mcp/lib/tool-response.d.ts +46 -0
- package/dist/mcp/lib/tool-response.d.ts.map +1 -0
- package/dist/mcp/lib/tool-response.js +83 -0
- package/dist/mcp/lib/tool-response.js.map +1 -0
- package/dist/mcp/server.d.ts +14 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +216 -158
- 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 +80 -6
- package/dist/models/code-skeleton.d.ts.map +1 -1
- package/dist/models/code-skeleton.js +30 -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 +173 -94
- package/dist/models/module-spec.d.ts.map +1 -1
- package/dist/models/module-spec.js +6 -0
- package/dist/models/module-spec.js.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 +15 -2
- package/dist/panoramic/builders/doc-graph-builder.d.ts.map +1 -1
- package/dist/panoramic/builders/doc-graph-builder.js +20 -0
- 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 +72 -2
- package/dist/panoramic/graph/graph-builder.d.ts.map +1 -1
- package/dist/panoramic/graph/graph-builder.js +330 -46
- 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 +49 -2
- package/dist/panoramic/graph/graph-query.d.ts.map +1 -1
- package/dist/panoramic/graph/graph-query.js +117 -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/graph/index.d.ts +2 -1
- package/dist/panoramic/graph/index.d.ts.map +1 -1
- package/dist/panoramic/graph/index.js +1 -1
- package/dist/panoramic/graph/index.js.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/adr-evidence-verifier.d.ts.map +1 -1
- package/dist/panoramic/pipelines/adr-evidence-verifier.js +1 -29
- package/dist/panoramic/pipelines/adr-evidence-verifier.js.map +1 -1
- 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/query.d.ts +1 -0
- package/dist/panoramic/query.d.ts.map +1 -1
- package/dist/panoramic/query.js +5 -0
- package/dist/panoramic/query.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/scaffold-kb/api-entities-serializer.d.ts +12 -0
- package/dist/scaffold-kb/api-entities-serializer.d.ts.map +1 -0
- package/dist/scaffold-kb/api-entities-serializer.js +144 -0
- package/dist/scaffold-kb/api-entities-serializer.js.map +1 -0
- package/dist/scaffold-kb/arbitration.d.ts +44 -0
- package/dist/scaffold-kb/arbitration.d.ts.map +1 -0
- package/dist/scaffold-kb/arbitration.js +144 -0
- package/dist/scaffold-kb/arbitration.js.map +1 -0
- package/dist/scaffold-kb/chunk-splitter.d.ts +20 -0
- package/dist/scaffold-kb/chunk-splitter.d.ts.map +1 -0
- package/dist/scaffold-kb/chunk-splitter.js +309 -0
- package/dist/scaffold-kb/chunk-splitter.js.map +1 -0
- package/dist/scaffold-kb/doc-graph-builder.d.ts +26 -0
- package/dist/scaffold-kb/doc-graph-builder.d.ts.map +1 -0
- package/dist/scaffold-kb/doc-graph-builder.js +72 -0
- package/dist/scaffold-kb/doc-graph-builder.js.map +1 -0
- package/dist/scaffold-kb/entity-extractor.d.ts +40 -0
- package/dist/scaffold-kb/entity-extractor.d.ts.map +1 -0
- package/dist/scaffold-kb/entity-extractor.js +0 -0
- package/dist/scaffold-kb/entity-extractor.js.map +1 -0
- package/dist/scaffold-kb/entity-heuristic.d.ts +14 -0
- package/dist/scaffold-kb/entity-heuristic.d.ts.map +1 -0
- package/dist/scaffold-kb/entity-heuristic.js +107 -0
- package/dist/scaffold-kb/entity-heuristic.js.map +1 -0
- package/dist/scaffold-kb/entity-matcher.d.ts +20 -0
- package/dist/scaffold-kb/entity-matcher.d.ts.map +1 -0
- package/dist/scaffold-kb/entity-matcher.js +53 -0
- package/dist/scaffold-kb/entity-matcher.js.map +1 -0
- package/dist/scaffold-kb/entity-util.d.ts +11 -0
- package/dist/scaffold-kb/entity-util.d.ts.map +1 -0
- package/dist/scaffold-kb/entity-util.js +23 -0
- package/dist/scaffold-kb/entity-util.js.map +1 -0
- package/dist/scaffold-kb/evidence-envelope.d.ts +17 -0
- package/dist/scaffold-kb/evidence-envelope.d.ts.map +1 -0
- package/dist/scaffold-kb/evidence-envelope.js +32 -0
- package/dist/scaffold-kb/evidence-envelope.js.map +1 -0
- package/dist/scaffold-kb/index.d.ts +20 -0
- package/dist/scaffold-kb/index.d.ts.map +1 -0
- package/dist/scaffold-kb/index.js +102 -0
- package/dist/scaffold-kb/index.js.map +1 -0
- package/dist/scaffold-kb/ingest/ingest-core.d.ts +47 -0
- package/dist/scaffold-kb/ingest/ingest-core.d.ts.map +1 -0
- package/dist/scaffold-kb/ingest/ingest-core.js +231 -0
- package/dist/scaffold-kb/ingest/ingest-core.js.map +1 -0
- package/dist/scaffold-kb/ingest/office-parser.d.ts +33 -0
- package/dist/scaffold-kb/ingest/office-parser.d.ts.map +1 -0
- package/dist/scaffold-kb/ingest/office-parser.js +187 -0
- package/dist/scaffold-kb/ingest/office-parser.js.map +1 -0
- package/dist/scaffold-kb/ingest/url-fetcher.d.ts +43 -0
- package/dist/scaffold-kb/ingest/url-fetcher.d.ts.map +1 -0
- package/dist/scaffold-kb/ingest/url-fetcher.js +245 -0
- package/dist/scaffold-kb/ingest/url-fetcher.js.map +1 -0
- package/dist/scaffold-kb/ingester.d.ts +38 -0
- package/dist/scaffold-kb/ingester.d.ts.map +1 -0
- package/dist/scaffold-kb/ingester.js +261 -0
- package/dist/scaffold-kb/ingester.js.map +1 -0
- package/dist/scaffold-kb/injection-format.d.ts +25 -0
- package/dist/scaffold-kb/injection-format.d.ts.map +1 -0
- package/dist/scaffold-kb/injection-format.js +55 -0
- package/dist/scaffold-kb/injection-format.js.map +1 -0
- package/dist/scaffold-kb/kb-writer.d.ts +13 -0
- package/dist/scaffold-kb/kb-writer.d.ts.map +1 -0
- package/dist/scaffold-kb/kb-writer.js +69 -0
- package/dist/scaffold-kb/kb-writer.js.map +1 -0
- package/dist/scaffold-kb/keyword-extract.d.ts +16 -0
- package/dist/scaffold-kb/keyword-extract.d.ts.map +1 -0
- package/dist/scaffold-kb/keyword-extract.js +49 -0
- package/dist/scaffold-kb/keyword-extract.js.map +1 -0
- package/dist/scaffold-kb/query-sanitizer.d.ts +28 -0
- package/dist/scaffold-kb/query-sanitizer.d.ts.map +1 -0
- package/dist/scaffold-kb/query-sanitizer.js +38 -0
- package/dist/scaffold-kb/query-sanitizer.js.map +1 -0
- package/dist/scaffold-kb/recall-eval.d.ts +48 -0
- package/dist/scaffold-kb/recall-eval.d.ts.map +1 -0
- package/dist/scaffold-kb/recall-eval.js +55 -0
- package/dist/scaffold-kb/recall-eval.js.map +1 -0
- package/dist/scaffold-kb/schema-compat.d.ts +22 -0
- package/dist/scaffold-kb/schema-compat.d.ts.map +1 -0
- package/dist/scaffold-kb/schema-compat.js +32 -0
- package/dist/scaffold-kb/schema-compat.js.map +1 -0
- package/dist/scaffold-kb/search-core.d.ts +42 -0
- package/dist/scaffold-kb/search-core.d.ts.map +1 -0
- package/dist/scaffold-kb/search-core.js +89 -0
- package/dist/scaffold-kb/search-core.js.map +1 -0
- package/dist/scaffold-kb/sqlite-engine.d.ts +58 -0
- package/dist/scaffold-kb/sqlite-engine.d.ts.map +1 -0
- package/dist/scaffold-kb/sqlite-engine.js +61 -0
- package/dist/scaffold-kb/sqlite-engine.js.map +1 -0
- package/dist/scaffold-kb/sqlite-writer.d.ts +18 -0
- package/dist/scaffold-kb/sqlite-writer.d.ts.map +1 -0
- package/dist/scaffold-kb/sqlite-writer.js +76 -0
- package/dist/scaffold-kb/sqlite-writer.js.map +1 -0
- package/dist/scaffold-kb/tokenizer.d.ts +26 -0
- package/dist/scaffold-kb/tokenizer.d.ts.map +1 -0
- package/dist/scaffold-kb/tokenizer.js +97 -0
- package/dist/scaffold-kb/tokenizer.js.map +1 -0
- package/dist/scaffold-kb/types.d.ts +157 -0
- package/dist/scaffold-kb/types.d.ts.map +1 -0
- package/dist/scaffold-kb/types.js +5 -0
- package/dist/scaffold-kb/types.js.map +1 -0
- package/dist/utils/file-scanner.d.ts +15 -0
- package/dist/utils/file-scanner.d.ts.map +1 -1
- package/dist/utils/file-scanner.js +18 -1
- package/dist/utils/file-scanner.js.map +1 -1
- package/dist/utils/string-distance.d.ts +20 -0
- package/dist/utils/string-distance.d.ts.map +1 -0
- package/dist/utils/string-distance.js +38 -0
- package/dist/utils/string-distance.js.map +1 -0
- package/package.json +22 -3
- package/plugins/demo-kb-en/.claude-plugin/plugin.json +11 -0
- package/plugins/demo-kb-en/.mcp.json +8 -0
- package/plugins/demo-kb-en/FIXTURE.json +23 -0
- package/plugins/demo-kb-en/FIXTURE.md +53 -0
- package/plugins/demo-kb-en/ingest-samples/meeting-notes.md +13 -0
- package/plugins/demo-kb-en/kb/api-entities.json +3445 -0
- package/plugins/demo-kb-en/kb/chunks.sqlite +0 -0
- package/plugins/demo-kb-en/kb/doc-graph.json +113 -0
- package/plugins/demo-kb-zh/.claude-plugin/plugin.json +11 -0
- package/plugins/demo-kb-zh/.mcp.json +8 -0
- package/plugins/demo-kb-zh/FIXTURE.json +23 -0
- package/plugins/demo-kb-zh/FIXTURE.md +63 -0
- package/plugins/demo-kb-zh/ingest-samples/meeting-notes.md +13 -0
- package/plugins/demo-kb-zh/kb/api-entities.json +990 -0
- package/plugins/demo-kb-zh/kb/chunks.sqlite +0 -0
- package/plugins/demo-kb-zh/kb/doc-graph.json +113 -0
- package/plugins/spec-driver/.claude-plugin/plugin.json +1 -1
- package/plugins/spec-driver/README.md +50 -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 +108 -1
- package/plugins/spec-driver/config/orchestration.yaml +39 -31
- package/plugins/spec-driver/contracts/orchestration-overrides-contract.yaml +27 -0
- package/plugins/spec-driver/contracts/orchestration-schema.mjs +272 -227
- package/plugins/spec-driver/contracts/wrapper-source-of-truth.yaml +3 -0
- package/plugins/spec-driver/docs/customization.md +134 -0
- package/plugins/spec-driver/docs/spectra-mcp-integration.md +165 -0
- package/plugins/spec-driver/hooks/hooks.json +9 -0
- package/plugins/spec-driver/hooks/stop-fix-compliance-check.sh +36 -0
- package/plugins/spec-driver/lib/delegation-contract.mjs +84 -0
- package/plugins/spec-driver/lib/orchestration-resolver.mjs +49 -0
- package/plugins/spec-driver/lib/orchestrator.mjs +29 -1
- package/plugins/spec-driver/lib/preference-rules.mjs +96 -0
- package/plugins/spec-driver/scripts/codex-skills.sh +28 -28
- package/plugins/spec-driver/scripts/dev/spike-fix-compliance-e2e.mjs +130 -0
- package/plugins/spec-driver/scripts/fix-compliance-judge.mjs +415 -0
- package/plugins/spec-driver/scripts/generate-adoption-insights.mjs +48 -1
- package/plugins/spec-driver/scripts/goal-loop-cli.mjs +307 -0
- package/plugins/spec-driver/scripts/init-project.sh +56 -0
- package/plugins/spec-driver/scripts/kb-prequery.mjs +125 -0
- package/plugins/spec-driver/scripts/lib/config-schema.mjs +200 -94
- package/plugins/spec-driver/scripts/lib/ensure-gitignore.sh +277 -0
- package/plugins/spec-driver/scripts/lib/extract-wrapper-body.mjs +136 -0
- package/plugins/spec-driver/scripts/lib/fix-compliance-core.mjs +434 -0
- package/plugins/spec-driver/scripts/lib/fix-compliance-io.mjs +335 -0
- package/plugins/spec-driver/scripts/lib/goal-loop-core.mjs +783 -0
- package/plugins/spec-driver/scripts/lib/init-project-output.sh +28 -0
- package/plugins/spec-driver/scripts/lib/load-zod.mjs +62 -0
- package/plugins/spec-driver/scripts/lib/project-profile-resolver.mjs +141 -49
- package/plugins/spec-driver/scripts/lib/project-profile-schema.mjs +88 -54
- package/plugins/spec-driver/scripts/postinstall.sh +13 -1
- package/plugins/spec-driver/scripts/record-workflow-run.mjs +75 -0
- package/plugins/spec-driver/scripts/sync-delegation-contract.mjs +187 -0
- package/plugins/spec-driver/scripts/sync-preference-rules.mjs +148 -0
- package/plugins/spec-driver/scripts/validate-orchestrator-models.mjs +156 -0
- package/plugins/spec-driver/scripts/validate-wrapper-sources.mjs +46 -1
- package/plugins/spec-driver/skills/spec-driver-feature/SKILL.md +302 -0
- package/plugins/spec-driver/skills/spec-driver-fix/SKILL.md +97 -8
- package/plugins/spec-driver/skills/spec-driver-implement/SKILL.md +18 -0
- package/plugins/spec-driver/skills/spec-driver-refactor/SKILL.md +10 -0
- package/plugins/spec-driver/skills/spec-driver-resume/SKILL.md +12 -1
- package/plugins/spec-driver/skills/spec-driver-story/SKILL.md +30 -0
- package/plugins/spec-driver/templates/delegation-contract.md +27 -0
- package/plugins/spec-driver/templates/goal-loop-override-template.yaml +284 -0
- package/plugins/spec-driver/templates/preference-rules.md +39 -0
- package/plugins/spec-driver/templates/specify-base/project-context-template.yaml +10 -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/module-spec.hbs +1 -0
- package/templates/product-overview.hbs +1 -1
|
@@ -11,101 +11,156 @@
|
|
|
11
11
|
* - resolveEffectiveConfig() effective config 合并
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { loadZod } from './load-zod.mjs';
|
|
15
15
|
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
// ────────────────────────────────────────
|
|
19
|
-
|
|
20
|
-
const modelNameSchema = z.enum(['opus', 'sonnet', 'haiku'])
|
|
21
|
-
.or(z.string().min(1));
|
|
22
|
-
|
|
23
|
-
const agentOverrideSchema = z.object({
|
|
24
|
-
model: modelNameSchema.optional(),
|
|
25
|
-
}).strict();
|
|
26
|
-
|
|
27
|
-
const agentsSchema = z.record(
|
|
28
|
-
z.string(),
|
|
29
|
-
agentOverrideSchema,
|
|
30
|
-
).optional();
|
|
31
|
-
|
|
32
|
-
const aliasMapSchema = z.record(z.string(), z.string());
|
|
33
|
-
|
|
34
|
-
const modelCompatSchema = z.object({
|
|
35
|
-
runtime: z.enum(['auto', 'claude', 'codex']).default('auto'),
|
|
36
|
-
aliases: z.object({
|
|
37
|
-
codex: aliasMapSchema.optional(),
|
|
38
|
-
claude: aliasMapSchema.optional(),
|
|
39
|
-
}).optional(),
|
|
40
|
-
defaults: z.object({
|
|
41
|
-
codex: z.string().optional(),
|
|
42
|
-
claude: z.string().optional(),
|
|
43
|
-
}).optional(),
|
|
44
|
-
}).optional();
|
|
45
|
-
|
|
46
|
-
const codexSchema = z.object({
|
|
47
|
-
service_tier: z.enum(['fast', 'standard', 'flex']).default('fast'),
|
|
48
|
-
}).optional();
|
|
49
|
-
|
|
50
|
-
const codexThinkingSchema = z.object({
|
|
51
|
-
default_level: z.enum(['low', 'medium', 'high', 'xhigh']).default('xhigh'),
|
|
52
|
-
level_map: z.record(z.string(), z.enum(['low', 'medium', 'high', 'xhigh'])).optional(),
|
|
53
|
-
}).optional();
|
|
54
|
-
|
|
55
|
-
const researchSchema = z.object({
|
|
56
|
-
default_mode: z.enum([
|
|
57
|
-
'auto', 'full', 'tech-only', 'product-only',
|
|
58
|
-
'codebase-scan', 'skip', 'custom',
|
|
59
|
-
]).default('auto'),
|
|
60
|
-
custom_steps: z.array(z.string()).default([]),
|
|
61
|
-
}).optional();
|
|
62
|
-
|
|
63
|
-
const verificationSchema = z.object({
|
|
64
|
-
commands: z.record(z.string(), z.record(z.string(), z.string())).default({}),
|
|
65
|
-
monorepo: z.object({
|
|
66
|
-
enabled: z.boolean().default(true),
|
|
67
|
-
}).optional(),
|
|
68
|
-
timeout: z.number().int().positive().optional().default(300),
|
|
69
|
-
}).optional();
|
|
70
|
-
|
|
71
|
-
const gatePauseSchema = z.object({
|
|
72
|
-
pause: z.enum(['always', 'auto', 'on_failure']),
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const gatesSchema = z.record(z.string(), gatePauseSchema).optional();
|
|
76
|
-
|
|
77
|
-
const qualityGatesSchema = z.object({
|
|
78
|
-
auto_continue_on_warning: z.boolean().default(true),
|
|
79
|
-
pause_on_critical: z.boolean().default(true),
|
|
80
|
-
}).optional();
|
|
81
|
-
|
|
82
|
-
const retrySchema = z.object({
|
|
83
|
-
max_attempts: z.number().int().min(0).max(10).default(2),
|
|
84
|
-
}).optional();
|
|
85
|
-
|
|
86
|
-
const progressSchema = z.object({
|
|
87
|
-
show_stage_progress: z.boolean().default(true),
|
|
88
|
-
show_stage_summary: z.boolean().default(true),
|
|
89
|
-
}).optional();
|
|
16
|
+
// 经共享 helper 同步加载 zod;缺失时 zodAvailable=false,模块加载不崩
|
|
17
|
+
const { z, available: zodAvailable } = loadZod();
|
|
90
18
|
|
|
91
19
|
// ────────────────────────────────────────
|
|
92
|
-
// 顶层 Schema
|
|
20
|
+
// 子 Schema + 顶层 Schema
|
|
93
21
|
// ────────────────────────────────────────
|
|
22
|
+
//
|
|
23
|
+
// 全部 schema 求值必须包进 zodAvailable 守卫:缺 zod 时模块体完全不触碰 z,
|
|
24
|
+
// 否则会从 MODULE_NOT_FOUND 退化为 ReferenceError —— 等于没修。
|
|
25
|
+
// ESM 语法限制 export const 不能进 if 块,故 specDriverConfigSchema 用 let + 末尾 export。
|
|
26
|
+
|
|
27
|
+
let specDriverConfigSchema = null;
|
|
28
|
+
|
|
29
|
+
if (zodAvailable) {
|
|
30
|
+
const modelNameSchema = z.enum(['opus', 'sonnet', 'haiku'])
|
|
31
|
+
.or(z.string().min(1));
|
|
32
|
+
|
|
33
|
+
const agentOverrideSchema = z.object({
|
|
34
|
+
model: modelNameSchema.optional(),
|
|
35
|
+
}).strict();
|
|
36
|
+
|
|
37
|
+
const agentsSchema = z.record(
|
|
38
|
+
z.string(),
|
|
39
|
+
agentOverrideSchema,
|
|
40
|
+
).optional();
|
|
41
|
+
|
|
42
|
+
const aliasMapSchema = z.record(z.string(), z.string());
|
|
43
|
+
|
|
44
|
+
const modelCompatSchema = z.object({
|
|
45
|
+
runtime: z.enum(['auto', 'claude', 'codex']).default('auto'),
|
|
46
|
+
aliases: z.object({
|
|
47
|
+
codex: aliasMapSchema.optional(),
|
|
48
|
+
claude: aliasMapSchema.optional(),
|
|
49
|
+
}).optional(),
|
|
50
|
+
defaults: z.object({
|
|
51
|
+
codex: z.string().optional(),
|
|
52
|
+
claude: z.string().optional(),
|
|
53
|
+
}).optional(),
|
|
54
|
+
}).optional();
|
|
55
|
+
|
|
56
|
+
const codexSchema = z.object({
|
|
57
|
+
service_tier: z.enum(['fast', 'standard', 'flex']).default('fast'),
|
|
58
|
+
}).optional();
|
|
59
|
+
|
|
60
|
+
const codexThinkingSchema = z.object({
|
|
61
|
+
default_level: z.enum(['low', 'medium', 'high', 'xhigh']).default('xhigh'),
|
|
62
|
+
level_map: z.record(z.string(), z.enum(['low', 'medium', 'high', 'xhigh'])).optional(),
|
|
63
|
+
}).optional();
|
|
64
|
+
|
|
65
|
+
const researchSchema = z.object({
|
|
66
|
+
default_mode: z.enum([
|
|
67
|
+
'auto', 'full', 'tech-only', 'product-only',
|
|
68
|
+
'codebase-scan', 'skip', 'custom',
|
|
69
|
+
]).default('auto'),
|
|
70
|
+
custom_steps: z.array(z.string()).default([]),
|
|
71
|
+
}).optional();
|
|
72
|
+
|
|
73
|
+
const verificationSchema = z.object({
|
|
74
|
+
commands: z.record(z.string(), z.record(z.string(), z.string())).default({}),
|
|
75
|
+
monorepo: z.object({
|
|
76
|
+
enabled: z.boolean().default(true),
|
|
77
|
+
}).optional(),
|
|
78
|
+
timeout: z.number().int().positive().optional().default(300),
|
|
79
|
+
}).optional();
|
|
80
|
+
|
|
81
|
+
const gatePauseSchema = z.object({
|
|
82
|
+
pause: z.enum(['always', 'auto', 'on_failure']),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const gatesSchema = z.record(z.string(), gatePauseSchema).optional();
|
|
86
|
+
|
|
87
|
+
const qualityGatesSchema = z.object({
|
|
88
|
+
auto_continue_on_warning: z.boolean().default(true),
|
|
89
|
+
pause_on_critical: z.boolean().default(true),
|
|
90
|
+
}).optional();
|
|
91
|
+
|
|
92
|
+
const retrySchema = z.object({
|
|
93
|
+
max_attempts: z.number().int().min(0).max(10).default(2),
|
|
94
|
+
}).optional();
|
|
95
|
+
|
|
96
|
+
const progressSchema = z.object({
|
|
97
|
+
show_stage_progress: z.boolean().default(true),
|
|
98
|
+
show_stage_summary: z.boolean().default(true),
|
|
99
|
+
}).optional();
|
|
100
|
+
|
|
101
|
+
// goal_loop 段(Feature 201):feature mode goal_loop agent_mode 的预算/迭代配置。
|
|
102
|
+
// 用 .default({}) 而非 .optional():省略该段时 z.object 会用四项各自 default 填全,
|
|
103
|
+
// 使 validateConfig 输出始终含 goal_loop.* 全默认值(W2 修复——避免运行时读到 undefined 而非 5)。
|
|
104
|
+
// 四项均带 default —— 不破坏现有 config 校验(未声明该段的现有 config 仍通过,只是补默认)。
|
|
105
|
+
// 仅在 .specify/orchestration-overrides.yaml 启用 goal_loop 时被编排器读取(FR-005/006/007)。
|
|
106
|
+
const goalLoopSchema = z.object({
|
|
107
|
+
// 最大迭代轮数上限(FR-005),到顶且未达标则停止进 GATE_VERIFY
|
|
108
|
+
max_iterations: z.number().int().min(1).default(5),
|
|
109
|
+
// 连续无进展(五维 delta 全 0)轮数触发早停(FR-006)
|
|
110
|
+
no_progress_max_rounds: z.number().int().min(1).default(2),
|
|
111
|
+
// 单轮 verify 墙钟上限(秒,FR-007)——timeout 强制、可机器校验,主预算
|
|
112
|
+
max_verify_seconds: z.number().positive().default(300),
|
|
113
|
+
// 单轮编排器可见委派/调用数上限(FR-007)——best-effort 粗粒度安全网,辅助上限
|
|
114
|
+
max_tool_invocations: z.number().int().min(1).default(50),
|
|
115
|
+
// 命令集完整性校验(F204):full 报告必须包含这些 kind 类别的 PASS 命令才能 REACHED_GOAL。
|
|
116
|
+
// 默认 [](跳过校验,保向后兼容);项目级 opt-in:['build','test','lint','check']。
|
|
117
|
+
full_required_kinds: z.array(z.enum(['build', 'test', 'lint', 'check'])).default([]),
|
|
118
|
+
}).default({});
|
|
119
|
+
|
|
120
|
+
// Spectra batch 并发配置(Feature 146)。concurrency 的接受集与运行时
|
|
121
|
+
// src/config/spec-driver-config.ts:readBatchConcurrency 对齐:有限 number 或可解析为
|
|
122
|
+
// 有限数字的字符串(如 quoted "3")。整数化与越界裁剪交由运行时 normalizeConcurrency
|
|
123
|
+
// 统一处理,故此处不加 int()/positive(),避免 validate gate 与运行时对同一配置判定相反。
|
|
124
|
+
const concurrencySchema = z.union([
|
|
125
|
+
z.number().finite(),
|
|
126
|
+
z.string().refine(
|
|
127
|
+
(s) => { const t = s.trim(); return t.length > 0 && Number.isFinite(Number(t)); },
|
|
128
|
+
{ message: '必须是可解析为有限数字的字符串(如 "3")' },
|
|
129
|
+
),
|
|
130
|
+
]);
|
|
131
|
+
const batchSchema = z.object({
|
|
132
|
+
concurrency: concurrencySchema.optional(),
|
|
133
|
+
}).strict().optional();
|
|
134
|
+
|
|
135
|
+
// fix_compliance 段(Feature 208,FR-015):fix 模式流程依从性强制程度。
|
|
136
|
+
// 用 .default({}) 而非 .optional():省略该段时 enforcement 被 default 填为 'block',
|
|
137
|
+
// 使 validateConfig 输出始终含 fix_compliance.enforcement(与 goal_loop 同惯例)。
|
|
138
|
+
// 注意:Stop hook 判定路径刻意不 import 本模块(走 simple-yaml 非抛出式读取,见
|
|
139
|
+
// contracts/fix-compliance-config-field.md);本 schema 只服务 validate-config 声明式校验。
|
|
140
|
+
const fixComplianceSchema = z.object({
|
|
141
|
+
enforcement: z.enum(['block', 'warn', 'off']).default('block'),
|
|
142
|
+
}).default({});
|
|
143
|
+
|
|
144
|
+
specDriverConfigSchema = z.object({
|
|
145
|
+
preset: z.enum(['balanced', 'quality-first', 'cost-efficient']).default('balanced'),
|
|
146
|
+
batch: batchSchema,
|
|
147
|
+
agents: agentsSchema,
|
|
148
|
+
model_compat: modelCompatSchema,
|
|
149
|
+
codex: codexSchema,
|
|
150
|
+
codex_thinking: codexThinkingSchema,
|
|
151
|
+
research: researchSchema,
|
|
152
|
+
verification: verificationSchema,
|
|
153
|
+
quality_gates: qualityGatesSchema,
|
|
154
|
+
gate_policy: z.enum(['strict', 'balanced', 'autonomous']).default('balanced'),
|
|
155
|
+
gates: gatesSchema,
|
|
156
|
+
retry: retrySchema,
|
|
157
|
+
progress: progressSchema,
|
|
158
|
+
goal_loop: goalLoopSchema,
|
|
159
|
+
fix_compliance: fixComplianceSchema,
|
|
160
|
+
}).strict();
|
|
161
|
+
}
|
|
94
162
|
|
|
95
|
-
export
|
|
96
|
-
preset: z.enum(['balanced', 'quality-first', 'cost-efficient']).default('balanced'),
|
|
97
|
-
agents: agentsSchema,
|
|
98
|
-
model_compat: modelCompatSchema,
|
|
99
|
-
codex: codexSchema,
|
|
100
|
-
codex_thinking: codexThinkingSchema,
|
|
101
|
-
research: researchSchema,
|
|
102
|
-
verification: verificationSchema,
|
|
103
|
-
quality_gates: qualityGatesSchema,
|
|
104
|
-
gate_policy: z.enum(['strict', 'balanced', 'autonomous']).default('balanced'),
|
|
105
|
-
gates: gatesSchema,
|
|
106
|
-
retry: retrySchema,
|
|
107
|
-
progress: progressSchema,
|
|
108
|
-
}).strict();
|
|
163
|
+
export { specDriverConfigSchema, zodAvailable };
|
|
109
164
|
|
|
110
165
|
// ────────────────────────────────────────
|
|
111
166
|
// 常量
|
|
@@ -127,6 +182,16 @@ export const BUILTIN_DEFAULTS = {
|
|
|
127
182
|
'model_compat.runtime': 'auto',
|
|
128
183
|
'codex.service_tier': 'fast',
|
|
129
184
|
'codex_thinking.default_level': 'xhigh',
|
|
185
|
+
// goal_loop 默认值(Feature 201,W2 修复)——与 goalLoopSchema 各项 default 一致,
|
|
186
|
+
// 使 resolveEffectiveConfig 在 config 省略 goal_loop 段时也 surface 默认值。
|
|
187
|
+
'goal_loop.max_iterations': 5,
|
|
188
|
+
'goal_loop.no_progress_max_rounds': 2,
|
|
189
|
+
'goal_loop.max_verify_seconds': 300,
|
|
190
|
+
'goal_loop.max_tool_invocations': 50,
|
|
191
|
+
// F204:full 轮必需命令 kind 类别,默认 [](跳过校验,保向后兼容)。
|
|
192
|
+
'goal_loop.full_required_kinds': [],
|
|
193
|
+
// fix_compliance 默认值(Feature 208,FR-015)——block 为缺省强制程度。
|
|
194
|
+
'fix_compliance.enforcement': 'block',
|
|
130
195
|
};
|
|
131
196
|
|
|
132
197
|
/** preset 默认值表 */
|
|
@@ -231,9 +296,9 @@ export function suggestField(unknown, knownFields) {
|
|
|
231
296
|
|
|
232
297
|
/** 顶层 Schema 合法字段名列表 */
|
|
233
298
|
const KNOWN_TOP_LEVEL_FIELDS = [
|
|
234
|
-
'preset', 'agents', 'model_compat', 'codex', 'codex_thinking',
|
|
299
|
+
'preset', 'batch', 'agents', 'model_compat', 'codex', 'codex_thinking',
|
|
235
300
|
'research', 'verification', 'quality_gates', 'gate_policy',
|
|
236
|
-
'gates', 'retry', 'progress',
|
|
301
|
+
'gates', 'retry', 'progress', 'goal_loop', 'fix_compliance',
|
|
237
302
|
];
|
|
238
303
|
|
|
239
304
|
/**
|
|
@@ -249,6 +314,21 @@ export function validateConfig(parsedYaml) {
|
|
|
249
314
|
return { success: true, data: {}, diagnostics };
|
|
250
315
|
}
|
|
251
316
|
|
|
317
|
+
// 缺 zod 降级:无法做 schema 校验,best-effort 接受原样配置并标 degraded。
|
|
318
|
+
// success=true 保证 validate-config.mjs 不误判为校验失败退非 0(其退出码只看 error 级诊断)。
|
|
319
|
+
if (!zodAvailable) {
|
|
320
|
+
return {
|
|
321
|
+
success: true,
|
|
322
|
+
data: (parsedYaml && typeof parsedYaml === 'object') ? parsedYaml : {},
|
|
323
|
+
degraded: true,
|
|
324
|
+
diagnostics: [{
|
|
325
|
+
level: 'warning',
|
|
326
|
+
code: 'config.zod-unavailable',
|
|
327
|
+
message: '未能加载 zod,已跳过 spec-driver.config.yaml schema 校验并 best-effort 接受配置;如需完整校验请在已安装依赖的目录运行(npm i)或从仓内源路径运行',
|
|
328
|
+
}],
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
252
332
|
const result = specDriverConfigSchema.safeParse(parsedYaml);
|
|
253
333
|
|
|
254
334
|
if (result.success) {
|
|
@@ -302,11 +382,13 @@ export function validateConfig(parsedYaml) {
|
|
|
302
382
|
path,
|
|
303
383
|
});
|
|
304
384
|
} else if (issue.code === 'too_small' && issue.type === 'number') {
|
|
305
|
-
//
|
|
385
|
+
// 数值下界校验(如 timeout / goal_loop.* 预算项)。
|
|
386
|
+
// 部分字段允许小数(如 goal_loop.max_verify_seconds 用 z.number().positive()),
|
|
387
|
+
// 故文案统一用"正数"而非"正整数",避免误导(W3 修复)。
|
|
306
388
|
diagnostics.push({
|
|
307
389
|
level: 'error',
|
|
308
390
|
code: 'config.invalid-positive-int',
|
|
309
|
-
message: `\`${path}\`
|
|
391
|
+
message: `\`${path}\` 必须为正数,当前值: ${issue.minimum !== undefined ? `< ${issue.minimum}` : '非法'}`,
|
|
310
392
|
path,
|
|
311
393
|
});
|
|
312
394
|
} else {
|
|
@@ -389,6 +471,12 @@ export function resolveEffectiveConfig(options) {
|
|
|
389
471
|
'model_compat.runtime',
|
|
390
472
|
'codex.service_tier',
|
|
391
473
|
'codex_thinking.default_level',
|
|
474
|
+
'goal_loop.max_iterations',
|
|
475
|
+
'goal_loop.no_progress_max_rounds',
|
|
476
|
+
'goal_loop.max_verify_seconds',
|
|
477
|
+
'goal_loop.max_tool_invocations',
|
|
478
|
+
'goal_loop.full_required_kinds',
|
|
479
|
+
'fix_compliance.enforcement',
|
|
392
480
|
];
|
|
393
481
|
|
|
394
482
|
for (const dotPath of nestedKeys) {
|
|
@@ -400,6 +488,24 @@ export function resolveEffectiveConfig(options) {
|
|
|
400
488
|
}
|
|
401
489
|
}
|
|
402
490
|
|
|
491
|
+
// Spectra batch 子系统旋钮(Feature 146)——刻意与上方编排器 nestedKeys 分开处理。
|
|
492
|
+
// why 单独成块、且只在用户显式配置时才展示:
|
|
493
|
+
// 1) batch.concurrency 虽落在同一份 spec-driver.config.yaml,却由 Spectra batch 运行时消费,
|
|
494
|
+
// 而非 spec-driver 编排器;标注子系统来源以免被误读成编排器并发旋钮
|
|
495
|
+
// (编排器并发是 orchestration-overrides.yaml 的 parallel_scheduling.max_concurrent_tasks)。
|
|
496
|
+
// 2) 其默认值 3 的 canonical source 在 src/ 运行时侧(cli/commands/batch.ts:resolveBatchConcurrency
|
|
497
|
+
// 与 batch-orchestrator.ts 的 `?? 3`),不在本插件脚本;故刻意不进 BUILTIN_DEFAULTS——
|
|
498
|
+
// 在此 hardcode 3 会与运行时默认形成双源,一旦运行时漂移就显示过期值,比"不展示"更误导
|
|
499
|
+
// (见 111423f Codex R1 WARNING 2 的取舍)。
|
|
500
|
+
const batchConcurrency = getNestedValue(configYaml, 'batch.concurrency');
|
|
501
|
+
if (batchConcurrency !== undefined) {
|
|
502
|
+
entries.push({
|
|
503
|
+
key: 'batch.concurrency',
|
|
504
|
+
value: batchConcurrency,
|
|
505
|
+
source: 'config.yaml (spectra batch)',
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
|
|
403
509
|
// preset 默认值提供的 agent 模型配置
|
|
404
510
|
const presetDefaults = PRESET_DEFAULTS[effectivePreset] || {};
|
|
405
511
|
const agents = configYaml.agents || {};
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Spec Driver - ignore 自举共享库(Feature 207)
|
|
3
|
+
# 由 init-project.sh 与 postinstall.sh 共同 source。
|
|
4
|
+
# 职责:确保 Spec Driver 落盘产物的 4 条 ignore 规则就位,避免脚手架与本机绝对路径
|
|
5
|
+
# 污染宿主 repo 的 git diff / 交付 patch。提供两个入口:
|
|
6
|
+
# - ensure_spec_driver_gitignore → 写宿主 <project_root>/.gitignore(团队共享)
|
|
7
|
+
# - ensure_spec_driver_git_exclude → 写 <project_root>/.git/info/exclude(非 tracked,零 diff)
|
|
8
|
+
# 两者共享内部注入实现 _spec_driver_inject_entries,行为契约一致(幂等、CRLF/NUL/symlink/
|
|
9
|
+
# negation 防御、mkdir 原子锁保护并发)。
|
|
10
|
+
#
|
|
11
|
+
# 注意:本文件只定义函数,不含 set -e / 顶层执行逻辑,避免被 source 时影响调用方主流程。
|
|
12
|
+
# 函数内所有写入均显式检查返回值,不依赖 trap EXIT(避免污染被 source 进
|
|
13
|
+
# set -euo pipefail 调用方的退出钩子)。
|
|
14
|
+
|
|
15
|
+
# Spec Driver 落盘产物的固定 4 条 ignore 条目(与开发仓库 .gitignore 一致,顺序即注入顺序):
|
|
16
|
+
# .specify/.spec-driver-path — 机器绝对路径(隐私 / 可移植)
|
|
17
|
+
# .specify/runs/ — 本地运行态
|
|
18
|
+
# .specify/scorecards/ — 插件默认品复制,可再生
|
|
19
|
+
# .specify/templates/ — 插件默认品复制,可再生
|
|
20
|
+
# 写死为字面量作为唯一事实来源,不从外部读取,避免引入新的路径依赖。
|
|
21
|
+
SPEC_DRIVER_GITIGNORE_ENTRIES=(
|
|
22
|
+
".specify/.spec-driver-path"
|
|
23
|
+
".specify/runs/"
|
|
24
|
+
".specify/scorecards/"
|
|
25
|
+
".specify/templates/"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# ── 并发取舍说明(W1 修复,Codex 四轮)─────────────────────────────────────
|
|
29
|
+
# 本库刻意**不做 stale 锁抢占**:曾有的 mtime 阈值 + rmdir 重试逻辑存在 ABA 竞态——
|
|
30
|
+
# 预置过期锁 + 高并发时,多个进程会同判 stale、rmdir 互删对方刚建的新锁,导致多个进程
|
|
31
|
+
# 同时进入临界区重复注入。故抢锁失败一律直接 skipped:0。
|
|
32
|
+
# 残余风险:进程在临界区内被 SIGKILL → 孤儿锁使该 repo 永久 skip 注入。此风险经权衡接受:
|
|
33
|
+
# (1) 临界区为毫秒级窗口,命中概率极低;
|
|
34
|
+
# (2) 孤儿锁只造成静默跳过(主流程零影响,下次会话无法自愈但不报错),
|
|
35
|
+
# 危害远小于 ABA 重复写入把用户 .gitignore 堆出重复行。
|
|
36
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
# _spec_driver_has_nul <file>
|
|
39
|
+
# 检测文件是否含 NUL 字节(0x00)。含 NUL 的文件不是合法文本,装载为 shell 变量会截断,
|
|
40
|
+
# 无法可靠做整行匹配 → 一律拒写。跨平台实现:比较原始字节数与去除 NUL 后的字节数。
|
|
41
|
+
# 返回 0(真)表示含 NUL,返回 1(假)表示不含或读取失败。
|
|
42
|
+
_spec_driver_has_nul() {
|
|
43
|
+
local file="$1"
|
|
44
|
+
local raw stripped
|
|
45
|
+
raw="$(wc -c < "$file" 2>/dev/null)" || return 1
|
|
46
|
+
# LC_ALL=C 确保 tr 按字节而非多字节字符处理;去掉所有 NUL 后再计字节数
|
|
47
|
+
stripped="$(LC_ALL=C tr -d '\000' < "$file" 2>/dev/null | wc -c)" || return 1
|
|
48
|
+
# 归一化空白(wc 输出可能带前导空格)
|
|
49
|
+
raw="${raw//[[:space:]]/}"
|
|
50
|
+
stripped="${stripped//[[:space:]]/}"
|
|
51
|
+
[[ "$raw" != "$stripped" ]]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# _spec_driver_inject_entries <target_file> <with_header>
|
|
55
|
+
#
|
|
56
|
+
# 向 <target_file> 注入 SPEC_DRIVER_GITIGNORE_ENTRIES 中缺失的条目(幂等)。
|
|
57
|
+
# 调用方须在持锁状态下调用;本函数不负责加锁/解锁(由入口函数统一管理)。
|
|
58
|
+
#
|
|
59
|
+
# 参数:
|
|
60
|
+
# target_file - 目标 ignore 文件绝对路径(.gitignore 或 .git/info/exclude)
|
|
61
|
+
# with_header - "1" 表示新建文件时写注释头;"0" 表示不写(exclude 场景不带头)
|
|
62
|
+
#
|
|
63
|
+
# 行为契约:
|
|
64
|
+
# - target_file 为 symlink(含 dangling)→ 一律不写,stdout: failed:0
|
|
65
|
+
# (-L 检测必须先于 -f 分支:dangling symlink 时 [[ ! -f ]] 为真会走创建分支,
|
|
66
|
+
# `>` 重定向会跟随 symlink 在 symlink 指向的外部路径创建文件——安全隐患)
|
|
67
|
+
# - target_file 含 NUL 字节 → 拒写,stdout: failed:0(文件不被改动)
|
|
68
|
+
# - target_file 不存在 → 创建(with_header=1 时带注释头 + 4 行条目),stdout: created:N
|
|
69
|
+
# - target_file 存在但缺条目 → 精确整行匹配缺失项追加到末尾,stdout: appended:N
|
|
70
|
+
# - target_file 存在且 4 条全就位 → 不写文件(mtime 不变),stdout: ready:0
|
|
71
|
+
# - negation 尊重:归一化视图中若存在以 '!' 开头、去掉 '!' 后等于该条目或以该条目为
|
|
72
|
+
# 前缀的行(如 !.specify/templates/ 或 !.specify/templates/**),该条目跳过不追加
|
|
73
|
+
# (尊重用户显式 un-ignore 意图),跳过条目不计入 appended:N
|
|
74
|
+
# - 匹配采用 CRLF 归一化视图(tr -d '\r'):CRLF 行尾文件不被误判为缺失而重复追加;
|
|
75
|
+
# 但不改写原文件行尾
|
|
76
|
+
# - 写入失败(只读 FS 等)→ stdout: failed:0
|
|
77
|
+
# - 始终 return 0
|
|
78
|
+
_spec_driver_inject_entries() {
|
|
79
|
+
local target_file="$1"
|
|
80
|
+
local with_header="$2"
|
|
81
|
+
|
|
82
|
+
# symlink 防御(含 dangling):必须先于 -f 分支判断
|
|
83
|
+
if [[ -L "$target_file" ]]; then
|
|
84
|
+
printf 'failed:0\n'
|
|
85
|
+
return 0
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# NUL 防御:仅对已存在的普通文件检测(不存在时无从检测,创建分支会写纯文本)
|
|
89
|
+
if [[ -f "$target_file" ]] && _spec_driver_has_nul "$target_file"; then
|
|
90
|
+
printf 'failed:0\n'
|
|
91
|
+
return 0
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# 场景 1:文件不存在 → 创建新文件,stdout: created:N
|
|
95
|
+
if [[ ! -f "$target_file" ]]; then
|
|
96
|
+
# 关键 bash 地雷(W-A 修复):绝不用「复合命令组 { …; } > file」形式写入。
|
|
97
|
+
# 1. 命令组的重定向失败退出码在 `if ! { …; } > file` 形式下会被吞掉——
|
|
98
|
+
# 直接跑 rc=1,但 `if !` 包裹时不进 then 分支 → failed 分支永不触发 →
|
|
99
|
+
# 落到 created:N 误报(.git/info 被普通文件占用时 `> exclude` 必然失败)。
|
|
100
|
+
# 2. `> file 2>/dev/null` 中 stdout 重定向失败发生在 `2>/dev/null` 生效之前 →
|
|
101
|
+
# "Not a directory" 等 stderr 泄漏。
|
|
102
|
+
# 正解:内容先攒进变量,再用「简单命令」写入,且把 `2>/dev/null` 置于 `>` 之前
|
|
103
|
+
# 先吞 stderr。简单命令的 `if !` 重定向失败已实测能被捕获(bash 3.2 与 5.x 一致)。
|
|
104
|
+
local content=""
|
|
105
|
+
if [[ "$with_header" == "1" ]]; then
|
|
106
|
+
content="# Spec Driver 本地缓存与运行态(自动注入,可手动调整顺序)"$'\n'
|
|
107
|
+
fi
|
|
108
|
+
local entry
|
|
109
|
+
for entry in "${SPEC_DRIVER_GITIGNORE_ENTRIES[@]}"; do
|
|
110
|
+
content+="${entry}"$'\n'
|
|
111
|
+
done
|
|
112
|
+
if ! printf '%s' "$content" 2>/dev/null > "$target_file"; then
|
|
113
|
+
printf 'failed:0\n'
|
|
114
|
+
return 0
|
|
115
|
+
fi
|
|
116
|
+
printf 'created:%d\n' "${#SPEC_DRIVER_GITIGNORE_ENTRIES[@]}"
|
|
117
|
+
return 0
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# 场景 2/3:文件已存在 → 逐条精确整行匹配(CRLF 归一化视图),收集缺失项
|
|
121
|
+
# tr -d '\r' 剥离视图内的 CR,使 CRLF 行尾文件不被误判为缺失;不改写原文件。
|
|
122
|
+
local normalized_view
|
|
123
|
+
normalized_view="$(tr -d '\r' < "$target_file" 2>/dev/null)" || normalized_view=""
|
|
124
|
+
local missing=()
|
|
125
|
+
local entry
|
|
126
|
+
for entry in "${SPEC_DRIVER_GITIGNORE_ENTRIES[@]}"; do
|
|
127
|
+
# -F 纯字符串、-x 整行匹配:避免 .specify/runs/ 被 .specify/runs/xxx 宽松误判为已存在
|
|
128
|
+
# 用 here-string 而非管道喂 grep:调用方多为 set -o pipefail,大文件(>64KB pipe buffer)
|
|
129
|
+
# 且目标条目在文件前部时,grep -q 匹配即退会令 printf 写端收 SIGPIPE,管道退出码 141
|
|
130
|
+
# 被 pipefail 放大成整体失败 → 已存在条目被误判缺失而重复追加。here-string 无管道,规避此问题。
|
|
131
|
+
if grep -qxF -- "$entry" <<< "$normalized_view"; then
|
|
132
|
+
continue
|
|
133
|
+
fi
|
|
134
|
+
# negation 冲突检测:用户显式 un-ignore(! 前缀)时尊重其意图,跳过该条目。
|
|
135
|
+
# 匹配 !<entry> 精确等,或 !<entry>* 前缀形式(如 !.specify/templates/**)。
|
|
136
|
+
if _spec_driver_has_negation "$normalized_view" "$entry"; then
|
|
137
|
+
continue
|
|
138
|
+
fi
|
|
139
|
+
missing+=("$entry")
|
|
140
|
+
done
|
|
141
|
+
|
|
142
|
+
# 全部就位(或被 negation 尊重跳过)→ 不触碰文件(幂等契约:mtime 不变),stdout: ready:0
|
|
143
|
+
if [[ ${#missing[@]} -eq 0 ]]; then
|
|
144
|
+
printf 'ready:0\n'
|
|
145
|
+
return 0
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
# 部分缺失 → 追加缺失条目到文件末尾(不带注释头,追加场景保持幂等最简)
|
|
149
|
+
# 末尾无换行边界:若最后一个字节非换行符,先补一个 \n 再追加,避免与最后一行粘连
|
|
150
|
+
if [[ -s "$target_file" ]]; then
|
|
151
|
+
local last_char
|
|
152
|
+
last_char="$(tail -c 1 "$target_file" 2>/dev/null)"
|
|
153
|
+
if [[ -n "$last_char" ]]; then
|
|
154
|
+
# 2>/dev/null 置于 >> 之前先吞 stderr(同 W-A:避免重定向失败时 "Not a directory" 泄漏)
|
|
155
|
+
if ! printf '\n' 2>/dev/null >> "$target_file"; then
|
|
156
|
+
printf 'failed:0\n'
|
|
157
|
+
return 0
|
|
158
|
+
fi
|
|
159
|
+
fi
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
for entry in "${missing[@]}"; do
|
|
163
|
+
# 同上:2>/dev/null 前置于 >>,消除 stderr 泄漏
|
|
164
|
+
if ! printf '%s\n' "$entry" 2>/dev/null >> "$target_file"; then
|
|
165
|
+
printf 'failed:0\n'
|
|
166
|
+
return 0
|
|
167
|
+
fi
|
|
168
|
+
done
|
|
169
|
+
|
|
170
|
+
printf 'appended:%d\n' "${#missing[@]}"
|
|
171
|
+
return 0
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
# _spec_driver_has_negation <normalized_view> <entry>
|
|
175
|
+
# 判断归一化视图中是否存在尊重该条目的 negation 行(以 '!' 开头)。
|
|
176
|
+
# 命中形式:!<entry>(精确)或 !<entry> 后接任意字符(前缀,如 !.specify/templates/**)。
|
|
177
|
+
# 返回 0(真)表示存在 negation,返回 1(假)表示不存在。
|
|
178
|
+
_spec_driver_has_negation() {
|
|
179
|
+
local view="$1"
|
|
180
|
+
local entry="$2"
|
|
181
|
+
local line stripped
|
|
182
|
+
while IFS= read -r line; do
|
|
183
|
+
[[ "$line" == '!'* ]] || continue
|
|
184
|
+
stripped="${line#!}"
|
|
185
|
+
# 精确等 或 以 entry 为前缀(覆盖 !<entry> / !<entry>** / !<entry>foo)
|
|
186
|
+
if [[ "$stripped" == "$entry" || "$stripped" == "$entry"* ]]; then
|
|
187
|
+
return 0
|
|
188
|
+
fi
|
|
189
|
+
done <<< "$view"
|
|
190
|
+
return 1
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# _spec_driver_acquire_lock <lock_dir>
|
|
194
|
+
# 尝试获取 mkdir 原子锁。成功返回 0;失败(已被占用)返回 1。
|
|
195
|
+
# 不做 stale 抢占(见文件顶部并发取舍说明)。
|
|
196
|
+
_spec_driver_acquire_lock() {
|
|
197
|
+
mkdir "$1" 2>/dev/null
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
# ensure_spec_driver_gitignore <project_root>
|
|
201
|
+
#
|
|
202
|
+
# 写宿主 <project_root>/.gitignore(团队共享的 ignore 配置)。
|
|
203
|
+
# 行为契约见 plan.md §1.1:
|
|
204
|
+
# - 三态输出 created:N / appended:N / ready:0 / failed:0 / skipped:0
|
|
205
|
+
# - symlink / NUL / negation 防御见 _spec_driver_inject_entries
|
|
206
|
+
# - 非 git 目录也照常写入(用户后续 git init 即生效)
|
|
207
|
+
# - 并发:mkdir 原子锁保护临界区;抢锁失败 → skipped:0(不 stale 抢占)
|
|
208
|
+
# - 始终 return 0;仅 project_root 为空或非目录时 return 1
|
|
209
|
+
ensure_spec_driver_gitignore() {
|
|
210
|
+
local project_root="$1"
|
|
211
|
+
if [[ -z "$project_root" || ! -d "$project_root" ]]; then
|
|
212
|
+
return 1
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
local gitignore_file="${project_root}/.gitignore"
|
|
216
|
+
local lock_dir="${project_root}/.specify/.ensure-gitignore.lock"
|
|
217
|
+
|
|
218
|
+
# 锁父路径 .specify/ 兜底创建(.specify/ 是 Spec Driver 自身域,不越界)
|
|
219
|
+
mkdir -p "${project_root}/.specify" 2>/dev/null || true
|
|
220
|
+
|
|
221
|
+
if ! _spec_driver_acquire_lock "$lock_dir"; then
|
|
222
|
+
printf 'skipped:0\n'
|
|
223
|
+
return 0
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
local result
|
|
227
|
+
result="$(_spec_driver_inject_entries "$gitignore_file" "1")"
|
|
228
|
+
rmdir "$lock_dir" 2>/dev/null || true
|
|
229
|
+
printf '%s\n' "$result"
|
|
230
|
+
return 0
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
# ensure_spec_driver_git_exclude <project_root>
|
|
234
|
+
#
|
|
235
|
+
# 写 <project_root>/.git/info/exclude(Git 原生的非 tracked 项目级 ignore)。
|
|
236
|
+
# 动机:用户 repo 的 .gitignore 几乎都被 track,注入产生 `M .gitignore` 仍进 patch;
|
|
237
|
+
# 写 .git/info/exclude 零 diff 污染。这是分层防线的主防线。
|
|
238
|
+
# 行为契约:
|
|
239
|
+
# - 仅当 <project_root>/.git 是**目录**时执行;.git 为文件(worktree/submodule 的
|
|
240
|
+
# gitdir 指针)→ skipped:0(gitdir 解析复杂且 exclude 共享主仓库,.gitignore 路径覆盖)
|
|
241
|
+
# - 非 git repo(无 .git)→ skipped:0
|
|
242
|
+
# - .git/info/ 不存在则 mkdir -p 创建
|
|
243
|
+
# - 三态输出与防御同 _spec_driver_inject_entries(不带注释头)
|
|
244
|
+
# - 复用同一把锁(与 gitignore 各自独立拿/放锁,无死锁)
|
|
245
|
+
# - 始终 return 0;仅 project_root 为空或非目录时 return 1
|
|
246
|
+
ensure_spec_driver_git_exclude() {
|
|
247
|
+
local project_root="$1"
|
|
248
|
+
if [[ -z "$project_root" || ! -d "$project_root" ]]; then
|
|
249
|
+
return 1
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
local git_dir="${project_root}/.git"
|
|
253
|
+
# .git 必须是目录:非 git repo 或 worktree/submodule(.git 为文件)→ 跳过
|
|
254
|
+
if [[ ! -d "$git_dir" ]]; then
|
|
255
|
+
printf 'skipped:0\n'
|
|
256
|
+
return 0
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
local exclude_file="${git_dir}/info/exclude"
|
|
260
|
+
local lock_dir="${project_root}/.specify/.ensure-gitignore.lock"
|
|
261
|
+
|
|
262
|
+
# info/ 目录兜底创建(标准 git repo 一般已有,但防御缺失)
|
|
263
|
+
mkdir -p "${git_dir}/info" 2>/dev/null || true
|
|
264
|
+
# 锁父路径 .specify/ 兜底创建
|
|
265
|
+
mkdir -p "${project_root}/.specify" 2>/dev/null || true
|
|
266
|
+
|
|
267
|
+
if ! _spec_driver_acquire_lock "$lock_dir"; then
|
|
268
|
+
printf 'skipped:0\n'
|
|
269
|
+
return 0
|
|
270
|
+
fi
|
|
271
|
+
|
|
272
|
+
local result
|
|
273
|
+
result="$(_spec_driver_inject_entries "$exclude_file" "0")"
|
|
274
|
+
rmdir "$lock_dir" 2>/dev/null || true
|
|
275
|
+
printf '%s\n' "$result"
|
|
276
|
+
return 0
|
|
277
|
+
}
|