@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikdna/kdna-cli",
3
- "version": "0.16.6",
3
+ "version": "0.16.7",
4
4
  "description": "KDNA CLI — create, validate, install, and manage domain cognition packages for AI agents.",
5
5
  "type": "commonjs",
6
6
  "bin": {
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];
@@ -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) error(`Directory already exists: ${outDir}\nUse --force to overwrite.`, EXIT.INPUT_ERROR);
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: (pat?.terminology?.preferred_terms || pat?.terminology?.standard_terms || []).length,
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) console.log(` Evolution stages: ${(evo.stages || []).length}`);
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) console.log(` Intended use: ${kdnaCard.intended_use[0]}${kdnaCard.intended_use.length > 1 ? ` (+${kdnaCard.intended_use.length - 1} more)` : ''}`);
749
- if (kdnaCard.out_of_scope?.length) console.log(` Out of scope: ${kdnaCard.out_of_scope[0]}${kdnaCard.out_of_scope.length > 1 ? ` (+${kdnaCard.out_of_scope.length - 1} more)` : ''}`);
750
- if (kdnaCard.known_limitations?.length) console.log(` Limitations: ${kdnaCard.known_limitations[0]}${kdnaCard.known_limitations.length > 1 ? ` (+${kdnaCard.known_limitations.length - 1} more)` : ''}`);
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.readdirSync(abs).filter(f => f.endsWith('.json') && f !== 'kdna.json').length;
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)) error('License file not found', EXIT.INPUT_ERROR);
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('Use --license <license.json> or --key <secret> to provide encryption key', EXIT.INPUT_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(` Files: ${files.length} (${files.filter(isEncryptable).length} encrypted, ${files.filter(f => !isEncryptable(f)).length} plaintext)`);
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)) error('License file not found', EXIT.INPUT_ERROR);
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) error(`Directory already exists: ${outDir}\nUse --force to overwrite.`, EXIT.INPUT_ERROR);
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 { execSync(`unzip -q -o "${abs}" -d "${tmpDir}"`, { stdio: 'pipe' }); }
958
- catch { error('Cannot unpack .kdnae container'); }
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 { fs.unlinkSync(tmpPy); } catch { /* cleanup */ }
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 { fs.rmSync(tmpDir, { recursive: true, force: true }); } catch { /* cleanup */ }
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
  };