@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @aikdna/kdna-core
2
2
 
3
- Pure logic library (zero dependencies) for loading, validating, linting, rendering, and composing KDNA domain cognition packages.
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 { lintDomain, validateDomainSchema, validateCrossFile, renderDomain } = require('@aikdna/kdna-core');
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.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/knowledge-dna/KDNA.git",
35
+ "url": "git+https://github.com/aikdna/kdna.git",
34
36
  "directory": "packages/kdna-core"
35
37
  },
36
38
  "homepage": "https://aikdna.com",
@@ -58,7 +58,10 @@
58
58
  "type": "string"
59
59
  },
60
60
  "does_not_act_as": {
61
- "type": "string"
61
+ "oneOf": [
62
+ { "type": "string" },
63
+ { "type": "array", "items": { "type": "string" } }
64
+ ]
62
65
  },
63
66
  "responsibility": {
64
67
  "type": "string"
@@ -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": "string"
161
+ "type": "array",
162
+ "items": { "type": "string" }
162
163
  },
163
164
  "signals_bad": {
164
- "type": "string"
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": "string"
188
+ "type": "array",
189
+ "items": { "type": "string" }
187
190
  },
188
191
  "acceptable_exception": {
189
- "type": "string"
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": "string"
215
+ "type": "array",
216
+ "items": { "type": "string" }
212
217
  },
213
218
  "warn_when": {
214
- "type": "string"
219
+ "type": "array",
220
+ "items": { "type": "string" }
215
221
  }
216
222
  },
217
223
  "additionalProperties": true