kibi-cli 2.2.0 → 2.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.
Files changed (183) hide show
  1. package/dist/cli-operation-loader.d.ts.map +1 -1
  2. package/dist/cli-operation-loader.js +3 -0
  3. package/dist/cli-operation-metadata.d.ts +4 -0
  4. package/dist/cli-operation-metadata.d.ts.map +1 -1
  5. package/dist/cli-operation-metadata.js +5 -0
  6. package/dist/cli-register-reporting.d.ts.map +1 -1
  7. package/dist/cli-register-reporting.js +4 -0
  8. package/dist/commands/check-diff.d.ts +5 -0
  9. package/dist/commands/check-diff.d.ts.map +1 -0
  10. package/dist/commands/check-diff.js +62 -0
  11. package/dist/commands/check-generated.d.ts.map +1 -1
  12. package/dist/commands/check-generated.js +41 -18
  13. package/dist/commands/check.d.ts.map +1 -1
  14. package/dist/commands/check.js +210 -73
  15. package/dist/commands/doctor.d.ts.map +1 -1
  16. package/dist/commands/doctor.js +63 -29
  17. package/dist/commands/github-init.d.ts.map +1 -1
  18. package/dist/commands/github-init.js +9 -2
  19. package/dist/commands/sync/manifest.d.ts.map +1 -1
  20. package/dist/commands/sync/manifest.js +3 -1
  21. package/dist/engine.d.ts +15 -1
  22. package/dist/engine.d.ts.map +1 -1
  23. package/dist/engine.js +252 -52
  24. package/dist/extractors/symbols-coordinator.d.ts +7 -0
  25. package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
  26. package/dist/extractors/symbols-coordinator.js +75 -39
  27. package/dist/operations/modeling/predicate-inference-1.js +1 -1
  28. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  29. package/dist/operations/mutation/source-authoring.js +175 -53
  30. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  31. package/dist/operations/mutation/upsert.js +5 -7
  32. package/dist/operations/planning/apply-plan.d.ts.map +1 -1
  33. package/dist/operations/planning/apply-plan.js +5 -9
  34. package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
  35. package/dist/operations/proof/ingest-proof.js +1 -0
  36. package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
  37. package/dist/operations/semantic-advisor/analysis-receipt.js +7 -1
  38. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  39. package/dist/operations/semantic-advisor/analyze-prose.js +26 -4
  40. package/dist/operations/semantic-advisor/clauses.d.ts +1 -0
  41. package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
  42. package/dist/operations/semantic-advisor/clauses.js +7 -1
  43. package/dist/performance-trace.d.ts +17 -0
  44. package/dist/performance-trace.d.ts.map +1 -0
  45. package/dist/performance-trace.js +134 -0
  46. package/dist/plugins/approved-source-analyzers.d.ts +13 -0
  47. package/dist/plugins/approved-source-analyzers.d.ts.map +1 -0
  48. package/dist/plugins/approved-source-analyzers.generated.d.ts +71 -0
  49. package/dist/plugins/approved-source-analyzers.generated.d.ts.map +1 -0
  50. package/dist/plugins/approved-source-analyzers.generated.js +77 -0
  51. package/dist/plugins/approved-source-analyzers.js +3 -0
  52. package/dist/plugins/maintenance-source-analysis.d.ts +14 -0
  53. package/dist/plugins/maintenance-source-analysis.d.ts.map +1 -0
  54. package/dist/plugins/maintenance-source-analysis.js +191 -0
  55. package/dist/plugins/registry.d.ts +2 -1
  56. package/dist/plugins/registry.d.ts.map +1 -1
  57. package/dist/plugins/registry.js +6 -1
  58. package/dist/plugins/source-analysis-service.d.ts +36 -1
  59. package/dist/plugins/source-analysis-service.d.ts.map +1 -1
  60. package/dist/plugins/source-analysis-service.js +184 -27
  61. package/dist/plugins/source-change-analysis.d.ts +15 -0
  62. package/dist/plugins/source-change-analysis.d.ts.map +1 -0
  63. package/dist/plugins/source-change-analysis.js +54 -0
  64. package/dist/plugins/source-classification.d.ts +41 -0
  65. package/dist/plugins/source-classification.d.ts.map +1 -0
  66. package/dist/plugins/source-classification.js +490 -0
  67. package/dist/prolog/swipl-resolver.d.ts +88 -0
  68. package/dist/prolog/swipl-resolver.d.ts.map +1 -0
  69. package/dist/prolog/swipl-resolver.js +446 -0
  70. package/dist/prolog.d.ts +15 -1
  71. package/dist/prolog.d.ts.map +1 -1
  72. package/dist/prolog.js +67 -6
  73. package/dist/public/impact/analyzer.d.ts.map +1 -1
  74. package/dist/public/impact/analyzer.js +56 -5
  75. package/dist/public/impact/diagnostics.d.ts.map +1 -1
  76. package/dist/public/impact/diagnostics.js +3 -1
  77. package/dist/public/impact/manifest.d.ts.map +1 -1
  78. package/dist/public/impact/manifest.js +15 -1
  79. package/dist/public/impact/source-changes.d.ts.map +1 -1
  80. package/dist/public/impact/source-changes.js +35 -27
  81. package/dist/public/impact/types.d.ts +2 -0
  82. package/dist/public/impact/types.d.ts.map +1 -1
  83. package/dist/public/operations/catalog.d.ts +44 -0
  84. package/dist/public/operations/catalog.d.ts.map +1 -1
  85. package/dist/public/operations/catalog.js +2 -0
  86. package/dist/public/operations/contracts.d.ts.map +1 -1
  87. package/dist/public/operations/contracts.js +309 -8
  88. package/dist/public/operations/impact-review-preparation.d.ts +14 -0
  89. package/dist/public/operations/impact-review-preparation.d.ts.map +1 -0
  90. package/dist/public/operations/impact-review-preparation.js +379 -0
  91. package/dist/public/operations/index.d.ts +2 -0
  92. package/dist/public/operations/index.d.ts.map +1 -1
  93. package/dist/public/operations/index.js +2 -0
  94. package/dist/public/operations/node-ports.d.ts.map +1 -1
  95. package/dist/public/operations/node-ports.js +1 -35
  96. package/dist/public/operations/proof-receipt-projection.d.ts +5 -0
  97. package/dist/public/operations/proof-receipt-projection.d.ts.map +1 -0
  98. package/dist/public/operations/proof-receipt-projection.js +36 -0
  99. package/dist/public/operations/specs/impact-review-preparation.d.ts +47 -0
  100. package/dist/public/operations/specs/impact-review-preparation.d.ts.map +1 -0
  101. package/dist/public/operations/specs/impact-review-preparation.js +43 -0
  102. package/dist/public/operations/types.d.ts +1 -1
  103. package/dist/public/operations/types.d.ts.map +1 -1
  104. package/dist/public/skills/kibi-usage/resources/operation-access.md +1 -0
  105. package/dist/traceability/analysis-gate.d.ts +39 -0
  106. package/dist/traceability/analysis-gate.d.ts.map +1 -0
  107. package/dist/traceability/analysis-gate.js +51 -0
  108. package/dist/traceability/git-change-snapshot.d.ts +27 -0
  109. package/dist/traceability/git-change-snapshot.d.ts.map +1 -0
  110. package/dist/traceability/git-change-snapshot.js +411 -0
  111. package/dist/traceability/git-staged.d.ts +5 -1
  112. package/dist/traceability/git-staged.d.ts.map +1 -1
  113. package/dist/traceability/git-staged.js +16 -11
  114. package/dist/traceability/impact-evaluator.d.ts +54 -0
  115. package/dist/traceability/impact-evaluator.d.ts.map +1 -0
  116. package/dist/traceability/impact-evaluator.js +270 -0
  117. package/dist/traceability/impact-git-tree.d.ts +12 -0
  118. package/dist/traceability/impact-git-tree.d.ts.map +1 -0
  119. package/dist/traceability/impact-git-tree.js +46 -0
  120. package/dist/traceability/impact-knowledge.d.ts +16 -0
  121. package/dist/traceability/impact-knowledge.d.ts.map +1 -0
  122. package/dist/traceability/impact-knowledge.js +165 -0
  123. package/dist/traceability/impact-policy.d.ts +15 -0
  124. package/dist/traceability/impact-policy.d.ts.map +1 -0
  125. package/dist/traceability/impact-policy.js +48 -0
  126. package/dist/traceability/impact-policy.v1.schema.json +48 -0
  127. package/dist/traceability/impact-pr-diff.d.ts +5 -0
  128. package/dist/traceability/impact-pr-diff.d.ts.map +1 -0
  129. package/dist/traceability/impact-pr-diff.js +83 -0
  130. package/dist/traceability/impact-record-validation.d.ts +9 -0
  131. package/dist/traceability/impact-record-validation.d.ts.map +1 -0
  132. package/dist/traceability/impact-record-validation.js +113 -0
  133. package/dist/traceability/impact-review.d.ts +148 -0
  134. package/dist/traceability/impact-review.d.ts.map +1 -0
  135. package/dist/traceability/impact-review.js +494 -0
  136. package/dist/traceability/impact-review.schema.json +365 -0
  137. package/dist/traceability/impact-side-evidence.d.ts +13 -0
  138. package/dist/traceability/impact-side-evidence.d.ts.map +1 -0
  139. package/dist/traceability/impact-side-evidence.js +240 -0
  140. package/dist/traceability/reviewed-coordinate-refresh.d.ts +10 -0
  141. package/dist/traceability/reviewed-coordinate-refresh.d.ts.map +1 -0
  142. package/dist/traceability/reviewed-coordinate-refresh.js +49 -0
  143. package/dist/traceability/snapshot-knowledge.d.ts +4 -0
  144. package/dist/traceability/snapshot-knowledge.d.ts.map +1 -0
  145. package/dist/traceability/snapshot-knowledge.js +98 -0
  146. package/dist/traceability/staged-file-coverage.d.ts +23 -0
  147. package/dist/traceability/staged-file-coverage.d.ts.map +1 -1
  148. package/dist/traceability/staged-impact-contract.d.ts.map +1 -1
  149. package/dist/traceability/staged-impact-contract.js +2 -16
  150. package/dist/traceability/staged-symbols-manifest.d.ts +4 -0
  151. package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
  152. package/dist/traceability/staged-symbols-manifest.js +17 -6
  153. package/dist/traceability/symbol-extract.d.ts +3 -5
  154. package/dist/traceability/symbol-extract.d.ts.map +1 -1
  155. package/dist/traceability/symbol-extract.js +49 -34
  156. package/dist/traceability/temp-kb.d.ts +1 -1
  157. package/dist/traceability/temp-kb.d.ts.map +1 -1
  158. package/dist/traceability/temp-kb.js +49 -13
  159. package/dist/traceability/trusted-pr-event.d.ts +13 -0
  160. package/dist/traceability/trusted-pr-event.d.ts.map +1 -0
  161. package/dist/traceability/trusted-pr-event.js +105 -0
  162. package/dist/utils/canonical-path.d.ts +3 -0
  163. package/dist/utils/canonical-path.d.ts.map +1 -0
  164. package/dist/utils/canonical-path.js +33 -0
  165. package/package.json +14 -5
  166. package/src/public/impact/analyzer.ts +88 -5
  167. package/src/public/impact/diagnostics.ts +7 -5
  168. package/src/public/impact/manifest.ts +14 -1
  169. package/src/public/impact/source-changes.ts +39 -34
  170. package/src/public/impact/types.ts +5 -0
  171. package/src/public/operations/catalog.ts +2 -0
  172. package/src/public/operations/contracts.ts +385 -9
  173. package/src/public/operations/impact-review-preparation.ts +548 -0
  174. package/src/public/operations/index.ts +2 -0
  175. package/src/public/operations/node-ports.ts +1 -39
  176. package/src/public/operations/proof-receipt-projection.ts +39 -0
  177. package/src/public/operations/specs/impact-review-preparation.ts +46 -0
  178. package/src/public/operations/types.ts +1 -0
  179. package/src/public/skills/kibi-usage/resources/operation-access.md +1 -0
  180. package/src/traceability/impact-policy.v1.schema.json +48 -0
  181. package/src/traceability/impact-review.schema.json +365 -0
  182. package/templates/github/kibi-badge.yml +0 -4
  183. package/templates/github/kibi-report.yml +0 -4
@@ -15,7 +15,7 @@
15
15
  You should have received a copy of the GNU Affero General Public License
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
- import { KIBI_PLUGIN_API_VERSION, ONTOLOGY_PACK_CAPABILITY_ID, SEMANTIC_CLASSIFIER_CAPABILITY_ID, SYMBOL_EXTRACTOR_CAPABILITY_ID, VOCABULARY_ALIGNMENT_CAPABILITY_ID, defineKibiPlugin, validateKibiPlugin, } from "kibi-plugin-sdk";
18
+ import { KIBI_PLUGIN_API_VERSION, ONTOLOGY_PACK_CAPABILITY_ID, SEMANTIC_CLASSIFIER_CAPABILITY_ID, SYMBOL_EXTRACTOR_CAPABILITY_ID, SYMBOL_EXTRACTOR_V2_CAPABILITY_ID, VOCABULARY_ALIGNMENT_CAPABILITY_ID, defineKibiPlugin, validateKibiPlugin, } from "kibi-plugin-sdk";
19
19
  import { loadPluginPackage } from "./load-plugin.js";
20
20
  import { readProjectKibiConfig } from "./project-config.js";
21
21
  import { PluginResolutionError } from "./resolve-package.js";
@@ -23,6 +23,7 @@ const CAPABILITY_SLOT = {
23
23
  [SEMANTIC_CLASSIFIER_CAPABILITY_ID]: "semanticClassifier",
24
24
  [ONTOLOGY_PACK_CAPABILITY_ID]: "ontologyPack",
25
25
  [SYMBOL_EXTRACTOR_CAPABILITY_ID]: "symbolExtractor",
26
+ [SYMBOL_EXTRACTOR_V2_CAPABILITY_ID]: "symbolExtractorV2",
26
27
  [VOCABULARY_ALIGNMENT_CAPABILITY_ID]: "vocabularyAlignment",
27
28
  };
28
29
  /**
@@ -197,6 +198,10 @@ export class CapabilityRegistry {
197
198
  async resolveSymbolExtractors() {
198
199
  return this.resolveCapability(SYMBOL_EXTRACTOR_CAPABILITY_ID);
199
200
  }
201
+ // implements REQ-capability-plugin-activation-disclosure-v1
202
+ async resolveSymbolExtractorsV2() {
203
+ return this.resolveCapability(SYMBOL_EXTRACTOR_V2_CAPABILITY_ID);
204
+ }
200
205
  async resolveVocabularyAlignment() {
201
206
  return this.resolveCapability(VOCABULARY_ALIGNMENT_CAPABILITY_ID);
202
207
  }
@@ -1,4 +1,4 @@
1
- import { type PluginProviderStamp, type SourceAnalysisResult, type SymbolExtractorV1 } from "kibi-plugin-sdk";
1
+ import { type PluginProviderStamp, type SourceAnalysisResult, type SourceAnalysisResultV2, type SymbolExtractorV1, type SymbolExtractorV2 } from "kibi-plugin-sdk";
2
2
  import type { CapabilityModeResolution, CapabilityRegistry } from "./registry.js";
3
3
  export type HostSourceAnalysisShadowComparison = Readonly<{
4
4
  pluginId: string;
@@ -18,9 +18,21 @@ export type HostSourceAnalysisResult = SourceAnalysisResult & Readonly<{
18
18
  }>;
19
19
  export type SourceAnalysisServiceOptions = Readonly<{
20
20
  registry: CapabilityRegistry;
21
+ /** Explicit v2 resolution; maintenance callers supply only approved providers. */
22
+ resolveExtractorsV2?: () => Promise<CapabilityModeResolution<SymbolExtractorV2>>;
23
+ /** Wall-clock deadline for async providers; CPU-bound plugins need their own terminable worker. */
24
+ analysisTimeoutMs?: number;
25
+ /** Host-verified package/asset fingerprint, never accepted from result data. */
26
+ providerFingerprints?: Readonly<Record<string, string>>;
21
27
  /** Injectable resolution for tests. */
22
28
  resolveExtractors?: () => Promise<CapabilityModeResolution<SymbolExtractorV1>>;
23
29
  }>;
30
+ /**
31
+ * The host owns the analysis deadline. Providers get a slightly smaller budget
32
+ * so a cooperative provider reports its own timeout diagnostic before the host
33
+ * abandons the call.
34
+ */
35
+ export declare function providerBudgetMs(hostTimeoutMs: number): number;
24
36
  export declare function createConservativeFallbackAnalysis(filePath: string, fallbackReason: string): HostSourceAnalysisResult;
25
37
  /**
26
38
  * Host-validated symbol analysis over registry providers with conservative
@@ -32,8 +44,23 @@ export declare function createConservativeFallbackAnalysis(filePath: string, fal
32
44
  */
33
45
  export declare class SourceAnalysisService {
34
46
  private readonly registry;
47
+ private readonly options;
35
48
  private readonly resolveExtractors;
36
49
  constructor(options: SourceAnalysisServiceOptions);
50
+ /**
51
+ * Analyze supplied snapshot bytes with explicit completeness and host provenance.
52
+ * An explicit language hint selects an ambiguous extension only when it agrees
53
+ * with any shebang; conflicting signals return unsupported without dispatch.
54
+ *
55
+ * Classify, bound the input, resolve providers, take the first claiming
56
+ * provider's result as canonical, then record shadow comparisons.
57
+ */
58
+ analyzeTextV2(filePath: string, content: string, explicitLanguageHint?: string): Promise<HostSourceAnalysisResultV2>;
59
+ /**
60
+ * Run one provider under the host-owned deadline. Returns null when the
61
+ * provider does not claim the input; a claimed failure is a failed result.
62
+ */
63
+ private runV2Extractor;
37
64
  analyzeText(filePath: string, content: string): Promise<HostSourceAnalysisResult>;
38
65
  }
39
66
  /**
@@ -41,4 +68,12 @@ export declare class SourceAnalysisService {
41
68
  */
42
69
  export declare function analyzeWithResolution(resolution: CapabilityModeResolution<SymbolExtractorV1>, filePath: string, content: string): Promise<HostSourceAnalysisResult>;
43
70
  export declare function createSourceAnalysisService(options: SourceAnalysisServiceOptions): SourceAnalysisService;
71
+ /** V2 results preserve failure/completeness; provenance is always assigned by the host. */
72
+ export type HostSourceAnalysisResultV2 = SourceAnalysisResultV2 & Readonly<{
73
+ providerId: string | null;
74
+ stamp: PluginProviderStamp | null;
75
+ inputFingerprint: string;
76
+ providerFingerprint: string | null;
77
+ shadowComparisons: readonly HostSourceAnalysisShadowComparison[];
78
+ }>;
44
79
  //# sourceMappingURL=source-analysis-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"source-analysis-service.d.ts","sourceRoot":"","sources":["../../src/plugins/source-analysis-service.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EAGvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EACV,wBAAwB,EACxB,kBAAkB,EACnB,MAAM,eAAe,CAAC;AA4BvB,MAAM,MAAM,kCAAkC,GAAG,QAAQ,CAAC;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAGH,MAAM,MAAM,wBAAwB,GAAG,oBAAoB,GACzD,QAAQ,CAAC;IACP,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,oEAAoE;IACpE,iBAAiB,EAAE,SAAS,kCAAkC,EAAE,CAAC;CAClE,CAAC,CAAC;AAGL,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAC/B,wBAAwB,CAAC,iBAAiB,CAAC,CAC5C,CAAC;CACH,CAAC,CAAC;AAgBH,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACrB,wBAAwB,CAkB1B;AAuBD;;;;;;;GAOG;AAEH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAEhC;gBAEU,OAAO,EAAE,4BAA4B;IAO3C,WAAW,CACf,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,wBAAwB,CAAC;CAiIrC;AAED;;GAEG;AAEH,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,wBAAwB,CAAC,iBAAiB,CAAC,EACvD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,wBAAwB,CAAC,CAQnC;AAGD,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,4BAA4B,GACpC,qBAAqB,CAEvB"}
1
+ {"version":3,"file":"source-analysis-service.d.ts","sourceRoot":"","sources":["../../src/plugins/source-analysis-service.ts"],"names":[],"mappings":"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"}
@@ -15,35 +15,73 @@
15
15
  You should have received a copy of the GNU Affero General Public License
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
+ import { createHash } from "node:crypto";
18
19
  import * as path from "node:path";
19
- import { toSourceAnalysisProvider, validateSourceAnalysisResultForPath, } from "kibi-plugin-sdk";
20
- const SOURCE_LANGUAGE_EXTENSIONS = {
21
- ".c": "c",
22
- ".cc": "cpp",
23
- ".cjs": "javascript",
24
- ".cpp": "cpp",
25
- ".cs": "csharp",
26
- ".cts": "typescript",
27
- ".go": "go",
28
- ".h": "c",
29
- ".hpp": "cpp",
30
- ".java": "java",
31
- ".js": "javascript",
32
- ".jsx": "javascript",
33
- ".kt": "kotlin",
34
- ".mjs": "javascript",
35
- ".mts": "typescript",
36
- ".php": "php",
37
- ".py": "python",
38
- ".rb": "ruby",
39
- ".rs": "rust",
40
- ".swift": "swift",
41
- ".ts": "typescript",
42
- ".tsx": "typescript",
43
- };
20
+ import { SOURCE_ANALYSIS_V2_MAX_INPUT_CODE_UNITS, SYMBOL_EXTRACTOR_V2_CAPABILITY_ID, toSourceAnalysisProvider, validateSourceAnalysisResultForPath, validateSourceAnalysisResultV2, } from "kibi-plugin-sdk";
21
+ import { classifySource, extensionLanguage } from "./source-classification.js";
44
22
  function detectSourceLanguage(filePath) {
45
- return (SOURCE_LANGUAGE_EXTENSIONS[path.extname(filePath).toLowerCase()] ??
46
- "unknown");
23
+ return extensionLanguage(filePath);
24
+ }
25
+ /** Classify once and bind every result for this input to one fingerprint. */
26
+ function createV2Request(filePath, content, explicitLanguageHint) {
27
+ const classification = classifySource(filePath, content, explicitLanguageHint);
28
+ const language = classification.language;
29
+ const inputFingerprint = createHash("sha256")
30
+ .update(filePath)
31
+ .update("\0")
32
+ .update(content)
33
+ .update("\0")
34
+ .update(classification.kind)
35
+ .update("\0")
36
+ .update(classification.language)
37
+ .update("\0")
38
+ .update(explicitLanguageHint?.trim().toLowerCase() ?? "")
39
+ .digest("hex");
40
+ return {
41
+ classification,
42
+ input: {
43
+ path: filePath,
44
+ content,
45
+ ...(classification.kind === "language"
46
+ ? { language: classification.language }
47
+ : {}),
48
+ },
49
+ inputFingerprint,
50
+ fallback: (status, code, message) => ({
51
+ contractVersion: SYMBOL_EXTRACTOR_V2_CAPABILITY_ID,
52
+ status,
53
+ sourceFile: filePath,
54
+ language,
55
+ module: {
56
+ title: inferModuleTitle(filePath),
57
+ language,
58
+ analysisMode: "fallback",
59
+ fallbackReason: code,
60
+ },
61
+ symbols: [],
62
+ diagnostics: [{ code, message }],
63
+ uncoveredRanges: [],
64
+ providerId: null,
65
+ stamp: null,
66
+ inputFingerprint,
67
+ providerFingerprint: null,
68
+ shadowComparisons: [],
69
+ }),
70
+ };
71
+ }
72
+ function hostDeadlineMs(requested) {
73
+ const value = requested ?? 10000;
74
+ return Number.isFinite(value) && value > 0 ? Math.min(value, 60000) : 10000;
75
+ }
76
+ /**
77
+ * The host owns the analysis deadline. Providers get a slightly smaller budget
78
+ * so a cooperative provider reports its own timeout diagnostic before the host
79
+ * abandons the call.
80
+ */
81
+ // implements REQ-source-analysis-v2
82
+ export function providerBudgetMs(hostTimeoutMs) {
83
+ const grace = Math.min(1000, Math.floor(hostTimeoutMs / 10));
84
+ return Math.max(1, hostTimeoutMs - grace);
47
85
  }
48
86
  function inferModuleTitle(filePath) {
49
87
  const extension = path.extname(filePath);
@@ -100,13 +138,132 @@ function dedupeSymbols(symbols) {
100
138
  // implements REQ-capability-plugin-activation-disclosure-v1
101
139
  export class SourceAnalysisService {
102
140
  registry;
141
+ options;
103
142
  resolveExtractors;
104
143
  constructor(options) {
105
144
  this.registry = options.registry;
145
+ this.options = options;
106
146
  this.resolveExtractors =
107
147
  options.resolveExtractors ??
108
148
  (() => this.registry.resolveSymbolExtractors());
109
149
  }
150
+ /**
151
+ * Analyze supplied snapshot bytes with explicit completeness and host provenance.
152
+ * An explicit language hint selects an ambiguous extension only when it agrees
153
+ * with any shebang; conflicting signals return unsupported without dispatch.
154
+ *
155
+ * Classify, bound the input, resolve providers, take the first claiming
156
+ * provider's result as canonical, then record shadow comparisons.
157
+ */
158
+ // implements REQ-capability-plugin-activation-disclosure-v1
159
+ async analyzeTextV2(filePath, content, explicitLanguageHint) {
160
+ const request = createV2Request(filePath, content, explicitLanguageHint);
161
+ const { classification } = request;
162
+ if (content.length > SOURCE_ANALYSIS_V2_MAX_INPUT_CODE_UNITS ||
163
+ Buffer.byteLength(content, "utf8") > 8 * 1024 * 1024)
164
+ return request.fallback("failed", "input_limit", `Source input exceeds the ${SOURCE_ANALYSIS_V2_MAX_INPUT_CODE_UNITS} UTF-16 code unit or 8 MiB UTF-8 analysis limit`);
165
+ let resolution;
166
+ try {
167
+ resolution = await (this.options.resolveExtractorsV2?.() ??
168
+ this.registry.resolveSymbolExtractorsV2());
169
+ }
170
+ catch (error) {
171
+ return request.fallback("failed", "provider_resolution_failed", String(error));
172
+ }
173
+ if (classification.kind !== "language" &&
174
+ classification.kind !== "unknown") {
175
+ const code = classification.kind === "ambiguous"
176
+ ? "source_language_ambiguous"
177
+ : classification.kind === "conflict"
178
+ ? "source_classification_conflict"
179
+ : classification.kind === "file-level"
180
+ ? "source_file_level_only"
181
+ : "unsupported_language";
182
+ return request.fallback("unsupported", code, classification.reason);
183
+ }
184
+ const entries = resolution.replace
185
+ ? [resolution.replace, resolution.builtin, ...resolution.augment]
186
+ : [resolution.builtin, ...resolution.augment];
187
+ let canonical = null;
188
+ for (const entry of entries) {
189
+ const result = await this.runV2Extractor(entry, request);
190
+ if (result === null)
191
+ continue;
192
+ // A claimed file's incomplete/failed result is authoritative uncertainty.
193
+ // Never turn a required provider failure into empty symbols or success.
194
+ canonical = result;
195
+ break;
196
+ }
197
+ canonical ??= request.fallback("unsupported", "unsupported_language", "No configured source analyzer claims this file; file-level review remains required.");
198
+ const shadowComparisons = [];
199
+ for (const entry of resolution.shadow) {
200
+ const result = await this.runV2Extractor(entry, request);
201
+ if (!result)
202
+ continue;
203
+ shadowComparisons.push({
204
+ pluginId: entry.pluginId,
205
+ stamp: entry.stamp,
206
+ symbolCount: result.symbols.length,
207
+ language: result.language,
208
+ ok: result.status === "ok",
209
+ ...(result.status !== "ok"
210
+ ? { error: result.diagnostics.map((d) => d.message).join("; ") }
211
+ : {}),
212
+ });
213
+ }
214
+ return { ...canonical, shadowComparisons };
215
+ }
216
+ /**
217
+ * Run one provider under the host-owned deadline. Returns null when the
218
+ * provider does not claim the input; a claimed failure is a failed result.
219
+ */
220
+ async runV2Extractor(entry, request) {
221
+ const { classification, input } = request;
222
+ try {
223
+ const supportsInput = classification.kind === "language"
224
+ ? { path: input.path, language: classification.language }
225
+ : { path: input.path };
226
+ if (!entry.capability.supports(supportsInput))
227
+ return null;
228
+ const timeout = hostDeadlineMs(this.options.analysisTimeoutMs);
229
+ let timer;
230
+ let raw;
231
+ try {
232
+ raw = await Promise.race([
233
+ entry.capability.analyze({
234
+ ...input,
235
+ timeoutMs: providerBudgetMs(timeout),
236
+ }),
237
+ new Promise((_, reject) => {
238
+ timer = setTimeout(() => reject(new Error("Source analysis deadline exceeded")), timeout);
239
+ }),
240
+ ]);
241
+ }
242
+ finally {
243
+ if (timer !== undefined)
244
+ clearTimeout(timer);
245
+ }
246
+ const validated = validateSourceAnalysisResultV2(raw, input);
247
+ return {
248
+ ...validated,
249
+ providerId: entry.capability.id,
250
+ stamp: entry.stamp,
251
+ inputFingerprint: request.inputFingerprint,
252
+ providerFingerprint: this.options.providerFingerprints?.[entry.pluginId] ??
253
+ createHash("sha256")
254
+ .update(`${entry.pluginId}\0${entry.pluginVersion}\0${entry.stamp.capability}`)
255
+ .digest("hex"),
256
+ shadowComparisons: [],
257
+ };
258
+ }
259
+ catch (error) {
260
+ return {
261
+ ...request.fallback("failed", "provider_failed", `Extractor '${entry.capability.id}' failed: ${String(error)}`),
262
+ providerId: entry.capability.id,
263
+ stamp: entry.stamp,
264
+ };
265
+ }
266
+ }
110
267
  async analyzeText(filePath, content) {
111
268
  const resolution = await this.resolveExtractors();
112
269
  const diagnostics = [];
@@ -0,0 +1,15 @@
1
+ import { type GateAnalysis } from "../traceability/analysis-gate.js";
2
+ import type { StagedPath } from "../traceability/git-staged.js";
3
+ import type { HostSourceAnalysisResultV2, SourceAnalysisService } from "./source-analysis-service.js";
4
+ export interface SourceChangeAnalysis {
5
+ path: string;
6
+ before: HostSourceAnalysisResultV2 | null;
7
+ after: HostSourceAnalysisResultV2 | null;
8
+ }
9
+ /** Analyze both versions without changing the complete inventory or assigning proof. */
10
+ export declare function analyzeSourceChanges(inventory: readonly StagedPath[], service: SourceAnalysisService): Promise<Map<string, SourceChangeAnalysis>>;
11
+ /** Adapt a host result to the shared analysis gate. */
12
+ export declare function gateAnalysis(result: HostSourceAnalysisResultV2 | null): GateAnalysis<HostSourceAnalysisResultV2["uncoveredRanges"][number]> | null;
13
+ /** Enforce the shared analysis gate when no impact policy accepts reviews. */
14
+ export declare function assertSourceAnalysisGate(inventory: readonly StagedPath[], analyses: ReadonlyMap<string, SourceChangeAnalysis>): void;
15
+ //# sourceMappingURL=source-change-analysis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-change-analysis.d.ts","sourceRoot":"","sources":["../../src/plugins/source-change-analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EAElB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EACV,0BAA0B,EAC1B,qBAAqB,EACtB,MAAM,8BAA8B,CAAC;AAGtC,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAC1C,KAAK,EAAE,0BAA0B,GAAG,IAAI,CAAC;CAC1C;AAKD,wFAAwF;AAExF,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,SAAS,UAAU,EAAE,EAChC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAgC5C;AAED,uDAAuD;AAEvD,wBAAgB,YAAY,CAC1B,MAAM,EAAE,0BAA0B,GAAG,IAAI,GACxC,YAAY,CAAC,0BAA0B,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAQ5E;AAED,8EAA8E;AAE9E,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,SAAS,UAAU,EAAE,EAChC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAClD,IAAI,CAkBN"}
@@ -0,0 +1,54 @@
1
+ import { analysisObligation, } from "../traceability/analysis-gate.js";
2
+ /** Files analyzed at once; pooled providers bound their own worker count. */
3
+ const SOURCE_ANALYSIS_CONCURRENCY = 4;
4
+ /** Analyze both versions without changing the complete inventory or assigning proof. */
5
+ // implements REQ-014
6
+ export async function analyzeSourceChanges(inventory, service) {
7
+ const files = inventory.filter((file) => file.analysisDepth !== "metadata" && !file.skipReason);
8
+ const results = new Array(files.length);
9
+ let next = 0;
10
+ const worker = async () => {
11
+ while (next < files.length) {
12
+ const index = next++;
13
+ const file = files[index];
14
+ const [before, after] = await Promise.all([
15
+ file.previousContent === undefined
16
+ ? null
17
+ : service.analyzeTextV2(file.oldPath ?? file.copyFromPath ?? file.path, file.previousContent),
18
+ file.content === undefined
19
+ ? null
20
+ : service.analyzeTextV2(file.path, file.content),
21
+ ]);
22
+ results[index] = { path: file.path, before, after };
23
+ }
24
+ };
25
+ await Promise.all(Array.from({ length: Math.min(SOURCE_ANALYSIS_CONCURRENCY, files.length) }, worker));
26
+ // Map order follows the inventory, independent of completion order.
27
+ return new Map(results.map((change) => [change.path, change]));
28
+ }
29
+ /** Adapt a host result to the shared analysis gate. */
30
+ // implements REQ-source-analysis-v2
31
+ export function gateAnalysis(result) {
32
+ return result
33
+ ? {
34
+ status: result.status,
35
+ diagnosticCodes: result.diagnostics.map((item) => item.code),
36
+ uncoveredRanges: result.uncoveredRanges,
37
+ }
38
+ : null;
39
+ }
40
+ /** Enforce the shared analysis gate when no impact policy accepts reviews. */
41
+ // implements REQ-source-analysis-v2
42
+ export function assertSourceAnalysisGate(inventory, analyses) {
43
+ for (const file of inventory) {
44
+ const analysis = analyses.get(file.path);
45
+ const after = analysis?.after ?? null;
46
+ const obligation = analysisObligation("after", gateAnalysis(after), file.hunkRanges);
47
+ if (obligation.kind !== "blocked" && obligation.kind !== "partial_review")
48
+ continue;
49
+ const detail = after?.diagnostics.map((d) => d.message).join("; ") ?? "";
50
+ throw new Error(obligation.kind === "blocked"
51
+ ? `Source analysis ${after?.status} for ${file.path}: ${detail}`
52
+ : `Source analysis partial for ${file.path} where the staged change touches uncovered lines (${obligation.ranges.map((range) => `${range.startLine}-${range.endLine}`).join(", ")}): ${detail}`);
53
+ }
54
+ }
@@ -0,0 +1,41 @@
1
+ export type SourceClassification = Readonly<{
2
+ kind: "language";
3
+ language: string;
4
+ source: "extension" | "shebang" | "explicit";
5
+ }> | Readonly<{
6
+ kind: "file-level";
7
+ language: string;
8
+ source: "extension" | "shebang" | "explicit";
9
+ reason: string;
10
+ }> | Readonly<{
11
+ kind: "ambiguous";
12
+ language: string;
13
+ candidates: readonly string[];
14
+ reason: string;
15
+ }> | Readonly<{
16
+ kind: "conflict";
17
+ language: "unknown";
18
+ extensionLanguage?: string;
19
+ shebangLanguage?: string;
20
+ explicitLanguage?: string;
21
+ reason: string;
22
+ }> | Readonly<{
23
+ kind: "unknown";
24
+ language: "unknown";
25
+ reason: string;
26
+ }>;
27
+ /**
28
+ * Extension-only language label for a path, or "unknown". This is the single
29
+ * extension table; callers that need content-aware classification (shebangs,
30
+ * explicit hints, ambiguity) must use classifySource instead.
31
+ */
32
+ export declare function extensionLanguage(filePath: string): string;
33
+ /** True for TypeScript/JavaScript paths handled by the ts-morph analyzer. */
34
+ export declare function isTsJsSourcePath(filePath: string): boolean;
35
+ /** True for paths whose language has qualified declaration analysis. */
36
+ export declare function isQualifiedSourcePath(filePath: string): boolean;
37
+ /** Every classified extension, for parity checks against provider catalogs. */
38
+ export declare function classifiedExtensions(): readonly string[];
39
+ /** Classifies a path and bounded snapshot prefix without executing the source or its interpreter. */
40
+ export declare function classifySource(filePath: string, content: string, explicitLanguageHint?: string): SourceClassification;
41
+ //# sourceMappingURL=source-classification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-classification.d.ts","sourceRoot":"","sources":["../../src/plugins/source-classification.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAC5B,QAAQ,CAAC;IACP,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;CAC9C,CAAC,GACF,QAAQ,CAAC;IACP,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,GACF,QAAQ,CAAC;IACP,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,GACF,QAAQ,CAAC;IACP,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,GACF,QAAQ,CAAC;IACP,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAsGP;;;;GAIG;AAEH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,6EAA6E;AAE7E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAG1D;AAED,wEAAwE;AAExE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAM/D;AAED,+EAA+E;AAE/E,wBAAgB,oBAAoB,IAAI,SAAS,MAAM,EAAE,CAExD;AAuQD,qGAAqG;AACrG,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,oBAAoB,CAAC,EAAE,MAAM,GAC5B,oBAAoB,CA2JtB"}