@codeledger/cli 0.6.3 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/commands/verify.d.ts.map +1 -1
  2. package/dist/commands/verify.js +78 -2
  3. package/dist/commands/verify.js.map +1 -1
  4. package/dist/index.js +2 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/policy/schema.d.ts.map +1 -1
  7. package/dist/policy/schema.js +1 -0
  8. package/dist/policy/schema.js.map +1 -1
  9. package/dist/review-intelligence/companion-check.d.ts +28 -0
  10. package/dist/review-intelligence/companion-check.d.ts.map +1 -0
  11. package/dist/review-intelligence/companion-check.js +71 -0
  12. package/dist/review-intelligence/companion-check.js.map +1 -0
  13. package/dist/review-intelligence/detectors/outbound-io.d.ts +14 -0
  14. package/dist/review-intelligence/detectors/outbound-io.d.ts.map +1 -0
  15. package/dist/review-intelligence/detectors/outbound-io.js +122 -0
  16. package/dist/review-intelligence/detectors/outbound-io.js.map +1 -0
  17. package/dist/review-intelligence/detectors/platform-helpers.d.ts +15 -0
  18. package/dist/review-intelligence/detectors/platform-helpers.d.ts.map +1 -0
  19. package/dist/review-intelligence/detectors/platform-helpers.js +171 -0
  20. package/dist/review-intelligence/detectors/platform-helpers.js.map +1 -0
  21. package/dist/review-intelligence/detectors/runtime-validation.d.ts +10 -0
  22. package/dist/review-intelligence/detectors/runtime-validation.d.ts.map +1 -0
  23. package/dist/review-intelligence/detectors/runtime-validation.js +109 -0
  24. package/dist/review-intelligence/detectors/runtime-validation.js.map +1 -0
  25. package/dist/review-intelligence/index.d.ts +17 -0
  26. package/dist/review-intelligence/index.d.ts.map +1 -0
  27. package/dist/review-intelligence/index.js +90 -0
  28. package/dist/review-intelligence/index.js.map +1 -0
  29. package/dist/review-intelligence/invariants.d.ts +10 -0
  30. package/dist/review-intelligence/invariants.d.ts.map +1 -0
  31. package/dist/review-intelligence/invariants.js +29 -0
  32. package/dist/review-intelligence/invariants.js.map +1 -0
  33. package/dist/review-intelligence/output.d.ts +25 -0
  34. package/dist/review-intelligence/output.d.ts.map +1 -0
  35. package/dist/review-intelligence/output.js +116 -0
  36. package/dist/review-intelligence/output.js.map +1 -0
  37. package/dist/review-intelligence/repair-guidance.d.ts +11 -0
  38. package/dist/review-intelligence/repair-guidance.d.ts.map +1 -0
  39. package/dist/review-intelligence/repair-guidance.js +91 -0
  40. package/dist/review-intelligence/repair-guidance.js.map +1 -0
  41. package/dist/review-intelligence/severity.d.ts +10 -0
  42. package/dist/review-intelligence/severity.d.ts.map +1 -0
  43. package/dist/review-intelligence/severity.js +36 -0
  44. package/dist/review-intelligence/severity.js.map +1 -0
  45. package/dist/review-intelligence/standards-discovery.d.ts +12 -0
  46. package/dist/review-intelligence/standards-discovery.d.ts.map +1 -0
  47. package/dist/review-intelligence/standards-discovery.js +221 -0
  48. package/dist/review-intelligence/standards-discovery.js.map +1 -0
  49. package/dist/review-intelligence/triggers.d.ts +15 -0
  50. package/dist/review-intelligence/triggers.d.ts.map +1 -0
  51. package/dist/review-intelligence/triggers.js +104 -0
  52. package/dist/review-intelligence/triggers.js.map +1 -0
  53. package/dist/review-intelligence/types.d.ts +137 -0
  54. package/dist/review-intelligence/types.d.ts.map +1 -0
  55. package/dist/review-intelligence/types.js +3 -0
  56. package/dist/review-intelligence/types.js.map +1 -0
  57. package/package.json +9 -9
@@ -0,0 +1,171 @@
1
+ import { detectTriggers } from '../triggers.js';
2
+ /**
3
+ * INVARIANT 3 — platform_helpers
4
+ *
5
+ * Detect bypassing of repository-standard helpers/patterns.
6
+ *
7
+ * Examples:
8
+ * - raw reply.status(...).send(...) instead of shared error helper
9
+ * - manual cache key format instead of shared helper
10
+ * - custom rate limit logic instead of shared middleware
11
+ *
12
+ * Severity: P2 (repository drift)
13
+ */
14
+ export const platformHelpersDetector = {
15
+ name: 'platform_helpers',
16
+ analyze(ctx) {
17
+ const findings = [];
18
+ for (const filePath of ctx.files) {
19
+ const content = ctx.fileContents.get(filePath);
20
+ if (!content)
21
+ continue;
22
+ if (!isAnalyzableFile(filePath))
23
+ continue;
24
+ // Check each pattern category
25
+ findings.push(...checkErrorResponseDrift(filePath, content, ctx));
26
+ findings.push(...checkCacheKeyDrift(filePath, content, ctx));
27
+ findings.push(...checkRateLimitDrift(filePath, content, ctx));
28
+ }
29
+ return findings;
30
+ },
31
+ };
32
+ /**
33
+ * Detect raw error responses when a shared error helper exists.
34
+ */
35
+ function checkErrorResponseDrift(filePath, content, ctx) {
36
+ const errorHelper = ctx.repoStandards.find((s) => {
37
+ const lower = s.helper_name.toLowerCase();
38
+ return (lower.includes('error') ||
39
+ lower.includes('response') ||
40
+ lower.includes('notfound') ||
41
+ lower.includes('badrequest') ||
42
+ lower.includes('send'));
43
+ });
44
+ if (!errorHelper)
45
+ return [];
46
+ if (isInHelperDefinition(filePath, errorHelper))
47
+ return [];
48
+ const findings = [];
49
+ const triggers = detectTriggers(filePath, content);
50
+ const errorTriggers = triggers.filter((t) => t.type === 'raw_error_response');
51
+ for (const trigger of errorTriggers) {
52
+ // Check if this line or nearby lines use the shared helper
53
+ const lines = content.split('\n');
54
+ const startLine = Math.max(0, trigger.line - 4);
55
+ const endLine = Math.min(lines.length, trigger.line + 3);
56
+ const nearby = lines.slice(startLine, endLine).join('\n');
57
+ if (!nearby.includes(errorHelper.helper_name)) {
58
+ findings.push({
59
+ rule_id: 'RI-PH-001',
60
+ title: 'Raw error response bypasses shared error helper',
61
+ severity: 'P2',
62
+ category: 'platform_helpers',
63
+ file: filePath,
64
+ line: trigger.line,
65
+ trigger: 'raw error response construction',
66
+ missing_companions: [`Use ${errorHelper.helper_name} for consistent error responses`],
67
+ why_it_matters: `This repository has a standard error helper (${errorHelper.helper_name}). ` +
68
+ 'Using raw reply.status().send() for errors creates inconsistency in error format, ' +
69
+ 'may miss logging/observability hooks, and makes error handling harder to maintain.',
70
+ repo_standard: errorHelper,
71
+ confidence: 'medium',
72
+ });
73
+ }
74
+ }
75
+ return findings;
76
+ }
77
+ /**
78
+ * Detect manual cache key construction when a shared helper exists.
79
+ */
80
+ function checkCacheKeyDrift(filePath, content, ctx) {
81
+ const cacheHelper = ctx.repoStandards.find((s) => {
82
+ const lower = s.helper_name.toLowerCase();
83
+ return (lower.includes('cache') ||
84
+ lower.includes('key'));
85
+ });
86
+ if (!cacheHelper)
87
+ return [];
88
+ if (isInHelperDefinition(filePath, cacheHelper))
89
+ return [];
90
+ const findings = [];
91
+ const triggers = detectTriggers(filePath, content);
92
+ const cacheTriggers = triggers.filter((t) => t.type === 'redis_cache_key');
93
+ for (const trigger of cacheTriggers) {
94
+ const lines = content.split('\n');
95
+ const startLine = Math.max(0, trigger.line - 4);
96
+ const endLine = Math.min(lines.length, trigger.line + 3);
97
+ const nearby = lines.slice(startLine, endLine).join('\n');
98
+ if (!nearby.includes(cacheHelper.helper_name)) {
99
+ findings.push({
100
+ rule_id: 'RI-PH-002',
101
+ title: 'Manual cache key bypasses shared cache helper',
102
+ severity: 'P2',
103
+ category: 'platform_helpers',
104
+ file: filePath,
105
+ line: trigger.line,
106
+ trigger: 'manual cache key construction',
107
+ missing_companions: [`Use ${cacheHelper.helper_name} for consistent cache key format`],
108
+ why_it_matters: `This repository has a standard cache helper (${cacheHelper.helper_name}). ` +
109
+ 'Manual cache key construction risks inconsistent key formats, ' +
110
+ 'missing tenant isolation, or namespace collisions.',
111
+ repo_standard: cacheHelper,
112
+ confidence: 'medium',
113
+ });
114
+ }
115
+ }
116
+ return findings;
117
+ }
118
+ /**
119
+ * Detect custom rate limiting when shared middleware exists.
120
+ */
121
+ function checkRateLimitDrift(filePath, content, ctx) {
122
+ const rateLimitHelper = ctx.repoStandards.find((s) => s.helper_name.includes('rateLimit') ||
123
+ s.helper_name.includes('rate_limit') ||
124
+ s.helper_name.includes('throttle'));
125
+ if (!rateLimitHelper)
126
+ return [];
127
+ if (isInHelperDefinition(filePath, rateLimitHelper))
128
+ return [];
129
+ const findings = [];
130
+ // Detect custom rate limiting patterns
131
+ const rateLimitPatterns = [
132
+ /\brateLimit\s*\(/,
133
+ /\bthrottle\s*\(/,
134
+ /\brequestCount\b.*\b(?:>=|>|===)\b/,
135
+ /\bwindow\b.*\b(?:requests?|count|limit)\b/i,
136
+ ];
137
+ const lines = content.split('\n');
138
+ for (let i = 0; i < lines.length; i++) {
139
+ const line = lines[i];
140
+ const trimmed = line.trim();
141
+ if (trimmed.startsWith('//') || trimmed.startsWith('import '))
142
+ continue;
143
+ for (const pattern of rateLimitPatterns) {
144
+ if (pattern.test(line) && !line.includes(rateLimitHelper.helper_name)) {
145
+ findings.push({
146
+ rule_id: 'RI-PH-003',
147
+ title: 'Custom rate limiting bypasses shared middleware',
148
+ severity: 'P2',
149
+ category: 'platform_helpers',
150
+ file: filePath,
151
+ line: i + 1,
152
+ trigger: 'custom rate limit logic',
153
+ missing_companions: [`Use ${rateLimitHelper.helper_name} for consistent rate limiting`],
154
+ why_it_matters: `This repository has a standard rate limiting helper (${rateLimitHelper.helper_name}). ` +
155
+ 'Custom rate limiting creates inconsistency and may miss distributed coordination.',
156
+ repo_standard: rateLimitHelper,
157
+ confidence: 'low',
158
+ });
159
+ break;
160
+ }
161
+ }
162
+ }
163
+ return findings;
164
+ }
165
+ function isInHelperDefinition(filePath, helper) {
166
+ return helper.example_paths.some((p) => filePath === p || filePath.endsWith(p));
167
+ }
168
+ function isAnalyzableFile(filePath) {
169
+ return /\.(?:ts|tsx|js|jsx|mts|mjs)$/.test(filePath);
170
+ }
171
+ //# sourceMappingURL=platform-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-helpers.js","sourceRoot":"","sources":["../../../src/review-intelligence/detectors/platform-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { InvariantDetector } from '../types.js';
2
+ /**
3
+ * INVARIANT 1 — runtime_validation
4
+ *
5
+ * Trigger: typed route body/params/query (e.g. server.post<{ Body: ... }>(...))
6
+ * Invariant: runtime validation must exist (zod, ajv, Fastify schema)
7
+ * Severity: P1 (missing runtime validation)
8
+ */
9
+ export declare const runtimeValidationDetector: InvariantDetector;
10
+ //# sourceMappingURL=runtime-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-validation.d.ts","sourceRoot":"","sources":["../../../src/review-intelligence/detectors/runtime-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,aAAa,CAAC;AAGrB;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,EAAE,iBAiEvC,CAAC"}
@@ -0,0 +1,109 @@
1
+ import { detectTriggers, isTypedRouteTrigger } from '../triggers.js';
2
+ /**
3
+ * INVARIANT 1 — runtime_validation
4
+ *
5
+ * Trigger: typed route body/params/query (e.g. server.post<{ Body: ... }>(...))
6
+ * Invariant: runtime validation must exist (zod, ajv, Fastify schema)
7
+ * Severity: P1 (missing runtime validation)
8
+ */
9
+ export const runtimeValidationDetector = {
10
+ name: 'runtime_validation',
11
+ analyze(ctx) {
12
+ const findings = [];
13
+ for (const filePath of ctx.files) {
14
+ const content = ctx.fileContents.get(filePath);
15
+ if (!content)
16
+ continue;
17
+ // Only analyze TypeScript/JavaScript files
18
+ if (!isAnalyzableFile(filePath))
19
+ continue;
20
+ const triggers = detectTriggers(filePath, content);
21
+ const typedRouteTriggers = triggers.filter(isTypedRouteTrigger);
22
+ if (typedRouteTriggers.length === 0)
23
+ continue;
24
+ // Check if file has runtime validation evidence
25
+ const hasValidation = checkRuntimeValidation(content, ctx);
26
+ if (!hasValidation.found) {
27
+ // Group triggers by proximity to avoid duplicate findings
28
+ const grouped = groupTriggersByProximity(typedRouteTriggers);
29
+ for (const group of grouped) {
30
+ const firstTrigger = group[0];
31
+ const triggerTypes = [...new Set(group.map((t) => t.type))];
32
+ const triggerLabel = triggerTypes
33
+ .map(formatTriggerType)
34
+ .join(', ');
35
+ const finding = {
36
+ rule_id: 'RI-RV-001',
37
+ title: 'Typed route without runtime validation',
38
+ severity: 'P1',
39
+ category: 'runtime_validation',
40
+ file: filePath,
41
+ line: firstTrigger.line,
42
+ trigger: triggerLabel,
43
+ missing_companions: ['Runtime validation (zod, ajv, or Fastify schema)'],
44
+ why_it_matters: 'TypeScript generics on route definitions (Body, Params, Querystring) provide compile-time safety only. ' +
45
+ 'Without runtime validation, malformed input from clients will bypass type checks and may cause unexpected behavior or security issues.',
46
+ confidence: 'high',
47
+ };
48
+ // Attach repo standard if a validation helper was discovered
49
+ const validationStandard = ctx.repoStandards.find((s) => s.helper_name.includes('validate') ||
50
+ s.helper_name.includes('schema') ||
51
+ s.helper_name.includes('parse'));
52
+ if (validationStandard) {
53
+ finding.repo_standard = validationStandard;
54
+ }
55
+ findings.push(finding);
56
+ }
57
+ }
58
+ }
59
+ return findings;
60
+ },
61
+ };
62
+ function checkRuntimeValidation(content, _ctx) {
63
+ // Zod: .parse(), .safeParse(), z.object(), z.string(), etc.
64
+ if (/\bz\.(?:object|string|number|array|enum|union|literal|boolean)\s*\(/.test(content) && /\.(?:parse|safeParse)\s*\(/.test(content)) {
65
+ return { found: true, type: 'zod' };
66
+ }
67
+ // AJV: ajv.compile(), ajv.validate(), validate()
68
+ if (/\bajv\b/i.test(content) && /\.(?:compile|validate)\s*\(/.test(content)) {
69
+ return { found: true, type: 'ajv' };
70
+ }
71
+ // Fastify schema: schema: { body: ..., params: ..., querystring: ... }
72
+ if (/schema\s*:\s*\{/.test(content) && /(?:body|params|querystring)\s*:/.test(content)) {
73
+ return { found: true, type: 'fastify_schema' };
74
+ }
75
+ // Generic validation patterns: joi, yup, superstruct, valibot
76
+ if (/\b(?:joi|yup|superstruct|valibot)\b/i.test(content) && /\.(?:validate|parse|assert)\s*\(/.test(content)) {
77
+ return { found: true, type: 'generic_validator' };
78
+ }
79
+ return { found: false };
80
+ }
81
+ function isAnalyzableFile(filePath) {
82
+ return /\.(?:ts|tsx|js|jsx|mts|mjs)$/.test(filePath);
83
+ }
84
+ function formatTriggerType(type) {
85
+ return type.replace(/_/g, ' ');
86
+ }
87
+ /**
88
+ * Group triggers that are within 10 lines of each other
89
+ * to avoid duplicate findings for the same route handler.
90
+ */
91
+ function groupTriggersByProximity(triggers) {
92
+ if (triggers.length === 0)
93
+ return [];
94
+ const sorted = [...triggers].sort((a, b) => a.line - b.line);
95
+ const groups = [[sorted[0]]];
96
+ for (let i = 1; i < sorted.length; i++) {
97
+ const current = sorted[i];
98
+ const lastGroup = groups[groups.length - 1];
99
+ const lastInGroup = lastGroup[lastGroup.length - 1];
100
+ if (current.line - lastInGroup.line <= 10) {
101
+ lastGroup.push(current);
102
+ }
103
+ else {
104
+ groups.push([current]);
105
+ }
106
+ }
107
+ return groups;
108
+ }
109
+ //# sourceMappingURL=runtime-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-validation.js","sourceRoot":"","sources":["../../../src/review-intelligence/detectors/runtime-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { ReviewIntelligenceResult, ReviewIntelligenceOptions, ReviewIntelligencePolicy } from './types.js';
2
+ export type { ReviewIntelligenceResult, ReviewIntelligenceOptions, ReviewIntelligencePolicy, ReviewFinding, } from './types.js';
3
+ export { getAvailableInvariantNames } from './invariants.js';
4
+ export { formatHumanOutput, formatJsonOutput, formatDebugOutput, formatVerifySummaryLine } from './output.js';
5
+ /** Default policy when no review_intelligence config is present */
6
+ export declare const DEFAULT_REVIEW_INTELLIGENCE_POLICY: ReviewIntelligencePolicy;
7
+ /**
8
+ * Run the Review Intelligence engine.
9
+ *
10
+ * Pipeline:
11
+ * 1. Load file contents for changed/relevant files
12
+ * 2. Discover repo standards (helpers, wrappers)
13
+ * 3. Run enabled invariant detectors
14
+ * 4. Sort and summarize findings
15
+ */
16
+ export declare function runReviewIntelligence(options: ReviewIntelligenceOptions): ReviewIntelligenceResult;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/review-intelligence/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EAGzB,MAAM,YAAY,CAAC;AAMpB,YAAY,EACV,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE9G,mEAAmE;AACnE,eAAO,MAAM,kCAAkC,EAAE,wBAQhD,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,yBAAyB,GACjC,wBAAwB,CAyE1B"}
@@ -0,0 +1,90 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { getEnabledDetectors, getAvailableInvariantNames } from './invariants.js';
4
+ import { discoverRepoStandards } from './standards-discovery.js';
5
+ import { sortFindings, determineStatus } from './severity.js';
6
+ import { detectTriggers } from './triggers.js';
7
+ export { getAvailableInvariantNames } from './invariants.js';
8
+ export { formatHumanOutput, formatJsonOutput, formatDebugOutput, formatVerifySummaryLine } from './output.js';
9
+ /** Default policy when no review_intelligence config is present */
10
+ export const DEFAULT_REVIEW_INTELLIGENCE_POLICY = {
11
+ enabled: true,
12
+ severity_threshold: 'P1',
13
+ invariants: {
14
+ runtime_validation: { enabled: true },
15
+ outbound_io: { enabled: true },
16
+ platform_helpers: { enabled: true },
17
+ },
18
+ };
19
+ /**
20
+ * Run the Review Intelligence engine.
21
+ *
22
+ * Pipeline:
23
+ * 1. Load file contents for changed/relevant files
24
+ * 2. Discover repo standards (helpers, wrappers)
25
+ * 3. Run enabled invariant detectors
26
+ * 4. Sort and summarize findings
27
+ */
28
+ export function runReviewIntelligence(options) {
29
+ const startTime = Date.now();
30
+ // Validate invariant filter
31
+ if (options.invariant) {
32
+ const available = getAvailableInvariantNames();
33
+ if (!available.includes(options.invariant)) {
34
+ throw new Error(`Unknown invariant "${options.invariant}". Available: ${available.join(', ')}`);
35
+ }
36
+ }
37
+ // Load file contents
38
+ const fileContents = new Map();
39
+ for (const filePath of options.files) {
40
+ const fullPath = join(options.cwd, filePath);
41
+ try {
42
+ fileContents.set(filePath, readFileSync(fullPath, 'utf-8'));
43
+ }
44
+ catch {
45
+ // Skip files that can't be read (deleted, binary, etc.)
46
+ }
47
+ }
48
+ // Discover repo standards
49
+ const repoStandards = discoverRepoStandards(options.cwd, options.files);
50
+ // Build detector context
51
+ const ctx = {
52
+ cwd: options.cwd,
53
+ files: options.files,
54
+ fileContents,
55
+ repoStandards,
56
+ explain: options.explain,
57
+ };
58
+ // Run enabled detectors
59
+ const detectors = getEnabledDetectors(options.policy, options.invariant);
60
+ const allFindings = [];
61
+ for (const detector of detectors) {
62
+ const findings = detector.analyze(ctx);
63
+ allFindings.push(...findings);
64
+ }
65
+ // Sort findings by severity, then file
66
+ const sortedFindings = sortFindings(allFindings);
67
+ // Count triggers (for debug output)
68
+ let triggerCount = 0;
69
+ for (const [, content] of fileContents) {
70
+ triggerCount += detectTriggers('', content).length;
71
+ }
72
+ // Build summary
73
+ const summary = {
74
+ p0: sortedFindings.filter((f) => f.severity === 'P0').length,
75
+ p1: sortedFindings.filter((f) => f.severity === 'P1').length,
76
+ p2: sortedFindings.filter((f) => f.severity === 'P2').length,
77
+ p3: sortedFindings.filter((f) => f.severity === 'P3').length,
78
+ total: sortedFindings.length,
79
+ };
80
+ const status = determineStatus(sortedFindings, options.policy.severity_threshold);
81
+ const duration = Date.now() - startTime;
82
+ return {
83
+ findings: sortedFindings,
84
+ repo_standards: repoStandards,
85
+ summary,
86
+ status,
87
+ duration_ms: duration,
88
+ };
89
+ }
90
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/review-intelligence/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { InvariantDetector, ReviewIntelligencePolicy } from './types.js';
2
+ /**
3
+ * Get enabled detectors based on policy configuration and optional filter.
4
+ */
5
+ export declare function getEnabledDetectors(policy: ReviewIntelligencePolicy, invariantFilter?: string): InvariantDetector[];
6
+ /**
7
+ * Get all available detector names (for --invariant flag validation).
8
+ */
9
+ export declare function getAvailableInvariantNames(): string[];
10
+ //# sourceMappingURL=invariants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invariants.d.ts","sourceRoot":"","sources":["../../src/review-intelligence/invariants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAY9E;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,wBAAwB,EAChC,eAAe,CAAC,EAAE,MAAM,GACvB,iBAAiB,EAAE,CAWrB;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,EAAE,CAErD"}
@@ -0,0 +1,29 @@
1
+ import { runtimeValidationDetector } from './detectors/runtime-validation.js';
2
+ import { outboundIODetector } from './detectors/outbound-io.js';
3
+ import { platformHelpersDetector } from './detectors/platform-helpers.js';
4
+ /** Registry of all invariant detector modules */
5
+ const ALL_DETECTORS = [
6
+ runtimeValidationDetector,
7
+ outboundIODetector,
8
+ platformHelpersDetector,
9
+ ];
10
+ /**
11
+ * Get enabled detectors based on policy configuration and optional filter.
12
+ */
13
+ export function getEnabledDetectors(policy, invariantFilter) {
14
+ let detectors = ALL_DETECTORS.filter((d) => {
15
+ const config = policy.invariants[d.name];
16
+ return config?.enabled !== false;
17
+ });
18
+ if (invariantFilter) {
19
+ detectors = detectors.filter((d) => d.name === invariantFilter);
20
+ }
21
+ return detectors;
22
+ }
23
+ /**
24
+ * Get all available detector names (for --invariant flag validation).
25
+ */
26
+ export function getAvailableInvariantNames() {
27
+ return ALL_DETECTORS.map((d) => d.name);
28
+ }
29
+ //# sourceMappingURL=invariants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invariants.js","sourceRoot":"","sources":["../../src/review-intelligence/invariants.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,iDAAiD;AACjD,MAAM,aAAa,GAAwB;IACzC,yBAAyB;IACzB,kBAAkB;IAClB,uBAAuB;CACxB,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAgC,EAChC,eAAwB;IAExB,IAAI,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACzC,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACzC,OAAO,MAAM,EAAE,OAAO,KAAK,KAAK,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,IAAI,eAAe,EAAE,CAAC;QACpB,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,0BAA0B;IACxC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { ReviewIntelligenceResult } from './types.js';
2
+ import type { ReviewSeverity } from './types.js';
3
+ /**
4
+ * Format review intelligence results for human-readable console output.
5
+ */
6
+ export declare function formatHumanOutput(result: ReviewIntelligenceResult, options: {
7
+ explain: boolean;
8
+ severityThreshold: ReviewSeverity;
9
+ }): string;
10
+ /**
11
+ * Format review intelligence results as JSON for machine consumption.
12
+ */
13
+ export declare function formatJsonOutput(result: ReviewIntelligenceResult): string;
14
+ /**
15
+ * Format debug output showing trigger detection internals.
16
+ */
17
+ export declare function formatDebugOutput(result: ReviewIntelligenceResult, _detectorInfo: {
18
+ filesAnalyzed: number;
19
+ triggersFound: number;
20
+ }): string;
21
+ /**
22
+ * Format a compact summary line for the verify output.
23
+ */
24
+ export declare function formatVerifySummaryLine(result: ReviewIntelligenceResult): string;
25
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/review-intelligence/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAA+B,MAAM,YAAY,CAAC;AAGxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,wBAAwB,EAChC,OAAO,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,iBAAiB,EAAE,cAAc,CAAA;CAAE,GAC/D,MAAM,CA6DR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,wBAAwB,GAC/B,MAAM,CAER;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,wBAAwB,EAChC,aAAa,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAC9D,MAAM,CAsBR;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAYhF"}
@@ -0,0 +1,116 @@
1
+ import { generateRepairGuidance, formatRepoStandardRecommendations } from './repair-guidance.js';
2
+ import { filterBySeverity } from './severity.js';
3
+ /**
4
+ * Format review intelligence results for human-readable console output.
5
+ */
6
+ export function formatHumanOutput(result, options) {
7
+ const lines = [];
8
+ const visibleFindings = filterBySeverity(result.findings, options.severityThreshold);
9
+ // Header section
10
+ lines.push('');
11
+ lines.push('Review Intelligence');
12
+ lines.push('───────────────────');
13
+ lines.push(` Status: ${result.status}`);
14
+ lines.push(` Findings: ${result.summary.total} total (P0:${result.summary.p0} P1:${result.summary.p1} P2:${result.summary.p2} P3:${result.summary.p3})`);
15
+ if (visibleFindings.length === 0) {
16
+ lines.push(' No findings at current severity threshold.');
17
+ lines.push('');
18
+ return lines.join('\n');
19
+ }
20
+ // Top Findings
21
+ lines.push('');
22
+ lines.push(' Top Findings');
23
+ lines.push(' ────────────');
24
+ for (const finding of visibleFindings) {
25
+ lines.push('');
26
+ lines.push(` [${finding.severity}] ${finding.title}`);
27
+ lines.push(` File: ${finding.file}:${finding.line}`);
28
+ lines.push(` Trigger: ${finding.trigger}`);
29
+ if (finding.missing_companions.length > 0) {
30
+ lines.push(` Missing: ${finding.missing_companions.join('; ')}`);
31
+ }
32
+ if (options.explain) {
33
+ lines.push(` Why: ${finding.why_it_matters}`);
34
+ if (finding.repo_standard) {
35
+ lines.push(` Repo standard: ${finding.repo_standard.helper_name} (${finding.repo_standard.usage_count} uses)`);
36
+ if (finding.repo_standard.example_paths.length > 0) {
37
+ lines.push(` Example: ${finding.repo_standard.example_paths[0]}`);
38
+ }
39
+ }
40
+ const guidance = generateRepairGuidance(finding);
41
+ if (guidance) {
42
+ lines.push(' Fix:');
43
+ for (const guidanceLine of guidance.split('\n')) {
44
+ lines.push(` ${guidanceLine}`);
45
+ }
46
+ }
47
+ }
48
+ }
49
+ // Repo standard recommendations (if any findings reference them)
50
+ const referencedStandards = getReferencedStandards(visibleFindings);
51
+ if (referencedStandards.length > 0 && options.explain) {
52
+ lines.push('');
53
+ lines.push(' ' + formatRepoStandardRecommendations(referencedStandards).split('\n').join('\n '));
54
+ }
55
+ lines.push('');
56
+ return lines.join('\n');
57
+ }
58
+ /**
59
+ * Format review intelligence results as JSON for machine consumption.
60
+ */
61
+ export function formatJsonOutput(result) {
62
+ return JSON.stringify(result, null, 2);
63
+ }
64
+ /**
65
+ * Format debug output showing trigger detection internals.
66
+ */
67
+ export function formatDebugOutput(result, _detectorInfo) {
68
+ const lines = [];
69
+ lines.push('');
70
+ lines.push('Review Intelligence — Debug');
71
+ lines.push('──────────────────────────');
72
+ lines.push(` Files analyzed: ${_detectorInfo.filesAnalyzed}`);
73
+ lines.push(` Triggers found: ${_detectorInfo.triggersFound}`);
74
+ lines.push(` Findings generated: ${result.summary.total}`);
75
+ lines.push(` Repo standards discovered: ${result.repo_standards.length}`);
76
+ lines.push(` Duration: ${result.duration_ms}ms`);
77
+ if (result.repo_standards.length > 0) {
78
+ lines.push('');
79
+ lines.push(' Discovered Standards:');
80
+ for (const std of result.repo_standards) {
81
+ lines.push(` ${std.helper_name} — ${std.usage_count} uses — ${std.example_paths.join(', ')}`);
82
+ }
83
+ }
84
+ lines.push('');
85
+ return lines.join('\n');
86
+ }
87
+ /**
88
+ * Format a compact summary line for the verify output.
89
+ */
90
+ export function formatVerifySummaryLine(result) {
91
+ if (result.summary.total === 0) {
92
+ return 'Review Intelligence: PASS (no architectural findings)';
93
+ }
94
+ const parts = [];
95
+ if (result.summary.p0 > 0)
96
+ parts.push(`${result.summary.p0} P0`);
97
+ if (result.summary.p1 > 0)
98
+ parts.push(`${result.summary.p1} P1`);
99
+ if (result.summary.p2 > 0)
100
+ parts.push(`${result.summary.p2} P2`);
101
+ if (result.summary.p3 > 0)
102
+ parts.push(`${result.summary.p3} P3`);
103
+ return `Review Intelligence: ${result.status} (${parts.join(', ')})`;
104
+ }
105
+ function getReferencedStandards(findings) {
106
+ const seen = new Set();
107
+ const standards = [];
108
+ for (const finding of findings) {
109
+ if (finding.repo_standard && !seen.has(finding.repo_standard.helper_name)) {
110
+ seen.add(finding.repo_standard.helper_name);
111
+ standards.push(finding.repo_standard);
112
+ }
113
+ }
114
+ return standards;
115
+ }
116
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/review-intelligence/output.ts"],"names":[],"mappings":"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"}