@aikdna/kdna-core 0.15.9 → 0.15.10

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+
4
+ ## v0.15.10 (2026-06-30)
5
+
6
+ **API**: export `parseSemver`, `compareSemver`, `satisfies` from public module.
7
+
8
+ These semver utilities were already used internally by kdna-core (Story 6 dependency
9
+ resolution) but were not part of the public API. Exporting them allows consumers
10
+ (e.g. `@aikdna/kdna-cli`) to use the canonical implementation rather than maintaining
11
+ a parallel copy.
12
+
13
+ - **`parseSemver(v)`** — parse a semver string into `{major, minor, patch}` or `null`
14
+ - **`compareSemver(a, b)`** — compare two version strings, returns `< 0 | 0 | > 0`
15
+ - **`satisfies(version, range)`** — test a version against a range (`^`, `~`, `>=`, etc.)
16
+
17
+ No breaking changes. Purely additive.
18
+
3
19
  ## v0.15.9 (2026-06-28)
4
20
 
5
21
  Story 12 — Asset inheritance (`extends` field, RFC #148 v2.x Phase 3).
package/package.json CHANGED
@@ -1,70 +1,70 @@
1
1
  {
2
- "name": "@aikdna/kdna-core",
3
- "version": "0.15.9",
4
- "description": "KDNA Core library for validating, planning, and loading local .kdna judgment assets.",
5
- "engines": {
6
- "node": ">=18.0.0"
7
- },
8
- "type": "commonjs",
9
- "main": "src/index.js",
10
- "module": "src/index.mjs",
11
- "exports": {
12
- ".": {
13
- "import": "./src/index.mjs",
14
- "require": "./src/index.js",
15
- "types": "./src/types.d.ts"
2
+ "name": "@aikdna/kdna-core",
3
+ "version": "0.15.10",
4
+ "description": "KDNA Core library for validating, planning, and loading local .kdna judgment assets.",
5
+ "engines": {
6
+ "node": ">=18.0.0"
16
7
  },
17
- "./package.json": "./package.json",
18
- "./schema/*": "./schema/*",
19
- "./v1": {
20
- "import": "./src/v1/index.mjs",
21
- "require": "./src/v1/index.js",
22
- "types": "./src/types.d.ts"
23
- }
24
- },
25
- "types": "src/types.d.ts",
26
- "scripts": {
27
- "test": "node ../../scripts/run-node-tests.js test/*.test.js && node -e \"const m = require('./src/index.js'); console.log('kdna-core exports:', Object.keys(m).join(', '));\"",
28
- "prepublishOnly": "npm run release:check",
29
- "release:check": "node scripts/check-release-readiness.js"
30
- },
31
- "files": [
32
- "src/",
33
- "schema/",
34
- "README.md",
35
- "CHANGELOG.md",
36
- "LICENSE",
37
- "NOTICE"
38
- ],
39
- "keywords": [
40
- "kdna",
41
- "kdna-core",
42
- "ai-agent",
43
- "judgment-assets"
44
- ],
45
- "license": "Apache-2.0",
46
- "repository": {
47
- "type": "git",
48
- "url": "git+https://github.com/aikdna/kdna.git",
49
- "directory": "packages/kdna-core"
50
- },
51
- "homepage": "https://aikdna.com",
52
- "peerDependencies": {
53
- "ajv": "^8.17.1",
54
- "ajv-formats": "^3.0.1"
55
- },
56
- "peerDependenciesMeta": {
57
- "ajv": {
58
- "optional": true
8
+ "type": "commonjs",
9
+ "main": "src/index.js",
10
+ "module": "src/index.mjs",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./src/index.mjs",
14
+ "require": "./src/index.js",
15
+ "types": "./src/types.d.ts"
16
+ },
17
+ "./package.json": "./package.json",
18
+ "./schema/*": "./schema/*",
19
+ "./v1": {
20
+ "import": "./src/v1/index.mjs",
21
+ "require": "./src/v1/index.js",
22
+ "types": "./src/types.d.ts"
23
+ }
24
+ },
25
+ "types": "src/types.d.ts",
26
+ "scripts": {
27
+ "test": "node ../../scripts/run-node-tests.js test/*.test.js && node -e \"const m = require('./src/index.js'); console.log('kdna-core exports:', Object.keys(m).join(', '));\"",
28
+ "prepublishOnly": "npm run release:check",
29
+ "release:check": "node scripts/check-release-readiness.js"
30
+ },
31
+ "files": [
32
+ "src/",
33
+ "schema/",
34
+ "README.md",
35
+ "CHANGELOG.md",
36
+ "LICENSE",
37
+ "NOTICE"
38
+ ],
39
+ "keywords": [
40
+ "kdna",
41
+ "kdna-core",
42
+ "ai-agent",
43
+ "judgment-assets"
44
+ ],
45
+ "license": "Apache-2.0",
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/aikdna/kdna.git",
49
+ "directory": "packages/kdna-core"
50
+ },
51
+ "homepage": "https://aikdna.com",
52
+ "peerDependencies": {
53
+ "ajv": "^8.17.1",
54
+ "ajv-formats": "^3.0.1"
55
+ },
56
+ "peerDependenciesMeta": {
57
+ "ajv": {
58
+ "optional": true
59
+ },
60
+ "ajv-formats": {
61
+ "optional": true
62
+ }
59
63
  },
60
- "ajv-formats": {
61
- "optional": true
64
+ "dependencies": {
65
+ "@noble/hashes": "^1.8.0",
66
+ "cbor-x": "^1.6.4",
67
+ "ajv": "^8.20.0",
68
+ "ajv-formats": "^3.0.1"
62
69
  }
63
- },
64
- "dependencies": {
65
- "@noble/hashes": "^1.8.0",
66
- "cbor-x": "^1.6.4",
67
- "ajv": "^8.20.0",
68
- "ajv-formats": "^3.0.1"
69
- }
70
70
  }
@@ -311,28 +311,42 @@ function verifyHumanLockSignatures(coreData, manifest, errors, warnings) {
311
311
  // Skip if no public key available (unsigned assets are valid)
312
312
  return;
313
313
  }
314
- const axioms = coreData?.axioms || [];
315
- if (!Array.isArray(axioms) || axioms.length === 0) return;
314
+
315
+ // All card-type arrays in KDNA_Core.json that may carry human_lock.
316
+ // Ordered by how they appear in the compiled payload (compileCore in
317
+ // kdna-studio-core/src/compile/index.js).
318
+ const CORE_CARD_ARRAYS = [
319
+ ['axioms', 'axiom'],
320
+ ['ontology', 'ontology'],
321
+ ['frameworks', 'framework'],
322
+ ['boundaries', 'boundary'],
323
+ ['risks', 'risk'],
324
+ ['stances', 'stance'],
325
+ ];
316
326
 
317
327
  let verified = 0, missing = 0, invalid = 0;
318
- for (const ax of axioms) {
319
- const hl = ax.human_lock;
320
- if (!hl || !hl.signature) {
321
- // Only warn for locked cards without signature
322
- if (ax.status === 'locked' || ax.status === 'tested' || ax.status === 'published') {
323
- missing++;
328
+ for (const [arrayName, _cardType] of CORE_CARD_ARRAYS) {
329
+ const cards = coreData?.[arrayName];
330
+ if (!Array.isArray(cards) || cards.length === 0) continue;
331
+
332
+ for (const card of cards) {
333
+ const hl = card.human_lock;
334
+ if (!hl || !hl.signature) {
335
+ if (card.status === 'locked' || card.status === 'tested' || card.status === 'published') {
336
+ missing++;
337
+ }
338
+ continue;
339
+ }
340
+ try {
341
+ const payload = [card.id, hl.statement || '', hl.judgment_fingerprint || ''].join('\n');
342
+ const sig = Buffer.from(String(hl.signature).replace(/^ed25519:/, ''), 'hex');
343
+ const key = crypto.createPublicKey(publicKeyPEM);
344
+ const ok = crypto.verify(null, Buffer.from(payload), key, sig);
345
+ if (ok) { verified++; }
346
+ else { invalid++; }
347
+ } catch {
348
+ invalid++;
324
349
  }
325
- continue;
326
- }
327
- try {
328
- const payload = [ax.id, hl.statement || '', hl.judgment_fingerprint || ''].join('\n');
329
- const sig = Buffer.from(String(hl.signature).replace(/^ed25519:/, ''), 'hex');
330
- const key = crypto.createPublicKey(publicKeyPEM);
331
- const ok = crypto.verify(null, Buffer.from(payload), key, sig);
332
- if (ok) { verified++; }
333
- else { invalid++; }
334
- } catch {
335
- invalid++;
336
350
  }
337
351
  }
338
352
 
package/src/v1/index.js CHANGED
@@ -1616,6 +1616,12 @@ module.exports = {
1616
1616
  unpack,
1617
1617
  loadV1,
1618
1618
  FORBIDDEN_OUTPUT_TERMS,
1619
+ // Semver utilities (Story 6 / Story 13) — exported so consumers
1620
+ // (e.g. kdna-cli) can use the canonical implementation instead of
1621
+ // duplicating it.
1622
+ parseSemver,
1623
+ compareSemver,
1624
+ satisfies,
1619
1625
  };
1620
1626
 
1621
1627
  // ─── loadV1 — v1 runtime loading / load contract ──────────────────────