amalgm 0.1.245 → 0.1.246

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 (157) hide show
  1. package/README.md +12 -0
  2. package/lib/cli.js +146 -8
  3. package/lib/layout.js +89 -4
  4. package/lib/shared-realtime-tunnel.js +384 -43
  5. package/lib/supervisor.js +0 -3
  6. package/package.json +2 -2
  7. package/runtime/scripts/amalgm-mcp/adapters/contract.js +197 -0
  8. package/runtime/scripts/amalgm-mcp/adapters/filesystem.js +135 -0
  9. package/runtime/scripts/amalgm-mcp/adapters/git.js +84 -0
  10. package/runtime/scripts/amalgm-mcp/adapters/index.js +43 -0
  11. package/runtime/scripts/amalgm-mcp/adapters/reference.js +31 -0
  12. package/runtime/scripts/amalgm-mcp/adapters/truth.js +19 -0
  13. package/runtime/scripts/amalgm-mcp/browser/cookie-jar.js +20 -68
  14. package/runtime/scripts/amalgm-mcp/index.js +4 -0
  15. package/runtime/scripts/amalgm-mcp/lib/layout.js +89 -4
  16. package/runtime/scripts/amalgm-mcp/observer/README.md +259 -0
  17. package/runtime/scripts/amalgm-mcp/observer/apply.js +150 -0
  18. package/runtime/scripts/amalgm-mcp/observer/continuity.js +111 -0
  19. package/runtime/scripts/amalgm-mcp/observer/edges.js +111 -0
  20. package/runtime/scripts/amalgm-mcp/observer/index.js +1146 -0
  21. package/runtime/scripts/amalgm-mcp/observer/scan.js +387 -0
  22. package/runtime/scripts/amalgm-mcp/observer/store.js +262 -0
  23. package/runtime/scripts/amalgm-mcp/observer/verify.js +200 -0
  24. package/runtime/scripts/amalgm-mcp/observer/watch.js +62 -0
  25. package/runtime/scripts/amalgm-mcp/project-context/store.js +19 -87
  26. package/runtime/scripts/amalgm-mcp/registration/classify.js +33 -0
  27. package/runtime/scripts/amalgm-mcp/registration/entity-cloud.js +456 -0
  28. package/runtime/scripts/amalgm-mcp/registration/entity-content.js +345 -0
  29. package/runtime/scripts/amalgm-mcp/registration/index.js +752 -0
  30. package/runtime/scripts/amalgm-mcp/registration/refusal.js +42 -0
  31. package/runtime/scripts/amalgm-mcp/registration/repo-followers.js +127 -0
  32. package/runtime/scripts/amalgm-mcp/registration/repo-states.js +109 -0
  33. package/runtime/scripts/amalgm-mcp/registration/service.js +310 -0
  34. package/runtime/scripts/amalgm-mcp/registration/tree.js +178 -0
  35. package/runtime/scripts/amalgm-mcp/registry/evidence.js +826 -0
  36. package/runtime/scripts/amalgm-mcp/registry/index.js +666 -0
  37. package/runtime/scripts/amalgm-mcp/registry/store.js +290 -0
  38. package/runtime/scripts/amalgm-mcp/repocard/README.md +103 -0
  39. package/runtime/scripts/amalgm-mcp/repocard/apply.js +111 -0
  40. package/runtime/scripts/amalgm-mcp/repocard/capture-worker.js +94 -0
  41. package/runtime/scripts/amalgm-mcp/repocard/capture.js +149 -0
  42. package/runtime/scripts/amalgm-mcp/repocard/follow.js +310 -0
  43. package/runtime/scripts/amalgm-mcp/repocard/git.js +48 -0
  44. package/runtime/scripts/amalgm-mcp/repocard/index.js +48 -0
  45. package/runtime/scripts/amalgm-mcp/server/local-service-router.js +2 -0
  46. package/runtime/scripts/amalgm-mcp/server/routes/entities.js +287 -0
  47. package/runtime/scripts/amalgm-mcp/server/routes/state.js +0 -13
  48. package/runtime/scripts/amalgm-mcp/state/attachments.js +11 -45
  49. package/runtime/scripts/amalgm-mcp/state/db.js +46 -215
  50. package/runtime/scripts/amalgm-mcp/state/docs.js +301 -1101
  51. package/runtime/scripts/amalgm-mcp/state/mutation-contracts.js +0 -99
  52. package/runtime/scripts/amalgm-mcp/state/mutations.js +130 -507
  53. package/runtime/scripts/amalgm-mcp/state/promotions.js +1 -21
  54. package/runtime/scripts/amalgm-mcp/state/replicas.js +13 -134
  55. package/runtime/scripts/amalgm-mcp/state/shared-rest.js +3 -46
  56. package/runtime/scripts/amalgm-mcp/tests/adapters.test.js +379 -0
  57. package/runtime/scripts/amalgm-mcp/tests/browser-cookie-cloud.test.js +0 -193
  58. package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.life.test.js +449 -0
  59. package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.rig.js +107 -0
  60. package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.watch.test.js +213 -0
  61. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/adapter.js +72 -0
  62. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/assert.js +497 -0
  63. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/bind.js +91 -0
  64. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/graph.js +1031 -0
  65. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/ledger.js +234 -0
  66. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/referee.js +118 -0
  67. package/runtime/scripts/amalgm-mcp/tests/entity.oracle.test.js +1365 -0
  68. package/runtime/scripts/amalgm-mcp/tests/entity.registry.test.js +967 -0
  69. package/runtime/scripts/amalgm-mcp/tests/entity.rig.js +239 -0
  70. package/runtime/scripts/amalgm-mcp/tests/entity.storm.test.js +486 -0
  71. package/runtime/scripts/amalgm-mcp/tests/fake-watch.js +35 -0
  72. package/runtime/scripts/amalgm-mcp/tests/observer.links.test.js +289 -0
  73. package/runtime/scripts/amalgm-mcp/tests/observer.rig.js +103 -0
  74. package/runtime/scripts/amalgm-mcp/tests/observer.roots.test.js +505 -0
  75. package/runtime/scripts/amalgm-mcp/tests/observer.storm.test.js +389 -0
  76. package/runtime/scripts/amalgm-mcp/tests/observer.territory.test.js +845 -0
  77. package/runtime/scripts/amalgm-mcp/tests/observer.test.js +657 -0
  78. package/runtime/scripts/amalgm-mcp/tests/project-context.test.js +17 -32
  79. package/runtime/scripts/amalgm-mcp/tests/registration.service.test.js +256 -0
  80. package/runtime/scripts/amalgm-mcp/tests/registration.test.js +931 -0
  81. package/runtime/scripts/amalgm-mcp/tests/repocard.storm.test.js +284 -0
  82. package/runtime/scripts/amalgm-mcp/tests/repocard.test.js +371 -0
  83. package/runtime/scripts/amalgm-mcp/tests/repofollow.storm.test.js +435 -0
  84. package/runtime/scripts/amalgm-mcp/tests/repofollow.test.js +675 -0
  85. package/runtime/scripts/amalgm-mcp/tests/shared-tunnel-rehydration.test.js +0 -84
  86. package/runtime/scripts/amalgm-mcp/tests/state-docs.test.js +13 -376
  87. package/runtime/scripts/amalgm-mcp/tests/state-mutations.test.js +0 -309
  88. package/runtime/scripts/amalgm-mcp/tests/state-shared-replica.test.js +30 -758
  89. package/runtime/scripts/amalgm-mcp/tests/workspace-cards-store.test.js +3 -72
  90. package/runtime/scripts/amalgm-mcp/tests/workspace-cards.test.js +1 -89
  91. package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint-reducer.test.js +24 -55
  92. package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint.test.js +141 -424
  93. package/runtime/scripts/amalgm-mcp/tests/workspace-object-tunnel.test.js +3 -171
  94. package/runtime/scripts/amalgm-mcp/tests/workspace-objects.test.js +7 -220
  95. package/runtime/scripts/amalgm-mcp/tests/workspace-publication-invariants.test.js +236 -179
  96. package/runtime/scripts/amalgm-mcp/tests/workspace-reducer.test.js +326 -2228
  97. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-cloud.test.js +3 -5319
  98. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-core.test.js +1 -191
  99. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-store.test.js +17 -3140
  100. package/runtime/scripts/amalgm-mcp/tests/workspace-wall.test.js +740 -137
  101. package/runtime/scripts/amalgm-mcp/workspace/access-store.js +1 -5
  102. package/runtime/scripts/amalgm-mcp/workspace/card.js +11 -35
  103. package/runtime/scripts/amalgm-mcp/workspace/cards.js +14 -39
  104. package/runtime/scripts/amalgm-mcp/workspace/checkpoint.js +147 -587
  105. package/runtime/scripts/amalgm-mcp/workspace/git.js +34 -406
  106. package/runtime/scripts/amalgm-mcp/workspace/merge.js +181 -102
  107. package/runtime/scripts/amalgm-mcp/workspace/objects.js +56 -221
  108. package/runtime/scripts/amalgm-mcp/workspace/reducer.js +538 -1964
  109. package/runtime/scripts/amalgm-mcp/workspace/rest.js +28 -49
  110. package/runtime/scripts/amalgm-mcp/workspace/store.js +4 -77
  111. package/runtime/scripts/amalgm-mcp/workspace/transition.js +192 -1734
  112. package/runtime/scripts/amalgm-mcp/workspace/tree/inclusion.js +1 -7
  113. package/runtime/scripts/amalgm-mcp/workspace/tree/local-state.js +61 -73
  114. package/runtime/scripts/amalgm-mcp/workspace/tree/reducer.js +6 -51
  115. package/runtime/scripts/amalgm-mcp/workspace/tree/snapshot.js +8 -79
  116. package/runtime/scripts/amalgm-mcp/workspace/tree-cloud.js +146 -3461
  117. package/runtime/scripts/amalgm-mcp/workspace/tree-store.js +71 -899
  118. package/runtime/scripts/amalgm-mcp/workspace/wall.js +538 -370
  119. package/runtime/scripts/local-gateway.js +1 -0
  120. package/runtime/scripts/amalgm-mcp/state/doc-disk.js +0 -550
  121. package/runtime/scripts/amalgm-mcp/tests/code-project-stream.test.js +0 -399
  122. package/runtime/scripts/amalgm-mcp/tests/fixtures/code-project-stream-v2.json +0 -1
  123. package/runtime/scripts/amalgm-mcp/tests/workspace-durable.test.js +0 -24
  124. package/runtime/scripts/amalgm-mcp/tests/workspace-local-intent.test.js +0 -1999
  125. package/runtime/scripts/amalgm-mcp/tests/workspace-native-file-transaction.test.js +0 -364
  126. package/runtime/scripts/amalgm-mcp/tests/workspace-provenance.test.js +0 -185
  127. package/runtime/scripts/amalgm-mcp/tests/workspace-reducer-liveness.test.js +0 -26
  128. package/runtime/scripts/amalgm-mcp/tests/workspace-sync-stats.test.js +0 -119
  129. package/runtime/scripts/amalgm-mcp/tests/workspace-transition.test.js +0 -1446
  130. package/runtime/scripts/amalgm-mcp/workspace/content.js +0 -32
  131. package/runtime/scripts/amalgm-mcp/workspace/durable.js +0 -45
  132. package/runtime/scripts/amalgm-mcp/workspace/intent.js +0 -535
  133. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/BUILD.md +0 -31
  134. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/darwin-arm64/amalgm-file-transaction +0 -0
  135. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/linux-x64/amalgm-file-transaction +0 -0
  136. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/build.mjs +0 -72
  137. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/client.js +0 -165
  138. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.mod +0 -5
  139. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.sum +0 -2
  140. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/main.go +0 -2201
  141. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/manifest.json +0 -19
  142. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_darwin.go +0 -18
  143. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_linux.go +0 -18
  144. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_darwin.go +0 -33
  145. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_linux.go +0 -47
  146. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/verify.mjs +0 -43
  147. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_darwin.go +0 -114
  148. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_linux.go +0 -84
  149. package/runtime/scripts/amalgm-mcp/workspace/project-stream.js +0 -771
  150. package/runtime/scripts/amalgm-mcp/workspace/provenance.js +0 -240
  151. package/runtime/scripts/amalgm-mcp/workspace/sync-stats.js +0 -240
  152. package/runtime/scripts/amalgm-mcp/workspace/tree/floor.js +0 -100
  153. package/runtime/scripts/amalgm-mcp/workspace/tree/observation-holds.js +0 -127
  154. package/runtime/scripts/amalgm-mcp/workspace/tree/path-state.js +0 -12
  155. package/runtime/scripts/amalgm-mcp/workspace/tree/root-binding.js +0 -125
  156. package/runtime/scripts/amalgm-mcp/workspace/tree/symlinks.js +0 -76
  157. package/runtime/scripts/amalgm-mcp/workspace/tree-materialization.js +0 -3766
@@ -1,399 +0,0 @@
1
- 'use strict';
2
-
3
- const test = require('node:test');
4
- const assert = require('node:assert/strict');
5
- const crypto = require('crypto');
6
- const fs = require('fs');
7
- const os = require('os');
8
- const path = require('path');
9
-
10
- const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'amalgm-code-project-stream-'));
11
- process.env.AMALGM_DIR = path.join(tempRoot, '.amalgm');
12
- process.env.AMALGM_WORKSPACES_DIR = path.join(process.env.AMALGM_DIR, 'workspaces');
13
- process.env.AMALGM_COMPUTER_ID = 'machine-a';
14
- process.env.AMALGM_DEVICE_ID = 'machine-a';
15
- fs.mkdirSync(process.env.AMALGM_DIR, { recursive: true });
16
- fs.writeFileSync(
17
- path.join(process.env.AMALGM_DIR, 'computer.json'),
18
- JSON.stringify({
19
- computer_id: 'machine-a',
20
- user_id: '11111111-1111-4111-8111-111111111111',
21
- }),
22
- );
23
-
24
- const { closeLocalDb } = require('../state/db');
25
- const attachments = require('../state/attachments');
26
- const promotions = require('../state/promotions');
27
- const replicas = require('../state/replicas');
28
- const mutations = require('../state/mutations');
29
- const shared = require('../state/shared-rest');
30
- const projectStream = require('../workspace/project-stream');
31
-
32
- const PROJECT = '018f0000-0000-7000-8000-00000000c0de';
33
- const HEAD = '1'.repeat(40);
34
-
35
- test.after(() => {
36
- closeLocalDb();
37
- fs.rmSync(tempRoot, { recursive: true, force: true });
38
- });
39
-
40
- function call(handler, body) {
41
- return new Promise((resolve, reject) => {
42
- handler(body, (status, payload) => {
43
- if (status >= 400) reject(Object.assign(new Error(payload?.error), { status, payload }));
44
- else resolve({ status, payload });
45
- });
46
- });
47
- }
48
-
49
- function clone(value) {
50
- return JSON.parse(JSON.stringify(value));
51
- }
52
-
53
- function chunks(byte = 'a', bytes = 1) {
54
- const list = [{ sha256: byte.repeat(64), bytes }];
55
- return {
56
- checksum: crypto.createHash('sha256').update(Buffer.from(JSON.stringify(list))).digest('hex'),
57
- bytes,
58
- chunks: list,
59
- };
60
- }
61
-
62
- function bundle(oid = HEAD, byte = 'a') {
63
- return {
64
- kind: 'bundle',
65
- contract: projectStream.BUNDLE_CONTRACT,
66
- resourceId: PROJECT,
67
- oid,
68
- ref: `refs/amalgm/exports/${oid}`,
69
- ...chunks(byte),
70
- };
71
- }
72
-
73
- function cleanValue() {
74
- return { revision: null, indexDiff: '', worktreeDiff: '' };
75
- }
76
-
77
- function cardSet() {
78
- return {
79
- kind: 'card.set',
80
- card: projectStream.CARD_CONTRACT,
81
- head: { branch: 'main', oid: HEAD, detached: false },
82
- objects: bundle(),
83
- branches: [{ name: 'main', oid: HEAD, objects: bundle() }],
84
- checkpoint: {
85
- checkpoint: projectStream.CHECKPOINT_CONTRACT,
86
- baseOid: HEAD,
87
- branch: 'main',
88
- value: cleanValue(),
89
- },
90
- };
91
- }
92
-
93
- function operation(delta) {
94
- return { kind: 'code.publish', project: PROJECT, delta };
95
- }
96
-
97
- function official(snapshot, delta, version, machine, mutationId) {
98
- return projectStream._test.fold(
99
- snapshot,
100
- operation(delta),
101
- { version, machine, mutationId },
102
- );
103
- }
104
-
105
- function encodedSnapshot(snapshot) {
106
- const bytes = Buffer.from(`${JSON.stringify(snapshot)}\n`, 'utf8');
107
- return {
108
- snapshotBase64: bytes.toString('base64'),
109
- snapshotChecksum: crypto.createHash('sha256').update(bytes).digest('hex'),
110
- };
111
- }
112
-
113
- test('the shared gateway/runtime fixture folds byte-for-byte to one canonical snapshot', () => {
114
- const fixture = require('./fixtures/code-project-stream-v2.json');
115
- const folded = fixture.mutations.reduce((snapshot, mutation) => (
116
- projectStream._test.fold(
117
- snapshot,
118
- mutation.operation,
119
- {
120
- version: mutation.version,
121
- machine: mutation.device_id,
122
- mutationId: mutation.mutation_id,
123
- },
124
- )
125
- ), fixture.initialSnapshot);
126
- assert.deepEqual(folded, fixture.expectedSnapshot);
127
- });
128
-
129
- test('state-neutral events retain the independently born mutation identity', () => {
130
- const first = official(
131
- projectStream.emptySnapshot(PROJECT),
132
- cardSet(),
133
- 1,
134
- 'machine-a',
135
- 'mut_real_change_0001',
136
- );
137
- const repeatedCard = official(
138
- first,
139
- cardSet(),
140
- 2,
141
- 'machine-b',
142
- 'mut_independent_card_0002',
143
- );
144
- assert.equal(repeatedCard.version, 2);
145
- assert.equal(repeatedCard.card.mutationId, 'mut_independent_card_0002');
146
- const repeatedCheckpoint = official(repeatedCard, {
147
- kind: 'checkpoint.set',
148
- checkpoint: projectStream.CHECKPOINT_CONTRACT,
149
- baseOid: HEAD,
150
- branch: 'main',
151
- from: cleanValue(),
152
- to: cleanValue(),
153
- }, 3, 'machine-c', 'mut_independent_checkpoint_0003');
154
- assert.equal(repeatedCheckpoint.version, 3);
155
- assert.equal(
156
- repeatedCheckpoint.checkpoint.mutationId,
157
- 'mut_independent_checkpoint_0003',
158
- );
159
- });
160
-
161
- test('checkpoint publication is exact-from compare-and-set', () => {
162
- const first = official(
163
- projectStream.emptySnapshot(PROJECT),
164
- cardSet(),
165
- 1,
166
- 'machine-a',
167
- 'mut_cas_card_0001',
168
- );
169
- const staleDiff = 'diff --git a/stale.js b/stale.js\n';
170
- const stale = {
171
- revision: require('../workspace/checkpoint').revisionOf(HEAD, '', staleDiff),
172
- indexDiff: '',
173
- worktreeDiff: staleDiff,
174
- };
175
- assert.throws(
176
- () => official(first, {
177
- kind: 'checkpoint.set',
178
- checkpoint: projectStream.CHECKPOINT_CONTRACT,
179
- baseOid: HEAD,
180
- branch: 'main',
181
- from: stale,
182
- to: cleanValue(),
183
- }, 2, 'machine-b', 'mut_stale_checkpoint_0002'),
184
- (error) => error.code === 'code_project_stale_base',
185
- );
186
- });
187
-
188
- test('all branch fields use one exact Git branch grammar', () => {
189
- for (const name of ['HEAD', '@', '-bad', 'bad..ref', 'bad//ref', '.hidden/ref', 'bad.lock']) {
190
- for (const mutate of [
191
- (delta) => { delta.head.branch = name; },
192
- (delta) => { delta.branches[0].name = name; },
193
- (delta) => { delta.checkpoint.branch = name; },
194
- ]) {
195
- const delta = clone(cardSet());
196
- mutate(delta);
197
- assert.throws(
198
- () => projectStream._test.normalizeDelta(delta, PROJECT),
199
- /branch/,
200
- name,
201
- );
202
- }
203
- }
204
- });
205
-
206
- test('checkpoint sections prove their content revision', () => {
207
- const inline = {
208
- revision: 'f'.repeat(64),
209
- sections: {
210
- index: [],
211
- worktree: [{ text: 'diff --git a/app.js b/app.js\n' }],
212
- },
213
- };
214
- assert.throws(
215
- () => projectStream._test.normalizeDelta({
216
- kind: 'checkpoint.set',
217
- checkpoint: projectStream.CHECKPOINT_CONTRACT,
218
- baseOid: HEAD,
219
- branch: 'main',
220
- from: cleanValue(),
221
- to: inline,
222
- }, PROJECT),
223
- /revision/,
224
- );
225
-
226
- const payload = {
227
- kind: 'chunks',
228
- contract: projectStream.PAYLOAD_CONTRACT,
229
- resourceId: PROJECT,
230
- ...chunks('c'),
231
- };
232
- assert.throws(
233
- () => projectStream._test.normalizeDelta({
234
- kind: 'checkpoint.set',
235
- checkpoint: projectStream.CHECKPOINT_CONTRACT,
236
- baseOid: HEAD,
237
- branch: 'main',
238
- from: cleanValue(),
239
- to: {
240
- revision: null,
241
- sections: {
242
- index: [],
243
- worktree: [{ payload }],
244
- },
245
- },
246
- }, PROJECT),
247
- /revision/,
248
- );
249
- });
250
-
251
- test('inline and external sections have one Merkle revision', () => {
252
- const text = 'diff --git a/app.js b/app.js\n';
253
- const { describeBytes, manifestChecksum } = require('../workspace/content');
254
- const sectionChunks = describeBytes(Buffer.from(text, 'utf8'));
255
- const revision = require('../workspace/checkpoint').revisionOfValue(HEAD, {
256
- sections: {
257
- index: [],
258
- worktree: [{ text }],
259
- },
260
- });
261
- const inline = {
262
- revision,
263
- sections: {
264
- index: [],
265
- worktree: [{ text }],
266
- },
267
- };
268
- const external = {
269
- revision,
270
- sections: {
271
- index: [],
272
- worktree: [{
273
- payload: {
274
- kind: 'chunks',
275
- contract: projectStream.PAYLOAD_CONTRACT,
276
- resourceId: PROJECT,
277
- checksum: manifestChecksum(sectionChunks),
278
- bytes: Buffer.byteLength(text),
279
- chunks: sectionChunks,
280
- },
281
- }],
282
- },
283
- };
284
- for (const to of [inline, external]) {
285
- assert.doesNotThrow(() => projectStream._test.normalizeDelta({
286
- kind: 'checkpoint.set',
287
- checkpoint: projectStream.CHECKPOINT_CONTRACT,
288
- baseOid: HEAD,
289
- branch: 'main',
290
- from: cleanValue(),
291
- to,
292
- }, PROJECT));
293
- }
294
- });
295
-
296
- test('one content-addressed chunk cannot claim two sizes', () => {
297
- const delta = cardSet();
298
- delta.branches[0].objects = {
299
- ...delta.branches[0].objects,
300
- ...chunks('a', 2),
301
- };
302
- assert.throws(
303
- () => projectStream._test.normalizeDelta(delta, PROJECT),
304
- /two sizes/,
305
- );
306
- });
307
-
308
- test('official mutation ids use the one transport grammar', () => {
309
- assert.throws(
310
- () => official(
311
- projectStream.emptySnapshot(PROJECT),
312
- cardSet(),
313
- 1,
314
- 'machine-a',
315
- 'short',
316
- ),
317
- /mutation id/,
318
- );
319
- });
320
-
321
- test('a code project promotes as a compact v2 snapshot', async () => {
322
- const resourceId = '018f0000-0000-7000-8000-000000000001';
323
- const file = path.join(tempRoot, 'promotion.json');
324
- projectStream.writeSnapshot(file, projectStream.emptySnapshot(resourceId));
325
-
326
- const started = await call(shared.handlePromotionStart, {
327
- resourceId,
328
- path: file,
329
- contract: projectStream.STREAM_CONTRACT,
330
- });
331
- assert.equal(started.status, 202);
332
- const promotion = promotions.getPromotion(started.payload.promotion.promotionId);
333
- assert.equal(promotion.schemaVersion, 2);
334
- promotions.acknowledgePromotion(promotion.promotionId, {
335
- resourceId,
336
- authorityEpoch: 1,
337
- headVersion: 0,
338
- snapshotVersion: 0,
339
- snapshotChecksum: promotion.snapshotChecksum,
340
- snapshotKey: 'shared/code-project/promotion.bin',
341
- });
342
- assert.equal(replicas.getReplicaByResourceId(resourceId).contract, projectStream.STREAM_CONTRACT);
343
- });
344
-
345
- test('local outbox and ack are silent until the official tail folds', async () => {
346
- const resourceId = '018f0000-0000-7000-8000-000000000002';
347
- const file = path.join(tempRoot, 'official-tail.json');
348
- const empty = projectStream.emptySnapshot(resourceId);
349
- const encoded = encodedSnapshot(empty);
350
- const attachment = attachments.enqueueAttachment({
351
- attachmentId: 'att_code_project_official_tail_01',
352
- resourceId,
353
- localPath: file,
354
- contract: projectStream.STREAM_CONTRACT,
355
- });
356
- attachments.acknowledgeAttachment(attachment.attachment.attachmentId, {
357
- resourceId,
358
- authorityEpoch: 1,
359
- headVersion: 0,
360
- snapshotVersion: 0,
361
- contract: projectStream.STREAM_CONTRACT,
362
- schemaVersion: 2,
363
- ...encoded,
364
- });
365
-
366
- const project = { resourceId, file };
367
- const delta = {
368
- ...cardSet(),
369
- objects: { ...cardSet().objects, resourceId },
370
- branches: cardSet().branches.map((branch) => ({
371
- ...branch,
372
- objects: { ...branch.objects, resourceId },
373
- })),
374
- };
375
- const published = projectStream.publish(
376
- project,
377
- delta,
378
- 'mut_code_official_tail_01',
379
- );
380
- assert.equal(projectStream.readSnapshot(file, resourceId).version, 0);
381
- const claimed = mutations.claimCloudMutations().find((entry) => (
382
- entry.mutation.mutationId === published.mutation.mutationId
383
- ));
384
- mutations.acknowledgeCloudMutation(resourceId, published.mutation.mutationId, {
385
- version: 1,
386
- committedAt: '2026-07-26T12:00:00.000Z',
387
- });
388
- assert.equal(replicas.getReplicaByResourceId(resourceId).appliedVersion, 0);
389
- assert.equal(projectStream.readSnapshot(file, resourceId).version, 0);
390
-
391
- projectStream.applyCloudMutation({
392
- version: 1,
393
- committedAt: '2026-07-26T12:00:00.000Z',
394
- envelope: claimed.envelope,
395
- });
396
- assert.equal(replicas.getReplicaByResourceId(resourceId).appliedVersion, 1);
397
- assert.equal(projectStream.readSnapshot(file, resourceId).version, 1);
398
- assert.equal(mutations.listUnappliedOfficialMutations(resourceId).length, 0);
399
- });
@@ -1 +0,0 @@
1
- {"initialSnapshot":{"schemaVersion":2,"project":"018f0000-0000-7000-8000-00000000c0de","version":0,"card":null,"checkpoint":null},"mutations":[{"resource_id":"018f0000-0000-7000-8000-00000000c0de","version":1,"authority_epoch":1,"mutation_id":"mut_fixture_card_0001","actor_user_id":"11111111-1111-4111-8111-111111111111","device_id":"machine-a","base_version":0,"contract":"code-project-stream@2","schema_version":2,"operation_kind":"code.publish","operation":{"kind":"code.publish","project":"018f0000-0000-7000-8000-00000000c0de","delta":{"kind":"card.set","card":"repo-card@3","head":{"branch":"main","oid":"1111111111111111111111111111111111111111","detached":false},"objects":{"kind":"bundle","contract":"git-bundle-chunks@2","resourceId":"018f0000-0000-7000-8000-00000000c0de","oid":"1111111111111111111111111111111111111111","ref":"refs/amalgm/exports/1111111111111111111111111111111111111111","checksum":"c73bdbb6f6997aa08dfa250e66c49dd02aaa826c293bc9221f4b80614b9640ba","bytes":1,"chunks":[{"sha256":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","bytes":1}]},"branches":[{"name":"dev","oid":"2222222222222222222222222222222222222222","objects":{"kind":"bundle","contract":"git-bundle-chunks@2","resourceId":"018f0000-0000-7000-8000-00000000c0de","oid":"2222222222222222222222222222222222222222","ref":"refs/amalgm/exports/2222222222222222222222222222222222222222","checksum":"7bee928eebf88ea25f8c85aad26c2120325d4cee5ed3fbdd2ed7e92b9df46d98","bytes":2,"chunks":[{"sha256":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","bytes":2}]}},{"name":"main","oid":"1111111111111111111111111111111111111111","objects":{"kind":"bundle","contract":"git-bundle-chunks@2","resourceId":"018f0000-0000-7000-8000-00000000c0de","oid":"1111111111111111111111111111111111111111","ref":"refs/amalgm/exports/1111111111111111111111111111111111111111","checksum":"c73bdbb6f6997aa08dfa250e66c49dd02aaa826c293bc9221f4b80614b9640ba","bytes":1,"chunks":[{"sha256":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","bytes":1}]}}],"checkpoint":{"checkpoint":"repo-checkpoint@11","baseOid":"1111111111111111111111111111111111111111","branch":"main","value":{"revision":null,"indexDiff":"","worktreeDiff":""}}}},"committed_at":"2026-07-26T12:00:00.000Z"},{"resource_id":"018f0000-0000-7000-8000-00000000c0de","version":2,"authority_epoch":1,"mutation_id":"mut_fixture_checkpoint_0002","actor_user_id":"22222222-2222-4222-8222-222222222222","device_id":"machine-b","base_version":1,"contract":"code-project-stream@2","schema_version":2,"operation_kind":"code.publish","operation":{"kind":"code.publish","project":"018f0000-0000-7000-8000-00000000c0de","delta":{"kind":"checkpoint.set","checkpoint":"repo-checkpoint@11","baseOid":"1111111111111111111111111111111111111111","branch":"main","from":{"revision":null,"indexDiff":"","worktreeDiff":""},"to":{"revision":"643c62c9879267f7312002ffeb672cce37f9bd1436306430deac344dfa2944e9","indexDiff":"","worktreeDiff":"diff --git a/app.js b/app.js\n"}}},"committed_at":"2026-07-26T12:00:01.000Z"}],"expectedSnapshot":{"schemaVersion":2,"project":"018f0000-0000-7000-8000-00000000c0de","version":2,"card":{"card":"repo-card@3","head":{"branch":"main","oid":"1111111111111111111111111111111111111111","detached":false},"objects":{"kind":"bundle","contract":"git-bundle-chunks@2","resourceId":"018f0000-0000-7000-8000-00000000c0de","oid":"1111111111111111111111111111111111111111","ref":"refs/amalgm/exports/1111111111111111111111111111111111111111","checksum":"c73bdbb6f6997aa08dfa250e66c49dd02aaa826c293bc9221f4b80614b9640ba","bytes":1,"chunks":[{"sha256":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","bytes":1}]},"branches":[{"name":"dev","oid":"2222222222222222222222222222222222222222","objects":{"kind":"bundle","contract":"git-bundle-chunks@2","resourceId":"018f0000-0000-7000-8000-00000000c0de","oid":"2222222222222222222222222222222222222222","ref":"refs/amalgm/exports/2222222222222222222222222222222222222222","checksum":"7bee928eebf88ea25f8c85aad26c2120325d4cee5ed3fbdd2ed7e92b9df46d98","bytes":2,"chunks":[{"sha256":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","bytes":2}]}},{"name":"main","oid":"1111111111111111111111111111111111111111","objects":{"kind":"bundle","contract":"git-bundle-chunks@2","resourceId":"018f0000-0000-7000-8000-00000000c0de","oid":"1111111111111111111111111111111111111111","ref":"refs/amalgm/exports/1111111111111111111111111111111111111111","checksum":"c73bdbb6f6997aa08dfa250e66c49dd02aaa826c293bc9221f4b80614b9640ba","bytes":1,"chunks":[{"sha256":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","bytes":1}]}}],"machine":"machine-a","mutationId":"mut_fixture_card_0001","version":1},"checkpoint":{"checkpoint":"repo-checkpoint@11","baseOid":"1111111111111111111111111111111111111111","branch":"main","value":{"revision":"643c62c9879267f7312002ffeb672cce37f9bd1436306430deac344dfa2944e9","indexDiff":"","worktreeDiff":"diff --git a/app.js b/app.js\n"},"machine":"machine-b","mutationId":"mut_fixture_checkpoint_0002","version":2}}}
@@ -1,24 +0,0 @@
1
- 'use strict';
2
-
3
- const assert = require('node:assert/strict');
4
- const fs = require('fs');
5
- const os = require('os');
6
- const path = require('path');
7
- const test = require('node:test');
8
- const durable = require('../workspace/durable');
9
-
10
- test('durable state replacement leaves one complete value and no temporary file', () => {
11
- const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'amalgm-durable-'));
12
- const file = path.join(directory, 'state.json');
13
- try {
14
- durable.writeJson(file, { version: 1, value: 'old' });
15
- durable.writeJson(file, { version: 2, value: 'new' });
16
- assert.deepEqual(JSON.parse(fs.readFileSync(file, 'utf8')), {
17
- version: 2,
18
- value: 'new',
19
- });
20
- assert.deepEqual(fs.readdirSync(directory), ['state.json']);
21
- } finally {
22
- fs.rmSync(directory, { recursive: true, force: true });
23
- }
24
- });