kibi-cli 0.10.0 → 0.11.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/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -0
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +204 -3
- package/dist/commands/init-helpers.d.ts.map +1 -1
- package/dist/commands/init-helpers.js +11 -14
- package/dist/commands/sync/manifest.d.ts +8 -2
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +56 -11
- package/dist/commands/sync.d.ts +1 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +9 -7
- package/dist/commands/usage-metrics.d.ts +8 -0
- package/dist/commands/usage-metrics.d.ts.map +1 -0
- package/dist/commands/usage-metrics.js +323 -0
- package/dist/extractors/manifest.d.ts +30 -0
- package/dist/extractors/manifest.d.ts.map +1 -1
- package/dist/extractors/manifest.js +60 -7
- package/dist/extractors/symbol-coordinates.d.ts +15 -0
- package/dist/extractors/symbol-coordinates.d.ts.map +1 -0
- package/dist/extractors/symbol-coordinates.js +83 -0
- package/dist/public/extractors/manifest.d.ts +1 -1
- package/dist/public/extractors/manifest.d.ts.map +1 -1
- package/dist/public/extractors/manifest.js +1 -1
- package/dist/traceability/evidence-model.d.ts +142 -0
- package/dist/traceability/evidence-model.d.ts.map +1 -0
- package/dist/traceability/evidence-model.js +70 -0
- package/dist/traceability/git-staged.d.ts +1 -0
- package/dist/traceability/git-staged.d.ts.map +1 -1
- package/dist/traceability/git-staged.js +28 -3
- package/dist/traceability/staged-diagnostics.d.ts +25 -0
- package/dist/traceability/staged-diagnostics.d.ts.map +1 -0
- package/dist/traceability/staged-diagnostics.js +67 -0
- package/dist/traceability/staged-impact-contract.d.ts +57 -0
- package/dist/traceability/staged-impact-contract.d.ts.map +1 -0
- package/dist/traceability/staged-impact-contract.js +202 -0
- package/dist/traceability/staged-symbols-manifest.d.ts +23 -0
- package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -0
- package/dist/traceability/staged-symbols-manifest.js +269 -0
- package/dist/traceability/symbol-extract.d.ts.map +1 -1
- package/dist/traceability/symbol-extract.js +33 -9
- package/dist/utils/manifest-paths.d.ts +8 -0
- package/dist/utils/manifest-paths.d.ts.map +1 -0
- package/dist/utils/manifest-paths.js +62 -0
- package/package.json +1 -1
- package/src/public/extractors/manifest.ts +2 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable contract for staged Kibi impact evidence.
|
|
3
|
+
*
|
|
4
|
+
* This module is intentionally explicit and non-heuristic. Upstream staged-file
|
|
5
|
+
* analysis decides whether a source edit is behavior-changing; this contract only
|
|
6
|
+
* records that decision and the staged KB artifacts that cover it.
|
|
7
|
+
*/
|
|
8
|
+
/** User-facing KB schema documentation cited by staged diagnostics. */
|
|
9
|
+
export declare const KIBI_ENTITY_SCHEMA_DOC = "docs/entity-schema.md";
|
|
10
|
+
/** Canonical symbols manifest path used by staged traceability enforcement. */
|
|
11
|
+
export declare const KIBI_SYMBOLS_MANIFEST_PATH = "documentation/symbols.yaml";
|
|
12
|
+
/** Canonical symbol coordinates artifact used by staged traceability enforcement. */
|
|
13
|
+
export declare const KIBI_SYMBOL_COORDINATES_PATH = "documentation/symbol-coordinates.yaml";
|
|
14
|
+
/** Explicit declaration string for audited no-impact overrides. */
|
|
15
|
+
export declare const KIBI_NO_IMPACT_DECLARATION = "Kibi-Impact: none";
|
|
16
|
+
/** Canonical Kibi entity types that can provide staged evidence. */
|
|
17
|
+
export type KibiEntityType = "req" | "scenario" | "test" | "adr" | "flag" | "event" | "symbol" | "fact";
|
|
18
|
+
/**
|
|
19
|
+
* Explicit source-edit classification from upstream staged analysis.
|
|
20
|
+
*
|
|
21
|
+
* - `behavior_source_edit`: a supported staged source change already classified
|
|
22
|
+
* as behavior-changing or traceability-relevant by the caller.
|
|
23
|
+
* - `non_behavior_source_edit`: a supported staged source change that remains in
|
|
24
|
+
* scope for auditing but does not require KB changes.
|
|
25
|
+
*/
|
|
26
|
+
export type SourceChangeKind = "behavior_source_edit" | "non_behavior_source_edit";
|
|
27
|
+
/** One staged source file participating in Kibi impact evaluation. */
|
|
28
|
+
export interface KibiImpactSourceChange {
|
|
29
|
+
/** Repo-relative staged source path. */
|
|
30
|
+
path: string;
|
|
31
|
+
/** Explicit upstream classification; this module does not infer it. */
|
|
32
|
+
kind: SourceChangeKind;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Staged KB markdown evidence linked to one or more staged source files.
|
|
36
|
+
*
|
|
37
|
+
* Evidence is explicit only when the staged artifact names concrete KB entities
|
|
38
|
+
* and lists the staged source paths it is intended to cover.
|
|
39
|
+
*/
|
|
40
|
+
export interface KibiImpactKbArtifact {
|
|
41
|
+
/** Artifact category. Kept narrow to avoid heuristic interpretation. */
|
|
42
|
+
kind: "entity_markdown" | "symbols_manifest";
|
|
43
|
+
/** Repo-relative staged KB artifact path. */
|
|
44
|
+
path: string;
|
|
45
|
+
/** Canonical Kibi entity types present in the staged artifact. */
|
|
46
|
+
entityTypes: KibiEntityType[];
|
|
47
|
+
/** Concrete KB entities updated by the staged artifact. */
|
|
48
|
+
entityIds: string[];
|
|
49
|
+
/** Repo-relative source paths explicitly covered by this artifact. */
|
|
50
|
+
sourcePaths: string[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Deterministic symbol coordinates artifact state for the staged change-set.
|
|
54
|
+
*
|
|
55
|
+
* - `not_required`: symbol extraction output did not change for the listed
|
|
56
|
+
* staged source paths.
|
|
57
|
+
* - `fresh`: a staged coordinate refresh covers the listed source paths.
|
|
58
|
+
* - `stale`: coordinate artifact content is reverted, outdated, or otherwise does not match
|
|
59
|
+
* the staged symbol extraction result.
|
|
60
|
+
* - `missing`: a refresh is required but no staged coordinate artifact exists.
|
|
61
|
+
*/
|
|
62
|
+
export interface KibiImpactSymbolsManifest {
|
|
63
|
+
/** Canonical repo-relative symbol coordinate artifact path. */
|
|
64
|
+
path: string;
|
|
65
|
+
/** Explicit manifest freshness state. */
|
|
66
|
+
state: "not_required" | "fresh" | "stale" | "missing";
|
|
67
|
+
/** Repo-relative staged source paths whose symbol output this state describes. */
|
|
68
|
+
sourcePaths: string[];
|
|
69
|
+
}
|
|
70
|
+
/** Supported audited reasons for a no-impact override. */
|
|
71
|
+
export type KibiNoImpactReason = "false_positive" | "non_behavioral_source_edit";
|
|
72
|
+
/**
|
|
73
|
+
* Explicit no-impact override record.
|
|
74
|
+
*
|
|
75
|
+
* Overrides are only valid for non-behavioral edits or classifier false
|
|
76
|
+
* positives. They never satisfy real behavior-changing source edits.
|
|
77
|
+
*/
|
|
78
|
+
export interface KibiNoImpactOverride {
|
|
79
|
+
/** Required literal declaration. */
|
|
80
|
+
declaration: typeof KIBI_NO_IMPACT_DECLARATION;
|
|
81
|
+
/** Repo-relative staged record path carrying the override. */
|
|
82
|
+
path: string;
|
|
83
|
+
/** Repo-relative source paths covered by the override record. */
|
|
84
|
+
sourcePaths: string[];
|
|
85
|
+
/** Audited reason for allowing the override. */
|
|
86
|
+
reason: KibiNoImpactReason;
|
|
87
|
+
/** Human-readable justification stored with the override record. */
|
|
88
|
+
rationale: string;
|
|
89
|
+
}
|
|
90
|
+
/** Explicit evidence state: staged KB artifacts are present. */
|
|
91
|
+
export interface KibiImpactKbChangesMode {
|
|
92
|
+
kind: "kb_changes";
|
|
93
|
+
/** Staged KB markdown artifacts linked to staged source changes. */
|
|
94
|
+
kbArtifacts: KibiImpactKbArtifact[];
|
|
95
|
+
}
|
|
96
|
+
/** Explicit evidence state: a staged no-impact override is being used. */
|
|
97
|
+
export interface KibiImpactNoImpactOverrideMode {
|
|
98
|
+
kind: "no_impact_override";
|
|
99
|
+
/** Staged override record for false positives or non-behavioral edits. */
|
|
100
|
+
override: KibiNoImpactOverride;
|
|
101
|
+
}
|
|
102
|
+
/** Explicit evidence state: no staged KB evidence or override exists. */
|
|
103
|
+
export interface KibiImpactMissingMode {
|
|
104
|
+
kind: "missing";
|
|
105
|
+
}
|
|
106
|
+
/** Discriminated union describing how the staged change-set is justified. */
|
|
107
|
+
export type KibiImpactMode = KibiImpactKbChangesMode | KibiImpactNoImpactOverrideMode | KibiImpactMissingMode;
|
|
108
|
+
/**
|
|
109
|
+
* Full evidence snapshot for staged Kibi impact enforcement.
|
|
110
|
+
*
|
|
111
|
+
* `sourceChanges` is always required so diagnostics can cite exact staged source
|
|
112
|
+
* files. `mode` captures whether those files are backed by KB changes, by an
|
|
113
|
+
* audited no-impact override, or by nothing. `symbolsManifest` records whether a
|
|
114
|
+
* staged manifest refresh is part of that evidence.
|
|
115
|
+
*/
|
|
116
|
+
export interface KibiImpactEvidence {
|
|
117
|
+
/** All staged source files in scope for Kibi impact enforcement. */
|
|
118
|
+
sourceChanges: KibiImpactSourceChange[];
|
|
119
|
+
/** Deterministic staged symbols manifest state for the same change-set. */
|
|
120
|
+
symbolsManifest: KibiImpactSymbolsManifest;
|
|
121
|
+
/** Explicit evidence mode for the staged change-set. */
|
|
122
|
+
mode: KibiImpactMode;
|
|
123
|
+
}
|
|
124
|
+
/** Returns staged behavior-changing source paths only. */
|
|
125
|
+
export declare function getBehaviorSourcePaths(evidence: KibiImpactEvidence): string[];
|
|
126
|
+
/** Returns staged source paths covered by explicit KB artifacts. */
|
|
127
|
+
export declare function getKbCoveredSourcePaths(evidence: KibiImpactEvidence): string[];
|
|
128
|
+
/** Returns staged source paths covered by a fresh symbol coordinate refresh. */
|
|
129
|
+
export declare function getFreshSymbolsManifestSourcePaths(evidence: KibiImpactEvidence): string[];
|
|
130
|
+
/**
|
|
131
|
+
* Returns all staged evidence file paths that a later CLI integration can cite
|
|
132
|
+
* in diagnostics or logs.
|
|
133
|
+
*/
|
|
134
|
+
export declare function getKbEvidencePaths(evidence: KibiImpactEvidence): string[];
|
|
135
|
+
/** True when a staged no-impact override includes a non-empty rationale. */
|
|
136
|
+
export declare function hasOverrideRationale(evidence: KibiImpactEvidence): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Returns behavior-changing staged source files that still lack valid Kibi
|
|
139
|
+
* impact evidence.
|
|
140
|
+
*/
|
|
141
|
+
export declare function getMissingBehaviorSourcePaths(evidence: KibiImpactEvidence): string[];
|
|
142
|
+
//# sourceMappingURL=evidence-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-model.d.ts","sourceRoot":"","sources":["../../src/traceability/evidence-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable contract for staged Kibi impact evidence.
|
|
3
|
+
*
|
|
4
|
+
* This module is intentionally explicit and non-heuristic. Upstream staged-file
|
|
5
|
+
* analysis decides whether a source edit is behavior-changing; this contract only
|
|
6
|
+
* records that decision and the staged KB artifacts that cover it.
|
|
7
|
+
*/
|
|
8
|
+
/** User-facing KB schema documentation cited by staged diagnostics. */
|
|
9
|
+
export const KIBI_ENTITY_SCHEMA_DOC = "docs/entity-schema.md";
|
|
10
|
+
/** Canonical symbols manifest path used by staged traceability enforcement. */
|
|
11
|
+
export const KIBI_SYMBOLS_MANIFEST_PATH = "documentation/symbols.yaml";
|
|
12
|
+
/** Canonical symbol coordinates artifact used by staged traceability enforcement. */
|
|
13
|
+
export const KIBI_SYMBOL_COORDINATES_PATH = "documentation/symbol-coordinates.yaml";
|
|
14
|
+
/** Explicit declaration string for audited no-impact overrides. */
|
|
15
|
+
export const KIBI_NO_IMPACT_DECLARATION = "Kibi-Impact: none";
|
|
16
|
+
function uniqueSorted(values) {
|
|
17
|
+
return Array.from(new Set(values)).sort();
|
|
18
|
+
}
|
|
19
|
+
/** Returns staged behavior-changing source paths only. */
|
|
20
|
+
export function getBehaviorSourcePaths(evidence) {
|
|
21
|
+
return evidence.sourceChanges
|
|
22
|
+
.filter((change) => change.kind === "behavior_source_edit")
|
|
23
|
+
.map((change) => change.path)
|
|
24
|
+
.sort();
|
|
25
|
+
}
|
|
26
|
+
/** Returns staged source paths covered by explicit KB artifacts. */
|
|
27
|
+
export function getKbCoveredSourcePaths(evidence) {
|
|
28
|
+
if (evidence.mode.kind !== "kb_changes") {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
return uniqueSorted(evidence.mode.kbArtifacts.flatMap((artifact) => artifact.sourcePaths));
|
|
32
|
+
}
|
|
33
|
+
/** Returns staged source paths covered by a fresh symbol coordinate refresh. */
|
|
34
|
+
export function getFreshSymbolsManifestSourcePaths(evidence) {
|
|
35
|
+
if (evidence.symbolsManifest.state !== "fresh") {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
return [...evidence.symbolsManifest.sourcePaths].sort();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns all staged evidence file paths that a later CLI integration can cite
|
|
42
|
+
* in diagnostics or logs.
|
|
43
|
+
*/
|
|
44
|
+
export function getKbEvidencePaths(evidence) {
|
|
45
|
+
const paths = [];
|
|
46
|
+
if (evidence.mode.kind === "kb_changes") {
|
|
47
|
+
paths.push(...evidence.mode.kbArtifacts.map((artifact) => artifact.path));
|
|
48
|
+
}
|
|
49
|
+
if (evidence.symbolsManifest.state === "fresh") {
|
|
50
|
+
paths.push(evidence.symbolsManifest.path);
|
|
51
|
+
}
|
|
52
|
+
return uniqueSorted(paths);
|
|
53
|
+
}
|
|
54
|
+
/** True when a staged no-impact override includes a non-empty rationale. */
|
|
55
|
+
export function hasOverrideRationale(evidence) {
|
|
56
|
+
return (evidence.mode.kind === "no_impact_override" &&
|
|
57
|
+
evidence.mode.override.rationale.trim().length > 0);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Returns behavior-changing staged source files that still lack valid Kibi
|
|
61
|
+
* impact evidence.
|
|
62
|
+
*/
|
|
63
|
+
export function getMissingBehaviorSourcePaths(evidence) {
|
|
64
|
+
const behaviorPaths = getBehaviorSourcePaths(evidence);
|
|
65
|
+
const coveredPaths = new Set([
|
|
66
|
+
...getKbCoveredSourcePaths(evidence),
|
|
67
|
+
...getFreshSymbolsManifestSourcePaths(evidence),
|
|
68
|
+
]);
|
|
69
|
+
return behaviorPaths.filter((path) => !coveredPaths.has(path));
|
|
70
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-staged.d.ts","sourceRoot":"","sources":["../../src/traceability/git-staged.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"git-staged.d.ts","sourceRoot":"","sources":["../../src/traceability/git-staged.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAK,MAAM,CAAC;AAalE;;GAEG;AAEH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAwB5C;AAsED;;GAEG;AACH,wBAAgB,kBAAkB,CAEhC,QAAQ,EAAE,MAAM,EAChB,SAAS,UAAQ,GAChB,SAAS,EAAE,CAuBb;AAED;;GAEG;AAEH,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAAiB,GAAG,UAAU,EAAE,CAwGpE;AAED,eAAe,cAAc,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
2
|
import { isCliTraceOrDebugEnabled } from "../env.js";
|
|
3
|
+
import { loadConfig } from "../utils/config.js";
|
|
3
4
|
function runGit(cmd, exec) {
|
|
4
5
|
try {
|
|
5
6
|
return exec(cmd, { encoding: "utf8" });
|
|
@@ -47,8 +48,20 @@ const SUPPORTED_EXT = new Set([
|
|
|
47
48
|
".mjs",
|
|
48
49
|
".cjs",
|
|
49
50
|
]);
|
|
50
|
-
const SUPPORTED_MANIFEST = new Set([
|
|
51
|
-
|
|
51
|
+
const SUPPORTED_MANIFEST = new Set([
|
|
52
|
+
"symbols.yaml",
|
|
53
|
+
"symbols.yml",
|
|
54
|
+
"symbol-coordinates.yaml",
|
|
55
|
+
]);
|
|
56
|
+
const ENTITY_MARKDOWN_DIRS = [
|
|
57
|
+
"/requirements/",
|
|
58
|
+
"/scenarios/",
|
|
59
|
+
"/tests/",
|
|
60
|
+
"/facts/",
|
|
61
|
+
"/adr/",
|
|
62
|
+
"/flags/",
|
|
63
|
+
"/events/",
|
|
64
|
+
];
|
|
52
65
|
function shouldLogTraceDebug() {
|
|
53
66
|
return isCliTraceOrDebugEnabled();
|
|
54
67
|
}
|
|
@@ -72,13 +85,24 @@ function isEntityMarkdown(p) {
|
|
|
72
85
|
return false;
|
|
73
86
|
}
|
|
74
87
|
function isManifestFile(p) {
|
|
75
|
-
const base = p.split(/[
|
|
88
|
+
const base = p.split(/[\\/]/).pop();
|
|
76
89
|
if (!base)
|
|
77
90
|
return false;
|
|
78
91
|
for (const name of SUPPORTED_MANIFEST) {
|
|
79
92
|
if (base === name)
|
|
80
93
|
return true;
|
|
81
94
|
}
|
|
95
|
+
try {
|
|
96
|
+
const config = loadConfig(process.cwd());
|
|
97
|
+
if (config.paths.symbols) {
|
|
98
|
+
const configuredBase = config.paths.symbols.split(/[\\/]/).pop();
|
|
99
|
+
if (configuredBase && base === configuredBase)
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// ignore config read errors
|
|
105
|
+
}
|
|
82
106
|
return false;
|
|
83
107
|
}
|
|
84
108
|
/**
|
|
@@ -198,6 +222,7 @@ export function getStagedFiles(exec = execSync) {
|
|
|
198
222
|
status,
|
|
199
223
|
...(oldPath !== undefined ? { oldPath } : {}),
|
|
200
224
|
hunkRanges,
|
|
225
|
+
diffText,
|
|
201
226
|
content,
|
|
202
227
|
});
|
|
203
228
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type KibiImpactEvidence } from "./evidence-model.js";
|
|
2
|
+
export type KibiImpactDiagnosticId = "kibi_impact_evidence_missing" | "symbols_manifest_stale" | "kibi_impact_override_missing_rationale";
|
|
3
|
+
export interface KibiImpactDiagnostic {
|
|
4
|
+
/** Stable staged-enforcement diagnostic identifier. */
|
|
5
|
+
id: KibiImpactDiagnosticId;
|
|
6
|
+
/** Hard-gate severity for staged enforcement. */
|
|
7
|
+
severity: "error";
|
|
8
|
+
/** Repo-relative files that explain why the diagnostic fired. */
|
|
9
|
+
files: string[];
|
|
10
|
+
/** User-facing docs that explain the policy. */
|
|
11
|
+
docs: string[];
|
|
12
|
+
/** Exact CLI-facing diagnostic message. */
|
|
13
|
+
message: string;
|
|
14
|
+
/** Deterministic remediation guidance. */
|
|
15
|
+
suggestion: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Collects deterministic staged diagnostics for Kibi impact enforcement.
|
|
19
|
+
*
|
|
20
|
+
* This function assumes upstream staged analysis has already classified source
|
|
21
|
+
* files and manifest freshness. It only evaluates explicit predicates recorded in
|
|
22
|
+
* `KibiImpactEvidence`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function collectStagedKibiDiagnostics(evidence: KibiImpactEvidence): KibiImpactDiagnostic[];
|
|
25
|
+
//# sourceMappingURL=staged-diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staged-diagnostics.d.ts","sourceRoot":"","sources":["../../src/traceability/staged-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,sBAAsB,GAC9B,8BAA8B,GAC9B,wBAAwB,GACxB,wCAAwC,CAAC;AAE7C,MAAM,WAAW,oBAAoB;IACnC,uDAAuD;IACvD,EAAE,EAAE,sBAAsB,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,gDAAgD;IAChD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;CACpB;AAsDD;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,kBAAkB,GAC3B,oBAAoB,EAAE,CAoCxB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { KIBI_ENTITY_SCHEMA_DOC, KIBI_SYMBOL_COORDINATES_PATH, KIBI_SYMBOLS_MANIFEST_PATH, getBehaviorSourcePaths, getMissingBehaviorSourcePaths, hasOverrideRationale, } from "./evidence-model.js";
|
|
2
|
+
function formatFileList(paths) {
|
|
3
|
+
return paths.join(", ");
|
|
4
|
+
}
|
|
5
|
+
function createMissingEvidenceDiagnostic(paths) {
|
|
6
|
+
return {
|
|
7
|
+
id: "kibi_impact_evidence_missing",
|
|
8
|
+
severity: "error",
|
|
9
|
+
files: [...paths],
|
|
10
|
+
docs: [KIBI_ENTITY_SCHEMA_DOC],
|
|
11
|
+
message: `Behavior-changing staged files are missing Kibi impact evidence (see ${KIBI_ENTITY_SCHEMA_DOC}): ${formatFileList(paths)}`,
|
|
12
|
+
suggestion: `Query Kibi via MCP before deciding, then stage requirement/scenario/test/fact/symbol markdown evidence, staged authored ${KIBI_SYMBOLS_MANIFEST_PATH} metadata, or refreshed ${KIBI_SYMBOL_COORDINATES_PATH}. Re-run kibi check --staged after staging the evidence.`,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function createSymbolsManifestStaleDiagnostic(paths) {
|
|
16
|
+
return {
|
|
17
|
+
id: "symbols_manifest_stale",
|
|
18
|
+
severity: "error",
|
|
19
|
+
files: [KIBI_SYMBOL_COORDINATES_PATH, ...paths],
|
|
20
|
+
docs: [KIBI_ENTITY_SCHEMA_DOC],
|
|
21
|
+
message: `${KIBI_SYMBOL_COORDINATES_PATH} is stale or missing for staged source files: ${formatFileList(paths)}`,
|
|
22
|
+
suggestion: `Run kibi sync --refresh-symbol-coordinates && git add ${KIBI_SYMBOL_COORDINATES_PATH} ${KIBI_SYMBOLS_MANIFEST_PATH}, then re-run kibi check --staged.`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function createMissingOverrideRationaleDiagnostic(evidence) {
|
|
26
|
+
if (evidence.mode.kind !== "no_impact_override") {
|
|
27
|
+
throw new Error("Override rationale diagnostic requires a no-impact override");
|
|
28
|
+
}
|
|
29
|
+
const paths = [...evidence.mode.override.sourcePaths].sort();
|
|
30
|
+
return {
|
|
31
|
+
id: "kibi_impact_override_missing_rationale",
|
|
32
|
+
severity: "error",
|
|
33
|
+
files: [evidence.mode.override.path, ...paths],
|
|
34
|
+
docs: [KIBI_ENTITY_SCHEMA_DOC],
|
|
35
|
+
message: `Kibi-Impact: none override is missing rationale for staged source files: ${formatFileList(paths)}`,
|
|
36
|
+
suggestion: "Add a non-empty rationale in the same staged override record, keep overrides limited to false positives or non-behavioral source edits, and re-run kibi check --staged.",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Collects deterministic staged diagnostics for Kibi impact enforcement.
|
|
41
|
+
*
|
|
42
|
+
* This function assumes upstream staged analysis has already classified source
|
|
43
|
+
* files and manifest freshness. It only evaluates explicit predicates recorded in
|
|
44
|
+
* `KibiImpactEvidence`.
|
|
45
|
+
*/
|
|
46
|
+
export function collectStagedKibiDiagnostics(evidence) {
|
|
47
|
+
const diagnostics = [];
|
|
48
|
+
if (evidence.mode.kind === "no_impact_override" &&
|
|
49
|
+
!hasOverrideRationale(evidence)) {
|
|
50
|
+
diagnostics.push(createMissingOverrideRationaleDiagnostic(evidence));
|
|
51
|
+
}
|
|
52
|
+
if ((evidence.symbolsManifest.state === "stale" ||
|
|
53
|
+
evidence.symbolsManifest.state === "missing") &&
|
|
54
|
+
evidence.symbolsManifest.sourcePaths.length > 0) {
|
|
55
|
+
diagnostics.push(createSymbolsManifestStaleDiagnostic([...evidence.symbolsManifest.sourcePaths].sort()));
|
|
56
|
+
}
|
|
57
|
+
const missingBehaviorPaths = getMissingBehaviorSourcePaths(evidence);
|
|
58
|
+
if (missingBehaviorPaths.length > 0) {
|
|
59
|
+
diagnostics.push(createMissingEvidenceDiagnostic(missingBehaviorPaths));
|
|
60
|
+
}
|
|
61
|
+
if (evidence.mode.kind === "no_impact_override" &&
|
|
62
|
+
evidence.mode.override.sourcePaths.length === 0 &&
|
|
63
|
+
getBehaviorSourcePaths(evidence).length === 0) {
|
|
64
|
+
return diagnostics;
|
|
65
|
+
}
|
|
66
|
+
return diagnostics;
|
|
67
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export declare const KIBI_IMPACT_DIAGNOSTIC_IDS: readonly ["kibi_impact_evidence_missing", "symbols_manifest_stale", "kibi_impact_override_missing_rationale"];
|
|
2
|
+
export type KibiImpactDiagnosticId = (typeof KIBI_IMPACT_DIAGNOSTIC_IDS)[number];
|
|
3
|
+
export type KibiImpactEvidenceKind = "entity_markdown" | "symbols_manifest" | "audited_no_impact";
|
|
4
|
+
export interface KibiImpactDiagnosticContract {
|
|
5
|
+
id: KibiImpactDiagnosticId;
|
|
6
|
+
title: string;
|
|
7
|
+
resolution: [string, string, string];
|
|
8
|
+
}
|
|
9
|
+
export interface KibiImpactEvidenceInput {
|
|
10
|
+
filePath?: string;
|
|
11
|
+
extractionOutputChanged?: boolean;
|
|
12
|
+
overrideDeclared?: boolean;
|
|
13
|
+
overrideRationale?: string | null;
|
|
14
|
+
symbolsManifestPath?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface BehaviorSourceEditInput {
|
|
17
|
+
path: string;
|
|
18
|
+
diffText: string;
|
|
19
|
+
intersectsBehaviorBearingSymbol: boolean;
|
|
20
|
+
knownUserFacingSurface?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface ParsedKibiImpactOverride {
|
|
23
|
+
declared: boolean;
|
|
24
|
+
rationale: string | null;
|
|
25
|
+
}
|
|
26
|
+
export interface AuditedNoImpactOverrideInput {
|
|
27
|
+
behaviorSourceEdit: boolean;
|
|
28
|
+
override: ParsedKibiImpactOverride;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Staged Kibi impact contract for `kibi check --staged`.
|
|
32
|
+
*
|
|
33
|
+
* This is intentionally a small, stable contract for tests and future staged
|
|
34
|
+
* enforcement wiring:
|
|
35
|
+
* - `behavior_source_edit` is a supported source-file edit whose staged hunks
|
|
36
|
+
* intersect exported or other behavior-bearing/user-facing surfaces and whose
|
|
37
|
+
* changed lines are not comment-only or formatting-only.
|
|
38
|
+
* - `kibi_impact_evidence` is staged entity markdown, staged authored
|
|
39
|
+
* `documentation/symbols.yaml` metadata, refreshed
|
|
40
|
+
* `documentation/symbol-coordinates.yaml` when extraction output changes, or
|
|
41
|
+
* an explicit audited `Kibi-Impact: none` declaration with
|
|
42
|
+
* rationale for false positives/non-behavior-only edits.
|
|
43
|
+
* - `Kibi-Impact: none` never satisfies a genuine behavior change.
|
|
44
|
+
* - Test-only edits do not require new KB evidence unless they introduce
|
|
45
|
+
* executable test symbols that need traceability.
|
|
46
|
+
*
|
|
47
|
+
* This contract deliberately avoids broad semantic diffing and stays
|
|
48
|
+
* conservative so later staged-check enforcement can share exact diagnostic IDs
|
|
49
|
+
* and operator-facing remediation steps.
|
|
50
|
+
*/
|
|
51
|
+
export declare const KIBI_IMPACT_DIAGNOSTICS: Record<KibiImpactDiagnosticId, KibiImpactDiagnosticContract>;
|
|
52
|
+
export declare function classifyKibiImpactEvidence(input: KibiImpactEvidenceInput): KibiImpactEvidenceKind | null;
|
|
53
|
+
export declare function parseKibiImpactOverride(text: string): ParsedKibiImpactOverride;
|
|
54
|
+
export declare function isAuditedNoImpactOverrideAllowed(input: AuditedNoImpactOverrideInput): boolean;
|
|
55
|
+
export declare function isBehaviorSourceEdit(input: BehaviorSourceEditInput): boolean;
|
|
56
|
+
export declare function isSupportedBehaviorSourcePath(filePath: string): boolean;
|
|
57
|
+
//# sourceMappingURL=staged-impact-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staged-impact-contract.d.ts","sourceRoot":"","sources":["../../src/traceability/staged-impact-contract.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,0BAA0B,+GAI7B,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAChC,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,MAAM,MAAM,sBAAsB,GAC9B,iBAAiB,GACjB,kBAAkB,GAClB,mBAAmB,CAAC;AAExB,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,sBAAsB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B,EAAE,OAAO,CAAC;IACzC,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,4BAA4B;IAC3C,kBAAkB,EAAE,OAAO,CAAC;IAC5B,QAAQ,EAAE,wBAAwB,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAC1C,sBAAsB,EACtB,4BAA4B,CA6B7B,CAAC;AAEF,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,uBAAuB,GAC7B,sBAAsB,GAAG,IAAI,CAsB/B;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,GACX,wBAAwB,CAS1B;AAED,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,4BAA4B,GAClC,OAAO,CAMT;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CA8B5E;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQvE"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
const SUPPORTED_BEHAVIOR_SOURCE_EXTENSIONS = new Set([
|
|
2
|
+
".ts",
|
|
3
|
+
".tsx",
|
|
4
|
+
".js",
|
|
5
|
+
".jsx",
|
|
6
|
+
".mts",
|
|
7
|
+
".cts",
|
|
8
|
+
".mjs",
|
|
9
|
+
".cjs",
|
|
10
|
+
]);
|
|
11
|
+
const ENTITY_EVIDENCE_SEGMENTS = [
|
|
12
|
+
"/requirements/",
|
|
13
|
+
"/scenarios/",
|
|
14
|
+
"/tests/",
|
|
15
|
+
"/facts/",
|
|
16
|
+
"/adr/",
|
|
17
|
+
"/flags/",
|
|
18
|
+
"/events/",
|
|
19
|
+
];
|
|
20
|
+
export const KIBI_IMPACT_DIAGNOSTIC_IDS = [
|
|
21
|
+
"kibi_impact_evidence_missing",
|
|
22
|
+
"symbols_manifest_stale",
|
|
23
|
+
"kibi_impact_override_missing_rationale",
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Staged Kibi impact contract for `kibi check --staged`.
|
|
27
|
+
*
|
|
28
|
+
* This is intentionally a small, stable contract for tests and future staged
|
|
29
|
+
* enforcement wiring:
|
|
30
|
+
* - `behavior_source_edit` is a supported source-file edit whose staged hunks
|
|
31
|
+
* intersect exported or other behavior-bearing/user-facing surfaces and whose
|
|
32
|
+
* changed lines are not comment-only or formatting-only.
|
|
33
|
+
* - `kibi_impact_evidence` is staged entity markdown, staged authored
|
|
34
|
+
* `documentation/symbols.yaml` metadata, refreshed
|
|
35
|
+
* `documentation/symbol-coordinates.yaml` when extraction output changes, or
|
|
36
|
+
* an explicit audited `Kibi-Impact: none` declaration with
|
|
37
|
+
* rationale for false positives/non-behavior-only edits.
|
|
38
|
+
* - `Kibi-Impact: none` never satisfies a genuine behavior change.
|
|
39
|
+
* - Test-only edits do not require new KB evidence unless they introduce
|
|
40
|
+
* executable test symbols that need traceability.
|
|
41
|
+
*
|
|
42
|
+
* This contract deliberately avoids broad semantic diffing and stays
|
|
43
|
+
* conservative so later staged-check enforcement can share exact diagnostic IDs
|
|
44
|
+
* and operator-facing remediation steps.
|
|
45
|
+
*/
|
|
46
|
+
export const KIBI_IMPACT_DIAGNOSTICS = {
|
|
47
|
+
kibi_impact_evidence_missing: {
|
|
48
|
+
id: "kibi_impact_evidence_missing",
|
|
49
|
+
title: "Behavior edit requires staged Kibi impact evidence",
|
|
50
|
+
resolution: [
|
|
51
|
+
"Query Kibi via MCP first: use kb_search for discovery, then kb_query for exact follow-up.",
|
|
52
|
+
"Stage related KB entity markdown, stage authored documentation/symbols.yaml metadata, or refresh coordinates with kibi sync --refresh-symbol-coordinates and stage documentation/symbol-coordinates.yaml documentation/symbols.yaml.",
|
|
53
|
+
"Re-run or let the hook run kibi check --staged.",
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
symbols_manifest_stale: {
|
|
57
|
+
id: "symbols_manifest_stale",
|
|
58
|
+
title: "Symbol coordinates evidence is stale for changed extraction output",
|
|
59
|
+
resolution: [
|
|
60
|
+
"Refresh symbol coordinates for the changed source file with kibi sync --refresh-symbol-coordinates.",
|
|
61
|
+
"Stage documentation/symbol-coordinates.yaml in the same change as the behavior edit, and stage documentation/symbols.yaml only if migration cleanup changed it.",
|
|
62
|
+
"Re-run or let the hook run kibi check --staged.",
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
kibi_impact_override_missing_rationale: {
|
|
66
|
+
id: "kibi_impact_override_missing_rationale",
|
|
67
|
+
title: "Kibi no-impact override requires an explicit rationale",
|
|
68
|
+
resolution: [
|
|
69
|
+
"Use an audited declaration only for false positives or non-behavioral edits.",
|
|
70
|
+
"Include both 'Kibi-Impact: none' and a nearby 'Rationale:' line describing why the edit has no behavior impact.",
|
|
71
|
+
"Re-run or let the hook run kibi check --staged.",
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
export function classifyKibiImpactEvidence(input) {
|
|
76
|
+
if (input.overrideDeclared && hasText(input.overrideRationale)) {
|
|
77
|
+
return "audited_no_impact";
|
|
78
|
+
}
|
|
79
|
+
const filePath = input.filePath ?? "";
|
|
80
|
+
if (!filePath) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
if (isEntityEvidenceMarkdown(filePath)) {
|
|
84
|
+
return "entity_markdown";
|
|
85
|
+
}
|
|
86
|
+
if (isSymbolsManifest(filePath, input.symbolsManifestPath) &&
|
|
87
|
+
input.extractionOutputChanged) {
|
|
88
|
+
return "symbols_manifest";
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
export function parseKibiImpactOverride(text) {
|
|
93
|
+
const declared = /^Kibi-Impact:\s*none\s*$/im.test(text);
|
|
94
|
+
const rationaleMatch = text.match(/^Rationale:\s*(.+)\s*$/im);
|
|
95
|
+
return {
|
|
96
|
+
declared,
|
|
97
|
+
rationale: hasText(rationaleMatch?.[1])
|
|
98
|
+
? (rationaleMatch?.[1]?.trim() ?? null)
|
|
99
|
+
: null,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export function isAuditedNoImpactOverrideAllowed(input) {
|
|
103
|
+
return (input.override.declared &&
|
|
104
|
+
hasText(input.override.rationale) &&
|
|
105
|
+
!input.behaviorSourceEdit);
|
|
106
|
+
}
|
|
107
|
+
export function isBehaviorSourceEdit(input) {
|
|
108
|
+
if (!isSupportedBehaviorSourcePath(input.path)) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
if (!input.intersectsBehaviorBearingSymbol && !input.knownUserFacingSurface) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
const changes = extractChangedLines(input.diffText);
|
|
115
|
+
if (changes.length === 0) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (changes.every((line) => isIgnorableChangeLine(line))) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
const removed = normalizeChangedLines(changes.filter((line) => line.kind === "remove"));
|
|
122
|
+
const added = normalizeChangedLines(changes.filter((line) => line.kind === "add"));
|
|
123
|
+
if (removed.length > 0 && removed.join("\n") === added.join("\n")) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
export function isSupportedBehaviorSourcePath(filePath) {
|
|
129
|
+
for (const extension of SUPPORTED_BEHAVIOR_SOURCE_EXTENSIONS) {
|
|
130
|
+
if (filePath.endsWith(extension)) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
function isEntityEvidenceMarkdown(filePath) {
|
|
137
|
+
if (!filePath.endsWith(".md")) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
return ENTITY_EVIDENCE_SEGMENTS.some((segment) => filePath.includes(segment));
|
|
141
|
+
}
|
|
142
|
+
function isSymbolsManifest(filePath, symbolsManifestPath) {
|
|
143
|
+
const candidates = new Set([
|
|
144
|
+
"symbols.yaml",
|
|
145
|
+
"symbols.yml",
|
|
146
|
+
"documentation/symbols.yaml",
|
|
147
|
+
"documentation/symbols.yml",
|
|
148
|
+
]);
|
|
149
|
+
if (symbolsManifestPath) {
|
|
150
|
+
candidates.add(symbolsManifestPath);
|
|
151
|
+
if (symbolsManifestPath.endsWith(".yaml")) {
|
|
152
|
+
candidates.add(`${symbolsManifestPath.slice(0, -5)}.yml`);
|
|
153
|
+
}
|
|
154
|
+
if (symbolsManifestPath.endsWith(".yml")) {
|
|
155
|
+
candidates.add(`${symbolsManifestPath.slice(0, -4)}.yaml`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (candidates.has(filePath)) {
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
return (filePath.endsWith("/symbols.yaml") ||
|
|
162
|
+
filePath.endsWith("/symbols.yml") ||
|
|
163
|
+
filePath === "symbols.yaml" ||
|
|
164
|
+
filePath === "symbols.yml");
|
|
165
|
+
}
|
|
166
|
+
function hasText(value) {
|
|
167
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
168
|
+
}
|
|
169
|
+
function extractChangedLines(diffText) {
|
|
170
|
+
const lines = diffText.split(/\r?\n/);
|
|
171
|
+
const changes = [];
|
|
172
|
+
for (const line of lines) {
|
|
173
|
+
if (line.startsWith("+++") ||
|
|
174
|
+
line.startsWith("---") ||
|
|
175
|
+
line.startsWith("@@")) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (line.startsWith("+")) {
|
|
179
|
+
changes.push({ kind: "add", text: line.slice(1) });
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (line.startsWith("-")) {
|
|
183
|
+
changes.push({ kind: "remove", text: line.slice(1) });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return changes;
|
|
187
|
+
}
|
|
188
|
+
function isIgnorableChangeLine(line) {
|
|
189
|
+
const trimmed = line.text.trim();
|
|
190
|
+
if (!trimmed) {
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
return (trimmed.startsWith("//") ||
|
|
194
|
+
trimmed.startsWith("/*") ||
|
|
195
|
+
trimmed.startsWith("*/") ||
|
|
196
|
+
trimmed.startsWith("*"));
|
|
197
|
+
}
|
|
198
|
+
function normalizeChangedLines(lines) {
|
|
199
|
+
return lines
|
|
200
|
+
.map((line) => line.text.replace(/\s+/g, ""))
|
|
201
|
+
.filter((line) => line.length > 0);
|
|
202
|
+
}
|