@aikdna/kdna-core 0.1.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/package.json +44 -0
- package/schema/KDNA_Cases.schema.json +51 -0
- package/schema/KDNA_Cluster.schema.json +53 -0
- package/schema/KDNA_Core.schema.json +102 -0
- package/schema/KDNA_Evolution.schema.json +76 -0
- package/schema/KDNA_Patterns.schema.json +71 -0
- package/schema/KDNA_Reasoning.schema.json +56 -0
- package/schema/KDNA_Scenarios.schema.json +81 -0
- package/schema/kdna-file.schema.json +262 -0
- package/src/index.js +14 -0
- package/src/index.mjs +17 -0
- package/src/lint-pure.js +197 -0
- package/src/loader.js +263 -0
- package/src/render.js +111 -0
- package/src/types.d.ts +254 -0
- package/src/validate-pure.js +131 -0
package/src/loader.js
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KDNA Core Loader — Pure logic for loading KDNA domain cognition.
|
|
3
|
+
*
|
|
4
|
+
* No fs, no path, no Node.js dependencies.
|
|
5
|
+
* Data-first API: accepts already-parsed JSON objects.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const FILE_MAP = {
|
|
9
|
+
core: 'KDNA_Core.json',
|
|
10
|
+
patterns: 'KDNA_Patterns.json',
|
|
11
|
+
scenarios: 'KDNA_Scenarios.json',
|
|
12
|
+
cases: 'KDNA_Cases.json',
|
|
13
|
+
reasoning: 'KDNA_Reasoning.json',
|
|
14
|
+
evolution: 'KDNA_Evolution.json',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Load the minimum required KDNA data from already-parsed objects.
|
|
19
|
+
* @param {object} coreData — parsed KDNA_Core.json
|
|
20
|
+
* @param {object} patternsData — parsed KDNA_Patterns.json
|
|
21
|
+
* @returns {object|null}
|
|
22
|
+
*/
|
|
23
|
+
function loadCorePatternsFromData(coreData, patternsData) {
|
|
24
|
+
if (!coreData || !patternsData) return null;
|
|
25
|
+
return { core: coreData, patterns: patternsData };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Load a complete KDNA domain from a map of already-parsed data.
|
|
30
|
+
*
|
|
31
|
+
* @param {Object} dataMap — keyed by file type: { core, patterns, scenarios?, cases?, reasoning?, evolution? }
|
|
32
|
+
* @param {object} [options]
|
|
33
|
+
* @param {string} [options.input] — user input text for conditional loading
|
|
34
|
+
* @param {'all'|'minimum'|'auto'} [options.mode='auto']
|
|
35
|
+
* @returns {object|null}
|
|
36
|
+
*/
|
|
37
|
+
function loadDomainFromData(dataMap, options = {}) {
|
|
38
|
+
const { input = '', mode = 'auto' } = options;
|
|
39
|
+
|
|
40
|
+
const base = loadCorePatternsFromData(dataMap.core, dataMap.patterns);
|
|
41
|
+
if (!base) return null;
|
|
42
|
+
|
|
43
|
+
const result = { ...base };
|
|
44
|
+
|
|
45
|
+
if (mode === 'minimum') return result;
|
|
46
|
+
|
|
47
|
+
const toLoad =
|
|
48
|
+
mode === 'all'
|
|
49
|
+
? ['scenarios', 'cases', 'reasoning', 'evolution']
|
|
50
|
+
: classifyInput(input);
|
|
51
|
+
|
|
52
|
+
for (const key of toLoad) {
|
|
53
|
+
if (dataMap[key]) result[key] = dataMap[key];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Load a KDNA domain from a map keyed by filename.
|
|
61
|
+
* Converts filename keys to type keys, then delegates to loadDomainFromData.
|
|
62
|
+
*
|
|
63
|
+
* @param {Object} fileDataMap — e.g. { 'KDNA_Core.json': parsedObj, 'KDNA_Patterns.json': parsedObj, ... }
|
|
64
|
+
* @param {object} [options] — same as loadDomainFromData
|
|
65
|
+
* @returns {object|null}
|
|
66
|
+
*/
|
|
67
|
+
function loadDomainFromFiles(fileDataMap, options = {}) {
|
|
68
|
+
const dataMap = {};
|
|
69
|
+
for (const [key, filename] of Object.entries(FILE_MAP)) {
|
|
70
|
+
if (fileDataMap[filename]) dataMap[key] = fileDataMap[filename];
|
|
71
|
+
}
|
|
72
|
+
return loadDomainFromData(dataMap, options);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Determine which optional files to load based on user input text.
|
|
77
|
+
* Pure function — no side effects.
|
|
78
|
+
*
|
|
79
|
+
* @param {string} text
|
|
80
|
+
* @returns {string[]}
|
|
81
|
+
*/
|
|
82
|
+
function classifyInput(text) {
|
|
83
|
+
const lower = (text || '').toLowerCase();
|
|
84
|
+
const optional = [];
|
|
85
|
+
|
|
86
|
+
if (
|
|
87
|
+
/\b(situation|scenario|conflict|happened|tell\s+me\s+about|describe|instance|specific)\b/.test(
|
|
88
|
+
lower,
|
|
89
|
+
) ||
|
|
90
|
+
/(情况|场景|冲突|发生了什么|具体|描述一下|谈谈|说说看)/.test(text || '')
|
|
91
|
+
) {
|
|
92
|
+
optional.push('scenarios');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (
|
|
96
|
+
/\b(example|demonstrat|full\s+case|show\s+me|sample|illustrate|walk\s+through|case)\b/.test(
|
|
97
|
+
lower,
|
|
98
|
+
) ||
|
|
99
|
+
/(案例|示例|演示|展示一下|完整案例|示范|讲解|举例|举个)/.test(text || '')
|
|
100
|
+
) {
|
|
101
|
+
optional.push('cases');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (
|
|
105
|
+
/\b(why|rationale|principle|explain|reason|logic|how\s+come|cause)\b/.test(lower) ||
|
|
106
|
+
/(为什么|原理|逻辑|解释|理由|原因|推理|依据)/.test(text || '')
|
|
107
|
+
) {
|
|
108
|
+
optional.push('reasoning');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (
|
|
112
|
+
/\b(practice|improv|learn|grow|level|progress|measur|assess|evaluat|benchmark)\b/.test(lower) ||
|
|
113
|
+
/(练习|提高|学习|成长|水平|进度|评估|测量|改进|提升|训练)/.test(text || '')
|
|
114
|
+
) {
|
|
115
|
+
optional.push('evolution');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return [...new Set(optional)];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Format a loaded KDNA domain into a context string suitable for
|
|
123
|
+
* inclusion in an agent's system prompt.
|
|
124
|
+
*
|
|
125
|
+
* @param {object} domain — result from loadDomainFromData() or loadDomainFromFiles()
|
|
126
|
+
* @returns {string}
|
|
127
|
+
*/
|
|
128
|
+
function formatContext(domain) {
|
|
129
|
+
if (!domain || !domain.core || !domain.patterns) return '';
|
|
130
|
+
|
|
131
|
+
const parts = [];
|
|
132
|
+
const core = domain.core;
|
|
133
|
+
const pat = domain.patterns;
|
|
134
|
+
|
|
135
|
+
parts.push('## Domain Cognition (KDNA)');
|
|
136
|
+
parts.push(`Domain: ${core.meta.domain}`);
|
|
137
|
+
parts.push('');
|
|
138
|
+
|
|
139
|
+
if (core.stances && core.stances.length) {
|
|
140
|
+
parts.push('### Stances');
|
|
141
|
+
for (const s of core.stances) {
|
|
142
|
+
parts.push(`- ${s}`);
|
|
143
|
+
}
|
|
144
|
+
parts.push('');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (core.axioms && core.axioms.length) {
|
|
148
|
+
parts.push('### Axioms');
|
|
149
|
+
for (const a of core.axioms) {
|
|
150
|
+
parts.push(`- **${a.one_sentence}** ${a.full_statement}`);
|
|
151
|
+
parts.push(` *Why:* ${a.why}`);
|
|
152
|
+
}
|
|
153
|
+
parts.push('');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (core.ontology && core.ontology.length) {
|
|
157
|
+
parts.push('### Key Concepts');
|
|
158
|
+
for (const c of core.ontology) {
|
|
159
|
+
parts.push(`- **${c.id.replace(/_/g, ' ')}** — ${c.one_sentence}`);
|
|
160
|
+
parts.push(` Boundary: ${c.boundary}`);
|
|
161
|
+
}
|
|
162
|
+
parts.push('');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (core.frameworks && core.frameworks.length) {
|
|
166
|
+
parts.push('### Frameworks');
|
|
167
|
+
for (const fw of core.frameworks) {
|
|
168
|
+
parts.push(`- **${fw.name}**: ${fw.when_to_use}`);
|
|
169
|
+
}
|
|
170
|
+
parts.push('');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (pat.terminology && pat.terminology.banned_terms && pat.terminology.banned_terms.length) {
|
|
174
|
+
parts.push('### Avoid These Terms');
|
|
175
|
+
for (const b of pat.terminology.banned_terms) {
|
|
176
|
+
parts.push(`- Avoid "${b.term}". ${b.why} Use "${b.replace_with}" instead.`);
|
|
177
|
+
}
|
|
178
|
+
parts.push('');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (pat.misunderstandings && pat.misunderstandings.length) {
|
|
182
|
+
parts.push('### Watch For These Misunderstandings');
|
|
183
|
+
for (const m of pat.misunderstandings) {
|
|
184
|
+
parts.push(`- **Wrong:** ${m.wrong}`);
|
|
185
|
+
parts.push(` **Correct:** ${m.correct}`);
|
|
186
|
+
}
|
|
187
|
+
parts.push('');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (pat.self_check && pat.self_check.length) {
|
|
191
|
+
parts.push('### Before Responding, Check');
|
|
192
|
+
for (const s of pat.self_check) {
|
|
193
|
+
parts.push(`- [ ] ${s}`);
|
|
194
|
+
}
|
|
195
|
+
parts.push('');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (domain.scenarios && domain.scenarios.scenes) {
|
|
199
|
+
parts.push('### Relevant Scenarios');
|
|
200
|
+
for (const scene of domain.scenarios.scenes) {
|
|
201
|
+
parts.push(`- **${scene.name}**: ${scene.trigger_signal}`);
|
|
202
|
+
}
|
|
203
|
+
parts.push('');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (domain.reasoning && domain.reasoning.reasoning_chains) {
|
|
207
|
+
parts.push('### Reasoning Chains');
|
|
208
|
+
for (const r of domain.reasoning.reasoning_chains) {
|
|
209
|
+
parts.push(`- **${r.one_sentence}** → ${r.so_what}`);
|
|
210
|
+
}
|
|
211
|
+
parts.push('');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (domain.cases && domain.cases.cases && domain.cases.cases.length) {
|
|
215
|
+
parts.push('### Cases');
|
|
216
|
+
for (const c of domain.cases.cases) {
|
|
217
|
+
parts.push(`- **${c.title}**`);
|
|
218
|
+
parts.push(` Context: ${c.context}`);
|
|
219
|
+
parts.push(` What happened: ${c.what_happened}`);
|
|
220
|
+
parts.push(` Learned: ${c.what_was_learned}`);
|
|
221
|
+
parts.push(` Pattern: ${c.structural_pattern}`);
|
|
222
|
+
}
|
|
223
|
+
parts.push('');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (domain.evolution) {
|
|
227
|
+
const evo = domain.evolution;
|
|
228
|
+
if (evo.stages && evo.stages.length) {
|
|
229
|
+
parts.push('### Growth Stages');
|
|
230
|
+
for (const stage of evo.stages) {
|
|
231
|
+
parts.push(`- **${stage.name}**: ${stage.description}`);
|
|
232
|
+
}
|
|
233
|
+
parts.push('');
|
|
234
|
+
}
|
|
235
|
+
if (evo.evolution_layers && evo.evolution_layers.length) {
|
|
236
|
+
parts.push('### Capability Layers');
|
|
237
|
+
for (const layer of evo.evolution_layers) {
|
|
238
|
+
parts.push(
|
|
239
|
+
`- **${layer.name}**: ${layer.capability} (${layer.from_stage} → ${layer.to_stage})`,
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
parts.push('');
|
|
243
|
+
}
|
|
244
|
+
if (evo.measurement && evo.measurement.length) {
|
|
245
|
+
parts.push('### Measurement');
|
|
246
|
+
for (const m of evo.measurement) {
|
|
247
|
+
parts.push(`- **${m.what}**: ${m.how} (threshold: ${m.threshold})`);
|
|
248
|
+
}
|
|
249
|
+
parts.push('');
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return parts.join('\n').trim();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
module.exports = {
|
|
257
|
+
FILE_MAP,
|
|
258
|
+
loadCorePatternsFromData,
|
|
259
|
+
loadDomainFromData,
|
|
260
|
+
loadDomainFromFiles,
|
|
261
|
+
classifyInput,
|
|
262
|
+
formatContext,
|
|
263
|
+
};
|
package/src/render.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KDNA Render — Pure HTML rendering for KDNA domain preview.
|
|
3
|
+
*
|
|
4
|
+
* No fs, no path, no Node.js dependencies.
|
|
5
|
+
* Takes a loaded domain object and optional manifest, returns HTML string.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Escape HTML special characters.
|
|
10
|
+
* @param {string} s
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
function escHtml(s) {
|
|
14
|
+
return (s || '')
|
|
15
|
+
.replace(/&/g, '&')
|
|
16
|
+
.replace(/</g, '<')
|
|
17
|
+
.replace(/>/g, '>')
|
|
18
|
+
.replace(/"/g, '"');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Render a card section.
|
|
23
|
+
* @param {string} title
|
|
24
|
+
* @param {number|undefined} count
|
|
25
|
+
* @param {string} items — HTML string of card items
|
|
26
|
+
* @returns {string}
|
|
27
|
+
*/
|
|
28
|
+
function renderCard(title, count, items) {
|
|
29
|
+
if (!count || !items) return '';
|
|
30
|
+
return `<div class="card"><h3>${title} <span>${count}</span></h3>${items}</div>`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Render a full KDNA domain as a preview HTML page.
|
|
35
|
+
*
|
|
36
|
+
* @param {object} domain — loaded domain from loadDomainFromData() / loadDomainFromFiles()
|
|
37
|
+
* @param {object} [manifest] — parsed kdna.json manifest
|
|
38
|
+
* @returns {string} complete HTML document
|
|
39
|
+
*/
|
|
40
|
+
function renderPreviewHTML(domain, manifest) {
|
|
41
|
+
if (!domain || !domain.core) return '<!DOCTYPE html><html><body><p>No domain data</p></body></html>';
|
|
42
|
+
|
|
43
|
+
const core = domain.core;
|
|
44
|
+
const patterns = domain.patterns;
|
|
45
|
+
const scenarios = domain.scenarios;
|
|
46
|
+
const cases = domain.cases;
|
|
47
|
+
const reasoning = domain.reasoning;
|
|
48
|
+
const evolution = domain.evolution;
|
|
49
|
+
|
|
50
|
+
const name = manifest?.name || core.meta?.domain || 'Unnamed Domain';
|
|
51
|
+
const version = manifest?.version || core.meta?.version || '?';
|
|
52
|
+
const status = manifest?.status || 'experimental';
|
|
53
|
+
const desc = manifest?.description || core.meta?.purpose || '';
|
|
54
|
+
|
|
55
|
+
// Count present files
|
|
56
|
+
const fileCount = ['core', 'patterns', 'scenarios', 'cases', 'reasoning', 'evolution']
|
|
57
|
+
.filter((k) => domain[k])
|
|
58
|
+
.length;
|
|
59
|
+
|
|
60
|
+
return `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>${escHtml(name)} — KDNA Preview</title>
|
|
61
|
+
<style>
|
|
62
|
+
:root{--bg:#08100d;--bg2:#0d1713;--border:#24352b;--text:#f0ead7;--dim:#c3baa0;--muted:#8b836c;--accent:#d1ad63;--green:#76b987;--red:#df806d;--blue:#8fa7d7;--sans:Inter,system-ui,sans-serif;--mono:SF Mono,monospace}
|
|
63
|
+
*{box-sizing:border-box;margin:0;padding:0}body{background:var(--bg);color:var(--text);font-family:var(--sans);line-height:1.6;max-width:960px;margin:0 auto;padding:40px 24px}
|
|
64
|
+
.meta{display:flex;flex-wrap:wrap;gap:16px;align-items:center;padding:20px 24px;border:1px solid var(--border);border-radius:10px;background:var(--bg2);margin-bottom:24px}
|
|
65
|
+
.meta .name{font-size:24px;font-weight:700}
|
|
66
|
+
.meta .ver{color:var(--muted);font-size:14px}
|
|
67
|
+
.meta .badge{padding:3px 12px;border-radius:999px;font-size:11px;font-weight:700}
|
|
68
|
+
.badge-ok{background:rgba(118,185,135,.15);color:var(--green)}
|
|
69
|
+
.badge-warn{background:rgba(209,173,99,.15);color:var(--accent)}
|
|
70
|
+
.desc{color:var(--dim);margin:16px 0 24px;font-size:15px;line-height:1.7}
|
|
71
|
+
.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(380px,1fr));gap:14px}
|
|
72
|
+
.card{border:1px solid var(--border);border-radius:10px;background:var(--bg2);padding:20px}
|
|
73
|
+
.card h3{font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:14px;display:flex;justify-content:space-between}
|
|
74
|
+
.card h3 span{color:var(--dim);font-weight:400}
|
|
75
|
+
.card .item{padding:10px 0;border-bottom:1px solid rgba(36,53,43,.5)}
|
|
76
|
+
.card .item:last-child{border-bottom:0}
|
|
77
|
+
.card .item strong{display:block;font-size:14px;margin-bottom:2px}
|
|
78
|
+
.card .item .detail{font-size:13px;color:var(--dim);line-height:1.5}
|
|
79
|
+
.card .item .meta{font-size:11px;color:var(--muted);margin-top:2px;padding:0;border:0;background:transparent;margin-bottom:0}
|
|
80
|
+
.card .item .why{color:var(--red);font-size:12px}
|
|
81
|
+
.card .item .replace{color:var(--green);font-size:12px}
|
|
82
|
+
.footer{text-align:center;color:var(--muted);margin-top:40px;font-size:13px}
|
|
83
|
+
.footer a{color:var(--accent)}
|
|
84
|
+
@media(max-width:680px){.cards{grid-template-columns:1fr}}
|
|
85
|
+
</style></head><body>
|
|
86
|
+
<h1 style="font-size:14px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:16px">KDNA Domain Preview</h1>
|
|
87
|
+
<div class="meta">
|
|
88
|
+
<span class="name">${escHtml(name)}</span>
|
|
89
|
+
<span class="ver">v${escHtml(version)}</span>
|
|
90
|
+
<span class="badge badge-${status === 'validated' || status === 'stable' ? 'ok' : 'warn'}">${escHtml(status)}</span>
|
|
91
|
+
<span style="color:var(--dim);font-size:13px">${fileCount} files</span>
|
|
92
|
+
</div>
|
|
93
|
+
${desc ? `<p class="desc">${escHtml(desc)}</p>` : ''}
|
|
94
|
+
<div class="cards">
|
|
95
|
+
${renderCard('Axioms', core.axioms?.length, (core.axioms || []).map((a) => `<div class="item"><strong>${escHtml(a.one_sentence || '')}</strong><div class="detail">${escHtml(a.full_statement || a.why || '')}</div></div>`).join(''))}
|
|
96
|
+
${renderCard('Concepts', core.ontology?.length, (core.ontology || []).map((o) => `<div class="item"><strong>${escHtml(o.one_sentence || o.id || '')}</strong><div class="detail">${escHtml(o.essence || '')}</div><div class="meta">Boundary: ${escHtml(o.boundary || '')}</div></div>`).join(''))}
|
|
97
|
+
${renderCard('Frameworks', core.frameworks?.length, (core.frameworks || []).map((f) => `<div class="item"><strong>${escHtml(f.name || '')}</strong><div class="detail">When: ${escHtml(f.when_to_use || '')}</div><div class="detail">Steps: ${(f.steps || []).map((s) => escHtml(s)).join(' → ')}</div></div>`).join(''))}
|
|
98
|
+
${renderCard('Stances', core.stances?.length, (core.stances || []).map((s) => `<div class="item"><strong>${escHtml(typeof s === 'string' ? s : s.one_sentence || '')}</strong></div>`).join(''))}
|
|
99
|
+
${renderCard('Banned Terms', patterns?.terminology?.banned_terms?.length, (patterns?.terminology?.banned_terms || []).map((bt) => `<div class="item"><strong>${escHtml(bt.term)} <span class="replace">→ ${escHtml(bt.replace_with || '')}</span></strong><div class="why">${escHtml(bt.why || '')}</div></div>`).join(''))}
|
|
100
|
+
${renderCard('Misunderstandings', patterns?.misunderstandings?.length, (patterns?.misunderstandings || []).map((mu) => `<div class="item"><strong>Wrong: ${escHtml(mu.wrong || '')}</strong><div class="detail">Correct: ${escHtml(mu.correct || '')}</div><div class="meta">${escHtml(mu.key_distinction || '')}</div></div>`).join(''))}
|
|
101
|
+
${renderCard('Self-Checks', patterns?.self_check?.length, (patterns?.self_check || []).map((sc) => `<div class="item"><strong>✓ ${escHtml(typeof sc === 'string' ? sc : sc.one_sentence || '')}</strong></div>`).join(''))}
|
|
102
|
+
${scenarios ? renderCard('Scenarios', scenarios.scenes?.length || 0, (scenarios.scenes || []).map((s) => `<div class="item"><strong>${escHtml(s.name || s.id || '')}</strong><div class="detail">${escHtml(s.trigger_signal || '')}</div></div>`).join('')) : ''}
|
|
103
|
+
${cases ? renderCard('Cases', cases.cases?.length || 0, (cases.cases || []).map((c) => `<div class="item"><strong>${escHtml(c.title || c.id || '')}</strong><div class="detail">${escHtml((c.what_was_learned || '').substring(0, 150))}</div></div>`).join('')) : ''}
|
|
104
|
+
${reasoning ? renderCard('Reasoning', reasoning.reasoning_chains?.length || 0, (reasoning.reasoning_chains || []).map((r) => `<div class="item"><strong>${escHtml(r.one_sentence || r.id || '')}</strong><div class="detail">${escHtml(r.so_what || '')}</div></div>`).join('')) : ''}
|
|
105
|
+
${evolution ? renderCard('Evolution', evolution.stages?.length || 0, (evolution.stages || []).map((s) => `<div class="item"><strong>${escHtml(s.name || s.id || '')}</strong><div class="detail">${escHtml(s.description || '')}</div></div>`).join('')) : ''}
|
|
106
|
+
</div>
|
|
107
|
+
<div class="footer">Generated: ${new Date().toISOString().slice(0, 10)} · <a href="https://aikdna.com">aikdna.com</a></div>
|
|
108
|
+
</body></html>`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports = { renderPreviewHTML, escHtml, renderCard };
|
package/src/types.d.ts
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
export interface KDNAMeta {
|
|
2
|
+
version: string;
|
|
3
|
+
domain: string;
|
|
4
|
+
created: string;
|
|
5
|
+
purpose: string;
|
|
6
|
+
load_condition: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface KDNAAxiom {
|
|
10
|
+
id: string;
|
|
11
|
+
one_sentence: string;
|
|
12
|
+
full_statement: string;
|
|
13
|
+
why: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface KDNAOntologyConcept {
|
|
17
|
+
id: string;
|
|
18
|
+
one_sentence: string;
|
|
19
|
+
essence: string;
|
|
20
|
+
boundary: string;
|
|
21
|
+
trigger_signal: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface KDNAFramework {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
when_to_use: string;
|
|
28
|
+
steps: string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface KDNACoreStructure {
|
|
32
|
+
from: string;
|
|
33
|
+
to: string;
|
|
34
|
+
via: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface KDNACore {
|
|
38
|
+
meta: KDNAMeta;
|
|
39
|
+
axioms: KDNAAxiom[];
|
|
40
|
+
ontology: KDNAOntologyConcept[];
|
|
41
|
+
frameworks: KDNAFramework[];
|
|
42
|
+
core_structure: KDNACoreStructure[];
|
|
43
|
+
stances: string[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface KDNAStandardTerm {
|
|
47
|
+
term: string;
|
|
48
|
+
definition: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface KDNABannedTerm {
|
|
52
|
+
term: string;
|
|
53
|
+
why: string;
|
|
54
|
+
replace_with: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface KDNATerminology {
|
|
58
|
+
standard_terms: KDNAStandardTerm[];
|
|
59
|
+
banned_terms: KDNABannedTerm[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface KDNAMisunderstanding {
|
|
63
|
+
id: string;
|
|
64
|
+
wrong: string;
|
|
65
|
+
correct: string;
|
|
66
|
+
key_distinction: string;
|
|
67
|
+
why: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface KDNAPatterns {
|
|
71
|
+
meta: KDNAMeta;
|
|
72
|
+
terminology: KDNATerminology;
|
|
73
|
+
misunderstandings: KDNAMisunderstanding[];
|
|
74
|
+
self_check: string[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface KDNASubScenario {
|
|
78
|
+
id: string;
|
|
79
|
+
trap_belief: string;
|
|
80
|
+
three_questions: {
|
|
81
|
+
belief: string;
|
|
82
|
+
state: string;
|
|
83
|
+
need: string;
|
|
84
|
+
};
|
|
85
|
+
action_template: string[];
|
|
86
|
+
replace: {
|
|
87
|
+
avoid: string;
|
|
88
|
+
use: string;
|
|
89
|
+
}[];
|
|
90
|
+
expected_result: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface KDNAScene {
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
trigger_signal: string;
|
|
97
|
+
sub_scenarios: KDNASubScenario[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface KDNAScenarios {
|
|
101
|
+
meta: KDNAMeta;
|
|
102
|
+
scenes: KDNAScene[];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface KDNACase {
|
|
106
|
+
id: string;
|
|
107
|
+
scene_id?: string;
|
|
108
|
+
title: string;
|
|
109
|
+
context: string;
|
|
110
|
+
what_happened: string;
|
|
111
|
+
what_was_learned: string;
|
|
112
|
+
structural_pattern: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface KDNACases {
|
|
116
|
+
meta: KDNAMeta;
|
|
117
|
+
cases: KDNACase[];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface KDNAReasoningChain {
|
|
121
|
+
id: string;
|
|
122
|
+
one_sentence: string;
|
|
123
|
+
logic: string[];
|
|
124
|
+
so_what: string;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface KDNAReasoning {
|
|
128
|
+
meta: KDNAMeta;
|
|
129
|
+
reasoning_chains: KDNAReasoningChain[];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface KDNAStage {
|
|
133
|
+
id: string;
|
|
134
|
+
name: string;
|
|
135
|
+
description: string;
|
|
136
|
+
indicators: string[];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface KDNAEvolutionLayer {
|
|
140
|
+
id: string;
|
|
141
|
+
name: string;
|
|
142
|
+
capability: string;
|
|
143
|
+
from_stage: string;
|
|
144
|
+
to_stage: string;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface KDNAMeasurement {
|
|
148
|
+
id: string;
|
|
149
|
+
what: string;
|
|
150
|
+
how: string;
|
|
151
|
+
threshold: string;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export interface KDNAEvolution {
|
|
155
|
+
meta: KDNAMeta;
|
|
156
|
+
stages: KDNAStage[];
|
|
157
|
+
evolution_layers: KDNAEvolutionLayer[];
|
|
158
|
+
measurement: KDNAMeasurement[];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export type KDNADomainFile =
|
|
162
|
+
| KDNACore
|
|
163
|
+
| KDNAPatterns
|
|
164
|
+
| KDNAScenarios
|
|
165
|
+
| KDNACases
|
|
166
|
+
| KDNAReasoning
|
|
167
|
+
| KDNAEvolution;
|
|
168
|
+
|
|
169
|
+
export interface LoadedDomain {
|
|
170
|
+
core: KDNACore;
|
|
171
|
+
patterns: KDNAPatterns;
|
|
172
|
+
scenarios?: KDNAScenarios;
|
|
173
|
+
cases?: KDNACases;
|
|
174
|
+
reasoning?: KDNAReasoning;
|
|
175
|
+
evolution?: KDNAEvolution;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export interface LoadOptions {
|
|
179
|
+
input?: string;
|
|
180
|
+
mode?: 'all' | 'minimum' | 'auto';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** Data map keyed by type (core, patterns, scenarios, etc.) */
|
|
184
|
+
export interface KDNADataMap {
|
|
185
|
+
core: KDNACore;
|
|
186
|
+
patterns: KDNAPatterns;
|
|
187
|
+
scenarios?: KDNAScenarios;
|
|
188
|
+
cases?: KDNACases;
|
|
189
|
+
reasoning?: KDNAReasoning;
|
|
190
|
+
evolution?: KDNAEvolution;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** Data map keyed by filename */
|
|
194
|
+
export interface KDNAFileDataMap {
|
|
195
|
+
'KDNA_Core.json': KDNACore;
|
|
196
|
+
'KDNA_Patterns.json': KDNAPatterns;
|
|
197
|
+
'KDNA_Scenarios.json'?: KDNAScenarios;
|
|
198
|
+
'KDNA_Cases.json'?: KDNACases;
|
|
199
|
+
'KDNA_Reasoning.json'?: KDNAReasoning;
|
|
200
|
+
'KDNA_Evolution.json'?: KDNAEvolution;
|
|
201
|
+
'kdna.json'?: KDNAManifest;
|
|
202
|
+
[key: string]: any;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface KDNAManifest {
|
|
206
|
+
kdna_spec: string;
|
|
207
|
+
name: string;
|
|
208
|
+
version: string;
|
|
209
|
+
status: 'experimental' | 'basic' | 'stable' | 'pro';
|
|
210
|
+
access: 'open' | 'licensed' | 'runtime';
|
|
211
|
+
language: string;
|
|
212
|
+
author: { name: string; id?: string };
|
|
213
|
+
license: { type: string; url?: string };
|
|
214
|
+
description: string;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export interface LintResult {
|
|
218
|
+
errors: string[];
|
|
219
|
+
warnings: string[];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface ValidationResult {
|
|
223
|
+
valid: boolean;
|
|
224
|
+
errors: string[];
|
|
225
|
+
warnings: string[];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Loader — data-first API
|
|
229
|
+
export function loadCorePatternsFromData(
|
|
230
|
+
coreData: KDNACore,
|
|
231
|
+
patternsData: KDNAPatterns,
|
|
232
|
+
): { core: KDNACore; patterns: KDNAPatterns } | null;
|
|
233
|
+
|
|
234
|
+
export function loadDomainFromData(dataMap: KDNADataMap, options?: LoadOptions): LoadedDomain | null;
|
|
235
|
+
|
|
236
|
+
export function loadDomainFromFiles(fileDataMap: KDNAFileDataMap, options?: LoadOptions): LoadedDomain | null;
|
|
237
|
+
|
|
238
|
+
export function classifyInput(text: string): string[];
|
|
239
|
+
|
|
240
|
+
export function formatContext(domain: LoadedDomain): string;
|
|
241
|
+
|
|
242
|
+
export const FILE_MAP: Record<string, string>;
|
|
243
|
+
|
|
244
|
+
// Lint
|
|
245
|
+
export function lintDomain(dataMap: KDNAFileDataMap): LintResult;
|
|
246
|
+
|
|
247
|
+
// Validate
|
|
248
|
+
export function validateDomainSchema(dataMap: KDNAFileDataMap, schemaMap?: Record<string, any>): ValidationResult;
|
|
249
|
+
export function validateCrossFile(dataMap: KDNAFileDataMap): ValidationResult;
|
|
250
|
+
|
|
251
|
+
// Render
|
|
252
|
+
export function renderPreviewHTML(domain: LoadedDomain, manifest?: KDNAManifest): string;
|
|
253
|
+
export function escHtml(s: string): string;
|
|
254
|
+
export function renderCard(title: string, count: number | undefined, items: string): string;
|