@aikdna/kdna-cli 0.16.5 → 0.16.7
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 +13 -1
- package/src/cmds/domain.js +130 -18
- package/src/verify.js +86 -1
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -14,6 +14,7 @@ const {
|
|
|
14
14
|
cmdUnpack,
|
|
15
15
|
cmdUnpackEncrypt,
|
|
16
16
|
cmdInspect,
|
|
17
|
+
cmdCard,
|
|
17
18
|
} = require('./cmds/domain');
|
|
18
19
|
const { cmdList, cmdRegistry } = require('./cmds/registry');
|
|
19
20
|
const {
|
|
@@ -85,6 +86,8 @@ Domain Authoring:
|
|
|
85
86
|
unpack <file> Unpack .kdna container
|
|
86
87
|
unpack <file> --license <file> Unpack encrypted .kdnae container
|
|
87
88
|
inspect <path> Inspect domain or .kdna file
|
|
89
|
+
inspect <path> --locale zh-CN Inspect with localized governance data
|
|
90
|
+
card <path> [--locale zh-CN] Display KDNA Card (governance metadata)
|
|
88
91
|
publish <path> Pack + sign + publish
|
|
89
92
|
publish --check <path> Quality gate check only
|
|
90
93
|
version bump <level> [path] Bump domain version
|
|
@@ -107,7 +110,8 @@ Agent Runtime:
|
|
|
107
110
|
|
|
108
111
|
Testing & Verification:
|
|
109
112
|
verify <name> 3-layer: structure + trust + judgment
|
|
110
|
-
verify <name> --i18n I18N verification:
|
|
113
|
+
verify <name> --i18n I18N verification: locales, overlays, card completeness
|
|
114
|
+
verify <name> --governance Governance verification: risk_level, KDNA_CARD, provenance
|
|
111
115
|
verify <name> --judgment --run-tests Judgment validation with eval cases
|
|
112
116
|
compare <name> --input "..." With/without KDNA reasoning diff
|
|
113
117
|
compare <name> --input "..." --report-md Markdown report format
|
|
@@ -285,6 +289,14 @@ switch (cmd) {
|
|
|
285
289
|
cmdInspect(target, args.includes('--json'), locale);
|
|
286
290
|
break;
|
|
287
291
|
}
|
|
292
|
+
case 'card': {
|
|
293
|
+
const target = args.filter((a) => !a.startsWith('--'))[1];
|
|
294
|
+
if (!target) error('Usage: kdna card <path> [--json] [--locale zh-CN]');
|
|
295
|
+
const localeIdx = args.indexOf('--locale');
|
|
296
|
+
const locale = localeIdx >= 0 ? args[localeIdx + 1] : null;
|
|
297
|
+
cmdCard(target, locale);
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
288
300
|
case 'verify': {
|
|
289
301
|
const { cmdVerify } = require('./verify');
|
|
290
302
|
const target = args.filter((a) => !a.startsWith('--'))[1];
|
package/src/cmds/domain.js
CHANGED
|
@@ -333,7 +333,8 @@ function cmdUnpack(filePath, force) {
|
|
|
333
333
|
const outDir = path.join(path.dirname(abs), domainName);
|
|
334
334
|
|
|
335
335
|
if (fs.existsSync(outDir)) {
|
|
336
|
-
if (!force)
|
|
336
|
+
if (!force)
|
|
337
|
+
error(`Directory already exists: ${outDir}\nUse --force to overwrite.`, EXIT.INPUT_ERROR);
|
|
337
338
|
fs.rmSync(outDir, { recursive: true, force: true });
|
|
338
339
|
}
|
|
339
340
|
|
|
@@ -645,7 +646,11 @@ function cmdInspect(dir, jsonMode = false, locale = null) {
|
|
|
645
646
|
frameworks: (c.frameworks || []).length,
|
|
646
647
|
core_structures: (c.core_structure || []).length,
|
|
647
648
|
stances: (c.stances || []).length,
|
|
648
|
-
preferred_terms: (
|
|
649
|
+
preferred_terms: (
|
|
650
|
+
pat?.terminology?.preferred_terms ||
|
|
651
|
+
pat?.terminology?.standard_terms ||
|
|
652
|
+
[]
|
|
653
|
+
).length,
|
|
649
654
|
banned_terms: (pat?.terminology?.banned_terms || []).length,
|
|
650
655
|
misunderstandings: (pat?.misunderstandings || []).length,
|
|
651
656
|
self_checks: (pat?.self_check || []).length,
|
|
@@ -725,7 +730,7 @@ function cmdInspect(dir, jsonMode = false, locale = null) {
|
|
|
725
730
|
|
|
726
731
|
if (rea) console.log(` Reasoning chains: ${(rea.reasoning_chains || []).length}`);
|
|
727
732
|
|
|
728
|
-
if (evo)
|
|
733
|
+
if (evo) console.log(` Evolution stages: ${(evo.stages || []).length}`);
|
|
729
734
|
|
|
730
735
|
// Governance metadata (with locale support)
|
|
731
736
|
let kdnaCard = readJson(path.join(abs, 'KDNA_CARD.json'));
|
|
@@ -745,9 +750,18 @@ function cmdInspect(dir, jsonMode = false, locale = null) {
|
|
|
745
750
|
if (summary && locale) console.log(` Summary: ${summary}`);
|
|
746
751
|
console.log(` Risk level: ${kdnaCard.risk_level || '?'}`);
|
|
747
752
|
console.log(` Review status: ${kdnaCard.review_status || '?'}`);
|
|
748
|
-
if (kdnaCard.intended_use?.length)
|
|
749
|
-
|
|
750
|
-
|
|
753
|
+
if (kdnaCard.intended_use?.length)
|
|
754
|
+
console.log(
|
|
755
|
+
` Intended use: ${kdnaCard.intended_use[0]}${kdnaCard.intended_use.length > 1 ? ` (+${kdnaCard.intended_use.length - 1} more)` : ''}`,
|
|
756
|
+
);
|
|
757
|
+
if (kdnaCard.out_of_scope?.length)
|
|
758
|
+
console.log(
|
|
759
|
+
` Out of scope: ${kdnaCard.out_of_scope[0]}${kdnaCard.out_of_scope.length > 1 ? ` (+${kdnaCard.out_of_scope.length - 1} more)` : ''}`,
|
|
760
|
+
);
|
|
761
|
+
if (kdnaCard.known_limitations?.length)
|
|
762
|
+
console.log(
|
|
763
|
+
` Limitations: ${kdnaCard.known_limitations[0]}${kdnaCard.known_limitations.length > 1 ? ` (+${kdnaCard.known_limitations.length - 1} more)` : ''}`,
|
|
764
|
+
);
|
|
751
765
|
if (kdnaCard.requires_expert_review) console.log(` ⚠ Expert review required`);
|
|
752
766
|
}
|
|
753
767
|
|
|
@@ -778,7 +792,9 @@ function cmdPackEncrypt(dir, args = []) {
|
|
|
778
792
|
|
|
779
793
|
let manifest = readJson(path.join(abs, 'kdna.json'));
|
|
780
794
|
if (!manifest) {
|
|
781
|
-
const jsonCount = fs
|
|
795
|
+
const jsonCount = fs
|
|
796
|
+
.readdirSync(abs)
|
|
797
|
+
.filter((f) => f.endsWith('.json') && f !== 'kdna.json').length;
|
|
782
798
|
manifest = {
|
|
783
799
|
kdna_spec: '1.0-rc',
|
|
784
800
|
name: domainName,
|
|
@@ -803,7 +819,8 @@ function cmdPackEncrypt(dir, args = []) {
|
|
|
803
819
|
|
|
804
820
|
if (licenseIdx >= 0) {
|
|
805
821
|
const licensePath = args[licenseIdx + 1];
|
|
806
|
-
if (!licensePath || !fs.existsSync(licensePath))
|
|
822
|
+
if (!licensePath || !fs.existsSync(licensePath))
|
|
823
|
+
error('License file not found', EXIT.INPUT_ERROR);
|
|
807
824
|
const license = JSON.parse(fs.readFileSync(licensePath, 'utf8'));
|
|
808
825
|
const licenseKey = license.license_id;
|
|
809
826
|
const fp = machineFingerprint();
|
|
@@ -813,7 +830,10 @@ function cmdPackEncrypt(dir, args = []) {
|
|
|
813
830
|
if (!rawKey) error('--key requires a value', EXIT.INPUT_ERROR);
|
|
814
831
|
encKey = deriveKey(rawKey, machineFingerprint());
|
|
815
832
|
} else {
|
|
816
|
-
error(
|
|
833
|
+
error(
|
|
834
|
+
'Use --license <license.json> or --key <secret> to provide encryption key',
|
|
835
|
+
EXIT.INPUT_ERROR,
|
|
836
|
+
);
|
|
817
837
|
}
|
|
818
838
|
|
|
819
839
|
const outputDir = args.includes('--output') ? args[args.indexOf('--output') + 1] : null;
|
|
@@ -823,7 +843,7 @@ function cmdPackEncrypt(dir, args = []) {
|
|
|
823
843
|
|
|
824
844
|
// Build encrypted ZIP
|
|
825
845
|
const zlib = require('zlib');
|
|
826
|
-
const files = fs.readdirSync(abs).filter(f => {
|
|
846
|
+
const files = fs.readdirSync(abs).filter((f) => {
|
|
827
847
|
if (f.startsWith('.')) return false;
|
|
828
848
|
const ext = path.extname(f);
|
|
829
849
|
return ext === '.json' || f === 'README.md' || f === 'LICENSE' || f === 'kdna.json';
|
|
@@ -897,7 +917,9 @@ function cmdPackEncrypt(dir, args = []) {
|
|
|
897
917
|
|
|
898
918
|
console.log(`✓ Encrypted pack: ${outPath}`);
|
|
899
919
|
console.log(` Domain: ${domainName} v${manifest.version}`);
|
|
900
|
-
console.log(
|
|
920
|
+
console.log(
|
|
921
|
+
` Files: ${files.length} (${files.filter(isEncryptable).length} encrypted, ${files.filter((f) => !isEncryptable(f)).length} plaintext)`,
|
|
922
|
+
);
|
|
901
923
|
console.log(` Container: AES-256-GCM .kdnae`);
|
|
902
924
|
}
|
|
903
925
|
|
|
@@ -916,7 +938,8 @@ function cmdUnpackEncrypt(filePath, args = []) {
|
|
|
916
938
|
|
|
917
939
|
if (licenseIdx >= 0) {
|
|
918
940
|
const licensePath = args[licenseIdx + 1];
|
|
919
|
-
if (!licensePath || !fs.existsSync(licensePath))
|
|
941
|
+
if (!licensePath || !fs.existsSync(licensePath))
|
|
942
|
+
error('License file not found', EXIT.INPUT_ERROR);
|
|
920
943
|
const license = JSON.parse(fs.readFileSync(licensePath, 'utf8'));
|
|
921
944
|
const licenseKey = license.license_id;
|
|
922
945
|
const fp = machineFingerprint();
|
|
@@ -934,7 +957,8 @@ function cmdUnpackEncrypt(filePath, args = []) {
|
|
|
934
957
|
const force = args.includes('--force');
|
|
935
958
|
|
|
936
959
|
if (fs.existsSync(outDir)) {
|
|
937
|
-
if (!force)
|
|
960
|
+
if (!force)
|
|
961
|
+
error(`Directory already exists: ${outDir}\nUse --force to overwrite.`, EXIT.INPUT_ERROR);
|
|
938
962
|
fs.rmSync(outDir, { recursive: true, force: true });
|
|
939
963
|
}
|
|
940
964
|
fs.mkdirSync(outDir, { recursive: true });
|
|
@@ -954,10 +978,17 @@ zf.close()
|
|
|
954
978
|
fs.writeFileSync(tmpPy, script);
|
|
955
979
|
execSync(`python3 ${tmpPy}`, { stdio: 'pipe' });
|
|
956
980
|
} catch {
|
|
957
|
-
try {
|
|
958
|
-
|
|
981
|
+
try {
|
|
982
|
+
execSync(`unzip -q -o "${abs}" -d "${tmpDir}"`, { stdio: 'pipe' });
|
|
983
|
+
} catch {
|
|
984
|
+
error('Cannot unpack .kdnae container');
|
|
985
|
+
}
|
|
959
986
|
} finally {
|
|
960
|
-
try {
|
|
987
|
+
try {
|
|
988
|
+
fs.unlinkSync(tmpPy);
|
|
989
|
+
} catch {
|
|
990
|
+
/* cleanup */
|
|
991
|
+
}
|
|
961
992
|
}
|
|
962
993
|
|
|
963
994
|
// Copy plaintext files, decrypt KDNA files
|
|
@@ -979,13 +1010,93 @@ zf.close()
|
|
|
979
1010
|
}
|
|
980
1011
|
}
|
|
981
1012
|
} finally {
|
|
982
|
-
try {
|
|
1013
|
+
try {
|
|
1014
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
1015
|
+
} catch {
|
|
1016
|
+
/* cleanup */
|
|
1017
|
+
}
|
|
983
1018
|
}
|
|
984
1019
|
|
|
985
1020
|
console.log(`✓ Decrypted: ${outDir}`);
|
|
986
1021
|
const files = fs.readdirSync(outDir);
|
|
987
1022
|
console.log(` Files: ${files.length}`);
|
|
988
|
-
files.forEach(f => console.log(` ${f}`));
|
|
1023
|
+
files.forEach((f) => console.log(` ${f}`));
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
// ─── KDNA Card (locale-aware) ────────────────────────────────────
|
|
1027
|
+
|
|
1028
|
+
function cmdCard(dir, locale = null) {
|
|
1029
|
+
const abs = path.resolve(dir);
|
|
1030
|
+
let card = readJson(path.join(abs, 'KDNA_CARD.json'));
|
|
1031
|
+
|
|
1032
|
+
if (locale) {
|
|
1033
|
+
const localeCard = readJson(path.join(abs, 'locales', locale, 'KDNA_CARD.json'));
|
|
1034
|
+
if (localeCard) {
|
|
1035
|
+
card = { ...card, ...localeCard };
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
if (!card) {
|
|
1040
|
+
error(
|
|
1041
|
+
`No KDNA_CARD.json found in ${abs}${locale ? ` or locales/${locale}/` : ''}`,
|
|
1042
|
+
EXIT.INPUT_ERROR,
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
const jsonMode = process.argv.includes('--json');
|
|
1047
|
+
|
|
1048
|
+
if (jsonMode) {
|
|
1049
|
+
console.log(JSON.stringify(card, null, 2));
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
console.log('═'.repeat(60));
|
|
1054
|
+
console.log(` KDNA Card${locale ? ` (${locale})` : ''}`);
|
|
1055
|
+
console.log('═'.repeat(60));
|
|
1056
|
+
console.log('');
|
|
1057
|
+
if (card.display_name) console.log(` Display name: ${card.display_name}`);
|
|
1058
|
+
console.log(` Domain: ${card.name || '?'}`);
|
|
1059
|
+
console.log(` Version: ${card.version || '?'}`);
|
|
1060
|
+
console.log(` Risk level: ${card.risk_level || '?'}`);
|
|
1061
|
+
console.log(` Quality: ${card.quality_badge || '?'}`);
|
|
1062
|
+
console.log(` Review: ${card.review_status || '?'}`);
|
|
1063
|
+
console.log(` License: ${card.license || '?'}`);
|
|
1064
|
+
if (card.summary) console.log(` Summary: ${card.summary}`);
|
|
1065
|
+
console.log('');
|
|
1066
|
+
if (card.intended_use?.length) {
|
|
1067
|
+
console.log(' ── Intended Use ──');
|
|
1068
|
+
card.intended_use.forEach((u) => console.log(` ✓ ${u}`));
|
|
1069
|
+
console.log('');
|
|
1070
|
+
}
|
|
1071
|
+
if (card.out_of_scope?.length) {
|
|
1072
|
+
console.log(' ── Out of Scope ──');
|
|
1073
|
+
card.out_of_scope.forEach((o) => console.log(` ✗ ${o}`));
|
|
1074
|
+
console.log('');
|
|
1075
|
+
}
|
|
1076
|
+
if (card.known_limitations?.length) {
|
|
1077
|
+
console.log(' ── Known Limitations ──');
|
|
1078
|
+
card.known_limitations.forEach((l) => console.log(` ⚠ ${l}`));
|
|
1079
|
+
console.log('');
|
|
1080
|
+
}
|
|
1081
|
+
if (card.risk_warnings?.length) {
|
|
1082
|
+
console.log(' ── Risk Warnings ──');
|
|
1083
|
+
card.risk_warnings.forEach((w) => console.log(` ⚡ ${w}`));
|
|
1084
|
+
console.log('');
|
|
1085
|
+
}
|
|
1086
|
+
if (card.author_responsibility) {
|
|
1087
|
+
console.log(` Author: ${card.author_responsibility}`);
|
|
1088
|
+
console.log('');
|
|
1089
|
+
}
|
|
1090
|
+
if (card.provenance) {
|
|
1091
|
+
console.log(' ── Provenance ──');
|
|
1092
|
+
console.log(` Studio: ${card.provenance.studio_core || '?'}`);
|
|
1093
|
+
console.log(` Version: ${card.provenance.studio_core_version || '?'}`);
|
|
1094
|
+
console.log(` Built: ${card.provenance.built_at || '?'}`);
|
|
1095
|
+
if (card.provenance.content_fingerprint)
|
|
1096
|
+
console.log(` Fingerprint: ${card.provenance.content_fingerprint}`);
|
|
1097
|
+
console.log('');
|
|
1098
|
+
}
|
|
1099
|
+
console.log('═'.repeat(60));
|
|
989
1100
|
}
|
|
990
1101
|
|
|
991
1102
|
module.exports = {
|
|
@@ -995,4 +1106,5 @@ module.exports = {
|
|
|
995
1106
|
cmdUnpack,
|
|
996
1107
|
cmdUnpackEncrypt,
|
|
997
1108
|
cmdInspect,
|
|
1109
|
+
cmdCard,
|
|
998
1110
|
};
|
package/src/verify.js
CHANGED
|
@@ -467,6 +467,87 @@ function checkI18n(destDir) {
|
|
|
467
467
|
};
|
|
468
468
|
}
|
|
469
469
|
|
|
470
|
+
// ─── Governance layer ───────────────────────────────────────────────
|
|
471
|
+
|
|
472
|
+
function checkGovernance(destDir) {
|
|
473
|
+
const issues = [];
|
|
474
|
+
const passed = [];
|
|
475
|
+
const card = readJson(path.join(destDir, 'KDNA_CARD.json')) || {};
|
|
476
|
+
|
|
477
|
+
if (!readJson(path.join(destDir, 'KDNA_CARD.json'))) {
|
|
478
|
+
issues.push({ severity: 'error', msg: 'governance: KDNA_CARD.json missing — required' });
|
|
479
|
+
return { layer: 'governance', passed: false, issues, results: issues.map((i) => i.msg) };
|
|
480
|
+
}
|
|
481
|
+
passed.push('KDNA_CARD.json present');
|
|
482
|
+
|
|
483
|
+
if (!card.risk_level) {
|
|
484
|
+
issues.push({ severity: 'error', msg: 'governance: risk_level not declared (R0/R1/R2/R3)' });
|
|
485
|
+
} else if (!['R0', 'R1', 'R2', 'R3'].includes(card.risk_level)) {
|
|
486
|
+
issues.push({ severity: 'error', msg: `governance: invalid risk_level "${card.risk_level}"` });
|
|
487
|
+
} else {
|
|
488
|
+
passed.push(`risk_level: ${card.risk_level}`);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
if (!card.intended_use?.length) {
|
|
492
|
+
issues.push({ severity: 'error', msg: 'governance: intended_use empty' });
|
|
493
|
+
} else {
|
|
494
|
+
passed.push(`intended_use: ${card.intended_use.length} entries`);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
if (!card.out_of_scope?.length) {
|
|
498
|
+
issues.push({ severity: 'error', msg: 'governance: out_of_scope empty' });
|
|
499
|
+
} else {
|
|
500
|
+
passed.push(`out_of_scope: ${card.out_of_scope.length} entries`);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (!card.known_limitations?.length) {
|
|
504
|
+
issues.push({ severity: 'warn', msg: 'governance: known_limitations empty' });
|
|
505
|
+
} else {
|
|
506
|
+
passed.push(`known_limitations: ${card.known_limitations.length} entries`);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (['R1', 'R2', 'R3'].includes(card.risk_level) && !card.author_responsibility) {
|
|
510
|
+
issues.push({
|
|
511
|
+
severity: 'warn',
|
|
512
|
+
msg: `governance: risk ${card.risk_level} should declare author_responsibility`,
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (['R2', 'R3'].includes(card.risk_level)) {
|
|
517
|
+
if (!card.reviewed_by && !card.requires_expert_review) {
|
|
518
|
+
issues.push({
|
|
519
|
+
severity: 'error',
|
|
520
|
+
msg: `governance: risk ${card.risk_level} requires expert_review`,
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
if (!card.risk_warnings?.length) {
|
|
524
|
+
issues.push({
|
|
525
|
+
severity: 'error',
|
|
526
|
+
msg: `governance: risk ${card.risk_level} requires risk_warnings`,
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (!card.human_lock_summary)
|
|
532
|
+
issues.push({ severity: 'warn', msg: 'governance: human_lock_summary missing' });
|
|
533
|
+
else passed.push('human_lock_summary present');
|
|
534
|
+
|
|
535
|
+
if (!card.provenance) issues.push({ severity: 'warn', msg: 'governance: provenance missing' });
|
|
536
|
+
else passed.push('provenance present');
|
|
537
|
+
|
|
538
|
+
if (!card.quality_badge)
|
|
539
|
+
issues.push({ severity: 'warn', msg: 'governance: quality_badge missing' });
|
|
540
|
+
else passed.push(`quality_badge: ${card.quality_badge}`);
|
|
541
|
+
|
|
542
|
+
return {
|
|
543
|
+
layer: 'governance',
|
|
544
|
+
passed: issues.filter((i) => i.severity === 'error').length === 0,
|
|
545
|
+
issues,
|
|
546
|
+
results: passed.concat(issues.map((i) => i.msg)),
|
|
547
|
+
score: { total: passed.length, max: passed.length + issues.length },
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
|
|
470
551
|
// ─── Main ──────────────────────────────────────────────────────────────
|
|
471
552
|
|
|
472
553
|
function cmdVerify(input, args = []) {
|
|
@@ -477,8 +558,9 @@ function cmdVerify(input, args = []) {
|
|
|
477
558
|
trust: args.includes('--trust'),
|
|
478
559
|
judgment: args.includes('--judgment'),
|
|
479
560
|
i18n: args.includes('--i18n'),
|
|
561
|
+
governance: args.includes('--governance'),
|
|
480
562
|
};
|
|
481
|
-
const all = !want.structure && !want.trust && !want.judgment && !want.i18n;
|
|
563
|
+
const all = !want.structure && !want.trust && !want.judgment && !want.i18n && !want.governance;
|
|
482
564
|
if (all) want.structure = want.trust = want.judgment = true;
|
|
483
565
|
|
|
484
566
|
// Resolve name → installed path + scope/entry
|
|
@@ -532,6 +614,7 @@ function cmdVerify(input, args = []) {
|
|
|
532
614
|
if (want.trust) results.push(checkTrust(destDir, scope, entry));
|
|
533
615
|
if (want.judgment) results.push(checkJudgment(destDir));
|
|
534
616
|
if (want.i18n) results.push(checkI18n(destDir));
|
|
617
|
+
if (want.governance) results.push(checkGovernance(destDir));
|
|
535
618
|
|
|
536
619
|
// ── JSON output ──────────────────────────────────────────────────────
|
|
537
620
|
if (jsonMode) {
|
|
@@ -548,6 +631,8 @@ function cmdVerify(input, args = []) {
|
|
|
548
631
|
const structureResult = results.find((r) => r.layer === 'structure');
|
|
549
632
|
const trustResult = results.find((r) => r.layer === 'trust');
|
|
550
633
|
const judgmentResult = results.find((r) => r.layer === 'judgment');
|
|
634
|
+
const i18nResult = results.find((r) => r.layer === 'i18n');
|
|
635
|
+
const governanceResult = results.find((r) => r.layer === 'governance');
|
|
551
636
|
|
|
552
637
|
let exitCode = EXIT.OK;
|
|
553
638
|
if (structureResult && structureResult.issues.some((i) => i.severity === 'error')) {
|