@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,11 @@
1
+ import type { ReviewFinding, RepoStandard } from './types.js';
2
+ /**
3
+ * Generate repair guidance for a finding.
4
+ * Provides actionable recommendations that AI agents can apply.
5
+ */
6
+ export declare function generateRepairGuidance(finding: ReviewFinding): string;
7
+ /**
8
+ * Format all repo standards as a recommendation section.
9
+ */
10
+ export declare function formatRepoStandardRecommendations(standards: RepoStandard[]): string;
11
+ //# sourceMappingURL=repair-guidance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repair-guidance.d.ts","sourceRoot":"","sources":["../../src/review-intelligence/repair-guidance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAuErE;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,YAAY,EAAE,GACxB,MAAM,CAgBR"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Generate repair guidance for a finding.
3
+ * Provides actionable recommendations that AI agents can apply.
4
+ */
5
+ export function generateRepairGuidance(finding) {
6
+ const lines = [];
7
+ switch (finding.rule_id) {
8
+ case 'RI-RV-001':
9
+ lines.push('Add runtime validation for route input:');
10
+ lines.push('');
11
+ if (finding.repo_standard) {
12
+ lines.push(` Recommended: Use ${finding.repo_standard.helper_name}`);
13
+ if (finding.repo_standard.example_paths.length > 0) {
14
+ lines.push(` Example: See ${finding.repo_standard.example_paths[0]}`);
15
+ }
16
+ }
17
+ else {
18
+ lines.push(' Option 1: Add Fastify schema validation:');
19
+ lines.push(' schema: { body: Type.Object({ ... }) }');
20
+ lines.push('');
21
+ lines.push(' Option 2: Add zod parsing in the handler:');
22
+ lines.push(' const parsed = MySchema.safeParse(request.body);');
23
+ lines.push(' if (!parsed.success) return reply.status(400).send(parsed.error);');
24
+ }
25
+ break;
26
+ case 'RI-OI-001':
27
+ lines.push('Add a timeout to this outbound call:');
28
+ lines.push('');
29
+ if (finding.repo_standard) {
30
+ lines.push(` Recommended: Use ${finding.repo_standard.helper_name} instead of raw fetch/axios`);
31
+ if (finding.repo_standard.example_paths.length > 0) {
32
+ lines.push(` Example: See ${finding.repo_standard.example_paths[0]}`);
33
+ }
34
+ }
35
+ else {
36
+ lines.push(' Option 1: AbortController with timeout:');
37
+ lines.push(' const controller = new AbortController();');
38
+ lines.push(' const timeout = setTimeout(() => controller.abort(), 5000);');
39
+ lines.push(' try { await fetch(url, { signal: controller.signal }); }');
40
+ lines.push(' finally { clearTimeout(timeout); }');
41
+ lines.push('');
42
+ lines.push(' Option 2: axios timeout:');
43
+ lines.push(' await axios.get(url, { timeout: 5000 });');
44
+ }
45
+ break;
46
+ case 'RI-OI-002':
47
+ if (finding.repo_standard) {
48
+ lines.push(`Replace raw call with ${finding.repo_standard.helper_name}:`);
49
+ lines.push('');
50
+ lines.push(` import { ${finding.repo_standard.helper_name} } from '...';`);
51
+ if (finding.repo_standard.example_paths.length > 0) {
52
+ lines.push(` Example usage: See ${finding.repo_standard.example_paths[0]}`);
53
+ }
54
+ }
55
+ break;
56
+ case 'RI-PH-001':
57
+ case 'RI-PH-002':
58
+ case 'RI-PH-003':
59
+ if (finding.repo_standard) {
60
+ lines.push(`Use ${finding.repo_standard.helper_name} instead:`);
61
+ lines.push('');
62
+ lines.push(` import { ${finding.repo_standard.helper_name} } from '...';`);
63
+ if (finding.repo_standard.example_paths.length > 0) {
64
+ lines.push(` See: ${finding.repo_standard.example_paths[0]}`);
65
+ }
66
+ }
67
+ break;
68
+ default:
69
+ lines.push('Review the finding and apply the recommended fix.');
70
+ }
71
+ return lines.join('\n');
72
+ }
73
+ /**
74
+ * Format all repo standards as a recommendation section.
75
+ */
76
+ export function formatRepoStandardRecommendations(standards) {
77
+ if (standards.length === 0)
78
+ return '';
79
+ const lines = [];
80
+ lines.push('Suggested Repo Patterns');
81
+ lines.push('───────────────────────');
82
+ for (const standard of standards) {
83
+ lines.push(` ${standard.helper_name} (${standard.usage_count} uses)`);
84
+ lines.push(` ${standard.recommendation}`);
85
+ if (standard.example_paths.length > 0) {
86
+ lines.push(` Defined in: ${standard.example_paths.join(', ')}`);
87
+ }
88
+ }
89
+ return lines.join('\n');
90
+ }
91
+ //# sourceMappingURL=repair-guidance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repair-guidance.js","sourceRoot":"","sources":["../../src/review-intelligence/repair-guidance.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAsB;IAC3D,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,QAAQ,OAAO,CAAC,OAAO,EAAE,CAAC;QACxB,KAAK,WAAW;YACd,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;YACtD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,sBAAsB,OAAO,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC;gBACtE,IAAI,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACnD,KAAK,CAAC,IAAI,CAAC,kBAAkB,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACzE,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;gBACzD,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;gBACzD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;gBAC1D,KAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;gBACnE,KAAK,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;YACtF,CAAC;YACD,MAAM;QAER,KAAK,WAAW;YACd,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;YACnD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,sBAAsB,OAAO,CAAC,aAAa,CAAC,WAAW,6BAA6B,CAAC,CAAC;gBACjG,IAAI,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACnD,KAAK,CAAC,IAAI,CAAC,kBAAkB,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACzE,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;gBACxD,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;gBAC5D,KAAK,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;gBAC9E,KAAK,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;gBAC3E,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;gBACrD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;gBACzC,KAAK,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;YAC7D,CAAC;YACD,MAAM;QAER,KAAK,WAAW;YACd,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,yBAAyB,OAAO,CAAC,aAAa,CAAC,WAAW,GAAG,CAAC,CAAC;gBAC1E,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC,cAAc,OAAO,CAAC,aAAa,CAAC,WAAW,gBAAgB,CAAC,CAAC;gBAC5E,IAAI,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACnD,KAAK,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC/E,CAAC;YACH,CAAC;YACD,MAAM;QAER,KAAK,WAAW,CAAC;QACjB,KAAK,WAAW,CAAC;QACjB,KAAK,WAAW;YACd,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,OAAO,OAAO,CAAC,aAAa,CAAC,WAAW,WAAW,CAAC,CAAC;gBAChE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC,cAAc,OAAO,CAAC,aAAa,CAAC,WAAW,gBAAgB,CAAC,CAAC;gBAC5E,IAAI,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACnD,KAAK,CAAC,IAAI,CAAC,UAAU,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACjE,CAAC;YACH,CAAC;YACD,MAAM;QAER;YACE,KAAK,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IACpE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iCAAiC,CAC/C,SAAyB;IAEzB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACtC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAEtC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW,QAAQ,CAAC,CAAC;QACvE,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC;QAC7C,IAAI,QAAQ,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,CAAC,mBAAmB,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ReviewSeverity, ReviewFinding } from './types.js';
2
+ /** Check if a severity meets or exceeds the threshold */
3
+ export declare function meetsSeverityThreshold(severity: ReviewSeverity, threshold: ReviewSeverity): boolean;
4
+ /** Filter findings by severity threshold */
5
+ export declare function filterBySeverity(findings: ReviewFinding[], threshold: ReviewSeverity): ReviewFinding[];
6
+ /** Sort findings by severity (most severe first), then by file and line */
7
+ export declare function sortFindings(findings: ReviewFinding[]): ReviewFinding[];
8
+ /** Determine overall status from findings */
9
+ export declare function determineStatus(findings: ReviewFinding[], threshold: ReviewSeverity): 'PASS' | 'WARN' | 'FAIL';
10
+ //# sourceMappingURL=severity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severity.d.ts","sourceRoot":"","sources":["../../src/review-intelligence/severity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAUhE,yDAAyD;AACzD,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,cAAc,EACxB,SAAS,EAAE,cAAc,GACxB,OAAO,CAET;AAED,4CAA4C;AAC5C,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,aAAa,EAAE,EACzB,SAAS,EAAE,cAAc,GACxB,aAAa,EAAE,CAEjB;AAED,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE,CAQvE;AAED,6CAA6C;AAC7C,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,aAAa,EAAE,EACzB,SAAS,EAAE,cAAc,GACxB,MAAM,GAAG,MAAM,GAAG,MAAM,CAQ1B"}
@@ -0,0 +1,36 @@
1
+ /** Numeric rank for severity comparison (lower = more severe) */
2
+ const SEVERITY_RANK = {
3
+ P0: 0,
4
+ P1: 1,
5
+ P2: 2,
6
+ P3: 3,
7
+ };
8
+ /** Check if a severity meets or exceeds the threshold */
9
+ export function meetsSeverityThreshold(severity, threshold) {
10
+ return SEVERITY_RANK[severity] <= SEVERITY_RANK[threshold];
11
+ }
12
+ /** Filter findings by severity threshold */
13
+ export function filterBySeverity(findings, threshold) {
14
+ return findings.filter((f) => meetsSeverityThreshold(f.severity, threshold));
15
+ }
16
+ /** Sort findings by severity (most severe first), then by file and line */
17
+ export function sortFindings(findings) {
18
+ return [...findings].sort((a, b) => {
19
+ const sevCmp = SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity];
20
+ if (sevCmp !== 0)
21
+ return sevCmp;
22
+ const fileCmp = a.file.localeCompare(b.file);
23
+ if (fileCmp !== 0)
24
+ return fileCmp;
25
+ return a.line - b.line;
26
+ });
27
+ }
28
+ /** Determine overall status from findings */
29
+ export function determineStatus(findings, threshold) {
30
+ const thresholdFindings = filterBySeverity(findings, threshold);
31
+ if (thresholdFindings.length === 0)
32
+ return 'PASS';
33
+ const hasP0orP1 = thresholdFindings.some((f) => f.severity === 'P0' || f.severity === 'P1');
34
+ return hasP0orP1 ? 'FAIL' : 'WARN';
35
+ }
36
+ //# sourceMappingURL=severity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severity.js","sourceRoot":"","sources":["../../src/review-intelligence/severity.ts"],"names":[],"mappings":"AAEA,iEAAiE;AACjE,MAAM,aAAa,GAAmC;IACpD,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;CACN,CAAC;AAEF,yDAAyD;AACzD,MAAM,UAAU,sBAAsB,CACpC,QAAwB,EACxB,SAAyB;IAEzB,OAAO,aAAa,CAAC,QAAQ,CAAC,IAAI,aAAa,CAAC,SAAS,CAAC,CAAC;AAC7D,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,gBAAgB,CAC9B,QAAyB,EACzB,SAAyB;IAEzB,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,sBAAsB,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,YAAY,CAAC,QAAyB;IACpD,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACjC,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACrE,IAAI,MAAM,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC;QAChC,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,OAAO,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;QAClC,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,eAAe,CAC7B,QAAyB,EACzB,SAAyB;IAEzB,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAChE,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAElD,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CACtC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI,CAClD,CAAC;IACF,OAAO,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AACrC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { RepoStandard } from './types.js';
2
+ /**
3
+ * Discover repository-standard helpers, wrappers, and patterns
4
+ * by analyzing import frequency and repeated usage patterns.
5
+ *
6
+ * Uses lightweight heuristics:
7
+ * - import frequency analysis
8
+ * - repeated wrapper/helper name detection
9
+ * - callsite clustering in utility/helper directories
10
+ */
11
+ export declare function discoverRepoStandards(cwd: string, changedFiles: string[]): RepoStandard[];
12
+ //# sourceMappingURL=standards-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standards-discovery.d.ts","sourceRoot":"","sources":["../../src/review-intelligence/standards-discovery.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ/C;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EAAE,GACrB,YAAY,EAAE,CAmChB"}
@@ -0,0 +1,221 @@
1
+ import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
2
+ import { join, extname } from 'node:path';
3
+ /** Maximum files to scan during discovery */
4
+ const MAX_DISCOVERY_FILES = 200;
5
+ /** Minimum import/usage count to qualify as a "standard" */
6
+ const MIN_USAGE_COUNT = 2;
7
+ /**
8
+ * Discover repository-standard helpers, wrappers, and patterns
9
+ * by analyzing import frequency and repeated usage patterns.
10
+ *
11
+ * Uses lightweight heuristics:
12
+ * - import frequency analysis
13
+ * - repeated wrapper/helper name detection
14
+ * - callsite clustering in utility/helper directories
15
+ */
16
+ export function discoverRepoStandards(cwd, changedFiles) {
17
+ const standards = [];
18
+ // Collect analyzable files from common helper/utility directories
19
+ const helperDirs = findHelperDirectories(cwd);
20
+ const helperFiles = collectHelperFiles(cwd, helperDirs);
21
+ // Also scan the changed files and their siblings
22
+ const relevantFiles = new Set();
23
+ for (const f of changedFiles) {
24
+ relevantFiles.add(f);
25
+ }
26
+ for (const f of helperFiles) {
27
+ relevantFiles.add(f);
28
+ }
29
+ // Analyze exports from helper files to identify standard patterns
30
+ const exportedHelpers = analyzeHelperExports(cwd, helperFiles);
31
+ // Count usage of these helpers across the codebase
32
+ const usageCounts = countHelperUsage(cwd, exportedHelpers, relevantFiles);
33
+ // Build standards from sufficiently-used helpers
34
+ for (const [helperName, info] of usageCounts.entries()) {
35
+ if (info.count >= MIN_USAGE_COUNT) {
36
+ standards.push({
37
+ helper_name: helperName,
38
+ example_paths: info.definedIn,
39
+ recommendation: `Use ${helperName} from ${info.definedIn[0] ?? 'shared helpers'}`,
40
+ usage_count: info.count,
41
+ });
42
+ }
43
+ }
44
+ return standards;
45
+ }
46
+ /**
47
+ * Find directories likely to contain shared helpers/utilities.
48
+ */
49
+ function findHelperDirectories(cwd) {
50
+ const candidates = [
51
+ 'src/utils',
52
+ 'src/helpers',
53
+ 'src/lib',
54
+ 'src/shared',
55
+ 'src/common',
56
+ 'lib',
57
+ 'utils',
58
+ 'helpers',
59
+ 'shared',
60
+ 'common',
61
+ ];
62
+ const found = [];
63
+ // Also check packages/*/src/{utils,helpers,lib,shared,common}
64
+ const packagesDir = join(cwd, 'packages');
65
+ if (existsSync(packagesDir)) {
66
+ try {
67
+ const pkgs = readdirSync(packagesDir);
68
+ for (const pkg of pkgs) {
69
+ const pkgDir = join('packages', pkg);
70
+ for (const sub of ['src/utils', 'src/helpers', 'src/lib', 'src/shared', 'src/common', 'utils', 'helpers', 'lib']) {
71
+ candidates.push(join(pkgDir, sub));
72
+ }
73
+ }
74
+ }
75
+ catch {
76
+ // Skip if can't read packages dir
77
+ }
78
+ }
79
+ for (const candidate of candidates) {
80
+ const fullPath = join(cwd, candidate);
81
+ if (existsSync(fullPath)) {
82
+ try {
83
+ const stat = statSync(fullPath);
84
+ if (stat.isDirectory()) {
85
+ found.push(candidate);
86
+ }
87
+ }
88
+ catch {
89
+ // Skip inaccessible directories
90
+ }
91
+ }
92
+ }
93
+ return found;
94
+ }
95
+ /**
96
+ * Collect TypeScript/JavaScript files from helper directories.
97
+ */
98
+ function collectHelperFiles(cwd, dirs) {
99
+ const files = [];
100
+ const analyzableExts = new Set(['.ts', '.tsx', '.js', '.jsx', '.mts', '.mjs']);
101
+ for (const dir of dirs) {
102
+ const fullDir = join(cwd, dir);
103
+ try {
104
+ const entries = readdirSync(fullDir);
105
+ for (const entry of entries) {
106
+ if (files.length >= MAX_DISCOVERY_FILES)
107
+ break;
108
+ const ext = extname(entry);
109
+ if (analyzableExts.has(ext) && !entry.endsWith('.test.ts') && !entry.endsWith('.spec.ts')) {
110
+ files.push(join(dir, entry));
111
+ }
112
+ }
113
+ }
114
+ catch {
115
+ // Skip unreadable directories
116
+ }
117
+ }
118
+ return files;
119
+ }
120
+ /**
121
+ * Analyze helper files for exported functions/classes that look like
122
+ * shared utilities.
123
+ */
124
+ function analyzeHelperExports(cwd, helperFiles) {
125
+ const helpers = [];
126
+ for (const filePath of helperFiles) {
127
+ const fullPath = join(cwd, filePath);
128
+ let content;
129
+ try {
130
+ content = readFileSync(fullPath, 'utf-8');
131
+ }
132
+ catch {
133
+ continue;
134
+ }
135
+ // Find exported function/const/class names
136
+ const exportPattern = /export\s+(?:async\s+)?(?:function|const|class)\s+(\w+)/g;
137
+ let match;
138
+ while ((match = exportPattern.exec(content)) !== null) {
139
+ const name = match[1];
140
+ const category = categorizeHelper(name, content);
141
+ helpers.push({ name, filePath, category });
142
+ }
143
+ // Also find export { name } patterns
144
+ const reExportPattern = /export\s*\{([^}]+)\}/g;
145
+ while ((match = reExportPattern.exec(content)) !== null) {
146
+ const names = match[1].split(',').map((n) => n.trim().split(/\s+as\s+/)[0].trim());
147
+ for (const name of names) {
148
+ if (name && /^[a-zA-Z_]/.test(name)) {
149
+ const category = categorizeHelper(name, content);
150
+ helpers.push({ name, filePath, category });
151
+ }
152
+ }
153
+ }
154
+ }
155
+ return helpers;
156
+ }
157
+ function categorizeHelper(name, content) {
158
+ const lower = name.toLowerCase();
159
+ if (lower.includes('fetch') || lower.includes('http') || lower.includes('request') || lower.includes('api')) {
160
+ return 'fetch';
161
+ }
162
+ if (lower.includes('error') || lower.includes('response') || lower.includes('reply')) {
163
+ return 'error';
164
+ }
165
+ if (lower.includes('cache') || lower.includes('redis') || lower.includes('key')) {
166
+ return 'cache';
167
+ }
168
+ if (lower.includes('valid') || lower.includes('schema') || lower.includes('parse')) {
169
+ return 'validation';
170
+ }
171
+ if (lower.includes('rate') || lower.includes('limit') || lower.includes('throttle')) {
172
+ return 'rate_limit';
173
+ }
174
+ // Also check content context
175
+ if (/fetch|axios|http\.request/.test(content))
176
+ return 'fetch';
177
+ if (/redis|cache/.test(content))
178
+ return 'cache';
179
+ return 'general';
180
+ }
181
+ /**
182
+ * Count how many files import or reference each discovered helper.
183
+ */
184
+ function countHelperUsage(cwd, helpers, filesToScan) {
185
+ const usage = new Map();
186
+ // Initialize with helper definitions
187
+ for (const helper of helpers) {
188
+ const existing = usage.get(helper.name);
189
+ if (existing) {
190
+ if (!existing.definedIn.includes(helper.filePath)) {
191
+ existing.definedIn.push(helper.filePath);
192
+ }
193
+ }
194
+ else {
195
+ usage.set(helper.name, { count: 0, definedIn: [helper.filePath] });
196
+ }
197
+ }
198
+ // Count imports/usage across scanned files
199
+ for (const filePath of filesToScan) {
200
+ const fullPath = join(cwd, filePath);
201
+ let content;
202
+ try {
203
+ content = readFileSync(fullPath, 'utf-8');
204
+ }
205
+ catch {
206
+ continue;
207
+ }
208
+ for (const helper of helpers) {
209
+ // Skip counting usage in the file where it's defined
210
+ if (filePath === helper.filePath)
211
+ continue;
212
+ // Check for import or direct usage
213
+ if (content.includes(helper.name)) {
214
+ const info = usage.get(helper.name);
215
+ info.count++;
216
+ }
217
+ }
218
+ }
219
+ return usage;
220
+ }
221
+ //# sourceMappingURL=standards-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standards-discovery.js","sourceRoot":"","sources":["../../src/review-intelligence/standards-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG1C,6CAA6C;AAC7C,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,4DAA4D;AAC5D,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,GAAW,EACX,YAAsB;IAEtB,MAAM,SAAS,GAAmB,EAAE,CAAC;IAErC,kEAAkE;IAClE,MAAM,UAAU,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAExD,iDAAiD;IACjD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;QAC7B,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,kEAAkE;IAClE,MAAM,eAAe,GAAG,oBAAoB,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAE/D,mDAAmD;IACnD,MAAM,WAAW,GAAG,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC;IAE1E,iDAAiD;IACjD,KAAK,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,IAAI,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC;YAClC,SAAS,CAAC,IAAI,CAAC;gBACb,WAAW,EAAE,UAAU;gBACvB,aAAa,EAAE,IAAI,CAAC,SAAS;gBAC7B,cAAc,EAAE,OAAO,UAAU,SAAS,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,gBAAgB,EAAE;gBACjF,WAAW,EAAE,IAAI,CAAC,KAAK;aACxB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAAC,GAAW;IACxC,MAAM,UAAU,GAAG;QACjB,WAAW;QACX,aAAa;QACb,SAAS;QACT,YAAY;QACZ,YAAY;QACZ,KAAK;QACL,OAAO;QACP,SAAS;QACT,QAAQ;QACR,QAAQ;KACT,CAAC;IAEF,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,8DAA8D;IAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC1C,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;YACtC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;gBACrC,KAAK,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;oBACjH,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;IACH,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACtC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAChC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;oBACvB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,gCAAgC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,GAAW,EAAE,IAAc;IACrD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAE/E,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;YACrC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,KAAK,CAAC,MAAM,IAAI,mBAAmB;oBAAE,MAAM;gBAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC3B,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC1F,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;QAChC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAUD;;;GAGG;AACH,SAAS,oBAAoB,CAAC,GAAW,EAAE,WAAqB;IAC9D,MAAM,OAAO,GAAqB,EAAE,CAAC;IAErC,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACrC,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,2CAA2C;QAC3C,MAAM,aAAa,GAAG,yDAAyD,CAAC;QAChF,IAAI,KAA6B,CAAC;QAClC,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACtD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC7C,CAAC;QAED,qCAAqC;QACrC,MAAM,eAAe,GAAG,uBAAuB,CAAC;QAChD,OAAO,CAAC,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACxD,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,CAAC;YACrF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,IAAI,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACpC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBACjD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,OAAe;IACrD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAEjC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5G,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACrF,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAChF,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACnF,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACpF,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,6BAA6B;IAC7B,IAAI,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAC9D,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAEhD,OAAO,SAAS,CAAC;AACnB,CAAC;AAOD;;GAEG;AACH,SAAS,gBAAgB,CACvB,GAAW,EACX,OAAyB,EACzB,WAAwB;IAExB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAC;IAE3C,qCAAqC;IACrC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClD,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACrC,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,qDAAqD;YACrD,IAAI,QAAQ,KAAK,MAAM,CAAC,QAAQ;gBAAE,SAAS;YAE3C,mCAAmC;YACnC,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAE,CAAC;gBACrC,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { DetectedTrigger } from './types.js';
2
+ /**
3
+ * Scan file content for trigger patterns. Returns all detected triggers
4
+ * with file path, line number, and matched text.
5
+ */
6
+ export declare function detectTriggers(filePath: string, content: string): DetectedTrigger[];
7
+ /**
8
+ * Check if triggers indicate typed route definitions (Body/Params/Querystring).
9
+ */
10
+ export declare function isTypedRouteTrigger(trigger: DetectedTrigger): boolean;
11
+ /**
12
+ * Check if triggers indicate outbound I/O.
13
+ */
14
+ export declare function isOutboundIOTrigger(trigger: DetectedTrigger): boolean;
15
+ //# sourceMappingURL=triggers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triggers.d.ts","sourceRoot":"","sources":["../../src/review-intelligence/triggers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,YAAY,CAAC;AA8D/D;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,eAAe,EAAE,CAkCnB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAMrE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAMrE"}
@@ -0,0 +1,104 @@
1
+ const TRIGGER_PATTERNS = [
2
+ // Fastify route definitions
3
+ {
4
+ type: 'fastify_route',
5
+ pattern: /\b(?:server|app|fastify|instance)\s*\.\s*(?:get|post|put|patch|delete|head|options|all|route)\s*[<(]/,
6
+ },
7
+ // Typed route body
8
+ {
9
+ type: 'typed_route_body',
10
+ pattern: /[<{]\s*(?:Body|body)\s*:/,
11
+ },
12
+ // Typed route params
13
+ {
14
+ type: 'typed_route_params',
15
+ pattern: /[<{]\s*(?:Params|params)\s*:/,
16
+ },
17
+ // Typed route query
18
+ {
19
+ type: 'typed_route_query',
20
+ pattern: /[<{]\s*(?:Querystring|querystring|Query|query)\s*:/,
21
+ },
22
+ // fetch() calls
23
+ {
24
+ type: 'fetch_call',
25
+ pattern: /\bfetch\s*\(/,
26
+ },
27
+ // axios calls
28
+ {
29
+ type: 'axios_call',
30
+ pattern: /\baxios\s*(?:\.\s*(?:get|post|put|patch|delete|head|options|request))?\s*\(/,
31
+ },
32
+ // http.request / https.request
33
+ {
34
+ type: 'http_request',
35
+ pattern: /\b(?:https?)\s*\.\s*(?:request|get)\s*\(/,
36
+ },
37
+ // Raw error responses (reply.status(...).send / res.status(...).send / res.status(...).json)
38
+ {
39
+ type: 'raw_error_response',
40
+ pattern: /\b(?:reply|res|response)\s*\.\s*(?:status|code)\s*\(\s*(?:4\d{2}|5\d{2})\s*\)/,
41
+ },
42
+ // Redis/cache key construction
43
+ {
44
+ type: 'redis_cache_key',
45
+ pattern: /\b(?:redis|cache|client)\s*\.\s*(?:get|set|del|hget|hset|sadd|srem|zadd|zrem|expire|ttl)\s*\(\s*[`'"]/,
46
+ },
47
+ // Circuit breaker
48
+ {
49
+ type: 'circuit_breaker',
50
+ pattern: /\b(?:circuitBreaker|circuit_breaker|breaker)\s*\.\s*(?:fire|execute|run|call)\s*\(/,
51
+ },
52
+ ];
53
+ /**
54
+ * Scan file content for trigger patterns. Returns all detected triggers
55
+ * with file path, line number, and matched text.
56
+ */
57
+ export function detectTriggers(filePath, content) {
58
+ const triggers = [];
59
+ const lines = content.split('\n');
60
+ for (let i = 0; i < lines.length; i++) {
61
+ const line = lines[i];
62
+ // Skip comments and import lines
63
+ const trimmed = line.trim();
64
+ if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*')) {
65
+ continue;
66
+ }
67
+ if (trimmed.startsWith('import ') || trimmed.startsWith('import{')) {
68
+ continue;
69
+ }
70
+ for (const tp of TRIGGER_PATTERNS) {
71
+ const match = tp.pattern.exec(line);
72
+ if (match) {
73
+ // Skip if it's a type import or type definition
74
+ if (/\btype\b/.test(line) && !line.includes('('))
75
+ continue;
76
+ triggers.push({
77
+ type: tp.type,
78
+ file: filePath,
79
+ line: i + 1,
80
+ matched_text: match[0],
81
+ context: trimmed.length > 120 ? trimmed.slice(0, 120) + '...' : trimmed,
82
+ });
83
+ }
84
+ }
85
+ }
86
+ return triggers;
87
+ }
88
+ /**
89
+ * Check if triggers indicate typed route definitions (Body/Params/Querystring).
90
+ */
91
+ export function isTypedRouteTrigger(trigger) {
92
+ return (trigger.type === 'typed_route_body' ||
93
+ trigger.type === 'typed_route_params' ||
94
+ trigger.type === 'typed_route_query');
95
+ }
96
+ /**
97
+ * Check if triggers indicate outbound I/O.
98
+ */
99
+ export function isOutboundIOTrigger(trigger) {
100
+ return (trigger.type === 'fetch_call' ||
101
+ trigger.type === 'axios_call' ||
102
+ trigger.type === 'http_request');
103
+ }
104
+ //# sourceMappingURL=triggers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triggers.js","sourceRoot":"","sources":["../../src/review-intelligence/triggers.ts"],"names":[],"mappings":"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"}