@aikdna/kdna-cli 0.9.0 → 0.12.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/src/cli.js CHANGED
@@ -1,24 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * kdna — Unified CLI for KDNA domain cognition assets.
3
+ * kdna — The runtime control plane for domain judgment.
4
4
  *
5
- * Commands:
6
- * kdna validate <path> Validate a domain directory or .kdna file
7
- * kdna verify <path> Verify a domain (alias for validate)
8
- * kdna pack <path> Pack a domain folder into .kdna container (ZIP)
9
- * kdna unpack <path> Unpack .kdna container to domain folder
10
- * kdna install <domain-id> Install a domain from registry
11
- * kdna inspect <path> Inspect a domain directory or .kdna file
12
- * kdna list List installed domains
13
- * kdna compare <before> <after> Compare judgment with/without KDNA
14
- * kdna match "<task>" Match task against available domains
15
- * kdna setup One-command setup: install CLI + skills + data root
16
- * kdna cluster lint <path> Validate a cluster manifest
17
- * kdna identity init Generate Ed25519 identity key pair
18
- * kdna identity show Display public key and buyer ID
5
+ * KDNA CLI is the runtime control plane for loading, validating,
6
+ * composing, testing, and governing domain judgment for AI agents.
19
7
  */
20
8
 
21
- const { usage, error } = require('./cmds/_common');
9
+ const { error, EXIT, setQuiet, setExitCodeOnly } = require('./cmds/_common');
22
10
  const { cmdValidate, cmdPack, cmdUnpack, cmdInspect } = require('./cmds/domain');
23
11
  const { cmdList, cmdRegistry } = require('./cmds/registry');
24
12
  const {
@@ -27,29 +15,142 @@ const {
27
15
  cmdSearch,
28
16
  cmdAvailable,
29
17
  cmdMatch,
18
+ cmdSelect,
30
19
  cmdLoad,
20
+ cmdPostvalidate,
31
21
  } = require('./cmds/quality');
32
22
  const { cmdCluster } = require('./cmds/cluster');
33
23
  const { cmdIdentity } = require('./cmds/identity');
34
24
  const { cmdSetup } = require('./cmds/setup');
35
- const { cmdPreview, cmdProject, cmdEval, cmdSelect, cmdExport, cmdDemo } = require('./cmds/legacy');
25
+ const { cmdDoctor } = require('./cmds/doctor');
26
+ const { cmdTrace, cmdHistory } = require('./cmds/trace');
27
+ const { cmdPreview, cmdProject, cmdEval, cmdExport, cmdDemo } = require('./cmds/legacy');
28
+ const { cmdStudioScaffold, cmdCardsValidate, cmdLockVerify, cmdStudioCompile, cmdStudioReadiness } = require('./cmds/studio');
29
+ const { cmdTestRun, cmdTestImport } = require('./cmds/test');
30
+ const { cmdChangelog } = require('./cmds/changelog');
31
+ const { cmdProposalCreate, cmdProposalValidate, cmdReview, cmdLockCard, cmdEvolution, cmdRegression } = require('./cmds/governance');
32
+ const { cmdBadgeCompute, cmdRegistryAudit, cmdPackage } = require('./cmds/badge');
36
33
 
37
34
  // ─── Main ─────────────────────────────────────────────────────────────
38
35
 
39
36
  const args = process.argv.slice(2);
40
37
  if (!args.length || args[0] === 'help' || args[0] === '--help' || args[0] === '-h') {
41
- usage();
38
+ showHelp();
42
39
  process.exit(0);
43
40
  }
44
41
 
42
+ // Global flags
43
+ if (args.includes('--quiet')) setQuiet(true);
44
+ if (args.includes('--exit-code')) setExitCodeOnly(true);
45
+
46
+ function showHelp() {
47
+ const v = require('../package.json').version;
48
+ console.log(`kdna v${v} — The runtime control plane for domain judgment
49
+
50
+ Usage: kdna <command> [options]
51
+
52
+ Domain Authoring:
53
+ init <name> Scaffold a new domain from template
54
+ validate <path> Validate domain structure
55
+ validate --schema <path> Schema-only validation
56
+ pack <path> Pack into .kdna container
57
+ unpack <file> Unpack .kdna container
58
+ inspect <path> Inspect domain or .kdna file
59
+ publish <path> Pack + sign + publish
60
+ publish --check <path> Quality gate check only
61
+ version bump <level> [path] Bump domain version
62
+ version bump --suggest [path] Suggest version bump level
63
+
64
+ Studio Integration (Phase 1):
65
+ studio scaffold <name> Create Studio project + card templates
66
+ cards validate <project.json> Validate Judgment Cards structure
67
+ lock verify <project.json> Verify Human Lock status
68
+ studio compile <project.json> Compile locked cards into KDNA domain
69
+ studio readiness <project.json> Generate domain readiness card
70
+
71
+ Agent Runtime:
72
+ available [--json] List installed domains with v2.1 fields
73
+ match "<task>" [--json] Signal matching — find relevant domains
74
+ select --input "..." [--json] Selection policy — decide which domains to load
75
+ load <name> [--as=prompt|json|raw] Emit domain in agent-ready format
76
+ load <name> --profile=index|compact|scenario|full Load profiles (Phase 2)
77
+ postvalidate <name> --output <file> Post-generation judgment check
78
+
79
+ Testing & Verification:
80
+ verify <name> 3-layer: structure + trust + judgment
81
+ verify <name> --judgment --run-tests Judgment validation with eval cases
82
+ compare <name> --input "..." With/without KDNA reasoning diff
83
+ diff <name>@<v1> <name>@<v2> Judgment-level diff between versions
84
+ test run <name> --input <file> Record test result against domain
85
+ test import <run> --as-eval Convert test result to eval card
86
+ changelog <name> --from --to Generate judgment changelog
87
+
88
+ Cluster Composition:
89
+ cluster lint <path> Validate cluster manifest
90
+ cluster match <path> --input ".." Match input to cluster domains
91
+ cluster compose <path> --input Compose context with source attribution
92
+ cluster conflicts <path> --input Detect inter-domain conflicts
93
+ cluster graph <path> Output domain relationship graph (DOT/JSON)
94
+
95
+ Governance & Release (Phase 6):
96
+ proposal create --from-test <run> --domain <path> Create improvement proposal
97
+ proposal validate <proposal.json> Validate proposal structure
98
+ review accept <proposal> --by --reason Accept improvement proposal
99
+ review reject <proposal> --by --reason Reject improvement proposal
100
+ lock card <id> --by --reason Record human lock on a card
101
+ evolution add-proposal <file> Add proposal to evolution record
102
+ evolution add-lock <file> Add lock to evolution record
103
+ evolution report <domain> Show domain evolution history
104
+ regression <old> <new> --evals <dir> Detect judgment regression
105
+
106
+ Quality & Distribution (Phase 7):
107
+ badge compute <domain> Compute quality badge (draft/tested/trusted)
108
+ registry audit --scope <@scope> Audit registry scope health
109
+ package <domain> --format=kdna Package domain as distributable asset
110
+
111
+ Registry & Distribution:
112
+ install <name> Install domain from registry
113
+ remove <name> Uninstall a domain
114
+ update <name> Update installed domain
115
+ info <name> Show domain metadata and trust status
116
+ list [--available] List installed or available domains
117
+ search <keyword> Search registry
118
+ registry refresh Refresh registry cache
119
+
120
+ Identity & Signing:
121
+ identity init Generate Ed25519 signing key
122
+ identity show Display public key and buyer ID
123
+ identity export [--out] Backup private key (encrypted)
124
+ identity import <file> Restore identity from backup
125
+
126
+ Setup:
127
+ setup One-command setup: CLI + skill + data root
128
+
129
+ Trace & Diagnostics:
130
+ doctor [--agents] [--domains] [--json] System health check
131
+ trace [--json] [--since 7d] [--export <file>] Agent judgment trace
132
+ history [--stats] [--domain <name>] [--agent <name>] Recent usage
133
+
134
+ Flags:
135
+ --json Structured JSON output (machine-readable)
136
+ --quiet Suppress non-error output
137
+
138
+ Exit Codes:
139
+ 0 OK 1 VALIDATION_FAILED 2 INPUT_ERROR 3 TRUST_FAILED
140
+ 4 JUDGMENT_QUALITY_FAILED 5 REGISTRY_ERROR 6 PROVIDER_ERROR
141
+ 7 POLICY_VIOLATION 8 HUMAN_LOCK_REQUIRED
142
+ `);
143
+ }
144
+
45
145
  const cmd = args[0];
46
146
 
47
147
  switch (cmd) {
48
148
  case 'validate': {
49
149
  const schemaFlag = args.includes('--schema');
50
- const target = args.filter((a, i) => i > 0 && a !== '--schema')[0];
150
+ const jsonFlag = args.includes('--json');
151
+ const target = args.filter((a, i) => i > 0 && a !== '--schema' && a !== '--json')[0];
51
152
  if (!target) error('Usage: kdna validate <path>');
52
- cmdValidate(target, schemaFlag);
153
+ cmdValidate(target, schemaFlag, jsonFlag);
53
154
  break;
54
155
  }
55
156
  case 'pack': {
@@ -113,9 +214,9 @@ switch (cmd) {
113
214
  }
114
215
  case 'info': {
115
216
  const { cmdInfo } = require('./install');
116
- const target = args[1];
217
+ const target = args.filter((a) => !a.startsWith('--'))[1];
117
218
  if (!target) error('Usage: kdna info <domain>');
118
- cmdInfo(target);
219
+ cmdInfo(target, args.includes('--json'));
119
220
  break;
120
221
  }
121
222
  case 'update': {
@@ -130,9 +231,9 @@ switch (cmd) {
130
231
  break;
131
232
  }
132
233
  case 'inspect': {
133
- const target = args[1];
234
+ const target = args.filter((a) => !a.startsWith('--'))[1];
134
235
  if (!target) error('Usage: kdna inspect <path>');
135
- cmdInspect(target);
236
+ cmdInspect(target, args.includes('--json'));
136
237
  break;
137
238
  }
138
239
  case 'verify': {
@@ -174,6 +275,97 @@ switch (cmd) {
174
275
  cmdLoad(args);
175
276
  break;
176
277
  }
278
+ case 'select': {
279
+ cmdSelect(args);
280
+ break;
281
+ }
282
+ case 'postvalidate': {
283
+ cmdPostvalidate(args);
284
+ break;
285
+ }
286
+ case 'test': {
287
+ const sub = args[1];
288
+ if (sub === 'run') {
289
+ cmdTestRun(['test', ...args.slice(2)]);
290
+ } else if (sub === 'import') {
291
+ cmdTestImport(['test', ...args.slice(2)]);
292
+ } else {
293
+ error(
294
+ 'Usage:\n' +
295
+ ' kdna test run <domain> --input <file> [--save <dir>]\n' +
296
+ ' kdna test import <run-file> --as-eval --out <file>',
297
+ EXIT.INPUT_ERROR,
298
+ );
299
+ }
300
+ break;
301
+ }
302
+ case 'changelog': {
303
+ cmdChangelog(args);
304
+ break;
305
+ }
306
+ case 'proposal': {
307
+ const sub = args[1];
308
+ if (sub === 'create') {
309
+ cmdProposalCreate(args);
310
+ } else if (sub === 'validate') {
311
+ cmdProposalValidate(args);
312
+ } else {
313
+ error('Usage: kdna proposal create --from-test <run.json> --domain <path>\n kdna proposal validate <proposal.json>', EXIT.INPUT_ERROR);
314
+ }
315
+ break;
316
+ }
317
+ case 'review': {
318
+ cmdReview(args);
319
+ break;
320
+ }
321
+ case 'lock': {
322
+ const sub = args[1];
323
+ if (sub === 'verify') {
324
+ const target = args.filter((a) => !a.startsWith('--'))[2];
325
+ if (!target) error('Usage: kdna lock verify <studio.project.json>');
326
+ cmdLockVerify(target, args);
327
+ } else if (sub === 'card') {
328
+ cmdLockCard(args);
329
+ } else {
330
+ error(
331
+ 'Usage:\n' +
332
+ ' kdna lock verify <studio.project.json> Verify human lock status\n' +
333
+ ' kdna lock card <card-id> --by <name> --reason "..." Lock a judgment card',
334
+ EXIT.INPUT_ERROR,
335
+ );
336
+ }
337
+ break;
338
+ }
339
+ case 'evolution': {
340
+ cmdEvolution(args);
341
+ break;
342
+ }
343
+ case 'regression': {
344
+ cmdRegression(args);
345
+ break;
346
+ }
347
+ case 'badge': {
348
+ const sub = args[1];
349
+ if (sub === 'compute') {
350
+ const target = args.filter((a) => !a.startsWith('--'))[2];
351
+ if (!target) error('Usage: kdna badge compute <domain>');
352
+ cmdBadgeCompute(target, args);
353
+ } else {
354
+ error('Usage: kdna badge compute <domain>', EXIT.INPUT_ERROR);
355
+ }
356
+ break;
357
+ }
358
+ case 'audit': {
359
+ cmdRegistryAudit(args);
360
+ break;
361
+ }
362
+ case 'package': {
363
+ const target = args.filter((a) => !a.startsWith('--'))[1];
364
+ if (!target) error('Usage: kdna package <domain> --format=kdna');
365
+ cmdPackage(target, args);
366
+ break;
367
+ }
368
+ // Legacy (removed) commands
177
369
  case 'project': {
178
370
  cmdProject();
179
371
  break;
@@ -182,22 +374,18 @@ switch (cmd) {
182
374
  cmdEval();
183
375
  break;
184
376
  }
185
- case 'select': {
186
- cmdSelect();
187
- break;
188
- }
189
377
  case 'export': {
190
378
  cmdExport();
191
379
  break;
192
380
  }
193
- case 'list': {
194
- cmdList(args.includes('--available'));
195
- break;
196
- }
197
381
  case 'demo': {
198
382
  cmdDemo();
199
383
  break;
200
384
  }
385
+ case 'list': {
386
+ cmdList(args.includes('--available'), args.includes('--json'));
387
+ break;
388
+ }
201
389
  case 'setup': {
202
390
  cmdSetup();
203
391
  break;
@@ -206,6 +394,18 @@ switch (cmd) {
206
394
  cmdCluster(args);
207
395
  break;
208
396
  }
397
+ case 'doctor': {
398
+ cmdDoctor(args);
399
+ break;
400
+ }
401
+ case 'trace': {
402
+ cmdTrace(args);
403
+ break;
404
+ }
405
+ case 'history': {
406
+ cmdHistory(args);
407
+ break;
408
+ }
209
409
  case 'identity': {
210
410
  cmdIdentity(args);
211
411
  break;
@@ -239,19 +439,61 @@ switch (cmd) {
239
439
  break;
240
440
  }
241
441
  case 'version': {
242
- const { cmdVersionBump } = require('./version');
442
+ const { cmdVersionBump, cmdVersionSuggest } = require('./version');
243
443
  const sub = args[1];
244
444
  if (sub === 'bump') {
245
- const level = args[2];
246
- const target = args[3] || '.';
247
- if (!level || !['patch', 'minor', 'major'].includes(level)) {
248
- error('Usage: kdna version bump <patch|minor|major> [path]');
445
+ if (args.includes('--suggest')) {
446
+ const target = args.filter((a) => !a.startsWith('--'))[3] || '.';
447
+ cmdVersionSuggest(target, args);
448
+ } else {
449
+ const level = args[2];
450
+ const target = args[3] || '.';
451
+ if (!level || !['patch', 'minor', 'major'].includes(level)) {
452
+ error('Usage: kdna version bump <patch|minor|major> [path]');
453
+ }
454
+ cmdVersionBump(level, target);
249
455
  }
250
- cmdVersionBump(level, target);
251
456
  } else {
252
457
  console.log(`kdna v${require('../package.json').version}`);
253
458
  console.log('');
254
459
  console.log('Usage: kdna version bump <patch|minor|major> [path]');
460
+ console.log(' kdna version bump --suggest [path]');
461
+ }
462
+ break;
463
+ }
464
+ case 'cards': {
465
+ const sub = args[1];
466
+ if (sub === 'validate') {
467
+ const target = args.filter((a) => !a.startsWith('--'))[2];
468
+ if (!target) error('Usage: kdna cards validate <studio.project.json>');
469
+ cmdCardsValidate(target, args);
470
+ } else {
471
+ error('Usage: kdna cards validate <studio.project.json>', EXIT.INPUT_ERROR);
472
+ }
473
+ break;
474
+ }
475
+ case 'studio': {
476
+ const sub = args[1];
477
+ if (sub === 'scaffold') {
478
+ const target = args.filter((a) => !a.startsWith('--'))[2];
479
+ if (!target) error('Usage: kdna studio scaffold <name> [--type=cluster] [--minimal]');
480
+ cmdStudioScaffold(target, args);
481
+ } else if (sub === 'compile') {
482
+ const target = args.filter((a) => !a.startsWith('--'))[2];
483
+ if (!target) error('Usage: kdna studio compile <studio.project.json> [--out <dir>]');
484
+ cmdStudioCompile(target, args);
485
+ } else if (sub === 'readiness') {
486
+ const target = args.filter((a) => !a.startsWith('--'))[2];
487
+ if (!target) error('Usage: kdna studio readiness <studio.project.json>');
488
+ cmdStudioReadiness(target, args);
489
+ } else {
490
+ error(
491
+ 'Usage:\n' +
492
+ ' kdna studio scaffold <name> [--type=cluster] [--minimal]\n' +
493
+ ' kdna studio compile <studio.project.json> [--out <dir>]\n' +
494
+ ' kdna studio readiness <studio.project.json>',
495
+ EXIT.INPUT_ERROR,
496
+ );
255
497
  }
256
498
  break;
257
499
  }
@@ -5,6 +5,48 @@ const { loadRegistry: loadCanonicalRegistry } = require('../registry');
5
5
  const USER_KDNA_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.kdna');
6
6
  const INSTALL_DIR = path.join(USER_KDNA_DIR, 'domains');
7
7
 
8
+ // ─── Global flags ──────────────────────────────────────────────────────
9
+
10
+ let _quiet = false;
11
+ let _exitCodeOnly = false;
12
+ const _originalLog = console.log;
13
+ const _originalError = console.error;
14
+ const _originalWarn = console.warn;
15
+
16
+ function setQuiet(val) {
17
+ _quiet = val;
18
+ if (val) {
19
+ console.log = () => {};
20
+ } else {
21
+ console.log = _originalLog;
22
+ }
23
+ }
24
+
25
+ function isQuiet() { return _quiet; }
26
+
27
+ function setExitCodeOnly(val) {
28
+ _exitCodeOnly = val;
29
+ if (val) {
30
+ console.log = () => {};
31
+ console.warn = () => {};
32
+ console.error = () => {};
33
+ } else {
34
+ console.log = _originalLog;
35
+ console.warn = _originalWarn;
36
+ console.error = _originalError;
37
+ }
38
+ }
39
+
40
+ function isExitCodeOnly() { return _exitCodeOnly; }
41
+
42
+ function log(...args) {
43
+ if (!_quiet && !_exitCodeOnly) _originalLog(...args);
44
+ }
45
+
46
+ function warn(...args) {
47
+ if (!_exitCodeOnly) _originalWarn(...args);
48
+ }
49
+
8
50
  function usage() {
9
51
  console.log(`kdna — KDNA domain cognition asset tool
10
52
 
@@ -57,6 +99,9 @@ Usage:
57
99
 
58
100
  --- Other ---
59
101
  kdna setup One-command setup: CLI + skill + data root
102
+ kdna doctor [--agents] [--domains] [--json] System health check
103
+ kdna trace [--json] [--since 7d] [--export <file>] Agent judgment trace
104
+ kdna history [--stats] [--domain <name>] [--agent <name>] Recent usage
60
105
  kdna version Show kdna CLI version
61
106
  kdna help Show this help
62
107
 
@@ -68,9 +113,22 @@ Examples:
68
113
  kdna publish ./my_domain --release-tag v0.1.0 --repo yourname/kdna-my_domain`);
69
114
  }
70
115
 
71
- function error(msg) {
72
- console.error(`Error: ${msg}`);
73
- process.exit(1);
116
+ // Exit codes — semantic exit codes for all KDNA CLI commands
117
+ const EXIT = {
118
+ OK: 0,
119
+ VALIDATION_FAILED: 1,
120
+ INPUT_ERROR: 2,
121
+ TRUST_FAILED: 3,
122
+ JUDGMENT_QUALITY_FAILED: 4,
123
+ REGISTRY_ERROR: 5,
124
+ PROVIDER_ERROR: 6,
125
+ POLICY_VIOLATION: 7,
126
+ HUMAN_LOCK_REQUIRED: 8,
127
+ };
128
+
129
+ function error(msg, code = EXIT.VALIDATION_FAILED) {
130
+ if (!_exitCodeOnly) _originalError(`Error: ${msg}`);
131
+ process.exit(code);
74
132
  }
75
133
 
76
134
  function readJson(file) {
@@ -90,10 +148,17 @@ function loadRegistry() {
90
148
  }
91
149
 
92
150
  module.exports = {
151
+ EXIT,
93
152
  USER_KDNA_DIR,
94
153
  INSTALL_DIR,
95
154
  usage,
96
155
  error,
156
+ log,
157
+ warn,
158
+ setQuiet,
159
+ isQuiet,
160
+ setExitCodeOnly,
161
+ isExitCodeOnly,
97
162
  readJson,
98
163
  writeJson,
99
164
  loadRegistry,