@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,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM Provider — abstraction over OpenAI, Anthropic, and local models.
|
|
3
|
+
*
|
|
4
|
+
* Used only by `kern evolve discover` and `kern evolve backfill`.
|
|
5
|
+
* Never called during compilation.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Create an LLM provider based on configuration.
|
|
9
|
+
* Checks environment variables for API keys.
|
|
10
|
+
*/
|
|
11
|
+
export function createLLMProvider(options = {}) {
|
|
12
|
+
const provider = options.provider || detectProvider();
|
|
13
|
+
switch (provider) {
|
|
14
|
+
case 'openai':
|
|
15
|
+
return createOpenAIProvider(options);
|
|
16
|
+
case 'anthropic':
|
|
17
|
+
return createAnthropicProvider(options);
|
|
18
|
+
case 'ollama':
|
|
19
|
+
return createOllamaProvider(options);
|
|
20
|
+
default:
|
|
21
|
+
throw new Error(`No LLM provider configured. Set OPENAI_API_KEY, ANTHROPIC_API_KEY, or use --provider=ollama`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function detectProvider() {
|
|
25
|
+
if (process.env.OPENAI_API_KEY)
|
|
26
|
+
return 'openai';
|
|
27
|
+
if (process.env.ANTHROPIC_API_KEY)
|
|
28
|
+
return 'anthropic';
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
function createOpenAIProvider(options) {
|
|
32
|
+
const apiKey = options.apiKey || process.env.OPENAI_API_KEY;
|
|
33
|
+
if (!apiKey)
|
|
34
|
+
throw new Error('OPENAI_API_KEY not set');
|
|
35
|
+
const model = options.model || 'gpt-4o';
|
|
36
|
+
const baseUrl = options.baseUrl || 'https://api.openai.com/v1';
|
|
37
|
+
const maxTokens = options.maxTokens || 4096;
|
|
38
|
+
return {
|
|
39
|
+
name: `openai/${model}`,
|
|
40
|
+
async complete(prompt) {
|
|
41
|
+
const response = await fetch(`${baseUrl}/chat/completions`, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: {
|
|
44
|
+
'Content-Type': 'application/json',
|
|
45
|
+
Authorization: `Bearer ${apiKey}`,
|
|
46
|
+
},
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
model,
|
|
49
|
+
messages: [{ role: 'user', content: prompt }],
|
|
50
|
+
max_tokens: maxTokens,
|
|
51
|
+
temperature: 0.2,
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
const text = await response.text();
|
|
56
|
+
throw new Error(`OpenAI API error ${response.status}: ${text}`);
|
|
57
|
+
}
|
|
58
|
+
const data = await response.json();
|
|
59
|
+
return data.choices[0]?.message?.content || '';
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function createAnthropicProvider(options) {
|
|
64
|
+
const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY;
|
|
65
|
+
if (!apiKey)
|
|
66
|
+
throw new Error('ANTHROPIC_API_KEY not set');
|
|
67
|
+
const model = options.model || 'claude-sonnet-4-6';
|
|
68
|
+
const maxTokens = options.maxTokens || 4096;
|
|
69
|
+
return {
|
|
70
|
+
name: `anthropic/${model}`,
|
|
71
|
+
async complete(prompt) {
|
|
72
|
+
const response = await fetch('https://api.anthropic.com/v1/messages', {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
headers: {
|
|
75
|
+
'Content-Type': 'application/json',
|
|
76
|
+
'x-api-key': apiKey,
|
|
77
|
+
'anthropic-version': '2023-06-01',
|
|
78
|
+
},
|
|
79
|
+
body: JSON.stringify({
|
|
80
|
+
model,
|
|
81
|
+
max_tokens: maxTokens,
|
|
82
|
+
messages: [{ role: 'user', content: prompt }],
|
|
83
|
+
}),
|
|
84
|
+
});
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
const text = await response.text();
|
|
87
|
+
throw new Error(`Anthropic API error ${response.status}: ${text}`);
|
|
88
|
+
}
|
|
89
|
+
const data = await response.json();
|
|
90
|
+
return data.content[0]?.text || '';
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function createOllamaProvider(options) {
|
|
95
|
+
const model = options.model || 'llama3';
|
|
96
|
+
const baseUrl = options.baseUrl || 'http://localhost:11434';
|
|
97
|
+
return {
|
|
98
|
+
name: `ollama/${model}`,
|
|
99
|
+
async complete(prompt) {
|
|
100
|
+
const response = await fetch(`${baseUrl}/api/generate`, {
|
|
101
|
+
method: 'POST',
|
|
102
|
+
headers: { 'Content-Type': 'application/json' },
|
|
103
|
+
body: JSON.stringify({
|
|
104
|
+
model,
|
|
105
|
+
prompt,
|
|
106
|
+
stream: false,
|
|
107
|
+
}),
|
|
108
|
+
});
|
|
109
|
+
if (!response.ok) {
|
|
110
|
+
const text = await response.text();
|
|
111
|
+
throw new Error(`Ollama error ${response.status}: ${text}`);
|
|
112
|
+
}
|
|
113
|
+
const data = await response.json();
|
|
114
|
+
return data.response || '';
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Track token usage for cost estimation.
|
|
120
|
+
*/
|
|
121
|
+
export class TokenBudget {
|
|
122
|
+
limit;
|
|
123
|
+
used = 0;
|
|
124
|
+
constructor(limit) {
|
|
125
|
+
this.limit = limit;
|
|
126
|
+
}
|
|
127
|
+
add(tokens) {
|
|
128
|
+
this.used += tokens;
|
|
129
|
+
}
|
|
130
|
+
get remaining() {
|
|
131
|
+
return Math.max(0, this.limit - this.used);
|
|
132
|
+
}
|
|
133
|
+
get exhausted() {
|
|
134
|
+
return this.used >= this.limit;
|
|
135
|
+
}
|
|
136
|
+
get totalUsed() {
|
|
137
|
+
return this.used;
|
|
138
|
+
}
|
|
139
|
+
toString() {
|
|
140
|
+
return `${this.used}/${this.limit} tokens (${Math.round(this.used / this.limit * 100)}%)`;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=llm-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-provider.js","sourceRoot":"","sources":["../src/llm-provider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAA8B,EAAE;IAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,cAAc,EAAE,CAAC;IAEtD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACvC,KAAK,WAAW;YACd,OAAO,uBAAuB,CAAC,OAAO,CAAC,CAAC;QAC1C,KAAK,QAAQ;YACX,OAAO,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACvC;YACE,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;IACN,CAAC;AACH,CAAC;AAED,SAAS,cAAc;IACrB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,QAAQ,CAAC;IAChD,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAAE,OAAO,WAAW,CAAC;IACtD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,oBAAoB,CAAC,OAA2B;IACvD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC5D,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAEvD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC;IACxC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,2BAA2B,CAAC;IAC/D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;IAE5C,OAAO;QACL,IAAI,EAAE,UAAU,KAAK,EAAE;QACvB,KAAK,CAAC,QAAQ,CAAC,MAAc;YAC3B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,mBAAmB,EAAE;gBAC1D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,UAAU,MAAM,EAAE;iBAClC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK;oBACL,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;oBAC7C,UAAU,EAAE,SAAS;oBACrB,WAAW,EAAE,GAAG;iBACjB,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;YAClE,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA0D,CAAC;YAC3F,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;QACjD,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAAC,OAA2B;IAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC/D,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAE1D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,mBAAmB,CAAC;IACnD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;IAE5C,OAAO;QACL,IAAI,EAAE,aAAa,KAAK,EAAE;QAC1B,KAAK,CAAC,QAAQ,CAAC,MAAc;YAC3B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,uCAAuC,EAAE;gBACpE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,WAAW,EAAE,MAAM;oBACnB,mBAAmB,EAAE,YAAY;iBAClC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK;oBACL,UAAU,EAAE,SAAS;oBACrB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;iBAC9C,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA0C,CAAC;YAC3E,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;QACrC,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,OAA2B;IACvD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC;IACxC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,wBAAwB,CAAC;IAE5D,OAAO;QACL,IAAI,EAAE,UAAU,KAAK,EAAE;QACvB,KAAK,CAAC,QAAQ,CAAC,MAAc;YAC3B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,eAAe,EAAE;gBACtD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK;oBACL,MAAM;oBACN,MAAM,EAAE,KAAK;iBACd,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,gBAAgB,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;YAC9D,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA0B,CAAC;YAC3D,OAAO,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,WAAW;IAGM;IAFpB,IAAI,GAAG,CAAC,CAAC;IAEjB,YAA4B,KAAa;QAAb,UAAK,GAAL,KAAK,CAAQ;IAAG,CAAC;IAE7C,GAAG,CAAC,MAAc;QAChB,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC;IACtB,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC;IACjC,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,YAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC;IAC5F,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Governance Gate — quality control for IR node proposals.
|
|
3
|
+
*
|
|
4
|
+
* Ensures only high-quality, well-evidenced proposals pass through.
|
|
5
|
+
* Checks: frequency, expressibility, target coverage, quality score.
|
|
6
|
+
*/
|
|
7
|
+
import type { NodeProposal } from './types.js';
|
|
8
|
+
export interface GovernanceResult {
|
|
9
|
+
pass: boolean;
|
|
10
|
+
reasons: string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Run the governance gate on a node proposal.
|
|
14
|
+
* All checks must pass for the proposal to be approved.
|
|
15
|
+
*/
|
|
16
|
+
export declare function governanceGate(proposal: NodeProposal): GovernanceResult;
|
|
17
|
+
/** Get governance thresholds for display. */
|
|
18
|
+
export declare function getGovernanceThresholds(): {
|
|
19
|
+
minFrequency: number;
|
|
20
|
+
minExpressibility: number;
|
|
21
|
+
minTargetCoverage: number;
|
|
22
|
+
minQualityScore: number;
|
|
23
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Governance Gate — quality control for IR node proposals.
|
|
3
|
+
*
|
|
4
|
+
* Ensures only high-quality, well-evidenced proposals pass through.
|
|
5
|
+
* Checks: frequency, expressibility, target coverage, quality score.
|
|
6
|
+
*/
|
|
7
|
+
const MIN_FREQUENCY = 3;
|
|
8
|
+
const MIN_EXPRESSIBILITY = 7.0;
|
|
9
|
+
const MIN_TARGET_COVERAGE = 8; // out of 11 targets
|
|
10
|
+
const MIN_QUALITY_SCORE = 60;
|
|
11
|
+
/**
|
|
12
|
+
* Run the governance gate on a node proposal.
|
|
13
|
+
* All checks must pass for the proposal to be approved.
|
|
14
|
+
*/
|
|
15
|
+
export function governanceGate(proposal) {
|
|
16
|
+
const reasons = [];
|
|
17
|
+
if (proposal.frequency < MIN_FREQUENCY) {
|
|
18
|
+
reasons.push(`frequency ${proposal.frequency} < ${MIN_FREQUENCY} (need more instances)`);
|
|
19
|
+
}
|
|
20
|
+
if (proposal.expressibilityScore.overall < MIN_EXPRESSIBILITY) {
|
|
21
|
+
reasons.push(`expressibility ${proposal.expressibilityScore.overall} < ${MIN_EXPRESSIBILITY} (current IR may suffice)`);
|
|
22
|
+
}
|
|
23
|
+
if (proposal.qualityScore < MIN_QUALITY_SCORE) {
|
|
24
|
+
reasons.push(`quality ${proposal.qualityScore} < ${MIN_QUALITY_SCORE}`);
|
|
25
|
+
}
|
|
26
|
+
// Target coverage check: count how many targets the codegen stub covers
|
|
27
|
+
const targetCount = Object.keys(proposal.targetStubs).length;
|
|
28
|
+
if (targetCount > 0 && targetCount < MIN_TARGET_COVERAGE) {
|
|
29
|
+
reasons.push(`target coverage ${targetCount}/${MIN_TARGET_COVERAGE}`);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
pass: reasons.length === 0,
|
|
33
|
+
reasons,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Get governance thresholds for display. */
|
|
37
|
+
export function getGovernanceThresholds() {
|
|
38
|
+
return {
|
|
39
|
+
minFrequency: MIN_FREQUENCY,
|
|
40
|
+
minExpressibility: MIN_EXPRESSIBILITY,
|
|
41
|
+
minTargetCoverage: MIN_TARGET_COVERAGE,
|
|
42
|
+
minQualityScore: MIN_QUALITY_SCORE,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=node-governance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-governance.js","sourceRoot":"","sources":["../src/node-governance.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAC/B,MAAM,mBAAmB,GAAG,CAAC,CAAC,CAAC,oBAAoB;AACnD,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAsB;IACnD,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,IAAI,QAAQ,CAAC,SAAS,GAAG,aAAa,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,SAAS,MAAM,aAAa,wBAAwB,CAAC,CAAC;IAC3F,CAAC;IAED,IAAI,QAAQ,CAAC,mBAAmB,CAAC,OAAO,GAAG,kBAAkB,EAAE,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,kBAAkB,QAAQ,CAAC,mBAAmB,CAAC,OAAO,MAAM,kBAAkB,2BAA2B,CAAC,CAAC;IAC1H,CAAC;IAED,IAAI,QAAQ,CAAC,YAAY,GAAG,iBAAiB,EAAE,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,WAAW,QAAQ,CAAC,YAAY,MAAM,iBAAiB,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,wEAAwE;IACxE,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;IAC7D,IAAI,WAAW,GAAG,CAAC,IAAI,WAAW,GAAG,mBAAmB,EAAE,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,mBAAmB,WAAW,IAAI,mBAAmB,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC;QAC1B,OAAO;KACR,CAAC;AACJ,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,YAAY,EAAE,aAAa;QAC3B,iBAAiB,EAAE,kBAAkB;QACrC,iBAAiB,EAAE,mBAAmB;QACtC,eAAe,EAAE,iBAAiB;KACnC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Proposer — generates IR node proposals from structural gap patterns.
|
|
3
|
+
*
|
|
4
|
+
* Deterministic: no LLM needed (--llm is optional enhancement).
|
|
5
|
+
* Maps detected structural patterns to proposed KERN node types.
|
|
6
|
+
*/
|
|
7
|
+
import type { AnalyzedPattern, NodeProposal, ExpressibilityScore } from './types.js';
|
|
8
|
+
export declare function resetNodeProposalIds(): void;
|
|
9
|
+
/**
|
|
10
|
+
* Derive a KERN node name from a structural pattern's detector ID.
|
|
11
|
+
*/
|
|
12
|
+
export declare function deriveNodeName(pattern: AnalyzedPattern): string;
|
|
13
|
+
/**
|
|
14
|
+
* Generate example KERN syntax for a proposed node.
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateKernSyntaxExample(nodeName: string, pattern: AnalyzedPattern): string;
|
|
17
|
+
/**
|
|
18
|
+
* Generate a codegen stub for a proposed node.
|
|
19
|
+
*/
|
|
20
|
+
export declare function generateCodegenStub(nodeName: string, pattern: AnalyzedPattern): string;
|
|
21
|
+
/**
|
|
22
|
+
* Propose new IR nodes from analyzed structural patterns.
|
|
23
|
+
*
|
|
24
|
+
* Each pattern with an expressibility score above the threshold
|
|
25
|
+
* gets a deterministic node proposal.
|
|
26
|
+
*/
|
|
27
|
+
export declare function proposeNodes(patterns: AnalyzedPattern[], scores: Map<string, ExpressibilityScore>): NodeProposal[];
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Proposer — generates IR node proposals from structural gap patterns.
|
|
3
|
+
*
|
|
4
|
+
* Deterministic: no LLM needed (--llm is optional enhancement).
|
|
5
|
+
* Maps detected structural patterns to proposed KERN node types.
|
|
6
|
+
*/
|
|
7
|
+
let _nodeProposalCounter = 0;
|
|
8
|
+
function nextNodeProposalId() {
|
|
9
|
+
return `node-proposal-${++_nodeProposalCounter}`;
|
|
10
|
+
}
|
|
11
|
+
export function resetNodeProposalIds() {
|
|
12
|
+
_nodeProposalCounter = 0;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Derive a KERN node name from a structural pattern's detector ID.
|
|
16
|
+
*/
|
|
17
|
+
export function deriveNodeName(pattern) {
|
|
18
|
+
// Strip gap- prefix and trailing counter: gap-structural-model-1 → structural-model
|
|
19
|
+
const detectorId = pattern.gapIds[0]?.replace(/^gap-/, '').replace(/-\d+$/, '') || pattern.templateName;
|
|
20
|
+
const nameMap = {
|
|
21
|
+
'structural-model': 'model',
|
|
22
|
+
'structural-repository': 'repository',
|
|
23
|
+
'structural-dependency': 'dependency',
|
|
24
|
+
'structural-cache': 'cache',
|
|
25
|
+
'structural-conditional': 'conditional',
|
|
26
|
+
'structural-select': 'select',
|
|
27
|
+
};
|
|
28
|
+
// Direct match on stripped detector ID
|
|
29
|
+
if (nameMap[detectorId])
|
|
30
|
+
return nameMap[detectorId];
|
|
31
|
+
// Try to match from template name
|
|
32
|
+
for (const [prefix, name] of Object.entries(nameMap)) {
|
|
33
|
+
if (pattern.templateName.includes(prefix.replace('structural-', ''))) {
|
|
34
|
+
return name;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Fallback: derive from template name
|
|
38
|
+
const cleaned = pattern.templateName
|
|
39
|
+
.replace(/^structural-?/, '')
|
|
40
|
+
.replace(/-\w+$/, '');
|
|
41
|
+
return cleaned || 'unknown';
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Generate example KERN syntax for a proposed node.
|
|
45
|
+
*/
|
|
46
|
+
export function generateKernSyntaxExample(nodeName, pattern) {
|
|
47
|
+
const examples = {
|
|
48
|
+
model: [
|
|
49
|
+
`model name=Example table=examples`,
|
|
50
|
+
` column name=id type=uuid primary=true`,
|
|
51
|
+
` column name=name type=string`,
|
|
52
|
+
].join('\n'),
|
|
53
|
+
repository: [
|
|
54
|
+
`repository name=ExampleRepo model=Example`,
|
|
55
|
+
` method name=findById params="id:string" returns="Example|null"`,
|
|
56
|
+
` handler <<<return this.findOne({ id });>>>`,
|
|
57
|
+
].join('\n'),
|
|
58
|
+
dependency: [
|
|
59
|
+
`dependency name=exampleService scope=singleton`,
|
|
60
|
+
` inject name=repo type=ExampleRepository`,
|
|
61
|
+
` returns ExampleService with=repo`,
|
|
62
|
+
].join('\n'),
|
|
63
|
+
cache: [
|
|
64
|
+
`cache name=exampleCache backend=redis prefix="ex:" ttl=3600`,
|
|
65
|
+
` entry name=item key="ex:{id}"`,
|
|
66
|
+
` strategy read-through`,
|
|
67
|
+
].join('\n'),
|
|
68
|
+
conditional: [
|
|
69
|
+
`conditional if=isEnabled`,
|
|
70
|
+
` text value="Feature enabled"`,
|
|
71
|
+
].join('\n'),
|
|
72
|
+
select: [
|
|
73
|
+
`select name=status value=current placeholder="Choose"`,
|
|
74
|
+
` option value=active label="Active"`,
|
|
75
|
+
` option value=inactive label="Inactive"`,
|
|
76
|
+
].join('\n'),
|
|
77
|
+
};
|
|
78
|
+
return examples[nodeName] || `${nodeName} name=example\n // TODO: define syntax`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Generate a codegen stub for a proposed node.
|
|
82
|
+
*/
|
|
83
|
+
export function generateCodegenStub(nodeName, pattern) {
|
|
84
|
+
const fnName = `generate${nodeName[0].toUpperCase()}${nodeName.slice(1)}`;
|
|
85
|
+
return [
|
|
86
|
+
`export function ${fnName}(node: IRNode): string[] {`,
|
|
87
|
+
` const props = p(node);`,
|
|
88
|
+
` const name = props.name as string;`,
|
|
89
|
+
` const lines: string[] = [];`,
|
|
90
|
+
` // TODO: implement codegen for ${nodeName}`,
|
|
91
|
+
` lines.push(\`// ${nodeName}: \${name}\`);`,
|
|
92
|
+
` return lines;`,
|
|
93
|
+
`}`,
|
|
94
|
+
].join('\n');
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Propose new IR nodes from analyzed structural patterns.
|
|
98
|
+
*
|
|
99
|
+
* Each pattern with an expressibility score above the threshold
|
|
100
|
+
* gets a deterministic node proposal.
|
|
101
|
+
*/
|
|
102
|
+
export function proposeNodes(patterns, scores) {
|
|
103
|
+
const proposals = [];
|
|
104
|
+
for (const pattern of patterns) {
|
|
105
|
+
const score = scores.get(pattern.structuralHash);
|
|
106
|
+
if (!score)
|
|
107
|
+
continue;
|
|
108
|
+
const nodeName = deriveNodeName(pattern);
|
|
109
|
+
const kernSyntax = generateKernSyntaxExample(nodeName, pattern);
|
|
110
|
+
const codegenStub = generateCodegenStub(nodeName, pattern);
|
|
111
|
+
proposals.push({
|
|
112
|
+
id: nextNodeProposalId(),
|
|
113
|
+
nodeName,
|
|
114
|
+
kernSyntax,
|
|
115
|
+
codegenStub,
|
|
116
|
+
targetStubs: {},
|
|
117
|
+
expressibilityScore: score,
|
|
118
|
+
frequency: pattern.instanceCount,
|
|
119
|
+
qualityScore: pattern.qualityScore.overallScore,
|
|
120
|
+
supportingGapIds: pattern.gapIds,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
// Sort by quality score descending
|
|
124
|
+
proposals.sort((a, b) => b.qualityScore - a.qualityScore);
|
|
125
|
+
return proposals;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=node-proposer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-proposer.js","sourceRoot":"","sources":["../src/node-proposer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Validator — validates IR node proposals by parsing + codegen dry-run.
|
|
3
|
+
*
|
|
4
|
+
* Checks:
|
|
5
|
+
* 1. KERN syntax parses without errors
|
|
6
|
+
* 2. Codegen stub compiles (syntax check)
|
|
7
|
+
* 3. Count target coverage
|
|
8
|
+
*/
|
|
9
|
+
import type { NodeProposal, NodeValidationResult } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Validate a node proposal.
|
|
12
|
+
*
|
|
13
|
+
* In v3, this is a lightweight structural check.
|
|
14
|
+
* Full validation (typecheck output, run against all targets) is deferred to promotion.
|
|
15
|
+
*/
|
|
16
|
+
export declare function validateNodeProposal(proposal: NodeProposal): NodeValidationResult;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Validator — validates IR node proposals by parsing + codegen dry-run.
|
|
3
|
+
*
|
|
4
|
+
* Checks:
|
|
5
|
+
* 1. KERN syntax parses without errors
|
|
6
|
+
* 2. Codegen stub compiles (syntax check)
|
|
7
|
+
* 3. Count target coverage
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Validate a node proposal.
|
|
11
|
+
*
|
|
12
|
+
* In v3, this is a lightweight structural check.
|
|
13
|
+
* Full validation (typecheck output, run against all targets) is deferred to promotion.
|
|
14
|
+
*/
|
|
15
|
+
export function validateNodeProposal(proposal) {
|
|
16
|
+
const errors = [];
|
|
17
|
+
// 1. Check KERN syntax is non-empty and parseable-looking
|
|
18
|
+
const parseOk = validateKernSyntax(proposal.kernSyntax, errors);
|
|
19
|
+
// 2. Check codegen stub has expected structure
|
|
20
|
+
const codegenOk = validateCodegenStub(proposal.codegenStub, proposal.nodeName, errors);
|
|
21
|
+
// 3. Count target coverage
|
|
22
|
+
const targetCoverage = countTargetCoverage(proposal);
|
|
23
|
+
return {
|
|
24
|
+
parseOk,
|
|
25
|
+
codegenOk,
|
|
26
|
+
targetCoverage,
|
|
27
|
+
errors,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function validateKernSyntax(syntax, errors) {
|
|
31
|
+
if (!syntax || syntax.trim().length === 0) {
|
|
32
|
+
errors.push('KERN syntax is empty');
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
// Check the syntax has proper indentation structure
|
|
36
|
+
const lines = syntax.split('\n').filter(l => l.trim().length > 0);
|
|
37
|
+
if (lines.length === 0) {
|
|
38
|
+
errors.push('KERN syntax has no non-empty lines');
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
// First line should start with a node type (alpha chars)
|
|
42
|
+
const firstLine = lines[0].trimStart();
|
|
43
|
+
if (!/^[a-zA-Z]/.test(firstLine)) {
|
|
44
|
+
errors.push(`KERN syntax first line doesn't start with a node type: "${firstLine}"`);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
function validateCodegenStub(stub, nodeName, errors) {
|
|
50
|
+
if (!stub || stub.trim().length === 0) {
|
|
51
|
+
errors.push('Codegen stub is empty');
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
// Check it contains a function definition
|
|
55
|
+
if (!stub.includes('function')) {
|
|
56
|
+
errors.push('Codegen stub missing function definition');
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
// Check it references the node name
|
|
60
|
+
const expectedFn = `generate${nodeName[0].toUpperCase()}${nodeName.slice(1)}`;
|
|
61
|
+
if (!stub.includes(expectedFn)) {
|
|
62
|
+
errors.push(`Codegen stub missing expected function name: ${expectedFn}`);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
function countTargetCoverage(proposal) {
|
|
68
|
+
// Core node types work across all targets (11)
|
|
69
|
+
// Target stubs add specific coverage
|
|
70
|
+
const baseCoverage = 11; // core nodes work everywhere
|
|
71
|
+
const stubs = Object.keys(proposal.targetStubs).length;
|
|
72
|
+
return stubs > 0 ? stubs : baseCoverage;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=node-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-validator.js","sourceRoot":"","sources":["../src/node-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAsB;IACzD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,0DAA0D;IAC1D,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAEhE,+CAA+C;IAC/C,MAAM,SAAS,GAAG,mBAAmB,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEvF,2BAA2B;IAC3B,MAAM,cAAc,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAErD,OAAO;QACL,OAAO;QACP,SAAS;QACT,cAAc;QACd,MAAM;KACP,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc,EAAE,MAAgB;IAC1D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,oDAAoD;IACpD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,yDAAyD;IACzD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IACvC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,2DAA2D,SAAS,GAAG,CAAC,CAAC;QACrF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY,EAAE,QAAgB,EAAE,MAAgB;IAC3E,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACrC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,0CAA0C;IAC1C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,oCAAoC;IACpC,MAAM,UAAU,GAAG,WAAW,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,gDAAgD,UAAU,EAAE,CAAC,CAAC;QAC1E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAsB;IACjD,+CAA+C;IAC/C,qCAAqC;IACrC,MAAM,YAAY,GAAG,EAAE,CAAC,CAAC,6BAA6B;IACtD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;IACvD,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
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 type { PatternGap, AnalyzedPattern, QualityThresholds } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Compute a structural hash for a pattern gap.
|
|
10
|
+
*
|
|
11
|
+
* Variables are replaced with placeholders so structurally equivalent
|
|
12
|
+
* patterns (same shape, different values) get the same hash.
|
|
13
|
+
*/
|
|
14
|
+
export declare function computeStructuralHash(gap: PatternGap): string;
|
|
15
|
+
/**
|
|
16
|
+
* Derive a human-readable template name from a gap.
|
|
17
|
+
*
|
|
18
|
+
* Uses the detector ID and key identifiers, not auto-generated garbage.
|
|
19
|
+
*/
|
|
20
|
+
export declare function deriveTemplateName(gap: PatternGap): string;
|
|
21
|
+
/**
|
|
22
|
+
* Analyze structural gaps separately for v3 node proposals.
|
|
23
|
+
*/
|
|
24
|
+
export declare function analyzeStructuralPatterns(gaps: PatternGap[], thresholds?: QualityThresholds): AnalyzedPattern[];
|
|
25
|
+
/**
|
|
26
|
+
* Analyze and group pattern gaps into deduplicated, scored patterns.
|
|
27
|
+
*/
|
|
28
|
+
export declare function analyzePatterns(gaps: PatternGap[], thresholds?: QualityThresholds): AnalyzedPattern[];
|