@aikdna/kdna-cli 0.17.0 → 0.18.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/README.md +42 -23
- package/package.json +5 -4
- package/skills/kdna-loader/SKILL.md +5 -6
- package/src/agent.js +145 -109
- package/src/cli.js +104 -60
- package/src/cmds/_common.js +32 -16
- package/src/cmds/badge.js +7 -7
- package/src/cmds/changelog.js +1 -1
- package/src/cmds/cluster.js +16 -48
- package/src/cmds/doctor.js +10 -27
- package/src/cmds/domain.js +77 -400
- package/src/cmds/explain.js +122 -0
- package/src/cmds/legacy.js +8 -8
- package/src/cmds/license.js +483 -26
- package/src/cmds/quality.js +2 -2
- package/src/cmds/registry.js +15 -67
- package/src/cmds/studio.js +4 -5
- package/src/cmds/test.js +4 -4
- package/src/cmds/trace.js +11 -7
- package/src/compare.js +28 -22
- package/src/diff.js +11 -13
- package/src/init.js +2 -2
- package/src/install.js +138 -460
- package/src/loader.js +10 -10
- package/src/package-store.js +229 -0
- package/src/paths.js +44 -0
- package/src/publish.js +73 -22
- package/src/registry.js +76 -9
- package/src/setup.js +19 -20
- package/src/verify.js +233 -124
- package/templates/standard-domain/kdna.json +2 -1
- package/src/cmds/encrypt.js +0 -199
package/src/cli.js
CHANGED
|
@@ -10,9 +10,7 @@ const { error, EXIT, setQuiet, setExitCodeOnly } = require('./cmds/_common');
|
|
|
10
10
|
const {
|
|
11
11
|
cmdValidate,
|
|
12
12
|
cmdPack,
|
|
13
|
-
cmdPackEncrypt,
|
|
14
13
|
cmdUnpack,
|
|
15
|
-
cmdUnpackEncrypt,
|
|
16
14
|
cmdInspect,
|
|
17
15
|
cmdCard,
|
|
18
16
|
} = require('./cmds/domain');
|
|
@@ -39,6 +37,9 @@ const {
|
|
|
39
37
|
cmdLicenseBind,
|
|
40
38
|
cmdLicenseShow,
|
|
41
39
|
cmdLicenseInstall,
|
|
40
|
+
cmdLicenseStatus,
|
|
41
|
+
cmdLicenseActivate,
|
|
42
|
+
cmdLicenseSync,
|
|
42
43
|
} = require('./cmds/license');
|
|
43
44
|
const { cmdPreview, cmdProject, cmdEval, cmdExport, cmdDemo } = require('./cmds/legacy');
|
|
44
45
|
const {
|
|
@@ -58,7 +59,8 @@ const {
|
|
|
58
59
|
cmdEvolution,
|
|
59
60
|
cmdRegression,
|
|
60
61
|
} = require('./cmds/governance');
|
|
61
|
-
const { cmdBadgeCompute, cmdRegistryAudit
|
|
62
|
+
const { cmdBadgeCompute, cmdRegistryAudit } = require('./cmds/badge');
|
|
63
|
+
const { cmdExplain } = require('./cmds/explain');
|
|
62
64
|
|
|
63
65
|
// ─── Main ─────────────────────────────────────────────────────────────
|
|
64
66
|
|
|
@@ -80,15 +82,14 @@ Usage: kdna <command> [options]
|
|
|
80
82
|
|
|
81
83
|
Domain Authoring:
|
|
82
84
|
init <name> Scaffold a new domain from template
|
|
83
|
-
validate <path>
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
card <path> [--locale zh-CN] Display KDNA Card (governance metadata)
|
|
85
|
+
dev validate <path> Validate a dev source directory
|
|
86
|
+
dev pack <path> Build a dev source directory into .kdna
|
|
87
|
+
dev unpack <file> Unpack .kdna into a dev source directory
|
|
88
|
+
dev inspect <path> Inspect a dev source directory
|
|
89
|
+
dev card <path> Display KDNA Card from a dev source directory
|
|
90
|
+
inspect <file.kdna> Inspect a .kdna asset
|
|
91
|
+
card <file.kdna> [--locale zh-CN] Display KDNA Card from a .kdna asset
|
|
92
|
+
explain <name> Natural language summary: axioms, terms, scenarios
|
|
92
93
|
publish <path> Pack + sign + publish
|
|
93
94
|
publish --check <path> Quality gate check only
|
|
94
95
|
version bump <level> [path] Bump domain version
|
|
@@ -106,18 +107,18 @@ Agent Runtime:
|
|
|
106
107
|
available [--json] List installed domains with v2.1 fields
|
|
107
108
|
match "<task>" [--json] Signal matching — find relevant domains
|
|
108
109
|
select --input "..." [--json] Selection policy — decide which domains to load
|
|
109
|
-
load <name> [--as=prompt|json|raw] Emit
|
|
110
|
-
load <name> --profile=index|compact|scenario|full Load profiles (Phase 2)
|
|
110
|
+
load <name|file.kdna> [--as=prompt|json|raw] Emit asset in agent-ready format
|
|
111
|
+
load <name|file.kdna> --profile=index|compact|scenario|full Load profiles (Phase 2)
|
|
111
112
|
postvalidate <name> --output <file> Post-generation judgment check
|
|
112
113
|
|
|
113
114
|
Testing & Verification:
|
|
114
|
-
verify <name>
|
|
115
|
-
verify <name> --i18n
|
|
116
|
-
verify <name> --governance
|
|
117
|
-
verify <name> --judgment --run-tests Judgment validation with eval cases
|
|
118
|
-
compare <name> --input "..." With/without KDNA reasoning diff
|
|
119
|
-
compare <name> --input "..." --report-md Markdown report format
|
|
120
|
-
compare <name> --input "..." --report-json JSON report with scoring
|
|
115
|
+
verify <name|file.kdna> 3-layer: structure + trust + judgment
|
|
116
|
+
verify <name|file.kdna> --i18n I18N verification: locales, overlays, card completeness
|
|
117
|
+
verify <name|file.kdna> --governance Governance verification: risk_level, KDNA_CARD, provenance
|
|
118
|
+
verify <name|file.kdna> --judgment --run-tests Judgment validation with eval cases
|
|
119
|
+
compare <name|file.kdna> --input "..." With/without KDNA reasoning diff
|
|
120
|
+
compare <name|file.kdna> --input "..." --report-md Markdown report format
|
|
121
|
+
compare <name|file.kdna> --input "..." --report-json JSON report with scoring
|
|
121
122
|
diff <name>@<v1> <name>@<v2> Judgment-level diff between versions
|
|
122
123
|
test run <name> --input <file> Record test result against domain
|
|
123
124
|
test import <run> --as-eval Convert test result to eval card
|
|
@@ -148,6 +149,7 @@ Quality & Distribution (Phase 7):
|
|
|
148
149
|
|
|
149
150
|
Registry & Distribution:
|
|
150
151
|
install <name> Install domain from registry
|
|
152
|
+
install <file.kdna> Install a local .kdna asset
|
|
151
153
|
remove <name> Uninstall a domain
|
|
152
154
|
update <name> Update installed domain
|
|
153
155
|
info <name> Show domain metadata and trust status
|
|
@@ -172,9 +174,12 @@ Trace & Diagnostics:
|
|
|
172
174
|
License & Authorization:
|
|
173
175
|
license generate <domain> --to <email> Generate signed license
|
|
174
176
|
license install <license.json> Register license for auto-decrypt
|
|
177
|
+
license activate <domain> --key --server Activate license from entitlement source
|
|
178
|
+
license sync [domain] [--server] Refresh entitlement / revocation status
|
|
175
179
|
license verify <license.json> Verify license signature
|
|
176
180
|
license bind <license.json> Bind license to this machine
|
|
177
181
|
license show <license.json> Display license details
|
|
182
|
+
license status [domain] [--json] Show installed license activation status
|
|
178
183
|
|
|
179
184
|
Flags:
|
|
180
185
|
--json Structured JSON output (machine-readable)
|
|
@@ -190,41 +195,69 @@ Exit Codes:
|
|
|
190
195
|
const cmd = args[0];
|
|
191
196
|
|
|
192
197
|
switch (cmd) {
|
|
198
|
+
case 'dev': {
|
|
199
|
+
const sub = args[1];
|
|
200
|
+
if (sub === 'validate') {
|
|
201
|
+
const schemaFlag = args.includes('--schema');
|
|
202
|
+
const jsonFlag = args.includes('--json');
|
|
203
|
+
const target = args.filter((a, i) => i > 1 && a !== '--schema' && a !== '--json')[0];
|
|
204
|
+
if (!target) error('Usage: kdna dev validate <source-dir>');
|
|
205
|
+
cmdValidate(target, schemaFlag, jsonFlag);
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
if (sub === 'pack') {
|
|
209
|
+
let output = null;
|
|
210
|
+
let target = null;
|
|
211
|
+
for (let i = 2; i < args.length; i++) {
|
|
212
|
+
if (args[i] === '--output' || args[i] === '-o') {
|
|
213
|
+
output = args[i + 1];
|
|
214
|
+
i++;
|
|
215
|
+
} else if (args[i].startsWith('-')) {
|
|
216
|
+
error(`Unknown option for kdna dev pack: ${args[i]}`, EXIT.INPUT_ERROR);
|
|
217
|
+
} else if (!target) {
|
|
218
|
+
target = args[i];
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (!target) error('Usage: kdna dev pack <source-dir>');
|
|
222
|
+
cmdPack(target, output);
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
if (sub === 'unpack') {
|
|
226
|
+
const target = args[2];
|
|
227
|
+
if (!target) error('Usage: kdna dev unpack <file.kdna>');
|
|
228
|
+
if (!target.endsWith('.kdna')) error('Not a .kdna asset.', EXIT.INPUT_ERROR);
|
|
229
|
+
cmdUnpack(target, args.includes('--force'));
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
if (sub === 'inspect') {
|
|
233
|
+
const target = args.filter((a, i) => i > 1 && !a.startsWith('--'))[0];
|
|
234
|
+
if (!target) error('Usage: kdna dev inspect <source-dir> [--json] [--locale zh-CN]');
|
|
235
|
+
const localeIdx = args.indexOf('--locale');
|
|
236
|
+
const locale = localeIdx >= 0 ? args[localeIdx + 1] : null;
|
|
237
|
+
cmdInspect(target, args.includes('--json'), locale, { allowDirectory: true });
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
if (sub === 'card') {
|
|
241
|
+
const target = args.filter((a, i) => i > 1 && !a.startsWith('--'))[0];
|
|
242
|
+
if (!target) error('Usage: kdna dev card <source-dir> [--json] [--locale zh-CN]');
|
|
243
|
+
const localeIdx = args.indexOf('--locale');
|
|
244
|
+
const locale = localeIdx >= 0 ? args[localeIdx + 1] : null;
|
|
245
|
+
cmdCard(target, args.includes('--json'), locale, { allowDirectory: true });
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
error('Usage: kdna dev <validate|pack|unpack|inspect|card> ...', EXIT.INPUT_ERROR);
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
193
251
|
case 'validate': {
|
|
194
|
-
|
|
195
|
-
const jsonFlag = args.includes('--json');
|
|
196
|
-
const target = args.filter((a, i) => i > 0 && a !== '--schema' && a !== '--json')[0];
|
|
197
|
-
if (!target) error('Usage: kdna validate <path>');
|
|
198
|
-
cmdValidate(target, schemaFlag, jsonFlag);
|
|
252
|
+
error('Directory validation is a dev-only operation. Use: kdna dev validate <source-dir>', EXIT.INPUT_ERROR);
|
|
199
253
|
break;
|
|
200
254
|
}
|
|
201
255
|
case 'pack': {
|
|
202
|
-
|
|
203
|
-
let target = null;
|
|
204
|
-
for (let i = 1; i < args.length; i++) {
|
|
205
|
-
if (args[i] === '--output' || args[i] === '-o') {
|
|
206
|
-
output = args[i + 1];
|
|
207
|
-
i++;
|
|
208
|
-
} else if (!target) {
|
|
209
|
-
target = args[i];
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
if (!target) error('Usage: kdna pack <path>');
|
|
213
|
-
if (args.includes('--encrypt')) {
|
|
214
|
-
cmdPackEncrypt(target, args);
|
|
215
|
-
} else {
|
|
216
|
-
cmdPack(target, output);
|
|
217
|
-
}
|
|
256
|
+
error('Directory packaging is a dev-only operation. Use: kdna dev pack <source-dir>', EXIT.INPUT_ERROR);
|
|
218
257
|
break;
|
|
219
258
|
}
|
|
220
259
|
case 'unpack': {
|
|
221
|
-
|
|
222
|
-
if (!target) error('Usage: kdna unpack <file.kdna|file.kdnae>');
|
|
223
|
-
if (target.endsWith('.kdnae')) {
|
|
224
|
-
cmdUnpackEncrypt(target, args);
|
|
225
|
-
} else {
|
|
226
|
-
cmdUnpack(target, args.includes('--force'));
|
|
227
|
-
}
|
|
260
|
+
error('Unpacking exposes internal files and is dev-only. Use: kdna dev unpack <file.kdna>', EXIT.INPUT_ERROR);
|
|
228
261
|
break;
|
|
229
262
|
}
|
|
230
263
|
case 'preview': {
|
|
@@ -242,7 +275,7 @@ switch (cmd) {
|
|
|
242
275
|
domainId = args[i];
|
|
243
276
|
}
|
|
244
277
|
}
|
|
245
|
-
if (!domainId) error('Usage: kdna install <domain-id|
|
|
278
|
+
if (!domainId) error('Usage: kdna install <domain-id|file.kdna>');
|
|
246
279
|
|
|
247
280
|
const { cmdInstallExtended } = require('./install');
|
|
248
281
|
if (fromGit) {
|
|
@@ -285,7 +318,7 @@ switch (cmd) {
|
|
|
285
318
|
}
|
|
286
319
|
case 'inspect': {
|
|
287
320
|
const target = args.filter((a) => !a.startsWith('--'))[1];
|
|
288
|
-
if (!target) error('Usage: kdna inspect <
|
|
321
|
+
if (!target) error('Usage: kdna inspect <file.kdna> [--json] [--locale zh-CN]');
|
|
289
322
|
const localeIdx = args.indexOf('--locale');
|
|
290
323
|
const locale = localeIdx >= 0 ? args[localeIdx + 1] : null;
|
|
291
324
|
cmdInspect(target, args.includes('--json'), locale);
|
|
@@ -293,7 +326,7 @@ switch (cmd) {
|
|
|
293
326
|
}
|
|
294
327
|
case 'card': {
|
|
295
328
|
const target = args.filter((a) => !a.startsWith('--'))[1];
|
|
296
|
-
if (!target) error('Usage: kdna card <
|
|
329
|
+
if (!target) error('Usage: kdna card <file.kdna> [--json] [--locale zh-CN]');
|
|
297
330
|
const localeIdx = args.indexOf('--locale');
|
|
298
331
|
const locale = localeIdx >= 0 ? args[localeIdx + 1] : null;
|
|
299
332
|
cmdCard(target, args.includes('--json'), locale);
|
|
@@ -305,10 +338,10 @@ switch (cmd) {
|
|
|
305
338
|
if (!target) {
|
|
306
339
|
error(
|
|
307
340
|
'Usage:\n' +
|
|
308
|
-
' kdna verify <name> Run all three layers (structure / trust / judgment)\n' +
|
|
309
|
-
' kdna verify <name> --structure Files + schema only\n' +
|
|
310
|
-
' kdna verify <name> --trust Signature + scope + Ed25519 only\n' +
|
|
311
|
-
' kdna verify <name> --judgment v2.1 governance fields + eval cases only',
|
|
341
|
+
' kdna verify <name|file.kdna> Run all three layers (structure / trust / judgment)\n' +
|
|
342
|
+
' kdna verify <name|file.kdna> --structure Files + schema only\n' +
|
|
343
|
+
' kdna verify <name|file.kdna> --trust Signature + scope + Ed25519 only\n' +
|
|
344
|
+
' kdna verify <name|file.kdna> --judgment v2.1 governance fields + eval cases only',
|
|
312
345
|
);
|
|
313
346
|
}
|
|
314
347
|
cmdVerify(target, args);
|
|
@@ -430,9 +463,7 @@ switch (cmd) {
|
|
|
430
463
|
break;
|
|
431
464
|
}
|
|
432
465
|
case 'package': {
|
|
433
|
-
|
|
434
|
-
if (!target) error('Usage: kdna package <domain> --format=kdna');
|
|
435
|
-
cmdPackage(target, args);
|
|
466
|
+
error('Directory packaging is a dev-only operation. Use: kdna dev pack <source-dir>', EXIT.INPUT_ERROR);
|
|
436
467
|
break;
|
|
437
468
|
}
|
|
438
469
|
// Legacy (removed) commands
|
|
@@ -452,6 +483,10 @@ switch (cmd) {
|
|
|
452
483
|
cmdDemo();
|
|
453
484
|
break;
|
|
454
485
|
}
|
|
486
|
+
case 'explain': {
|
|
487
|
+
cmdExplain(args);
|
|
488
|
+
break;
|
|
489
|
+
}
|
|
455
490
|
case 'list': {
|
|
456
491
|
const localeIdx = args.indexOf('--locale');
|
|
457
492
|
const locale = localeIdx >= 0 ? args[localeIdx + 1] : null;
|
|
@@ -491,14 +526,23 @@ switch (cmd) {
|
|
|
491
526
|
cmdLicenseShow(rest);
|
|
492
527
|
} else if (sub === 'install') {
|
|
493
528
|
cmdLicenseInstall(rest);
|
|
529
|
+
} else if (sub === 'status') {
|
|
530
|
+
cmdLicenseStatus(rest);
|
|
531
|
+
} else if (sub === 'activate') {
|
|
532
|
+
cmdLicenseActivate(rest).catch((e) => error(e.message, EXIT.TRUST_FAILED));
|
|
533
|
+
} else if (sub === 'sync') {
|
|
534
|
+
cmdLicenseSync(rest).catch((e) => error(e.message, EXIT.TRUST_FAILED));
|
|
494
535
|
} else {
|
|
495
536
|
error(
|
|
496
537
|
'Usage:\n' +
|
|
497
538
|
' kdna license generate <domain> --to <email> [--expires <date>]\n' +
|
|
498
539
|
' kdna license install <license.json>\n' +
|
|
540
|
+
' kdna license activate <domain> --key <license-key> --server <url>\n' +
|
|
541
|
+
' kdna license sync [domain] [--server <url>]\n' +
|
|
499
542
|
' kdna license verify <license.json>\n' +
|
|
500
543
|
' kdna license bind <license.json>\n' +
|
|
501
|
-
' kdna license show <license.json
|
|
544
|
+
' kdna license show <license.json>\n' +
|
|
545
|
+
' kdna license status [domain] [--json]',
|
|
502
546
|
EXIT.INPUT_ERROR,
|
|
503
547
|
);
|
|
504
548
|
}
|
package/src/cmds/_common.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
2
|
const { loadRegistry: loadCanonicalRegistry } = require('../registry');
|
|
4
|
-
|
|
5
|
-
const USER_KDNA_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.kdna');
|
|
6
|
-
const INSTALL_DIR = path.join(USER_KDNA_DIR, 'domains');
|
|
3
|
+
const { USER_KDNA_DIR, INSTALL_DIR } = require('../paths');
|
|
7
4
|
|
|
8
5
|
// ─── Global flags ──────────────────────────────────────────────────────
|
|
9
6
|
|
|
@@ -54,14 +51,13 @@ Usage:
|
|
|
54
51
|
|
|
55
52
|
--- Domain authors ---
|
|
56
53
|
kdna init <name> Scaffold a new KDNA domain from template
|
|
57
|
-
kdna validate <path>
|
|
58
|
-
kdna
|
|
59
|
-
kdna
|
|
60
|
-
kdna
|
|
61
|
-
kdna
|
|
62
|
-
kdna
|
|
63
|
-
kdna
|
|
64
|
-
kdna publish <path> Pack + sign + output registry patch
|
|
54
|
+
kdna dev validate <path> Validate a dev source directory
|
|
55
|
+
kdna dev pack <path> Build a dev source directory into .kdna
|
|
56
|
+
kdna dev unpack <path> Unpack .kdna into a dev source directory
|
|
57
|
+
kdna dev inspect <path> Inspect a dev source directory
|
|
58
|
+
kdna dev card <path> Display KDNA Card from a dev source directory
|
|
59
|
+
kdna inspect <file.kdna> Inspect a .kdna asset
|
|
60
|
+
kdna publish <path> Pack + sign a dev source directory
|
|
65
61
|
kdna publish <path> --release-tag <tag> --repo <o/r> ...also upload to GitHub
|
|
66
62
|
kdna publish --check <path> Run quality gate only (no pack/upload)
|
|
67
63
|
kdna version bump <patch|minor|major> [path] Bump domain version
|
|
@@ -72,7 +68,6 @@ Usage:
|
|
|
72
68
|
kdna install @scope/name Install any scoped domain
|
|
73
69
|
kdna install @aikdna/animation Install a cluster (installs all sub-domains)
|
|
74
70
|
kdna install ./file.kdna Install from a local .kdna file
|
|
75
|
-
kdna install ./folder Install from a local directory (dev)
|
|
76
71
|
kdna remove <name> Uninstall a domain
|
|
77
72
|
kdna update <name> Update an installed domain
|
|
78
73
|
kdna update --all Update all installed domains
|
|
@@ -83,14 +78,14 @@ Usage:
|
|
|
83
78
|
kdna registry refresh Refresh the canonical registry cache
|
|
84
79
|
|
|
85
80
|
--- Quality + judgment ---
|
|
86
|
-
kdna verify <name>
|
|
87
|
-
kdna compare <name> --input "<text>" With/without KDNA reasoning diff
|
|
81
|
+
kdna verify <name|file.kdna> Quality check: structure + trust + judgment
|
|
82
|
+
kdna compare <name|file.kdna> --input "<text>" With/without KDNA reasoning diff
|
|
88
83
|
kdna diff <name>@<v1> <name>@<v2> Judgment-level diff between versions
|
|
89
84
|
|
|
90
85
|
--- Agent-facing (called by the kdna-loader skill) ---
|
|
91
86
|
kdna available [--json] List installed domains + v2.1 fields
|
|
92
87
|
kdna match "<task>" [--json] Hint signals (dropped + weak overlap)
|
|
93
|
-
kdna load <name> [--as=prompt|json|raw] Emit
|
|
88
|
+
kdna load <name|file.kdna> [--as=prompt|json|raw] Emit asset in agent-ready format
|
|
94
89
|
|
|
95
90
|
--- Identity ---
|
|
96
91
|
kdna identity init Generate Ed25519 identity key pair
|
|
@@ -144,6 +139,25 @@ function writeJson(file, data) {
|
|
|
144
139
|
fs.writeFileSync(file, JSON.stringify(data, null, 2) + '\n');
|
|
145
140
|
}
|
|
146
141
|
|
|
142
|
+
function selfCheckText(item) {
|
|
143
|
+
if (typeof item === 'string') return item;
|
|
144
|
+
if (item && typeof item === 'object' && typeof item.question === 'string') return item.question;
|
|
145
|
+
return '';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function isYesNoSelfCheck(item) {
|
|
149
|
+
const raw = selfCheckText(item).trim();
|
|
150
|
+
if (!raw) return false;
|
|
151
|
+
const lower = raw.toLowerCase();
|
|
152
|
+
return (
|
|
153
|
+
lower.endsWith('?') ||
|
|
154
|
+
raw.endsWith('?') ||
|
|
155
|
+
raw.endsWith('吗') ||
|
|
156
|
+
raw.includes('是否') ||
|
|
157
|
+
/^(have|has|can|does|do|is|are|did|was|were|should|will|would|could|might|can not|cannot|能不能|会不会|有没有|要不要|是不是)/.test(lower)
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
147
161
|
function loadRegistry() {
|
|
148
162
|
return loadCanonicalRegistry({ allowNetwork: true });
|
|
149
163
|
}
|
|
@@ -162,5 +176,7 @@ module.exports = {
|
|
|
162
176
|
isExitCodeOnly,
|
|
163
177
|
readJson,
|
|
164
178
|
writeJson,
|
|
179
|
+
selfCheckText,
|
|
180
|
+
isYesNoSelfCheck,
|
|
165
181
|
loadRegistry,
|
|
166
182
|
};
|
package/src/cmds/badge.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* kdna badge compute <domain> [--json]
|
|
5
5
|
* kdna registry audit --scope <scope> [--json]
|
|
6
|
-
* kdna
|
|
6
|
+
* kdna dev pack <domain>
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const fs = require('fs');
|
|
@@ -142,9 +142,9 @@ function cmdRegistryAudit(args = []) {
|
|
|
142
142
|
status: d.status || 'experimental',
|
|
143
143
|
yanked: d.yanked || false,
|
|
144
144
|
deprecated: d.deprecated || false,
|
|
145
|
-
|
|
145
|
+
has_asset_url: !!d.asset_url,
|
|
146
146
|
has_signature: !!d.signature,
|
|
147
|
-
|
|
147
|
+
has_asset_digest: !!d.asset_digest,
|
|
148
148
|
})),
|
|
149
149
|
issues: [],
|
|
150
150
|
};
|
|
@@ -152,12 +152,12 @@ function cmdRegistryAudit(args = []) {
|
|
|
152
152
|
// Detect issues
|
|
153
153
|
const yanked = scopeDomains.filter((d) => d.yanked);
|
|
154
154
|
const deprecated = scopeDomains.filter((d) => d.deprecated);
|
|
155
|
-
const noPackage = scopeDomains.filter((d) => !d.
|
|
155
|
+
const noPackage = scopeDomains.filter((d) => !d.asset_url);
|
|
156
156
|
const noSignature = scopeDomains.filter((d) => !d.signature);
|
|
157
157
|
|
|
158
158
|
if (yanked.length) audit.issues.push(`${yanked.length} yanked domain(s)`);
|
|
159
159
|
if (deprecated.length) audit.issues.push(`${deprecated.length} deprecated domain(s)`);
|
|
160
|
-
if (noPackage.length) audit.issues.push(`${noPackage.length} domain(s) without .kdna package`);
|
|
160
|
+
if (noPackage.length) audit.issues.push(`${noPackage.length} domain(s) without .kdna dev package`);
|
|
161
161
|
if (noSignature.length) audit.issues.push(`${noSignature.length} domain(s) without signature`);
|
|
162
162
|
|
|
163
163
|
audit.healthy = audit.issues.length === 0;
|
|
@@ -183,7 +183,7 @@ function cmdRegistryAudit(args = []) {
|
|
|
183
183
|
const flags = [];
|
|
184
184
|
if (d.yanked) flags.push('yanked');
|
|
185
185
|
if (d.deprecated) flags.push('deprecated');
|
|
186
|
-
if (!d.
|
|
186
|
+
if (!d.has_asset_url) flags.push('no-package');
|
|
187
187
|
console.log(` ${d.name.padEnd(36)} v${d.version || '?'} ${flags.length ? `[${flags.join(', ')}]` : '✓'}`);
|
|
188
188
|
}
|
|
189
189
|
}
|
|
@@ -205,7 +205,7 @@ function cmdPackage(domainPath, args = []) {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
const manifest = readJson(path.join(abs, 'kdna.json'));
|
|
208
|
-
if (!manifest) error(`No kdna.json found in ${abs}. Run: kdna pack`, EXIT.INPUT_ERROR);
|
|
208
|
+
if (!manifest) error(`No kdna.json found in ${abs}. Run: kdna dev pack`, EXIT.INPUT_ERROR);
|
|
209
209
|
|
|
210
210
|
const domainName = manifest.name?.split('/')?.[1] || path.basename(abs);
|
|
211
211
|
const outFile = path.join(abs, 'dist', `${domainName}-${manifest.version || '0.1.0'}.kdna`);
|
package/src/cmds/changelog.js
CHANGED
|
@@ -18,7 +18,7 @@ function downloadVersion(entry, version, destDir) {
|
|
|
18
18
|
const { execSync, execFileSync } = require('child_process');
|
|
19
19
|
const tmpFile = `${destDir}.kdna.tmp`;
|
|
20
20
|
try {
|
|
21
|
-
execFileSync('curl', ['-fsSL', '--retry', '2', '-o', tmpFile, entry.
|
|
21
|
+
execFileSync('curl', ['-fsSL', '--retry', '2', '-o', tmpFile, entry.asset_url], {
|
|
22
22
|
timeout: 60000,
|
|
23
23
|
stdio: 'pipe',
|
|
24
24
|
});
|
package/src/cmds/cluster.js
CHANGED
|
@@ -8,6 +8,16 @@ const {
|
|
|
8
8
|
detectDomainConflicts,
|
|
9
9
|
generateClusterTrace,
|
|
10
10
|
} = require('@aikdna/kdna-core');
|
|
11
|
+
const { getInstalled, readContainer } = require('../package-store');
|
|
12
|
+
|
|
13
|
+
function loadInstalledDomain(domainId) {
|
|
14
|
+
const full = domainId.startsWith('@') ? domainId : `@aikdna/${domainId}`;
|
|
15
|
+
const installed = getInstalled(full);
|
|
16
|
+
if (!installed) return null;
|
|
17
|
+
const { core, patterns } = readContainer(installed.asset_path);
|
|
18
|
+
if (!core || !patterns) return null;
|
|
19
|
+
return { core, patterns };
|
|
20
|
+
}
|
|
11
21
|
|
|
12
22
|
function cmdCluster(args) {
|
|
13
23
|
const { cmdClusterLint } = require('../cluster');
|
|
@@ -101,7 +111,7 @@ function cmdClusterInfo(target, _format = 'human') {
|
|
|
101
111
|
}
|
|
102
112
|
|
|
103
113
|
/**
|
|
104
|
-
* Load a cluster: resolve domains from installed
|
|
114
|
+
* Load a cluster: resolve domains from installed .kdna assets,
|
|
105
115
|
* classify input signals, compose context with attribution, detect
|
|
106
116
|
* conflicts, and emit the composed context.
|
|
107
117
|
*/
|
|
@@ -116,23 +126,7 @@ function cmdClusterLoad(target, args = []) {
|
|
|
116
126
|
const manifest = readJson(abs);
|
|
117
127
|
if (!manifest || !manifest.cluster_id) error('Not a valid cluster manifest');
|
|
118
128
|
|
|
119
|
-
const
|
|
120
|
-
process.env.HOME || process.env.USERPROFILE || '.',
|
|
121
|
-
'.kdna',
|
|
122
|
-
'domains',
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
// Domain loader: resolve from installed ~/.kdna/domains/
|
|
126
|
-
const domainLoader = (domainId) => {
|
|
127
|
-
const [scope, ident] = domainId.startsWith('@')
|
|
128
|
-
? [domainId.slice(0, domainId.indexOf('/')), domainId.slice(domainId.indexOf('/') + 1)]
|
|
129
|
-
: ['@aikdna', domainId];
|
|
130
|
-
const dir = path.join(INSTALL_DIR, scope, ident);
|
|
131
|
-
const core = readJson(path.join(dir, 'KDNA_Core.json'));
|
|
132
|
-
const pat = readJson(path.join(dir, 'KDNA_Patterns.json'));
|
|
133
|
-
if (!core || !pat) return null;
|
|
134
|
-
return { core, patterns: pat };
|
|
135
|
-
};
|
|
129
|
+
const domainLoader = loadInstalledDomain;
|
|
136
130
|
|
|
137
131
|
const result = loadCluster(abs, domainLoader);
|
|
138
132
|
if (result.errors.length) {
|
|
@@ -208,22 +202,7 @@ function cmdClusterMatch(target, args = []) {
|
|
|
208
202
|
const manifest = readJson(abs);
|
|
209
203
|
if (!manifest || !manifest.cluster_id) error('Not a valid cluster manifest');
|
|
210
204
|
|
|
211
|
-
const
|
|
212
|
-
process.env.HOME || process.env.USERPROFILE || '.',
|
|
213
|
-
'.kdna',
|
|
214
|
-
'domains',
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
const domainLoader = (domainId) => {
|
|
218
|
-
const [scope, ident] = domainId.startsWith('@')
|
|
219
|
-
? [domainId.slice(0, domainId.indexOf('/')), domainId.slice(domainId.indexOf('/') + 1)]
|
|
220
|
-
: ['@aikdna', domainId];
|
|
221
|
-
const dir = path.join(INSTALL_DIR, scope, ident);
|
|
222
|
-
const core = readJson(path.join(dir, 'KDNA_Core.json'));
|
|
223
|
-
const pat = readJson(path.join(dir, 'KDNA_Patterns.json'));
|
|
224
|
-
if (!core || !pat) return null;
|
|
225
|
-
return { core, patterns: pat };
|
|
226
|
-
};
|
|
205
|
+
const domainLoader = loadInstalledDomain;
|
|
227
206
|
|
|
228
207
|
const result = loadCluster(abs, domainLoader);
|
|
229
208
|
const classification = classifySignalsAcrossDomains(input, result.domains);
|
|
@@ -423,23 +402,12 @@ function cmdClusterGraph(target, args = []) {
|
|
|
423
402
|
* Shared domain loader for cluster commands.
|
|
424
403
|
*/
|
|
425
404
|
function loadClusterDomains(manifest) {
|
|
426
|
-
const INSTALL_DIR = path.join(
|
|
427
|
-
process.env.HOME || process.env.USERPROFILE || '.',
|
|
428
|
-
'.kdna',
|
|
429
|
-
'domains',
|
|
430
|
-
);
|
|
431
|
-
|
|
432
405
|
return (manifest.domains || []).map((d) => {
|
|
433
406
|
const domainId = d.id;
|
|
434
407
|
if (!domainId) return null;
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
const dir = path.join(INSTALL_DIR, scope, ident);
|
|
439
|
-
const core = readJson(path.join(dir, 'KDNA_Core.json'));
|
|
440
|
-
const pat = readJson(path.join(dir, 'KDNA_Patterns.json'));
|
|
441
|
-
if (!core || !pat) return null;
|
|
442
|
-
return { id: domainId, role: d.role, required: d.required !== false, core, patterns: pat };
|
|
408
|
+
const loaded = loadInstalledDomain(domainId);
|
|
409
|
+
if (!loaded) return null;
|
|
410
|
+
return { id: domainId, role: d.role, required: d.required !== false, ...loaded };
|
|
443
411
|
}).filter(Boolean);
|
|
444
412
|
}
|
|
445
413
|
|
package/src/cmds/doctor.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const { EXIT
|
|
3
|
+
const { EXIT } = require('./_common');
|
|
4
4
|
const USER_KDNA_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.kdna');
|
|
5
|
-
const
|
|
5
|
+
const PATHS = require('../paths');
|
|
6
|
+
const { listInstalled } = require('../package-store');
|
|
6
7
|
|
|
7
8
|
const AGENTS = [
|
|
8
9
|
{ name: 'OpenCode', dir: path.join(process.env.HOME || '', '.agents'), skillsDir: 'skills' },
|
|
@@ -17,11 +18,6 @@ const AGENTS = [
|
|
|
17
18
|
];
|
|
18
19
|
|
|
19
20
|
const V2_1_MARKER = 'kdna available';
|
|
20
|
-
|
|
21
|
-
function detectAgents() {
|
|
22
|
-
return AGENTS.filter((a) => fs.existsSync(a.dir));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
21
|
function checkAgentSkill(agent) {
|
|
26
22
|
const skillPath = path.join(agent.dir, agent.skillsDir, 'kdna-loader', 'SKILL.md');
|
|
27
23
|
if (!fs.existsSync(skillPath)) return { installed: false, version: null, path: skillPath };
|
|
@@ -74,38 +70,25 @@ function cmdDoctor(args) {
|
|
|
74
70
|
checks.push({ name: 'KDNA data directory', status: 'warn', detail: '~/.kdna/ not found' });
|
|
75
71
|
}
|
|
76
72
|
|
|
77
|
-
// 4. ~/.kdna/
|
|
78
|
-
if (fs.existsSync(
|
|
79
|
-
const domains =
|
|
80
|
-
.readdirSync(INSTALL_DIR, { withFileTypes: true })
|
|
81
|
-
.filter((d) => d.isDirectory())
|
|
82
|
-
.reduce((acc, scopeDir) => {
|
|
83
|
-
if (scopeDir.name.startsWith('@')) {
|
|
84
|
-
try {
|
|
85
|
-
return acc + fs.readdirSync(path.join(INSTALL_DIR, scopeDir.name)).length;
|
|
86
|
-
} catch {
|
|
87
|
-
return acc;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return acc + 1;
|
|
91
|
-
}, 0);
|
|
73
|
+
// 4. ~/.kdna/packages/ exists and has .kdna assets
|
|
74
|
+
if (fs.existsSync(PATHS.packages)) {
|
|
75
|
+
const domains = listInstalled().length;
|
|
92
76
|
checks.push({
|
|
93
|
-
name: 'Installed
|
|
77
|
+
name: 'Installed assets',
|
|
94
78
|
status: domains > 0 ? 'ok' : 'warn',
|
|
95
|
-
detail: `${domains}
|
|
79
|
+
detail: `${domains} .kdna asset${domains !== 1 ? 's' : ''} installed`,
|
|
96
80
|
});
|
|
97
81
|
} else {
|
|
98
82
|
checks.push({
|
|
99
|
-
name: '
|
|
83
|
+
name: 'Package asset store',
|
|
100
84
|
status: 'warn',
|
|
101
|
-
detail: '~/.kdna/
|
|
85
|
+
detail: '~/.kdna/packages/ not found',
|
|
102
86
|
});
|
|
103
87
|
}
|
|
104
88
|
}
|
|
105
89
|
|
|
106
90
|
if (!domainsOnly) {
|
|
107
91
|
// 5. Agent integration check
|
|
108
|
-
const detected = detectAgents();
|
|
109
92
|
for (const agent of AGENTS) {
|
|
110
93
|
const agentDirExists = fs.existsSync(agent.dir);
|
|
111
94
|
const skill = agentDirExists
|