@aikdna/kdna-cli 0.19.2 → 0.20.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.
@@ -0,0 +1,181 @@
1
+ const { readFileSync } = require('fs');
2
+ const path = require('path');
3
+ const { error, EXIT } = require('./_common');
4
+
5
+ const SCHEMA_DIR = path.join(
6
+ path.dirname(require.resolve('@aikdna/kdna-core/package.json')),
7
+ '..',
8
+ '..',
9
+ 'specs',
10
+ );
11
+
12
+ const SCHEMAS = {
13
+ 'artifact-envelope': 'artifact-envelope.schema.json',
14
+ 'stage-definition': 'stage-definition.schema.json',
15
+ 'fidelity-result': 'fidelity-result.schema.json',
16
+ 'product-runtime': 'product-runtime.schema.json',
17
+ };
18
+
19
+ function validate(args) {
20
+ const file = args.filter((a) => !a.startsWith('--'))[1];
21
+ const schemaName = args.includes('--schema') ? args[args.indexOf('--schema') + 1] : null;
22
+
23
+ if (!file) {
24
+ error('Usage: kdna protocol validate <file.json> [--schema <name>]', EXIT.INPUT_ERROR);
25
+ }
26
+
27
+ let data;
28
+ try {
29
+ data = JSON.parse(readFileSync(file, 'utf8'));
30
+ } catch (e) {
31
+ error(`Failed to read or parse ${file}: ${e.message}`, EXIT.INPUT_ERROR);
32
+ }
33
+
34
+ const schemasToCheck = schemaName ? [schemaName] : Object.keys(SCHEMAS);
35
+ let passed = 0;
36
+ let failed = 0;
37
+
38
+ for (const name of schemasToCheck) {
39
+ const schemaFile = SCHEMAS[name];
40
+ if (!schemaFile) {
41
+ error(
42
+ `Unknown schema: ${name}. Available: ${Object.keys(SCHEMAS).join(', ')}`,
43
+ EXIT.INPUT_ERROR,
44
+ );
45
+ }
46
+
47
+ try {
48
+ const schemaPath = path.join(SCHEMA_DIR, schemaFile);
49
+ const schema = JSON.parse(readFileSync(schemaPath, 'utf8'));
50
+ const { validate: ajvValidate } = loadAjv();
51
+ const valid = ajvValidate(schema, data);
52
+ if (valid) {
53
+ console.log(` ✓ ${name} (${schemaFile})`);
54
+ passed++;
55
+ } else {
56
+ console.log(` ✗ ${name} (${schemaFile})`);
57
+ failed++;
58
+ }
59
+ } catch (e) {
60
+ console.log(` ✗ ${name}: ${e.message}`);
61
+ failed++;
62
+ }
63
+ }
64
+
65
+ if (failed > 0) {
66
+ error(`Validation failed: ${failed}/${passed + failed} schema(s)`, EXIT.VALIDATION_FAILED);
67
+ }
68
+ console.log(`Validation passed: ${passed}/${passed + failed} schema(s)`);
69
+ }
70
+
71
+ function inspect(args) {
72
+ const file = args.filter((a) => !a.startsWith('--'))[1];
73
+ if (!file) {
74
+ error('Usage: kdna protocol inspect <file.json>', EXIT.INPUT_ERROR);
75
+ }
76
+
77
+ let data;
78
+ try {
79
+ data = JSON.parse(readFileSync(file, 'utf8'));
80
+ } catch (e) {
81
+ error(`Failed to read ${file}: ${e.message}`, EXIT.INPUT_ERROR);
82
+ }
83
+
84
+ if (args.includes('--json')) {
85
+ console.log(JSON.stringify(summarize(data), null, 2));
86
+ } else {
87
+ const summary = summarize(data);
88
+ console.log(`Type: ${summary.type}`);
89
+ if (summary.artifact_type) console.log(`Artifact: ${summary.artifact_type}`);
90
+ if (summary.generator)
91
+ console.log(`Generator: ${summary.generator.engine} v${summary.generator.version}`);
92
+ if (summary.source_kdna_count) console.log(`KDNA domains: ${summary.source_kdna_count}`);
93
+ if (summary.stages_count) console.log(`Stages: ${summary.stages_count}`);
94
+ if (summary.quality) console.log(`Quality: ${summary.quality}`);
95
+ if (summary.fidelity) console.log(`Fidelity: ${summary.fidelity}`);
96
+ if (summary.review) console.log(`Review: ${summary.review}`);
97
+ }
98
+ }
99
+
100
+ function summarize(data) {
101
+ const summary = { type: 'unknown' };
102
+
103
+ if (data.format === 'kdna-pipeline') {
104
+ summary.type = 'pipeline';
105
+ summary.stages_count = data.stages?.length || 0;
106
+ if (data.pipeline_kdna) summary.kdna_mode = data.pipeline_kdna.mode;
107
+ if (data.artifacts?.enabled) summary.artifacts_enabled = true;
108
+ if (data.trace?.enabled) summary.trace_enabled = true;
109
+ } else if (data.artifact_id && data.artifact_type) {
110
+ summary.type = 'artifact';
111
+ summary.artifact_type = data.artifact_type;
112
+ if (data.generator) summary.generator = data.generator;
113
+ summary.source_kdna_count = data.source_kdna?.length || 0;
114
+ if (data.quality?.overall_result) summary.quality = data.quality.overall_result;
115
+ if (data.review?.status) summary.review = data.review.status;
116
+ if (data.quality?.fidelity?.score !== undefined)
117
+ summary.fidelity = `${data.quality.fidelity.score} (v${data.quality.fidelity.protocol_version})`;
118
+ } else if (
119
+ data.fidelity_id &&
120
+ (data.protocol_version !== undefined || data.protocolVersion !== undefined)
121
+ ) {
122
+ summary.type = 'fidelity_result';
123
+ summary.overall_score = data.overall_score ?? data.overallScore;
124
+ summary.passed = data.passed;
125
+ const cmp = data.comparison;
126
+ if (cmp) {
127
+ if (cmp.blind_delta !== undefined) summary.blind_delta = cmp.blind_delta;
128
+ else if (cmp.blindDelta !== undefined) summary.blind_delta = cmp.blindDelta;
129
+ }
130
+ } else if (data.format === 'kdna-product-runtime') {
131
+ summary.type = 'product_runtime';
132
+ if (data.schedule) summary.schedule_type = data.schedule.type;
133
+ if (data.selection) summary.selection_type = data.selection.type;
134
+ }
135
+
136
+ return summary;
137
+ }
138
+
139
+ let _ajv = null;
140
+ function loadAjv() {
141
+ if (_ajv) return _ajv;
142
+ try {
143
+ const Ajv = require('ajv');
144
+ const addFormats = require('ajv-formats');
145
+ const ajv = new Ajv({ allErrors: true, strict: false, validateSchema: false });
146
+ addFormats(ajv);
147
+ _ajv = { ajv, validate: (schema, data) => ajv.validate(schema, data) };
148
+ } catch {
149
+ _ajv = {
150
+ validate: () => {
151
+ throw new Error('ajv not installed. Run: npm install ajv ajv-formats');
152
+ },
153
+ };
154
+ }
155
+ return _ajv;
156
+ }
157
+
158
+ function cmdProtocol(args) {
159
+ const sub = args[1];
160
+ const rest = args.slice(1);
161
+
162
+ switch (sub) {
163
+ case 'validate':
164
+ validate(rest);
165
+ break;
166
+ case 'inspect':
167
+ inspect(rest);
168
+ break;
169
+ default:
170
+ error(
171
+ 'Usage: kdna protocol <validate|inspect> [file]\n' +
172
+ ' kdna protocol validate <file.json> [--schema <name>]\n' +
173
+ ' kdna protocol inspect <file.json> [--json]\n' +
174
+ '\nSchemas: ' +
175
+ Object.keys(SCHEMAS).join(', '),
176
+ EXIT.INPUT_ERROR,
177
+ );
178
+ }
179
+ }
180
+
181
+ module.exports = { cmdProtocol };
@@ -1,11 +1,11 @@
1
1
  /**
2
- * KDNA Studio CLI commands Phase 1: Studio Beta 底层支撑.
2
+ * Dev-only Studio project diagnostics retained for old project files.
3
3
  *
4
- * kdna studio scaffold <name> Create Studio project skeleton
4
+ * kdna-studio create <name> Create Studio project skeleton
5
5
  * kdna cards validate <project.json> Validate Judgment Cards
6
6
  * kdna lock verify <project.json> Verify Human Lock status
7
- * kdna studio compile <project.json> Compile locked cards into KDNA domain
8
- * kdna studio readiness <project.json> Generate Domain Readiness Card
7
+ * kdna-studio compile <project.json> Compile locked cards into Studio build output
8
+ * kdna-studio report <project.json> Generate Domain Readiness Card
9
9
  */
10
10
 
11
11
  const fs = require('fs');
@@ -80,10 +80,7 @@ const CARD_TEMPLATES = {
80
80
 
81
81
  function cmdStudioScaffold(name, args = []) {
82
82
  if (!name)
83
- error(
84
- 'Usage: kdna studio scaffold <name> [--type=domain|cluster] [--minimal]',
85
- EXIT.INPUT_ERROR,
86
- );
83
+ error('Usage: kdna-studio create <name> [--type=domain|cluster] [--minimal]', EXIT.INPUT_ERROR);
87
84
  if (!/^[a-z][a-z0-9_-]*$/.test(name)) {
88
85
  error(
89
86
  `Invalid name "${name}". Use lowercase letters, numbers, hyphens, underscores. Start with letter.`,
@@ -139,7 +136,7 @@ function cmdStudioScaffold(name, args = []) {
139
136
  // Write exports/README.md
140
137
  fs.writeFileSync(
141
138
  path.join(targetDir, 'exports', 'README.md'),
142
- `# ${name}\n\nCompiled KDNA domain files will appear here after \`kdna studio compile\`.\n`,
139
+ `# ${name}\n\nCompiled KDNA domain files will appear here after \`kdna-studio compile\`.\n`,
143
140
  );
144
141
 
145
142
  console.log(`✓ Studio project created: ${targetDir}/`);
@@ -150,7 +147,7 @@ function cmdStudioScaffold(name, args = []) {
150
147
  console.log(' 1. Edit cards/ — replace all [TODO] placeholders');
151
148
  console.log(' 2. Run: kdna cards validate studio.project.json');
152
149
  console.log(' 3. Run: kdna lock verify studio.project.json');
153
- console.log(' 4. Run: kdna studio compile studio.project.json');
150
+ console.log(' 4. Run: kdna-studio compile studio.project.json');
154
151
  }
155
152
 
156
153
  // ─── Cards Validate ───────────────────────────────────────────────────