@sublang/playbook 17.11.1 → 18.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,36 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
3
+
4
+ import { MAX_SESSION_CHUNK_BYTES } from './session-chunks.js';
5
+
6
+ export const SESSION_STORAGE_VERSION = 8;
7
+ const FIELDS = ['schemaVersion', 'kind', 'sessionId', 'cwd', 'state', 'createdAt', 'updatedAt', 'root'];
8
+ const SUMMARY = ['sessionId', 'cwd', 'state', 'createdAt', 'updatedAt'];
9
+
10
+ // Logical schema validation remains owned by portable-codec. This boundary
11
+ // validates the physical representation before giving that codec its input.
12
+ export async function decodeStoredManifest(bytes, chunks, sessionId) {
13
+ const value = JSON.parse(bytes);
14
+ if (value?.schemaVersion !== SESSION_STORAGE_VERSION) return value;
15
+ if (Buffer.byteLength(bytes) > MAX_SESSION_CHUNK_BYTES ||
16
+ !value || Array.isArray(value) || Object.keys(value).length !== FIELDS.length ||
17
+ FIELDS.some((key) => !Object.hasOwn(value, key)) ||
18
+ value.kind !== 'captain-session-storage' || value.sessionId !== sessionId) {
19
+ throw new Error('invalid bounded session manifest');
20
+ }
21
+ const manifest = await chunks.readJson(value.root);
22
+ if (manifest?.schemaVersion !== 7 || SUMMARY.some((key) => manifest[key] !== value[key])) {
23
+ throw new Error('bounded session summary differs from recovery');
24
+ }
25
+ return manifest;
26
+ }
27
+
28
+ export async function encodeStoredManifest(manifest, chunks) {
29
+ const root = await chunks.writeJson(manifest);
30
+ const value = { schemaVersion: SESSION_STORAGE_VERSION, kind: 'captain-session-storage' };
31
+ for (const key of SUMMARY) value[key] = manifest[key];
32
+ value.root = root;
33
+ const bytes = Buffer.from(`${JSON.stringify(value)}\n`);
34
+ if (bytes.length > MAX_SESSION_CHUNK_BYTES) throw new Error('session manifest summary exceeds file bound');
35
+ return bytes;
36
+ }
@@ -9,6 +9,8 @@ export interface SessionBundle {
9
9
  readonly manifest: Uint8Array;
10
10
  readonly replay: Uint8Array;
11
11
  readonly assets: readonly AssetFile[];
12
+ /** Verified physical bundle files relative to sessionsDir; replay is a logical prefix. */
13
+ readonly files: readonly { readonly path: string; readonly byteLength: number }[];
12
14
  }
13
15
 
14
16
  export declare const RECORDS_STREAM_VERSION: 1;