@aikdna/kdna-cli 0.17.0 → 0.18.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 +42 -23
- package/package.json +5 -4
- package/skills/kdna-loader/SKILL.md +5 -6
- package/src/agent.js +145 -109
- package/src/cli.js +104 -60
- package/src/cmds/_common.js +32 -16
- package/src/cmds/badge.js +7 -7
- package/src/cmds/changelog.js +1 -1
- package/src/cmds/cluster.js +16 -48
- package/src/cmds/doctor.js +10 -27
- package/src/cmds/domain.js +77 -400
- package/src/cmds/explain.js +122 -0
- package/src/cmds/legacy.js +8 -8
- package/src/cmds/license.js +483 -26
- package/src/cmds/quality.js +2 -2
- package/src/cmds/registry.js +15 -67
- package/src/cmds/studio.js +4 -5
- package/src/cmds/test.js +4 -4
- package/src/cmds/trace.js +11 -7
- package/src/compare.js +28 -22
- package/src/diff.js +11 -13
- package/src/init.js +2 -2
- package/src/install.js +138 -460
- package/src/loader.js +10 -10
- package/src/package-store.js +229 -0
- package/src/paths.js +44 -0
- package/src/publish.js +73 -22
- package/src/registry.js +76 -9
- package/src/setup.js +19 -20
- package/src/verify.js +233 -124
- package/templates/standard-domain/kdna.json +2 -1
- package/src/cmds/encrypt.js +0 -199
package/src/agent.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* not treat as a fit decision; many false positives expected)
|
|
17
17
|
* The agent makes the final call using its own language understanding.
|
|
18
18
|
*
|
|
19
|
-
* kdna load <name> [--as=prompt|json|raw]
|
|
19
|
+
* kdna load <name|file.kdna> [--as=prompt|json|raw]
|
|
20
20
|
* Read the domain's Core + Patterns and emit:
|
|
21
21
|
* --as=prompt (default): compact text suitable for system-prompt
|
|
22
22
|
* injection (axioms one-liners + stances +
|
|
@@ -30,44 +30,44 @@
|
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
32
|
const fs = require('fs');
|
|
33
|
-
const path = require('path');
|
|
34
33
|
const { parseName } = require('./registry');
|
|
35
34
|
const { recordTrace } = require('./cmds/trace');
|
|
35
|
+
const {
|
|
36
|
+
getInstalled,
|
|
37
|
+
listInstalled: listInstalledAssets,
|
|
38
|
+
readContainer,
|
|
39
|
+
readContainerEntry,
|
|
40
|
+
readContainerJson,
|
|
41
|
+
resolveAsset,
|
|
42
|
+
} = require('./package-store');
|
|
43
|
+
const { licenseDecryptOptionsForManifest } = require('./cmds/license');
|
|
36
44
|
|
|
37
45
|
function detectAgent() {
|
|
38
46
|
return process.env.KDNA_AGENT || 'cli';
|
|
39
47
|
}
|
|
40
48
|
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
function listInstalled() {
|
|
50
|
+
return listInstalledAssets().map((entry) => {
|
|
51
|
+
const parsed = parseName(entry.full);
|
|
52
|
+
return { ...entry, scope: parsed.scope, ident: parsed.ident };
|
|
53
|
+
});
|
|
54
|
+
}
|
|
43
55
|
|
|
44
|
-
function
|
|
45
|
-
|
|
46
|
-
return JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
47
|
-
} catch {
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
56
|
+
function assetLabel(asset, fallback) {
|
|
57
|
+
return asset.name || asset.parsed?.full || fallback;
|
|
50
58
|
}
|
|
51
59
|
|
|
52
|
-
function
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (!fs.statSync(dir).isDirectory()) continue;
|
|
64
|
-
out.push({ scope: scopeName, ident, dir, full: `${scopeName}/${ident}` });
|
|
65
|
-
}
|
|
66
|
-
} catch {
|
|
67
|
-
/* skip */
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return out;
|
|
60
|
+
function traceAssetFields(asset, manifest = {}, license = null) {
|
|
61
|
+
const fields = {
|
|
62
|
+
asset_path: asset.asset_path,
|
|
63
|
+
asset_digest: asset.asset_digest || null,
|
|
64
|
+
content_digest: asset.content_digest || null,
|
|
65
|
+
version: manifest.version || asset.version || null,
|
|
66
|
+
judgment_version: manifest.judgment_version || asset.judgment_version || null,
|
|
67
|
+
access: manifest.access || asset.access || null,
|
|
68
|
+
};
|
|
69
|
+
if (license?.license_id) fields.license_id = license.license_id;
|
|
70
|
+
return fields;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// ─── kdna available ────────────────────────────────────────────────────
|
|
@@ -78,11 +78,9 @@ function cmdAvailable(args = []) {
|
|
|
78
78
|
|
|
79
79
|
const out = [];
|
|
80
80
|
for (const e of installed) {
|
|
81
|
-
const manifest =
|
|
81
|
+
const { manifest = {}, core = {} } = readContainer(e.asset_path);
|
|
82
82
|
if (manifest.yanked === true) continue;
|
|
83
83
|
|
|
84
|
-
const core = readJson(path.join(e.dir, 'KDNA_Core.json')) || {};
|
|
85
|
-
|
|
86
84
|
// Pull applies_when across all axioms (this is what the agent needs
|
|
87
85
|
// for fit-check). Collapsing per-axiom into one set makes the agent's
|
|
88
86
|
// matching decision much cheaper.
|
|
@@ -110,14 +108,7 @@ function cmdAvailable(args = []) {
|
|
|
110
108
|
}
|
|
111
109
|
|
|
112
110
|
if (wantJson) {
|
|
113
|
-
|
|
114
|
-
? out
|
|
115
|
-
: {
|
|
116
|
-
count: 0,
|
|
117
|
-
domains: [],
|
|
118
|
-
note: 'No domains installed. Run: kdna install <name> See: kdna list --available',
|
|
119
|
-
};
|
|
120
|
-
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
111
|
+
process.stdout.write(JSON.stringify(out, null, 2) + '\n');
|
|
121
112
|
return;
|
|
122
113
|
}
|
|
123
114
|
|
|
@@ -195,12 +186,11 @@ function cmdMatch(taskText, args = []) {
|
|
|
195
186
|
const hints = [];
|
|
196
187
|
|
|
197
188
|
for (const e of installed) {
|
|
198
|
-
const manifest =
|
|
189
|
+
const { manifest = {}, core = {} } = readContainer(e.asset_path);
|
|
199
190
|
if (manifest.yanked === true) {
|
|
200
191
|
dropped.push({ name: manifest.name || e.full, reason: 'yanked' });
|
|
201
192
|
continue;
|
|
202
193
|
}
|
|
203
|
-
const core = readJson(path.join(e.dir, 'KDNA_Core.json')) || {};
|
|
204
194
|
|
|
205
195
|
// does_not_apply_when disqualification (HARD signal)
|
|
206
196
|
let disqualified = null;
|
|
@@ -318,7 +308,7 @@ function cmdMatch(taskText, args = []) {
|
|
|
318
308
|
}
|
|
319
309
|
}
|
|
320
310
|
console.log('');
|
|
321
|
-
console.log('To consider any of these, read its full data: kdna load <name> --as=json');
|
|
311
|
+
console.log('To consider any of these, read its full data: kdna load <name|file.kdna> --as=json');
|
|
322
312
|
}
|
|
323
313
|
}
|
|
324
314
|
|
|
@@ -348,20 +338,38 @@ function cmdLoad(input, args = []) {
|
|
|
348
338
|
profileInput = args[inputIdx + 1] || null;
|
|
349
339
|
}
|
|
350
340
|
|
|
351
|
-
const
|
|
352
|
-
if (!
|
|
353
|
-
console.error(`
|
|
341
|
+
const asset = resolveAsset(input);
|
|
342
|
+
if (!asset) {
|
|
343
|
+
console.error(`KDNA asset not found: ${input}. Use an installed name or a .kdna file.`);
|
|
354
344
|
process.exit(2);
|
|
355
345
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
346
|
+
|
|
347
|
+
const manifest = readContainerJson(asset.asset_path, 'kdna.json') || {};
|
|
348
|
+
const encryptedEntries = manifest.encryption?.encrypted_entries || [];
|
|
349
|
+
let decryptOptions = {};
|
|
350
|
+
let licenseActivation = null;
|
|
351
|
+
if (manifest.access === 'licensed' || encryptedEntries.length > 0) {
|
|
352
|
+
const activation = licenseDecryptOptionsForManifest(manifest);
|
|
353
|
+
if (!activation.ok) {
|
|
354
|
+
console.error(`KDNA license required for ${manifest.name || input}: ${activation.error}`);
|
|
355
|
+
console.error(`Install a license with: kdna license install <license.json>`);
|
|
356
|
+
process.exit(3);
|
|
357
|
+
}
|
|
358
|
+
decryptOptions = { decryptEntry: activation.decryptEntry };
|
|
359
|
+
licenseActivation = activation.license;
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
-
|
|
362
|
+
let container;
|
|
363
|
+
try {
|
|
364
|
+
container = readContainer(asset.asset_path, decryptOptions);
|
|
365
|
+
} catch (e) {
|
|
366
|
+
console.error(`Failed to load KDNA asset: ${e.message}`);
|
|
367
|
+
process.exit(3);
|
|
368
|
+
}
|
|
369
|
+
const parsed = asset.parsed || parseName(manifest.name || '');
|
|
370
|
+
const label = assetLabel(asset, input);
|
|
363
371
|
if (manifest.yanked === true) {
|
|
364
|
-
console.error(`${
|
|
372
|
+
console.error(`${label}@${manifest.version} has been yanked.`);
|
|
365
373
|
if (manifest.replaced_by) console.error(`Try: ${manifest.replaced_by}`);
|
|
366
374
|
process.exit(2);
|
|
367
375
|
}
|
|
@@ -386,8 +394,8 @@ function cmdLoad(input, args = []) {
|
|
|
386
394
|
if (loadWarnings.length > 0) {
|
|
387
395
|
console.error(loadWarnings.join('\n'));
|
|
388
396
|
}
|
|
389
|
-
const core =
|
|
390
|
-
const pat =
|
|
397
|
+
const core = container.core || {};
|
|
398
|
+
const pat = container.patterns || {};
|
|
391
399
|
|
|
392
400
|
// JSON format
|
|
393
401
|
if (format === 'json') {
|
|
@@ -401,13 +409,17 @@ function cmdLoad(input, args = []) {
|
|
|
401
409
|
deprecated: manifest.status === 'deprecated',
|
|
402
410
|
yanked: false,
|
|
403
411
|
warnings: loadWarnings,
|
|
412
|
+
asset_digest: asset.asset_digest || null,
|
|
413
|
+
content_digest: asset.content_digest || null,
|
|
414
|
+
license_id: licenseActivation?.license_id || null,
|
|
404
415
|
},
|
|
405
416
|
}, null, 2) + '\n');
|
|
406
417
|
recordTrace({
|
|
407
418
|
timestamp: new Date().toISOString(),
|
|
408
419
|
agent: detectAgent(),
|
|
409
|
-
domain:
|
|
420
|
+
domain: label,
|
|
410
421
|
format: 'json',
|
|
422
|
+
asset: traceAssetFields(asset, manifest, licenseActivation),
|
|
411
423
|
});
|
|
412
424
|
return;
|
|
413
425
|
}
|
|
@@ -415,40 +427,46 @@ function cmdLoad(input, args = []) {
|
|
|
415
427
|
// Raw format
|
|
416
428
|
if (format === 'raw') {
|
|
417
429
|
for (const f of ['KDNA_Core.json', 'KDNA_Patterns.json']) {
|
|
418
|
-
const
|
|
419
|
-
|
|
430
|
+
const encrypted = encryptedEntries.includes(f);
|
|
431
|
+
const buf = encrypted
|
|
432
|
+
? Buffer.from(JSON.stringify(container[f === 'KDNA_Core.json' ? 'core' : 'patterns'], null, 2))
|
|
433
|
+
: readContainerEntry(asset.asset_path, f);
|
|
434
|
+
if (buf) {
|
|
420
435
|
process.stdout.write(`\n=== ${f} ===\n`);
|
|
421
|
-
process.stdout.write(
|
|
436
|
+
process.stdout.write(buf.toString('utf8'));
|
|
422
437
|
}
|
|
423
438
|
}
|
|
424
439
|
recordTrace({
|
|
425
440
|
timestamp: new Date().toISOString(),
|
|
426
441
|
agent: detectAgent(),
|
|
427
|
-
domain:
|
|
442
|
+
domain: label,
|
|
428
443
|
format: 'raw',
|
|
444
|
+
asset: traceAssetFields(asset, manifest, licenseActivation),
|
|
429
445
|
});
|
|
430
446
|
return;
|
|
431
447
|
}
|
|
432
448
|
|
|
433
449
|
// Load profiles
|
|
434
450
|
if (profile) {
|
|
435
|
-
emitProfile(parsed, manifest, core, pat, profile, profileInput);
|
|
451
|
+
emitProfile(parsed || { full: label }, manifest, core, pat, profile, profileInput);
|
|
436
452
|
recordTrace({
|
|
437
453
|
timestamp: new Date().toISOString(),
|
|
438
454
|
agent: detectAgent(),
|
|
439
|
-
domain:
|
|
455
|
+
domain: label,
|
|
440
456
|
format: `profile:${profile}`,
|
|
457
|
+
asset: traceAssetFields(asset, manifest, licenseActivation),
|
|
441
458
|
});
|
|
442
459
|
return;
|
|
443
460
|
}
|
|
444
461
|
|
|
445
462
|
// Default: --as=prompt — compact text optimized for system-prompt injection.
|
|
446
|
-
emitCompact(parsed, manifest, core, pat);
|
|
463
|
+
emitCompact(parsed || { full: label }, manifest, core, pat);
|
|
447
464
|
recordTrace({
|
|
448
465
|
timestamp: new Date().toISOString(),
|
|
449
466
|
agent: detectAgent(),
|
|
450
|
-
domain:
|
|
467
|
+
domain: label,
|
|
451
468
|
format: 'prompt',
|
|
469
|
+
asset: traceAssetFields(asset, manifest, licenseActivation),
|
|
452
470
|
});
|
|
453
471
|
}
|
|
454
472
|
|
|
@@ -461,6 +479,7 @@ function emitProfile(parsed, manifest, core, pat, profile, input) {
|
|
|
461
479
|
lines.push('');
|
|
462
480
|
|
|
463
481
|
const axioms = core.axioms || [];
|
|
482
|
+
emitRequiredOutput(lines, manifest, core, pat);
|
|
464
483
|
|
|
465
484
|
switch (profile) {
|
|
466
485
|
case 'index':
|
|
@@ -546,11 +565,11 @@ function emitProfile(parsed, manifest, core, pat, profile, input) {
|
|
|
546
565
|
}
|
|
547
566
|
|
|
548
567
|
if (pat.terminology?.banned_terms?.length) {
|
|
549
|
-
lines.push('##
|
|
568
|
+
lines.push('## MUST NOT SAY');
|
|
550
569
|
for (const t of pat.terminology.banned_terms) {
|
|
551
570
|
const term = typeof t === 'string' ? t : t.term;
|
|
552
571
|
const replace = typeof t === 'object' ? t.replace_with : null;
|
|
553
|
-
lines.push(`- "${term}"${replace ? `
|
|
572
|
+
lines.push(`- "${term}"${replace ? ` -> use: ${replace}` : ''}`);
|
|
554
573
|
}
|
|
555
574
|
lines.push('');
|
|
556
575
|
}
|
|
@@ -589,8 +608,11 @@ function emitCompact(parsed, manifest, core, pat) {
|
|
|
589
608
|
if (manifest.core_insight) lines.push(`# core insight: ${manifest.core_insight}`);
|
|
590
609
|
lines.push('');
|
|
591
610
|
|
|
611
|
+
emitRequiredOutput(lines, manifest, core, pat);
|
|
612
|
+
|
|
592
613
|
if (core.axioms?.length) {
|
|
593
|
-
lines.push('##
|
|
614
|
+
lines.push('## JUDGMENT GUIDANCE');
|
|
615
|
+
lines.push('### Axioms (reason from these)');
|
|
594
616
|
for (const a of core.axioms) {
|
|
595
617
|
lines.push(`- ${a.one_sentence}`);
|
|
596
618
|
if (a.applies_when?.length) {
|
|
@@ -605,7 +627,7 @@ function emitCompact(parsed, manifest, core, pat) {
|
|
|
605
627
|
}
|
|
606
628
|
|
|
607
629
|
if (core.stances?.length) {
|
|
608
|
-
lines.push('
|
|
630
|
+
lines.push('### Stances');
|
|
609
631
|
for (const s of core.stances) {
|
|
610
632
|
const text = typeof s === 'string' ? s : s.stance;
|
|
611
633
|
if (text) lines.push(`- ${text}`);
|
|
@@ -614,17 +636,18 @@ function emitCompact(parsed, manifest, core, pat) {
|
|
|
614
636
|
}
|
|
615
637
|
|
|
616
638
|
if (pat.terminology?.banned_terms?.length) {
|
|
617
|
-
lines.push('##
|
|
639
|
+
lines.push('## MUST NOT SAY');
|
|
618
640
|
for (const t of pat.terminology.banned_terms) {
|
|
619
641
|
const term = typeof t === 'string' ? t : t.term;
|
|
620
642
|
const replace = typeof t === 'object' ? t.replace_with : null;
|
|
621
|
-
lines.push(`- "${term}"${replace ? `
|
|
643
|
+
lines.push(`- "${term}"${replace ? ` -> use: ${replace}` : ''}`);
|
|
622
644
|
}
|
|
623
645
|
lines.push('');
|
|
624
646
|
}
|
|
625
647
|
|
|
626
648
|
if (pat.misunderstandings?.length) {
|
|
627
|
-
lines.push('##
|
|
649
|
+
if (!core.axioms?.length) lines.push('## JUDGMENT GUIDANCE');
|
|
650
|
+
lines.push('### Misunderstandings to detect and avoid');
|
|
628
651
|
for (const m of pat.misunderstandings) {
|
|
629
652
|
lines.push(`- WRONG: ${m.wrong}`);
|
|
630
653
|
lines.push(` CORRECT: ${m.correct}`);
|
|
@@ -634,7 +657,8 @@ function emitCompact(parsed, manifest, core, pat) {
|
|
|
634
657
|
}
|
|
635
658
|
|
|
636
659
|
if (pat.self_check?.length) {
|
|
637
|
-
lines.push('##
|
|
660
|
+
lines.push('## SELF-CHECK');
|
|
661
|
+
lines.push('Answer before final output.');
|
|
638
662
|
for (const q of pat.self_check) {
|
|
639
663
|
const text = typeof q === 'string' ? q : q.question;
|
|
640
664
|
if (text) lines.push(`- ${text}`);
|
|
@@ -649,6 +673,37 @@ function emitCompact(parsed, manifest, core, pat) {
|
|
|
649
673
|
process.stdout.write(lines.join('\n') + '\n');
|
|
650
674
|
}
|
|
651
675
|
|
|
676
|
+
function emitRequiredOutput(lines, manifest, core, pat) {
|
|
677
|
+
const required = uniqueStrings([
|
|
678
|
+
...asStringArray(manifest.required_output),
|
|
679
|
+
...asStringArray(manifest.must_include),
|
|
680
|
+
...asStringArray(core.required_output),
|
|
681
|
+
...asStringArray(core.must_include),
|
|
682
|
+
...asStringArray(pat.required_output),
|
|
683
|
+
...asStringArray(pat.must_include),
|
|
684
|
+
...asStringArray(pat.output_constraints?.required_output),
|
|
685
|
+
...asStringArray(pat.output_constraints?.must_include),
|
|
686
|
+
]);
|
|
687
|
+
|
|
688
|
+
if (!required.length) return;
|
|
689
|
+
|
|
690
|
+
lines.push('## REQUIRED OUTPUT');
|
|
691
|
+
lines.push('Include these statements when they are relevant to the user request.');
|
|
692
|
+
for (const item of required) lines.push(`- ${item}`);
|
|
693
|
+
lines.push('');
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
function asStringArray(value) {
|
|
697
|
+
if (!value) return [];
|
|
698
|
+
if (typeof value === 'string') return [value];
|
|
699
|
+
if (!Array.isArray(value)) return [];
|
|
700
|
+
return value.filter((item) => typeof item === 'string' && item.trim()).map((item) => item.trim());
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
function uniqueStrings(items) {
|
|
704
|
+
return Array.from(new Set(items.map((item) => item.trim()).filter(Boolean)));
|
|
705
|
+
}
|
|
706
|
+
|
|
652
707
|
// ─── kdna select ───────────────────────────────────────────────────────
|
|
653
708
|
|
|
654
709
|
function cmdSelect(args = []) {
|
|
@@ -674,9 +729,8 @@ function cmdSelect(args = []) {
|
|
|
674
729
|
const scores = [];
|
|
675
730
|
|
|
676
731
|
for (const e of installed) {
|
|
677
|
-
const manifest =
|
|
732
|
+
const { manifest = {}, core = {} } = readContainer(e.asset_path);
|
|
678
733
|
if (manifest.yanked === true) continue;
|
|
679
|
-
const core = readJson(path.join(e.dir, 'KDNA_Core.json')) || {};
|
|
680
734
|
|
|
681
735
|
// Check does_not_apply_when hard exclusion
|
|
682
736
|
let excluded = false;
|
|
@@ -774,14 +828,15 @@ function cmdPostvalidate(args = []) {
|
|
|
774
828
|
console.error(`Invalid name "${input}".`);
|
|
775
829
|
process.exit(2);
|
|
776
830
|
}
|
|
777
|
-
const
|
|
778
|
-
if (!
|
|
831
|
+
const installed = getInstalled(parsed.full);
|
|
832
|
+
if (!installed) {
|
|
779
833
|
console.error(`${parsed.full} is not installed.`);
|
|
780
834
|
process.exit(2);
|
|
781
835
|
}
|
|
782
836
|
|
|
783
|
-
const
|
|
784
|
-
const
|
|
837
|
+
const container = readContainer(installed.asset_path);
|
|
838
|
+
const core = container.core || {};
|
|
839
|
+
const pat = container.patterns || {};
|
|
785
840
|
|
|
786
841
|
// Read agent output
|
|
787
842
|
let agentOutput = '';
|
|
@@ -1017,7 +1072,7 @@ function cmdRoute(taskText, args = []) {
|
|
|
1017
1072
|
const candidates = [];
|
|
1018
1073
|
|
|
1019
1074
|
for (const e of installed) {
|
|
1020
|
-
const manifest =
|
|
1075
|
+
const { manifest = {}, core = {} } = readContainer(e.asset_path);
|
|
1021
1076
|
if (manifest.yanked === true) {
|
|
1022
1077
|
result.rejected_domains.push({
|
|
1023
1078
|
domain: manifest.name || e.full,
|
|
@@ -1027,8 +1082,6 @@ function cmdRoute(taskText, args = []) {
|
|
|
1027
1082
|
continue;
|
|
1028
1083
|
}
|
|
1029
1084
|
|
|
1030
|
-
const core = readJson(path.join(e.dir, 'KDNA_Core.json')) || {};
|
|
1031
|
-
|
|
1032
1085
|
// Negative match: does_not_apply_when
|
|
1033
1086
|
let disqualified = null;
|
|
1034
1087
|
for (const a of core.axioms || []) {
|
|
@@ -1181,19 +1234,16 @@ function cmdRoute(taskText, args = []) {
|
|
|
1181
1234
|
}
|
|
1182
1235
|
}
|
|
1183
1236
|
|
|
1184
|
-
function checkTrust(domainName
|
|
1237
|
+
function checkTrust(domainName) {
|
|
1185
1238
|
const failures = [];
|
|
1186
1239
|
const warnings = [];
|
|
1187
|
-
const
|
|
1188
|
-
const entry = installed.find(e => `${e.scope}/${e.ident}` === domainName || e.full === domainName);
|
|
1240
|
+
const entry = getInstalled(domainName);
|
|
1189
1241
|
if (!entry) {
|
|
1190
|
-
failures.push('domain not found in
|
|
1242
|
+
failures.push('domain asset not found in package index');
|
|
1191
1243
|
return { passed: false, failures, warnings };
|
|
1192
1244
|
}
|
|
1193
1245
|
|
|
1194
|
-
const manifest =
|
|
1195
|
-
const core = readJson(path.join(entry.dir, 'KDNA_Core.json')) || {};
|
|
1196
|
-
const evolution = readJson(path.join(entry.dir, 'KDNA_Evolution.json')) || {};
|
|
1246
|
+
const { manifest = {}, core = {}, evolution = {} } = readContainer(entry.asset_path);
|
|
1197
1247
|
|
|
1198
1248
|
// 1. Yank check
|
|
1199
1249
|
if (manifest.yanked === true) {
|
|
@@ -1236,31 +1286,17 @@ function checkTrust(domainName, options = {}) {
|
|
|
1236
1286
|
|
|
1237
1287
|
// 6. License validity (commercial domains)
|
|
1238
1288
|
if (manifest.access === 'licensed' || manifest.access === 'runtime') {
|
|
1239
|
-
const
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
if (!entry.expires_at || new Date(entry.expires_at) > new Date()) {
|
|
1248
|
-
licenseOk = true;
|
|
1249
|
-
break;
|
|
1250
|
-
}
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
if (!licenseOk) {
|
|
1254
|
-
warnings.push('commercial domain has no active license — install with: kdna install ' + domainName + ' --license <key>');
|
|
1255
|
-
}
|
|
1256
|
-
} else {
|
|
1257
|
-
warnings.push('no license store found — commercial domain may require a license');
|
|
1258
|
-
}
|
|
1259
|
-
} catch { /* license check unavailable */ }
|
|
1289
|
+
const licenseCheck = licenseDecryptOptionsForManifest({ ...manifest, name: domainName });
|
|
1290
|
+
if (!licenseCheck.ok) {
|
|
1291
|
+
warnings.push(
|
|
1292
|
+
'commercial domain has no active entitlement — run: kdna license activate ' +
|
|
1293
|
+
domainName +
|
|
1294
|
+
' --key <license-key> --server <url>'
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1260
1297
|
}
|
|
1261
1298
|
|
|
1262
1299
|
// 7. Human Lock check (judgment-class cards)
|
|
1263
|
-
const judgmentCardTypes = ['axiom', 'boundary', 'risk'];
|
|
1264
1300
|
const axioms = core.axioms || [];
|
|
1265
1301
|
const hasJudgmentCards = axioms.length > 0;
|
|
1266
1302
|
if (hasJudgmentCards) {
|