@aikdna/kdna-cli 0.20.4 → 0.21.1

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.4",
3
+ "version": "0.21.1",
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": {
@@ -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
@@ -62,7 +62,11 @@ function validateManifestFn(manifest) {
62
62
  if (manifest.format && manifest.format !== 'kdna') {
63
63
  errors.push(`kdna.json.format: invalid value "${manifest.format}". Expected "kdna".`);
64
64
  }
65
- if (manifest.format_version && manifest.format_version !== '1.0' && manifest.format_version !== '2.0') {
65
+ if (
66
+ manifest.format_version &&
67
+ manifest.format_version !== '1.0' &&
68
+ manifest.format_version !== '2.0'
69
+ ) {
66
70
  errors.push(
67
71
  `kdna.json.format_version: invalid value "${manifest.format_version}". Expected "1.0" or "2.0".`,
68
72
  );
@@ -109,87 +113,41 @@ function directoryView(root) {
109
113
 
110
114
  function assetView(kdnaPath, options = {}) {
111
115
  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
116
+ let dataMap = null;
117
+ const _ensureDataMap = () => {
118
+ if (!dataMap) dataMap = readContainerDataMap(kdnaPath, options);
119
+ return dataMap;
120
+ };
121
+ const allEntries = new Set(entries);
122
+ allEntries.add('KDNA_Core.json');
123
+ allEntries.add('KDNA_Patterns.json');
167
124
  return {
168
125
  kind: 'asset',
169
126
  path: kdnaPath,
170
127
  exists(name) {
171
- return entries.has(name);
128
+ return allEntries.has(name) || entries.has(name);
172
129
  },
173
130
  readJson(name) {
174
- return readContainerJson(kdnaPath, name, options);
131
+ if (entries.has(name)) return readContainerJson(kdnaPath, name, options);
132
+ return _ensureDataMap()[name] || null;
175
133
  },
176
134
  readText(name) {
177
- if (!entries.has(name)) return '';
178
- return readContainerEntry(kdnaPath, name).toString('utf8');
135
+ if (entries.has(name)) return readContainerEntry(kdnaPath, name).toString('utf8');
136
+ const dm = _ensureDataMap();
137
+ return dm[name] ? JSON.stringify(dm[name]) : '';
179
138
  },
180
139
  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;
140
+ const prefix = dirName.replace(/\/+$/, '') + '/';
141
+ return [...entries]
142
+ .filter((e) => e.startsWith(prefix))
143
+ .map((e) => {
144
+ const r = e.slice(prefix.length);
145
+ return r.includes('/') ? null : r;
146
+ })
147
+ .filter(Boolean);
189
148
  },
190
149
  };
191
150
  }
192
-
193
151
  function asView(input, options = {}) {
194
152
  if (input && typeof input.exists === 'function') return input;
195
153
  return directoryView(input, options);