@aikdna/kdna-core 0.3.0 → 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 +30 -0
- 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/compose.js +2 -2
- package/src/lint-pure.js +159 -4
- package/src/loader.js +30 -20
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.
|
|
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/
|
|
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
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "KDNA_Patterns",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": [
|
|
6
|
+
"meta",
|
|
7
|
+
"terminology",
|
|
8
|
+
"misunderstandings",
|
|
9
|
+
"self_check"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"meta": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"required": [
|
|
15
|
+
"version",
|
|
16
|
+
"domain",
|
|
17
|
+
"created",
|
|
18
|
+
"purpose",
|
|
19
|
+
"load_condition"
|
|
20
|
+
],
|
|
21
|
+
"properties": {
|
|
22
|
+
"version": {
|
|
23
|
+
"type": "string"
|
|
24
|
+
},
|
|
25
|
+
"domain": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"pattern": "^[a-z][a-z0-9_]*$"
|
|
28
|
+
},
|
|
29
|
+
"created": {
|
|
30
|
+
"type": "string"
|
|
31
|
+
},
|
|
32
|
+
"purpose": {
|
|
33
|
+
"type": "string"
|
|
34
|
+
},
|
|
35
|
+
"load_condition": {
|
|
36
|
+
"type": "string"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"additionalProperties": true
|
|
40
|
+
},
|
|
41
|
+
"terminology": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"minProperties": 1,
|
|
44
|
+
"properties": {
|
|
45
|
+
"standard_terms": {
|
|
46
|
+
"type": "array",
|
|
47
|
+
"items": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"required": [
|
|
50
|
+
"term",
|
|
51
|
+
"definition"
|
|
52
|
+
],
|
|
53
|
+
"properties": {
|
|
54
|
+
"term": {
|
|
55
|
+
"type": "string"
|
|
56
|
+
},
|
|
57
|
+
"definition": {
|
|
58
|
+
"type": "string"
|
|
59
|
+
},
|
|
60
|
+
"applies_when": {
|
|
61
|
+
"type": "array",
|
|
62
|
+
"items": {
|
|
63
|
+
"type": "string"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"does_not_apply_when": {
|
|
67
|
+
"type": "array",
|
|
68
|
+
"items": {
|
|
69
|
+
"type": "string"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"additionalProperties": true
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"preferred_terms": {
|
|
77
|
+
"type": "array",
|
|
78
|
+
"items": {
|
|
79
|
+
"type": "object",
|
|
80
|
+
"required": [
|
|
81
|
+
"term",
|
|
82
|
+
"definition"
|
|
83
|
+
],
|
|
84
|
+
"properties": {
|
|
85
|
+
"term": {
|
|
86
|
+
"type": "string"
|
|
87
|
+
},
|
|
88
|
+
"definition": {
|
|
89
|
+
"type": "string"
|
|
90
|
+
},
|
|
91
|
+
"applies_when": {
|
|
92
|
+
"type": "array",
|
|
93
|
+
"items": {
|
|
94
|
+
"type": "string"
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"does_not_apply_when": {
|
|
98
|
+
"type": "array",
|
|
99
|
+
"items": {
|
|
100
|
+
"type": "string"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"additionalProperties": true
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"banned_terms": {
|
|
108
|
+
"type": "array",
|
|
109
|
+
"items": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"required": [
|
|
112
|
+
"term",
|
|
113
|
+
"why",
|
|
114
|
+
"replace_with"
|
|
115
|
+
],
|
|
116
|
+
"properties": {
|
|
117
|
+
"term": {
|
|
118
|
+
"type": "string"
|
|
119
|
+
},
|
|
120
|
+
"why": {
|
|
121
|
+
"type": "string"
|
|
122
|
+
},
|
|
123
|
+
"replace_with": {
|
|
124
|
+
"type": "string"
|
|
125
|
+
},
|
|
126
|
+
"applies_when": {
|
|
127
|
+
"type": "array",
|
|
128
|
+
"items": {
|
|
129
|
+
"type": "string"
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"does_not_apply_when": {
|
|
133
|
+
"type": "array",
|
|
134
|
+
"items": {
|
|
135
|
+
"type": "string"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"additionalProperties": true
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"additionalProperties": true
|
|
144
|
+
},
|
|
145
|
+
"aesthetic_preferences": {
|
|
146
|
+
"type": "array",
|
|
147
|
+
"items": {
|
|
148
|
+
"type": "object",
|
|
149
|
+
"required": [
|
|
150
|
+
"prefer",
|
|
151
|
+
"avoid"
|
|
152
|
+
],
|
|
153
|
+
"properties": {
|
|
154
|
+
"prefer": {
|
|
155
|
+
"type": "string"
|
|
156
|
+
},
|
|
157
|
+
"avoid": {
|
|
158
|
+
"type": "string"
|
|
159
|
+
},
|
|
160
|
+
"signals_good": {
|
|
161
|
+
"type": "array",
|
|
162
|
+
"items": { "type": "string" }
|
|
163
|
+
},
|
|
164
|
+
"signals_bad": {
|
|
165
|
+
"type": "array",
|
|
166
|
+
"items": { "type": "string" }
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"additionalProperties": true
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
"boundaries": {
|
|
173
|
+
"type": "array",
|
|
174
|
+
"items": {
|
|
175
|
+
"type": "object",
|
|
176
|
+
"required": [
|
|
177
|
+
"rule",
|
|
178
|
+
"why"
|
|
179
|
+
],
|
|
180
|
+
"properties": {
|
|
181
|
+
"rule": {
|
|
182
|
+
"type": "string"
|
|
183
|
+
},
|
|
184
|
+
"why": {
|
|
185
|
+
"type": "string"
|
|
186
|
+
},
|
|
187
|
+
"must_not_do": {
|
|
188
|
+
"type": "array",
|
|
189
|
+
"items": { "type": "string" }
|
|
190
|
+
},
|
|
191
|
+
"acceptable_exception": {
|
|
192
|
+
"type": "array",
|
|
193
|
+
"items": { "type": "string" }
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
"additionalProperties": true
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
"risk_model": {
|
|
200
|
+
"type": "object",
|
|
201
|
+
"properties": {
|
|
202
|
+
"highest_risk_errors": {
|
|
203
|
+
"type": "array",
|
|
204
|
+
"items": {
|
|
205
|
+
"type": "string"
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"acceptable_errors": {
|
|
209
|
+
"type": "array",
|
|
210
|
+
"items": {
|
|
211
|
+
"type": "string"
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
"must_block_when": {
|
|
215
|
+
"type": "array",
|
|
216
|
+
"items": { "type": "string" }
|
|
217
|
+
},
|
|
218
|
+
"warn_when": {
|
|
219
|
+
"type": "array",
|
|
220
|
+
"items": { "type": "string" }
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
"additionalProperties": true
|
|
224
|
+
},
|
|
225
|
+
"misunderstandings": {
|
|
226
|
+
"type": "array",
|
|
227
|
+
"items": {
|
|
228
|
+
"type": "object",
|
|
229
|
+
"required": [
|
|
230
|
+
"id",
|
|
231
|
+
"wrong",
|
|
232
|
+
"correct",
|
|
233
|
+
"key_distinction",
|
|
234
|
+
"why",
|
|
235
|
+
"applies_when",
|
|
236
|
+
"does_not_apply_when",
|
|
237
|
+
"failure_risk",
|
|
238
|
+
"confidence"
|
|
239
|
+
],
|
|
240
|
+
"properties": {
|
|
241
|
+
"id": {
|
|
242
|
+
"type": "string"
|
|
243
|
+
},
|
|
244
|
+
"wrong": {
|
|
245
|
+
"type": "string"
|
|
246
|
+
},
|
|
247
|
+
"correct": {
|
|
248
|
+
"type": "string"
|
|
249
|
+
},
|
|
250
|
+
"key_distinction": {
|
|
251
|
+
"type": "string"
|
|
252
|
+
},
|
|
253
|
+
"why": {
|
|
254
|
+
"type": "string"
|
|
255
|
+
},
|
|
256
|
+
"confidence": {
|
|
257
|
+
"type": "string"
|
|
258
|
+
},
|
|
259
|
+
"evidence_type": {
|
|
260
|
+
"type": "array",
|
|
261
|
+
"items": {
|
|
262
|
+
"type": "string"
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
"applies_when": {
|
|
266
|
+
"type": "array",
|
|
267
|
+
"items": {
|
|
268
|
+
"type": "string"
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
"does_not_apply_when": {
|
|
272
|
+
"type": "array",
|
|
273
|
+
"items": {
|
|
274
|
+
"type": "string"
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
"failure_risk": {
|
|
278
|
+
"type": "string"
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
"additionalProperties": true
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
"self_check": {
|
|
285
|
+
"type": "array",
|
|
286
|
+
"items": {
|
|
287
|
+
"anyOf": [
|
|
288
|
+
{
|
|
289
|
+
"type": "string"
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"type": "object",
|
|
293
|
+
"required": [
|
|
294
|
+
"question"
|
|
295
|
+
],
|
|
296
|
+
"properties": {
|
|
297
|
+
"question": {
|
|
298
|
+
"type": "string"
|
|
299
|
+
},
|
|
300
|
+
"applies_when": {
|
|
301
|
+
"type": "array",
|
|
302
|
+
"items": {
|
|
303
|
+
"type": "string"
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
"additionalProperties": true
|
|
308
|
+
}
|
|
309
|
+
]
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
"counterexamples": {
|
|
313
|
+
"type": "array",
|
|
314
|
+
"items": {
|
|
315
|
+
"type": "object",
|
|
316
|
+
"required": [
|
|
317
|
+
"bad_example",
|
|
318
|
+
"why_bad"
|
|
319
|
+
],
|
|
320
|
+
"properties": {
|
|
321
|
+
"bad_example": {
|
|
322
|
+
"type": "string"
|
|
323
|
+
},
|
|
324
|
+
"why_bad": {
|
|
325
|
+
"type": "string"
|
|
326
|
+
},
|
|
327
|
+
"violated_axioms": {
|
|
328
|
+
"type": "array",
|
|
329
|
+
"items": {
|
|
330
|
+
"type": "string"
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
"better_direction": {
|
|
334
|
+
"type": "string"
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
"additionalProperties": true
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
"additionalProperties": true
|
|
342
|
+
}
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
"scenes": {
|
|
35
|
+
"description": "Deprecated since v1.0-rc. Use scenarios (canonical) instead. Kept for backward compatibility.",
|
|
35
36
|
"type": "array",
|
|
36
37
|
"items": {
|
|
37
38
|
"type": "object",
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
"name": { "type": "string" },
|
|
42
43
|
"trigger_signal": {
|
|
43
44
|
"type": "string",
|
|
44
|
-
"description": "Deprecated
|
|
45
|
+
"description": "Deprecated since v1.0-rc. Use trigger_signals (array) instead. Kept for backward compatibility."
|
|
45
46
|
},
|
|
46
47
|
"trigger_signals": {
|
|
47
48
|
"type": "array",
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "KDNA_Scenarios (Strict)",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": ["meta", "scenarios"],
|
|
6
|
+
"properties": {
|
|
7
|
+
"meta": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"required": [
|
|
10
|
+
"version",
|
|
11
|
+
"domain",
|
|
12
|
+
"created",
|
|
13
|
+
"purpose",
|
|
14
|
+
"load_condition"
|
|
15
|
+
],
|
|
16
|
+
"properties": {
|
|
17
|
+
"version": { "type": "string" },
|
|
18
|
+
"domain": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"pattern": "^[a-z][a-z0-9_]*$"
|
|
21
|
+
},
|
|
22
|
+
"created": { "type": "string" },
|
|
23
|
+
"purpose": { "type": "string" },
|
|
24
|
+
"load_condition": { "type": "string" }
|
|
25
|
+
},
|
|
26
|
+
"additionalProperties": true
|
|
27
|
+
},
|
|
28
|
+
"scenarios": {
|
|
29
|
+
"type": "array",
|
|
30
|
+
"items": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"required": ["id", "name", "trigger_signals"],
|
|
33
|
+
"properties": {
|
|
34
|
+
"id": { "type": "string" },
|
|
35
|
+
"name": { "type": "string" },
|
|
36
|
+
"trigger_signals": {
|
|
37
|
+
"type": "array",
|
|
38
|
+
"items": { "type": "string" },
|
|
39
|
+
"description": "Signals that trigger this scenario."
|
|
40
|
+
},
|
|
41
|
+
"negative_signals": {
|
|
42
|
+
"type": "array",
|
|
43
|
+
"items": { "type": "string" },
|
|
44
|
+
"description": "Signals that explicitly exclude this scenario."
|
|
45
|
+
},
|
|
46
|
+
"classification_rule": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"description": "Rule for classifying input into this scenario."
|
|
49
|
+
},
|
|
50
|
+
"risk_level": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"description": "Risk level associated with this scenario."
|
|
53
|
+
},
|
|
54
|
+
"expected_judgment_shift": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"description": "How judgment should shift when this scenario is detected."
|
|
57
|
+
},
|
|
58
|
+
"sub_scenarios": {
|
|
59
|
+
"type": "array",
|
|
60
|
+
"items": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"required": ["id", "trap_belief", "action_template", "expected_result"],
|
|
63
|
+
"properties": {
|
|
64
|
+
"id": { "type": "string" },
|
|
65
|
+
"trap_belief": { "type": "string" },
|
|
66
|
+
"three_questions": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"required": ["belief", "state", "need"],
|
|
69
|
+
"properties": {
|
|
70
|
+
"belief": { "type": "string" },
|
|
71
|
+
"state": { "type": "string" },
|
|
72
|
+
"need": { "type": "string" }
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"action_template": {
|
|
76
|
+
"type": "array",
|
|
77
|
+
"items": { "type": "string" }
|
|
78
|
+
},
|
|
79
|
+
"replace": {
|
|
80
|
+
"type": "array",
|
|
81
|
+
"items": {
|
|
82
|
+
"type": "object",
|
|
83
|
+
"required": ["avoid", "use"],
|
|
84
|
+
"properties": {
|
|
85
|
+
"avoid": { "type": "string" },
|
|
86
|
+
"use": { "type": "string" }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"expected_result": { "type": "string" }
|
|
91
|
+
},
|
|
92
|
+
"additionalProperties": true
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"additionalProperties": true
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"additionalProperties": false
|
|
101
|
+
}
|
package/src/compose.js
CHANGED
|
@@ -322,8 +322,8 @@ function detectDomainConflicts(domains) {
|
|
|
322
322
|
for (const sa of sA) {
|
|
323
323
|
for (const sb of sB) {
|
|
324
324
|
// Simple negation check — can be extended
|
|
325
|
-
|
|
326
|
-
|
|
325
|
+
if (sa && sb && (/\bnot\b/.test(sa) && sb.toLowerCase().includes(sa.toLowerCase().replace('not ', ''))) ||
|
|
326
|
+
(/\bnot\b/.test(sb) && sa.toLowerCase().includes(sb.toLowerCase().replace('not ', '')))) {
|
|
327
327
|
conflicts.push({
|
|
328
328
|
type: 'stance_conflict',
|
|
329
329
|
domains: [domains[i].id, domains[j].id],
|
package/src/lint-pure.js
CHANGED
|
@@ -29,6 +29,15 @@ const OLD_FIELD_HINTS = {
|
|
|
29
29
|
judgment: 'via',
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
const KDNA_DOMAIN_FILES = new Set([
|
|
33
|
+
'KDNA_Core.json',
|
|
34
|
+
'KDNA_Patterns.json',
|
|
35
|
+
'KDNA_Scenarios.json',
|
|
36
|
+
'KDNA_Cases.json',
|
|
37
|
+
'KDNA_Reasoning.json',
|
|
38
|
+
'KDNA_Evolution.json',
|
|
39
|
+
]);
|
|
40
|
+
|
|
32
41
|
/**
|
|
33
42
|
* Lint a KDNA domain from a map of parsed JSON objects.
|
|
34
43
|
*
|
|
@@ -104,9 +113,7 @@ function lintDomain(dataMap) {
|
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
// Check file count
|
|
107
|
-
const kdnaFiles = Object.keys(dataMap).filter(
|
|
108
|
-
(f) => f.endsWith('.json') && f !== 'kdna.json',
|
|
109
|
-
);
|
|
116
|
+
const kdnaFiles = Object.keys(dataMap).filter((f) => KDNA_DOMAIN_FILES.has(f));
|
|
110
117
|
if (kdnaFiles.length > 6) errors.push(`Domain has ${kdnaFiles.length} JSON files; KDNA allows at most 6.`);
|
|
111
118
|
|
|
112
119
|
// Validate meta on all files
|
|
@@ -245,4 +252,152 @@ function lintDomain(dataMap) {
|
|
|
245
252
|
return { errors, warnings };
|
|
246
253
|
}
|
|
247
254
|
|
|
248
|
-
|
|
255
|
+
/**
|
|
256
|
+
* Canonical enum tables for manifest validation.
|
|
257
|
+
* Single source of truth — keep in sync with schema/kdna-manifest-v1rc.json and specs/enum-tables.md.
|
|
258
|
+
*/
|
|
259
|
+
const VALID_STATUS = new Set(['draft', 'experimental', 'stable', 'deprecated', 'staging']);
|
|
260
|
+
const VALID_BADGE = new Set(['untested', 'tested', 'validated', 'expert_reviewed', 'production_ready']);
|
|
261
|
+
const VALID_ACCESS = new Set(['open', 'licensed', 'runtime']);
|
|
262
|
+
const VALID_RISK = new Set(['R0', 'R1', 'R2', 'R3']);
|
|
263
|
+
const VALID_I18N = new Set(['L0', 'L1', 'L2', 'L3']);
|
|
264
|
+
|
|
265
|
+
const MANIFEST_REQUIRED = [
|
|
266
|
+
'kdna_spec', 'name', 'version', 'judgment_version',
|
|
267
|
+
'description', 'author', 'license', 'status',
|
|
268
|
+
'quality_badge', 'access', 'language',
|
|
269
|
+
];
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Validate a kdna.json manifest against the canonical v1.0-rc schema.
|
|
273
|
+
*
|
|
274
|
+
* @param {Object} manifest — parsed kdna.json
|
|
275
|
+
* @returns {{ errors: string[], warnings: string[] }}
|
|
276
|
+
*/
|
|
277
|
+
function validateManifest(manifest) {
|
|
278
|
+
const errors = [];
|
|
279
|
+
const warnings = [];
|
|
280
|
+
|
|
281
|
+
if (!manifest || typeof manifest !== 'object') {
|
|
282
|
+
errors.push('kdna.json: missing or empty manifest');
|
|
283
|
+
return { errors, warnings };
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// 1. Check spec_version is NOT in domain manifest (use kdna_spec only)
|
|
287
|
+
if ('spec_version' in manifest) {
|
|
288
|
+
errors.push(
|
|
289
|
+
'kdna.json: spec_version is deprecated in domain manifests. Use kdna_spec. ' +
|
|
290
|
+
'(spec_version is reserved for .kdna container manifests only.)',
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// 2. Check required fields
|
|
295
|
+
for (const field of MANIFEST_REQUIRED) {
|
|
296
|
+
if (!(field in manifest) || manifest[field] === undefined || manifest[field] === '') {
|
|
297
|
+
errors.push(`kdna.json: missing required field "${field}"`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// 3. Validate name format
|
|
302
|
+
if (manifest.name && !/^@[a-z][a-z0-9-]*\/[a-z][a-z0-9_]*$/.test(manifest.name)) {
|
|
303
|
+
errors.push(`kdna.json.name: invalid format "${manifest.name}". Expected @scope/name.`);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// 4. Validate enum fields
|
|
307
|
+
if (manifest.status && !VALID_STATUS.has(manifest.status)) {
|
|
308
|
+
errors.push(
|
|
309
|
+
`kdna.json.status: invalid value "${manifest.status}". ` +
|
|
310
|
+
`Valid: ${[...VALID_STATUS].join(', ')}`,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
if (manifest.quality_badge && !VALID_BADGE.has(manifest.quality_badge)) {
|
|
314
|
+
errors.push(
|
|
315
|
+
`kdna.json.quality_badge: invalid value "${manifest.quality_badge}". ` +
|
|
316
|
+
`Valid: ${[...VALID_BADGE].join(', ')}`,
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
if (manifest.access && !VALID_ACCESS.has(manifest.access)) {
|
|
320
|
+
errors.push(
|
|
321
|
+
`kdna.json.access: invalid value "${manifest.access}". ` +
|
|
322
|
+
`Valid: ${[...VALID_ACCESS].join(', ')}`,
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
if (manifest.risk_level && !VALID_RISK.has(manifest.risk_level)) {
|
|
326
|
+
errors.push(
|
|
327
|
+
`kdna.json.risk_level: invalid value "${manifest.risk_level}". ` +
|
|
328
|
+
`Valid: ${[...VALID_RISK].join(', ')}`,
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
if (manifest.i18n_level && !VALID_I18N.has(manifest.i18n_level)) {
|
|
332
|
+
warnings.push(
|
|
333
|
+
`kdna.json.i18n_level: non-standard value "${manifest.i18n_level}". ` +
|
|
334
|
+
`Valid: ${[...VALID_I18N].join(', ')}`,
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// 5. Deprecated status must have replaced_by
|
|
339
|
+
if (manifest.status === 'deprecated' && !manifest.replaced_by) {
|
|
340
|
+
errors.push('kdna.json: status is "deprecated" but replaced_by is missing');
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// 6. Tested+ badge must have signature
|
|
344
|
+
const needsSig = ['tested', 'validated', 'expert_reviewed', 'production_ready'];
|
|
345
|
+
if (needsSig.includes(manifest.quality_badge) && !manifest.signature) {
|
|
346
|
+
warnings.push(
|
|
347
|
+
`kdna.json: quality_badge "${manifest.quality_badge}" should have a signature`,
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// 7. Validate author
|
|
352
|
+
if (manifest.author) {
|
|
353
|
+
if (!manifest.author.name) errors.push('kdna.json.author: missing "name"');
|
|
354
|
+
if (!manifest.author.id) errors.push('kdna.json.author: missing "id"');
|
|
355
|
+
if (manifest.author.pubkey && !/^ed25519:[0-9a-f]{64}$/.test(manifest.author.pubkey)) {
|
|
356
|
+
warnings.push('kdna.json.author.pubkey: non-standard format. Expected ed25519:<64 hex chars>.');
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// 8. Validate license
|
|
361
|
+
if (manifest.license && !manifest.license.type) {
|
|
362
|
+
errors.push('kdna.json.license: missing "type"');
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// 9. Validate kdna_spec value
|
|
366
|
+
if (manifest.kdna_spec && manifest.kdna_spec !== '1.0-rc') {
|
|
367
|
+
warnings.push(
|
|
368
|
+
`kdna.json.kdna_spec: non-standard value "${manifest.kdna_spec}". Expected "1.0-rc".`,
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// 10. Validate version format
|
|
373
|
+
if (manifest.version && !/^\d+\.\d+\.\d+/.test(manifest.version)) {
|
|
374
|
+
warnings.push(
|
|
375
|
+
`kdna.json.version: non-semver format "${manifest.version}". Expected MAJOR.MINOR.PATCH.`,
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// 11. Check for removed fields
|
|
380
|
+
const removedFields = ['release_status', 'domain_field', 'judgment_patterns', 'files', 'registry'];
|
|
381
|
+
for (const field of removedFields) {
|
|
382
|
+
if (field in manifest) {
|
|
383
|
+
warnings.push(
|
|
384
|
+
`kdna.json: field "${field}" is not in the canonical domain manifest and should be removed`,
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// 12. Check removed license sub-fields
|
|
390
|
+
if (manifest.license && typeof manifest.license === 'object') {
|
|
391
|
+
for (const field of ['commercial', 'allow_agent_use', 'allow_redistribution', 'allow_training']) {
|
|
392
|
+
if (field in manifest.license) {
|
|
393
|
+
warnings.push(
|
|
394
|
+
`kdna.json.license.${field}: license-type-specific field, not universal. Consider removing.`,
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return { errors, warnings };
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
module.exports = { lintDomain, validateManifest };
|
package/src/loader.js
CHANGED
|
@@ -174,6 +174,16 @@ function detectOldFieldNames(obj, path = '', warnings = []) {
|
|
|
174
174
|
* @param {object} domain — result from loadDomainFromData() or loadDomainFromFiles()
|
|
175
175
|
* @returns {string}
|
|
176
176
|
*/
|
|
177
|
+
function sanitize(str) {
|
|
178
|
+
if (typeof str !== 'string') return str;
|
|
179
|
+
return str
|
|
180
|
+
.replace(/^#{1,6}\s/gm, '\\# ') // Escape leading # to prevent fake headers
|
|
181
|
+
.replace(/```/g, '\\`\\`\\`') // Escape code blocks
|
|
182
|
+
.replace(/<\|/g, '<|') // Escape special tokens
|
|
183
|
+
.replace(/\b(ignore|forget|disregard)\s+(all\s+)?(previous|prior|above)\s+(instructions?|directives?|rules?|constraints?)\b/gi,
|
|
184
|
+
'[filtered: $&]'); // Filter prompt injection patterns
|
|
185
|
+
}
|
|
186
|
+
|
|
177
187
|
function formatContext(domain) {
|
|
178
188
|
if (!domain || !domain.core || !domain.patterns) return '';
|
|
179
189
|
|
|
@@ -193,13 +203,13 @@ function formatContext(domain) {
|
|
|
193
203
|
}
|
|
194
204
|
|
|
195
205
|
parts.push('## Domain Cognition (KDNA)');
|
|
196
|
-
parts.push(`Domain: ${core.meta.domain}`);
|
|
206
|
+
parts.push(`Domain: ${sanitize(core.meta.domain)}`);
|
|
197
207
|
parts.push('');
|
|
198
208
|
|
|
199
209
|
if (core.stances && core.stances.length) {
|
|
200
210
|
parts.push('### Stances');
|
|
201
211
|
for (const s of core.stances) {
|
|
202
|
-
parts.push(`- ${s}`);
|
|
212
|
+
parts.push(`- ${sanitize(s)}`);
|
|
203
213
|
}
|
|
204
214
|
parts.push('');
|
|
205
215
|
}
|
|
@@ -207,8 +217,8 @@ function formatContext(domain) {
|
|
|
207
217
|
if (core.axioms && core.axioms.length) {
|
|
208
218
|
parts.push('### Axioms');
|
|
209
219
|
for (const a of core.axioms) {
|
|
210
|
-
parts.push(`- **${a.one_sentence}** ${a.full_statement}`);
|
|
211
|
-
parts.push(` *Why:* ${a.why}`);
|
|
220
|
+
parts.push(`- **${sanitize(a.one_sentence)}** ${sanitize(a.full_statement)}`);
|
|
221
|
+
parts.push(` *Why:* ${sanitize(a.why)}`);
|
|
212
222
|
}
|
|
213
223
|
parts.push('');
|
|
214
224
|
}
|
|
@@ -216,8 +226,8 @@ function formatContext(domain) {
|
|
|
216
226
|
if (core.ontology && core.ontology.length) {
|
|
217
227
|
parts.push('### Key Concepts');
|
|
218
228
|
for (const c of core.ontology) {
|
|
219
|
-
parts.push(`- **${c.id.replace(/_/g, ' ')}** — ${c.one_sentence}`);
|
|
220
|
-
parts.push(` Boundary: ${c.boundary}`);
|
|
229
|
+
parts.push(`- **${sanitize(c.id.replace(/_/g, ' '))}** — ${sanitize(c.one_sentence)}`);
|
|
230
|
+
parts.push(` Boundary: ${sanitize(c.boundary)}`);
|
|
221
231
|
}
|
|
222
232
|
parts.push('');
|
|
223
233
|
}
|
|
@@ -225,7 +235,7 @@ function formatContext(domain) {
|
|
|
225
235
|
if (core.frameworks && core.frameworks.length) {
|
|
226
236
|
parts.push('### Frameworks');
|
|
227
237
|
for (const fw of core.frameworks) {
|
|
228
|
-
parts.push(`- **${fw.name}**: ${fw.when_to_use}`);
|
|
238
|
+
parts.push(`- **${sanitize(fw.name)}**: ${sanitize(fw.when_to_use)}`);
|
|
229
239
|
}
|
|
230
240
|
parts.push('');
|
|
231
241
|
}
|
|
@@ -233,7 +243,7 @@ function formatContext(domain) {
|
|
|
233
243
|
if (pat.terminology && pat.terminology.banned_terms && pat.terminology.banned_terms.length) {
|
|
234
244
|
parts.push('### Avoid These Terms');
|
|
235
245
|
for (const b of pat.terminology.banned_terms) {
|
|
236
|
-
parts.push(`- Avoid "${b.term}". ${b.why} Use "${b.replace_with}" instead.`);
|
|
246
|
+
parts.push(`- Avoid "${sanitize(b.term)}". ${sanitize(b.why)} Use "${sanitize(b.replace_with)}" instead.`);
|
|
237
247
|
}
|
|
238
248
|
parts.push('');
|
|
239
249
|
}
|
|
@@ -241,8 +251,8 @@ function formatContext(domain) {
|
|
|
241
251
|
if (pat.misunderstandings && pat.misunderstandings.length) {
|
|
242
252
|
parts.push('### Watch For These Misunderstandings');
|
|
243
253
|
for (const m of pat.misunderstandings) {
|
|
244
|
-
parts.push(`- **Wrong:** ${m.wrong}`);
|
|
245
|
-
parts.push(` **Correct:** ${m.correct}`);
|
|
254
|
+
parts.push(`- **Wrong:** ${sanitize(m.wrong)}`);
|
|
255
|
+
parts.push(` **Correct:** ${sanitize(m.correct)}`);
|
|
246
256
|
}
|
|
247
257
|
parts.push('');
|
|
248
258
|
}
|
|
@@ -250,7 +260,7 @@ function formatContext(domain) {
|
|
|
250
260
|
if (pat.self_check && pat.self_check.length) {
|
|
251
261
|
parts.push('### Before Responding, Check');
|
|
252
262
|
for (const s of pat.self_check) {
|
|
253
|
-
parts.push(`- [ ] ${s}`);
|
|
263
|
+
parts.push(`- [ ] ${sanitize(s)}`);
|
|
254
264
|
}
|
|
255
265
|
parts.push('');
|
|
256
266
|
}
|
|
@@ -258,7 +268,7 @@ function formatContext(domain) {
|
|
|
258
268
|
if (domain.scenarios && domain.scenarios.scenes) {
|
|
259
269
|
parts.push('### Relevant Scenarios');
|
|
260
270
|
for (const scene of domain.scenarios.scenes) {
|
|
261
|
-
parts.push(`- **${scene.name}**: ${scene.trigger_signal}`);
|
|
271
|
+
parts.push(`- **${sanitize(scene.name)}**: ${sanitize(scene.trigger_signal)}`);
|
|
262
272
|
}
|
|
263
273
|
parts.push('');
|
|
264
274
|
}
|
|
@@ -266,7 +276,7 @@ function formatContext(domain) {
|
|
|
266
276
|
if (domain.reasoning && domain.reasoning.reasoning_chains) {
|
|
267
277
|
parts.push('### Reasoning Chains');
|
|
268
278
|
for (const r of domain.reasoning.reasoning_chains) {
|
|
269
|
-
parts.push(`- **${r.one_sentence}** → ${r.so_what}`);
|
|
279
|
+
parts.push(`- **${sanitize(r.one_sentence)}** → ${sanitize(r.so_what)}`);
|
|
270
280
|
}
|
|
271
281
|
parts.push('');
|
|
272
282
|
}
|
|
@@ -274,11 +284,11 @@ function formatContext(domain) {
|
|
|
274
284
|
if (domain.cases && domain.cases.cases && domain.cases.cases.length) {
|
|
275
285
|
parts.push('### Cases');
|
|
276
286
|
for (const c of domain.cases.cases) {
|
|
277
|
-
parts.push(`- **${c.title}**`);
|
|
278
|
-
parts.push(` Context: ${c.context}`);
|
|
279
|
-
parts.push(` What happened: ${c.what_happened}`);
|
|
280
|
-
parts.push(` Learned: ${c.what_was_learned}`);
|
|
281
|
-
parts.push(` Pattern: ${c.structural_pattern}`);
|
|
287
|
+
parts.push(`- **${sanitize(c.title)}**`);
|
|
288
|
+
parts.push(` Context: ${sanitize(c.context)}`);
|
|
289
|
+
parts.push(` What happened: ${sanitize(c.what_happened)}`);
|
|
290
|
+
parts.push(` Learned: ${sanitize(c.what_was_learned)}`);
|
|
291
|
+
parts.push(` Pattern: ${sanitize(c.structural_pattern)}`);
|
|
282
292
|
}
|
|
283
293
|
parts.push('');
|
|
284
294
|
}
|
|
@@ -288,7 +298,7 @@ function formatContext(domain) {
|
|
|
288
298
|
if (evo.stages && evo.stages.length) {
|
|
289
299
|
parts.push('### Growth Stages');
|
|
290
300
|
for (const stage of evo.stages) {
|
|
291
|
-
parts.push(`- **${stage.name}**: ${stage.description}`);
|
|
301
|
+
parts.push(`- **${sanitize(stage.name)}**: ${sanitize(stage.description)}`);
|
|
292
302
|
}
|
|
293
303
|
parts.push('');
|
|
294
304
|
}
|
|
@@ -296,7 +306,7 @@ function formatContext(domain) {
|
|
|
296
306
|
parts.push('### Capability Layers');
|
|
297
307
|
for (const layer of evo.evolution_layers) {
|
|
298
308
|
parts.push(
|
|
299
|
-
`- **${layer.name}**: ${layer.capability} (${layer.from_stage} → ${layer.to_stage})`,
|
|
309
|
+
`- **${sanitize(layer.name)}**: ${sanitize(layer.capability)} (${sanitize(layer.from_stage)} → ${sanitize(layer.to_stage)})`,
|
|
300
310
|
);
|
|
301
311
|
}
|
|
302
312
|
parts.push('');
|