@aikdna/kdna-core 0.16.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/CHANGELOG.md +164 -2
- package/README.md +151 -2
- package/package.json +3 -2
- package/schema/agent-host-2-receipt.schema.json +206 -0
- package/schema/agent-host-2-request.schema.json +135 -0
- package/schema/agent-host-capabilities-1.schema.json +40 -0
- package/schema/checksums.schema.json +40 -1
- package/schema/consumption-plan-1.schema.json +280 -0
- package/schema/digest-evidence.schema.json +123 -0
- package/schema/judgment-trace-1.schema.json +748 -0
- package/schema/load-plan.schema.json +2 -2
- package/schema/manifest.schema.json +4 -5
- package/schema/payload-profile-v1.schema.json +25 -0
- package/schema/runtime-capsule-1.schema.json +68 -0
- package/schema/runtime-capsule-2.schema.json +140 -0
- package/src/asset-reader.js +100 -120
- package/src/capsule-v2.js +687 -0
- package/src/container-dispatcher.js +4 -1
- package/src/execution-contract-v1.js +1850 -0
- package/src/index.js +4 -0
- package/src/index.mjs +136 -21
- package/src/lint-pure.js +6 -3
- package/src/public-api.js +59 -163
- package/src/runtime-api.js +5 -6
- package/src/types.d.ts +1181 -113
- package/src/v1/index.js +298 -56
- package/src/v1/index.mjs +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,156 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.18.0 (2026-07-15)
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Add opt-in Runtime Capsule 2 Core primitives, formal Capsule 1/Capsule 2 and
|
|
8
|
+
digest-evidence schemas, RFC 8785 JCS delivery hashing, deterministic
|
|
9
|
+
v2-to-v1 adaptation, and committed A/C/E/P conformance goldens. Existing
|
|
10
|
+
Runtime load entry points continue to emit frozen Capsule 1 values.
|
|
11
|
+
- Accept independent expected A/C/E values through `expectedDigests` and block
|
|
12
|
+
Capsule 2 emission with digest-specific mismatch codes.
|
|
13
|
+
- Preserve the four frozen Capsule 1 inheritance, dependency, and RAG
|
|
14
|
+
extension fields through the one-way Capsule 2 compatibility member.
|
|
15
|
+
- Define strict opt-in ConsumptionPlan 1.0, Agent Host 2, capability, runtime
|
|
16
|
+
receipt, and authoritative JudgmentTrace 1.0 schemas. Add committed
|
|
17
|
+
negotiation, plan/P recomputation, five-terminal Trace, exact-budget,
|
|
18
|
+
source-directory block, required-null, and cross-document tamper conformance
|
|
19
|
+
vectors. Plan 1 formally supports only Capsule 2 plus Host 2 and has no
|
|
20
|
+
downgrade or adapter; runtime defaults remain Plan 0.9, Capsule 1, and Host 1.
|
|
21
|
+
- Bind Trace elapsed evidence to the correlated Host receipt, make
|
|
22
|
+
unobserved finite limits propagate to an honest `not_observed` overall
|
|
23
|
+
comparison, and record Host-side P mismatch as a correlated pre-execution
|
|
24
|
+
rejection instead of an impossible terminal state.
|
|
25
|
+
- Expose the strict opt-in ConsumptionPlan 1, Agent Host 2, budget-evidence,
|
|
26
|
+
and JudgmentTrace 1 builders and validators from CJS, ESM, and TypeScript.
|
|
27
|
+
The conformance runner now consumes this single packaged implementation.
|
|
28
|
+
- Add a dedicated pre-Host budget-blocked Trace builder and validator. They
|
|
29
|
+
preserve projected A/C/E/P, profile, and exact character evidence without
|
|
30
|
+
exposing an over-budget Host request; calls within budget fail closed.
|
|
31
|
+
- Add a bounded raw execution-contract JSON parser that rejects duplicate
|
|
32
|
+
decoded keys, invalid UTF-8 and Unicode, BOMs, hostile-key prototype
|
|
33
|
+
mutation, non-finite numbers, and trailing or non-RFC JSON input before
|
|
34
|
+
Host 2 object validation.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- Converge the compatibility names `inspectKDNA`, `validateKDNA`, and
|
|
39
|
+
`loadKDNA` on the current unversioned Runtime implementation. Validation now
|
|
40
|
+
returns the current five format/schema/payload/checksum/load-contract gates,
|
|
41
|
+
and loading returns a Runtime Capsule; the old source-tree validation and
|
|
42
|
+
`{domain, context}` result shapes are no longer synthesized for current
|
|
43
|
+
assets.
|
|
44
|
+
- Make CJS, ESM, and TypeScript declarations expose the same compatibility
|
|
45
|
+
names and current return contracts.
|
|
46
|
+
- Accept `.kdna` bytes in memory across current inspect, validate, LoadPlan,
|
|
47
|
+
and load paths. Buffer verification does not extract or materialize the
|
|
48
|
+
asset on disk.
|
|
49
|
+
- Read packaged file paths once at load entry so LoadPlan authorization and
|
|
50
|
+
Runtime Capsule projection use the same immutable bytes. The default load
|
|
51
|
+
result is a Runtime Capsule, matching explicit `as: "json"`.
|
|
52
|
+
- Make `composeKDNA` fail closed with
|
|
53
|
+
`KDNA_COMPOSE_PROTOCOL_UNAVAILABLE` until current Cluster/Capsule
|
|
54
|
+
composition semantics are defined; it no longer returns a misleading empty
|
|
55
|
+
composition.
|
|
56
|
+
- Identify `schema/manifest.schema.json` as the sole Runtime manifest schema.
|
|
57
|
+
The older `schema/kdna-manifest.json` remains only for explicit legacy-source
|
|
58
|
+
migration. Runtime `language` remains valid and `creator` provenance remains
|
|
59
|
+
optional, while an explicitly declared creator still requires a non-empty
|
|
60
|
+
name.
|
|
61
|
+
|
|
62
|
+
### Fixed
|
|
63
|
+
|
|
64
|
+
- Restrict Core publication to canonical `kdna-core-v*` published-release
|
|
65
|
+
events, require the exact version tag to identify the workflow commit, and
|
|
66
|
+
make already-published versions idempotent only when registry `gitHead` and
|
|
67
|
+
artifact integrity and SHA-1 shasum match the current release evidence. Only
|
|
68
|
+
npm's structured, exact-version `No match found` response is treated as an
|
|
69
|
+
unpublished version; missing packages, authorization/registry errors,
|
|
70
|
+
missing identity, malformed digests, or a different artifact fail closed
|
|
71
|
+
instead of being treated as a successful duplicate.
|
|
72
|
+
- Report an unavailable GitHub Release lookup as an explicit non-gating
|
|
73
|
+
`SKIP`, rather than wrapping the skipped observation in a misleading
|
|
74
|
+
readiness `PASS`. Remove unused downstream repository checkouts from the
|
|
75
|
+
Core publish job.
|
|
76
|
+
- Make the ESM root and TypeScript declarations expose every existing CJS
|
|
77
|
+
public value, including the crypto, external-grant, Work Pack, composition,
|
|
78
|
+
container, and semver helpers. Permanent source and packed-install checks now
|
|
79
|
+
block entrypoint drift.
|
|
80
|
+
- Model the complete Argon2id password-KDF descriptor and require a machine
|
|
81
|
+
fingerprint when the unified decrypt API receives a legacy or profile-unknown
|
|
82
|
+
envelope. Package tests now isolate every npm operation from the user cache
|
|
83
|
+
and keep pack caches separate from a provably empty offline-install cache.
|
|
84
|
+
Third-party dependency fixtures are packed from script-free temporary copies,
|
|
85
|
+
so package-manager lifecycle behavior cannot introduce network or build-tool
|
|
86
|
+
dependencies into the offline release gate.
|
|
87
|
+
- Require a non-null independently trusted Plan digest throughout the strict
|
|
88
|
+
Plan 1 / Host 2 chain, snapshot hostile validation contexts without invoking
|
|
89
|
+
accessors, and keep pre-Host budget enforcement unavailable as a public
|
|
90
|
+
bypass option.
|
|
91
|
+
- Require matched Host receipts to correlate sender, Host-recomputed, echoed,
|
|
92
|
+
and actual Capsule delivery digests. Trace construction now requires an
|
|
93
|
+
explicit trusted delivery observation when no receipt exists, distinguishing
|
|
94
|
+
`not_delivered` from `not_observed` without inferring either from a request.
|
|
95
|
+
- Check internal C/E declarations and canonical/legacy alias agreement before
|
|
96
|
+
independent expected values, so external matches cannot hide conflicting
|
|
97
|
+
asset declarations.
|
|
98
|
+
- Validate public Capsule 2 builder and adapter inputs and outputs against the
|
|
99
|
+
packaged schemas and cross-field success invariants.
|
|
100
|
+
- Preserve only the frozen Capsule 1 access aliases `open`, `protected`, and
|
|
101
|
+
`runtime` for exact adapter parity while keeping Capsule 2 access canonical;
|
|
102
|
+
fail closed if compatibility metadata pairs an alias with the wrong
|
|
103
|
+
canonical access.
|
|
104
|
+
- Compute Capsule 1 E directly from Runtime manifest and payload bytes when
|
|
105
|
+
checksums are absent, share the same pure E implementation across checksum
|
|
106
|
+
build/verify and both Capsule generations, and reject Capsule 1 builder
|
|
107
|
+
inputs that disagree with their manifest or digest evidence.
|
|
108
|
+
- Sort canonical content-tree and signing entry paths by UTF-8 bytes while
|
|
109
|
+
retaining the existing UTF-16 JSON object-key order. U+E000/U+10000 vectors
|
|
110
|
+
freeze the distinction.
|
|
111
|
+
|
|
112
|
+
- Make stable verification fail closed on malformed CBOR, invalid current
|
|
113
|
+
manifests, checksum mismatches, and forbidden legacy plaintext containers,
|
|
114
|
+
while preserving whole-file `asset_digest`, canonical `content_digest`, and
|
|
115
|
+
existing expected-digest/signature hooks.
|
|
116
|
+
- Make direct `createKdnaAssetReader().loadProfile*` return the current Runtime
|
|
117
|
+
Capsule instead of silently returning `domain: null`; legacy `readDataMap*`
|
|
118
|
+
now fails explicitly rather than pretending current payloads are old source
|
|
119
|
+
files.
|
|
120
|
+
|
|
121
|
+
## v0.17.0 (2026-07-14)
|
|
122
|
+
|
|
123
|
+
### Added
|
|
124
|
+
|
|
125
|
+
- Structurally validate optional payload `worldview`, ordered `value_order`,
|
|
126
|
+
and `judgment_role`, then preserve their declared values in the compact
|
|
127
|
+
Runtime Capsule instead of silently dropping them. Compact prompt projection
|
|
128
|
+
renders worldview, value order, and the standard role fields `acts_as`,
|
|
129
|
+
`does_not_act_as`, and `responsibility`; role extension fields remain
|
|
130
|
+
available in the JSON Capsule without an unsupported prompt claim.
|
|
131
|
+
- Add a synthetic Golden Single-Asset Core fixture. It proves schema,
|
|
132
|
+
validation, content-neutral inspect, and exact compact projection only; it
|
|
133
|
+
does not claim author quality, task applicability, model consumption, or
|
|
134
|
+
conformance.
|
|
135
|
+
|
|
136
|
+
### Changed
|
|
137
|
+
|
|
138
|
+
- Make Runtime `creator` provenance optional. When it is declared,
|
|
139
|
+
`creator.name` remains required and non-empty; when provenance is unavailable,
|
|
140
|
+
producers omit the block instead of inventing an anonymous or `Unknown`
|
|
141
|
+
identity. This does not weaken authoring-source identity rules or turn
|
|
142
|
+
provenance into a trust claim.
|
|
143
|
+
- Keep canonical and packaged Runtime manifest/payload schemas aligned with the
|
|
144
|
+
creator and scoped-judgment contracts.
|
|
145
|
+
|
|
146
|
+
### Fixed
|
|
147
|
+
|
|
148
|
+
- Make ecosystem truth validation fail closed when a live component has
|
|
149
|
+
neither package/artifact evidence nor a verifiable repository checkout,
|
|
150
|
+
instead of silently accepting missing external evidence.
|
|
151
|
+
- Derive web-package readiness expectations from the declared current Core
|
|
152
|
+
version rather than a stale hard-coded release number.
|
|
153
|
+
|
|
3
154
|
## v0.16.0 (2026-07-13)
|
|
4
155
|
|
|
5
156
|
### Added
|
|
@@ -141,7 +292,6 @@ Story 6 — dependencies runtime. Supports semver-matching local/registry depend
|
|
|
141
292
|
- **Topological Sorting Resolver**: Added a robust, pure post-order DFS topological sorter with circular cycle, missing dependency, and version range mismatch checks.
|
|
142
293
|
- **Topological Prompt Composition**: Enabled recursive, multi-domain prompt composition and flat topological JSON return inside `loadAuthorized`.
|
|
143
294
|
|
|
144
|
-
|
|
145
295
|
## v0.15.6 (2026-06-28)
|
|
146
296
|
|
|
147
297
|
Story 5 — Bundle payload type. Bumps KDNA manifest format schema to v2, introduces bundle-profile-v1 payload profile, and starts KDNA v1 format deprecation window.
|
|
@@ -150,7 +300,6 @@ Story 5 — Bundle payload type. Bumps KDNA manifest format schema to v2, introd
|
|
|
150
300
|
- **V2 Schema support:** bumped manifest schema version to v2.0, supporting `kdna_version` as `"2.0"`.
|
|
151
301
|
- **Bundle profile support:** added `bundle-profile-v1` payload profile and validator.
|
|
152
302
|
|
|
153
|
-
|
|
154
303
|
## v0.15.5 (2026-06-28)
|
|
155
304
|
|
|
156
305
|
Phase 12 audit follow-up. Closes 3 issues filed against this
|
|
@@ -198,6 +347,7 @@ signature generated by one tool is accepted by every other.
|
|
|
198
347
|
in `docs/CANONICALIZATION.md`.
|
|
199
348
|
|
|
200
349
|
## v0.15.3 (2026-06-27)
|
|
350
|
+
|
|
201
351
|
- Fix (PC-2, real): `renderPromptItem` now actually ships the
|
|
202
352
|
boundary card branch. The previous v0.15.2 release (ee20c5e)
|
|
203
353
|
bumped package.json and added a CHANGELOG entry but did NOT
|
|
@@ -208,6 +358,7 @@ signature generated by one tool is accepted by every other.
|
|
|
208
358
|
`in scope: X; out of scope: Y` instead of the UUID `id`.
|
|
209
359
|
|
|
210
360
|
## v0.15.2 (2026-06-27)
|
|
361
|
+
|
|
211
362
|
- Fix (PC-2): `renderPromptItem` now renders boundary cards as
|
|
212
363
|
`in scope: X; out of scope: Y; exceptions: ...` instead of
|
|
213
364
|
falling through to the UUID `id`. The previous behavior made
|
|
@@ -219,12 +370,14 @@ signature generated by one tool is accepted by every other.
|
|
|
219
370
|
UUID `id`, so any unrecognized card shape is visible.
|
|
220
371
|
|
|
221
372
|
## v0.15.1 (2026-06-27)
|
|
373
|
+
|
|
222
374
|
- Fix: package.json `files` array now includes `CHANGELOG.md`. The
|
|
223
375
|
v0.15.0 tarball was published without the changelog, leaving
|
|
224
376
|
consumers with no way to read release notes from `npm install`.
|
|
225
377
|
Adding it now is a no-op for code but resolves the docs gap.
|
|
226
378
|
|
|
227
379
|
## v0.15.0 (2026-06-27)
|
|
380
|
+
|
|
228
381
|
- B2: scrypt password profile `kdna-password-protected-v1-scrypt` (ADR-007)
|
|
229
382
|
- encryptProtectedEntryScrypt / decryptProtectedEntryScrypt (zero new deps, Node crypto.scryptSync)
|
|
230
383
|
- AES-256-GCM + AES-256-KW envelope encryption, same CEK model as RFC-0008
|
|
@@ -235,6 +388,7 @@ signature generated by one tool is accepted by every other.
|
|
|
235
388
|
- B5: conformance:canonical npm script (threshold #8)
|
|
236
389
|
|
|
237
390
|
## v0.14.0 (2026-06-25)
|
|
391
|
+
|
|
238
392
|
- B1: unified container dispatcher (readAsset — v1/v2/ dir → CanonicalAssetModel)
|
|
239
393
|
- B4: loadAuthorized decryption orchestration (opts.password, opts.decryptEntry)
|
|
240
394
|
- B4: encrypted payload detection in runValidate (backward compatible)
|
|
@@ -245,6 +399,7 @@ signature generated by one tool is accepted by every other.
|
|
|
245
399
|
- Add: engines.node >=18.0.0
|
|
246
400
|
|
|
247
401
|
## v0.13.3 (2026-06-22)
|
|
402
|
+
|
|
248
403
|
- Fix: index profile includes max_tokens_hint
|
|
249
404
|
- Fix: compact profile falls back to full_statement for TBD placeholders
|
|
250
405
|
|
|
@@ -253,11 +408,13 @@ Packages: `@aikdna/kdna-core`
|
|
|
253
408
|
## v0.13.2 (2026-06-21)
|
|
254
409
|
|
|
255
410
|
### Fixed
|
|
411
|
+
|
|
256
412
|
- Compact boundary projection now correctly preserves `applies_when`, `does_not_apply_when`, and `failure_risk` fields across all load profiles. These axiom governance fields are required by `kdna-loader` for domain routing decisions and were being dropped in compact mode under certain manifest configurations.
|
|
257
413
|
- Cross-platform test stability: Node test glob patterns are now compatible with both macOS and Linux filesystem sort orders.
|
|
258
414
|
- Hash library compatibility: `@noble/hashes` replaces Node-only crypto for digest operations, maintaining Node 18 compatibility without native module binding requirements.
|
|
259
415
|
|
|
260
416
|
### Changed
|
|
417
|
+
|
|
261
418
|
- Public API boundary hardened: `loadKDNA`, `loadKDNASync`, `inspectKDNA`, and `inspectKDNASync` now enforce the asset-first contract — callers must pass `.kdna` files or asset handles, not raw directory paths.
|
|
262
419
|
- Examples in README and inline docs reference the packaged `.kdna` path rather than source directories.
|
|
263
420
|
- First-run contract tightened: exported symbols, error codes, and validation gate names are now part of the stable API surface.
|
|
@@ -267,10 +424,12 @@ Packages: `@aikdna/kdna-core`
|
|
|
267
424
|
## v0.13.1 (2026-06-21)
|
|
268
425
|
|
|
269
426
|
### Fixed
|
|
427
|
+
|
|
270
428
|
- **Compact boundary projection preserved.** The `planLoad` function and `loadAuthorized` shim now pass through the full axiom governance projection (applies_when, does_not_apply_when, failure_risk) even when the load contract is not present in the manifest. Prior versions could strip these fields under compact profile, breaking domain routing for `kdna-loader`.
|
|
271
429
|
- Digest matching now tolerates `sha256:` prefix in both `manifest_digest` and `payload_digest` checksums entries. Previously, a leading `sha256:` prefix was treated as part of the hex digest, causing false mismatches.
|
|
272
430
|
|
|
273
431
|
### Changed
|
|
432
|
+
|
|
274
433
|
- Public API provenance and profile split clarified: `loadKDNA` / `loadKDNASync` are the stable entry points for runtime consumers. Lower-level `readV1Layout`, `runValidate`, and `planLoad` are exported for advanced tooling but carry no backward-compatibility guarantee.
|
|
275
434
|
- Access enum values normalized everywhere: `public`, `licensed`, `remote`. Legacy aliases (`open` → `public`, `protected` → `licensed`, `runtime` → `remote`) are mapped transparently with an info-level issue in the LoadPlan.
|
|
276
435
|
- `verifyAsset` / `verifyAssetSync`, `verifyDigest` / `verifyDigestSync`, and `verifySignature` / `verifySignatureSync` are now documented as the stable verification API surface.
|
|
@@ -280,6 +439,7 @@ Packages: `@aikdna/kdna-core`
|
|
|
280
439
|
## v0.13.0 (2026-06-19)
|
|
281
440
|
|
|
282
441
|
### Added
|
|
442
|
+
|
|
283
443
|
- **Authorization LoadPlan contract.** The `planLoad(inputPath, opts)` function returns a structured LoadPlan before any judgment content is decrypted or emitted. The LoadPlan reports:
|
|
284
444
|
- `asset_id`, `asset_uid`, `title`, `version`, `judgment_version`
|
|
285
445
|
- `access` model (`public` | `licensed` | `remote`)
|
|
@@ -315,11 +475,13 @@ Packages: `@aikdna/kdna-core`
|
|
|
315
475
|
- **TypeScript declarations.** `src/types.d.ts` exports type definitions for the stable public API surface.
|
|
316
476
|
|
|
317
477
|
### Changed
|
|
478
|
+
|
|
318
479
|
- **V1 is the only active format path.** The v2 reader (`readDataMapSync`, `readDataMap`) remains in the codebase for migration compatibility but is no longer the default path. All new integrations should use the v1 API: `inspect`, `validate`, `planLoad`, `loadAuthorized`.
|
|
319
480
|
- `validate` and `planLoad` reject v2 containers (`application/vnd.aikdna.kdna+zip`) with a format error.
|
|
320
481
|
- Access model normalized to the three-tier `public` | `licensed` | `remote` enum. The LoadPlan maps legacy values transparently with an info-level issue.
|
|
321
482
|
- Container format detection (`detectContainerFormat`) reads only the first central-directory entry to determine v1 vs v2, preventing malicious later entries from causing format confusion.
|
|
322
483
|
|
|
323
484
|
### Removed
|
|
485
|
+
|
|
324
486
|
- Legacy v1 compatibility shims removed. v2 is the only legacy format and is handled through the existing `asset-reader.js` module.
|
|
325
487
|
- `readDataMapSync` / `readDataMap` deprecated for new use. Use `planLoad` + `loadV1` for runtime loading or `validate` + `inspect` for diagnostics.
|
package/README.md
CHANGED
|
@@ -28,9 +28,13 @@ const {
|
|
|
28
28
|
validate,
|
|
29
29
|
planLoad,
|
|
30
30
|
loadAuthorized,
|
|
31
|
+
loadCapsuleV2,
|
|
32
|
+
computeDigestEvidence,
|
|
33
|
+
computeCapsuleDeliveryDigest,
|
|
34
|
+
adaptCapsuleV2ToV1,
|
|
31
35
|
pack,
|
|
32
36
|
unpack,
|
|
33
|
-
buildChecksums
|
|
37
|
+
buildChecksums,
|
|
34
38
|
} = require('@aikdna/kdna-core');
|
|
35
39
|
|
|
36
40
|
const validation = validate('./asset.kdna');
|
|
@@ -45,7 +49,7 @@ if (plan.can_load_now !== true) {
|
|
|
45
49
|
|
|
46
50
|
const capsule = loadAuthorized('./asset.kdna', {
|
|
47
51
|
profile: 'compact',
|
|
48
|
-
as: 'json'
|
|
52
|
+
as: 'json',
|
|
49
53
|
});
|
|
50
54
|
|
|
51
55
|
if (capsule.type !== 'kdna.context.capsule') {
|
|
@@ -53,6 +57,145 @@ if (capsule.type !== 'kdna.context.capsule') {
|
|
|
53
57
|
}
|
|
54
58
|
```
|
|
55
59
|
|
|
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
|
+
```
|
|
85
|
+
|
|
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:
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
const {
|
|
96
|
+
parseExecutionContractJsonV1,
|
|
97
|
+
buildConsumptionPlanV1,
|
|
98
|
+
buildAgentHost2RequestV1,
|
|
99
|
+
buildPreHostBudgetBlockedTraceV1,
|
|
100
|
+
validatePreHostBudgetBlockedTraceV1,
|
|
101
|
+
validateAgentHost2ReceiptV1,
|
|
102
|
+
buildJudgmentTraceV1,
|
|
103
|
+
} = require('@aikdna/kdna-core');
|
|
104
|
+
|
|
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
|
+
});
|
|
115
|
+
|
|
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
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
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.
|
|
143
|
+
|
|
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:
|
|
147
|
+
|
|
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
|
+
```
|
|
164
|
+
|
|
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
|
+
|
|
56
199
|
## Supported Runtime Flow
|
|
57
200
|
|
|
58
201
|
```text
|
|
@@ -64,6 +207,12 @@ if (capsule.type !== 'kdna.context.capsule') {
|
|
|
64
207
|
→ Agent/runtime context
|
|
65
208
|
```
|
|
66
209
|
|
|
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.
|
|
215
|
+
|
|
67
216
|
For authoring and test fixtures, `pack()` can turn a local working folder into
|
|
68
217
|
a `.kdna` file before validation:
|
|
69
218
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aikdna/kdna-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.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"
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"scripts": {
|
|
22
22
|
"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
23
|
"prepublishOnly": "npm run release:check",
|
|
24
|
-
"release:check": "node scripts/check-release-readiness.js"
|
|
24
|
+
"release:check": "node scripts/check-release-readiness.js",
|
|
25
|
+
"publish:guard": "node scripts/check-publish-duplicate.js"
|
|
25
26
|
},
|
|
26
27
|
"files": [
|
|
27
28
|
"src/",
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/aikdna/kdna/specs/agent-host-2-receipt.schema.json",
|
|
4
|
+
"title": "KDNA Agent Host 2 Correlated Response Receipt",
|
|
5
|
+
"description": "Host 2 correlated response envelope. A matched runtime_receipt proves only that the Host boundary accepted the exact Capsule 2 value. A mismatched runtime_receipt proves that the Host rejected the request before provider execution. Neither proves semantic consumption or conformance.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["protocol", "request_id", "runtime_receipt", "outcome"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"protocol": { "const": "kdna.agent-host/2" },
|
|
11
|
+
"request_id": { "type": "string", "pattern": "^host_[0-9a-f]{24}$" },
|
|
12
|
+
"runtime_receipt": { "$ref": "#/$defs/runtimeReceipt" },
|
|
13
|
+
"outcome": {
|
|
14
|
+
"oneOf": [{ "$ref": "#/$defs/outcome" }, { "type": "null" }]
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"allOf": [
|
|
18
|
+
{
|
|
19
|
+
"if": {
|
|
20
|
+
"properties": {
|
|
21
|
+
"runtime_receipt": {
|
|
22
|
+
"properties": { "provider_execution_status": { "const": "completed" } },
|
|
23
|
+
"required": ["provider_execution_status"]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": ["runtime_receipt"]
|
|
27
|
+
},
|
|
28
|
+
"then": { "properties": { "outcome": { "$ref": "#/$defs/outcome" } } },
|
|
29
|
+
"else": { "properties": { "outcome": { "type": "null" } } }
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"$defs": {
|
|
33
|
+
"sha256": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"pattern": "^sha256:[0-9a-f]{64}$"
|
|
36
|
+
},
|
|
37
|
+
"runtimeReceipt": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"required": [
|
|
40
|
+
"type",
|
|
41
|
+
"receipt_version",
|
|
42
|
+
"capsule_version",
|
|
43
|
+
"capsule_digest_profile",
|
|
44
|
+
"sender_capsule_delivery_digest",
|
|
45
|
+
"host_recomputed_capsule_delivery_digest",
|
|
46
|
+
"echoed_capsule_delivery_digest",
|
|
47
|
+
"capsule_delivery_comparison",
|
|
48
|
+
"capsule_schema_validation",
|
|
49
|
+
"asset_id_correlation",
|
|
50
|
+
"provider_execution_status",
|
|
51
|
+
"usage",
|
|
52
|
+
"semantic_consumption",
|
|
53
|
+
"model_identity"
|
|
54
|
+
],
|
|
55
|
+
"additionalProperties": false,
|
|
56
|
+
"properties": {
|
|
57
|
+
"type": { "const": "kdna.agent-host.runtime-receipt" },
|
|
58
|
+
"receipt_version": { "const": "1.0.0" },
|
|
59
|
+
"capsule_version": { "const": "2.0" },
|
|
60
|
+
"capsule_digest_profile": { "const": "kdna-capsule-jcs-v1" },
|
|
61
|
+
"sender_capsule_delivery_digest": { "$ref": "#/$defs/sha256" },
|
|
62
|
+
"host_recomputed_capsule_delivery_digest": { "$ref": "#/$defs/sha256" },
|
|
63
|
+
"echoed_capsule_delivery_digest": { "$ref": "#/$defs/sha256" },
|
|
64
|
+
"capsule_delivery_comparison": { "enum": ["matched", "mismatched"] },
|
|
65
|
+
"capsule_schema_validation": { "const": "passed" },
|
|
66
|
+
"asset_id_correlation": { "const": "matched" },
|
|
67
|
+
"provider_execution_status": {
|
|
68
|
+
"enum": ["completed", "not_started", "failed", "cancelled", "timed_out"]
|
|
69
|
+
},
|
|
70
|
+
"usage": { "$ref": "#/$defs/observedUsage" },
|
|
71
|
+
"semantic_consumption": { "$ref": "#/$defs/semanticConsumption" },
|
|
72
|
+
"model_identity": { "$ref": "#/$defs/modelIdentity" }
|
|
73
|
+
},
|
|
74
|
+
"allOf": [
|
|
75
|
+
{
|
|
76
|
+
"if": {
|
|
77
|
+
"properties": { "capsule_delivery_comparison": { "const": "matched" } },
|
|
78
|
+
"required": ["capsule_delivery_comparison"]
|
|
79
|
+
},
|
|
80
|
+
"then": {
|
|
81
|
+
"properties": {
|
|
82
|
+
"provider_execution_status": {
|
|
83
|
+
"enum": ["completed", "failed", "cancelled", "timed_out"]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"else": {
|
|
88
|
+
"properties": {
|
|
89
|
+
"provider_execution_status": { "const": "not_started" },
|
|
90
|
+
"usage": {
|
|
91
|
+
"properties": {
|
|
92
|
+
"tokens_used": { "type": "null" },
|
|
93
|
+
"model_calls": { "type": "null" },
|
|
94
|
+
"basis": { "const": "not_observed" }
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"model_identity": {
|
|
98
|
+
"properties": {
|
|
99
|
+
"value": { "type": "null" },
|
|
100
|
+
"basis": { "const": "not_observed" }
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"semanticConsumption": {
|
|
109
|
+
"type": "object",
|
|
110
|
+
"required": ["state", "basis"],
|
|
111
|
+
"additionalProperties": false,
|
|
112
|
+
"properties": {
|
|
113
|
+
"state": { "const": "not_observed" },
|
|
114
|
+
"basis": { "type": "null" }
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"observedUsage": {
|
|
118
|
+
"type": "object",
|
|
119
|
+
"required": ["elapsed_ms", "elapsed_basis", "tokens_used", "model_calls", "basis"],
|
|
120
|
+
"additionalProperties": false,
|
|
121
|
+
"properties": {
|
|
122
|
+
"elapsed_ms": { "type": "integer", "minimum": 0 },
|
|
123
|
+
"elapsed_basis": { "const": "host_monotonic" },
|
|
124
|
+
"tokens_used": {
|
|
125
|
+
"oneOf": [{ "type": "integer", "minimum": 0 }, { "type": "null" }]
|
|
126
|
+
},
|
|
127
|
+
"model_calls": {
|
|
128
|
+
"oneOf": [{ "type": "integer", "minimum": 0 }, { "type": "null" }]
|
|
129
|
+
},
|
|
130
|
+
"basis": { "enum": ["host_reported", "not_observed"] }
|
|
131
|
+
},
|
|
132
|
+
"allOf": [
|
|
133
|
+
{
|
|
134
|
+
"if": {
|
|
135
|
+
"properties": { "basis": { "const": "host_reported" } },
|
|
136
|
+
"required": ["basis"]
|
|
137
|
+
},
|
|
138
|
+
"then": {
|
|
139
|
+
"properties": {
|
|
140
|
+
"tokens_used": { "type": "integer", "minimum": 0 },
|
|
141
|
+
"model_calls": { "type": "integer", "minimum": 0 }
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"else": {
|
|
145
|
+
"properties": {
|
|
146
|
+
"tokens_used": { "type": "null" },
|
|
147
|
+
"model_calls": { "type": "null" }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
},
|
|
153
|
+
"modelIdentity": {
|
|
154
|
+
"type": "object",
|
|
155
|
+
"required": ["value", "basis"],
|
|
156
|
+
"additionalProperties": false,
|
|
157
|
+
"properties": {
|
|
158
|
+
"value": { "type": ["string", "null"], "minLength": 1 },
|
|
159
|
+
"basis": { "enum": ["host_reported", "not_observed"] }
|
|
160
|
+
},
|
|
161
|
+
"allOf": [
|
|
162
|
+
{
|
|
163
|
+
"if": {
|
|
164
|
+
"properties": { "basis": { "const": "host_reported" } },
|
|
165
|
+
"required": ["basis"]
|
|
166
|
+
},
|
|
167
|
+
"then": { "properties": { "value": { "type": "string", "minLength": 1 } } },
|
|
168
|
+
"else": { "properties": { "value": { "type": "null" } } }
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
"outcome": {
|
|
173
|
+
"type": "object",
|
|
174
|
+
"required": ["judgment", "usage"],
|
|
175
|
+
"additionalProperties": false,
|
|
176
|
+
"properties": {
|
|
177
|
+
"judgment": { "$ref": "#/$defs/judgment" },
|
|
178
|
+
"usage": {
|
|
179
|
+
"oneOf": [{ "$ref": "#/$defs/usage" }, { "type": "null" }]
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
"judgment": {
|
|
184
|
+
"type": "object",
|
|
185
|
+
"required": ["answer", "reasoning", "confidence"],
|
|
186
|
+
"additionalProperties": false,
|
|
187
|
+
"properties": {
|
|
188
|
+
"answer": { "type": "string", "minLength": 1 },
|
|
189
|
+
"reasoning": {
|
|
190
|
+
"type": "array",
|
|
191
|
+
"items": { "type": "string" }
|
|
192
|
+
},
|
|
193
|
+
"confidence": { "type": ["string", "null"], "minLength": 1 }
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
"usage": {
|
|
197
|
+
"type": "object",
|
|
198
|
+
"required": ["tokens_used", "model_calls"],
|
|
199
|
+
"additionalProperties": false,
|
|
200
|
+
"properties": {
|
|
201
|
+
"tokens_used": { "type": "integer", "minimum": 0 },
|
|
202
|
+
"model_calls": { "type": "integer", "minimum": 0 }
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|