@aikdna/kdna-core 0.18.0 → 0.19.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +128 -94
  2. package/README.md +109 -215
  3. package/package.json +7 -2
  4. package/schema/agent-host-capabilities.schema.json +62 -0
  5. package/schema/agent-host-receipt.schema.json +371 -0
  6. package/schema/agent-host-request.schema.json +223 -0
  7. package/schema/{bundle-profile-v1.schema.json → bundle-profile.schema.json} +9 -5
  8. package/schema/checksums.schema.json +8 -8
  9. package/schema/consumption-plan.schema.json +428 -0
  10. package/schema/digest-evidence.schema.json +115 -26
  11. package/schema/{kdna-envelope-external-grant-v1.schema.json → external-grant-envelope.schema.json} +17 -4
  12. package/schema/{kdna-key-grant-v1.schema.json → external-key-grant.schema.json} +39 -7
  13. package/schema/judgment-trace.schema.json +1251 -0
  14. package/schema/load-plan.schema.json +5 -3
  15. package/schema/manifest.schema.json +70 -10
  16. package/schema/{payload-profile-v1.schema.json → payload-profile.schema.json} +30 -6
  17. package/schema/{runtime-capsule-2.schema.json → runtime-capsule.schema.json} +7 -31
  18. package/src/asset-reader.js +8 -2
  19. package/src/{v1 → container}/index.js +385 -198
  20. package/src/container/index.mjs +20 -0
  21. package/src/container-dispatcher.js +6 -6
  22. package/src/crypto-profile.js +37 -107
  23. package/src/external-key-grant.js +41 -15
  24. package/src/index.js +11 -8
  25. package/src/index.mjs +49 -45
  26. package/src/loader-compatibility.js +59 -0
  27. package/src/loader.js +1 -1
  28. package/src/public-api.js +5 -5
  29. package/src/remote-runtime.d.ts +13 -0
  30. package/src/remote-runtime.js +27 -0
  31. package/src/remote-runtime.mjs +3 -0
  32. package/src/runtime-api.js +5 -5
  33. package/src/{capsule-v2.js → runtime-capsule.js} +96 -254
  34. package/src/{execution-contract-v1.js → runtime-contract.js} +184 -152
  35. package/src/types.d.ts +200 -277
  36. package/src/workpack-pure.js +1 -1
  37. package/schema/agent-host-2-receipt.schema.json +0 -206
  38. package/schema/agent-host-2-request.schema.json +0 -135
  39. package/schema/agent-host-capabilities-1.schema.json +0 -40
  40. package/schema/consumption-plan-1.schema.json +0 -280
  41. package/schema/judgment-trace-1.schema.json +0 -748
  42. package/schema/runtime-capsule-1.schema.json +0 -68
  43. package/src/lint-pure.js +0 -433
  44. package/src/v1/index.mjs +0 -21
package/README.md CHANGED
@@ -1,50 +1,38 @@
1
1
  # @aikdna/kdna-core
2
2
 
3
- Core library for `.kdna` judgment assets. It implements the single KDNA Asset
4
- Container, strict-CBOR payload decoding, validation, LoadPlan authorization,
5
- and Runtime Capsule projection used by the CLI, Studio, skills, MCP
6
- integrations, and downstream Agent runtimes.
3
+ Core library for packaged `.kdna` judgment assets. It implements one current
4
+ container contract, authorization planning, integrity evidence, Runtime Capsule
5
+ projection, and the correlated Agent Host execution boundary.
7
6
 
8
- ## Installation
7
+ ## Install
9
8
 
10
9
  ```bash
11
10
  npm install @aikdna/kdna-core
12
11
  ```
13
12
 
14
- If you need full JSON Schema validation through Ajv, also install:
13
+ ## Pack, validate, plan, and load
15
14
 
16
- ```bash
17
- npm install ajv ajv-formats
18
- ```
19
-
20
- ## Public API
21
-
22
- Use the package root. Version-qualified entrypoints and API names are not part
23
- of the public contract.
15
+ Use the package root. Version-qualified entry points and parallel generation
16
+ APIs are not part of the public contract.
24
17
 
25
18
  ```js
26
19
  const {
27
- inspect,
20
+ pack,
28
21
  validate,
29
22
  planLoad,
30
23
  loadAuthorized,
31
- loadCapsuleV2,
32
- computeDigestEvidence,
33
- computeCapsuleDeliveryDigest,
34
- adaptCapsuleV2ToV1,
35
- pack,
36
- unpack,
37
- buildChecksums,
38
24
  } = require('@aikdna/kdna-core');
39
25
 
26
+ pack('./authoring-source', './asset.kdna');
27
+
40
28
  const validation = validate('./asset.kdna');
41
29
  if (!validation.overall_valid) {
42
30
  throw new Error(validation.problems.join('\n'));
43
31
  }
44
32
 
45
33
  const plan = planLoad('./asset.kdna');
46
- if (plan.can_load_now !== true) {
47
- throw new Error(`Asset is not loadable yet: ${plan.required_action}`);
34
+ if (!plan.can_load_now) {
35
+ throw new Error(`Asset is not loadable: ${plan.required_action}`);
48
36
  }
49
37
 
50
38
  const capsule = loadAuthorized('./asset.kdna', {
@@ -52,230 +40,136 @@ const capsule = loadAuthorized('./asset.kdna', {
52
40
  as: 'json',
53
41
  });
54
42
 
55
- if (capsule.type !== 'kdna.context.capsule') {
56
- throw new Error('Expected a Runtime Capsule');
43
+ if (
44
+ capsule.type !== 'kdna.runtime-capsule' ||
45
+ capsule.contract_version !== '0.1.0'
46
+ ) {
47
+ throw new Error('Unexpected Runtime Capsule contract');
57
48
  }
58
49
  ```
59
50
 
60
- Capsule 2 is opt-in. It exposes A/C/E under distinct digest members while the
61
- default Runtime API remains on the frozen Capsule 1 contract:
62
-
63
- ```js
64
- const expectedA = {
65
- value: 'sha256:<64 lowercase hex>',
66
- source: 'install_receipt',
67
- };
68
-
69
- const evidence = computeDigestEvidence('./asset.kdna', {
70
- expectedDigests: {
71
- asset: expectedA,
72
- },
73
- });
74
-
75
- const capsule2 = loadCapsuleV2('./asset.kdna', {
76
- profile: 'compact',
77
- expectedDigests: {
78
- asset: expectedA,
79
- },
80
- });
81
-
82
- const deliveryDigest = computeCapsuleDeliveryDigest(capsule2);
83
- const legacyCapsule = adaptCapsuleV2ToV1(capsule2);
84
- ```
51
+ Runtime entry points accept final packaged bytes or a packaged file. Authoring
52
+ directories must be packed before they can produce a Runtime Capsule.
85
53
 
86
- ConsumptionPlan 1, Agent Host 2, and JudgmentTrace 1 are opt-in APIs in
87
- `@aikdna/kdna-core@0.18.0`. Plan 1 accepts only Capsule 2 plus Host 2: it has no
88
- downgrade or legacy adapter. The default Runtime path remains Capsule 1,
89
- ConsumptionPlan 0.9, and Agent Host 1. The opt-in builders derive
90
- protocol-owned members, while every verifier receives a non-null trusted Plan
91
- digest and independently observed capabilities, request, receipt, and delivery
92
- state as explicit context:
54
+ `compatibility.min_loader_version` is a strict `x.y.z` loader package
55
+ coordinate. `inspect` and `validate` expose it together with
56
+ `loader_version` and `loader_compatible`. Structural validation remains
57
+ separate from loadability: `planLoad` and every load path block a valid asset
58
+ that requires a newer loader with `KDNA_LOADER_VERSION_UNSUPPORTED` before
59
+ projection.
93
60
 
94
- ```js
95
- const {
96
- parseExecutionContractJsonV1,
97
- buildConsumptionPlanV1,
98
- buildAgentHost2RequestV1,
99
- buildPreHostBudgetBlockedTraceV1,
100
- validatePreHostBudgetBlockedTraceV1,
101
- validateAgentHost2ReceiptV1,
102
- buildJudgmentTraceV1,
103
- } = require('@aikdna/kdna-core');
61
+ ## Stable Runtime contracts
104
62
 
105
- const plan = buildConsumptionPlanV1({
106
- plan_id: 'plan_0123456789abcdef',
107
- created_at: new Date().toISOString(),
108
- task,
109
- asset_ref,
110
- projection_profile: 'compact',
111
- budget,
112
- constraints: { enforce_before_host: true, reject_on_exceed: true },
113
- trace_policy: { emit: true, storage: 'session' },
114
- });
63
+ There is one current responsibility chain:
115
64
 
116
- const executionContext = {
117
- plan,
118
- trustedPlanDigest: plan.integrity.plan_digest,
119
- capabilities: observedHostCapabilities,
120
- coreCapsuleVersions: ['2.0', '1.0'],
121
- };
122
- const request = buildAgentHost2RequestV1(
123
- { request_id: 'host_0123456789abcdef01234567', capsule: capsule2 },
124
- executionContext,
125
- );
126
-
127
- // Parse raw Host JSON before object-level Schema/correlation validation.
128
- const receipt = parseExecutionContractJsonV1(rawReceiptBytes);
129
- const receiptValidation = validateAgentHost2ReceiptV1(receipt, { request });
130
- if (!receiptValidation.valid) throw new Error(receiptValidation.code);
131
-
132
- const trace = buildJudgmentTraceV1(traceInput, {
133
- ...executionContext,
134
- request,
135
- receipt,
136
- trustedDeliveryObservation: 'host_receipt',
137
- });
65
+ ```text
66
+ packaged .kdna
67
+ → validate
68
+ → planLoad
69
+ → authorize
70
+ → Runtime Capsule
71
+ → Consumption Plan
72
+ → Agent Host request and correlated receipt
73
+ → Judgment Trace
138
74
  ```
139
75
 
140
- When no receipt exists, Trace construction requires the caller to state the
141
- trusted observation explicitly as `not_delivered` or `not_observed`; request
142
- existence alone is not treated as delivery evidence.
76
+ Every KDNA-owned contract uses an explicit compatibility coordinate:
143
77
 
144
- If Capsule projection succeeded but the exact projection or task character
145
- count exceeds the Plan budget, `buildAgentHost2RequestV1()` fails closed and
146
- must not be bypassed. Use the dedicated evidence-only terminal instead:
78
+ | Contract | Identity | Compatibility coordinate |
79
+ | --- | --- | --- |
80
+ | Container manifest | `format_version` | `0.1.0` |
81
+ | Payload profile | `profile` + `profile_version` | `kdna.payload.judgment` + `0.1.0` |
82
+ | Runtime Capsule | `type` + `contract_version` | `kdna.runtime-capsule` + `0.1.0` |
83
+ | Consumption Plan | `type` + `contract_version` | `kdna.consumption-plan` + `0.1.0` |
84
+ | Agent Host | `protocol` + `protocol_version` | `kdna.agent-host` + `0.1.0` |
85
+ | Judgment Trace | `type` + `contract_version` | `kdna.judgment-trace` + `0.1.0` |
147
86
 
148
- ```js
149
- const blockedTrace = buildPreHostBudgetBlockedTraceV1(
150
- {
151
- trace_id: 'trace_0123456789abcdef',
152
- timestamp: new Date().toISOString(),
153
- capsule: capsule2,
154
- },
155
- executionContext,
156
- );
157
-
158
- const blockedValidation = validatePreHostBudgetBlockedTraceV1(blockedTrace, {
159
- ...executionContext,
160
- capsule: capsule2,
161
- });
162
- if (!blockedValidation.valid) throw new Error(blockedValidation.code);
163
- ```
87
+ There is no public adapter between competing Capsule or Host generations.
88
+ Unsupported compatibility coordinates fail closed.
164
89
 
165
- This API returns only a `blocked` / `not_delivered` Trace with a fixed budget
166
- error. It retains A/C/E, sender P, projection profile, exact character actuals,
167
- and `exceeded` comparison, but it never exposes an over-budget Host request or
168
- a request ID. Calling it when neither projection nor task is over budget is an
169
- error.
170
-
171
- `parseExecutionContractJsonV1()` is the raw protocol boundary. It rejects
172
- duplicate decoded object keys, invalid UTF-8, BOMs, non-scalar Unicode,
173
- non-finite numbers, trailing input, and non-RFC JSON grammar before an object
174
- validator runs. Its default limits are 2 MiB and 64 nested containers;
175
- `maxBytes` and `maxDepth` may only tighten those limits. Error
176
- `code_unit_offset` details are UTF-16 code-unit indexes, not UTF-8 byte
177
- offsets. Parsed object validators cannot reconstruct overwritten duplicate
178
- keys, invalid original bytes, or a stripped BOM, so Host adapters must not use
179
- plain `JSON.parse()` for untrusted protocol messages.
180
-
181
- An A, C, or E mismatch is returned as evidence by `computeDigestEvidence()`
182
- and blocks `loadCapsuleV2()` with a digest-specific error. The adapter always
183
- maps E to Capsule 1 `asset_digest`; it never substitutes A or C. Core computes
184
- E from the raw Runtime manifest and payload bytes even when `checksums.json` is
185
- absent, in which case E is reported as `not_compared`.
186
- Internal manifest/checksum declarations are checked before independent
187
- expected values, so a receipt match cannot conceal a bad declaration or
188
- conflicting digest alias. The adapter also preserves the four frozen Capsule 1
189
- inheritance/dependency/RAG extension fields through
190
- `compatibility.capsule_1_extensions` without giving them Capsule 2 authority.
191
- It preserves only the legacy access aliases `open`, `protected`, and `runtime`
192
- through `compatibility.capsule_1_access`; Capsule 2 itself always uses
193
- `public`, `licensed`, or `remote`. These values must map exactly as
194
- `open`/`public`, `protected`/`licensed`, and `runtime`/`remote`; the builder and
195
- adapter reject any mismatched pair. The public builder rejects a Capsule 1 value
196
- whose domain, judgment version, access, or E does not match the supplied
197
- manifest and digest evidence.
198
-
199
- ## Supported Runtime Flow
90
+ ## Digest responsibilities
200
91
 
201
- ```text
202
- .kdna file
203
- → validate
204
- → planLoad
205
- → loadAuthorized
206
- → Runtime Capsule
207
- → Agent/runtime context
208
- ```
92
+ Core keeps four digest bases separate:
209
93
 
210
- The default compact Capsule preserves the asset's scoped judgment context:
211
- `highest_question`, `worldview`, ordered `value_order`, `judgment_role`,
212
- applicability-aware axioms, boundaries, self-checks, failure modes, and a
213
- bounded pattern set. Core copies the three optional scoped fields without
214
- trimming, reordering, or treating them as facts, policy, or quality evidence.
94
+ - **A** — final packaged container bytes;
95
+ - **C** — the canonical content tree;
96
+ - **E** — the raw `kdna.json` and `payload.kdnab` runtime entry set;
97
+ - **P** — the canonical Runtime Capsule delivered to a Host.
215
98
 
216
- For authoring and test fixtures, `pack()` can turn a local working folder into
217
- a `.kdna` file before validation:
99
+ Use `computeDigestEvidence()` for A/C/E and
100
+ `computeCapsuleDeliveryDigest()` for P. A grant or registry expectation for A
101
+ must never be compared with E from `checksums.json`.
218
102
 
219
- ```text
220
- local working folder
221
- → pack
222
- → .kdna file
223
- → validate
224
- → planLoad
225
- → loadAuthorized
226
- ```
103
+ ## Consumption and Host execution
227
104
 
228
- ## KDNA Asset Container
105
+ `buildConsumptionPlan()` creates the single-asset execution plan and its
106
+ detached integrity digest. `buildAgentHostRequest()` validates the accepted
107
+ Plan digest, observed Host capabilities, Capsule compatibility coordinate,
108
+ task, asset identity, budgets, and P before producing a request.
229
109
 
230
- A `.kdna` asset contains:
110
+ Untrusted Host JSON must enter through `parseRuntimeContractJson()` before
111
+ object validation. It rejects duplicate keys, invalid UTF-8, non-JSON numeric
112
+ values, trailing input, and excessive input before correlation checks run.
231
113
 
232
- - `mimetype`
233
- - `kdna.json`
234
- - `payload.kdnab`
235
- - `checksums.json`
114
+ `buildJudgmentTrace()` records delivery, Host execution, budget, result, and
115
+ error evidence. A correlated receipt proves a technical boundary event; it
116
+ does not prove semantic consumption, behavioral influence, judgment quality,
117
+ or model conformance.
236
118
 
237
- `validate()` checks:
119
+ If the exact projection or task exceeds an enforceable pre-Host budget,
120
+ `buildAgentHostRequest()` fails closed. Use
121
+ `buildPreHostBudgetBlockedTrace()` to retain a terminal evidence record without
122
+ creating a deliverable Host request.
238
123
 
239
- - format
240
- - manifest schema
241
- - payload parseability
242
- - checksum consistency
243
- - load-profile contract
124
+ ## Licensed account/device grants
244
125
 
245
- `payload.kdnab` is CBOR. A password-protected or licensed asset stores a CBOR
246
- encryption envelope in the same entry; authorized plaintext is decrypted in
247
- memory and projected into the Runtime Capsule.
126
+ `authorizeExternalKeyGrant()` verifies the issuer signature, time window,
127
+ status, account, device, final packaged asset digest A, and encrypted entry.
128
+ It returns a branded entitlement and an in-memory decrypt hook. A plain object
129
+ such as `{ status: 'active' }` is not authorization.
248
130
 
249
- ### Account/device external grants
131
+ Keep device private keys in the platform secret store, dispose the returned
132
+ session after loading, and expose only the Runtime Capsule to Agent-facing
133
+ callers. Account grants never silently fall back to password authorization.
250
134
 
251
- RFC-0019 licensed assets can keep the encrypted container publicly available
252
- while an issuer grants independent account/device access. `authorizeExternalKeyGrant()`
253
- verifies the issuer signature, lease, revocation state, account, device, asset
254
- UID/version/digest, and encrypted entry before returning a branded entitlement
255
- and in-memory decrypt hook. A plain `{status: "active"}` object is not accepted.
135
+ ## Projection profiles
256
136
 
257
- Device private keys belong in the platform SecretStore. The returned session
258
- must be disposed after loading; Agent-facing callers should receive only the
259
- Runtime Capsule. Account grants never fall back to the password profile.
137
+ `loadAuthorized()` supports `index`, `compact`, `scenario`, and `full`, with
138
+ `json` or `prompt` output. The requested profile controls the emitted context
139
+ shape; implementations must not label one projection as another.
260
140
 
261
- ## Load Profiles
141
+ ## Deployer-controlled remote Runtime
262
142
 
263
- `loadAuthorized()` supports:
143
+ Ordinary consumers always receive `needs_runtime` / `connect_runtime` when an
144
+ asset declares `access: "remote"`. A deployer that physically controls the
145
+ server-side packaged asset uses the separate package subpath:
264
146
 
265
- - `index`
266
- - `compact`
267
- - `scenario`
268
- - `full`
147
+ ```js
148
+ const {
149
+ loadRemoteRuntimeAsset,
150
+ } = require('@aikdna/kdna-core/remote-runtime');
151
+
152
+ const fullCapsule = loadRemoteRuntimeAsset('./deployed-judgment.kdna');
153
+ ```
269
154
 
270
- Output formats:
155
+ The function accepts one final packaged file path or packaged byte buffer. It
156
+ validates and plans one immutable byte snapshot, accepts only a single remote
157
+ asset, and returns a full JSON Runtime Capsule for the server's projection
158
+ engine. It does not accept caller-selected access, profile, output, dependency,
159
+ or inheritance options.
271
160
 
272
- - `json`
273
- - `prompt`
161
+ Possession of the deployed asset is the authorization boundary for this
162
+ server-side API. The API does not authenticate network callers, verify their
163
+ entitlements, make plaintext confidential from the deployer, minimize the
164
+ projection returned to a client, or provide an AIKDNA-hosted service. The
165
+ embedding Runtime must implement those request and disclosure controls and
166
+ must never return the full server-side Capsule to an Agent client.
274
167
 
275
168
  ## Boundary
276
169
 
277
- KDNA Core is content-neutral. It validates file structure and loadability;
278
- it does not rank judgment quality or endorse specific assets.
170
+ Core validates technical structure, integrity, authorization, compatibility,
171
+ and observed execution facts. It does not rank judgment quality, endorse an
172
+ asset, or claim that a model understood or followed loaded judgment.
279
173
 
280
174
  ## License
281
175
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikdna/kdna-core",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "description": "KDNA Core library for validating, planning, and loading local .kdna judgment assets.",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -14,6 +14,11 @@
14
14
  "require": "./src/index.js",
15
15
  "types": "./src/types.d.ts"
16
16
  },
17
+ "./remote-runtime": {
18
+ "import": "./src/remote-runtime.mjs",
19
+ "require": "./src/remote-runtime.js",
20
+ "types": "./src/remote-runtime.d.ts"
21
+ },
17
22
  "./package.json": "./package.json",
18
23
  "./schema/*": "./schema/*"
19
24
  },
@@ -21,7 +26,7 @@
21
26
  "scripts": {
22
27
  "test": "node ../../scripts/run-node-tests.js test/*.test.js && node -e \"const m = require('./src/index.js'); console.log('kdna-core exports:', Object.keys(m).join(', '));\"",
23
28
  "prepublishOnly": "npm run release:check",
24
- "release:check": "node scripts/check-release-readiness.js",
29
+ "release:check": "node ../../scripts/check-post-cutover-naming.mjs && node scripts/check-release-readiness.js",
25
30
  "publish:guard": "node scripts/check-publish-duplicate.js"
26
31
  },
27
32
  "files": [
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/aikdna/kdna/specs/agent-host-capabilities.schema.json",
4
+ "title": "KDNA Agent Host Capabilities",
5
+ "description": "Orthogonal capabilities observed before Runtime contract execution.",
6
+ "type": "object",
7
+ "required": [
8
+ "type",
9
+ "protocol_version",
10
+ "capability_basis",
11
+ "host_protocols",
12
+ "capsule_versions",
13
+ "capsule_digest_profiles",
14
+ "capsule_digest_profile_versions"
15
+ ],
16
+ "additionalProperties": false,
17
+ "properties": {
18
+ "type": {
19
+ "const": "kdna.agent-host-capabilities"
20
+ },
21
+ "capability_basis": {
22
+ "enum": ["registered_descriptor", "legacy_assumption"]
23
+ },
24
+ "host_protocols": {
25
+ "type": "array",
26
+ "minItems": 1,
27
+ "uniqueItems": true,
28
+ "items": {
29
+ "enum": ["kdna.agent-host"]
30
+ }
31
+ },
32
+ "capsule_versions": {
33
+ "type": "array",
34
+ "minItems": 1,
35
+ "uniqueItems": true,
36
+ "items": {
37
+ "enum": ["0.1.0"]
38
+ }
39
+ },
40
+ "capsule_digest_profiles": {
41
+ "type": "array",
42
+ "uniqueItems": true,
43
+ "items": {
44
+ "const": "kdna.canonicalization.runtime-capsule-jcs"
45
+ }
46
+ },
47
+ "protocol_version": {
48
+ "const": "0.1.0"
49
+ },
50
+ "capsule_digest_profile_versions": {
51
+ "type": "array",
52
+ "prefixItems": [
53
+ {
54
+ "const": "0.1.0"
55
+ }
56
+ ],
57
+ "items": false,
58
+ "minItems": 1,
59
+ "maxItems": 1
60
+ }
61
+ }
62
+ }