@aikdna/kdna-cli 0.16.6 → 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 +11 -0
- package/src/cmds/domain.js +130 -18
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
|
|
@@ -286,6 +289,14 @@ switch (cmd) {
|
|
|
286
289
|
cmdInspect(target, args.includes('--json'), locale);
|
|
287
290
|
break;
|
|
288
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
|
+
}
|
|
289
300
|
case 'verify': {
|
|
290
301
|
const { cmdVerify } = require('./verify');
|
|
291
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
|
};
|