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
@@ -0,0 +1,48 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "urn:kibi:impact-policy:v1",
4
+ "title": "Kibi trusted base-tree impact policy",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "contractVersion",
9
+ "id",
10
+ "version",
11
+ "allowUnsupportedReview",
12
+ "allowedPartial",
13
+ "notApplicablePaths"
14
+ ],
15
+ "properties": {
16
+ "contractVersion": { "const": "kibi.impact-policy.v1" },
17
+ "id": { "type": "string", "minLength": 1 },
18
+ "version": { "type": "string", "minLength": 1 },
19
+ "allowUnsupportedReview": { "type": "boolean" },
20
+ "allowedPartial": {
21
+ "type": "array",
22
+ "items": {
23
+ "type": "object",
24
+ "additionalProperties": false,
25
+ "required": [
26
+ "providerId",
27
+ "providerFingerprint",
28
+ "diagnosticCode",
29
+ "limitationClass"
30
+ ],
31
+ "properties": {
32
+ "providerId": { "type": "string", "minLength": 1 },
33
+ "providerFingerprint": { "$ref": "#/$defs/sha256" },
34
+ "diagnosticCode": { "type": "string", "minLength": 1 },
35
+ "limitationClass": { "type": "string", "minLength": 1 }
36
+ }
37
+ }
38
+ },
39
+ "notApplicablePaths": {
40
+ "type": "array",
41
+ "uniqueItems": true,
42
+ "items": { "type": "string", "minLength": 1, "pattern": "^[^/].*$" }
43
+ }
44
+ },
45
+ "$defs": {
46
+ "sha256": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
47
+ }
48
+ }
@@ -0,0 +1,5 @@
1
+ import type { GitChangeSnapshot } from "./git-change-snapshot.js";
2
+ import type { TrustedPullRequestSnapshot } from "./trusted-pr-event.js";
3
+ /** Require a merge-base snapshot that still reflects the protected target state. */
4
+ export declare function assertTrustedPullRequestBaseline(snapshot: GitChangeSnapshot, event: TrustedPullRequestSnapshot): void;
5
+ //# sourceMappingURL=impact-pr-diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact-pr-diff.d.ts","sourceRoot":"","sources":["../../src/traceability/impact-pr-diff.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAqExE,oFAAoF;AACpF,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,EAAE,0BAA0B,GAChC,IAAI,CA6CN"}
@@ -0,0 +1,83 @@
1
+ import { snapshotFileContent } from "../public/operations/proof-receipt-projection.js";
2
+ import { fingerprint, fingerprintBytes } from "./impact-review.js";
3
+ import { IMPACT_POLICY_PATH } from "./impact-review.js";
4
+ function treeRows(snapshot, tree) {
5
+ const rows = [];
6
+ for (const raw of snapshot
7
+ .readGit(["ls-tree", "-r", "-z", tree])
8
+ .toString("binary")
9
+ .split("\0")
10
+ .filter(Boolean)) {
11
+ const tab = raw.indexOf("\t");
12
+ if (tab < 0)
13
+ throw new Error("Malformed Git tree listing");
14
+ const [mode, type, objectId] = raw.slice(0, tab).split(" ");
15
+ const path = new TextDecoder("utf-8", { fatal: true }).decode(Buffer.from(raw.slice(tab + 1), "binary"));
16
+ if (!mode || !type || !objectId)
17
+ throw new Error("Malformed Git tree entry");
18
+ rows.push({ mode, type, objectId, path });
19
+ }
20
+ return rows;
21
+ }
22
+ function stateFingerprint(snapshot, tree, include) {
23
+ const rows = treeRows(snapshot, tree)
24
+ .filter((row) => include(row.path))
25
+ .map((row) => {
26
+ const bytes = row.type === "blob"
27
+ ? snapshot.readBlobs([row.objectId]).get(row.objectId)
28
+ : undefined;
29
+ const receiptProjectedMarkdown = row.path.startsWith(".kb/") && row.path.endsWith(".md");
30
+ const projectedBytes = bytes && receiptProjectedMarkdown
31
+ ? snapshotFileContent(row.path, bytes)
32
+ : bytes;
33
+ return {
34
+ path: row.path,
35
+ mode: row.mode,
36
+ type: row.type,
37
+ ...(!receiptProjectedMarkdown ? { objectId: row.objectId } : {}),
38
+ bytes: projectedBytes !== undefined
39
+ ? fingerprintBytes(projectedBytes)
40
+ : null,
41
+ };
42
+ });
43
+ return fingerprint(rows);
44
+ }
45
+ function pathState(snapshot, tree, path) {
46
+ return stateFingerprint(snapshot, tree, (candidate) => candidate === path);
47
+ }
48
+ /** Require a merge-base snapshot that still reflects the protected target state. */
49
+ export function assertTrustedPullRequestBaseline(snapshot, event) {
50
+ if (snapshot.baseTree !== event.mergeBaseTree ||
51
+ snapshot.headTree !== event.headTree)
52
+ throw new Error("Diff snapshot does not match the verified PR event trees");
53
+ const stableTargetState = (path) => path === ".kb" ||
54
+ path.startsWith(".kb/") ||
55
+ path === ".kibi" ||
56
+ path.startsWith(".kibi/") ||
57
+ [
58
+ "package.json",
59
+ "bun.lock",
60
+ "bun.lockb",
61
+ "package-lock.json",
62
+ "pnpm-lock.yaml",
63
+ "yarn.lock",
64
+ ].includes(path);
65
+ if (stateFingerprint(snapshot, event.targetTree, stableTargetState) !==
66
+ stateFingerprint(snapshot, event.mergeBaseTree, stableTargetState))
67
+ throw new Error("Protected target knowledge, policy or provider configuration advanced; rebase and refresh the impact review");
68
+ if (snapshot.inventory.some((file) => file.path === IMPACT_POLICY_PATH))
69
+ throw new Error("Impact policy changes must be merged to the protected target separately before reviewed changes");
70
+ const touched = new Set();
71
+ for (const file of snapshot.inventory) {
72
+ touched.add(file.path);
73
+ if (file.oldPath)
74
+ touched.add(file.oldPath);
75
+ if (file.copyFromPath)
76
+ touched.add(file.copyFromPath);
77
+ }
78
+ for (const path of touched) {
79
+ if (pathState(snapshot, event.targetTree, path) !==
80
+ pathState(snapshot, event.mergeBaseTree, path))
81
+ throw new Error(`Protected target changed a reviewed path (${path}); rebase and refresh the impact review`);
82
+ }
83
+ }
@@ -0,0 +1,9 @@
1
+ import type { GitChangeSnapshot } from "./git-change-snapshot.js";
2
+ import type { PreparedImpactReview } from "./impact-evaluator.js";
3
+ import { type ImpactDecision, type ImpactFileRecord, type ImpactPolicy, type ImpactReviewRecord } from "./impact-review.js";
4
+ /** Validate an authored impact review record against the prepared snapshot. */
5
+ export declare function same(a: unknown, b: unknown): boolean;
6
+ export declare function recordFromCapturedTree(snapshot: GitChangeSnapshot): ImpactReviewRecord;
7
+ export declare function validateDecisionAgainstSnapshot(path: string, decision: ImpactDecision, prepared: PreparedImpactReview, changedPaths: ReadonlySet<string>): void;
8
+ export declare function validateAnalysisReviews(record: ImpactFileRecord, policy: ImpactPolicy): void;
9
+ //# sourceMappingURL=impact-record-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact-record-validation.d.ts","sourceRoot":"","sources":["../../src/traceability/impact-record-validation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAGlE,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EAGxB,MAAM,oBAAoB,CAAC;AAE5B,+EAA+E;AAE/E,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAEpD;AAGD,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,iBAAiB,GAC1B,kBAAkB,CAepB;AAGD,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,oBAAoB,EAC9B,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAChC,IAAI,CAqFN;AAGD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,YAAY,GACnB,IAAI,CA+CN"}
@@ -0,0 +1,113 @@
1
+ import { analysisObligation } from "./analysis-gate.js";
2
+ import { blobBytes, treeEntry } from "./impact-git-tree.js";
3
+ import { approvedPartialClass } from "./impact-policy.js";
4
+ import { IMPACT_REVIEW_PATH, canonicalJson, parseImpactReviewRecord, } from "./impact-review.js";
5
+ /** Validate an authored impact review record against the prepared snapshot. */
6
+ // implements REQ-impact-policy-stage-e-content-bound-review
7
+ export function same(a, b) {
8
+ return canonicalJson(a) === canonicalJson(b);
9
+ }
10
+ // implements REQ-impact-policy-stage-e-content-bound-review
11
+ export function recordFromCapturedTree(snapshot) {
12
+ const entry = treeEntry(snapshot, snapshot.headTree, IMPACT_REVIEW_PATH);
13
+ if (!entry ||
14
+ entry.type !== "blob" ||
15
+ (entry.mode !== "100644" && entry.mode !== "100755"))
16
+ throw new Error(`Captured impact review record missing: ${IMPACT_REVIEW_PATH}`);
17
+ const bytes = blobBytes(snapshot, entry);
18
+ if (!bytes)
19
+ throw new Error("Impact review record blob is missing");
20
+ return parseImpactReviewRecord(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes)));
21
+ }
22
+ // implements REQ-impact-policy-stage-e-content-bound-review
23
+ export function validateDecisionAgainstSnapshot(path, decision, prepared, changedPaths) {
24
+ if (decision.kind === "not_applicable") {
25
+ if (!prepared.policy.notApplicablePaths.includes(path))
26
+ throw new Error(`Policy does not permit not_applicable for ${path}`);
27
+ return;
28
+ }
29
+ const inScope = prepared.scopedRequirementIdsByPath.get(path) ?? [];
30
+ if (decision.kind === "no_impact") {
31
+ if (inScope.length !== 0)
32
+ throw new Error(`no_impact cannot omit scoped requirements for ${path}: ${inScope.join(", ")}`);
33
+ return;
34
+ }
35
+ const scoped = [...inScope].sort();
36
+ const reqs = [...new Set(decision.requirementIds)].sort();
37
+ if (reqs.length !== decision.requirementIds.length ||
38
+ reqs.length !== scoped.length ||
39
+ reqs.some((id, index) => id !== scoped[index]))
40
+ throw new Error(`Impact requirements do not equal the complete scoped set for ${path}`);
41
+ if (decision.knowledge.state === "still_current")
42
+ return;
43
+ const after = prepared.headEntities;
44
+ const before = prepared.baseEntities;
45
+ let changedRequirement = false;
46
+ const updatedRequirementIds = new Set();
47
+ for (const entity of decision.knowledge.entities) {
48
+ const oldRow = before.get(entity.entityId);
49
+ const newRow = after.get(entity.entityId);
50
+ if (!newRow ||
51
+ newRow.artifactPath !== entity.artifactPath ||
52
+ !changedPaths.has(entity.artifactPath))
53
+ throw new Error(`Updated entity does not resolve to a changed scoped artifact: ${entity.entityId}`);
54
+ if (entity.beforeFingerprint !== (oldRow?.fingerprint ?? null) ||
55
+ entity.afterFingerprint !== newRow.fingerprint ||
56
+ entity.beforeFingerprint === entity.afterFingerprint)
57
+ throw new Error(`Updated entity fingerprints are stale or semantically unchanged: ${entity.entityId}`);
58
+ if (newRow.type === "req") {
59
+ if (!reqs.includes(entity.entityId))
60
+ throw new Error(`Updated requirement is outside the complete scoped set: ${entity.entityId}`);
61
+ changedRequirement = true;
62
+ updatedRequirementIds.add(entity.entityId);
63
+ }
64
+ }
65
+ if (!changedRequirement)
66
+ throw new Error(`Updated evidence for ${path} must include a semantically changed scoped requirement`);
67
+ const unchangedRequirementIds = new Set();
68
+ for (const item of decision.knowledge.stillCurrent ?? []) {
69
+ if (!reqs.includes(item.requirementId))
70
+ throw new Error(`stillCurrent requirement is outside the complete scoped set: ${item.requirementId}`);
71
+ if (updatedRequirementIds.has(item.requirementId))
72
+ throw new Error(`Requirement is both updated and still_current: ${item.requirementId}`);
73
+ unchangedRequirementIds.add(item.requirementId);
74
+ }
75
+ if (unchangedRequirementIds.size !==
76
+ (decision.knowledge.stillCurrent?.length ?? 0) ||
77
+ updatedRequirementIds.size + unchangedRequirementIds.size !== reqs.length ||
78
+ reqs.some((id) => !updatedRequirementIds.has(id) && !unchangedRequirementIds.has(id)))
79
+ throw new Error(`Updated evidence must account for every scoped requirement on ${path}`);
80
+ }
81
+ // implements REQ-impact-policy-stage-e-content-bound-review
82
+ export function validateAnalysisReviews(record, policy) {
83
+ for (const side of ["before", "after"]) {
84
+ const analysis = record[side]?.analysis;
85
+ const reviews = record.analysisReviews.filter((review) => review.side === side);
86
+ const obligation = analysisObligation(side, analysis, record.newHunkRanges);
87
+ if (obligation.kind === "blocked")
88
+ throw new Error(`Source analysis cannot be waived for ${record.path} (${side}): ${obligation.reason}`);
89
+ if (obligation.kind === "none") {
90
+ if (reviews.length)
91
+ throw new Error(`Unnecessary analysis review on ${record.path} (${side}); only after-side gaps that overlap changed lines need review`);
92
+ continue;
93
+ }
94
+ if (obligation.kind === "unsupported_review") {
95
+ if (!policy.allowUnsupportedReview ||
96
+ reviews.length !== 1 ||
97
+ reviews[0]?.kind !== "unsupported_review")
98
+ throw new Error(`Unsupported side lacks one explicit whole-file review: ${record.path} (${side})`);
99
+ continue;
100
+ }
101
+ const allowedClass = analysis
102
+ ? approvedPartialClass(policy, analysis)
103
+ : null;
104
+ if (!allowedClass)
105
+ throw new Error(`Partial side is not approved by policy: ${record.path} (${side})`);
106
+ const review = reviews[0];
107
+ if (reviews.length !== 1 ||
108
+ review?.kind !== "partial_review" ||
109
+ review.limitationClass !== allowedClass ||
110
+ !same(review.ranges, obligation.ranges))
111
+ throw new Error(`Partial review must cover every uncovered range that overlaps changed lines: ${record.path} (${side})`);
112
+ }
113
+ }
@@ -0,0 +1,148 @@
1
+ import type { HunkRange, Status } from "./git-staged.js";
2
+ export declare const IMPACT_POLICY_PATH = ".kibi/impact-policy.json";
3
+ export declare const IMPACT_REVIEW_PATH = ".kibi/impact-review.json";
4
+ export declare const IMPACT_POLICY_VERSION: "kibi.impact-policy.v1";
5
+ export declare const IMPACT_REVIEW_VERSION: "kibi.impact-review.v1";
6
+ export declare const IMPACT_EVALUATOR_VERSION: "kibi.impact-evaluator.v1";
7
+ export type Fingerprint = `sha256:${string}`;
8
+ export type ImpactPolicy = Readonly<{
9
+ contractVersion: typeof IMPACT_POLICY_VERSION;
10
+ id: string;
11
+ version: string;
12
+ allowUnsupportedReview: boolean;
13
+ /** Exact trusted diagnostic/provider pairs; no globs or prefix matching. */
14
+ allowedPartial: readonly Readonly<{
15
+ providerId: string;
16
+ providerFingerprint: Fingerprint;
17
+ diagnosticCode: string;
18
+ limitationClass: string;
19
+ }>[];
20
+ /** Exact paths only. These paths still need a record and rationale. */
21
+ notApplicablePaths: readonly string[];
22
+ }>;
23
+ export type SideEvidence = Readonly<{
24
+ mode: string;
25
+ objectId: string | null;
26
+ byteFingerprint: Fingerprint;
27
+ kind: "regular" | "symlink" | "gitlink";
28
+ contentProjection?: "proof_receipts_stripped";
29
+ analysis: null | Readonly<{
30
+ contractVersion: string;
31
+ status: "ok" | "partial" | "unsupported" | "failed";
32
+ language: string;
33
+ sourceFile: string;
34
+ providerId: string | null;
35
+ providerStamp: unknown;
36
+ providerFingerprint: Fingerprint | null;
37
+ inputFingerprint: Fingerprint;
38
+ resultFingerprint: Fingerprint;
39
+ diagnosticCodes: readonly string[];
40
+ uncoveredRanges: readonly Readonly<{
41
+ startLine: number;
42
+ startColumn: number;
43
+ endLine: number;
44
+ endColumn: number;
45
+ reason: string;
46
+ }>[];
47
+ }>;
48
+ }>;
49
+ export type AnalysisReview = Readonly<{
50
+ kind: "unsupported_review";
51
+ side: "before" | "after";
52
+ wholeFile: true;
53
+ rationale: string;
54
+ }> | Readonly<{
55
+ kind: "partial_review";
56
+ side: "before" | "after";
57
+ limitationClass: string;
58
+ ranges: SideEvidence["analysis"] extends infer _T ? readonly Readonly<{
59
+ startLine: number;
60
+ startColumn: number;
61
+ endLine: number;
62
+ endColumn: number;
63
+ reason: string;
64
+ }>[] : never;
65
+ rationale: string;
66
+ }>;
67
+ export type ImpactDecision = Readonly<{
68
+ kind: "impact";
69
+ requirementIds: readonly string[];
70
+ knowledge: Readonly<{
71
+ state: "still_current";
72
+ rationale: string;
73
+ }> | Readonly<{
74
+ state: "updated";
75
+ stillCurrent?: readonly Readonly<{
76
+ requirementId: string;
77
+ rationale: string;
78
+ }>[];
79
+ entities: readonly Readonly<{
80
+ entityId: string;
81
+ artifactPath: string;
82
+ beforeFingerprint: Fingerprint | null;
83
+ afterFingerprint: Fingerprint;
84
+ }>[];
85
+ }>;
86
+ }> | Readonly<{
87
+ kind: "no_impact";
88
+ reason: string;
89
+ rationale: string;
90
+ }> | Readonly<{
91
+ kind: "not_applicable";
92
+ policyReason: string;
93
+ rationale: string;
94
+ }>;
95
+ export type ImpactFileRecord = Readonly<{
96
+ path: string;
97
+ status: Status;
98
+ oldPath?: string;
99
+ copyFromPath?: string;
100
+ analysisDepth: "symbol" | "metadata" | "file" | "none";
101
+ disposition: "checked" | "advisory" | "skipped";
102
+ skipReason?: "binary" | "unsupported_encoding" | "symlink" | "submodule";
103
+ gitMode?: string;
104
+ previousMode?: string;
105
+ oldHunkRanges: readonly HunkRange[];
106
+ newHunkRanges: readonly HunkRange[];
107
+ before: SideEvidence | null;
108
+ after: SideEvidence | null;
109
+ analysisReviews: readonly AnalysisReview[];
110
+ decision: ImpactDecision;
111
+ }>;
112
+ export type ImpactReviewRecord = Readonly<{
113
+ contractVersion: typeof IMPACT_REVIEW_VERSION;
114
+ policy: Readonly<{
115
+ id: string;
116
+ version: string;
117
+ fingerprint: Fingerprint;
118
+ }>;
119
+ evaluator: Readonly<{
120
+ contractVersion: typeof IMPACT_EVALUATOR_VERSION;
121
+ fingerprint: Fingerprint;
122
+ }>;
123
+ scope: Readonly<{
124
+ fingerprint: Fingerprint;
125
+ knowledgeFingerprint: Fingerprint;
126
+ providerSetFingerprint: Fingerprint;
127
+ }>;
128
+ /** Self-claimed local provenance; this field is explicitly not authorization. */
129
+ reviewer: Readonly<{
130
+ id: string;
131
+ source: "self-claimed-local";
132
+ }>;
133
+ reviewedAt: string;
134
+ files: readonly ImpactFileRecord[];
135
+ }>;
136
+ export type ImpactReviewDiagnostic = Readonly<{
137
+ code: string;
138
+ message: string;
139
+ path?: string;
140
+ }>;
141
+ export declare function canonicalJson(value: unknown): string;
142
+ export declare function fingerprint(value: unknown): Fingerprint;
143
+ export declare function fingerprintBytes(value: Uint8Array): Fingerprint;
144
+ export declare function parseImpactPolicy(value: unknown): ImpactPolicy;
145
+ export declare function parseImpactReviewRecord(value: unknown): ImpactReviewRecord;
146
+ export declare function assertSha256(value: string, name: string): asserts value is Fingerprint;
147
+ export declare function isGitObjectId(value: string): boolean;
148
+ //# sourceMappingURL=impact-review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact-review.d.ts","sourceRoot":"","sources":["../../src/traceability/impact-review.ts"],"names":[],"mappings":"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"}