@aikdna/kdna-core 0.3.0 → 0.5.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/README.md +96 -2
- package/package.json +6 -4
- package/schema/KDNA_Core.schema.json +4 -1
- package/schema/KDNA_Core.strict.schema.json +290 -0
- package/schema/KDNA_Patterns.schema.json +12 -6
- package/schema/KDNA_Patterns.strict.schema.json +342 -0
- package/schema/KDNA_Scenarios.schema.json +2 -1
- package/schema/KDNA_Scenarios.strict.schema.json +101 -0
- package/src/asset-reader.js +585 -0
- package/src/compose.js +2 -2
- package/src/crypto-profile.js +106 -0
- package/src/index.js +4 -0
- package/src/index.mjs +11 -0
- package/src/lint-pure.js +159 -4
- package/src/loader.js +30 -20
- package/src/types.d.ts +175 -3
- package/src/validate-pure.js +1 -7
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @aikdna/kdna-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Core library for loading, validating, linting, rendering, composing, and directly reading KDNA `.kdna` cognition assets. It has zero npm runtime dependencies.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -11,7 +11,12 @@ npm install @aikdna/kdna-core
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
13
|
```js
|
|
14
|
-
const {
|
|
14
|
+
const {
|
|
15
|
+
createKdnaAssetReader,
|
|
16
|
+
lintDomain,
|
|
17
|
+
validateDomainSchema,
|
|
18
|
+
validateCrossFile
|
|
19
|
+
} = require('@aikdna/kdna-core');
|
|
15
20
|
|
|
16
21
|
// Validate a domain
|
|
17
22
|
const dataMap = {
|
|
@@ -26,6 +31,65 @@ const crossResult = validateCrossFile(dataMap);
|
|
|
26
31
|
|
|
27
32
|
## API
|
|
28
33
|
|
|
34
|
+
### `createKdnaAssetReader()`
|
|
35
|
+
|
|
36
|
+
Direct `.kdna` container reader. The reader opens ZIP-backed `.kdna` assets without persistent extraction and exposes:
|
|
37
|
+
|
|
38
|
+
- `open(pathOrBytes)`
|
|
39
|
+
- `listEntries(asset)`
|
|
40
|
+
- `readEntry(asset, entryName)`
|
|
41
|
+
- `readJson(asset, entryName)`
|
|
42
|
+
- `readManifest(asset)`
|
|
43
|
+
- `readDataMap(asset)`
|
|
44
|
+
- `contentDigest(asset)`
|
|
45
|
+
- `verify(asset, { asset_digest?, content_digest?, requireSignature? })`
|
|
46
|
+
- `loadProfile(asset, "index" | "compact" | "scenario" | "full", options?)`
|
|
47
|
+
|
|
48
|
+
Example:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
const { createKdnaAssetReader } = require('@aikdna/kdna-core');
|
|
52
|
+
|
|
53
|
+
const reader = createKdnaAssetReader();
|
|
54
|
+
const asset = await reader.open('./writing.kdna');
|
|
55
|
+
const manifest = await reader.readManifest(asset);
|
|
56
|
+
const trust = await reader.verify(asset, { requireSignature: true });
|
|
57
|
+
const loaded = await reader.loadProfile(asset, 'compact');
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The asset reader treats extraction caches as implementation details. The `.kdna` file remains the identity, install, verification, and loading object.
|
|
61
|
+
|
|
62
|
+
Licensed assets can list encrypted JSON entries in `kdna.json`:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"access": "licensed",
|
|
67
|
+
"encryption": {
|
|
68
|
+
"profile": "kdna-licensed-entry-v1",
|
|
69
|
+
"encrypted_entries": ["KDNA_Core.json", "KDNA_Patterns.json"]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The reader never writes decrypted entries to disk. Callers provide an in-memory
|
|
75
|
+
`decryptEntry` hook when they have already validated license activation:
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
const { createLicensedDecryptEntry } = require('@aikdna/kdna-core');
|
|
79
|
+
|
|
80
|
+
const decryptEntry = createLicensedDecryptEntry({
|
|
81
|
+
licenseKey: activation.license_key,
|
|
82
|
+
machineFingerprint: activation.machine_fingerprint
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const loaded = await reader.loadProfile(asset, 'compact', { decryptEntry });
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The profile uses AES-256-GCM over each protected entry and derives the entry key
|
|
89
|
+
from the license key plus machine fingerprint using `scrypt-sha256`. This is a
|
|
90
|
+
runtime primitive, not a license activation system; callers must validate license
|
|
91
|
+
status before passing a decrypt hook to the reader.
|
|
92
|
+
|
|
29
93
|
### `lintDomain(dataMap)`
|
|
30
94
|
Structural linting — checks required files, field presence, unique IDs, yes/no answerable self-checks, cross-file references, and flags potentially vague axioms.
|
|
31
95
|
|
|
@@ -44,6 +108,36 @@ Returns `{ errors: string[], warnings: string[] }`.
|
|
|
44
108
|
### `renderDomain(dataMap, options?)`
|
|
45
109
|
Renders domain files into a structured context block using a standard template. The rendered context preserves the domain's structure as distinct, named sections suitable for agent system prompts.
|
|
46
110
|
|
|
111
|
+
## Compose API (9 functions)
|
|
112
|
+
|
|
113
|
+
Multi-domain composition — load multiple KDNA domains, classify which should activate for a given input, detect conflicts, and merge their judgment into a single agent context.
|
|
114
|
+
|
|
115
|
+
### Context Composition
|
|
116
|
+
|
|
117
|
+
- **`composeContext(domains, options?)`** — Merge multiple loaded domains into a single context string. Conflicting axioms or banned terms from different domains are both included; the agent must report the conflict rather than silently resolve it.
|
|
118
|
+
|
|
119
|
+
- **`composeContextWithAttribution(domains, options?)`** — Same as `composeContext`, but every axiom, misunderstanding, banned term, and self-check is prefixed with its origin domain (e.g., `[writing:axiom.axiom_problem_not_prose]`). Returns `{ context, attributionMap }`.
|
|
120
|
+
|
|
121
|
+
- **`loadAndCompose(dataMaps, options?)`** — Convenience function: loads each domain from file data maps, classifies signals against input, then composes the active domains. Returns `{ domains, context, activeIndices }`.
|
|
122
|
+
|
|
123
|
+
### Signal Classification
|
|
124
|
+
|
|
125
|
+
- **`classifySignals(input, domains)`** — Match user input against each domain's `trigger_signals`. Returns indices of matching domains. Domains with no signals defined are treated as primary (always active).
|
|
126
|
+
|
|
127
|
+
- **`classifySignalsAcrossDomains(input, domainEntries)`** — Full diagnostic version of signal classification. Returns `{ selected, excluded }` with reasons (`signal_match`, `required`, `blocked by does_not_apply_when`, `no signal match`).
|
|
128
|
+
|
|
129
|
+
### Cluster Operations
|
|
130
|
+
|
|
131
|
+
- **`loadCluster(clusterManifestPath, domainLoader)`** — Load a cluster manifest (`kdna.cluster.json`) and resolve each domain via the provided loader function. Returns `{ manifest, domains, errors }`.
|
|
132
|
+
|
|
133
|
+
- **`detectDomainConflicts(domains)`** — Detect conflicts between loaded domains in a cluster. Currently checks for: (1) banned term collisions across domains, (2) contradictory stances (simple negation heuristic). Returns array of conflict objects with `type`, `domains`, and `description`.
|
|
134
|
+
|
|
135
|
+
- **`generateClusterTrace({ input, loadedDomains, activeDomains, conflicts })`** — Generate a judgment trace record for a cluster operation. Returns `{ input, timestamp, loaded_domains, active_domains, active_count, domains_excluded, conflicts }`.
|
|
136
|
+
|
|
137
|
+
### Utilities
|
|
138
|
+
|
|
139
|
+
- **`composeChecks(domains)`** — Merge self-check items from multiple domains into a single checklist. Each item is prefixed with its domain name so overlaps are visible.
|
|
140
|
+
|
|
47
141
|
## License
|
|
48
142
|
|
|
49
143
|
Apache-2.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aikdna/kdna-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "KDNA core library — pure logic for loading, validating, linting, and rendering KDNA domain cognition packages. Zero Node.js dependencies.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"./schema/*": "./schema/*"
|
|
16
16
|
},
|
|
17
17
|
"types": "src/types.d.ts",
|
|
18
|
+
"scripts": {
|
|
19
|
+
"test": "node --test test/*.test.js && node -e \"const m = require('./src/index.js'); console.log('kdna-core exports:', Object.keys(m).join(', '));\""
|
|
20
|
+
},
|
|
18
21
|
"files": [
|
|
19
22
|
"src/",
|
|
20
23
|
"schema/",
|
|
@@ -24,13 +27,12 @@
|
|
|
24
27
|
"kdna",
|
|
25
28
|
"kdna-core",
|
|
26
29
|
"ai-agent",
|
|
27
|
-
"domain-cognition"
|
|
28
|
-
"knowledge-dna"
|
|
30
|
+
"domain-cognition"
|
|
29
31
|
],
|
|
30
32
|
"license": "Apache-2.0",
|
|
31
33
|
"repository": {
|
|
32
34
|
"type": "git",
|
|
33
|
-
"url": "git+https://github.com/
|
|
35
|
+
"url": "git+https://github.com/aikdna/kdna.git",
|
|
34
36
|
"directory": "packages/kdna-core"
|
|
35
37
|
},
|
|
36
38
|
"homepage": "https://aikdna.com",
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "KDNA_Core",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": [
|
|
6
|
+
"meta",
|
|
7
|
+
"axioms",
|
|
8
|
+
"ontology",
|
|
9
|
+
"frameworks",
|
|
10
|
+
"core_structure",
|
|
11
|
+
"stances"
|
|
12
|
+
],
|
|
13
|
+
"properties": {
|
|
14
|
+
"meta": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"required": [
|
|
17
|
+
"version",
|
|
18
|
+
"domain",
|
|
19
|
+
"created",
|
|
20
|
+
"purpose",
|
|
21
|
+
"load_condition"
|
|
22
|
+
],
|
|
23
|
+
"properties": {
|
|
24
|
+
"version": {
|
|
25
|
+
"type": "string"
|
|
26
|
+
},
|
|
27
|
+
"domain": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"pattern": "^[a-z][a-z0-9_]*$"
|
|
30
|
+
},
|
|
31
|
+
"created": {
|
|
32
|
+
"type": "string"
|
|
33
|
+
},
|
|
34
|
+
"purpose": {
|
|
35
|
+
"type": "string"
|
|
36
|
+
},
|
|
37
|
+
"load_condition": {
|
|
38
|
+
"type": "string"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"additionalProperties": true
|
|
42
|
+
},
|
|
43
|
+
"highest_question": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"description": "The highest-order question this domain answers."
|
|
46
|
+
},
|
|
47
|
+
"worldview": {
|
|
48
|
+
"type": "array",
|
|
49
|
+
"items": {
|
|
50
|
+
"type": "string"
|
|
51
|
+
},
|
|
52
|
+
"description": "Default assumptions about how the world works in this domain."
|
|
53
|
+
},
|
|
54
|
+
"judgment_role": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"properties": {
|
|
57
|
+
"acts_as": {
|
|
58
|
+
"type": "string"
|
|
59
|
+
},
|
|
60
|
+
"does_not_act_as": {
|
|
61
|
+
"oneOf": [
|
|
62
|
+
{ "type": "string" },
|
|
63
|
+
{ "type": "array", "items": { "type": "string" } }
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
"responsibility": {
|
|
67
|
+
"type": "string"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"additionalProperties": true
|
|
71
|
+
},
|
|
72
|
+
"value_order": {
|
|
73
|
+
"type": "array",
|
|
74
|
+
"items": {
|
|
75
|
+
"type": "string"
|
|
76
|
+
},
|
|
77
|
+
"description": "Priority ordering of values in this domain."
|
|
78
|
+
},
|
|
79
|
+
"axioms": {
|
|
80
|
+
"type": "array",
|
|
81
|
+
"items": {
|
|
82
|
+
"type": "object",
|
|
83
|
+
"required": [
|
|
84
|
+
"id",
|
|
85
|
+
"one_sentence",
|
|
86
|
+
"full_statement",
|
|
87
|
+
"why",
|
|
88
|
+
"applies_when",
|
|
89
|
+
"does_not_apply_when",
|
|
90
|
+
"failure_risk",
|
|
91
|
+
"confidence"
|
|
92
|
+
],
|
|
93
|
+
"properties": {
|
|
94
|
+
"id": {
|
|
95
|
+
"type": "string"
|
|
96
|
+
},
|
|
97
|
+
"one_sentence": {
|
|
98
|
+
"type": "string"
|
|
99
|
+
},
|
|
100
|
+
"full_statement": {
|
|
101
|
+
"type": "string"
|
|
102
|
+
},
|
|
103
|
+
"why": {
|
|
104
|
+
"type": "string"
|
|
105
|
+
},
|
|
106
|
+
"confidence": {
|
|
107
|
+
"type": "string"
|
|
108
|
+
},
|
|
109
|
+
"evidence_type": {
|
|
110
|
+
"type": "array",
|
|
111
|
+
"items": {
|
|
112
|
+
"type": "string"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"applies_when": {
|
|
116
|
+
"type": "array",
|
|
117
|
+
"items": {
|
|
118
|
+
"type": "string"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"does_not_apply_when": {
|
|
122
|
+
"type": "array",
|
|
123
|
+
"items": {
|
|
124
|
+
"type": "string"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"failure_risk": {
|
|
128
|
+
"type": "string"
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"additionalProperties": true
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"ontology": {
|
|
135
|
+
"type": "array",
|
|
136
|
+
"items": {
|
|
137
|
+
"type": "object",
|
|
138
|
+
"required": [
|
|
139
|
+
"id",
|
|
140
|
+
"one_sentence",
|
|
141
|
+
"essence",
|
|
142
|
+
"boundary",
|
|
143
|
+
"trigger_signal"
|
|
144
|
+
],
|
|
145
|
+
"properties": {
|
|
146
|
+
"id": {
|
|
147
|
+
"type": "string"
|
|
148
|
+
},
|
|
149
|
+
"one_sentence": {
|
|
150
|
+
"type": "string"
|
|
151
|
+
},
|
|
152
|
+
"essence": {
|
|
153
|
+
"type": "string"
|
|
154
|
+
},
|
|
155
|
+
"boundary": {
|
|
156
|
+
"type": "string"
|
|
157
|
+
},
|
|
158
|
+
"trigger_signal": {
|
|
159
|
+
"type": "string"
|
|
160
|
+
},
|
|
161
|
+
"applies_when": {
|
|
162
|
+
"type": "array",
|
|
163
|
+
"items": {
|
|
164
|
+
"type": "string"
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"does_not_apply_when": {
|
|
168
|
+
"type": "array",
|
|
169
|
+
"items": {
|
|
170
|
+
"type": "string"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"additionalProperties": true
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
"frameworks": {
|
|
178
|
+
"type": "array",
|
|
179
|
+
"items": {
|
|
180
|
+
"type": "object",
|
|
181
|
+
"required": [
|
|
182
|
+
"id",
|
|
183
|
+
"name",
|
|
184
|
+
"when_to_use",
|
|
185
|
+
"steps"
|
|
186
|
+
],
|
|
187
|
+
"properties": {
|
|
188
|
+
"id": {
|
|
189
|
+
"type": "string"
|
|
190
|
+
},
|
|
191
|
+
"name": {
|
|
192
|
+
"type": "string"
|
|
193
|
+
},
|
|
194
|
+
"when_to_use": {
|
|
195
|
+
"type": "string"
|
|
196
|
+
},
|
|
197
|
+
"steps": {
|
|
198
|
+
"type": "array",
|
|
199
|
+
"items": {
|
|
200
|
+
"type": "string"
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
"applies_when": {
|
|
204
|
+
"type": "array",
|
|
205
|
+
"items": {
|
|
206
|
+
"type": "string"
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
"does_not_apply_when": {
|
|
210
|
+
"type": "array",
|
|
211
|
+
"items": {
|
|
212
|
+
"type": "string"
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
"additionalProperties": true
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
"core_structure": {
|
|
220
|
+
"type": "array",
|
|
221
|
+
"items": {
|
|
222
|
+
"type": "object",
|
|
223
|
+
"required": [
|
|
224
|
+
"from",
|
|
225
|
+
"to",
|
|
226
|
+
"via"
|
|
227
|
+
],
|
|
228
|
+
"properties": {
|
|
229
|
+
"from": {
|
|
230
|
+
"type": "string"
|
|
231
|
+
},
|
|
232
|
+
"to": {
|
|
233
|
+
"type": "string"
|
|
234
|
+
},
|
|
235
|
+
"via": {
|
|
236
|
+
"type": "string"
|
|
237
|
+
},
|
|
238
|
+
"applies_when": {
|
|
239
|
+
"type": "array",
|
|
240
|
+
"items": {
|
|
241
|
+
"type": "string"
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
"does_not_apply_when": {
|
|
245
|
+
"type": "array",
|
|
246
|
+
"items": {
|
|
247
|
+
"type": "string"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
"additionalProperties": true
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
"stances": {
|
|
255
|
+
"type": "array",
|
|
256
|
+
"items": {
|
|
257
|
+
"anyOf": [
|
|
258
|
+
{
|
|
259
|
+
"type": "string"
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"type": "object",
|
|
263
|
+
"required": [
|
|
264
|
+
"stance"
|
|
265
|
+
],
|
|
266
|
+
"properties": {
|
|
267
|
+
"stance": {
|
|
268
|
+
"type": "string"
|
|
269
|
+
},
|
|
270
|
+
"applies_when": {
|
|
271
|
+
"type": "array",
|
|
272
|
+
"items": {
|
|
273
|
+
"type": "string"
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
"does_not_apply_when": {
|
|
277
|
+
"type": "array",
|
|
278
|
+
"items": {
|
|
279
|
+
"type": "string"
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
"additionalProperties": true
|
|
284
|
+
}
|
|
285
|
+
]
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
"additionalProperties": true
|
|
290
|
+
}
|
|
@@ -158,10 +158,12 @@
|
|
|
158
158
|
"type": "string"
|
|
159
159
|
},
|
|
160
160
|
"signals_good": {
|
|
161
|
-
"type": "
|
|
161
|
+
"type": "array",
|
|
162
|
+
"items": { "type": "string" }
|
|
162
163
|
},
|
|
163
164
|
"signals_bad": {
|
|
164
|
-
"type": "
|
|
165
|
+
"type": "array",
|
|
166
|
+
"items": { "type": "string" }
|
|
165
167
|
}
|
|
166
168
|
},
|
|
167
169
|
"additionalProperties": true
|
|
@@ -183,10 +185,12 @@
|
|
|
183
185
|
"type": "string"
|
|
184
186
|
},
|
|
185
187
|
"must_not_do": {
|
|
186
|
-
"type": "
|
|
188
|
+
"type": "array",
|
|
189
|
+
"items": { "type": "string" }
|
|
187
190
|
},
|
|
188
191
|
"acceptable_exception": {
|
|
189
|
-
"type": "
|
|
192
|
+
"type": "array",
|
|
193
|
+
"items": { "type": "string" }
|
|
190
194
|
}
|
|
191
195
|
},
|
|
192
196
|
"additionalProperties": true
|
|
@@ -208,10 +212,12 @@
|
|
|
208
212
|
}
|
|
209
213
|
},
|
|
210
214
|
"must_block_when": {
|
|
211
|
-
"type": "
|
|
215
|
+
"type": "array",
|
|
216
|
+
"items": { "type": "string" }
|
|
212
217
|
},
|
|
213
218
|
"warn_when": {
|
|
214
|
-
"type": "
|
|
219
|
+
"type": "array",
|
|
220
|
+
"items": { "type": "string" }
|
|
215
221
|
}
|
|
216
222
|
},
|
|
217
223
|
"additionalProperties": true
|