@runhalo/engine 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ast-engine.d.ts +60 -0
- package/dist/ast-engine.js +653 -0
- package/dist/ast-engine.js.map +1 -0
- package/dist/context-analyzer.d.ts +209 -0
- package/dist/context-analyzer.js +408 -0
- package/dist/context-analyzer.js.map +1 -0
- package/dist/data-flow-tracer.d.ts +106 -0
- package/dist/data-flow-tracer.js +506 -0
- package/dist/data-flow-tracer.js.map +1 -0
- package/dist/fp-patterns.d.ts +36 -0
- package/dist/fp-patterns.js +426 -0
- package/dist/fp-patterns.js.map +1 -0
- package/dist/frameworks/angular.d.ts +11 -0
- package/dist/frameworks/angular.js +41 -0
- package/dist/frameworks/angular.js.map +1 -0
- package/dist/frameworks/django.d.ts +11 -0
- package/dist/frameworks/django.js +57 -0
- package/dist/frameworks/django.js.map +1 -0
- package/dist/frameworks/index.d.ts +59 -0
- package/dist/frameworks/index.js +99 -0
- package/dist/frameworks/index.js.map +1 -0
- package/dist/frameworks/nextjs.d.ts +11 -0
- package/dist/frameworks/nextjs.js +59 -0
- package/dist/frameworks/nextjs.js.map +1 -0
- package/dist/frameworks/rails.d.ts +11 -0
- package/dist/frameworks/rails.js +58 -0
- package/dist/frameworks/rails.js.map +1 -0
- package/dist/frameworks/react.d.ts +13 -0
- package/dist/frameworks/react.js +36 -0
- package/dist/frameworks/react.js.map +1 -0
- package/dist/frameworks/types.d.ts +29 -0
- package/dist/frameworks/types.js +11 -0
- package/dist/frameworks/types.js.map +1 -0
- package/dist/frameworks/vue.d.ts +9 -0
- package/dist/frameworks/vue.js +39 -0
- package/dist/frameworks/vue.js.map +1 -0
- package/dist/graduation/fp-verdict-logger.d.ts +81 -0
- package/dist/graduation/fp-verdict-logger.js +130 -0
- package/dist/graduation/fp-verdict-logger.js.map +1 -0
- package/dist/graduation/graduation-codifier.d.ts +37 -0
- package/dist/graduation/graduation-codifier.js +205 -0
- package/dist/graduation/graduation-codifier.js.map +1 -0
- package/dist/graduation/graduation-validator.d.ts +73 -0
- package/dist/graduation/graduation-validator.js +204 -0
- package/dist/graduation/graduation-validator.js.map +1 -0
- package/dist/graduation/index.d.ts +71 -0
- package/dist/graduation/index.js +105 -0
- package/dist/graduation/index.js.map +1 -0
- package/dist/graduation/pattern-aggregator.d.ts +77 -0
- package/dist/graduation/pattern-aggregator.js +154 -0
- package/dist/graduation/pattern-aggregator.js.map +1 -0
- package/dist/index.d.ts +99 -0
- package/dist/index.js +718 -61
- package/dist/index.js.map +1 -1
- package/dist/review-board/two-agent-review.d.ts +152 -0
- package/dist/review-board/two-agent-review.js +463 -0
- package/dist/review-board/two-agent-review.js.map +1 -0
- package/dist/scope-analyzer.d.ts +91 -0
- package/dist/scope-analyzer.js +300 -0
- package/dist/scope-analyzer.js.map +1 -0
- package/package.json +9 -2
- package/rules/coppa-tier-1.yaml +17 -10
- package/rules/rules.json +2094 -99
- package/rules/validation-report.json +58 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprint 13a Week 2: Graduation Codifier
|
|
3
|
+
*
|
|
4
|
+
* Stage 4 of the Graduation Pipeline.
|
|
5
|
+
* Takes approved graduation candidates and generates the code changes
|
|
6
|
+
* needed to codify them as permanent engine heuristics.
|
|
7
|
+
*
|
|
8
|
+
* Output: TypeScript code snippets ready to insert into classifyFile()
|
|
9
|
+
* or the scan loop in packages/engine/src/index.ts.
|
|
10
|
+
*
|
|
11
|
+
* This does NOT auto-apply changes. It generates code for Bobby to
|
|
12
|
+
* review and approve before merging.
|
|
13
|
+
*/
|
|
14
|
+
import { GraduationCandidate } from './graduation-validator';
|
|
15
|
+
export interface CodegenResult {
|
|
16
|
+
/** Pattern being codified */
|
|
17
|
+
patternId: string;
|
|
18
|
+
/** Type of change */
|
|
19
|
+
changeType: 'classifyFile_pattern' | 'rule_suppression' | 'scan_loop_check';
|
|
20
|
+
/** Generated code snippet */
|
|
21
|
+
code: string;
|
|
22
|
+
/** Where to insert (file path + approximate location) */
|
|
23
|
+
insertLocation: string;
|
|
24
|
+
/** Human-readable explanation */
|
|
25
|
+
explanation: string;
|
|
26
|
+
/** Test case to validate the change */
|
|
27
|
+
testCase: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generate code for a single graduation candidate.
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateCode(candidate: GraduationCandidate): CodegenResult;
|
|
33
|
+
/**
|
|
34
|
+
* Generate code for all eligible candidates.
|
|
35
|
+
*/
|
|
36
|
+
export declare function generateAllCode(candidates: GraduationCandidate[]): CodegenResult[];
|
|
37
|
+
export declare function formatCodegenReport(results: CodegenResult[]): string;
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Sprint 13a Week 2: Graduation Codifier
|
|
4
|
+
*
|
|
5
|
+
* Stage 4 of the Graduation Pipeline.
|
|
6
|
+
* Takes approved graduation candidates and generates the code changes
|
|
7
|
+
* needed to codify them as permanent engine heuristics.
|
|
8
|
+
*
|
|
9
|
+
* Output: TypeScript code snippets ready to insert into classifyFile()
|
|
10
|
+
* or the scan loop in packages/engine/src/index.ts.
|
|
11
|
+
*
|
|
12
|
+
* This does NOT auto-apply changes. It generates code for Bobby to
|
|
13
|
+
* review and approve before merging.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.generateCode = generateCode;
|
|
17
|
+
exports.generateAllCode = generateAllCode;
|
|
18
|
+
exports.formatCodegenReport = formatCodegenReport;
|
|
19
|
+
// ─── Code Generation ────────────────────────────────────────────────────────
|
|
20
|
+
/**
|
|
21
|
+
* Generate code for a single graduation candidate.
|
|
22
|
+
*/
|
|
23
|
+
function generateCode(candidate) {
|
|
24
|
+
switch (candidate.recommendedHeuristic) {
|
|
25
|
+
case 'file_skip':
|
|
26
|
+
return generateFileSkipCode(candidate);
|
|
27
|
+
case 'rule_suppress':
|
|
28
|
+
return generateRuleSuppressionCode(candidate);
|
|
29
|
+
case 'severity_downgrade':
|
|
30
|
+
return generateSeverityDowngradeCode(candidate);
|
|
31
|
+
case 'context_check':
|
|
32
|
+
return generateContextCheckCode(candidate);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Generate code for all eligible candidates.
|
|
37
|
+
*/
|
|
38
|
+
function generateAllCode(candidates) {
|
|
39
|
+
return candidates
|
|
40
|
+
.filter(c => c.eligible)
|
|
41
|
+
.map(c => generateCode(c));
|
|
42
|
+
}
|
|
43
|
+
// ─── Generators ─────────────────────────────────────────────────────────────
|
|
44
|
+
function generateFileSkipCode(candidate) {
|
|
45
|
+
const pattern = candidate.pattern;
|
|
46
|
+
const patternId = pattern.fpPatternId;
|
|
47
|
+
// Extract path signals from sample paths
|
|
48
|
+
const pathPatterns = inferPathPatterns(pattern.samplePaths);
|
|
49
|
+
const code = `// Graduated from FP pattern: ${patternId}
|
|
50
|
+
// ${pattern.totalDismissals} dismissals, avg confidence ${pattern.avgConfidence}
|
|
51
|
+
// Source: Graduation Pipeline Sprint 13a
|
|
52
|
+
if (${pathPatterns.map(p => `normalizedPath.includes('${p}')`).join(' || ')}) {
|
|
53
|
+
return {
|
|
54
|
+
...baseClassification,
|
|
55
|
+
shouldSkip: true,
|
|
56
|
+
skipReason: '${patternId} (graduated)',
|
|
57
|
+
};
|
|
58
|
+
}`;
|
|
59
|
+
return {
|
|
60
|
+
patternId,
|
|
61
|
+
changeType: 'classifyFile_pattern',
|
|
62
|
+
code,
|
|
63
|
+
insertLocation: 'packages/engine/src/index.ts → classifyFile() function, before return statement',
|
|
64
|
+
explanation: `Skip files matching ${patternId} pattern. Based on ${pattern.totalDismissals} consistent dismissals across ${pattern.uniqueScans} scans with avg confidence ${pattern.avgConfidence}.`,
|
|
65
|
+
testCase: generateTestCase(patternId, pattern.samplePaths[0] || 'test/path', 'shouldSkip', true),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function generateRuleSuppressionCode(candidate) {
|
|
69
|
+
const pattern = candidate.pattern;
|
|
70
|
+
const patternId = pattern.fpPatternId;
|
|
71
|
+
const rules = pattern.affectedRules;
|
|
72
|
+
const code = `// Graduated from FP pattern: ${patternId}
|
|
73
|
+
// ${pattern.totalDismissals} dismissals, avg confidence ${pattern.avgConfidence}
|
|
74
|
+
const ${camelCase(patternId)}_SUPPRESS_RULES = new Set(${JSON.stringify(rules)});
|
|
75
|
+
|
|
76
|
+
// In scan loop, after classification:
|
|
77
|
+
if (classification.${inferClassificationFlag(patternId)} && ${camelCase(patternId)}_SUPPRESS_RULES.has(rule.id)) {
|
|
78
|
+
continue; // Skip this rule for ${patternId} files
|
|
79
|
+
}`;
|
|
80
|
+
return {
|
|
81
|
+
patternId,
|
|
82
|
+
changeType: 'rule_suppression',
|
|
83
|
+
code,
|
|
84
|
+
insertLocation: 'packages/engine/src/index.ts → scan loop, rule iteration block',
|
|
85
|
+
explanation: `Suppress rules [${rules.join(', ')}] when ${patternId} pattern detected. Based on ${pattern.totalDismissals} dismissals.`,
|
|
86
|
+
testCase: generateTestCase(patternId, pattern.samplePaths[0] || 'test/path', 'violations.length', 0),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function generateSeverityDowngradeCode(candidate) {
|
|
90
|
+
const pattern = candidate.pattern;
|
|
91
|
+
const patternId = pattern.fpPatternId;
|
|
92
|
+
const code = `// Graduated from FP pattern: ${patternId}
|
|
93
|
+
// ${pattern.totalDismissals} dismissals as downgrade, avg confidence ${pattern.avgConfidence}
|
|
94
|
+
if (${inferCondition(patternId)}) {
|
|
95
|
+
violation.severity = 'info'; // Downgraded from ${patternId}
|
|
96
|
+
violation.message += ' [Severity downgraded: ${patternId}]';
|
|
97
|
+
}`;
|
|
98
|
+
return {
|
|
99
|
+
patternId,
|
|
100
|
+
changeType: 'scan_loop_check',
|
|
101
|
+
code,
|
|
102
|
+
insertLocation: 'packages/engine/src/index.ts → after violation creation, before push to results',
|
|
103
|
+
explanation: `Downgrade severity for ${patternId} pattern. Mitigating factors present but not full dismissal.`,
|
|
104
|
+
testCase: generateTestCase(patternId, pattern.samplePaths[0] || 'test/path', 'severity', 'info'),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function generateContextCheckCode(candidate) {
|
|
108
|
+
const pattern = candidate.pattern;
|
|
109
|
+
const patternId = pattern.fpPatternId;
|
|
110
|
+
const code = `// Graduated from FP pattern: ${patternId}
|
|
111
|
+
// ${pattern.totalDismissals} dismissals, avg confidence ${pattern.avgConfidence}
|
|
112
|
+
// NOTE: This pattern requires surrounding code analysis.
|
|
113
|
+
// Consider adding to AI Review Board FP checklist instead of engine heuristic.
|
|
114
|
+
//
|
|
115
|
+
// Candidate code signals to check:
|
|
116
|
+
// ${pattern.fpReason || 'See FP library for details'}
|
|
117
|
+
//
|
|
118
|
+
// TODO: Implement context check or add to AI Review Board FP library`;
|
|
119
|
+
return {
|
|
120
|
+
patternId,
|
|
121
|
+
changeType: 'scan_loop_check',
|
|
122
|
+
code,
|
|
123
|
+
insertLocation: 'packages/engine/src/index.ts OR supabase/functions/ai-review/index.ts (FP checklists)',
|
|
124
|
+
explanation: `Context-dependent FP pattern. May be better served by expanding the AI Review Board FP checklist rather than engine heuristic.`,
|
|
125
|
+
testCase: `// Manual test: verify ${patternId} pattern is dismissed by Review Board`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
129
|
+
function inferPathPatterns(samplePaths) {
|
|
130
|
+
if (samplePaths.length === 0)
|
|
131
|
+
return ['UNKNOWN_PATTERN'];
|
|
132
|
+
// Find common path segments
|
|
133
|
+
const segments = samplePaths.flatMap(p => p.split('/'));
|
|
134
|
+
const commonSegments = new Map();
|
|
135
|
+
for (const seg of segments) {
|
|
136
|
+
if (seg && seg.length > 2 && !seg.includes('.')) {
|
|
137
|
+
commonSegments.set(seg, (commonSegments.get(seg) || 0) + 1);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Return segments that appear in multiple paths
|
|
141
|
+
const patterns = [...commonSegments.entries()]
|
|
142
|
+
.filter(([, count]) => count >= Math.max(samplePaths.length / 2, 1))
|
|
143
|
+
.map(([seg]) => seg)
|
|
144
|
+
.slice(0, 3);
|
|
145
|
+
return patterns.length > 0 ? patterns : ['REVIEW_PATH_PATTERN'];
|
|
146
|
+
}
|
|
147
|
+
function inferClassificationFlag(patternId) {
|
|
148
|
+
if (patternId.includes('admin'))
|
|
149
|
+
return 'isAdmin';
|
|
150
|
+
if (patternId.includes('consent'))
|
|
151
|
+
return 'isConsent';
|
|
152
|
+
if (patternId.includes('test') || patternId.includes('mock'))
|
|
153
|
+
return 'isTest';
|
|
154
|
+
if (patternId.includes('vendor'))
|
|
155
|
+
return 'isVendor';
|
|
156
|
+
if (patternId.includes('doc'))
|
|
157
|
+
return 'isDocGenerator';
|
|
158
|
+
return 'shouldSkip';
|
|
159
|
+
}
|
|
160
|
+
function inferCondition(patternId) {
|
|
161
|
+
if (patternId.includes('framework'))
|
|
162
|
+
return `classification.language && ['jsx', 'tsx', 'vue', 'svelte'].includes(fileExt)`;
|
|
163
|
+
if (patternId.includes('sanitized'))
|
|
164
|
+
return `codeContent.includes('DOMPurify') || codeContent.includes('sanitize(')`;
|
|
165
|
+
if (patternId.includes('error-monitoring'))
|
|
166
|
+
return `codeContent.includes('Sentry') || codeContent.includes('Bugsnag')`;
|
|
167
|
+
return `/* TODO: define condition for ${patternId} */`;
|
|
168
|
+
}
|
|
169
|
+
function camelCase(str) {
|
|
170
|
+
return str.replace(/[-_](\w)/g, (_, c) => c.toUpperCase());
|
|
171
|
+
}
|
|
172
|
+
function generateTestCase(patternId, samplePath, assertion, expected) {
|
|
173
|
+
return `test('${patternId} graduated pattern', () => {
|
|
174
|
+
const result = classifyFile('${samplePath}');
|
|
175
|
+
expect(result.${assertion}).toBe(${JSON.stringify(expected)});
|
|
176
|
+
});`;
|
|
177
|
+
}
|
|
178
|
+
// ─── Report ─────────────────────────────────────────────────────────────────
|
|
179
|
+
function formatCodegenReport(results) {
|
|
180
|
+
const lines = [
|
|
181
|
+
'═══ Graduation Codifier — Generated Code ═══',
|
|
182
|
+
'',
|
|
183
|
+
`Total patterns codified: ${results.length}`,
|
|
184
|
+
'',
|
|
185
|
+
];
|
|
186
|
+
for (const result of results) {
|
|
187
|
+
lines.push(`── ${result.patternId} (${result.changeType}) ──`);
|
|
188
|
+
lines.push(result.explanation);
|
|
189
|
+
lines.push('');
|
|
190
|
+
lines.push('Location: ' + result.insertLocation);
|
|
191
|
+
lines.push('');
|
|
192
|
+
lines.push('Code:');
|
|
193
|
+
lines.push('```typescript');
|
|
194
|
+
lines.push(result.code);
|
|
195
|
+
lines.push('```');
|
|
196
|
+
lines.push('');
|
|
197
|
+
lines.push('Test:');
|
|
198
|
+
lines.push('```typescript');
|
|
199
|
+
lines.push(result.testCase);
|
|
200
|
+
lines.push('```');
|
|
201
|
+
lines.push('');
|
|
202
|
+
}
|
|
203
|
+
return lines.join('\n');
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=graduation-codifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graduation-codifier.js","sourceRoot":"","sources":["../../src/graduation/graduation-codifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprint 13a Week 2: Graduation Validator
|
|
3
|
+
*
|
|
4
|
+
* Stage 3 of the Graduation Pipeline.
|
|
5
|
+
* Evaluates aggregated FP patterns against graduation criteria.
|
|
6
|
+
* Patterns that meet all thresholds become candidates for codification
|
|
7
|
+
* as permanent engine heuristics.
|
|
8
|
+
*
|
|
9
|
+
* Graduation criteria (configurable):
|
|
10
|
+
* - Minimum N dismissals across scans
|
|
11
|
+
* - Average confidence above threshold
|
|
12
|
+
* - Zero (or near-zero) false confirmations
|
|
13
|
+
* - Minimum precision when validated against ground truth
|
|
14
|
+
* - Appeared in minimum N unique scans
|
|
15
|
+
*/
|
|
16
|
+
import { PatternStats, AggregationResult } from './pattern-aggregator';
|
|
17
|
+
export interface GraduationCriteria {
|
|
18
|
+
/** Minimum total dismissals required */
|
|
19
|
+
minDismissals: number;
|
|
20
|
+
/** Minimum average confidence (1-10) */
|
|
21
|
+
minAvgConfidence: number;
|
|
22
|
+
/** Maximum allowed false confirmations (ground truth contradictions) */
|
|
23
|
+
maxFalseConfirmations: number;
|
|
24
|
+
/** Minimum precision when validated against ground truth (0-1) */
|
|
25
|
+
minPrecision: number;
|
|
26
|
+
/** Minimum unique scans the pattern appeared in */
|
|
27
|
+
minUniqueScans: number;
|
|
28
|
+
}
|
|
29
|
+
export interface GraduationCandidate {
|
|
30
|
+
/** The FP pattern being evaluated */
|
|
31
|
+
pattern: PatternStats;
|
|
32
|
+
/** Whether this pattern meets all criteria */
|
|
33
|
+
eligible: boolean;
|
|
34
|
+
/** Which criteria passed/failed */
|
|
35
|
+
criteriaResults: {
|
|
36
|
+
criterion: string;
|
|
37
|
+
passed: boolean;
|
|
38
|
+
actual: number;
|
|
39
|
+
required: number;
|
|
40
|
+
}[];
|
|
41
|
+
/** Recommended heuristic type for codification */
|
|
42
|
+
recommendedHeuristic: 'file_skip' | 'rule_suppress' | 'severity_downgrade' | 'context_check';
|
|
43
|
+
/** Generated heuristic description */
|
|
44
|
+
heuristicDescription: string;
|
|
45
|
+
/** Priority score (higher = graduate first) */
|
|
46
|
+
priorityScore: number;
|
|
47
|
+
}
|
|
48
|
+
export interface GraduationReport {
|
|
49
|
+
/** When validation was run */
|
|
50
|
+
validatedAt: string;
|
|
51
|
+
/** Criteria used */
|
|
52
|
+
criteria: GraduationCriteria;
|
|
53
|
+
/** All candidates evaluated */
|
|
54
|
+
candidates: GraduationCandidate[];
|
|
55
|
+
/** Eligible candidates only */
|
|
56
|
+
eligible: GraduationCandidate[];
|
|
57
|
+
/** Nearly eligible (missing 1 criterion) */
|
|
58
|
+
nearMiss: GraduationCandidate[];
|
|
59
|
+
/** Summary stats */
|
|
60
|
+
summary: {
|
|
61
|
+
totalPatterns: number;
|
|
62
|
+
eligibleCount: number;
|
|
63
|
+
nearMissCount: number;
|
|
64
|
+
rejectedCount: number;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export declare const DEFAULT_GRADUATION_CRITERIA: GraduationCriteria;
|
|
68
|
+
export declare const MVP_GRADUATION_CRITERIA: GraduationCriteria;
|
|
69
|
+
/**
|
|
70
|
+
* Evaluate FP patterns against graduation criteria.
|
|
71
|
+
*/
|
|
72
|
+
export declare function validateGraduation(aggregation: AggregationResult, criteria?: GraduationCriteria, groundTruthPrecision?: Map<string, number>): GraduationReport;
|
|
73
|
+
export declare function formatGraduationReport(report: GraduationReport): string;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Sprint 13a Week 2: Graduation Validator
|
|
4
|
+
*
|
|
5
|
+
* Stage 3 of the Graduation Pipeline.
|
|
6
|
+
* Evaluates aggregated FP patterns against graduation criteria.
|
|
7
|
+
* Patterns that meet all thresholds become candidates for codification
|
|
8
|
+
* as permanent engine heuristics.
|
|
9
|
+
*
|
|
10
|
+
* Graduation criteria (configurable):
|
|
11
|
+
* - Minimum N dismissals across scans
|
|
12
|
+
* - Average confidence above threshold
|
|
13
|
+
* - Zero (or near-zero) false confirmations
|
|
14
|
+
* - Minimum precision when validated against ground truth
|
|
15
|
+
* - Appeared in minimum N unique scans
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.MVP_GRADUATION_CRITERIA = exports.DEFAULT_GRADUATION_CRITERIA = void 0;
|
|
19
|
+
exports.validateGraduation = validateGraduation;
|
|
20
|
+
exports.formatGraduationReport = formatGraduationReport;
|
|
21
|
+
// ─── Default Criteria ───────────────────────────────────────────────────────
|
|
22
|
+
exports.DEFAULT_GRADUATION_CRITERIA = {
|
|
23
|
+
minDismissals: 15,
|
|
24
|
+
minAvgConfidence: 7.0,
|
|
25
|
+
maxFalseConfirmations: 0,
|
|
26
|
+
minPrecision: 0.95,
|
|
27
|
+
minUniqueScans: 2,
|
|
28
|
+
};
|
|
29
|
+
// Relaxed criteria for MVP (smaller dataset)
|
|
30
|
+
exports.MVP_GRADUATION_CRITERIA = {
|
|
31
|
+
minDismissals: 5,
|
|
32
|
+
minAvgConfidence: 6.0,
|
|
33
|
+
maxFalseConfirmations: 1,
|
|
34
|
+
minPrecision: 0.90,
|
|
35
|
+
minUniqueScans: 1,
|
|
36
|
+
};
|
|
37
|
+
// ─── Validator ──────────────────────────────────────────────────────────────
|
|
38
|
+
/**
|
|
39
|
+
* Evaluate FP patterns against graduation criteria.
|
|
40
|
+
*/
|
|
41
|
+
function validateGraduation(aggregation, criteria = exports.DEFAULT_GRADUATION_CRITERIA, groundTruthPrecision // patternId → precision from ground truth
|
|
42
|
+
) {
|
|
43
|
+
const candidates = [];
|
|
44
|
+
for (const pattern of aggregation.patterns) {
|
|
45
|
+
const precision = groundTruthPrecision?.get(pattern.fpPatternId) ?? 1.0;
|
|
46
|
+
const criteriaResults = [
|
|
47
|
+
{
|
|
48
|
+
criterion: 'minDismissals',
|
|
49
|
+
passed: pattern.totalDismissals >= criteria.minDismissals,
|
|
50
|
+
actual: pattern.totalDismissals,
|
|
51
|
+
required: criteria.minDismissals,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
criterion: 'minAvgConfidence',
|
|
55
|
+
passed: pattern.avgConfidence >= criteria.minAvgConfidence,
|
|
56
|
+
actual: pattern.avgConfidence,
|
|
57
|
+
required: criteria.minAvgConfidence,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
criterion: 'maxFalseConfirmations',
|
|
61
|
+
passed: pattern.falseConfirmations <= criteria.maxFalseConfirmations,
|
|
62
|
+
actual: pattern.falseConfirmations,
|
|
63
|
+
required: criteria.maxFalseConfirmations,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
criterion: 'minPrecision',
|
|
67
|
+
passed: precision >= criteria.minPrecision,
|
|
68
|
+
actual: Math.round(precision * 100) / 100,
|
|
69
|
+
required: criteria.minPrecision,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
criterion: 'minUniqueScans',
|
|
73
|
+
passed: pattern.uniqueScans >= criteria.minUniqueScans,
|
|
74
|
+
actual: pattern.uniqueScans,
|
|
75
|
+
required: criteria.minUniqueScans,
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
const eligible = criteriaResults.every(r => r.passed);
|
|
79
|
+
const failedCount = criteriaResults.filter(r => !r.passed).length;
|
|
80
|
+
// Determine recommended heuristic type
|
|
81
|
+
const recommendedHeuristic = inferHeuristicType(pattern);
|
|
82
|
+
const heuristicDescription = generateHeuristicDescription(pattern, recommendedHeuristic);
|
|
83
|
+
// Priority score: higher = more confident graduation candidate
|
|
84
|
+
const priorityScore = calculatePriorityScore(pattern, precision);
|
|
85
|
+
candidates.push({
|
|
86
|
+
pattern,
|
|
87
|
+
eligible,
|
|
88
|
+
criteriaResults,
|
|
89
|
+
recommendedHeuristic,
|
|
90
|
+
heuristicDescription,
|
|
91
|
+
priorityScore,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// Sort by priority score
|
|
95
|
+
candidates.sort((a, b) => b.priorityScore - a.priorityScore);
|
|
96
|
+
const eligible = candidates.filter(c => c.eligible);
|
|
97
|
+
const nearMiss = candidates.filter(c => {
|
|
98
|
+
const failed = c.criteriaResults.filter(r => !r.passed).length;
|
|
99
|
+
return !c.eligible && failed === 1;
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
validatedAt: new Date().toISOString(),
|
|
103
|
+
criteria,
|
|
104
|
+
candidates,
|
|
105
|
+
eligible,
|
|
106
|
+
nearMiss,
|
|
107
|
+
summary: {
|
|
108
|
+
totalPatterns: candidates.length,
|
|
109
|
+
eligibleCount: eligible.length,
|
|
110
|
+
nearMissCount: nearMiss.length,
|
|
111
|
+
rejectedCount: candidates.length - eligible.length - nearMiss.length,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// ─── Heuristic Inference ────────────────────────────────────────────────────
|
|
116
|
+
function inferHeuristicType(pattern) {
|
|
117
|
+
const patternId = pattern.fpPatternId.toLowerCase();
|
|
118
|
+
// File-level skip patterns
|
|
119
|
+
if (patternId.includes('vendor') ||
|
|
120
|
+
patternId.includes('test') ||
|
|
121
|
+
patternId.includes('doc-generator') ||
|
|
122
|
+
patternId.includes('migration') ||
|
|
123
|
+
patternId.includes('fixture') ||
|
|
124
|
+
patternId.includes('mock') ||
|
|
125
|
+
patternId.includes('build-output') ||
|
|
126
|
+
patternId.includes('type-def')) {
|
|
127
|
+
return 'file_skip';
|
|
128
|
+
}
|
|
129
|
+
// Rule suppression patterns (specific rule on specific file types)
|
|
130
|
+
if (patternId.includes('admin') ||
|
|
131
|
+
patternId.includes('consent') ||
|
|
132
|
+
patternId.includes('playback') ||
|
|
133
|
+
patternId.includes('deletion')) {
|
|
134
|
+
return 'rule_suppress';
|
|
135
|
+
}
|
|
136
|
+
// Severity downgrade patterns
|
|
137
|
+
if (patternId.includes('framework') ||
|
|
138
|
+
patternId.includes('sanitized') ||
|
|
139
|
+
patternId.includes('error-monitoring')) {
|
|
140
|
+
return 'severity_downgrade';
|
|
141
|
+
}
|
|
142
|
+
// Context check (needs surrounding code analysis)
|
|
143
|
+
return 'context_check';
|
|
144
|
+
}
|
|
145
|
+
function generateHeuristicDescription(pattern, type) {
|
|
146
|
+
const rules = pattern.affectedRules.join(', ');
|
|
147
|
+
switch (type) {
|
|
148
|
+
case 'file_skip':
|
|
149
|
+
return `Add path pattern to classifyFile() → shouldSkip=true. Affects: ${rules}. Pattern: ${pattern.fpPatternId}`;
|
|
150
|
+
case 'rule_suppress':
|
|
151
|
+
return `Add to rule-specific suppression list (similar to TEST_FP_RULES). Suppress ${rules} when pattern "${pattern.fpPatternId}" matches.`;
|
|
152
|
+
case 'severity_downgrade':
|
|
153
|
+
return `Add severity downgrade logic for ${rules} when "${pattern.fpPatternId}" context detected. Downgrade from 'warning' to 'info'.`;
|
|
154
|
+
case 'context_check':
|
|
155
|
+
return `Add code context check in scan loop: when "${pattern.fpPatternId}" signals detected in surrounding code, suppress ${rules}.`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function calculatePriorityScore(pattern, precision) {
|
|
159
|
+
// Weighted score:
|
|
160
|
+
// - 40% based on total dismissals (capped at 50)
|
|
161
|
+
// - 30% based on average confidence
|
|
162
|
+
// - 20% based on precision
|
|
163
|
+
// - 10% based on unique scans
|
|
164
|
+
const dismissalScore = Math.min(pattern.totalDismissals / 50, 1) * 40;
|
|
165
|
+
const confidenceScore = (pattern.avgConfidence / 10) * 30;
|
|
166
|
+
const precisionScore = precision * 20;
|
|
167
|
+
const scanScore = Math.min(pattern.uniqueScans / 5, 1) * 10;
|
|
168
|
+
return Math.round((dismissalScore + confidenceScore + precisionScore + scanScore) * 10) / 10;
|
|
169
|
+
}
|
|
170
|
+
// ─── Report Formatting ──────────────────────────────────────────────────────
|
|
171
|
+
function formatGraduationReport(report) {
|
|
172
|
+
const lines = [
|
|
173
|
+
'═══ Graduation Pipeline — Validation Report ═══',
|
|
174
|
+
'',
|
|
175
|
+
`Validated at: ${report.validatedAt}`,
|
|
176
|
+
`Criteria: minDismissals=${report.criteria.minDismissals}, minConf=${report.criteria.minAvgConfidence}, maxFalseConf=${report.criteria.maxFalseConfirmations}, minPrecision=${report.criteria.minPrecision}, minScans=${report.criteria.minUniqueScans}`,
|
|
177
|
+
'',
|
|
178
|
+
`Total patterns: ${report.summary.totalPatterns}`,
|
|
179
|
+
`Eligible for graduation: ${report.summary.eligibleCount}`,
|
|
180
|
+
`Near miss (1 criterion short): ${report.summary.nearMissCount}`,
|
|
181
|
+
`Rejected: ${report.summary.rejectedCount}`,
|
|
182
|
+
];
|
|
183
|
+
if (report.eligible.length > 0) {
|
|
184
|
+
lines.push('');
|
|
185
|
+
lines.push('── ELIGIBLE FOR GRADUATION ──');
|
|
186
|
+
for (const c of report.eligible) {
|
|
187
|
+
lines.push(` [${c.priorityScore}] ${c.pattern.fpPatternId}`);
|
|
188
|
+
lines.push(` Dismissals: ${c.pattern.totalDismissals}, Avg Conf: ${c.pattern.avgConfidence}, Scans: ${c.pattern.uniqueScans}`);
|
|
189
|
+
lines.push(` Rules: ${c.pattern.affectedRules.join(', ')}`);
|
|
190
|
+
lines.push(` Action: ${c.heuristicDescription}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (report.nearMiss.length > 0) {
|
|
194
|
+
lines.push('');
|
|
195
|
+
lines.push('── NEAR MISS (1 criterion short) ──');
|
|
196
|
+
for (const c of report.nearMiss) {
|
|
197
|
+
const failed = c.criteriaResults.find(r => !r.passed);
|
|
198
|
+
lines.push(` ${c.pattern.fpPatternId}`);
|
|
199
|
+
lines.push(` Missing: ${failed?.criterion} (actual: ${failed?.actual}, required: ${failed?.required})`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return lines.join('\n');
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=graduation-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graduation-validator.js","sourceRoot":"","sources":["../../src/graduation/graduation-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graduation Pipeline — Sprint 13a Week 2
|
|
3
|
+
*
|
|
4
|
+
* Four-stage pipeline that transforms AI Review Board FP verdicts
|
|
5
|
+
* into permanent engine heuristics:
|
|
6
|
+
*
|
|
7
|
+
* Stage 1: COLLECT — Log each verdict to structured JSONL
|
|
8
|
+
* Stage 2: AGGREGATE — Compute per-pattern statistics across scans
|
|
9
|
+
* Stage 3: VALIDATE — Check graduation criteria (dismissals, confidence, precision)
|
|
10
|
+
* Stage 4: CODIFY — Generate engine heuristic code for approved patterns
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* import { GraduationPipeline } from './graduation';
|
|
14
|
+
* const pipeline = new GraduationPipeline({ logDir: './verdict-logs' });
|
|
15
|
+
* pipeline.logVerdict(verdict); // Stage 1
|
|
16
|
+
* const stats = pipeline.aggregate(); // Stage 2
|
|
17
|
+
* const candidates = pipeline.validate(); // Stage 3
|
|
18
|
+
* const code = pipeline.codify(); // Stage 4
|
|
19
|
+
*/
|
|
20
|
+
export { FPVerdictLogger, VerdictLogEntry } from './fp-verdict-logger';
|
|
21
|
+
export { aggregatePatterns, aggregateFromDirectory, formatAggregationReport, PatternStats, AggregationResult, } from './pattern-aggregator';
|
|
22
|
+
export { validateGraduation, formatGraduationReport, DEFAULT_GRADUATION_CRITERIA, MVP_GRADUATION_CRITERIA, GraduationCriteria, GraduationCandidate, GraduationReport, } from './graduation-validator';
|
|
23
|
+
export { generateCode, generateAllCode, formatCodegenReport, CodegenResult, } from './graduation-codifier';
|
|
24
|
+
import { FPVerdictLogger, VerdictLogEntry } from './fp-verdict-logger';
|
|
25
|
+
import { AggregationResult } from './pattern-aggregator';
|
|
26
|
+
import { GraduationCriteria, GraduationReport } from './graduation-validator';
|
|
27
|
+
import { CodegenResult } from './graduation-codifier';
|
|
28
|
+
export interface GraduationPipelineConfig {
|
|
29
|
+
/** Directory for verdict JSONL logs */
|
|
30
|
+
logDir: string;
|
|
31
|
+
/** Known FP pattern IDs from the static library */
|
|
32
|
+
knownPatternIds?: Set<string>;
|
|
33
|
+
/** Graduation criteria (defaults to MVP criteria) */
|
|
34
|
+
criteria?: GraduationCriteria;
|
|
35
|
+
/** Ground truth precision per pattern (from regression suite) */
|
|
36
|
+
groundTruthPrecision?: Map<string, number>;
|
|
37
|
+
}
|
|
38
|
+
export declare class GraduationPipeline {
|
|
39
|
+
private config;
|
|
40
|
+
private logger;
|
|
41
|
+
constructor(config: GraduationPipelineConfig);
|
|
42
|
+
/**
|
|
43
|
+
* Initialize logger for a new scan.
|
|
44
|
+
*/
|
|
45
|
+
startScan(scanId: string, promptVersion?: string): FPVerdictLogger;
|
|
46
|
+
/**
|
|
47
|
+
* Log a single verdict (convenience method).
|
|
48
|
+
*/
|
|
49
|
+
logVerdict(entry: Omit<VerdictLogEntry, 'timestamp' | 'scanId' | 'promptVersion'>): void;
|
|
50
|
+
/**
|
|
51
|
+
* Aggregate all verdict logs in the log directory.
|
|
52
|
+
*/
|
|
53
|
+
aggregate(): AggregationResult;
|
|
54
|
+
/**
|
|
55
|
+
* Validate aggregated patterns against graduation criteria.
|
|
56
|
+
*/
|
|
57
|
+
validate(aggregation?: AggregationResult): GraduationReport;
|
|
58
|
+
/**
|
|
59
|
+
* Generate code for all eligible graduation candidates.
|
|
60
|
+
*/
|
|
61
|
+
codify(report?: GraduationReport): CodegenResult[];
|
|
62
|
+
/**
|
|
63
|
+
* Run the full pipeline (stages 2-4) on existing log data.
|
|
64
|
+
* Stage 1 (logging) happens during scans, not here.
|
|
65
|
+
*/
|
|
66
|
+
runPipeline(): {
|
|
67
|
+
aggregation: AggregationResult;
|
|
68
|
+
graduation: GraduationReport;
|
|
69
|
+
codegen: CodegenResult[];
|
|
70
|
+
};
|
|
71
|
+
}
|