@aikdna/kdna-core 0.17.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 CHANGED
@@ -1,5 +1,123 @@
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
+
3
121
  ## v0.17.0 (2026-07-14)
4
122
 
5
123
  ### Added
@@ -174,7 +292,6 @@ Story 6 — dependencies runtime. Supports semver-matching local/registry depend
174
292
  - **Topological Sorting Resolver**: Added a robust, pure post-order DFS topological sorter with circular cycle, missing dependency, and version range mismatch checks.
175
293
  - **Topological Prompt Composition**: Enabled recursive, multi-domain prompt composition and flat topological JSON return inside `loadAuthorized`.
176
294
 
177
-
178
295
  ## v0.15.6 (2026-06-28)
179
296
 
180
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.
@@ -183,7 +300,6 @@ Story 5 — Bundle payload type. Bumps KDNA manifest format schema to v2, introd
183
300
  - **V2 Schema support:** bumped manifest schema version to v2.0, supporting `kdna_version` as `"2.0"`.
184
301
  - **Bundle profile support:** added `bundle-profile-v1` payload profile and validator.
185
302
 
186
-
187
303
  ## v0.15.5 (2026-06-28)
188
304
 
189
305
  Phase 12 audit follow-up. Closes 3 issues filed against this
@@ -231,6 +347,7 @@ signature generated by one tool is accepted by every other.
231
347
  in `docs/CANONICALIZATION.md`.
232
348
 
233
349
  ## v0.15.3 (2026-06-27)
350
+
234
351
  - Fix (PC-2, real): `renderPromptItem` now actually ships the
235
352
  boundary card branch. The previous v0.15.2 release (ee20c5e)
236
353
  bumped package.json and added a CHANGELOG entry but did NOT
@@ -241,6 +358,7 @@ signature generated by one tool is accepted by every other.
241
358
  `in scope: X; out of scope: Y` instead of the UUID `id`.
242
359
 
243
360
  ## v0.15.2 (2026-06-27)
361
+
244
362
  - Fix (PC-2): `renderPromptItem` now renders boundary cards as
245
363
  `in scope: X; out of scope: Y; exceptions: ...` instead of
246
364
  falling through to the UUID `id`. The previous behavior made
@@ -252,12 +370,14 @@ signature generated by one tool is accepted by every other.
252
370
  UUID `id`, so any unrecognized card shape is visible.
253
371
 
254
372
  ## v0.15.1 (2026-06-27)
373
+
255
374
  - Fix: package.json `files` array now includes `CHANGELOG.md`. The
256
375
  v0.15.0 tarball was published without the changelog, leaving
257
376
  consumers with no way to read release notes from `npm install`.
258
377
  Adding it now is a no-op for code but resolves the docs gap.
259
378
 
260
379
  ## v0.15.0 (2026-06-27)
380
+
261
381
  - B2: scrypt password profile `kdna-password-protected-v1-scrypt` (ADR-007)
262
382
  - encryptProtectedEntryScrypt / decryptProtectedEntryScrypt (zero new deps, Node crypto.scryptSync)
263
383
  - AES-256-GCM + AES-256-KW envelope encryption, same CEK model as RFC-0008
@@ -268,6 +388,7 @@ signature generated by one tool is accepted by every other.
268
388
  - B5: conformance:canonical npm script (threshold #8)
269
389
 
270
390
  ## v0.14.0 (2026-06-25)
391
+
271
392
  - B1: unified container dispatcher (readAsset — v1/v2/ dir → CanonicalAssetModel)
272
393
  - B4: loadAuthorized decryption orchestration (opts.password, opts.decryptEntry)
273
394
  - B4: encrypted payload detection in runValidate (backward compatible)
@@ -278,6 +399,7 @@ signature generated by one tool is accepted by every other.
278
399
  - Add: engines.node >=18.0.0
279
400
 
280
401
  ## v0.13.3 (2026-06-22)
402
+
281
403
  - Fix: index profile includes max_tokens_hint
282
404
  - Fix: compact profile falls back to full_statement for TBD placeholders
283
405
 
@@ -286,11 +408,13 @@ Packages: `@aikdna/kdna-core`
286
408
  ## v0.13.2 (2026-06-21)
287
409
 
288
410
  ### Fixed
411
+
289
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.
290
413
  - Cross-platform test stability: Node test glob patterns are now compatible with both macOS and Linux filesystem sort orders.
291
414
  - Hash library compatibility: `@noble/hashes` replaces Node-only crypto for digest operations, maintaining Node 18 compatibility without native module binding requirements.
292
415
 
293
416
  ### Changed
417
+
294
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.
295
419
  - Examples in README and inline docs reference the packaged `.kdna` path rather than source directories.
296
420
  - First-run contract tightened: exported symbols, error codes, and validation gate names are now part of the stable API surface.
@@ -300,10 +424,12 @@ Packages: `@aikdna/kdna-core`
300
424
  ## v0.13.1 (2026-06-21)
301
425
 
302
426
  ### Fixed
427
+
303
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`.
304
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.
305
430
 
306
431
  ### Changed
432
+
307
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.
308
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.
309
435
  - `verifyAsset` / `verifyAssetSync`, `verifyDigest` / `verifyDigestSync`, and `verifySignature` / `verifySignatureSync` are now documented as the stable verification API surface.
@@ -313,6 +439,7 @@ Packages: `@aikdna/kdna-core`
313
439
  ## v0.13.0 (2026-06-19)
314
440
 
315
441
  ### Added
442
+
316
443
  - **Authorization LoadPlan contract.** The `planLoad(inputPath, opts)` function returns a structured LoadPlan before any judgment content is decrypted or emitted. The LoadPlan reports:
317
444
  - `asset_id`, `asset_uid`, `title`, `version`, `judgment_version`
318
445
  - `access` model (`public` | `licensed` | `remote`)
@@ -348,11 +475,13 @@ Packages: `@aikdna/kdna-core`
348
475
  - **TypeScript declarations.** `src/types.d.ts` exports type definitions for the stable public API surface.
349
476
 
350
477
  ### Changed
478
+
351
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`.
352
480
  - `validate` and `planLoad` reject v2 containers (`application/vnd.aikdna.kdna+zip`) with a format error.
353
481
  - Access model normalized to the three-tier `public` | `licensed` | `remote` enum. The LoadPlan maps legacy values transparently with an info-level issue.
354
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.
355
483
 
356
484
  ### Removed
485
+
357
486
  - Legacy v1 compatibility shims removed. v2 is the only legacy format and is handled through the existing `asset-reader.js` module.
358
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikdna/kdna-core",
3
- "version": "0.17.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
+ }