@aikdna/kdna-cli 0.16.4 → 0.16.5
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/package.json +1 -1
- package/src/cli.js +38 -6
- package/src/cmds/registry.js +1 -1
- package/src/verify.js +133 -13
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -7,7 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const { error, EXIT, setQuiet, setExitCodeOnly } = require('./cmds/_common');
|
|
10
|
-
const {
|
|
10
|
+
const {
|
|
11
|
+
cmdValidate,
|
|
12
|
+
cmdPack,
|
|
13
|
+
cmdPackEncrypt,
|
|
14
|
+
cmdUnpack,
|
|
15
|
+
cmdUnpackEncrypt,
|
|
16
|
+
cmdInspect,
|
|
17
|
+
} = require('./cmds/domain');
|
|
11
18
|
const { cmdList, cmdRegistry } = require('./cmds/registry');
|
|
12
19
|
const {
|
|
13
20
|
cmdCompare,
|
|
@@ -24,12 +31,31 @@ const { cmdIdentity } = require('./cmds/identity');
|
|
|
24
31
|
const { cmdSetup } = require('./cmds/setup');
|
|
25
32
|
const { cmdDoctor } = require('./cmds/doctor');
|
|
26
33
|
const { cmdTrace, cmdHistory } = require('./cmds/trace');
|
|
27
|
-
const {
|
|
34
|
+
const {
|
|
35
|
+
cmdLicenseGenerate,
|
|
36
|
+
cmdLicenseVerify,
|
|
37
|
+
cmdLicenseBind,
|
|
38
|
+
cmdLicenseShow,
|
|
39
|
+
cmdLicenseInstall,
|
|
40
|
+
} = require('./cmds/license');
|
|
28
41
|
const { cmdPreview, cmdProject, cmdEval, cmdExport, cmdDemo } = require('./cmds/legacy');
|
|
29
|
-
const {
|
|
42
|
+
const {
|
|
43
|
+
cmdStudioScaffold,
|
|
44
|
+
cmdCardsValidate,
|
|
45
|
+
cmdLockVerify,
|
|
46
|
+
cmdStudioCompile,
|
|
47
|
+
cmdStudioReadiness,
|
|
48
|
+
} = require('./cmds/studio');
|
|
30
49
|
const { cmdTestRun, cmdTestImport } = require('./cmds/test');
|
|
31
50
|
const { cmdChangelog } = require('./cmds/changelog');
|
|
32
|
-
const {
|
|
51
|
+
const {
|
|
52
|
+
cmdProposalCreate,
|
|
53
|
+
cmdProposalValidate,
|
|
54
|
+
cmdReview,
|
|
55
|
+
cmdLockCard,
|
|
56
|
+
cmdEvolution,
|
|
57
|
+
cmdRegression,
|
|
58
|
+
} = require('./cmds/governance');
|
|
33
59
|
const { cmdBadgeCompute, cmdRegistryAudit, cmdPackage } = require('./cmds/badge');
|
|
34
60
|
|
|
35
61
|
// ─── Main ─────────────────────────────────────────────────────────────
|
|
@@ -81,6 +107,7 @@ Agent Runtime:
|
|
|
81
107
|
|
|
82
108
|
Testing & Verification:
|
|
83
109
|
verify <name> 3-layer: structure + trust + judgment
|
|
110
|
+
verify <name> --i18n I18N verification: locale dirs, overlays, card completeness
|
|
84
111
|
verify <name> --judgment --run-tests Judgment validation with eval cases
|
|
85
112
|
compare <name> --input "..." With/without KDNA reasoning diff
|
|
86
113
|
compare <name> --input "..." --report-md Markdown report format
|
|
@@ -332,7 +359,10 @@ switch (cmd) {
|
|
|
332
359
|
} else if (sub === 'validate') {
|
|
333
360
|
cmdProposalValidate(args);
|
|
334
361
|
} else {
|
|
335
|
-
error(
|
|
362
|
+
error(
|
|
363
|
+
'Usage: kdna proposal create --from-test <run.json> --domain <path>\n kdna proposal validate <proposal.json>',
|
|
364
|
+
EXIT.INPUT_ERROR,
|
|
365
|
+
);
|
|
336
366
|
}
|
|
337
367
|
break;
|
|
338
368
|
}
|
|
@@ -405,7 +435,9 @@ switch (cmd) {
|
|
|
405
435
|
break;
|
|
406
436
|
}
|
|
407
437
|
case 'list': {
|
|
408
|
-
|
|
438
|
+
const localeIdx = args.indexOf('--locale');
|
|
439
|
+
const locale = localeIdx >= 0 ? args[localeIdx + 1] : null;
|
|
440
|
+
cmdList(args.includes('--available'), args.includes('--json'), locale);
|
|
409
441
|
break;
|
|
410
442
|
}
|
|
411
443
|
case 'setup': {
|
package/src/cmds/registry.js
CHANGED
|
@@ -3,7 +3,7 @@ const path = require('path');
|
|
|
3
3
|
const { CANONICAL_REGISTRY_URL, REGISTRY_CACHE, fetchRegistry } = require('../registry');
|
|
4
4
|
const { error, readJson, loadRegistry, INSTALL_DIR, EXIT } = require('./_common');
|
|
5
5
|
|
|
6
|
-
function cmdList(showAvailable, jsonMode = false) {
|
|
6
|
+
function cmdList(showAvailable, jsonMode = false, locale = null) {
|
|
7
7
|
if (showAvailable) {
|
|
8
8
|
const domains = loadRegistry({ allowNetwork: true });
|
|
9
9
|
if (!domains || !domains.length) {
|
package/src/verify.js
CHANGED
|
@@ -240,10 +240,16 @@ function checkJudgment(destDir) {
|
|
|
240
240
|
} else if (hasScope || hasOutOfScope) {
|
|
241
241
|
score.max += 2;
|
|
242
242
|
score.total += 1;
|
|
243
|
-
issues.push({
|
|
243
|
+
issues.push({
|
|
244
|
+
severity: 'warn',
|
|
245
|
+
msg: 'partial: README boundary declaration incomplete (missing Scope or Out-of-Scope section)',
|
|
246
|
+
});
|
|
244
247
|
} else {
|
|
245
248
|
score.max += 2;
|
|
246
|
-
issues.push({
|
|
249
|
+
issues.push({
|
|
250
|
+
severity: 'error',
|
|
251
|
+
msg: 'README missing boundary declaration: require ## Scope + ## Out of Scope (or v2.1 Four Questions)',
|
|
252
|
+
});
|
|
247
253
|
}
|
|
248
254
|
|
|
249
255
|
// 2. v2.1 axiom governance fields
|
|
@@ -321,14 +327,20 @@ function checkJudgment(destDir) {
|
|
|
321
327
|
} else if (files.length > 0) {
|
|
322
328
|
score.max += 2;
|
|
323
329
|
score.total += 1;
|
|
324
|
-
issues.push({
|
|
330
|
+
issues.push({
|
|
331
|
+
severity: 'warn',
|
|
332
|
+
msg: `evals/ has only ${files.length} files (require ≥4: core/boundary/failure/excluded)`,
|
|
333
|
+
});
|
|
325
334
|
} else {
|
|
326
335
|
score.max += 2;
|
|
327
336
|
issues.push({ severity: 'error', msg: 'evals/ directory exists but contains no case files' });
|
|
328
337
|
}
|
|
329
338
|
} else {
|
|
330
339
|
score.max += 2;
|
|
331
|
-
issues.push({
|
|
340
|
+
issues.push({
|
|
341
|
+
severity: 'error',
|
|
342
|
+
msg: 'evals/ directory missing: require ≥4 evaluation cases',
|
|
343
|
+
});
|
|
332
344
|
}
|
|
333
345
|
|
|
334
346
|
// 6. judgment_version manifest field (REQUIRED)
|
|
@@ -367,6 +379,94 @@ function renderLayer(result) {
|
|
|
367
379
|
}
|
|
368
380
|
}
|
|
369
381
|
|
|
382
|
+
// ─── I18N layer ──────────────────────────────────────────────────────
|
|
383
|
+
|
|
384
|
+
function checkI18n(destDir) {
|
|
385
|
+
const issues = [];
|
|
386
|
+
const passed = [];
|
|
387
|
+
const manifest = readJson(path.join(destDir, 'kdna.json')) || {};
|
|
388
|
+
const languages = manifest.languages || [];
|
|
389
|
+
const i18nLevel = manifest.i18n_level || 'L0';
|
|
390
|
+
|
|
391
|
+
if (languages.length === 0) {
|
|
392
|
+
passed.push('i18n: no languages declared (L0 — monolingual)');
|
|
393
|
+
return { layer: 'i18n', passed: true, issues, results: passed };
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
passed.push(`languages declared: ${languages.join(', ')}`);
|
|
397
|
+
passed.push(`i18n level: ${i18nLevel}`);
|
|
398
|
+
|
|
399
|
+
const canonical = manifest.default_language || languages[0] || 'en';
|
|
400
|
+
for (const lang of languages) {
|
|
401
|
+
if (lang === canonical) continue;
|
|
402
|
+
const localeDir = path.join(destDir, 'locales', lang);
|
|
403
|
+
|
|
404
|
+
// L1: card + readme
|
|
405
|
+
if (['L1', 'L2', 'L3', 'L4'].includes(i18nLevel)) {
|
|
406
|
+
if (!fs.existsSync(path.join(localeDir, 'KDNA_CARD.json'))) {
|
|
407
|
+
issues.push({ severity: 'error', msg: `i18n: ${lang} KDNA_CARD.json missing` });
|
|
408
|
+
} else {
|
|
409
|
+
const card = readJson(path.join(localeDir, 'KDNA_CARD.json'));
|
|
410
|
+
if (card) {
|
|
411
|
+
passed.push(`locales/${lang}/KDNA_CARD.json OK`);
|
|
412
|
+
if (!card.display_name)
|
|
413
|
+
issues.push({ severity: 'warn', msg: `i18n: ${lang} card missing display_name` });
|
|
414
|
+
if (!card.intended_use?.length)
|
|
415
|
+
issues.push({ severity: 'warn', msg: `i18n: ${lang} card missing intended_use` });
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
if (!fs.existsSync(path.join(localeDir, 'README.md'))) {
|
|
419
|
+
issues.push({ severity: 'warn', msg: `i18n: ${lang} README.md missing` });
|
|
420
|
+
} else {
|
|
421
|
+
passed.push(`locales/${lang}/README.md OK`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// L2: overlay files
|
|
426
|
+
if (['L2', 'L3', 'L4'].includes(i18nLevel)) {
|
|
427
|
+
const coreOverlay = path.join(localeDir, 'KDNA_Core.overlay.json');
|
|
428
|
+
if (!fs.existsSync(coreOverlay)) {
|
|
429
|
+
issues.push({ severity: 'error', msg: `i18n: ${lang} KDNA_Core.overlay.json missing` });
|
|
430
|
+
} else {
|
|
431
|
+
const overlay = readJson(coreOverlay);
|
|
432
|
+
if (overlay?.translations) {
|
|
433
|
+
const core = readJson(path.join(destDir, 'KDNA_Core.json'));
|
|
434
|
+
if (core?.axioms) {
|
|
435
|
+
const validIds = new Set(core.axioms.map((a) => a.id));
|
|
436
|
+
for (const key of Object.keys(overlay.translations)) {
|
|
437
|
+
const refId = key.split('.')[0];
|
|
438
|
+
if (!validIds.has(refId)) {
|
|
439
|
+
issues.push({
|
|
440
|
+
severity: 'error',
|
|
441
|
+
msg: `i18n: overlay refs unknown axiom: ${refId}`,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
passed.push(
|
|
447
|
+
`locales/${lang}/KDNA_Core.overlay.json OK (${Object.keys(overlay.translations).length} translations)`,
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (!fs.existsSync(path.join(localeDir, 'KDNA_Patterns.overlay.json'))) {
|
|
452
|
+
issues.push({ severity: 'warn', msg: `i18n: ${lang} KDNA_Patterns.overlay.json missing` });
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (manifest.languages?.length && !manifest.i18n_level) {
|
|
458
|
+
issues.push({ severity: 'warn', msg: 'i18n: languages declared but i18n_level not set' });
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
return {
|
|
462
|
+
layer: 'i18n',
|
|
463
|
+
passed: issues.filter((i) => i.severity === 'error').length === 0,
|
|
464
|
+
issues,
|
|
465
|
+
results: passed.concat(issues.map((i) => i.msg)),
|
|
466
|
+
score: { total: passed.length, max: passed.length + issues.length },
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
|
|
370
470
|
// ─── Main ──────────────────────────────────────────────────────────────
|
|
371
471
|
|
|
372
472
|
function cmdVerify(input, args = []) {
|
|
@@ -376,15 +476,22 @@ function cmdVerify(input, args = []) {
|
|
|
376
476
|
structure: args.includes('--structure'),
|
|
377
477
|
trust: args.includes('--trust'),
|
|
378
478
|
judgment: args.includes('--judgment'),
|
|
479
|
+
i18n: args.includes('--i18n'),
|
|
379
480
|
};
|
|
380
|
-
const all = !want.structure && !want.trust && !want.judgment;
|
|
481
|
+
const all = !want.structure && !want.trust && !want.judgment && !want.i18n;
|
|
381
482
|
if (all) want.structure = want.trust = want.judgment = true;
|
|
382
483
|
|
|
383
484
|
// Resolve name → installed path + scope/entry
|
|
384
485
|
const parsed = parseName(input);
|
|
385
486
|
if (!parsed) {
|
|
386
487
|
if (jsonMode) {
|
|
387
|
-
console.log(
|
|
488
|
+
console.log(
|
|
489
|
+
JSON.stringify({
|
|
490
|
+
name: input,
|
|
491
|
+
ok: false,
|
|
492
|
+
error: `Invalid name "${input}". Use @scope/name or bare name.`,
|
|
493
|
+
}),
|
|
494
|
+
);
|
|
388
495
|
} else {
|
|
389
496
|
console.error(`Invalid name "${input}". Use @scope/name or bare name.`);
|
|
390
497
|
}
|
|
@@ -394,7 +501,13 @@ function cmdVerify(input, args = []) {
|
|
|
394
501
|
const destDir = path.join(INSTALL_DIR, parsed.scope, parsed.ident);
|
|
395
502
|
if (!fs.existsSync(destDir)) {
|
|
396
503
|
if (jsonMode) {
|
|
397
|
-
console.log(
|
|
504
|
+
console.log(
|
|
505
|
+
JSON.stringify({
|
|
506
|
+
name: parsed.full,
|
|
507
|
+
ok: false,
|
|
508
|
+
error: `${parsed.full} is not installed. Run: kdna install ${input}`,
|
|
509
|
+
}),
|
|
510
|
+
);
|
|
398
511
|
} else {
|
|
399
512
|
console.error(`${parsed.full} is not installed. Run: kdna install ${input}`);
|
|
400
513
|
}
|
|
@@ -418,6 +531,7 @@ function cmdVerify(input, args = []) {
|
|
|
418
531
|
if (want.structure) results.push(checkStructure(destDir));
|
|
419
532
|
if (want.trust) results.push(checkTrust(destDir, scope, entry));
|
|
420
533
|
if (want.judgment) results.push(checkJudgment(destDir));
|
|
534
|
+
if (want.i18n) results.push(checkI18n(destDir));
|
|
421
535
|
|
|
422
536
|
// ── JSON output ──────────────────────────────────────────────────────
|
|
423
537
|
if (jsonMode) {
|
|
@@ -444,12 +558,18 @@ function cmdVerify(input, args = []) {
|
|
|
444
558
|
exitCode = EXIT.JUDGMENT_QUALITY_FAILED;
|
|
445
559
|
}
|
|
446
560
|
|
|
447
|
-
console.log(
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
561
|
+
console.log(
|
|
562
|
+
JSON.stringify(
|
|
563
|
+
{
|
|
564
|
+
name: parsed.full,
|
|
565
|
+
path: destDir,
|
|
566
|
+
layers,
|
|
567
|
+
ok: exitCode === EXIT.OK,
|
|
568
|
+
},
|
|
569
|
+
null,
|
|
570
|
+
2,
|
|
571
|
+
),
|
|
572
|
+
);
|
|
453
573
|
process.exit(exitCode);
|
|
454
574
|
}
|
|
455
575
|
|