@neurcode-ai/cli 0.10.0 → 0.12.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/.telemetry-bundle/dist/__tests__/harvest-verify.test.d.ts +1 -0
- package/.telemetry-bundle/dist/__tests__/harvest-verify.test.js +86 -0
- package/.telemetry-bundle/dist/contracts.d.ts +58 -0
- package/.telemetry-bundle/dist/contracts.js +8 -0
- package/.telemetry-bundle/dist/harvest-verify.d.ts +9 -0
- package/.telemetry-bundle/dist/harvest-verify.js +128 -0
- package/.telemetry-bundle/dist/index.d.ts +10 -0
- package/.telemetry-bundle/dist/index.js +22 -0
- package/.telemetry-bundle/dist/precision/leaderboards.d.ts +20 -0
- package/.telemetry-bundle/dist/precision/leaderboards.js +72 -0
- package/.telemetry-bundle/dist/reader.d.ts +5 -0
- package/.telemetry-bundle/dist/reader.js +46 -0
- package/.telemetry-bundle/dist/stable-json.d.ts +5 -0
- package/.telemetry-bundle/dist/stable-json.js +24 -0
- package/.telemetry-bundle/dist/store.d.ts +10 -0
- package/.telemetry-bundle/dist/store.js +52 -0
- package/.telemetry-bundle/dist/trust-scoring.d.ts +20 -0
- package/.telemetry-bundle/dist/trust-scoring.js +58 -0
- package/.telemetry-bundle/package.json +8 -0
- package/README.md +74 -25
- package/dist/commands/remediate-export.js +1 -1
- package/dist/commands/replay.d.ts.map +1 -1
- package/dist/commands/replay.js +36 -0
- package/dist/commands/replay.js.map +1 -1
- package/dist/commands/verify-output.d.ts.map +1 -1
- package/dist/commands/verify-output.js +66 -4
- package/dist/commands/verify-output.js.map +1 -1
- package/dist/commands/verify.d.ts +22 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +446 -34
- package/dist/commands/verify.js.map +1 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +4 -0
- package/dist/daemon/server.js.map +1 -1
- package/dist/governance/intent/drift-detector.d.ts +100 -0
- package/dist/governance/intent/drift-detector.d.ts.map +1 -0
- package/dist/governance/intent/drift-detector.js +275 -0
- package/dist/governance/intent/drift-detector.js.map +1 -0
- package/dist/governance/intent/glob-match.d.ts +43 -0
- package/dist/governance/intent/glob-match.d.ts.map +1 -0
- package/dist/governance/intent/glob-match.js +108 -0
- package/dist/governance/intent/glob-match.js.map +1 -0
- package/dist/governance/intent/import-graph.d.ts +56 -0
- package/dist/governance/intent/import-graph.d.ts.map +1 -0
- package/dist/governance/intent/import-graph.js +133 -0
- package/dist/governance/intent/import-graph.js.map +1 -0
- package/dist/governance/intent/index.d.ts +23 -0
- package/dist/governance/intent/index.d.ts.map +1 -0
- package/dist/governance/intent/index.js +48 -0
- package/dist/governance/intent/index.js.map +1 -0
- package/dist/governance/intent/intelligence-boundaries.d.ts +69 -0
- package/dist/governance/intent/intelligence-boundaries.d.ts.map +1 -0
- package/dist/governance/intent/intelligence-boundaries.js +163 -0
- package/dist/governance/intent/intelligence-boundaries.js.map +1 -0
- package/dist/governance/intent/intent-contract.d.ts +76 -0
- package/dist/governance/intent/intent-contract.d.ts.map +1 -0
- package/dist/governance/intent/intent-contract.js +397 -0
- package/dist/governance/intent/intent-contract.js.map +1 -0
- package/dist/governance/intent/intent-graph.d.ts +135 -0
- package/dist/governance/intent/intent-graph.d.ts.map +1 -0
- package/dist/governance/intent/intent-graph.js +67 -0
- package/dist/governance/intent/intent-graph.js.map +1 -0
- package/dist/governance/pipeline/computation-trace.d.ts +52 -0
- package/dist/governance/pipeline/computation-trace.d.ts.map +1 -0
- package/dist/governance/pipeline/computation-trace.js +79 -0
- package/dist/governance/pipeline/computation-trace.js.map +1 -0
- package/dist/governance/pipeline/envelope-assembly.d.ts +132 -0
- package/dist/governance/pipeline/envelope-assembly.d.ts.map +1 -0
- package/dist/governance/pipeline/envelope-assembly.js +140 -0
- package/dist/governance/pipeline/envelope-assembly.js.map +1 -0
- package/dist/governance/pipeline/fingerprint.d.ts +34 -0
- package/dist/governance/pipeline/fingerprint.d.ts.map +1 -0
- package/dist/governance/pipeline/fingerprint.js +78 -0
- package/dist/governance/pipeline/fingerprint.js.map +1 -0
- package/dist/governance/pipeline/helpers.d.ts +74 -0
- package/dist/governance/pipeline/helpers.d.ts.map +1 -0
- package/dist/governance/pipeline/helpers.js +112 -0
- package/dist/governance/pipeline/helpers.js.map +1 -0
- package/dist/governance/pipeline/index.d.ts +27 -0
- package/dist/governance/pipeline/index.d.ts.map +1 -0
- package/dist/governance/pipeline/index.js +63 -0
- package/dist/governance/pipeline/index.js.map +1 -0
- package/dist/governance/pipeline/lineage.d.ts +26 -0
- package/dist/governance/pipeline/lineage.d.ts.map +1 -0
- package/dist/governance/pipeline/lineage.js +51 -0
- package/dist/governance/pipeline/lineage.js.map +1 -0
- package/dist/governance/pipeline/orchestration/advisory-mode-contract.d.ts +15 -0
- package/dist/governance/pipeline/orchestration/advisory-mode-contract.d.ts.map +1 -0
- package/dist/governance/pipeline/orchestration/advisory-mode-contract.js +44 -0
- package/dist/governance/pipeline/orchestration/advisory-mode-contract.js.map +1 -0
- package/dist/governance/pipeline/orchestration/advisory-mode.d.ts +102 -0
- package/dist/governance/pipeline/orchestration/advisory-mode.d.ts.map +1 -0
- package/dist/governance/pipeline/orchestration/advisory-mode.js +170 -0
- package/dist/governance/pipeline/orchestration/advisory-mode.js.map +1 -0
- package/dist/governance/pipeline/orchestration/evidence-lifecycle.d.ts +133 -0
- package/dist/governance/pipeline/orchestration/evidence-lifecycle.d.ts.map +1 -0
- package/dist/governance/pipeline/orchestration/evidence-lifecycle.js +125 -0
- package/dist/governance/pipeline/orchestration/evidence-lifecycle.js.map +1 -0
- package/dist/governance/pipeline/orchestration/index.d.ts +16 -0
- package/dist/governance/pipeline/orchestration/index.d.ts.map +1 -0
- package/dist/governance/pipeline/orchestration/index.js +30 -0
- package/dist/governance/pipeline/orchestration/index.js.map +1 -0
- package/dist/governance/pipeline/orchestration/intent-drift-orchestration.d.ts +65 -0
- package/dist/governance/pipeline/orchestration/intent-drift-orchestration.d.ts.map +1 -0
- package/dist/governance/pipeline/orchestration/intent-drift-orchestration.js +102 -0
- package/dist/governance/pipeline/orchestration/intent-drift-orchestration.js.map +1 -0
- package/dist/governance/pipeline/orchestration/plan-structural-analysis.d.ts +41 -0
- package/dist/governance/pipeline/orchestration/plan-structural-analysis.d.ts.map +1 -0
- package/dist/governance/pipeline/orchestration/plan-structural-analysis.js +74 -0
- package/dist/governance/pipeline/orchestration/plan-structural-analysis.js.map +1 -0
- package/dist/governance/pipeline/orchestration/policy-evaluation-summaries.d.ts +165 -0
- package/dist/governance/pipeline/orchestration/policy-evaluation-summaries.d.ts.map +1 -0
- package/dist/governance/pipeline/orchestration/policy-evaluation-summaries.js +160 -0
- package/dist/governance/pipeline/orchestration/policy-evaluation-summaries.js.map +1 -0
- package/dist/governance/pipeline/orchestration/scope-guard-orchestration.d.ts +152 -0
- package/dist/governance/pipeline/orchestration/scope-guard-orchestration.d.ts.map +1 -0
- package/dist/governance/pipeline/orchestration/scope-guard-orchestration.js +188 -0
- package/dist/governance/pipeline/orchestration/scope-guard-orchestration.js.map +1 -0
- package/dist/governance/pipeline/runtime.d.ts +70 -0
- package/dist/governance/pipeline/runtime.d.ts.map +1 -0
- package/dist/governance/pipeline/runtime.js +223 -0
- package/dist/governance/pipeline/runtime.js.map +1 -0
- package/dist/governance/pipeline/shared-types.d.ts +7 -0
- package/dist/governance/pipeline/shared-types.d.ts.map +1 -0
- package/dist/governance/pipeline/shared-types.js +7 -0
- package/dist/governance/pipeline/shared-types.js.map +1 -0
- package/dist/governance/pipeline/stages/compiled-policy-stage.d.ts +28 -0
- package/dist/governance/pipeline/stages/compiled-policy-stage.d.ts.map +1 -0
- package/dist/governance/pipeline/stages/compiled-policy-stage.js +53 -0
- package/dist/governance/pipeline/stages/compiled-policy-stage.js.map +1 -0
- package/dist/governance/pipeline/stages/diff-normalization-stage.d.ts +63 -0
- package/dist/governance/pipeline/stages/diff-normalization-stage.d.ts.map +1 -0
- package/dist/governance/pipeline/stages/diff-normalization-stage.js +140 -0
- package/dist/governance/pipeline/stages/diff-normalization-stage.js.map +1 -0
- package/dist/governance/pipeline/stages/governance-synthesis-stage.d.ts +53 -0
- package/dist/governance/pipeline/stages/governance-synthesis-stage.d.ts.map +1 -0
- package/dist/governance/pipeline/stages/governance-synthesis-stage.js +129 -0
- package/dist/governance/pipeline/stages/governance-synthesis-stage.js.map +1 -0
- package/dist/governance/pipeline/stages/index.d.ts +29 -0
- package/dist/governance/pipeline/stages/index.d.ts.map +1 -0
- package/dist/governance/pipeline/stages/index.js +40 -0
- package/dist/governance/pipeline/stages/index.js.map +1 -0
- package/dist/governance/pipeline/stages/policy-lock-stage.d.ts +31 -0
- package/dist/governance/pipeline/stages/policy-lock-stage.d.ts.map +1 -0
- package/dist/governance/pipeline/stages/policy-lock-stage.js +71 -0
- package/dist/governance/pipeline/stages/policy-lock-stage.js.map +1 -0
- package/dist/governance/pipeline/stages/runtime-guard-stage.d.ts +29 -0
- package/dist/governance/pipeline/stages/runtime-guard-stage.d.ts.map +1 -0
- package/dist/governance/pipeline/stages/runtime-guard-stage.js +65 -0
- package/dist/governance/pipeline/stages/runtime-guard-stage.js.map +1 -0
- package/dist/governance/pipeline/stages/structural-analysis-stage.d.ts +24 -0
- package/dist/governance/pipeline/stages/structural-analysis-stage.d.ts.map +1 -0
- package/dist/governance/pipeline/stages/structural-analysis-stage.js +58 -0
- package/dist/governance/pipeline/stages/structural-analysis-stage.js.map +1 -0
- package/dist/governance/pipeline/summary.d.ts +14 -0
- package/dist/governance/pipeline/summary.d.ts.map +1 -0
- package/dist/governance/pipeline/summary.js +50 -0
- package/dist/governance/pipeline/summary.js.map +1 -0
- package/dist/governance/pipeline/types.d.ts +69 -0
- package/dist/governance/pipeline/types.d.ts.map +1 -0
- package/dist/governance/pipeline/types.js +30 -0
- package/dist/governance/pipeline/types.js.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/active-engineering-context.d.ts +16 -0
- package/dist/utils/active-engineering-context.d.ts.map +1 -1
- package/dist/utils/active-engineering-context.js +302 -0
- package/dist/utils/active-engineering-context.js.map +1 -1
- package/dist/utils/import-edge-classifier.d.ts +76 -0
- package/dist/utils/import-edge-classifier.d.ts.map +1 -0
- package/dist/utils/import-edge-classifier.js +308 -0
- package/dist/utils/import-edge-classifier.js.map +1 -0
- package/dist/utils/import-edge-extractor.d.ts +52 -0
- package/dist/utils/import-edge-extractor.d.ts.map +1 -0
- package/dist/utils/import-edge-extractor.js +223 -0
- package/dist/utils/import-edge-extractor.js.map +1 -0
- package/dist/utils/import-edge-governance.d.ts +37 -0
- package/dist/utils/import-edge-governance.d.ts.map +1 -0
- package/dist/utils/import-edge-governance.js +56 -0
- package/dist/utils/import-edge-governance.js.map +1 -0
- package/dist/utils/path-boundary-classifier.d.ts +42 -0
- package/dist/utils/path-boundary-classifier.d.ts.map +1 -0
- package/dist/utils/path-boundary-classifier.js +143 -0
- package/dist/utils/path-boundary-classifier.js.map +1 -0
- package/dist/utils/replay-html-report.d.ts +29 -0
- package/dist/utils/replay-html-report.d.ts.map +1 -0
- package/dist/utils/replay-html-report.js +309 -0
- package/dist/utils/replay-html-report.js.map +1 -0
- package/package.json +6 -5
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Architectural Drift Detector — deterministic, bounded, explainable.
|
|
4
|
+
*
|
|
5
|
+
* Given an intent graph (declared architecture) and a diff (proposed change),
|
|
6
|
+
* the detector answers: *did this change introduce a dependency edge that
|
|
7
|
+
* violates the declared architecture?*
|
|
8
|
+
*
|
|
9
|
+
* Algorithm (entirely deterministic):
|
|
10
|
+
* 1. Classify each diff-file into a layer using `firstMatchingGlob` over the
|
|
11
|
+
* contract's `layers[].glob`. First match wins. Files with no matching
|
|
12
|
+
* layer are "unclassified" and surface as soft findings (not violations).
|
|
13
|
+
* 2. Extract import edges from added lines via `extractImportEdgesFromDiff`.
|
|
14
|
+
* 3. For each edge, resolve the *target layer*:
|
|
15
|
+
* a. Relative specifiers (`./`, `../`) → resolve to a project-relative
|
|
16
|
+
* path, then classify by glob.
|
|
17
|
+
* b. Workspace-package specifiers (`@scope/name`) → mapped to the
|
|
18
|
+
* package's layer via a module entry, when available.
|
|
19
|
+
* c. Bare specifiers (`react`, `lodash`) → marked as `external`.
|
|
20
|
+
* External imports are not subject to layer rules in Phase 1.
|
|
21
|
+
* 4. For each (fromLayer, toLayer) pair where both are known:
|
|
22
|
+
* - If the pair appears in `forbiddenEdges` → produce a BLOCK violation.
|
|
23
|
+
* - If `allowedEdges` is non-empty and the pair is not in it →
|
|
24
|
+
* produce a WARN violation (`undeclared_edge`).
|
|
25
|
+
*
|
|
26
|
+
* Determinism: same diff + same contract = same `DriftReport` byte-for-byte.
|
|
27
|
+
* Output keys are emitted in stable order; arrays are sorted by `fromFile,line,specifier`.
|
|
28
|
+
*
|
|
29
|
+
* Intelligence classification: DETERMINISTIC.
|
|
30
|
+
*/
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.runDriftDetection = runDriftDetection;
|
|
33
|
+
exports.intentGraphIsEnforceable = intentGraphIsEnforceable;
|
|
34
|
+
const path_1 = require("path");
|
|
35
|
+
const import_graph_1 = require("./import-graph");
|
|
36
|
+
const glob_match_1 = require("./glob-match");
|
|
37
|
+
const intent_graph_1 = require("./intent-graph");
|
|
38
|
+
// ── Public API ───────────────────────────────────────────────────────────────
|
|
39
|
+
/**
|
|
40
|
+
* Run drift detection. Returns a stable, typed report.
|
|
41
|
+
*
|
|
42
|
+
* Behaviour edge-cases:
|
|
43
|
+
* - Empty graph → empty report, `driftDetected: false`. Zero cost.
|
|
44
|
+
* - Graph has layers but no edges → classification runs, no violations emitted.
|
|
45
|
+
* Useful for "observe before enforce" rollouts.
|
|
46
|
+
* - File-of-file with no matching layer → file surfaces in `unclassifiedFiles`,
|
|
47
|
+
* but its imports are skipped (we cannot evaluate a rule on an unknown layer).
|
|
48
|
+
*/
|
|
49
|
+
function runDriftDetection(input) {
|
|
50
|
+
const { graph, diffFiles } = input;
|
|
51
|
+
const enforce = input.enforce ?? false;
|
|
52
|
+
if ((0, intent_graph_1.isEmptyIntentGraph)(graph)) {
|
|
53
|
+
return emptyReport(graph.fingerprint);
|
|
54
|
+
}
|
|
55
|
+
// 1. Classify diff files.
|
|
56
|
+
const classifiedFiles = [];
|
|
57
|
+
const fileLayerMap = new Map();
|
|
58
|
+
const unclassified = [];
|
|
59
|
+
for (const f of diffFiles) {
|
|
60
|
+
const classification = classifyFile(f.path, graph);
|
|
61
|
+
classifiedFiles.push(classification);
|
|
62
|
+
if (classification.layer) {
|
|
63
|
+
fileLayerMap.set(f.path, classification.layer);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
unclassified.push(f.path);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// 2. Extract imports.
|
|
70
|
+
const allEdges = (0, import_graph_1.extractImportEdgesFromDiff)(diffFiles);
|
|
71
|
+
const byFile = (0, import_graph_1.groupImportEdgesByFile)(allEdges);
|
|
72
|
+
// 3. Evaluate edges.
|
|
73
|
+
const violations = [];
|
|
74
|
+
const external = [];
|
|
75
|
+
const layersTouched = new Set();
|
|
76
|
+
const forbiddenEdgesViolated = new Set();
|
|
77
|
+
let importsAnalyzed = 0;
|
|
78
|
+
for (const [file, edges] of byFile) {
|
|
79
|
+
const fromLayer = fileLayerMap.get(file);
|
|
80
|
+
if (!fromLayer) {
|
|
81
|
+
// We already recorded the file as unclassified; nothing to evaluate.
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
layersTouched.add(fromLayer);
|
|
85
|
+
for (const edge of edges) {
|
|
86
|
+
importsAnalyzed += 1;
|
|
87
|
+
const resolution = resolveImportTarget(edge, graph, file);
|
|
88
|
+
if (resolution.kind === 'external') {
|
|
89
|
+
external.push({ file, specifier: edge.specifier, line: edge.line });
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (resolution.kind === 'unresolved') {
|
|
93
|
+
// Internal-looking specifier we could not pin to a layer. Skip silently
|
|
94
|
+
// in Phase 1 — surface upgrades come in Phase 2 (semantic diff).
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const toLayer = resolution.layer;
|
|
98
|
+
layersTouched.add(toLayer);
|
|
99
|
+
// Forbidden edge check
|
|
100
|
+
const forbidden = graph.forbiddenEdges.find((e) => e.from === fromLayer && e.to === toLayer);
|
|
101
|
+
if (forbidden) {
|
|
102
|
+
const rule = `forbidden: ${fromLayer} → ${toLayer}`;
|
|
103
|
+
forbiddenEdgesViolated.add(rule);
|
|
104
|
+
violations.push({
|
|
105
|
+
kind: 'forbidden_edge',
|
|
106
|
+
severity: enforce ? 'block' : 'warn',
|
|
107
|
+
file,
|
|
108
|
+
line: edge.line,
|
|
109
|
+
fromLayer,
|
|
110
|
+
toLayer,
|
|
111
|
+
specifier: edge.specifier,
|
|
112
|
+
reason: forbidden.reason ??
|
|
113
|
+
`Layer "${fromLayer}" must not import from layer "${toLayer}".`,
|
|
114
|
+
evidence: {
|
|
115
|
+
rawStatement: edge.rawStatement,
|
|
116
|
+
contractRule: rule,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
// Undeclared edge check (only when allowedEdges is non-empty)
|
|
122
|
+
if (graph.allowedEdges.length > 0) {
|
|
123
|
+
const allowed = graph.allowedEdges.some((e) => e.from === fromLayer && e.to === toLayer);
|
|
124
|
+
if (!allowed && fromLayer !== toLayer) {
|
|
125
|
+
violations.push({
|
|
126
|
+
kind: 'undeclared_edge',
|
|
127
|
+
severity: 'warn',
|
|
128
|
+
file,
|
|
129
|
+
line: edge.line,
|
|
130
|
+
fromLayer,
|
|
131
|
+
toLayer,
|
|
132
|
+
specifier: edge.specifier,
|
|
133
|
+
reason: `Edge ${fromLayer} → ${toLayer} is not in the contract's allowedEdges. ` +
|
|
134
|
+
`Either add it to the contract or refactor the dependency.`,
|
|
135
|
+
evidence: {
|
|
136
|
+
rawStatement: edge.rawStatement,
|
|
137
|
+
contractRule: `not-in-allowed: ${fromLayer} → ${toLayer}`,
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Sort for determinism
|
|
145
|
+
violations.sort(sortByFileLineSpecifier);
|
|
146
|
+
const blockCount = violations.filter((v) => v.severity === 'block').length;
|
|
147
|
+
const warnCount = violations.filter((v) => v.severity === 'warn').length;
|
|
148
|
+
return {
|
|
149
|
+
schemaVersion: 1,
|
|
150
|
+
driftDetected: violations.length > 0,
|
|
151
|
+
violations,
|
|
152
|
+
classifiedFiles,
|
|
153
|
+
unclassifiedFiles: unclassified.slice().sort(),
|
|
154
|
+
externalImports: external,
|
|
155
|
+
summary: {
|
|
156
|
+
filesAnalyzed: diffFiles.length,
|
|
157
|
+
importsAnalyzed,
|
|
158
|
+
violationCount: violations.length,
|
|
159
|
+
blockCount,
|
|
160
|
+
warnCount,
|
|
161
|
+
layersTouched: [...layersTouched].sort(),
|
|
162
|
+
forbiddenEdgesViolated: [...forbiddenEdgesViolated].sort(),
|
|
163
|
+
},
|
|
164
|
+
contractFingerprint: graph.fingerprint,
|
|
165
|
+
intelligenceClassification: 'deterministic',
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
// Marker for use when enforcement is disabled and we want to short-circuit
|
|
169
|
+
function intentGraphIsEnforceable(graph) {
|
|
170
|
+
return (0, intent_graph_1.intentGraphHasEnforcement)(graph);
|
|
171
|
+
}
|
|
172
|
+
// ── Internal — classification ────────────────────────────────────────────────
|
|
173
|
+
function classifyFile(path, graph) {
|
|
174
|
+
for (const layer of graph.layers) {
|
|
175
|
+
const matched = (0, glob_match_1.firstMatchingGlob)(layer.glob, path);
|
|
176
|
+
if (matched) {
|
|
177
|
+
return { path, layer: layer.id, matchedGlob: matched };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return { path, layer: null, matchedGlob: null };
|
|
181
|
+
}
|
|
182
|
+
function resolveImportTarget(edge, graph, sourceFile) {
|
|
183
|
+
const spec = edge.specifier;
|
|
184
|
+
// Relative specifiers: resolve against the source file's directory.
|
|
185
|
+
if (spec.startsWith('./') || spec.startsWith('../') || spec.startsWith('/')) {
|
|
186
|
+
const resolved = resolveRelativeSpecifier(sourceFile, spec);
|
|
187
|
+
if (!resolved)
|
|
188
|
+
return { kind: 'unresolved' };
|
|
189
|
+
const layer = classifyPathToLayer(resolved, graph.layers);
|
|
190
|
+
if (layer)
|
|
191
|
+
return { kind: 'classified', layer };
|
|
192
|
+
return { kind: 'unresolved' };
|
|
193
|
+
}
|
|
194
|
+
// Bare specifier — external dependency, not a layer.
|
|
195
|
+
// Includes `@scope/pkg` since we don't have a workspace-package → layer
|
|
196
|
+
// map in Phase 1. Workspace-package layer mapping is a Phase 2 enhancement.
|
|
197
|
+
return { kind: 'external' };
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Resolve a relative specifier (e.g. `../service/auth`) against a source file
|
|
201
|
+
* (e.g. `src/commands/login.ts`) to a project-relative path (e.g.
|
|
202
|
+
* `src/service/auth`). Extension is not appended — the layer globs are expected
|
|
203
|
+
* to be flexible enough to match either form, but we additionally try common
|
|
204
|
+
* extensions for a best-effort hit.
|
|
205
|
+
*/
|
|
206
|
+
function resolveRelativeSpecifier(sourceFile, specifier) {
|
|
207
|
+
try {
|
|
208
|
+
const sourceDir = (0, path_1.dirname)((0, glob_match_1.normalizePathForGlob)(sourceFile));
|
|
209
|
+
const joined = path_1.posix.normalize(path_1.posix.join(sourceDir, specifier));
|
|
210
|
+
return joined;
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Classify a resolved path into a layer. Tries the bare path first, then
|
|
218
|
+
* common extensions, then path-with-/index appended. This handles the most
|
|
219
|
+
* common ESM/CJS resolution shapes without doing real filesystem lookups
|
|
220
|
+
* (which would be non-deterministic and slow).
|
|
221
|
+
*/
|
|
222
|
+
function classifyPathToLayer(resolvedPath, layers) {
|
|
223
|
+
const candidates = [
|
|
224
|
+
resolvedPath,
|
|
225
|
+
`${resolvedPath}.ts`,
|
|
226
|
+
`${resolvedPath}.tsx`,
|
|
227
|
+
`${resolvedPath}.js`,
|
|
228
|
+
`${resolvedPath}.jsx`,
|
|
229
|
+
`${resolvedPath}.py`,
|
|
230
|
+
`${resolvedPath}/index.ts`,
|
|
231
|
+
`${resolvedPath}/index.js`,
|
|
232
|
+
`${resolvedPath}/__init__.py`,
|
|
233
|
+
];
|
|
234
|
+
for (const layer of layers) {
|
|
235
|
+
for (const candidate of candidates) {
|
|
236
|
+
if ((0, glob_match_1.firstMatchingGlob)(layer.glob, candidate)) {
|
|
237
|
+
return layer.id;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
// ── Internal — sorting ───────────────────────────────────────────────────────
|
|
244
|
+
function sortByFileLineSpecifier(a, b) {
|
|
245
|
+
if (a.file !== b.file)
|
|
246
|
+
return a.file < b.file ? -1 : 1;
|
|
247
|
+
if (a.line !== b.line)
|
|
248
|
+
return a.line - b.line;
|
|
249
|
+
if (a.specifier !== b.specifier)
|
|
250
|
+
return a.specifier < b.specifier ? -1 : 1;
|
|
251
|
+
return 0;
|
|
252
|
+
}
|
|
253
|
+
// ── Empty result ─────────────────────────────────────────────────────────────
|
|
254
|
+
function emptyReport(fingerprint) {
|
|
255
|
+
return {
|
|
256
|
+
schemaVersion: 1,
|
|
257
|
+
driftDetected: false,
|
|
258
|
+
violations: [],
|
|
259
|
+
classifiedFiles: [],
|
|
260
|
+
unclassifiedFiles: [],
|
|
261
|
+
externalImports: [],
|
|
262
|
+
summary: {
|
|
263
|
+
filesAnalyzed: 0,
|
|
264
|
+
importsAnalyzed: 0,
|
|
265
|
+
violationCount: 0,
|
|
266
|
+
blockCount: 0,
|
|
267
|
+
warnCount: 0,
|
|
268
|
+
layersTouched: [],
|
|
269
|
+
forbiddenEdgesViolated: [],
|
|
270
|
+
},
|
|
271
|
+
contractFingerprint: fingerprint,
|
|
272
|
+
intelligenceClassification: 'deterministic',
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=drift-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift-detector.js","sourceRoot":"","sources":["../../../src/governance/intent/drift-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded deterministic glob matcher for intent governance.
|
|
3
|
+
*
|
|
4
|
+
* Why a local implementation:
|
|
5
|
+
* - Zero filesystem access. Pattern-vs-string only.
|
|
6
|
+
* - Replay determinism: identical (pattern, path) → identical boolean, forever.
|
|
7
|
+
* - No dependency on `glob`, `minimatch`, or `micromatch` (which have version drift,
|
|
8
|
+
* locale-sensitive behaviour, and historical bugs around `**` semantics).
|
|
9
|
+
*
|
|
10
|
+
* Supported syntax (intentionally minimal):
|
|
11
|
+
* `**` — match any number of path segments (including zero)
|
|
12
|
+
* `*` — match any sequence of chars except `/`
|
|
13
|
+
* `?` — match exactly one char except `/`
|
|
14
|
+
* Literal characters match themselves. No brace expansion, no character classes,
|
|
15
|
+
* no negation (negation is expressed at the contract layer, not the glob layer).
|
|
16
|
+
*
|
|
17
|
+
* Paths are normalised to forward slashes before matching. Leading `./` is stripped.
|
|
18
|
+
*
|
|
19
|
+
* Intelligence classification: DETERMINISTIC.
|
|
20
|
+
*/
|
|
21
|
+
/** Normalise a file path for matching: forward slashes, no leading `./`. */
|
|
22
|
+
export declare function normalizePathForGlob(path: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Compile a glob into a deterministic RegExp.
|
|
25
|
+
* The regex is anchored: it matches the full path, not a substring.
|
|
26
|
+
*/
|
|
27
|
+
export declare function compileGlob(pattern: string): RegExp;
|
|
28
|
+
/**
|
|
29
|
+
* Test whether `path` matches `pattern`. Both are normalised before comparison.
|
|
30
|
+
* Pure function — same inputs always produce the same output.
|
|
31
|
+
*/
|
|
32
|
+
export declare function matchesGlob(pattern: string, path: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Return true if `path` matches any pattern in `patterns`.
|
|
35
|
+
* Useful for layer membership checks where multiple globs are OR'd together.
|
|
36
|
+
*/
|
|
37
|
+
export declare function matchesAnyGlob(patterns: ReadonlyArray<string>, path: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Return the first pattern in `patterns` that matches `path`, or `null` if none match.
|
|
40
|
+
* Order matters — caller is responsible for arranging patterns in priority order.
|
|
41
|
+
*/
|
|
42
|
+
export declare function firstMatchingGlob(patterns: ReadonlyArray<string>, path: string): string | null;
|
|
43
|
+
//# sourceMappingURL=glob-match.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob-match.d.ts","sourceRoot":"","sources":["../../../src/governance/intent/glob-match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAwCnD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAElE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAMrF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,EAC/B,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAMf"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Bounded deterministic glob matcher for intent governance.
|
|
4
|
+
*
|
|
5
|
+
* Why a local implementation:
|
|
6
|
+
* - Zero filesystem access. Pattern-vs-string only.
|
|
7
|
+
* - Replay determinism: identical (pattern, path) → identical boolean, forever.
|
|
8
|
+
* - No dependency on `glob`, `minimatch`, or `micromatch` (which have version drift,
|
|
9
|
+
* locale-sensitive behaviour, and historical bugs around `**` semantics).
|
|
10
|
+
*
|
|
11
|
+
* Supported syntax (intentionally minimal):
|
|
12
|
+
* `**` — match any number of path segments (including zero)
|
|
13
|
+
* `*` — match any sequence of chars except `/`
|
|
14
|
+
* `?` — match exactly one char except `/`
|
|
15
|
+
* Literal characters match themselves. No brace expansion, no character classes,
|
|
16
|
+
* no negation (negation is expressed at the contract layer, not the glob layer).
|
|
17
|
+
*
|
|
18
|
+
* Paths are normalised to forward slashes before matching. Leading `./` is stripped.
|
|
19
|
+
*
|
|
20
|
+
* Intelligence classification: DETERMINISTIC.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.normalizePathForGlob = normalizePathForGlob;
|
|
24
|
+
exports.compileGlob = compileGlob;
|
|
25
|
+
exports.matchesGlob = matchesGlob;
|
|
26
|
+
exports.matchesAnyGlob = matchesAnyGlob;
|
|
27
|
+
exports.firstMatchingGlob = firstMatchingGlob;
|
|
28
|
+
const ESCAPE_RE = /[.+^${}()|[\]\\]/g;
|
|
29
|
+
/** Normalise a file path for matching: forward slashes, no leading `./`. */
|
|
30
|
+
function normalizePathForGlob(path) {
|
|
31
|
+
let p = path.replace(/\\/g, '/');
|
|
32
|
+
if (p.startsWith('./'))
|
|
33
|
+
p = p.slice(2);
|
|
34
|
+
return p;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Compile a glob into a deterministic RegExp.
|
|
38
|
+
* The regex is anchored: it matches the full path, not a substring.
|
|
39
|
+
*/
|
|
40
|
+
function compileGlob(pattern) {
|
|
41
|
+
const normalized = normalizePathForGlob(pattern);
|
|
42
|
+
let i = 0;
|
|
43
|
+
let out = '^';
|
|
44
|
+
while (i < normalized.length) {
|
|
45
|
+
const c = normalized[i];
|
|
46
|
+
// `**` — any number of segments (zero or more)
|
|
47
|
+
if (c === '*' && normalized[i + 1] === '*') {
|
|
48
|
+
// `**/` or `/**` collapses to "anything (including empty)" without trailing slash artifacts
|
|
49
|
+
if (normalized[i + 2] === '/') {
|
|
50
|
+
out += '(?:.*/)?';
|
|
51
|
+
i += 3;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
out += '.*';
|
|
55
|
+
i += 2;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// `*` — any chars except `/`
|
|
59
|
+
if (c === '*') {
|
|
60
|
+
out += '[^/]*';
|
|
61
|
+
i += 1;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
// `?` — one char except `/`
|
|
65
|
+
if (c === '?') {
|
|
66
|
+
out += '[^/]';
|
|
67
|
+
i += 1;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
// literal
|
|
71
|
+
out += c.replace(ESCAPE_RE, '\\$&');
|
|
72
|
+
i += 1;
|
|
73
|
+
}
|
|
74
|
+
out += '$';
|
|
75
|
+
return new RegExp(out);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Test whether `path` matches `pattern`. Both are normalised before comparison.
|
|
79
|
+
* Pure function — same inputs always produce the same output.
|
|
80
|
+
*/
|
|
81
|
+
function matchesGlob(pattern, path) {
|
|
82
|
+
return compileGlob(pattern).test(normalizePathForGlob(path));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Return true if `path` matches any pattern in `patterns`.
|
|
86
|
+
* Useful for layer membership checks where multiple globs are OR'd together.
|
|
87
|
+
*/
|
|
88
|
+
function matchesAnyGlob(patterns, path) {
|
|
89
|
+
const normalised = normalizePathForGlob(path);
|
|
90
|
+
for (const pattern of patterns) {
|
|
91
|
+
if (compileGlob(pattern).test(normalised))
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Return the first pattern in `patterns` that matches `path`, or `null` if none match.
|
|
98
|
+
* Order matters — caller is responsible for arranging patterns in priority order.
|
|
99
|
+
*/
|
|
100
|
+
function firstMatchingGlob(patterns, path) {
|
|
101
|
+
const normalised = normalizePathForGlob(path);
|
|
102
|
+
for (const pattern of patterns) {
|
|
103
|
+
if (compileGlob(pattern).test(normalised))
|
|
104
|
+
return pattern;
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=glob-match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob-match.js","sourceRoot":"","sources":["../../../src/governance/intent/glob-match.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;;AAKH,oDAIC;AAMD,kCAwCC;AAMD,kCAEC;AAMD,wCAMC;AAMD,8CASC;AAxFD,MAAM,SAAS,GAAG,mBAAmB,CAAC;AAEtC,4EAA4E;AAC5E,SAAgB,oBAAoB,CAAC,IAAY;IAC/C,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACjC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CAAC,OAAe;IACzC,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,IAAI,GAAG,GAAG,GAAG,CAAC;IACd,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAExB,+CAA+C;QAC/C,IAAI,CAAC,KAAK,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC3C,4FAA4F;YAC5F,IAAI,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC9B,GAAG,IAAI,UAAU,CAAC;gBAClB,CAAC,IAAI,CAAC,CAAC;gBACP,SAAS;YACX,CAAC;YACD,GAAG,IAAI,IAAI,CAAC;YACZ,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,6BAA6B;QAC7B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,GAAG,IAAI,OAAO,CAAC;YACf,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,4BAA4B;QAC5B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,GAAG,IAAI,MAAM,CAAC;YACd,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,UAAU;QACV,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACpC,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IACD,GAAG,IAAI,GAAG,CAAC;IACX,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CAAC,OAAe,EAAE,IAAY;IACvD,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,SAAgB,cAAc,CAAC,QAA+B,EAAE,IAAY;IAC1E,MAAM,UAAU,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC9C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;IACzD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,SAAgB,iBAAiB,CAC/B,QAA+B,EAC/B,IAAY;IAEZ,MAAM,UAAU,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC9C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE,OAAO,OAAO,CAAC;IAC5D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import Graph Extraction — bounded, deterministic, diff-scoped.
|
|
3
|
+
*
|
|
4
|
+
* Extracts import edges (file → imported specifier) from the **added** lines of
|
|
5
|
+
* a parsed diff. This is intentionally narrow:
|
|
6
|
+
*
|
|
7
|
+
* - **Bounded scope**: only files in the diff, only added lines.
|
|
8
|
+
* We never re-parse the entire project. This keeps drift detection fast
|
|
9
|
+
* and proportional to the size of the change, not the size of the codebase.
|
|
10
|
+
*
|
|
11
|
+
* - **Regex-based parsing**: not AST. For governance signals on imports
|
|
12
|
+
* specifically, ECMAScript `import`/`require` statements are unambiguous
|
|
13
|
+
* enough that regex matches what an AST would catch. False positives in
|
|
14
|
+
* pathological edge cases (e.g. import strings inside template literals)
|
|
15
|
+
* are acceptable — drift findings are advisory in Phase 1.
|
|
16
|
+
*
|
|
17
|
+
* - **TS/JS/Python first**: matchers for ESM imports, CJS requires, and
|
|
18
|
+
* Python `from X import` / `import X`. Other languages can be added as
|
|
19
|
+
* additional matcher entries.
|
|
20
|
+
*
|
|
21
|
+
* Intelligence classification: DETERMINISTIC.
|
|
22
|
+
*/
|
|
23
|
+
import type { DiffFile } from '@neurcode-ai/diff-parser';
|
|
24
|
+
/**
|
|
25
|
+
* One extracted import edge: a file imports a specifier on a specific line.
|
|
26
|
+
*
|
|
27
|
+
* `specifier` is the literal string from the source (e.g. `"./auth/login"`,
|
|
28
|
+
* `"@neurcode-ai/diff-parser"`, `"sqlalchemy.orm"`). Resolution to a layer is
|
|
29
|
+
* the next phase's job — this module produces raw, faithful edges.
|
|
30
|
+
*/
|
|
31
|
+
export interface ImportEdge {
|
|
32
|
+
/** Source file (project-relative). */
|
|
33
|
+
fromFile: string;
|
|
34
|
+
/** Raw imported specifier. */
|
|
35
|
+
specifier: string;
|
|
36
|
+
/** 1-based line number (best-effort, from the diff hunk). */
|
|
37
|
+
line: number;
|
|
38
|
+
/** Original matched text — used in drift reports as evidence. */
|
|
39
|
+
rawStatement: string;
|
|
40
|
+
/** Which matcher produced this edge. Aids debuggability. */
|
|
41
|
+
matcherId: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract all import edges from the added lines of the diff.
|
|
45
|
+
*
|
|
46
|
+
* Pure function — same `diffFiles` produces the same `ImportEdge[]` every time,
|
|
47
|
+
* with deterministic ordering (files in input order; lines in hunk order;
|
|
48
|
+
* matchers in declaration order).
|
|
49
|
+
*/
|
|
50
|
+
export declare function extractImportEdgesFromDiff(diffFiles: DiffFile[]): ImportEdge[];
|
|
51
|
+
/**
|
|
52
|
+
* Group edges by source file. Used by the drift detector to iterate
|
|
53
|
+
* file-by-file when classifying layers.
|
|
54
|
+
*/
|
|
55
|
+
export declare function groupImportEdgesByFile(edges: ImportEdge[]): Map<string, ImportEdge[]>;
|
|
56
|
+
//# sourceMappingURL=import-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-graph.d.ts","sourceRoot":"","sources":["../../../src/governance/intent/import-graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAIzD;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,YAAY,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;CACnB;AAoDD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE,CAsB9E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAWrF"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Import Graph Extraction — bounded, deterministic, diff-scoped.
|
|
4
|
+
*
|
|
5
|
+
* Extracts import edges (file → imported specifier) from the **added** lines of
|
|
6
|
+
* a parsed diff. This is intentionally narrow:
|
|
7
|
+
*
|
|
8
|
+
* - **Bounded scope**: only files in the diff, only added lines.
|
|
9
|
+
* We never re-parse the entire project. This keeps drift detection fast
|
|
10
|
+
* and proportional to the size of the change, not the size of the codebase.
|
|
11
|
+
*
|
|
12
|
+
* - **Regex-based parsing**: not AST. For governance signals on imports
|
|
13
|
+
* specifically, ECMAScript `import`/`require` statements are unambiguous
|
|
14
|
+
* enough that regex matches what an AST would catch. False positives in
|
|
15
|
+
* pathological edge cases (e.g. import strings inside template literals)
|
|
16
|
+
* are acceptable — drift findings are advisory in Phase 1.
|
|
17
|
+
*
|
|
18
|
+
* - **TS/JS/Python first**: matchers for ESM imports, CJS requires, and
|
|
19
|
+
* Python `from X import` / `import X`. Other languages can be added as
|
|
20
|
+
* additional matcher entries.
|
|
21
|
+
*
|
|
22
|
+
* Intelligence classification: DETERMINISTIC.
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.extractImportEdgesFromDiff = extractImportEdgesFromDiff;
|
|
26
|
+
exports.groupImportEdgesByFile = groupImportEdgesByFile;
|
|
27
|
+
/**
|
|
28
|
+
* The matcher set. Order is irrelevant — every matcher is run against every
|
|
29
|
+
* added line. A single line could in theory match multiple matchers; in
|
|
30
|
+
* practice the regexes are disjoint.
|
|
31
|
+
*/
|
|
32
|
+
const IMPORT_MATCHERS = [
|
|
33
|
+
// ESM: `import X from "..."`, `import "..."`, `import { X } from "..."`
|
|
34
|
+
{
|
|
35
|
+
id: 'esm-import-from',
|
|
36
|
+
pattern: /\bimport\s+[^'"]*?from\s+['"]([^'"]+)['"]/,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'esm-import-side-effect',
|
|
40
|
+
pattern: /\bimport\s+['"]([^'"]+)['"]/,
|
|
41
|
+
},
|
|
42
|
+
// ESM: dynamic `import("...")`
|
|
43
|
+
{
|
|
44
|
+
id: 'esm-import-dynamic',
|
|
45
|
+
pattern: /\bimport\s*\(\s*['"]([^'"]+)['"]\s*\)/,
|
|
46
|
+
},
|
|
47
|
+
// CJS: `require("...")`
|
|
48
|
+
{
|
|
49
|
+
id: 'cjs-require',
|
|
50
|
+
pattern: /\brequire\s*\(\s*['"]([^'"]+)['"]\s*\)/,
|
|
51
|
+
},
|
|
52
|
+
// Python: `from foo.bar import baz`
|
|
53
|
+
{
|
|
54
|
+
id: 'py-from-import',
|
|
55
|
+
pattern: /^\s*from\s+([\w.]+)\s+import\s+/,
|
|
56
|
+
},
|
|
57
|
+
// Python: `import foo.bar`
|
|
58
|
+
{
|
|
59
|
+
id: 'py-import',
|
|
60
|
+
pattern: /^\s*import\s+([\w.]+)(?:\s+as\s+\w+)?\s*$/,
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
// ── Public API ───────────────────────────────────────────────────────────────
|
|
64
|
+
/**
|
|
65
|
+
* Extract all import edges from the added lines of the diff.
|
|
66
|
+
*
|
|
67
|
+
* Pure function — same `diffFiles` produces the same `ImportEdge[]` every time,
|
|
68
|
+
* with deterministic ordering (files in input order; lines in hunk order;
|
|
69
|
+
* matchers in declaration order).
|
|
70
|
+
*/
|
|
71
|
+
function extractImportEdgesFromDiff(diffFiles) {
|
|
72
|
+
const edges = [];
|
|
73
|
+
for (const file of diffFiles) {
|
|
74
|
+
if (!file.hunks)
|
|
75
|
+
continue;
|
|
76
|
+
for (const hunk of file.hunks) {
|
|
77
|
+
if (!hunk.lines)
|
|
78
|
+
continue;
|
|
79
|
+
// newStart is the line number of the first line in the new file
|
|
80
|
+
let currentLine = hunk.newStart ?? 1;
|
|
81
|
+
for (const line of hunk.lines) {
|
|
82
|
+
if (line.type === 'added') {
|
|
83
|
+
collectMatchesFromLine(file.path, line.content ?? '', currentLine, edges);
|
|
84
|
+
currentLine += 1;
|
|
85
|
+
}
|
|
86
|
+
else if (line.type === 'context') {
|
|
87
|
+
currentLine += 1;
|
|
88
|
+
}
|
|
89
|
+
// 'removed' lines do not advance newStart counter
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return edges;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Group edges by source file. Used by the drift detector to iterate
|
|
97
|
+
* file-by-file when classifying layers.
|
|
98
|
+
*/
|
|
99
|
+
function groupImportEdgesByFile(edges) {
|
|
100
|
+
const grouped = new Map();
|
|
101
|
+
for (const edge of edges) {
|
|
102
|
+
const existing = grouped.get(edge.fromFile);
|
|
103
|
+
if (existing) {
|
|
104
|
+
existing.push(edge);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
grouped.set(edge.fromFile, [edge]);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return grouped;
|
|
111
|
+
}
|
|
112
|
+
// ── Internal ─────────────────────────────────────────────────────────────────
|
|
113
|
+
function collectMatchesFromLine(fromFile, rawContent, line, out) {
|
|
114
|
+
// Diff hunks may include a leading "+" in some representations; the
|
|
115
|
+
// @neurcode-ai/diff-parser strips it but we guard defensively.
|
|
116
|
+
const content = rawContent.startsWith('+') ? rawContent.slice(1) : rawContent;
|
|
117
|
+
for (const matcher of IMPORT_MATCHERS) {
|
|
118
|
+
const match = matcher.pattern.exec(content);
|
|
119
|
+
if (!match)
|
|
120
|
+
continue;
|
|
121
|
+
const specifier = match[1];
|
|
122
|
+
if (!specifier)
|
|
123
|
+
continue;
|
|
124
|
+
out.push({
|
|
125
|
+
fromFile,
|
|
126
|
+
specifier,
|
|
127
|
+
line,
|
|
128
|
+
rawStatement: content.trim(),
|
|
129
|
+
matcherId: matcher.id,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=import-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-graph.js","sourceRoot":"","sources":["../../../src/governance/intent/import-graph.ts"],"names":[],"mappings":"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"}
|