@kernlang/evolve 3.0.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/LICENSE +661 -0
- package/dist/concept-gap-adapter.d.ts +17 -0
- package/dist/concept-gap-adapter.js +43 -0
- package/dist/concept-gap-adapter.js.map +1 -0
- package/dist/detector-registry.d.ts +31 -0
- package/dist/detector-registry.js +89 -0
- package/dist/detector-registry.js.map +1 -0
- package/dist/detectors/animation.d.ts +5 -0
- package/dist/detectors/animation.js +67 -0
- package/dist/detectors/animation.js.map +1 -0
- package/dist/detectors/data-fetching.d.ts +5 -0
- package/dist/detectors/data-fetching.js +117 -0
- package/dist/detectors/data-fetching.js.map +1 -0
- package/dist/detectors/express-middleware.d.ts +5 -0
- package/dist/detectors/express-middleware.js +52 -0
- package/dist/detectors/express-middleware.js.map +1 -0
- package/dist/detectors/react-forms.d.ts +5 -0
- package/dist/detectors/react-forms.js +89 -0
- package/dist/detectors/react-forms.js.map +1 -0
- package/dist/detectors/schema-validation.d.ts +5 -0
- package/dist/detectors/schema-validation.js +92 -0
- package/dist/detectors/schema-validation.js.map +1 -0
- package/dist/detectors/state-mgmt.d.ts +5 -0
- package/dist/detectors/state-mgmt.js +102 -0
- package/dist/detectors/state-mgmt.js.map +1 -0
- package/dist/detectors/structural.d.ts +10 -0
- package/dist/detectors/structural.js +271 -0
- package/dist/detectors/structural.js.map +1 -0
- package/dist/detectors/testing.d.ts +5 -0
- package/dist/detectors/testing.js +56 -0
- package/dist/detectors/testing.js.map +1 -0
- package/dist/detectors/vue-composables.d.ts +5 -0
- package/dist/detectors/vue-composables.js +57 -0
- package/dist/detectors/vue-composables.js.map +1 -0
- package/dist/evolve-dedup.d.ts +12 -0
- package/dist/evolve-dedup.js +50 -0
- package/dist/evolve-dedup.js.map +1 -0
- package/dist/evolve-rollback.d.ts +58 -0
- package/dist/evolve-rollback.js +242 -0
- package/dist/evolve-rollback.js.map +1 -0
- package/dist/evolve-runner.d.ts +22 -0
- package/dist/evolve-runner.js +183 -0
- package/dist/evolve-runner.js.map +1 -0
- package/dist/evolve-validator-v4.d.ts +11 -0
- package/dist/evolve-validator-v4.js +253 -0
- package/dist/evolve-validator-v4.js.map +1 -0
- package/dist/evolved-node-loader.d.ts +61 -0
- package/dist/evolved-node-loader.js +228 -0
- package/dist/evolved-node-loader.js.map +1 -0
- package/dist/evolved-types.d.ts +110 -0
- package/dist/evolved-types.js +8 -0
- package/dist/evolved-types.js.map +1 -0
- package/dist/expressibility-scorer.d.ts +19 -0
- package/dist/expressibility-scorer.js +78 -0
- package/dist/expressibility-scorer.js.map +1 -0
- package/dist/gap-detector.d.ts +26 -0
- package/dist/gap-detector.js +141 -0
- package/dist/gap-detector.js.map +1 -0
- package/dist/golden-test-runner.d.ts +27 -0
- package/dist/golden-test-runner.js +120 -0
- package/dist/golden-test-runner.js.map +1 -0
- package/dist/graduation.d.ts +36 -0
- package/dist/graduation.js +175 -0
- package/dist/graduation.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/llm-discovery.d.ts +55 -0
- package/dist/llm-discovery.js +352 -0
- package/dist/llm-discovery.js.map +1 -0
- package/dist/llm-provider.d.ts +35 -0
- package/dist/llm-provider.js +143 -0
- package/dist/llm-provider.js.map +1 -0
- package/dist/node-governance.d.ts +23 -0
- package/dist/node-governance.js +45 -0
- package/dist/node-governance.js.map +1 -0
- package/dist/node-proposer.d.ts +27 -0
- package/dist/node-proposer.js +127 -0
- package/dist/node-proposer.js.map +1 -0
- package/dist/node-validator.d.ts +16 -0
- package/dist/node-validator.js +74 -0
- package/dist/node-validator.js.map +1 -0
- package/dist/pattern-analyzer.d.ts +28 -0
- package/dist/pattern-analyzer.js +181 -0
- package/dist/pattern-analyzer.js.map +1 -0
- package/dist/quality-scorer.d.ts +16 -0
- package/dist/quality-scorer.js +79 -0
- package/dist/quality-scorer.js.map +1 -0
- package/dist/sandboxed-generator.d.ts +26 -0
- package/dist/sandboxed-generator.js +133 -0
- package/dist/sandboxed-generator.js.map +1 -0
- package/dist/staging.d.ts +81 -0
- package/dist/staging.js +414 -0
- package/dist/staging.js.map +1 -0
- package/dist/template-proposer.d.ts +24 -0
- package/dist/template-proposer.js +103 -0
- package/dist/template-proposer.js.map +1 -0
- package/dist/template-validator.d.ts +18 -0
- package/dist/template-validator.js +174 -0
- package/dist/template-validator.js.map +1 -0
- package/dist/types.d.ts +169 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +27 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern Analyzer — Phase 2 of the evolve pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Groups gaps by structural hash, deduplicates, scores, and selects
|
|
5
|
+
* representative examples for template generation.
|
|
6
|
+
*/
|
|
7
|
+
import { createHash } from 'crypto';
|
|
8
|
+
import { scorePattern, passesThresholds, DEFAULT_THRESHOLDS } from './quality-scorer.js';
|
|
9
|
+
/**
|
|
10
|
+
* Compute a structural hash for a pattern gap.
|
|
11
|
+
*
|
|
12
|
+
* Variables are replaced with placeholders so structurally equivalent
|
|
13
|
+
* patterns (same shape, different values) get the same hash.
|
|
14
|
+
*/
|
|
15
|
+
export function computeStructuralHash(gap) {
|
|
16
|
+
// Normalize: replace variable values with slot types
|
|
17
|
+
const paramSignature = gap.extractedParams
|
|
18
|
+
.map(p => `${p.name}:${p.slotType}`)
|
|
19
|
+
.sort()
|
|
20
|
+
.join('|');
|
|
21
|
+
// The hash key: detector + pattern structure (not values)
|
|
22
|
+
const normalized = `${gap.detectorId}::${paramSignature}`;
|
|
23
|
+
return createHash('sha256').update(normalized).digest('hex').substring(0, 12);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Derive a human-readable template name from a gap.
|
|
27
|
+
*
|
|
28
|
+
* Uses the detector ID and key identifiers, not auto-generated garbage.
|
|
29
|
+
*/
|
|
30
|
+
export function deriveTemplateName(gap) {
|
|
31
|
+
// Start with detector ID which is already descriptive
|
|
32
|
+
const base = gap.detectorId;
|
|
33
|
+
// Look for a key identifier param (the main "name" param)
|
|
34
|
+
const nameParam = gap.extractedParams.find(p => p.slotType === 'identifier' && !p.optional);
|
|
35
|
+
// If there's a clear naming pattern, use it
|
|
36
|
+
if (nameParam) {
|
|
37
|
+
// e.g., react-hook-form + useForm → rhf-useform
|
|
38
|
+
const abbrev = abbreviateLibrary(gap.libraryName);
|
|
39
|
+
const paramHint = nameParam.name.replace(/Name$/, '');
|
|
40
|
+
return `${abbrev}-${paramHint}`.toLowerCase();
|
|
41
|
+
}
|
|
42
|
+
return base;
|
|
43
|
+
}
|
|
44
|
+
function abbreviateLibrary(name) {
|
|
45
|
+
// Common abbreviations
|
|
46
|
+
const abbrevs = {
|
|
47
|
+
'React Hook Form': 'rhf',
|
|
48
|
+
'Formik': 'formik',
|
|
49
|
+
'Recoil': 'recoil',
|
|
50
|
+
'Redux Toolkit': 'rtk',
|
|
51
|
+
'Framer Motion': 'motion',
|
|
52
|
+
'Axios': 'axios',
|
|
53
|
+
'Ky': 'ky',
|
|
54
|
+
'Yup': 'yup',
|
|
55
|
+
'Valibot': 'valibot',
|
|
56
|
+
'Express Middleware': 'express-mw',
|
|
57
|
+
'VueUse': 'vueuse',
|
|
58
|
+
'Testing Library': 'rtl',
|
|
59
|
+
};
|
|
60
|
+
return abbrevs[name] || name.toLowerCase().replace(/\s+/g, '-');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Extract import declarations from a gap's anchor import and library.
|
|
64
|
+
*/
|
|
65
|
+
function extractImports(gap) {
|
|
66
|
+
// The anchor import tells us what to import
|
|
67
|
+
return [{
|
|
68
|
+
from: gap.anchorImport.includes('/') ? gap.anchorImport : guessImportSource(gap),
|
|
69
|
+
names: [gap.anchorImport],
|
|
70
|
+
}];
|
|
71
|
+
}
|
|
72
|
+
function guessImportSource(gap) {
|
|
73
|
+
// Map library names to package names
|
|
74
|
+
const packageMap = {
|
|
75
|
+
'React Hook Form': 'react-hook-form',
|
|
76
|
+
'Formik': 'formik',
|
|
77
|
+
'Recoil': 'recoil',
|
|
78
|
+
'Redux Toolkit': '@reduxjs/toolkit',
|
|
79
|
+
'Framer Motion': 'framer-motion',
|
|
80
|
+
'Axios': 'axios',
|
|
81
|
+
'Ky': 'ky',
|
|
82
|
+
'Yup': 'yup',
|
|
83
|
+
'Valibot': 'valibot',
|
|
84
|
+
'VueUse': '@vueuse/core',
|
|
85
|
+
'Testing Library': '@testing-library/react',
|
|
86
|
+
};
|
|
87
|
+
return packageMap[gap.libraryName] || gap.libraryName.toLowerCase();
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Build a golden example from the representative gap.
|
|
91
|
+
*/
|
|
92
|
+
function buildGoldenExample(gap) {
|
|
93
|
+
const slotValues = {};
|
|
94
|
+
for (const param of gap.extractedParams) {
|
|
95
|
+
slotValues[param.name] = param.value;
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
originalTs: gap.snippet,
|
|
99
|
+
expectedExpansion: gap.snippet, // Will be refined during template proposal phase
|
|
100
|
+
slotValues,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Merge extracted params from multiple gaps into a union set.
|
|
105
|
+
* Params that appear in all instances stay required; others become optional.
|
|
106
|
+
*/
|
|
107
|
+
function mergeParams(gaps) {
|
|
108
|
+
if (gaps.length === 0)
|
|
109
|
+
return [];
|
|
110
|
+
if (gaps.length === 1)
|
|
111
|
+
return [...gaps[0].extractedParams];
|
|
112
|
+
// Count how many gaps have each param
|
|
113
|
+
const paramCounts = new Map();
|
|
114
|
+
const paramMap = new Map();
|
|
115
|
+
for (const gap of gaps) {
|
|
116
|
+
for (const param of gap.extractedParams) {
|
|
117
|
+
paramCounts.set(param.name, (paramCounts.get(param.name) || 0) + 1);
|
|
118
|
+
if (!paramMap.has(param.name)) {
|
|
119
|
+
paramMap.set(param.name, { ...param });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Params not in ALL instances become optional
|
|
124
|
+
const merged = [];
|
|
125
|
+
for (const [name, param] of paramMap) {
|
|
126
|
+
const count = paramCounts.get(name) || 0;
|
|
127
|
+
merged.push({
|
|
128
|
+
...param,
|
|
129
|
+
optional: param.optional || count < gaps.length,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return merged;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Analyze structural gaps separately for v3 node proposals.
|
|
136
|
+
*/
|
|
137
|
+
export function analyzeStructuralPatterns(gaps, thresholds = DEFAULT_THRESHOLDS) {
|
|
138
|
+
const structuralGaps = gaps.filter(g => g.libraryName === 'structural');
|
|
139
|
+
return groupAndScore(structuralGaps, thresholds);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Analyze and group pattern gaps into deduplicated, scored patterns.
|
|
143
|
+
*/
|
|
144
|
+
export function analyzePatterns(gaps, thresholds = DEFAULT_THRESHOLDS) {
|
|
145
|
+
// Structural gaps are findings, not template proposal candidates — filter them out
|
|
146
|
+
const templateGaps = gaps.filter(g => g.libraryName !== 'structural');
|
|
147
|
+
return groupAndScore(templateGaps, thresholds);
|
|
148
|
+
}
|
|
149
|
+
function groupAndScore(gaps, thresholds) {
|
|
150
|
+
const groups = new Map();
|
|
151
|
+
for (const gap of gaps) {
|
|
152
|
+
const hash = computeStructuralHash(gap);
|
|
153
|
+
const key = `${gap.libraryName}::${hash}`;
|
|
154
|
+
const group = groups.get(key) || [];
|
|
155
|
+
group.push(gap);
|
|
156
|
+
groups.set(key, group);
|
|
157
|
+
}
|
|
158
|
+
const patterns = [];
|
|
159
|
+
for (const [key, groupGaps] of groups) {
|
|
160
|
+
const representative = groupGaps[0];
|
|
161
|
+
const hash = computeStructuralHash(representative);
|
|
162
|
+
const qualityScore = scorePattern(groupGaps, thresholds);
|
|
163
|
+
if (!passesThresholds(qualityScore, thresholds))
|
|
164
|
+
continue;
|
|
165
|
+
patterns.push({
|
|
166
|
+
templateName: deriveTemplateName(representative),
|
|
167
|
+
structuralHash: hash,
|
|
168
|
+
namespace: representative.libraryName,
|
|
169
|
+
slots: mergeParams(groupGaps),
|
|
170
|
+
instanceCount: groupGaps.length,
|
|
171
|
+
qualityScore,
|
|
172
|
+
representativeSnippet: representative.snippet,
|
|
173
|
+
goldenExample: buildGoldenExample(representative),
|
|
174
|
+
imports: extractImports(representative),
|
|
175
|
+
gapIds: groupGaps.map(g => g.id),
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
patterns.sort((a, b) => b.qualityScore.overallScore - a.qualityScore.overallScore);
|
|
179
|
+
return patterns;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=pattern-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-analyzer.js","sourceRoot":"","sources":["../src/pattern-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzF;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAe;IACnD,qDAAqD;IACrD,MAAM,cAAc,GAAG,GAAG,CAAC,eAAe;SACvC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;SACnC,IAAI,EAAE;SACN,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,0DAA0D;IAC1D,MAAM,UAAU,GAAG,GAAG,GAAG,CAAC,UAAU,KAAK,cAAc,EAAE,CAAC;IAC1D,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAChF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAe;IAChD,sDAAsD;IACtD,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC;IAE5B,0DAA0D;IAC1D,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAC7C,CAAC,CAAC,QAAQ,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,QAAQ,CAC3C,CAAC;IAEF,4CAA4C;IAC5C,IAAI,SAAS,EAAE,CAAC;QACd,gDAAgD;QAChD,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACtD,OAAO,GAAG,MAAM,IAAI,SAAS,EAAE,CAAC,WAAW,EAAE,CAAC;IAChD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,uBAAuB;IACvB,MAAM,OAAO,GAA2B;QACtC,iBAAiB,EAAE,KAAK;QACxB,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,QAAQ;QAClB,eAAe,EAAE,KAAK;QACtB,eAAe,EAAE,QAAQ;QACzB,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,SAAS;QACpB,oBAAoB,EAAE,YAAY;QAClC,QAAQ,EAAE,QAAQ;QAClB,iBAAiB,EAAE,KAAK;KACzB,CAAC;IACF,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAClE,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,GAAe;IACrC,4CAA4C;IAC5C,OAAO,CAAC;YACN,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC;YAChF,KAAK,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC;SAC1B,CAAC,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAe;IACxC,qCAAqC;IACrC,MAAM,UAAU,GAA2B;QACzC,iBAAiB,EAAE,iBAAiB;QACpC,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,QAAQ;QAClB,eAAe,EAAE,kBAAkB;QACnC,eAAe,EAAE,eAAe;QAChC,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,SAAS;QACpB,QAAQ,EAAE,cAAc;QACxB,iBAAiB,EAAE,wBAAwB;KAC5C,CAAC;IACF,OAAO,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;AACtE,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,GAAe;IACzC,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;QACxC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;IACvC,CAAC;IAED,OAAO;QACL,UAAU,EAAE,GAAG,CAAC,OAAO;QACvB,iBAAiB,EAAE,GAAG,CAAC,OAAO,EAAE,iDAAiD;QACjF,UAAU;KACX,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAAC,IAAkB;IACrC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAE3D,sCAAsC;IACtC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC9C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEnD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;YACxC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACpE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IAED,8CAA8C;IAC9C,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,QAAQ,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC;YACV,GAAG,KAAK;YACR,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM;SAChD,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CACvC,IAAkB,EAClB,aAAgC,kBAAkB;IAElD,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC;IACxE,OAAO,aAAa,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAkB,EAClB,aAAgC,kBAAkB;IAElD,mFAAmF;IACnF,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC;IACtE,OAAO,aAAa,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,aAAa,CACpB,IAAkB,EAClB,UAA6B;IAE7B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;IAE/C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,QAAQ,GAAsB,EAAE,CAAC;IAEvC,KAAK,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,MAAM,EAAE,CAAC;QACtC,MAAM,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,qBAAqB,CAAC,cAAc,CAAC,CAAC;QACnD,MAAM,YAAY,GAAG,YAAY,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAEzD,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,UAAU,CAAC;YAAE,SAAS;QAE1D,QAAQ,CAAC,IAAI,CAAC;YACZ,YAAY,EAAE,kBAAkB,CAAC,cAAc,CAAC;YAChD,cAAc,EAAE,IAAI;YACpB,SAAS,EAAE,cAAc,CAAC,WAAW;YACrC,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC;YAC7B,aAAa,EAAE,SAAS,CAAC,MAAM;YAC/B,YAAY;YACZ,qBAAqB,EAAE,cAAc,CAAC,OAAO;YAC7C,aAAa,EAAE,kBAAkB,CAAC,cAAc,CAAC;YACjD,OAAO,EAAE,cAAc,CAAC,cAAc,CAAC;YACvC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjC,CAAC,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;IACnF,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality Scorer — scores patterns to filter out low-value template candidates.
|
|
3
|
+
*
|
|
4
|
+
* Patterns like `cors()` that are one-liners get low relevance scores.
|
|
5
|
+
* Templates should compress, not wrap.
|
|
6
|
+
*/
|
|
7
|
+
import type { PatternGap, QualityScore, QualityThresholds } from './types.js';
|
|
8
|
+
export declare const DEFAULT_THRESHOLDS: QualityThresholds;
|
|
9
|
+
/**
|
|
10
|
+
* Calculate quality score for a group of pattern gaps (same structural pattern).
|
|
11
|
+
*/
|
|
12
|
+
export declare function scorePattern(gaps: PatternGap[], thresholds?: QualityThresholds): QualityScore;
|
|
13
|
+
/**
|
|
14
|
+
* Check if a quality score passes the configured thresholds.
|
|
15
|
+
*/
|
|
16
|
+
export declare function passesThresholds(score: QualityScore, thresholds?: QualityThresholds): boolean;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality Scorer — scores patterns to filter out low-value template candidates.
|
|
3
|
+
*
|
|
4
|
+
* Patterns like `cors()` that are one-liners get low relevance scores.
|
|
5
|
+
* Templates should compress, not wrap.
|
|
6
|
+
*/
|
|
7
|
+
export const DEFAULT_THRESHOLDS = {
|
|
8
|
+
minConfidence: 60,
|
|
9
|
+
minSupport: 1,
|
|
10
|
+
maxVariability: 0.7,
|
|
11
|
+
minRelevance: 0.3,
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Calculate quality score for a group of pattern gaps (same structural pattern).
|
|
15
|
+
*/
|
|
16
|
+
export function scorePattern(gaps, thresholds = DEFAULT_THRESHOLDS) {
|
|
17
|
+
if (gaps.length === 0) {
|
|
18
|
+
return { confidence: 0, supportCount: 0, variability: 0, relevanceScore: 0, overallScore: 0 };
|
|
19
|
+
}
|
|
20
|
+
// Confidence: average across all instances
|
|
21
|
+
const confidence = gaps.reduce((sum, g) => sum + g.confidencePct, 0) / gaps.length;
|
|
22
|
+
// Support count
|
|
23
|
+
const supportCount = gaps.length;
|
|
24
|
+
// Variability: how much the params differ between instances (0 = identical, 1 = all different)
|
|
25
|
+
const variability = calculateVariability(gaps);
|
|
26
|
+
// Relevance: does this pattern actually compress code?
|
|
27
|
+
const relevanceScore = calculateRelevance(gaps);
|
|
28
|
+
// Weighted composite score
|
|
29
|
+
const overallScore = computeOverall(confidence, supportCount, variability, relevanceScore);
|
|
30
|
+
return { confidence, supportCount, variability, relevanceScore, overallScore };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Check if a quality score passes the configured thresholds.
|
|
34
|
+
*/
|
|
35
|
+
export function passesThresholds(score, thresholds = DEFAULT_THRESHOLDS) {
|
|
36
|
+
return (score.confidence >= thresholds.minConfidence &&
|
|
37
|
+
score.supportCount >= thresholds.minSupport &&
|
|
38
|
+
score.variability <= thresholds.maxVariability &&
|
|
39
|
+
score.relevanceScore >= thresholds.minRelevance);
|
|
40
|
+
}
|
|
41
|
+
function calculateVariability(gaps) {
|
|
42
|
+
if (gaps.length <= 1)
|
|
43
|
+
return 0;
|
|
44
|
+
// Compare the number and names of extracted params across instances
|
|
45
|
+
const paramSets = gaps.map(g => g.extractedParams.map(p => p.name).sort().join(','));
|
|
46
|
+
// Count how many unique param signatures there are
|
|
47
|
+
const uniqueSignatures = new Set(paramSets).size;
|
|
48
|
+
const variability = (uniqueSignatures - 1) / Math.max(gaps.length - 1, 1);
|
|
49
|
+
return Math.min(variability, 1);
|
|
50
|
+
}
|
|
51
|
+
function calculateRelevance(gaps) {
|
|
52
|
+
// Average snippet length as proxy for code complexity
|
|
53
|
+
const avgSnippetLength = gaps.reduce((sum, g) => sum + g.snippet.length, 0) / gaps.length;
|
|
54
|
+
const avgParams = gaps.reduce((sum, g) => sum + g.extractedParams.length, 0) / gaps.length;
|
|
55
|
+
// Short snippets with few params = low relevance (one-liner wrappers)
|
|
56
|
+
if (avgSnippetLength < 50 && avgParams <= 1)
|
|
57
|
+
return 0.1;
|
|
58
|
+
if (avgSnippetLength < 100 && avgParams <= 1)
|
|
59
|
+
return 0.2;
|
|
60
|
+
// Multi-line patterns with params are good template candidates
|
|
61
|
+
const lineBasedScore = Math.min(avgSnippetLength / 300, 1);
|
|
62
|
+
const paramBasedScore = Math.min(avgParams / 3, 1);
|
|
63
|
+
return (lineBasedScore * 0.6 + paramBasedScore * 0.4);
|
|
64
|
+
}
|
|
65
|
+
function computeOverall(confidence, supportCount, variability, relevanceScore) {
|
|
66
|
+
// Normalize confidence to 0-1
|
|
67
|
+
const confNorm = confidence / 100;
|
|
68
|
+
// Support bonus (diminishing returns after 5 instances)
|
|
69
|
+
const supportNorm = Math.min(supportCount / 5, 1);
|
|
70
|
+
// Variability penalty (higher variability = worse)
|
|
71
|
+
const varPenalty = 1 - variability;
|
|
72
|
+
// Weighted composite
|
|
73
|
+
const overall = confNorm * 0.3 +
|
|
74
|
+
supportNorm * 0.2 +
|
|
75
|
+
varPenalty * 0.2 +
|
|
76
|
+
relevanceScore * 0.3;
|
|
77
|
+
return Math.round(overall * 100);
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=quality-scorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-scorer.js","sourceRoot":"","sources":["../src/quality-scorer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandboxed Generator — loads evolved codegen.js files in a restricted vm context.
|
|
3
|
+
*
|
|
4
|
+
* Security: Only approved helpers are available. No require, process, fs, or network.
|
|
5
|
+
* The generator function signature matches core: (node: IRNode) => string[]
|
|
6
|
+
*/
|
|
7
|
+
import type { IRNode } from '@kernlang/core';
|
|
8
|
+
import type { CodegenHelpers } from './evolved-types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Load a pre-compiled codegen.js file into a sandboxed vm context.
|
|
11
|
+
* Returns a generator function: (node: IRNode) => string[]
|
|
12
|
+
*
|
|
13
|
+
* The sandbox only exposes:
|
|
14
|
+
* - `helpers` — the CodegenHelpers object
|
|
15
|
+
* - `exports` — the module's export target
|
|
16
|
+
*
|
|
17
|
+
* No require, process, fs, Buffer, setTimeout, fetch, or any global.
|
|
18
|
+
*/
|
|
19
|
+
export declare function loadSandboxedGenerator(jsPath: string): (node: IRNode) => string[];
|
|
20
|
+
/**
|
|
21
|
+
* Compile a codegen source string into a sandboxed generator function.
|
|
22
|
+
* Used both for loading from disk and for validation dry-runs.
|
|
23
|
+
*/
|
|
24
|
+
export declare function compileSandboxedGenerator(code: string): (node: IRNode) => string[];
|
|
25
|
+
/** Get a fresh copy of codegen helpers (for testing). */
|
|
26
|
+
export declare function getCodegenHelpers(): CodegenHelpers;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandboxed Generator — loads evolved codegen.js files in a restricted vm context.
|
|
3
|
+
*
|
|
4
|
+
* Security: Only approved helpers are available. No require, process, fs, or network.
|
|
5
|
+
* The generator function signature matches core: (node: IRNode) => string[]
|
|
6
|
+
*/
|
|
7
|
+
import { createContext, Script } from 'vm';
|
|
8
|
+
import { readFileSync } from 'fs';
|
|
9
|
+
/**
|
|
10
|
+
* Build the set of helpers available to sandboxed generators.
|
|
11
|
+
* These mirror the private helpers in codegen-core.ts.
|
|
12
|
+
*/
|
|
13
|
+
function buildHelpers() {
|
|
14
|
+
return {
|
|
15
|
+
capitalize: (s) => s.charAt(0).toUpperCase() + s.slice(1),
|
|
16
|
+
parseParamList: (params) => {
|
|
17
|
+
return params.split(',').map(p => {
|
|
18
|
+
const trimmed = p.trim();
|
|
19
|
+
const eqIdx = trimmed.indexOf('=');
|
|
20
|
+
if (eqIdx > 0) {
|
|
21
|
+
const paramPart = trimmed.slice(0, eqIdx);
|
|
22
|
+
const defaultVal = trimmed.slice(eqIdx + 1);
|
|
23
|
+
const colonIdx = paramPart.indexOf(':');
|
|
24
|
+
if (colonIdx > 0) {
|
|
25
|
+
return `${paramPart.slice(0, colonIdx)}: ${paramPart.slice(colonIdx + 1)} = ${defaultVal}`;
|
|
26
|
+
}
|
|
27
|
+
return `${paramPart} = ${defaultVal}`;
|
|
28
|
+
}
|
|
29
|
+
const colonIdx = trimmed.indexOf(':');
|
|
30
|
+
if (colonIdx > 0) {
|
|
31
|
+
return `${trimmed.slice(0, colonIdx)}: ${trimmed.slice(colonIdx + 1)}`;
|
|
32
|
+
}
|
|
33
|
+
return trimmed;
|
|
34
|
+
}).join(', ');
|
|
35
|
+
},
|
|
36
|
+
dedent: (code) => {
|
|
37
|
+
const lines = code.split('\n');
|
|
38
|
+
const nonEmpty = lines.filter(l => l.trim().length > 0);
|
|
39
|
+
if (nonEmpty.length === 0)
|
|
40
|
+
return code;
|
|
41
|
+
const min = Math.min(...nonEmpty.map(l => l.match(/^(\s*)/)?.[1].length ?? 0));
|
|
42
|
+
return lines.map(l => l.slice(min)).join('\n');
|
|
43
|
+
},
|
|
44
|
+
kids: (node, type) => {
|
|
45
|
+
const c = node.children || [];
|
|
46
|
+
return type ? c.filter(n => n.type === type) : c;
|
|
47
|
+
},
|
|
48
|
+
firstChild: (node, type) => {
|
|
49
|
+
return (node.children || []).find(n => n.type === type);
|
|
50
|
+
},
|
|
51
|
+
p: (node) => node.props || {},
|
|
52
|
+
handlerCode: (node) => {
|
|
53
|
+
const handler = (node.children || []).find(n => n.type === 'handler');
|
|
54
|
+
if (!handler)
|
|
55
|
+
return '';
|
|
56
|
+
const raw = handler.props?.code || '';
|
|
57
|
+
// Dedent
|
|
58
|
+
const lines = raw.split('\n');
|
|
59
|
+
const nonEmpty = lines.filter(l => l.trim().length > 0);
|
|
60
|
+
if (nonEmpty.length === 0)
|
|
61
|
+
return raw;
|
|
62
|
+
const min = Math.min(...nonEmpty.map(l => l.match(/^(\s*)/)?.[1].length ?? 0));
|
|
63
|
+
return lines.map(l => l.slice(min)).join('\n');
|
|
64
|
+
},
|
|
65
|
+
exportPrefix: (node) => {
|
|
66
|
+
return (node.props || {}).export === 'false' ? '' : 'export ';
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Load a pre-compiled codegen.js file into a sandboxed vm context.
|
|
72
|
+
* Returns a generator function: (node: IRNode) => string[]
|
|
73
|
+
*
|
|
74
|
+
* The sandbox only exposes:
|
|
75
|
+
* - `helpers` — the CodegenHelpers object
|
|
76
|
+
* - `exports` — the module's export target
|
|
77
|
+
*
|
|
78
|
+
* No require, process, fs, Buffer, setTimeout, fetch, or any global.
|
|
79
|
+
*/
|
|
80
|
+
export function loadSandboxedGenerator(jsPath) {
|
|
81
|
+
const code = readFileSync(jsPath, 'utf-8');
|
|
82
|
+
return compileSandboxedGenerator(code);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Compile a codegen source string into a sandboxed generator function.
|
|
86
|
+
* Used both for loading from disk and for validation dry-runs.
|
|
87
|
+
*/
|
|
88
|
+
export function compileSandboxedGenerator(code) {
|
|
89
|
+
const helpers = buildHelpers();
|
|
90
|
+
const sandbox = {
|
|
91
|
+
exports: {},
|
|
92
|
+
module: { exports: {} },
|
|
93
|
+
helpers,
|
|
94
|
+
// Explicitly blocked — undefined, not missing (prevents prototype chain access)
|
|
95
|
+
require: undefined,
|
|
96
|
+
process: undefined,
|
|
97
|
+
global: undefined,
|
|
98
|
+
globalThis: undefined,
|
|
99
|
+
Buffer: undefined,
|
|
100
|
+
setTimeout: undefined,
|
|
101
|
+
setInterval: undefined,
|
|
102
|
+
fetch: undefined,
|
|
103
|
+
console: undefined,
|
|
104
|
+
};
|
|
105
|
+
const ctx = createContext(sandbox, {
|
|
106
|
+
name: 'kern-evolved-codegen',
|
|
107
|
+
codeGeneration: { strings: false, wasm: false },
|
|
108
|
+
});
|
|
109
|
+
const script = new Script(code, { filename: 'evolved-codegen.js' });
|
|
110
|
+
script.runInContext(ctx);
|
|
111
|
+
// Support both `module.exports = fn` and `exports.default = fn` patterns
|
|
112
|
+
const fn = sandbox.module.exports.default
|
|
113
|
+
|| sandbox.module.exports.generate
|
|
114
|
+
|| sandbox.module.exports
|
|
115
|
+
|| sandbox.exports.default
|
|
116
|
+
|| sandbox.exports.generate;
|
|
117
|
+
if (typeof fn !== 'function') {
|
|
118
|
+
throw new Error('Evolved codegen must export a function: module.exports = function(node, helpers) { ... }');
|
|
119
|
+
}
|
|
120
|
+
// Wrap to inject helpers as second argument
|
|
121
|
+
return (node) => {
|
|
122
|
+
const result = fn(node, helpers);
|
|
123
|
+
if (!Array.isArray(result)) {
|
|
124
|
+
throw new Error(`Evolved codegen must return string[], got ${typeof result}`);
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** Get a fresh copy of codegen helpers (for testing). */
|
|
130
|
+
export function getCodegenHelpers() {
|
|
131
|
+
return buildHelpers();
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=sandboxed-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandboxed-generator.js","sourceRoot":"","sources":["../src/sandboxed-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staging — Phase 5 of the evolve pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Per-proposal file staging + approval workflow.
|
|
5
|
+
* Each proposal gets its own JSON file to avoid merge conflicts in teams.
|
|
6
|
+
*/
|
|
7
|
+
import type { TemplateProposal, ValidationResult, StagedProposal, ProposalStatus, EvolveConfig, NodeProposal, NodeValidationResult, StagedNodeProposal, NodeProposalStatus } from './types.js';
|
|
8
|
+
import type { EvolveNodeProposal, EvolveV4ValidationResult, StagedEvolveProposal, EvolveV4ProposalStatus } from './evolved-types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Stage a validated proposal for human review.
|
|
11
|
+
*/
|
|
12
|
+
export declare function stageProposal(proposal: TemplateProposal, validation: ValidationResult, config?: Partial<EvolveConfig>): StagedProposal;
|
|
13
|
+
/**
|
|
14
|
+
* List all staged proposals.
|
|
15
|
+
*/
|
|
16
|
+
export declare function listStaged(config?: Partial<EvolveConfig>): StagedProposal[];
|
|
17
|
+
/**
|
|
18
|
+
* Get a single staged proposal by ID.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getStaged(id: string, config?: Partial<EvolveConfig>): StagedProposal | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Update the status of a staged proposal.
|
|
23
|
+
*/
|
|
24
|
+
export declare function updateStagedStatus(id: string, status: ProposalStatus, config?: Partial<EvolveConfig>): StagedProposal | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Promote approved proposals to project-local templates directory.
|
|
27
|
+
*/
|
|
28
|
+
export declare function promoteLocal(config?: Partial<EvolveConfig>): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Remove rejected proposals from staging.
|
|
31
|
+
*/
|
|
32
|
+
export declare function cleanRejected(config?: Partial<EvolveConfig>): number;
|
|
33
|
+
/**
|
|
34
|
+
* Format a staged proposal for split-view display.
|
|
35
|
+
*/
|
|
36
|
+
export declare function formatSplitView(staged: StagedProposal): string;
|
|
37
|
+
/**
|
|
38
|
+
* Stage a validated node proposal for human review.
|
|
39
|
+
*/
|
|
40
|
+
export declare function stageNodeProposal(proposal: NodeProposal, validation: NodeValidationResult, config?: Partial<EvolveConfig>): StagedNodeProposal;
|
|
41
|
+
/**
|
|
42
|
+
* List all staged node proposals.
|
|
43
|
+
*/
|
|
44
|
+
export declare function listStagedNodes(config?: Partial<EvolveConfig>): StagedNodeProposal[];
|
|
45
|
+
/**
|
|
46
|
+
* Update the status of a staged node proposal.
|
|
47
|
+
*/
|
|
48
|
+
export declare function updateStagedNodeStatus(id: string, status: NodeProposalStatus, config?: Partial<EvolveConfig>): StagedNodeProposal | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Format a staged node proposal for split-view display.
|
|
51
|
+
*/
|
|
52
|
+
export declare function formatNodeSplitView(staged: StagedNodeProposal): string;
|
|
53
|
+
/**
|
|
54
|
+
* Stage a validated v4 proposal for human review.
|
|
55
|
+
*/
|
|
56
|
+
export declare function stageEvolveV4Proposal(proposal: EvolveNodeProposal, validation: EvolveV4ValidationResult): StagedEvolveProposal;
|
|
57
|
+
/**
|
|
58
|
+
* List all staged v4 proposals.
|
|
59
|
+
*/
|
|
60
|
+
export declare function listStagedEvolveV4(): StagedEvolveProposal[];
|
|
61
|
+
/**
|
|
62
|
+
* Get a single staged v4 proposal by ID.
|
|
63
|
+
*/
|
|
64
|
+
export declare function getStagedEvolveV4(id: string): StagedEvolveProposal | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Update the status of a staged v4 proposal.
|
|
67
|
+
*/
|
|
68
|
+
export declare function updateStagedEvolveV4Status(id: string, status: EvolveV4ProposalStatus): StagedEvolveProposal | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Remove rejected v4 proposals from staging.
|
|
71
|
+
*/
|
|
72
|
+
export declare function cleanRejectedEvolveV4(): number;
|
|
73
|
+
/**
|
|
74
|
+
* Remove approved v4 proposals from staging (after graduation).
|
|
75
|
+
*/
|
|
76
|
+
export declare function cleanApprovedEvolveV4(id: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Format a staged v4 proposal for split-view display.
|
|
79
|
+
* Matches the design doc UX: KERN syntax | Generated TypeScript, validation badges, reason.
|
|
80
|
+
*/
|
|
81
|
+
export declare function formatEvolveV4SplitView(staged: StagedEvolveProposal): string;
|