@aikdna/kdna-cli 0.20.3 → 0.21.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikdna/kdna-cli",
3
- "version": "0.20.3",
3
+ "version": "0.21.0",
4
4
  "description": "KDNA CLI — runtime control plane for verifying, installing, loading, comparing, publishing, and auditing existing .kdna assets.",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -493,7 +493,11 @@ function inspectKdnaFile(filePath, jsonMode = false) {
493
493
  const isZip = head[0] === 0x50 && head[1] === 0x4b;
494
494
  if (!isZip) error('Invalid .kdna asset: expected ZIP container');
495
495
 
496
- const { listContainerEntries, readContainerJson } = require('../package-store');
496
+ const {
497
+ listContainerEntries,
498
+ readContainerJson,
499
+ readContainerDataMap,
500
+ } = require('../package-store');
497
501
  const { licenseDecryptOptionsForManifest } = require('./license');
498
502
  const presentFiles = listContainerEntries(abs).filter(
499
503
  (f) => (f.startsWith('KDNA_') && f.endsWith('.json')) || f === 'README.md' || f === 'LICENSE',
@@ -513,8 +517,20 @@ function inspectKdnaFile(filePath, jsonMode = false) {
513
517
  let core = null;
514
518
  let patterns = null;
515
519
  try {
516
- core = decryptError ? null : readContainerJson(abs, 'KDNA_Core.json', decryptOptions);
517
- patterns = decryptError ? null : readContainerJson(abs, 'KDNA_Patterns.json', decryptOptions);
520
+ if (decryptError) {
521
+ /* skip */
522
+ }
523
+ // v2 container: use readDataMap
524
+ else if (listContainerEntries(abs).includes('payload.kdnab')) {
525
+ const dm = readContainerDataMap(abs, decryptOptions);
526
+ core = dm['KDNA_Core.json'] || null;
527
+ patterns = dm['KDNA_Patterns.json'] || null;
528
+ }
529
+ // v1 container: read individual files
530
+ else {
531
+ core = readContainerJson(abs, 'KDNA_Core.json', decryptOptions);
532
+ patterns = readContainerJson(abs, 'KDNA_Patterns.json', decryptOptions);
533
+ }
518
534
  } catch (e) {
519
535
  if (!encryptedEntries.length) error(`Cannot inspect .kdna asset: ${e.message}`);
520
536
  decryptError = e.message;
@@ -11,25 +11,6 @@ if (typeof core.createKdnaAssetReader !== 'function') {
11
11
 
12
12
  const assetReader = core.createKdnaAssetReader();
13
13
 
14
- const V1_ENTRIES = [
15
- 'KDNA_Core.json',
16
- 'KDNA_Patterns.json',
17
- 'KDNA_Scenarios.json',
18
- 'KDNA_Cases.json',
19
- 'KDNA_Reasoning.json',
20
- 'KDNA_Evolution.json',
21
- ];
22
-
23
- function validateContainerV2(asset, assetPath) {
24
- const hasPayload = asset.entries.has('payload.kdnab');
25
- if (hasPayload) return; // v2, OK
26
- const hasV1 = V1_ENTRIES.some((e) => asset.entries.has(e));
27
- if (!hasV1) return; // neither v1 nor v2, probably empty — let caller decide
28
- const found = V1_ENTRIES.filter((e) => asset.entries.has(e));
29
- const msg = `ERR_LEGACY_PLAINTEXT_CONTAINER: This .kdna uses the removed v1 plaintext ZIP format (found: ${found.join(', ')}). Rebuild from source with KDNA Container v2.`;
30
- throw Object.assign(new Error(msg), { code: 'ERR_LEGACY_PLAINTEXT_CONTAINER' });
31
- }
32
-
33
14
  const INDEX_VERSION = 2;
34
15
 
35
16
  function ensureDir(dir) {
@@ -87,33 +68,9 @@ function readContainerJson(kdnaPath, fileName, options = {}) {
87
68
 
88
69
  function readContainerDataMap(kdnaPath, options = {}) {
89
70
  const asset = assetReader.openSync(kdnaPath);
90
- if (asset.entries.has('payload.kdnab')) {
91
- const dataMap = assetReader.readDataMapSync(asset, undefined, options);
92
- // readDataMapSync only returns judgment files — add kdna.json explicitly
93
- if (asset.entries.has('kdna.json')) {
94
- dataMap['kdna.json'] = assetReader.readJsonSync(asset, 'kdna.json', options);
95
- }
96
- return dataMap;
97
- }
98
- // v1 fallback: read individual JSON files
99
- const dataMap = {};
100
- const v1Files = [
101
- 'kdna.json',
102
- 'KDNA_Core.json',
103
- 'KDNA_Patterns.json',
104
- 'KDNA_Scenarios.json',
105
- 'KDNA_Cases.json',
106
- 'KDNA_Reasoning.json',
107
- 'KDNA_Evolution.json',
108
- ];
109
- for (const f of v1Files) {
110
- if (asset.entries.has(f)) {
111
- try {
112
- dataMap[f] = assetReader.readJsonSync(asset, f, options);
113
- } catch {
114
- /* skip */
115
- }
116
- }
71
+ const dataMap = assetReader.readDataMapSync(asset, undefined, options);
72
+ if (asset.entries.has('kdna.json')) {
73
+ dataMap['kdna.json'] = assetReader.readJsonSync(asset, 'kdna.json', options);
117
74
  }
118
75
  return dataMap;
119
76
  }
@@ -130,7 +87,6 @@ function listContainerEntries(kdnaPath) {
130
87
 
131
88
  function readContainer(kdnaPath, options = {}) {
132
89
  const asset = assetReader.openSync(kdnaPath);
133
- validateContainerV2(asset, kdnaPath);
134
90
  const dataMap = assetReader.readDataMapSync(asset, undefined, options);
135
91
  return {
136
92
  manifest: dataMap['kdna.json'] || {},
package/src/verify.js CHANGED
@@ -109,87 +109,31 @@ function directoryView(root) {
109
109
 
110
110
  function assetView(kdnaPath, options = {}) {
111
111
  const entries = new Set(listContainerEntries(kdnaPath));
112
-
113
- // v2 container: synthesize view from CBOR payload
114
- if (entries.has('payload.kdnab')) {
115
- let dataMap = null;
116
- const _ensureDataMap = () => {
117
- if (!dataMap) dataMap = readContainerDataMap(kdnaPath, options);
118
- return dataMap;
119
- };
120
-
121
- const v2Entries = new Set(entries);
122
- v2Entries.add('KDNA_Core.json');
123
- v2Entries.add('KDNA_Patterns.json');
124
- if (dataMap) {
125
- for (const k of [
126
- 'KDNA_Scenarios.json',
127
- 'KDNA_Cases.json',
128
- 'KDNA_Reasoning.json',
129
- 'KDNA_Evolution.json',
130
- ]) {
131
- if (dataMap[k]) v2Entries.add(k);
132
- }
133
- }
134
-
135
- return {
136
- kind: 'asset',
137
- path: kdnaPath,
138
- exists(name) {
139
- if (v2Entries.has(name)) return true;
140
- return entries.has(name);
141
- },
142
- readJson(name) {
143
- if (entries.has(name)) return readContainerJson(kdnaPath, name, options);
144
- const dm = _ensureDataMap();
145
- return dm[name] || null;
146
- },
147
- readText(name) {
148
- if (entries.has(name)) return readContainerEntry(kdnaPath, name).toString('utf8');
149
- const dm = _ensureDataMap();
150
- return dm[name] ? JSON.stringify(dm[name]) : '';
151
- },
152
- listDirFiles(dirName) {
153
- const prefix = `${dirName.replace(/\/+$/, '')}/`;
154
- const files = [];
155
- for (const e of entries) {
156
- if (e.startsWith(prefix)) {
157
- const rest = e.slice(prefix.length);
158
- if (rest && !rest.includes('/')) files.push(rest);
159
- }
160
- }
161
- return files;
162
- },
163
- };
164
- }
165
-
166
- // v1 container: standard ZIP entry view
112
+ let dataMap = null;
113
+ const _ensureDataMap = () => {
114
+ if (!dataMap) dataMap = readContainerDataMap(kdnaPath, options);
115
+ return dataMap;
116
+ };
117
+ const allEntries = new Set(entries);
118
+ allEntries.add('KDNA_Core.json');
119
+ allEntries.add('KDNA_Patterns.json');
167
120
  return {
168
- kind: 'asset',
169
- path: kdnaPath,
170
- exists(name) {
171
- return entries.has(name);
172
- },
121
+ kind: 'asset', path: kdnaPath,
122
+ exists(name) { return allEntries.has(name) || entries.has(name); },
173
123
  readJson(name) {
174
- return readContainerJson(kdnaPath, name, options);
124
+ if (entries.has(name)) return readContainerJson(kdnaPath, name, options);
125
+ return _ensureDataMap()[name] || null;
175
126
  },
176
127
  readText(name) {
177
- if (!entries.has(name)) return '';
178
- return readContainerEntry(kdnaPath, name).toString('utf8');
128
+ if (entries.has(name)) return readContainerEntry(kdnaPath, name).toString('utf8');
129
+ const dm = _ensureDataMap();
130
+ return dm[name] ? JSON.stringify(dm[name]) : '';
179
131
  },
180
132
  listDirFiles(dirName) {
181
- const prefix = `${dirName.replace(/\/+$/, '')}/`;
182
- const files = [];
183
- for (const entryName of entries) {
184
- if (!entryName.startsWith(prefix)) continue;
185
- const rest = entryName.slice(prefix.length);
186
- if (rest && !rest.includes('/')) files.push(rest);
187
- }
188
- return files;
133
+ return [...entries].filter(e => e.startsWith(dirName.replace(//+$/,'')+'/')).map(e => { const r = e.slice(dirName.length+1); return r.includes('/') ? null : r; }).filter(Boolean);
189
134
  },
190
135
  };
191
136
  }
192
-
193
137
  function asView(input, options = {}) {
194
138
  if (input && typeof input.exists === 'function') return input;
195
139
  return directoryView(input, options);