@codeledger/cli 0.6.8 → 0.6.9
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/commands/activate.d.ts.map +1 -1
- package/dist/commands/activate.js +16 -1
- package/dist/commands/activate.js.map +1 -1
- package/dist/commands/commit-msg.d.ts +58 -0
- package/dist/commands/commit-msg.d.ts.map +1 -0
- package/dist/commands/commit-msg.js +461 -0
- package/dist/commands/commit-msg.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +14 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/intent.d.ts +3 -1
- package/dist/commands/intent.d.ts.map +1 -1
- package/dist/commands/intent.js +68 -2
- package/dist/commands/intent.js.map +1 -1
- package/dist/commands/pr-summary.d.ts +59 -0
- package/dist/commands/pr-summary.d.ts.map +1 -0
- package/dist/commands/pr-summary.js +524 -0
- package/dist/commands/pr-summary.js.map +1 -0
- package/dist/commands/session-cleanup.js +1 -0
- package/dist/commands/session-cleanup.js.map +1 -1
- package/dist/commands/session-summary.d.ts.map +1 -1
- package/dist/commands/session-summary.js +135 -3
- package/dist/commands/session-summary.js.map +1 -1
- package/dist/commands/setup-ci.d.ts.map +1 -1
- package/dist/commands/setup-ci.js +12 -0
- package/dist/commands/setup-ci.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +35 -3
- package/dist/commands/verify.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -1
- package/dist/index.js.map +1 -1
- package/dist/intent/extractor.d.ts +15 -0
- package/dist/intent/extractor.d.ts.map +1 -0
- package/dist/intent/extractor.js +149 -0
- package/dist/intent/extractor.js.map +1 -0
- package/dist/intent/fetcher.d.ts +33 -0
- package/dist/intent/fetcher.d.ts.map +1 -0
- package/dist/intent/fetcher.js +364 -0
- package/dist/intent/fetcher.js.map +1 -0
- package/dist/intent/loader.d.ts +26 -0
- package/dist/intent/loader.d.ts.map +1 -0
- package/dist/intent/loader.js +80 -0
- package/dist/intent/loader.js.map +1 -0
- package/dist/intent/types.d.ts +33 -0
- package/dist/intent/types.d.ts.map +1 -0
- package/dist/intent/types.js +9 -0
- package/dist/intent/types.js.map +1 -0
- package/dist/project-config.d.ts +38 -0
- package/dist/project-config.d.ts.map +1 -0
- package/dist/project-config.js +206 -0
- package/dist/project-config.js.map +1 -0
- package/dist/review-intelligence/detectors/architecture-graph.d.ts +18 -0
- package/dist/review-intelligence/detectors/architecture-graph.d.ts.map +1 -0
- package/dist/review-intelligence/detectors/architecture-graph.js +73 -0
- package/dist/review-intelligence/detectors/architecture-graph.js.map +1 -0
- package/dist/review-intelligence/detectors/pack-rules.d.ts +16 -0
- package/dist/review-intelligence/detectors/pack-rules.d.ts.map +1 -0
- package/dist/review-intelligence/detectors/pack-rules.js +107 -0
- package/dist/review-intelligence/detectors/pack-rules.js.map +1 -0
- package/dist/review-intelligence/fixes/index.d.ts +18 -0
- package/dist/review-intelligence/fixes/index.d.ts.map +1 -1
- package/dist/review-intelligence/fixes/index.js +198 -9
- package/dist/review-intelligence/fixes/index.js.map +1 -1
- package/dist/review-intelligence/index.d.ts +4 -1
- package/dist/review-intelligence/index.d.ts.map +1 -1
- package/dist/review-intelligence/index.js +20 -3
- package/dist/review-intelligence/index.js.map +1 -1
- package/dist/review-intelligence/invariants.d.ts +15 -0
- package/dist/review-intelligence/invariants.d.ts.map +1 -1
- package/dist/review-intelligence/invariants.js +36 -5
- package/dist/review-intelligence/invariants.js.map +1 -1
- package/dist/review-intelligence/types.d.ts +16 -12
- package/dist/review-intelligence/types.d.ts.map +1 -1
- package/dist/review-intelligence/types.js +9 -1
- package/dist/review-intelligence/types.js.map +1 -1
- package/dist/templates/claude-md.d.ts.map +1 -1
- package/dist/templates/claude-md.js +23 -128
- package/dist/templates/claude-md.js.map +1 -1
- package/dist/templates/hooks.d.ts.map +1 -1
- package/dist/templates/hooks.js +39 -0
- package/dist/templates/hooks.js.map +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-level configuration loader for .codeledger.yml
|
|
3
|
+
*
|
|
4
|
+
* Reads optional project config from repo root (.codeledger.yml) that controls
|
|
5
|
+
* commit-msg, pr-summary, and PR review bot defaults. This is separate from
|
|
6
|
+
* the core .codeledger/config.json which handles scoring, selection, and harness.
|
|
7
|
+
*
|
|
8
|
+
* Uses a minimal YAML parser (no dependency) — supports only the flat/nested
|
|
9
|
+
* key-value structure documented in sample.codeledger.yml.
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
const DEFAULT_CONFIG = {
|
|
14
|
+
pr: {
|
|
15
|
+
base_branch: 'main',
|
|
16
|
+
comment_enabled: true,
|
|
17
|
+
sections: [
|
|
18
|
+
'summary', 'why', 'business_impact', 'key_changes',
|
|
19
|
+
'subsystems_touched', 'risk_signals', 'verify_findings',
|
|
20
|
+
'reviewer_focus', 'testing', 'stats',
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
verify: {
|
|
24
|
+
mode: 'warn',
|
|
25
|
+
severity_threshold: 'P1',
|
|
26
|
+
review_intelligence: {
|
|
27
|
+
enabled: true,
|
|
28
|
+
invariants: {
|
|
29
|
+
runtime_validation: true,
|
|
30
|
+
outbound_io: true,
|
|
31
|
+
platform_helpers: true,
|
|
32
|
+
build_runtime: true,
|
|
33
|
+
test_integrity: true,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
commit_msg: {
|
|
38
|
+
signature: false,
|
|
39
|
+
format: 'full',
|
|
40
|
+
},
|
|
41
|
+
intent: {
|
|
42
|
+
tracker_prefix: '',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
// ── Minimal YAML parser ──────────────────────────────────────────────────────
|
|
46
|
+
// Handles the subset of YAML used in .codeledger.yml: scalars, simple lists,
|
|
47
|
+
// and nested objects (2-space indent). No anchors, aliases, flow style, or
|
|
48
|
+
// multi-line strings.
|
|
49
|
+
function parseSimpleYaml(text) {
|
|
50
|
+
const result = {};
|
|
51
|
+
const lines = text.split('\n');
|
|
52
|
+
const stack = [
|
|
53
|
+
{ indent: -1, obj: result },
|
|
54
|
+
];
|
|
55
|
+
for (const rawLine of lines) {
|
|
56
|
+
// Skip comments and blank lines
|
|
57
|
+
const commentIdx = rawLine.indexOf('#');
|
|
58
|
+
const line = commentIdx >= 0 ? rawLine.slice(0, commentIdx) : rawLine;
|
|
59
|
+
if (line.trim() === '')
|
|
60
|
+
continue;
|
|
61
|
+
const indent = line.length - line.trimStart().length;
|
|
62
|
+
const trimmed = line.trim();
|
|
63
|
+
// List item: "- value"
|
|
64
|
+
if (trimmed.startsWith('- ')) {
|
|
65
|
+
const value = parseScalar(trimmed.slice(2).trim());
|
|
66
|
+
// Find the parent at this indent level — pop entries at deeper or equal indent
|
|
67
|
+
while (stack.length > 1 && (stack[stack.length - 1]?.indent ?? -1) >= indent) {
|
|
68
|
+
stack.pop();
|
|
69
|
+
}
|
|
70
|
+
let parent = stack[stack.length - 1]?.obj ?? result;
|
|
71
|
+
// If we landed on an empty object created by "key:" syntax, go one level
|
|
72
|
+
// up and convert the key from an empty object to an array.
|
|
73
|
+
if (Object.keys(parent).length === 0 && stack.length > 1) {
|
|
74
|
+
stack.pop();
|
|
75
|
+
const grandparent = stack[stack.length - 1]?.obj ?? result;
|
|
76
|
+
const gpKeys = Object.keys(grandparent);
|
|
77
|
+
const gpLastKey = gpKeys[gpKeys.length - 1];
|
|
78
|
+
if (gpLastKey !== undefined) {
|
|
79
|
+
grandparent[gpLastKey] = [value];
|
|
80
|
+
}
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
// Find the last key in the parent to attach the list item
|
|
84
|
+
const keys = Object.keys(parent);
|
|
85
|
+
const lastKey = keys[keys.length - 1];
|
|
86
|
+
if (lastKey !== undefined) {
|
|
87
|
+
if (!Array.isArray(parent[lastKey])) {
|
|
88
|
+
parent[lastKey] = [];
|
|
89
|
+
}
|
|
90
|
+
parent[lastKey].push(value);
|
|
91
|
+
}
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
// Key-value pair: "key: value" or "key:" (nested object)
|
|
95
|
+
const colonIdx = trimmed.indexOf(':');
|
|
96
|
+
if (colonIdx < 0)
|
|
97
|
+
continue;
|
|
98
|
+
const key = trimmed.slice(0, colonIdx).trim();
|
|
99
|
+
const rawValue = trimmed.slice(colonIdx + 1).trim();
|
|
100
|
+
// Pop stack to find the right parent
|
|
101
|
+
while (stack.length > 1 && (stack[stack.length - 1]?.indent ?? -1) >= indent) {
|
|
102
|
+
stack.pop();
|
|
103
|
+
}
|
|
104
|
+
const parent = stack[stack.length - 1]?.obj ?? result;
|
|
105
|
+
if (rawValue === '') {
|
|
106
|
+
// Nested object — key with no value
|
|
107
|
+
const nested = {};
|
|
108
|
+
parent[key] = nested;
|
|
109
|
+
stack.push({ indent, obj: nested });
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
parent[key] = parseScalar(rawValue);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
function parseScalar(value) {
|
|
118
|
+
if (value === 'true')
|
|
119
|
+
return true;
|
|
120
|
+
if (value === 'false')
|
|
121
|
+
return false;
|
|
122
|
+
if (value === 'null' || value === '~')
|
|
123
|
+
return '';
|
|
124
|
+
// Quoted strings
|
|
125
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
126
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
127
|
+
return value.slice(1, -1);
|
|
128
|
+
}
|
|
129
|
+
// Numbers
|
|
130
|
+
const num = Number(value);
|
|
131
|
+
if (!isNaN(num) && value !== '')
|
|
132
|
+
return num;
|
|
133
|
+
return value;
|
|
134
|
+
}
|
|
135
|
+
// ── Loader ───────────────────────────────────────────────────────────────────
|
|
136
|
+
/**
|
|
137
|
+
* Load project config from .codeledger.yml in the given directory.
|
|
138
|
+
* Returns defaults if the file doesn't exist or fails to parse.
|
|
139
|
+
*/
|
|
140
|
+
export function loadProjectConfig(cwd) {
|
|
141
|
+
const filePath = join(cwd, '.codeledger.yml');
|
|
142
|
+
if (!existsSync(filePath)) {
|
|
143
|
+
return { ...DEFAULT_CONFIG };
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const raw = readFileSync(filePath, 'utf-8');
|
|
147
|
+
const parsed = parseSimpleYaml(raw);
|
|
148
|
+
return mergeConfig(DEFAULT_CONFIG, parsed);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Non-fatal — fall back to defaults
|
|
152
|
+
return { ...DEFAULT_CONFIG };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function mergeConfig(defaults, overrides) {
|
|
156
|
+
const result = structuredClone(defaults);
|
|
157
|
+
// pr section
|
|
158
|
+
const pr = overrides['pr'];
|
|
159
|
+
if (pr) {
|
|
160
|
+
if (typeof pr['base_branch'] === 'string')
|
|
161
|
+
result.pr.base_branch = pr['base_branch'];
|
|
162
|
+
if (typeof pr['comment_enabled'] === 'boolean')
|
|
163
|
+
result.pr.comment_enabled = pr['comment_enabled'];
|
|
164
|
+
if (Array.isArray(pr['sections']))
|
|
165
|
+
result.pr.sections = pr['sections'];
|
|
166
|
+
}
|
|
167
|
+
// verify section
|
|
168
|
+
const verify = overrides['verify'];
|
|
169
|
+
if (verify) {
|
|
170
|
+
if (typeof verify['mode'] === 'string' && ['observe', 'warn', 'block'].includes(verify['mode'])) {
|
|
171
|
+
result.verify.mode = verify['mode'];
|
|
172
|
+
}
|
|
173
|
+
if (typeof verify['severity_threshold'] === 'string') {
|
|
174
|
+
result.verify.severity_threshold = verify['severity_threshold'];
|
|
175
|
+
}
|
|
176
|
+
const ri = verify['review_intelligence'];
|
|
177
|
+
if (ri) {
|
|
178
|
+
if (typeof ri['enabled'] === 'boolean')
|
|
179
|
+
result.verify.review_intelligence.enabled = ri['enabled'];
|
|
180
|
+
const invariants = ri['invariants'];
|
|
181
|
+
if (invariants) {
|
|
182
|
+
for (const [k, v] of Object.entries(invariants)) {
|
|
183
|
+
if (typeof v === 'boolean')
|
|
184
|
+
result.verify.review_intelligence.invariants[k] = v;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// commit_msg section
|
|
190
|
+
const commitMsg = overrides['commit_msg'];
|
|
191
|
+
if (commitMsg) {
|
|
192
|
+
if (typeof commitMsg['signature'] === 'boolean')
|
|
193
|
+
result.commit_msg.signature = commitMsg['signature'];
|
|
194
|
+
if (typeof commitMsg['format'] === 'string' && ['full', 'minimal'].includes(commitMsg['format'])) {
|
|
195
|
+
result.commit_msg.format = commitMsg['format'];
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// intent section
|
|
199
|
+
const intent = overrides['intent'];
|
|
200
|
+
if (intent) {
|
|
201
|
+
if (typeof intent['tracker_prefix'] === 'string')
|
|
202
|
+
result.intent.tracker_prefix = intent['tracker_prefix'];
|
|
203
|
+
}
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=project-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-config.js","sourceRoot":"","sources":["../src/project-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { InvariantDetector } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* INVARIANT — architecture_graph
|
|
4
|
+
*
|
|
5
|
+
* Runs the architecture graph analysis and converts structural violations
|
|
6
|
+
* (circular dependencies, service boundary violations) into ReviewFindings
|
|
7
|
+
* so they appear in `codeledger verify` and CI gate output.
|
|
8
|
+
*
|
|
9
|
+
* This detector is graph-level (not per-file), so it ignores the files list
|
|
10
|
+
* and analyzes the whole repo structure. It caches the graph result per
|
|
11
|
+
* analysis run.
|
|
12
|
+
*
|
|
13
|
+
* Severity:
|
|
14
|
+
* - Circular dependencies: P1
|
|
15
|
+
* - Service boundary violations: P1 or P2 (from graph analysis)
|
|
16
|
+
*/
|
|
17
|
+
export declare const architectureGraphDetector: InvariantDetector;
|
|
18
|
+
//# sourceMappingURL=architecture-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architecture-graph.d.ts","sourceRoot":"","sources":["../../../src/review-intelligence/detectors/architecture-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,aAAa,CAAC;AAMrB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,yBAAyB,EAAE,iBA4DvC,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { buildArchitectureGraph, } from '../../architecture-graph/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* INVARIANT — architecture_graph
|
|
4
|
+
*
|
|
5
|
+
* Runs the architecture graph analysis and converts structural violations
|
|
6
|
+
* (circular dependencies, service boundary violations) into ReviewFindings
|
|
7
|
+
* so they appear in `codeledger verify` and CI gate output.
|
|
8
|
+
*
|
|
9
|
+
* This detector is graph-level (not per-file), so it ignores the files list
|
|
10
|
+
* and analyzes the whole repo structure. It caches the graph result per
|
|
11
|
+
* analysis run.
|
|
12
|
+
*
|
|
13
|
+
* Severity:
|
|
14
|
+
* - Circular dependencies: P1
|
|
15
|
+
* - Service boundary violations: P1 or P2 (from graph analysis)
|
|
16
|
+
*/
|
|
17
|
+
export const architectureGraphDetector = {
|
|
18
|
+
name: 'architecture_graph',
|
|
19
|
+
analyze(ctx) {
|
|
20
|
+
const findings = [];
|
|
21
|
+
let graph;
|
|
22
|
+
try {
|
|
23
|
+
graph = buildArchitectureGraph(ctx.cwd);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// Graph build can fail in repos without package structure — skip silently
|
|
27
|
+
return findings;
|
|
28
|
+
}
|
|
29
|
+
// Convert circular dependencies to findings
|
|
30
|
+
for (const cycle of graph.cycles) {
|
|
31
|
+
if (cycle.length < 2)
|
|
32
|
+
continue;
|
|
33
|
+
const cycleStr = cycle.join(' → ');
|
|
34
|
+
findings.push({
|
|
35
|
+
rule_id: 'RI-AG-001',
|
|
36
|
+
title: 'Circular dependency detected',
|
|
37
|
+
severity: 'P1',
|
|
38
|
+
category: 'architecture_graph',
|
|
39
|
+
file: cycle[0],
|
|
40
|
+
line: 0,
|
|
41
|
+
trigger: cycleStr,
|
|
42
|
+
missing_companions: [
|
|
43
|
+
'Break the cycle by extracting shared types/interfaces into a common package',
|
|
44
|
+
],
|
|
45
|
+
why_it_matters: `Circular dependency: ${cycleStr}. ` +
|
|
46
|
+
'Circular package dependencies cause unpredictable initialization order, ' +
|
|
47
|
+
'make tree-shaking impossible, and often indicate a layering violation.',
|
|
48
|
+
confidence: 'high',
|
|
49
|
+
fixable: false,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
// Convert boundary violations to findings
|
|
53
|
+
for (const violation of graph.boundaryViolations) {
|
|
54
|
+
findings.push({
|
|
55
|
+
rule_id: 'RI-AG-002',
|
|
56
|
+
title: 'Service boundary violation',
|
|
57
|
+
severity: violation.severity,
|
|
58
|
+
category: 'architecture_graph',
|
|
59
|
+
file: violation.sourceService,
|
|
60
|
+
line: 0,
|
|
61
|
+
trigger: `${violation.sourceService} imports ${violation.importPath}`,
|
|
62
|
+
missing_companions: [
|
|
63
|
+
'Use the public API/events of the target service instead of direct imports',
|
|
64
|
+
],
|
|
65
|
+
why_it_matters: violation.description,
|
|
66
|
+
confidence: 'high',
|
|
67
|
+
fixable: false,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return findings;
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=architecture-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architecture-graph.js","sourceRoot":"","sources":["../../../src/review-intelligence/detectors/architecture-graph.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,sBAAsB,GAEvB,MAAM,mCAAmC,CAAC;AAE3C;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAsB;IAC1D,IAAI,EAAE,oBAAoB;IAE1B,OAAO,CAAC,GAAoB;QAC1B,MAAM,QAAQ,GAAoB,EAAE,CAAC;QAErC,IAAI,KAAwB,CAAC;QAC7B,IAAI,CAAC;YACH,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;YAC1E,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,4CAA4C;QAC5C,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAS;YAE/B,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnC,QAAQ,CAAC,IAAI,CAAC;gBACZ,OAAO,EAAE,WAAW;gBACpB,KAAK,EAAE,8BAA8B;gBACrC,QAAQ,EAAE,IAAI;gBACd,QAAQ,EAAE,oBAAoB;gBAC9B,IAAI,EAAE,KAAK,CAAC,CAAC,CAAE;gBACf,IAAI,EAAE,CAAC;gBACP,OAAO,EAAE,QAAQ;gBACjB,kBAAkB,EAAE;oBAClB,6EAA6E;iBAC9E;gBACD,cAAc,EACZ,wBAAwB,QAAQ,IAAI;oBACpC,0EAA0E;oBAC1E,wEAAwE;gBAC1E,UAAU,EAAE,MAAM;gBAClB,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;QACL,CAAC;QAED,0CAA0C;QAC1C,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,kBAAkB,EAAE,CAAC;YACjD,QAAQ,CAAC,IAAI,CAAC;gBACZ,OAAO,EAAE,WAAW;gBACpB,KAAK,EAAE,4BAA4B;gBACnC,QAAQ,EAAE,SAAS,CAAC,QAAQ;gBAC5B,QAAQ,EAAE,oBAAoB;gBAC9B,IAAI,EAAE,SAAS,CAAC,aAAa;gBAC7B,IAAI,EAAE,CAAC;gBACP,OAAO,EAAE,GAAG,SAAS,CAAC,aAAa,YAAY,SAAS,CAAC,UAAU,EAAE;gBACrE,kBAAkB,EAAE;oBAClB,2EAA2E;iBAC5E;gBACD,cAAc,EAAE,SAAS,CAAC,WAAW;gBACrC,UAAU,EAAE,MAAM;gBAClB,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { InvariantDetector } from '../types.js';
|
|
2
|
+
import type { PackRule } from '../packs/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* INVARIANT — pack_rules (dynamic)
|
|
5
|
+
*
|
|
6
|
+
* Enforces enabled invariant pack rules. Each PackRule has:
|
|
7
|
+
* - trigger_pattern: regex that matches raw callsites
|
|
8
|
+
* - helper: the sanctioned wrapper/helper name that should be used
|
|
9
|
+
* - kind: required_wrapper | required_helper | forbidden_pattern | required_pattern
|
|
10
|
+
*
|
|
11
|
+
* This detector is parameterized at construction time with the active pack
|
|
12
|
+
* rules. It is NOT registered as a static built-in — instead it is created
|
|
13
|
+
* on-the-fly by the engine when enabled packs have rules.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createPackRulesDetector(rules: PackRule[]): InvariantDetector;
|
|
16
|
+
//# sourceMappingURL=pack-rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-rules.d.ts","sourceRoot":"","sources":["../../../src/review-intelligence/detectors/pack-rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAIlB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,iBAAiB,CA6B5E"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* INVARIANT — pack_rules (dynamic)
|
|
3
|
+
*
|
|
4
|
+
* Enforces enabled invariant pack rules. Each PackRule has:
|
|
5
|
+
* - trigger_pattern: regex that matches raw callsites
|
|
6
|
+
* - helper: the sanctioned wrapper/helper name that should be used
|
|
7
|
+
* - kind: required_wrapper | required_helper | forbidden_pattern | required_pattern
|
|
8
|
+
*
|
|
9
|
+
* This detector is parameterized at construction time with the active pack
|
|
10
|
+
* rules. It is NOT registered as a static built-in — instead it is created
|
|
11
|
+
* on-the-fly by the engine when enabled packs have rules.
|
|
12
|
+
*/
|
|
13
|
+
export function createPackRulesDetector(rules) {
|
|
14
|
+
return {
|
|
15
|
+
name: 'pack_rules',
|
|
16
|
+
analyze(ctx) {
|
|
17
|
+
const findings = [];
|
|
18
|
+
if (rules.length === 0)
|
|
19
|
+
return findings;
|
|
20
|
+
for (const filePath of ctx.files) {
|
|
21
|
+
const content = ctx.fileContents.get(filePath);
|
|
22
|
+
if (!content)
|
|
23
|
+
continue;
|
|
24
|
+
if (!isAnalyzableFile(filePath))
|
|
25
|
+
continue;
|
|
26
|
+
const lines = content.split('\n');
|
|
27
|
+
for (const rule of rules) {
|
|
28
|
+
if (rule.kind === 'forbidden_pattern') {
|
|
29
|
+
analyzeForbiddenPattern(rule, filePath, lines, findings);
|
|
30
|
+
}
|
|
31
|
+
else if (rule.kind === 'required_wrapper' || rule.kind === 'required_helper') {
|
|
32
|
+
analyzeRequiredWrapper(rule, filePath, content, lines, findings);
|
|
33
|
+
}
|
|
34
|
+
// required_pattern rules are structural — handled by built-in detectors
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return findings;
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function analyzeForbiddenPattern(rule, filePath, lines, findings) {
|
|
42
|
+
if (!rule.trigger_pattern)
|
|
43
|
+
return;
|
|
44
|
+
const triggerRe = new RegExp(rule.trigger_pattern, 'g');
|
|
45
|
+
for (let i = 0; i < lines.length; i++) {
|
|
46
|
+
const line = lines[i];
|
|
47
|
+
const trimmed = line.trim();
|
|
48
|
+
if (trimmed.startsWith('//') || trimmed.startsWith('*'))
|
|
49
|
+
continue;
|
|
50
|
+
triggerRe.lastIndex = 0;
|
|
51
|
+
if (triggerRe.test(trimmed)) {
|
|
52
|
+
findings.push({
|
|
53
|
+
rule_id: rule.rule_id,
|
|
54
|
+
title: rule.description,
|
|
55
|
+
severity: rule.severity,
|
|
56
|
+
category: 'pack_rules',
|
|
57
|
+
file: filePath,
|
|
58
|
+
line: i + 1,
|
|
59
|
+
trigger: trimmed.slice(0, 80),
|
|
60
|
+
missing_companions: ['Remove or replace the forbidden pattern'],
|
|
61
|
+
why_it_matters: rule.description,
|
|
62
|
+
confidence: 'high',
|
|
63
|
+
fixable: false,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function analyzeRequiredWrapper(rule, filePath, content, lines, findings) {
|
|
69
|
+
if (!rule.trigger_pattern || !rule.helper)
|
|
70
|
+
return;
|
|
71
|
+
// Check if the file uses the sanctioned helper
|
|
72
|
+
const helperUsed = content.includes(rule.helper);
|
|
73
|
+
if (helperUsed)
|
|
74
|
+
return; // File already uses the helper
|
|
75
|
+
const triggerRe = new RegExp(rule.trigger_pattern, 'g');
|
|
76
|
+
for (let i = 0; i < lines.length; i++) {
|
|
77
|
+
const line = lines[i];
|
|
78
|
+
const trimmed = line.trim();
|
|
79
|
+
if (trimmed.startsWith('//') || trimmed.startsWith('*'))
|
|
80
|
+
continue;
|
|
81
|
+
if (trimmed.startsWith('import '))
|
|
82
|
+
continue;
|
|
83
|
+
triggerRe.lastIndex = 0;
|
|
84
|
+
if (triggerRe.test(trimmed)) {
|
|
85
|
+
findings.push({
|
|
86
|
+
rule_id: rule.rule_id,
|
|
87
|
+
title: rule.description,
|
|
88
|
+
severity: rule.severity,
|
|
89
|
+
category: 'pack_rules',
|
|
90
|
+
file: filePath,
|
|
91
|
+
line: i + 1,
|
|
92
|
+
trigger: trimmed.slice(0, 80),
|
|
93
|
+
missing_companions: [`Use ${rule.helper} instead`],
|
|
94
|
+
why_it_matters: `Repository convention: ${rule.description}. ` +
|
|
95
|
+
`The sanctioned helper \`${rule.helper}\` should be used instead of raw calls.`,
|
|
96
|
+
confidence: 'high',
|
|
97
|
+
fixable: true,
|
|
98
|
+
});
|
|
99
|
+
// Only report first violation per file per rule to avoid noise
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function isAnalyzableFile(filePath) {
|
|
105
|
+
return /\.(?:ts|tsx|js|jsx|mts|mjs)$/.test(filePath);
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=pack-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-rules.js","sourceRoot":"","sources":["../../../src/review-intelligence/detectors/pack-rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,18 @@ export interface FixResult {
|
|
|
12
12
|
}
|
|
13
13
|
/** A fixer function */
|
|
14
14
|
export type Fixer = (finding: ReviewFinding, content: string) => FixResult | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Register a fixer for a rule ID. Replaces any existing fixer for that rule.
|
|
17
|
+
*/
|
|
18
|
+
export declare function registerFixer(ruleId: string, fixer: Fixer): void;
|
|
19
|
+
/**
|
|
20
|
+
* Remove a registered fixer by rule ID. No-op if not found.
|
|
21
|
+
*/
|
|
22
|
+
export declare function unregisterFixer(ruleId: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Register a fallback fixer that applies to findings matching a predicate.
|
|
25
|
+
*/
|
|
26
|
+
export declare function registerFallbackFixer(matches: (f: ReviewFinding) => boolean, fixer: Fixer): void;
|
|
15
27
|
/**
|
|
16
28
|
* Check if a finding has an auto-fix available.
|
|
17
29
|
*/
|
|
@@ -33,4 +45,10 @@ export declare function applyAllFixes(findings: ReviewFinding[], content: string
|
|
|
33
45
|
* Get all fixable rule IDs.
|
|
34
46
|
*/
|
|
35
47
|
export declare function getFixableRuleIds(): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Stamp `fixable: true` on findings that have a registered fixer
|
|
50
|
+
* (exact match OR fallback). Called by the engine after detectors run,
|
|
51
|
+
* before returning results.
|
|
52
|
+
*/
|
|
53
|
+
export declare function annotateFixable(findings: ReviewFinding[]): void;
|
|
36
54
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/review-intelligence/fixes/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,qCAAqC;AACrC,MAAM,WAAW,SAAS;IACxB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,uBAAuB;AACvB,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/review-intelligence/fixes/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,qCAAqC;AACrC,MAAM,WAAW,SAAS;IACxB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,uBAAuB;AACvB,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;AA2BvF;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAEhE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,OAAO,EACtC,KAAK,EAAE,KAAK,GACX,IAAI,CAEN;AAaD;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAEzD;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAIvF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,aAAa,EAAE,EACzB,OAAO,EAAE,MAAM,GACd;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,EAAE,CAAA;CAAE,CAiB9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAE5C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI,CAM/D"}
|