@amalgm/shell 0.1.112 → 0.1.113

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/PURPOSE.md CHANGED
@@ -687,6 +687,14 @@ shell only assembles.
687
687
  and applied prefix, and authority accepts that graph only while `N` is
688
688
  still the committed delivery tail under the entity-record ordering gate.
689
689
 
690
+ 59. **Shell journals graph publication without duplicating the graph.**
691
+ Live decides the immutable pages and head. Shell stores only the small
692
+ head operation plus the changed pages needed to replay that publication;
693
+ it never writes a second whole-registry snapshot into SQLite or rebuilds
694
+ roots Live did not select. A submitted intent keeps its mutation identity
695
+ across restart, and all pre-page journal shapes convert atomically without
696
+ dropping an unknown authority outcome.
697
+
690
698
  ## Relationship to amalgm-engine
691
699
 
692
700
  Stage 1 cut the bricks out of the engine. Stage 2 proves them here, composed.
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The registry graph as this machine holds it.
3
+ *
4
+ * The authority stores the graph as a small head naming each root's immutable
5
+ * pages, so this machine holds the same shape: the head, and the records of
6
+ * every root that head names, grouped exactly as the head pages them. A
7
+ * publication rebuilds only the roots it walked — every other root carries its
8
+ * page list forward untouched, never re-serialized, re-hashed, or re-journaled.
9
+ *
10
+ * A resource whose authority snapshot is still records-shaped (a login's
11
+ * initial publication, before any head has committed) is held with a null
12
+ * head. Its first head commit must page every root at once, which is exactly
13
+ * what the authority demands of a commit over a records base.
14
+ */
15
+ import { type CloudEntityRecord, type CloudSnapshot, type CloudGraphHead, type CloudGraphHeadReplacement, type GraphPage, type GraphPageRef, type Sha256Hex } from "@amalgm/live";
16
+ /** One publication's outcome: the graph it produces, the operation that
17
+ * commits it, the pages that must be sealed first, and the checksum the
18
+ * authority will hold once it lands. */
19
+ export interface RegistryGraphRebuild {
20
+ readonly graph: RegistryGraph;
21
+ readonly operation: CloudGraphHeadReplacement;
22
+ readonly pages: readonly GraphPage[];
23
+ readonly checksum: string;
24
+ }
25
+ export declare class RegistryGraph {
26
+ /** The committed head, or null while the authority still holds a
27
+ * records-shaped snapshot. */
28
+ readonly head: CloudGraphHead | null;
29
+ private readonly rootRecords;
30
+ private flat;
31
+ private rootIndex;
32
+ constructor(head: CloudGraphHead | null, rootRecords: ReadonlyMap<string, readonly CloudEntityRecord[]>);
33
+ /** Hold a records-shaped snapshot as the same per-root groups a head would
34
+ * name, so every reader above this class is shape-blind. */
35
+ static fromRecords(records: readonly CloudEntityRecord[]): RegistryGraph;
36
+ rootIds(): readonly string[];
37
+ recordsFor(rootId: string): readonly CloudEntityRecord[];
38
+ /** Every record of every root, uuid-sorted. Only whole-graph readers pay
39
+ * for this — a publication never calls it. */
40
+ records(): readonly CloudEntityRecord[];
41
+ /** The whole graph in the records shape the cold install and workspace
42
+ * selection paths read. Normalization already happened per root, so this
43
+ * only names the shape. */
44
+ snapshot(): CloudSnapshot;
45
+ /** Which root a record descends from, or null when the graph does not hold
46
+ * it. The index is built once, and only for callers that need it. */
47
+ rootOf(uuid: string): string | null;
48
+ /** The checksum the authority holds for this graph right now. */
49
+ checksum(sha256Hex: Sha256Hex): string;
50
+ /** Publish a new graph in which `rebuilt` roots carry the given records and
51
+ * every other root carries its committed pages forward. A root mapped to an
52
+ * empty record list is dropped from the graph. */
53
+ rebuild(rebuilt: ReadonlyMap<string, readonly CloudEntityRecord[]>, sha256Hex: Sha256Hex): RegistryGraphRebuild;
54
+ }
55
+ /** Every page identity the head names — the set a publication may skip
56
+ * uploading because the authority already holds it under this exact graph. */
57
+ export declare function graphPageIdentities(head: CloudGraphHead | null): ReadonlySet<string>;
58
+ /** Materialize the authority's stored snapshot bytes into this machine's
59
+ * graph. A head is materialized by reading the pages it names; a records-shaped
60
+ * snapshot is grouped in place. */
61
+ export declare function registryGraphFromSnapshot(bytes: Uint8Array, readPages: (refs: readonly GraphPageRef[]) => Promise<ReadonlyMap<string, Uint8Array>>, sha256Hex: Sha256Hex): Promise<RegistryGraph>;
@@ -0,0 +1,156 @@
1
+ /**
2
+ * The registry graph as this machine holds it.
3
+ *
4
+ * The authority stores the graph as a small head naming each root's immutable
5
+ * pages, so this machine holds the same shape: the head, and the records of
6
+ * every root that head names, grouped exactly as the head pages them. A
7
+ * publication rebuilds only the roots it walked — every other root carries its
8
+ * page list forward untouched, never re-serialized, re-hashed, or re-journaled.
9
+ *
10
+ * A resource whose authority snapshot is still records-shaped (a login's
11
+ * initial publication, before any head has committed) is held with a null
12
+ * head. Its first head commit must page every root at once, which is exactly
13
+ * what the authority demands of a commit over a records base.
14
+ */
15
+ import { assembleRootRecords, graphHeadChecksum, graphHeadFromRootPages, graphHeadReplacement, pagesForRoot, parseGraphHead, parseSnapshot, recordsByRoot, snapshotFromRecords, stableJson, ENTITY_CLOUD_SCHEMA_VERSION, GRAPH_HEAD_KIND, } from "@amalgm/live";
16
+ export class RegistryGraph {
17
+ /** The committed head, or null while the authority still holds a
18
+ * records-shaped snapshot. */
19
+ head;
20
+ rootRecords;
21
+ flat = null;
22
+ rootIndex = null;
23
+ constructor(head, rootRecords) {
24
+ this.head = head;
25
+ this.rootRecords = rootRecords;
26
+ }
27
+ /** Hold a records-shaped snapshot as the same per-root groups a head would
28
+ * name, so every reader above this class is shape-blind. */
29
+ static fromRecords(records) {
30
+ return new RegistryGraph(null, recordsByRoot(records));
31
+ }
32
+ rootIds() {
33
+ return [...this.rootRecords.keys()];
34
+ }
35
+ recordsFor(rootId) {
36
+ return this.rootRecords.get(rootId.toLowerCase()) ?? [];
37
+ }
38
+ /** Every record of every root, uuid-sorted. Only whole-graph readers pay
39
+ * for this — a publication never calls it. */
40
+ records() {
41
+ this.flat ??= snapshotFromRecords([...this.rootRecords.values()].flat()).records;
42
+ return this.flat;
43
+ }
44
+ /** The whole graph in the records shape the cold install and workspace
45
+ * selection paths read. Normalization already happened per root, so this
46
+ * only names the shape. */
47
+ snapshot() {
48
+ return {
49
+ schemaVersion: ENTITY_CLOUD_SCHEMA_VERSION,
50
+ kind: "amalgm-entity-registry",
51
+ records: this.records(),
52
+ };
53
+ }
54
+ /** Which root a record descends from, or null when the graph does not hold
55
+ * it. The index is built once, and only for callers that need it. */
56
+ rootOf(uuid) {
57
+ if (!this.rootIndex) {
58
+ const index = new Map();
59
+ for (const [rootId, records] of this.rootRecords) {
60
+ for (const record of records)
61
+ index.set(record.uuid, rootId);
62
+ }
63
+ this.rootIndex = index;
64
+ }
65
+ return this.rootIndex.get(uuid) ?? null;
66
+ }
67
+ /** The checksum the authority holds for this graph right now. */
68
+ checksum(sha256Hex) {
69
+ return this.head === null
70
+ ? sha256Hex(stableJson(snapshotFromRecords(this.records())))
71
+ : graphHeadChecksum(this.head, sha256Hex);
72
+ }
73
+ /** Publish a new graph in which `rebuilt` roots carry the given records and
74
+ * every other root carries its committed pages forward. A root mapped to an
75
+ * empty record list is dropped from the graph. */
76
+ rebuild(rebuilt, sha256Hex) {
77
+ const replaced = new Map([...rebuilt].map(([rootId, records]) => [rootId.toLowerCase(), records]));
78
+ if (this.head === null) {
79
+ // The authority's base carries no page identities, so it can prove
80
+ // nothing about a root this commit leaves alone. Paging every root is
81
+ // the only lawful first head.
82
+ for (const rootId of this.rootRecords.keys()) {
83
+ if (!replaced.has(rootId)) {
84
+ throw new Error(`the first graph head must page every root, and ${rootId} is missing`);
85
+ }
86
+ }
87
+ }
88
+ const carried = (this.head?.roots ?? []).filter((root) => !replaced.has(root.rootId));
89
+ const pages = [];
90
+ const paged = [];
91
+ const nextRecords = new Map(this.rootRecords);
92
+ for (const [rootId, records] of replaced) {
93
+ if (records.length === 0) {
94
+ nextRecords.delete(rootId);
95
+ continue;
96
+ }
97
+ const rootPages = pagesForRoot(rootId, records, sha256Hex);
98
+ pages.push(...rootPages);
99
+ paged.push({ rootId, pages: rootPages.map((page) => page.ref) });
100
+ nextRecords.set(rootId, rootPages.flatMap((page) => page.records));
101
+ }
102
+ const head = graphHeadFromRootPages([...carried, ...paged]);
103
+ return {
104
+ graph: new RegistryGraph(head, nextRecords),
105
+ operation: graphHeadReplacement(head, [...replaced.keys()]),
106
+ pages,
107
+ checksum: graphHeadChecksum(head, sha256Hex),
108
+ };
109
+ }
110
+ }
111
+ /** Every page identity the head names — the set a publication may skip
112
+ * uploading because the authority already holds it under this exact graph. */
113
+ export function graphPageIdentities(head) {
114
+ const identities = new Set();
115
+ for (const root of head?.roots ?? []) {
116
+ for (const page of root.pages)
117
+ identities.add(page.sha256);
118
+ }
119
+ return identities;
120
+ }
121
+ /** Materialize the authority's stored snapshot bytes into this machine's
122
+ * graph. A head is materialized by reading the pages it names; a records-shaped
123
+ * snapshot is grouped in place. */
124
+ export async function registryGraphFromSnapshot(bytes, readPages, sha256Hex) {
125
+ if (!snapshotIsGraphHead(bytes)) {
126
+ return RegistryGraph.fromRecords(parseSnapshot(bytes).records);
127
+ }
128
+ const head = parseGraphHead(bytes);
129
+ const read = await readPages(head.roots.flatMap((root) => root.pages));
130
+ const rootRecords = new Map();
131
+ for (const root of head.roots) {
132
+ rootRecords.set(root.rootId, assembleRootRecords(root.rootId, root.pages, root.pages.map((page) => {
133
+ const found = read.get(page.sha256);
134
+ if (!found)
135
+ throw new Error(`cloud graph page ${page.sha256} was not read`);
136
+ return found;
137
+ }), sha256Hex));
138
+ }
139
+ return new RegistryGraph(head, rootRecords);
140
+ }
141
+ /** Which shape the authority's snapshot bytes carry. Both shapes declare their
142
+ * kind ahead of their payload, and no record carries a `kind` of its own, so
143
+ * the first declaration in the opening bytes is the snapshot's — the shape is
144
+ * decided from a few bytes rather than by parsing a whole graph. */
145
+ function snapshotIsGraphHead(bytes) {
146
+ const declared = /"kind":"([^"]*)"/
147
+ .exec(Buffer.from(bytes.subarray(0, SNAPSHOT_KIND_PREFIX_BYTES)).toString("utf8"));
148
+ if (!declared)
149
+ throw new Error("cloud registry snapshot declares no kind");
150
+ return declared[1] === GRAPH_HEAD_KIND;
151
+ }
152
+ /** Enough opening bytes to hold the kind declaration of either shape, whatever
153
+ * small members precede it. The authority reads the same prefix to decide the
154
+ * same question. */
155
+ const SNAPSHOT_KIND_PREFIX_BYTES = 128;
156
+ //# sourceMappingURL=registry-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-graph.js","sourceRoot":"","sources":["../src/registry-graph.ts"],"names":[],"mappings":"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"}
@@ -182,6 +182,14 @@ export declare class UserGroundHost {
182
182
  private userRoot;
183
183
  private cacheDir;
184
184
  private cloudPort;
185
+ /** The authority's stored snapshot as this machine's graph. A head names
186
+ * immutable pages, so every page this machine already cached is a local read
187
+ * and an unchanged root never crosses the network twice. */
188
+ private materializeRegistry;
189
+ /** Read graph pages by identity: cached pages come off local disk, the rest
190
+ * are fetched straight from content storage and cached on the way in. Every
191
+ * page is re-proven against its declared identity before it is kept. */
192
+ private readGraphPages;
185
193
  private localPort;
186
194
  /** Send's small-cargo fast path: the record's sealed artifact rides the
187
195
  * submit frame itself, so one round trip carries record, manifest, and
@@ -219,6 +227,11 @@ export declare class UserGroundHost {
219
227
  * frames; the answer is the only permission to skip an upload. */
220
228
  private sealedContentHashes;
221
229
  private publishPendingSnapshots;
230
+ /** Seal this publication's graph pages. Pages are immutable, content
231
+ * addressed, and already in memory, so the authority's seal inventory alone
232
+ * decides what still has to move and whole pages ride cargo waves. The head
233
+ * may not commit until every page it newly names is sealed. */
234
+ private uploadGraphPages;
222
235
  private publishLoadedSnapshot;
223
236
  }
224
237
  /** The single opener and schema-migration entry for a user ground database.