@aikdna/kdna-cli 0.19.3 → 0.20.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/LICENSE +1 -1
- package/README.md +42 -28
- package/package.json +5 -4
- package/skills/kdna-loader/SKILL.md +3 -1
- package/src/capsule-verify.js +70 -0
- package/src/cli.js +72 -47
- package/src/cmds/_common.js +66 -8
- package/src/cmds/domain.js +20 -1
- package/src/cmds/governance.js +1 -1
- package/src/cmds/protect.js +314 -0
- package/src/cmds/protect.js.bak +245 -0
- package/src/cmds/protocol.js +181 -0
- package/src/cmds/studio.js +7 -10
- package/src/cmds/workpack.js +875 -0
- package/src/dev-pack-v2.js +117 -0
- package/src/init.js +14 -6
- package/src/install.js +116 -2
- package/src/kdf-spec.js +42 -0
- package/src/package-store.js +29 -7
- package/src/paths.js +3 -2
- package/src/publish.js +91 -183
- package/src/registry.js +73 -3
- package/src/signature.js +39 -0
- package/src/verify.js +78 -0
- package/templates/cluster/README.md +1 -1
- package/templates/standard-domain/USAGE.md +2 -1
- package/templates/standard-domain/kdna.json +1 -1
package/LICENSE
CHANGED
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
same "printed page" as the copyright notice for easier
|
|
188
188
|
identification within third-party archives.
|
|
189
189
|
|
|
190
|
-
Copyright
|
|
190
|
+
Copyright 2026 KDNA Contributors
|
|
191
191
|
|
|
192
192
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
193
|
you may not use this file except in compliance with the License.
|
package/README.md
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
# @aikdna/kdna-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@aikdna/kdna-cli) [](https://github.com/aikdna/kdna-cli/actions/workflows/ci.yml) [](LICENSE)
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
> **KDNA Ecosystem:** [`kdna`](https://github.com/aikdna/kdna) — the protocol. [KDNAChat](https://github.com/aikdna/kdnachat) — the consumption client. [KDNA Studio](https://github.com/aikdna/kdnastudio) — the authoring tool. [KDNAWork](https://github.com/aikdna/kdnawork) — the workbench. **You are here → kdna-cli** — the toolchain. [Registry](https://github.com/aikdna/kdna-registry) — the catalog.
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**Role**: kdna-cli is the **runtime control plane** — the official reference implementation for asset validation, loading, installation, comparison, publishing, and agent-facing runtime workflows. It bridges Studio output to Chat/Work consumption.
|
|
8
|
+
|
|
9
|
+
**KDNA CLI is the official open-source reference implementation for KDNA verification, loading, installation, comparison, registry access, publishing, and agent-facing runtime workflows.**
|
|
8
10
|
|
|
9
11
|
It is the runtime control plane for loading, validating, composing, testing, and governing domain judgment for AI agents.
|
|
10
12
|
|
|
11
|
-
KDNA CLI 是 KDNA
|
|
13
|
+
KDNA CLI 是 KDNA 验证、加载、安装、比较、注册表访问、发布和 Agent 运行时工作流的官方开源参考实现,也是 AI Agent 加载、验证、组合、测试和治理领域判断的运行控制平面。
|
|
12
14
|
|
|
13
15
|
The CLI is how a KDNA domain judgment package becomes usable by agents. It installs KDNA domains, verifies their structure and trust metadata, loads them into agent-readable form, compares judgment paths with and without KDNA, and records traces for audit.
|
|
14
16
|
|
|
15
17
|
KDNA CLI 让一个领域判断资产真正被 Agent 使用。它负责安装 KDNA、验证结构与信任信息、把 KDNA 转换成 Agent 可加载的形式、对比加载前后的判断路径,并记录可审计的使用痕迹。
|
|
16
18
|
|
|
19
|
+
A `.kdna` asset is not created by writing JSON files. It is compiled by a
|
|
20
|
+
Studio-compatible authoring pipeline that performs human confirmation,
|
|
21
|
+
validation, canonicalization, identity generation, digest computation, signing,
|
|
22
|
+
optional encryption, and provenance recording. kdna-cli verifies and publishes
|
|
23
|
+
existing assets; it does not author trusted KDNA.
|
|
24
|
+
|
|
17
25
|
Part of the [KDNA](https://github.com/aikdna/kdna) ecosystem.
|
|
18
26
|
|
|
19
27
|
## Install
|
|
@@ -47,20 +55,21 @@ kdna doctor --agents
|
|
|
47
55
|
|
|
48
56
|
## All Commands by Role
|
|
49
57
|
|
|
50
|
-
###
|
|
51
|
-
|
|
52
|
-
| Command | Status | Description
|
|
53
|
-
| ---------------------------------- | ------------ |
|
|
54
|
-
| `kdna init <name>` |
|
|
55
|
-
| `kdna dev
|
|
56
|
-
| `kdna dev
|
|
57
|
-
| `kdna dev
|
|
58
|
-
| `kdna dev
|
|
59
|
-
| `kdna dev
|
|
60
|
-
| `kdna
|
|
61
|
-
| `kdna
|
|
62
|
-
| `kdna publish
|
|
63
|
-
| `kdna
|
|
58
|
+
### Dev Source Utilities
|
|
59
|
+
|
|
60
|
+
| Command | Status | Description |
|
|
61
|
+
| ---------------------------------- | ------------ | --------------------------------------------------------------------------- |
|
|
62
|
+
| `kdna init <name>` | Deprecated | Alias for `kdna dev scaffold`; creates a non-canonical dev source workspace |
|
|
63
|
+
| `kdna dev scaffold <name>` | Beta | Scaffold a non-canonical dev source workspace |
|
|
64
|
+
| `kdna dev validate <path>` | Stable | Validate a non-canonical dev source directory |
|
|
65
|
+
| `kdna dev pack <path>` | Beta | Build a dev-only non-trusted `.kdna` bundle |
|
|
66
|
+
| `kdna dev unpack <file>` | Beta | Unpack .kdna into a dev source directory |
|
|
67
|
+
| `kdna dev inspect <path>` | Beta | Inspect a non-canonical dev source directory |
|
|
68
|
+
| `kdna dev card <path>` | Beta | Display KDNA Card from a dev source directory |
|
|
69
|
+
| `kdna inspect <file.kdna>` | Beta | Inspect a .kdna asset |
|
|
70
|
+
| `kdna publish <file.kdna>` | Experimental | Publish an existing Studio-compiled `.kdna` asset |
|
|
71
|
+
| `kdna publish --check <path>` | Experimental | Dev source readiness check only; does not publish |
|
|
72
|
+
| `kdna version bump <level> [path]` | Beta | Bump domain version |
|
|
64
73
|
|
|
65
74
|
### Agent Runtime
|
|
66
75
|
|
|
@@ -98,6 +107,11 @@ kdna doctor --agents
|
|
|
98
107
|
|
|
99
108
|
### License & Authorization
|
|
100
109
|
|
|
110
|
+
Licensed asset loading (`kdna install`, `kdna load`, `kdna verify`) requires a
|
|
111
|
+
valid local activation. Full RFC-0008 conformance across JS Core, Swift Core,
|
|
112
|
+
and CLI is tracked via cross-language test vectors in the
|
|
113
|
+
[kdna](https://github.com/aikdna/kdna) conformance suite.
|
|
114
|
+
|
|
101
115
|
| Command | Status | Description |
|
|
102
116
|
| ----------------------------------------------------------- | ------------ | -------------------------------------------------------------- |
|
|
103
117
|
| `kdna license generate <domain> --to <email>` | Experimental | Generate signed license |
|
|
@@ -165,7 +179,7 @@ The minimum valid `.kdna` asset requires these internal entries:
|
|
|
165
179
|
|
|
166
180
|
Each KDNA judgment file must include `meta.version`, `meta.domain`, `meta.created`, `meta.purpose`, and `meta.load_condition`.
|
|
167
181
|
|
|
168
|
-
Source directories are dev-only authoring workspaces. Public install, inspect, verify, load, compare, and agent-facing commands consume `.kdna` assets or installed asset names, not source directories.
|
|
182
|
+
Source directories are dev-only authoring workspaces. Public install, inspect, verify, load, compare, publish, and agent-facing commands consume `.kdna` assets or installed asset names, not source directories. To create a trusted `.kdna`, use KDNA Studio or a Studio-compatible compiler that records authoring provenance, Human Lock evidence, compiler metadata, and asset digest.
|
|
169
183
|
|
|
170
184
|
---
|
|
171
185
|
|
|
@@ -240,15 +254,15 @@ kdna license verify --json <file>
|
|
|
240
254
|
|
|
241
255
|
## Product Matrix
|
|
242
256
|
|
|
243
|
-
| Layer | Product | Responsibility
|
|
244
|
-
| ------------ | ----------------------- |
|
|
245
|
-
| Protocol | KDNA SPEC | Define judgment asset format
|
|
246
|
-
| Core Library | @aikdna/kdna-core | load / validate / compose / render
|
|
247
|
-
| Runtime | @aikdna/kdna-cli |
|
|
248
|
-
| Authoring | KDNA Studio |
|
|
249
|
-
| Consumption | KDNAChat | Load, use, compare
|
|
250
|
-
| Governance | KDNA Governance Console | Approve, release, audit
|
|
251
|
-
| Distribution | Registry | Discover, install, license, distribute
|
|
257
|
+
| Layer | Product | Responsibility |
|
|
258
|
+
| ------------ | ----------------------- | ----------------------------------------------------------------------------- |
|
|
259
|
+
| Protocol | KDNA SPEC | Define judgment asset format |
|
|
260
|
+
| Core Library | @aikdna/kdna-core | load / validate / compose / render |
|
|
261
|
+
| Runtime | @aikdna/kdna-cli | install / verify / load / compare / publish existing assets / license / trace |
|
|
262
|
+
| Authoring | KDNA Studio | author / lock / compile / export / sign / encrypt |
|
|
263
|
+
| Consumption | KDNAChat | Load, use, compare |
|
|
264
|
+
| Governance | KDNA Governance Console | Approve, release, audit |
|
|
265
|
+
| Distribution | Registry | Discover, install, license, distribute |
|
|
252
266
|
|
|
253
267
|
## Development
|
|
254
268
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aikdna/kdna-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "KDNA CLI —
|
|
3
|
+
"version": "0.20.1",
|
|
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": {
|
|
7
7
|
"kdna": "src/cli.js",
|
|
@@ -48,11 +48,12 @@
|
|
|
48
48
|
"node": ">=18"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@aikdna/kdna-core": "^0.
|
|
51
|
+
"@aikdna/kdna-core": "^0.8.0"
|
|
52
52
|
},
|
|
53
53
|
"optionalDependencies": {
|
|
54
54
|
"ajv": "^8.17.1",
|
|
55
|
-
"ajv-formats": "^3.0.1"
|
|
55
|
+
"ajv-formats": "^3.0.1",
|
|
56
|
+
"cbor-x": "^1.6.4"
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|
|
58
59
|
"@eslint/js": "^9.39.0",
|
|
@@ -295,7 +295,9 @@ Otherwise, stay silent about the loading mechanics.
|
|
|
295
295
|
|
|
296
296
|
- Not a list of available KDNA domains (those are installed `.kdna` assets, discovered on demand)
|
|
297
297
|
- Not a registry browser (use `kdna list --available` CLI)
|
|
298
|
-
- Not a domain creator
|
|
298
|
+
- Not a domain creator. Agents may draft judgment proposals, but trusted `.kdna`
|
|
299
|
+
assets must be Human Locked and compiled by KDNA Studio or a
|
|
300
|
+
Studio-compatible compiler.
|
|
299
301
|
- Not an auto-loader that runs on every request — you decide per
|
|
300
302
|
request whether the task needs KDNA at all
|
|
301
303
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// KDNA Capsule Verification — trust chain validation for agent consumption
|
|
2
|
+
// Ensures agents receive verified, tamper-proof context capsules.
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
const { execFileSync } = require('child_process');
|
|
5
|
+
|
|
6
|
+
function verifyCapsule(capsulePath, options = {}) {
|
|
7
|
+
const raw = require('fs').readFileSync(capsulePath, 'utf8');
|
|
8
|
+
let capsule;
|
|
9
|
+
try {
|
|
10
|
+
capsule = JSON.parse(raw);
|
|
11
|
+
} catch {
|
|
12
|
+
return { valid: false, error: 'Invalid capsule JSON' };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const errors = [];
|
|
16
|
+
const warnings = [];
|
|
17
|
+
|
|
18
|
+
// 1. Structural checks
|
|
19
|
+
if (capsule.type !== 'kdna.context.capsule') errors.push('Missing capsule type marker');
|
|
20
|
+
if (!capsule.domain) errors.push('Missing domain identifier');
|
|
21
|
+
if (!capsule.asset_digest) errors.push('Missing asset digest');
|
|
22
|
+
if (!capsule.signature) errors.push('Missing signature block');
|
|
23
|
+
|
|
24
|
+
// 2. Signature verification
|
|
25
|
+
if (capsule.signature && !capsule.signature.verified) {
|
|
26
|
+
errors.push('Capsule signature not verified — asset may be tampered');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 3. Digest integrity
|
|
30
|
+
if (capsule.asset_digest && capsule.domain) {
|
|
31
|
+
try {
|
|
32
|
+
const kdnaHome =
|
|
33
|
+
process.env.KDNA_HOME || require('path').join(require('os').homedir(), '.kdna');
|
|
34
|
+
const packagesDir = require('path').join(
|
|
35
|
+
kdnaHome,
|
|
36
|
+
'packages',
|
|
37
|
+
capsule.domain.replace('@', '').replace('/', '-'),
|
|
38
|
+
);
|
|
39
|
+
// Check if the installed asset matches the capsule's claimed digest
|
|
40
|
+
const result = execFileSync('kdna', ['verify', capsule.domain, '--structure'], {
|
|
41
|
+
encoding: 'utf8',
|
|
42
|
+
timeout: 15000,
|
|
43
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
44
|
+
});
|
|
45
|
+
if (!result.includes('valid')) {
|
|
46
|
+
warnings.push('Could not verify installed asset against capsule digest');
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
warnings.push('Could not run kdna verify to cross-check capsule digest');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 4. Trace metadata
|
|
54
|
+
if (capsule.trace) {
|
|
55
|
+
if (!capsule.trace.schema_valid)
|
|
56
|
+
warnings.push('Schema validation was not performed during load');
|
|
57
|
+
if (!capsule.trace.signature_valid)
|
|
58
|
+
warnings.push('Asset signature was not verified during load');
|
|
59
|
+
if (!capsule.trace.loaded_at) warnings.push('Missing load timestamp');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
valid: errors.length === 0,
|
|
64
|
+
errors,
|
|
65
|
+
warnings,
|
|
66
|
+
capsule,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = { verifyCapsule };
|
package/src/cli.js
CHANGED
|
@@ -35,14 +35,9 @@ const {
|
|
|
35
35
|
cmdLicenseActivate,
|
|
36
36
|
cmdLicenseSync,
|
|
37
37
|
} = require('./cmds/license');
|
|
38
|
+
const { cmdProtect, cmdUnlock, cmdRecover } = require('./cmds/protect');
|
|
38
39
|
const { cmdPreview, cmdProject, cmdEval, cmdExport, cmdDemo } = require('./cmds/legacy');
|
|
39
|
-
const {
|
|
40
|
-
cmdStudioScaffold,
|
|
41
|
-
cmdCardsValidate,
|
|
42
|
-
cmdLockVerify,
|
|
43
|
-
cmdStudioCompile,
|
|
44
|
-
cmdStudioReadiness,
|
|
45
|
-
} = require('./cmds/studio');
|
|
40
|
+
const { cmdCardsValidate, cmdLockVerify } = require('./cmds/studio');
|
|
46
41
|
const { cmdTestRun, cmdTestImport } = require('./cmds/test');
|
|
47
42
|
const { cmdChangelog } = require('./cmds/changelog');
|
|
48
43
|
const {
|
|
@@ -55,6 +50,8 @@ const {
|
|
|
55
50
|
} = require('./cmds/governance');
|
|
56
51
|
const { cmdBadgeCompute, cmdRegistryAudit } = require('./cmds/badge');
|
|
57
52
|
const { cmdExplain } = require('./cmds/explain');
|
|
53
|
+
const { cmdWorkpack } = require('./cmds/workpack');
|
|
54
|
+
const { cmdProtocol } = require('./cmds/protocol');
|
|
58
55
|
|
|
59
56
|
// ─── Main ─────────────────────────────────────────────────────────────
|
|
60
57
|
|
|
@@ -74,27 +71,26 @@ function showHelp() {
|
|
|
74
71
|
|
|
75
72
|
Usage: kdna <command> [options]
|
|
76
73
|
|
|
77
|
-
|
|
78
|
-
init <name>
|
|
74
|
+
Dev Source Utilities (non-canonical):
|
|
75
|
+
init <name> Deprecated alias for dev scaffold
|
|
76
|
+
dev scaffold <name> Scaffold a non-canonical dev source workspace
|
|
79
77
|
dev validate <path> Validate a dev source directory
|
|
80
|
-
dev pack <path> Build a dev
|
|
78
|
+
dev pack <path> Build a dev-only non-trusted .kdna bundle
|
|
81
79
|
dev unpack <file> Unpack .kdna into a dev source directory
|
|
82
80
|
dev inspect <path> Inspect a dev source directory
|
|
83
81
|
dev card <path> Display KDNA Card from a dev source directory
|
|
84
82
|
inspect <file.kdna> Inspect a .kdna asset
|
|
85
83
|
card <file.kdna> [--locale zh-CN] Display KDNA Card from a .kdna asset
|
|
86
84
|
explain <name> Natural language summary: axioms, terms, scenarios
|
|
87
|
-
publish <
|
|
88
|
-
publish --check <path>
|
|
85
|
+
publish <file.kdna> Publish an existing Studio-compiled .kdna asset
|
|
86
|
+
publish --check <path> Dev source readiness check only
|
|
89
87
|
version bump <level> [path] Bump domain version
|
|
90
88
|
version bump --suggest [path] Suggest version bump level
|
|
91
89
|
|
|
92
|
-
Studio
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
studio compile <project.json> Compile locked cards into KDNA domain
|
|
97
|
-
studio readiness <project.json> Generate domain readiness card
|
|
90
|
+
Studio Authoring Boundary (dev-preview only — use standalone kdna-studio for trusted authoring):
|
|
91
|
+
cards validate <project.json> Dev-only card structure check
|
|
92
|
+
lock verify <project.json> Dev-only Human Lock status check
|
|
93
|
+
studio Removed. Trusted KDNA authoring: npm install -g @aikdna/kdna-studio-cli
|
|
98
94
|
|
|
99
95
|
Agent Runtime:
|
|
100
96
|
route "<task>" [--json] [--discover] 5-Gate 7-State routing decision
|
|
@@ -125,6 +121,17 @@ Cluster Composition:
|
|
|
125
121
|
cluster conflicts <path> --input Detect inter-domain conflicts
|
|
126
122
|
cluster graph <path> Output domain relationship graph (DOT/JSON)
|
|
127
123
|
|
|
124
|
+
Work Pack (reusable AI work capabilities):
|
|
125
|
+
workpack init <name> [--domain] Scaffold a new Work Pack from template
|
|
126
|
+
workpack validate <path> Schema validation + structural completeness (L0→L1)
|
|
127
|
+
workpack validate <path> --json Machine-readable validation output
|
|
128
|
+
workpack inspect <path> Show Work Pack structure, KDNA refs, skills, gates
|
|
129
|
+
workpack inspect <path> --json Machine-readable inspection output
|
|
130
|
+
workpack explain <path> Natural-language explanation of what the Work Pack does
|
|
131
|
+
workpack plan <path> [--input] Dry-run execution plan — what WOULD happen
|
|
132
|
+
workpack run <path> --input <f> Execute Work Pack (--dry-run for simulation)
|
|
133
|
+
workpack report <session-id> Display session report
|
|
134
|
+
|
|
128
135
|
Governance & Release (Phase 6):
|
|
129
136
|
proposal create --from-test <run> --domain <path> Create improvement proposal
|
|
130
137
|
proposal validate <proposal.json> Validate proposal structure
|
|
@@ -139,11 +146,11 @@ Governance & Release (Phase 6):
|
|
|
139
146
|
Quality & Distribution (Phase 7):
|
|
140
147
|
badge compute <domain> Compute quality badge (draft/tested/trusted)
|
|
141
148
|
registry audit --scope <@scope> Audit registry scope health
|
|
142
|
-
package <domain> --format=kdna Package domain as distributable asset
|
|
143
149
|
|
|
144
150
|
Registry & Distribution:
|
|
145
151
|
install <name> Install domain from registry
|
|
146
152
|
install <file.kdna> Install a local .kdna asset
|
|
153
|
+
install <file.kdna> --trusted Install with mandatory trust verification
|
|
147
154
|
remove <name> Uninstall a domain
|
|
148
155
|
update <name> Update installed domain
|
|
149
156
|
info <name> Show domain metadata and trust status
|
|
@@ -175,6 +182,11 @@ License & Authorization:
|
|
|
175
182
|
license show <license.json> Display license details
|
|
176
183
|
license status [domain] [--json] Show installed license activation status
|
|
177
184
|
|
|
185
|
+
Protected Assets (RFC-0009):
|
|
186
|
+
protect <file.kdna> --out <file.kdna> [--entries <list>] Encrypt entries with password
|
|
187
|
+
unlock <file.kdna> [--profile compact|index|full] Decrypt and load protected asset
|
|
188
|
+
recover <file.kdna> --out <file.kdna> [--code-stdin] Reset password with recovery code
|
|
189
|
+
|
|
178
190
|
Flags:
|
|
179
191
|
--json Structured JSON output (machine-readable)
|
|
180
192
|
--quiet Suppress non-error output
|
|
@@ -216,6 +228,11 @@ switch (cmd) {
|
|
|
216
228
|
cmdPack(target, output);
|
|
217
229
|
break;
|
|
218
230
|
}
|
|
231
|
+
if (sub === 'scaffold') {
|
|
232
|
+
const { cmdInit } = require('./init');
|
|
233
|
+
cmdInit(args[2], { devScaffold: true });
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
219
236
|
if (sub === 'unpack') {
|
|
220
237
|
const target = args[2];
|
|
221
238
|
if (!target) error('Usage: kdna dev unpack <file.kdna>');
|
|
@@ -278,11 +295,10 @@ switch (cmd) {
|
|
|
278
295
|
domainId = args[i];
|
|
279
296
|
}
|
|
280
297
|
}
|
|
281
|
-
if (!domainId) error('Usage: kdna install <domain-id|file.kdna>');
|
|
298
|
+
if (!domainId) error('Usage: kdna install <domain-id|file.kdna> [--trusted]');
|
|
282
299
|
|
|
283
300
|
const { cmdInstallExtended } = require('./install');
|
|
284
301
|
if (fromGit) {
|
|
285
|
-
// Legacy --from-git: treat as github: URL
|
|
286
302
|
const url = fromGit.replace(/^https:\/\/github\.com\//, '').replace(/\.git$/, '');
|
|
287
303
|
cmdInstallExtended(`github:${url}`, args);
|
|
288
304
|
} else {
|
|
@@ -507,6 +523,14 @@ switch (cmd) {
|
|
|
507
523
|
cmdCluster(args);
|
|
508
524
|
break;
|
|
509
525
|
}
|
|
526
|
+
case 'workpack': {
|
|
527
|
+
cmdWorkpack(args);
|
|
528
|
+
break;
|
|
529
|
+
}
|
|
530
|
+
case 'protocol': {
|
|
531
|
+
cmdProtocol(args);
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
510
534
|
case 'doctor': {
|
|
511
535
|
cmdDoctor(args);
|
|
512
536
|
break;
|
|
@@ -554,13 +578,28 @@ switch (cmd) {
|
|
|
554
578
|
}
|
|
555
579
|
break;
|
|
556
580
|
}
|
|
581
|
+
case 'protect': {
|
|
582
|
+
const rest = args.slice(1);
|
|
583
|
+
cmdProtect(rest);
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
case 'unlock': {
|
|
587
|
+
const rest = args.slice(1);
|
|
588
|
+
cmdUnlock(rest);
|
|
589
|
+
break;
|
|
590
|
+
}
|
|
591
|
+
case 'recover': {
|
|
592
|
+
const rest = args.slice(1);
|
|
593
|
+
cmdRecover(rest);
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
557
596
|
case 'identity': {
|
|
558
597
|
cmdIdentity(args);
|
|
559
598
|
break;
|
|
560
599
|
}
|
|
561
600
|
case 'init': {
|
|
562
601
|
const { cmdInit } = require('./init');
|
|
563
|
-
cmdInit(args[1]);
|
|
602
|
+
cmdInit(args[1], { deprecatedAlias: true });
|
|
564
603
|
break;
|
|
565
604
|
}
|
|
566
605
|
case 'publish': {
|
|
@@ -576,10 +615,10 @@ switch (cmd) {
|
|
|
576
615
|
if (!target) {
|
|
577
616
|
error(
|
|
578
617
|
'Usage:\n' +
|
|
579
|
-
' kdna publish <
|
|
580
|
-
' kdna publish <
|
|
618
|
+
' kdna publish <file.kdna> Publish existing asset, output patch JSON\n' +
|
|
619
|
+
' kdna publish <file.kdna> --release-tag <tag> --repo <owner/name>\n' +
|
|
581
620
|
' ...also upload to GitHub Release\n' +
|
|
582
|
-
' kdna publish --check <path>
|
|
621
|
+
' kdna publish --check <path> Dev source readiness check only',
|
|
583
622
|
);
|
|
584
623
|
}
|
|
585
624
|
cmdPublish(target, args);
|
|
@@ -621,28 +660,14 @@ switch (cmd) {
|
|
|
621
660
|
break;
|
|
622
661
|
}
|
|
623
662
|
case 'studio': {
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
cmdStudioCompile(target, args);
|
|
633
|
-
} else if (sub === 'readiness') {
|
|
634
|
-
const target = args.filter((a) => !a.startsWith('--'))[2];
|
|
635
|
-
if (!target) error('Usage: kdna studio readiness <studio.project.json>');
|
|
636
|
-
cmdStudioReadiness(target, args);
|
|
637
|
-
} else {
|
|
638
|
-
error(
|
|
639
|
-
'Usage:\n' +
|
|
640
|
-
' kdna studio scaffold <name> [--type=cluster] [--minimal]\n' +
|
|
641
|
-
' kdna studio compile <studio.project.json> [--out <dir>]\n' +
|
|
642
|
-
' kdna studio readiness <studio.project.json>',
|
|
643
|
-
EXIT.INPUT_ERROR,
|
|
644
|
-
);
|
|
645
|
-
}
|
|
663
|
+
error(
|
|
664
|
+
'kdna studio has been removed from the runtime CLI.\n' +
|
|
665
|
+
'Trusted KDNA authoring belongs to the standalone Studio CLI:\n' +
|
|
666
|
+
' npm install -g @aikdna/kdna-studio-cli\n' +
|
|
667
|
+
' kdna-studio create <project>\n' +
|
|
668
|
+
' kdna-studio export <project> --out <file.kdna> --sign',
|
|
669
|
+
EXIT.INPUT_ERROR,
|
|
670
|
+
);
|
|
646
671
|
break;
|
|
647
672
|
}
|
|
648
673
|
default:
|
package/src/cmds/_common.js
CHANGED
|
@@ -53,17 +53,18 @@ function usage() {
|
|
|
53
53
|
|
|
54
54
|
Usage:
|
|
55
55
|
|
|
56
|
-
---
|
|
57
|
-
kdna init <name>
|
|
56
|
+
--- Dev source utilities (non-canonical) ---
|
|
57
|
+
kdna init <name> Deprecated alias for kdna dev scaffold <name>
|
|
58
|
+
kdna dev scaffold <name> Scaffold a non-canonical dev source workspace
|
|
58
59
|
kdna dev validate <path> Validate a dev source directory
|
|
59
|
-
kdna dev pack <path> Build a dev
|
|
60
|
+
kdna dev pack <path> Build a dev-only non-trusted .kdna bundle
|
|
60
61
|
kdna dev unpack <path> Unpack .kdna into a dev source directory
|
|
61
62
|
kdna dev inspect <path> Inspect a dev source directory
|
|
62
63
|
kdna dev card <path> Display KDNA Card from a dev source directory
|
|
63
64
|
kdna inspect <file.kdna> Inspect a .kdna asset
|
|
64
|
-
kdna publish <
|
|
65
|
-
kdna publish <
|
|
66
|
-
kdna publish --check <path> Run
|
|
65
|
+
kdna publish <file.kdna> Publish an existing Studio-compiled .kdna asset
|
|
66
|
+
kdna publish <file.kdna> --release-tag <tag> --repo <o/r> ...also upload to GitHub
|
|
67
|
+
kdna publish --check <path> Run dev source readiness checks only
|
|
67
68
|
kdna version bump <patch|minor|major> [path] Bump domain version
|
|
68
69
|
kdna cluster lint <path> Validate a cluster manifest
|
|
69
70
|
|
|
@@ -109,8 +110,8 @@ Examples:
|
|
|
109
110
|
kdna install writing
|
|
110
111
|
kdna verify @aikdna/writing
|
|
111
112
|
kdna available
|
|
112
|
-
kdna
|
|
113
|
-
kdna publish ./my_domain --release-tag v0.1.0 --repo yourname/kdna-my_domain`);
|
|
113
|
+
kdna dev scaffold my_domain
|
|
114
|
+
kdna publish ./dist/my_domain.kdna --release-tag v0.1.0 --repo yourname/kdna-my_domain`);
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
// Exit codes — semantic exit codes for all KDNA CLI commands
|
|
@@ -168,6 +169,62 @@ function loadRegistry() {
|
|
|
168
169
|
return loadCanonicalRegistry({ allowNetwork: true });
|
|
169
170
|
}
|
|
170
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Prompt for a password interactively without echoing to the terminal.
|
|
174
|
+
* Reads from stdin pipe if non-interactive.
|
|
175
|
+
*/
|
|
176
|
+
function promptPassword(question) {
|
|
177
|
+
const tty = require('tty');
|
|
178
|
+
|
|
179
|
+
// Non-interactive: read from stdin pipe
|
|
180
|
+
if (!tty.isatty(process.stdin.fd)) {
|
|
181
|
+
const data = fs.readFileSync(0, 'utf8').trim();
|
|
182
|
+
return data;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
process.stdout.write(question);
|
|
186
|
+
const stdin = process.stdin;
|
|
187
|
+
const wasRaw = stdin.isRaw;
|
|
188
|
+
|
|
189
|
+
if (stdin.setRawMode) {
|
|
190
|
+
stdin.setRawMode(true);
|
|
191
|
+
}
|
|
192
|
+
stdin.resume();
|
|
193
|
+
|
|
194
|
+
let password = '';
|
|
195
|
+
const buffer = Buffer.alloc(1);
|
|
196
|
+
|
|
197
|
+
while (true) {
|
|
198
|
+
fs.readSync(stdin.fd, buffer, 0, 1);
|
|
199
|
+
const ch = buffer[0];
|
|
200
|
+
if (ch === 0x0d || ch === 0x0a) {
|
|
201
|
+
process.stdout.write('\n');
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
if (ch === 0x03) {
|
|
205
|
+
// Ctrl+C
|
|
206
|
+
if (stdin.setRawMode) stdin.setRawMode(!!wasRaw);
|
|
207
|
+
stdin.pause();
|
|
208
|
+
process.exit(130);
|
|
209
|
+
}
|
|
210
|
+
if (ch === 0x7f) {
|
|
211
|
+
// Backspace
|
|
212
|
+
if (password.length > 0) {
|
|
213
|
+
password = password.slice(0, -1);
|
|
214
|
+
process.stdout.write('\b \b');
|
|
215
|
+
}
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
password += String.fromCharCode(ch);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (stdin.setRawMode) {
|
|
222
|
+
stdin.setRawMode(!!wasRaw);
|
|
223
|
+
}
|
|
224
|
+
stdin.pause();
|
|
225
|
+
return password;
|
|
226
|
+
}
|
|
227
|
+
|
|
171
228
|
module.exports = {
|
|
172
229
|
EXIT,
|
|
173
230
|
USER_KDNA_DIR,
|
|
@@ -185,4 +242,5 @@ module.exports = {
|
|
|
185
242
|
selfCheckText,
|
|
186
243
|
isYesNoSelfCheck,
|
|
187
244
|
loadRegistry,
|
|
245
|
+
promptPassword,
|
|
188
246
|
};
|
package/src/cmds/domain.js
CHANGED
|
@@ -213,6 +213,9 @@ function cmdPack(dir, outputDir) {
|
|
|
213
213
|
if (!core) error('KDNA_Core.json not found or invalid');
|
|
214
214
|
if (!pat) error('KDNA_Patterns.json not found or invalid');
|
|
215
215
|
|
|
216
|
+
console.warn('Warning: kdna dev pack creates a dev-only non-trusted .kdna bundle.');
|
|
217
|
+
console.warn('Use KDNA Studio compile/export to create a trusted canonical .kdna asset.');
|
|
218
|
+
|
|
216
219
|
// Human Lock Gate — check judgment-class cards before packing
|
|
217
220
|
const { checkHumanLock } = require('../publish');
|
|
218
221
|
const hl = checkHumanLock(abs);
|
|
@@ -328,11 +331,18 @@ with zipfile.ZipFile(out, 'w', zipfile.ZIP_DEFLATED) as zf:
|
|
|
328
331
|
error(`Cannot create ZIP.\n${hints[platform] || 'Install python3 or zip command.'}`);
|
|
329
332
|
}
|
|
330
333
|
|
|
331
|
-
|
|
334
|
+
// Count KDNA domain files from actual filesystem, not manifest (which may be stale)
|
|
335
|
+
const fileCount = [...KDNA_DOMAIN_FILES].filter((f) => fs.existsSync(path.join(abs, f))).length;
|
|
336
|
+
// Update manifest file_count to match reality
|
|
337
|
+
if (manifest.file_count !== fileCount) {
|
|
338
|
+
manifest.file_count = fileCount;
|
|
339
|
+
writeJson(path.join(abs, 'kdna.json'), manifest);
|
|
340
|
+
}
|
|
332
341
|
console.log(`✓ Packed: ${outPath}`);
|
|
333
342
|
console.log(` Domain: ${domainName} v${manifest.version}`);
|
|
334
343
|
console.log(` Files: ${fileCount} KDNA JSONs`);
|
|
335
344
|
console.log(` Container: ZIP (DEFLATE)`);
|
|
345
|
+
console.log(` Trust: dev-only bundle; not registry-trusted`);
|
|
336
346
|
}
|
|
337
347
|
|
|
338
348
|
// #22: Node.js-native ZIP creator (zero dependencies, fallback when python3/zip unavailable)
|
|
@@ -527,6 +537,7 @@ function inspectKdnaFile(filePath, jsonMode = false) {
|
|
|
527
537
|
status: m.status || 'experimental',
|
|
528
538
|
access: m.access || 'open',
|
|
529
539
|
author: m.author?.name || null,
|
|
540
|
+
authoring: m.authoring || null,
|
|
530
541
|
license: m.license?.type || null,
|
|
531
542
|
created: m.created || c.meta?.created || null,
|
|
532
543
|
description: m.description || c.meta?.purpose || null,
|
|
@@ -558,6 +569,14 @@ function inspectKdnaFile(filePath, jsonMode = false) {
|
|
|
558
569
|
console.log(` Status: ${m.status || 'experimental'}`);
|
|
559
570
|
console.log(` Access: ${m.access || 'open'}`);
|
|
560
571
|
console.log(` Author: ${m.author?.name || '?'}`);
|
|
572
|
+
if (m.authoring) {
|
|
573
|
+
console.log(
|
|
574
|
+
` Authoring: ${m.authoring.created_by || '?'} via ${m.authoring.compiler || m.authoring.authoring_tool || '?'}`,
|
|
575
|
+
);
|
|
576
|
+
console.log(
|
|
577
|
+
` Human Lock: ${m.authoring.human_confirmed ? 'confirmed' : 'unconfirmed'} (${m.authoring.human_lock_count ?? 0})`,
|
|
578
|
+
);
|
|
579
|
+
}
|
|
561
580
|
console.log(` License: ${m.license?.type || '?'}`);
|
|
562
581
|
console.log(` Created: ${m.created || c.meta?.created || '?'}`);
|
|
563
582
|
console.log(` Description: ${m.description || c.meta?.purpose || '?'}`);
|
package/src/cmds/governance.js
CHANGED
|
@@ -246,7 +246,7 @@ function cmdLockCard(args = []) {
|
|
|
246
246
|
const projectPath = path.resolve('studio.project.json');
|
|
247
247
|
if (!fs.existsSync(projectPath)) {
|
|
248
248
|
error(
|
|
249
|
-
'No studio.project.json found in current directory. Run: kdna
|
|
249
|
+
'No studio.project.json found in current directory. Run: kdna-studio create',
|
|
250
250
|
EXIT.INPUT_ERROR,
|
|
251
251
|
);
|
|
252
252
|
}
|