@aikdna/kdna-core 0.2.3 → 0.4.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
@@ -44,6 +44,36 @@ Returns `{ errors: string[], warnings: string[] }`.
44
44
  ### `renderDomain(dataMap, options?)`
45
45
  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
46
 
47
+ ## Compose API (9 functions)
48
+
49
+ 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.
50
+
51
+ ### Context Composition
52
+
53
+ - **`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.
54
+
55
+ - **`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 }`.
56
+
57
+ - **`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 }`.
58
+
59
+ ### Signal Classification
60
+
61
+ - **`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).
62
+
63
+ - **`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`).
64
+
65
+ ### Cluster Operations
66
+
67
+ - **`loadCluster(clusterManifestPath, domainLoader)`** — Load a cluster manifest (`kdna.cluster.json`) and resolve each domain via the provided loader function. Returns `{ manifest, domains, errors }`.
68
+
69
+ - **`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`.
70
+
71
+ - **`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 }`.
72
+
73
+ ### Utilities
74
+
75
+ - **`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.
76
+
47
77
  ## License
48
78
 
49
79
  Apache-2.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikdna/kdna-core",
3
- "version": "0.2.3",
3
+ "version": "0.4.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 -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",
@@ -0,0 +1,130 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "KDNA Composition Policy",
4
+ "description": "Schema for composition.policy.json — defines runtime composition behavior for domain clusters.",
5
+ "type": "object",
6
+ "required": ["policy_id", "version"],
7
+ "properties": {
8
+ "policy_id": {
9
+ "type": "string",
10
+ "description": "Unique policy identifier"
11
+ },
12
+ "version": {
13
+ "type": "string",
14
+ "description": "Semantic version of this policy"
15
+ },
16
+ "selection_policy": {
17
+ "type": "object",
18
+ "properties": {
19
+ "mode": {
20
+ "type": "string",
21
+ "enum": ["signal_based", "fixed", "staged", "overlay", "user_confirmed"]
22
+ },
23
+ "max_domains": { "type": "integer", "minimum": 1 },
24
+ "min_signal_score": { "type": "number", "minimum": 0, "maximum": 1 },
25
+ "ask_user_when_ambiguous": { "type": "boolean" }
26
+ }
27
+ },
28
+ "priority_policy": {
29
+ "type": "array",
30
+ "items": {
31
+ "type": "object",
32
+ "required": ["when", "domain", "priority", "effect"],
33
+ "properties": {
34
+ "when": { "type": "string", "description": "Condition expression triggering this rule" },
35
+ "domain": { "type": "string", "description": "Domain ID" },
36
+ "priority": { "type": "integer", "minimum": 0, "maximum": 100 },
37
+ "effect": {
38
+ "type": "string",
39
+ "enum": ["must_include", "block_or_require_confirmation", "deprioritize", "override"]
40
+ }
41
+ }
42
+ }
43
+ },
44
+ "conflict_policy": {
45
+ "type": "object",
46
+ "properties": {
47
+ "default": {
48
+ "type": "string",
49
+ "enum": ["surface", "priority_wins", "risk_wins", "block", "ask_user", "allow_with_warning"]
50
+ },
51
+ "rules": {
52
+ "type": "array",
53
+ "items": {
54
+ "type": "object",
55
+ "required": ["conflict_type", "action"],
56
+ "properties": {
57
+ "conflict_type": {
58
+ "type": "string",
59
+ "enum": ["value_conflict", "term_conflict", "risk_conflict", "stance_conflict", "framework_conflict", "output_policy_conflict", "priority_conflict"]
60
+ },
61
+ "action": {
62
+ "type": "string",
63
+ "enum": ["surface", "surface_and_ask", "risk_wins", "priority_wins", "block", "allow_with_warning"]
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+ },
70
+ "merge_policy": {
71
+ "type": "object",
72
+ "properties": {
73
+ "axioms": { "type": "string", "enum": ["include_all_with_source", "dedupe_by_id", "select_by_priority"] },
74
+ "banned_terms": { "type": "string", "enum": ["union_with_source", "strictest_only", "priority_domain_only"] },
75
+ "self_checks": { "type": "string", "enum": ["dedupe_by_semantic_similarity", "include_all_with_source", "priority_domain_only"] },
76
+ "frameworks": { "type": "string", "enum": ["select_by_scenario", "include_all_with_source", "priority_domain_only"] },
77
+ "stances": { "type": "string", "enum": ["include_conflicts", "priority_domain_only", "merge_with_source"] }
78
+ }
79
+ },
80
+ "output_policy": {
81
+ "type": "object",
82
+ "properties": {
83
+ "must_show_loaded_domains": { "type": "boolean" },
84
+ "must_record_judgment_trace": { "type": "boolean" },
85
+ "must_surface_conflicts": { "type": "boolean" },
86
+ "must_include_uncertainty": { "type": "boolean" }
87
+ }
88
+ },
89
+ "governance": {
90
+ "type": "object",
91
+ "properties": {
92
+ "ownership": {
93
+ "type": "object",
94
+ "properties": {
95
+ "owner_team": { "type": "string" },
96
+ "maintainers": { "type": "array", "items": { "type": "string" } },
97
+ "approvers": { "type": "array", "items": { "type": "string" } },
98
+ "review_cycle": { "type": "string" }
99
+ }
100
+ },
101
+ "lifecycle": {
102
+ "type": "object",
103
+ "properties": {
104
+ "status": { "type": "string", "enum": ["draft", "review", "approved", "active", "deprecated", "archived"] },
105
+ "effective_from": { "type": "string" },
106
+ "expires_at": { "type": "string" },
107
+ "review_required_before": { "type": "string" }
108
+ }
109
+ },
110
+ "change_control": {
111
+ "type": "object",
112
+ "properties": {
113
+ "requires_approval_for": { "type": "array", "items": { "type": "string" } },
114
+ "minor_changes_allowed_for": { "type": "array", "items": { "type": "string" } },
115
+ "audit_log_required": { "type": "boolean" }
116
+ }
117
+ },
118
+ "deployment": {
119
+ "type": "object",
120
+ "properties": {
121
+ "environments": { "type": "array", "items": { "type": "string" } },
122
+ "active_version": { "type": "string" },
123
+ "rollout_strategy": { "type": "string", "enum": ["manual", "canary", "all_at_once"] },
124
+ "rollback_version": { "type": "string" }
125
+ }
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }
@@ -42,8 +42,34 @@
42
42
  "outcome": { "type": "string" },
43
43
  "kdna_analysis": { "type": "string" },
44
44
  "modern_parallel": { "type": "string" },
45
- "axiom": { "type": "string" }
46
- }
45
+ "axiom": { "type": "string" },
46
+ "judgment_path": {
47
+ "type": "string",
48
+ "description": "The judgment process applied in this case."
49
+ },
50
+ "good_response": {
51
+ "type": "string",
52
+ "description": "An example of a good judgment response."
53
+ },
54
+ "bad_response": {
55
+ "type": "string",
56
+ "description": "An example of a poor judgment response."
57
+ },
58
+ "why_good": {
59
+ "type": "string",
60
+ "description": "Why the good response aligns with domain judgment."
61
+ },
62
+ "why_bad": {
63
+ "type": "string",
64
+ "description": "Why the bad response violates domain judgment."
65
+ },
66
+ "triggered_axioms": {
67
+ "type": "array",
68
+ "items": { "type": "string" },
69
+ "description": "Axioms triggered by this case."
70
+ }
71
+ },
72
+ "additionalProperties": true
47
73
  }
48
74
  }
49
75
  },
@@ -1,53 +1,132 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://aikdna.com/schema/KDNA_Cluster.schema.json",
4
3
  "title": "KDNA Cluster Manifest",
5
- "description": "Defines a composable group of KDNA packages that work together as a judgment system.",
4
+ "description": "Schema for kdna.cluster.json defines a composable judgment system of KDNA domains.",
6
5
  "type": "object",
7
- "required": ["name", "version", "packages"],
6
+ "required": ["cluster_id", "name", "version", "domains", "composition"],
8
7
  "properties": {
8
+ "cluster_id": {
9
+ "type": "string",
10
+ "description": "Fully qualified cluster identifier, e.g., @company/product-launch-system"
11
+ },
9
12
  "name": {
10
13
  "type": "string",
11
- "description": "Cluster identifier in lowercase snake_case."
14
+ "description": "Human-readable cluster name"
12
15
  },
13
16
  "version": {
14
17
  "type": "string",
15
- "description": "Semantic version of this cluster."
18
+ "description": "Semantic version of this cluster manifest"
19
+ },
20
+ "description": {
21
+ "type": "string",
22
+ "description": "What judgment system this cluster provides"
23
+ },
24
+ "type": {
25
+ "type": "string",
26
+ "enum": ["horizontal", "vertical", "governance", "enterprise_system"],
27
+ "description": "Cluster type determining default loading strategy"
28
+ },
29
+ "status": {
30
+ "type": "string",
31
+ "enum": ["draft", "experimental", "stable", "deprecated"]
16
32
  },
17
- "purpose": {
33
+ "access": {
18
34
  "type": "string",
19
- "description": "What complex domain task this cluster addresses."
35
+ "enum": ["open", "licensed", "runtime"]
20
36
  },
21
- "packages": {
37
+ "domains": {
22
38
  "type": "array",
23
- "description": "KDNA packages that form this cluster.",
24
- "minItems": 2,
25
39
  "items": {
26
40
  "type": "object",
27
- "required": ["id", "role"],
41
+ "required": ["id", "version", "role", "required", "load_condition"],
28
42
  "properties": {
29
- "id": { "type": "string" },
43
+ "id": {
44
+ "type": "string",
45
+ "description": "Fully qualified domain name (@scope/name)"
46
+ },
47
+ "version": {
48
+ "type": "string",
49
+ "description": "Semver range, e.g., ^1.2.0"
50
+ },
30
51
  "role": {
31
52
  "type": "string",
32
- "enum": ["primary", "advisor", "constraint", "critic"]
53
+ "enum": ["primary", "advisor", "risk_guard", "style_and_trust", "evaluator"]
33
54
  },
34
- "use_when": {
35
- "type": "array",
36
- "items": { "type": "string" },
37
- "description": "Keywords or conditions that trigger this package."
55
+ "required": {
56
+ "type": "boolean",
57
+ "description": "Whether this domain must load for cluster to function"
58
+ },
59
+ "load_condition": {
60
+ "type": "string",
61
+ "description": "When this domain should activate"
38
62
  }
39
63
  }
40
64
  }
41
65
  },
42
- "composition_rules": {
66
+ "relationships": {
43
67
  "type": "array",
44
- "items": { "type": "string" },
45
- "description": "Rules governing how packages in this cluster interact."
68
+ "items": {
69
+ "type": "object",
70
+ "required": ["from", "to", "type"],
71
+ "properties": {
72
+ "from": { "type": "string" },
73
+ "to": { "type": "string" },
74
+ "type": {
75
+ "type": "string",
76
+ "enum": ["depends_on", "constrains", "overrides", "blocks", "informs", "extends", "refines", "conflicts_with", "evaluates", "expressed_through"]
77
+ },
78
+ "description": { "type": "string" }
79
+ }
80
+ }
46
81
  },
47
- "routing_questions": {
48
- "type": "array",
49
- "items": { "type": "string" },
50
- "description": "Questions that help the router select the right primary and advisors."
82
+ "composition": {
83
+ "type": "object",
84
+ "required": ["strategy", "conflict_policy", "priority_order"],
85
+ "properties": {
86
+ "strategy": {
87
+ "type": "string",
88
+ "enum": ["fixed", "signal_based", "staged", "overlay", "user_confirmed"]
89
+ },
90
+ "max_active_domains": {
91
+ "type": "integer",
92
+ "minimum": 1
93
+ },
94
+ "default_domains": {
95
+ "type": "array",
96
+ "items": { "type": "string" }
97
+ },
98
+ "conflict_policy": {
99
+ "type": "string",
100
+ "enum": ["surface", "priority", "block", "ask_user"]
101
+ },
102
+ "priority_order": {
103
+ "type": "array",
104
+ "items": { "type": "string" },
105
+ "description": "Ordered list of domain names, highest priority first"
106
+ }
107
+ }
108
+ },
109
+ "token_budget": {
110
+ "type": "object",
111
+ "properties": {
112
+ "max_context_tokens": { "type": "integer" },
113
+ "domain_summary_mode": {
114
+ "type": "string",
115
+ "enum": ["full", "compact", "axioms_only", "scenario_only"]
116
+ },
117
+ "compression_strategy": { "type": "string" }
118
+ }
119
+ },
120
+ "evaluation": {
121
+ "type": "object",
122
+ "properties": {
123
+ "eval_set": { "type": "string" },
124
+ "minimum_pass_rate": { "type": "number", "minimum": 0, "maximum": 1 },
125
+ "required_dimensions": {
126
+ "type": "array",
127
+ "items": { "type": "string" }
128
+ }
129
+ }
51
130
  }
52
131
  }
53
132
  }
@@ -40,6 +40,42 @@
40
40
  },
41
41
  "additionalProperties": true
42
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
+ },
43
79
  "axioms": {
44
80
  "type": "array",
45
81
  "items": {
@@ -49,7 +85,46 @@
49
85
  "one_sentence",
50
86
  "full_statement",
51
87
  "why"
52
- ]
88
+ ],
89
+ "properties": {
90
+ "id": {
91
+ "type": "string"
92
+ },
93
+ "one_sentence": {
94
+ "type": "string"
95
+ },
96
+ "full_statement": {
97
+ "type": "string"
98
+ },
99
+ "why": {
100
+ "type": "string"
101
+ },
102
+ "confidence": {
103
+ "type": "string"
104
+ },
105
+ "evidence_type": {
106
+ "type": "array",
107
+ "items": {
108
+ "type": "string"
109
+ }
110
+ },
111
+ "applies_when": {
112
+ "type": "array",
113
+ "items": {
114
+ "type": "string"
115
+ }
116
+ },
117
+ "does_not_apply_when": {
118
+ "type": "array",
119
+ "items": {
120
+ "type": "string"
121
+ }
122
+ },
123
+ "failure_risk": {
124
+ "type": "string"
125
+ }
126
+ },
127
+ "additionalProperties": true
53
128
  }
54
129
  },
55
130
  "ontology": {
@@ -62,7 +137,37 @@
62
137
  "essence",
63
138
  "boundary",
64
139
  "trigger_signal"
65
- ]
140
+ ],
141
+ "properties": {
142
+ "id": {
143
+ "type": "string"
144
+ },
145
+ "one_sentence": {
146
+ "type": "string"
147
+ },
148
+ "essence": {
149
+ "type": "string"
150
+ },
151
+ "boundary": {
152
+ "type": "string"
153
+ },
154
+ "trigger_signal": {
155
+ "type": "string"
156
+ },
157
+ "applies_when": {
158
+ "type": "array",
159
+ "items": {
160
+ "type": "string"
161
+ }
162
+ },
163
+ "does_not_apply_when": {
164
+ "type": "array",
165
+ "items": {
166
+ "type": "string"
167
+ }
168
+ }
169
+ },
170
+ "additionalProperties": true
66
171
  }
67
172
  },
68
173
  "frameworks": {
@@ -74,7 +179,37 @@
74
179
  "name",
75
180
  "when_to_use",
76
181
  "steps"
77
- ]
182
+ ],
183
+ "properties": {
184
+ "id": {
185
+ "type": "string"
186
+ },
187
+ "name": {
188
+ "type": "string"
189
+ },
190
+ "when_to_use": {
191
+ "type": "string"
192
+ },
193
+ "steps": {
194
+ "type": "array",
195
+ "items": {
196
+ "type": "string"
197
+ }
198
+ },
199
+ "applies_when": {
200
+ "type": "array",
201
+ "items": {
202
+ "type": "string"
203
+ }
204
+ },
205
+ "does_not_apply_when": {
206
+ "type": "array",
207
+ "items": {
208
+ "type": "string"
209
+ }
210
+ }
211
+ },
212
+ "additionalProperties": true
78
213
  }
79
214
  },
80
215
  "core_structure": {
@@ -85,18 +220,67 @@
85
220
  "from",
86
221
  "to",
87
222
  "via"
88
- ]
223
+ ],
224
+ "properties": {
225
+ "from": {
226
+ "type": "string"
227
+ },
228
+ "to": {
229
+ "type": "string"
230
+ },
231
+ "via": {
232
+ "type": "string"
233
+ },
234
+ "applies_when": {
235
+ "type": "array",
236
+ "items": {
237
+ "type": "string"
238
+ }
239
+ },
240
+ "does_not_apply_when": {
241
+ "type": "array",
242
+ "items": {
243
+ "type": "string"
244
+ }
245
+ }
246
+ },
247
+ "additionalProperties": true
89
248
  }
90
249
  },
91
250
  "stances": {
92
251
  "type": "array",
93
252
  "items": {
94
253
  "anyOf": [
95
- { "type": "string" },
96
- { "type": "object", "required": ["stance"] }
254
+ {
255
+ "type": "string"
256
+ },
257
+ {
258
+ "type": "object",
259
+ "required": [
260
+ "stance"
261
+ ],
262
+ "properties": {
263
+ "stance": {
264
+ "type": "string"
265
+ },
266
+ "applies_when": {
267
+ "type": "array",
268
+ "items": {
269
+ "type": "string"
270
+ }
271
+ },
272
+ "does_not_apply_when": {
273
+ "type": "array",
274
+ "items": {
275
+ "type": "string"
276
+ }
277
+ }
278
+ },
279
+ "additionalProperties": true
280
+ }
97
281
  ]
98
282
  }
99
283
  }
100
284
  },
101
285
  "additionalProperties": true
102
- }
286
+ }