amalgm 0.1.239 → 0.1.241

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 (87) hide show
  1. package/lib/shared-realtime-tunnel.js +18 -4
  2. package/package.json +1 -1
  3. package/runtime/scripts/amalgm-mcp/browser/cookie-jar.js +68 -20
  4. package/runtime/scripts/amalgm-mcp/project-context/store.js +87 -19
  5. package/runtime/scripts/amalgm-mcp/server/routes/state.js +13 -0
  6. package/runtime/scripts/amalgm-mcp/state/attachments.js +40 -12
  7. package/runtime/scripts/amalgm-mcp/state/db.js +216 -17
  8. package/runtime/scripts/amalgm-mcp/state/doc-disk.js +550 -0
  9. package/runtime/scripts/amalgm-mcp/state/docs.js +1101 -301
  10. package/runtime/scripts/amalgm-mcp/state/mutation-contracts.js +99 -0
  11. package/runtime/scripts/amalgm-mcp/state/mutations.js +507 -130
  12. package/runtime/scripts/amalgm-mcp/state/promotions.js +21 -1
  13. package/runtime/scripts/amalgm-mcp/state/replicas.js +134 -13
  14. package/runtime/scripts/amalgm-mcp/state/shared-rest.js +14 -8
  15. package/runtime/scripts/amalgm-mcp/tests/browser-cookie-cloud.test.js +193 -0
  16. package/runtime/scripts/amalgm-mcp/tests/code-project-stream.test.js +313 -94
  17. package/runtime/scripts/amalgm-mcp/tests/fixtures/code-project-stream-v2.json +1 -0
  18. package/runtime/scripts/amalgm-mcp/tests/project-context.test.js +32 -17
  19. package/runtime/scripts/amalgm-mcp/tests/shared-tunnel-rehydration.test.js +84 -0
  20. package/runtime/scripts/amalgm-mcp/tests/state-docs.test.js +376 -13
  21. package/runtime/scripts/amalgm-mcp/tests/state-mutations.test.js +309 -0
  22. package/runtime/scripts/amalgm-mcp/tests/state-shared-replica.test.js +758 -30
  23. package/runtime/scripts/amalgm-mcp/tests/workspace-cards-store.test.js +72 -3
  24. package/runtime/scripts/amalgm-mcp/tests/workspace-cards.test.js +33 -6
  25. package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint-reducer.test.js +27 -0
  26. package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint.test.js +334 -191
  27. package/runtime/scripts/amalgm-mcp/tests/workspace-durable.test.js +24 -0
  28. package/runtime/scripts/amalgm-mcp/tests/workspace-local-intent.test.js +1999 -0
  29. package/runtime/scripts/amalgm-mcp/tests/workspace-native-file-transaction.test.js +364 -0
  30. package/runtime/scripts/amalgm-mcp/tests/workspace-object-tunnel.test.js +98 -4
  31. package/runtime/scripts/amalgm-mcp/tests/workspace-objects.test.js +156 -8
  32. package/runtime/scripts/amalgm-mcp/tests/workspace-provenance.test.js +185 -0
  33. package/runtime/scripts/amalgm-mcp/tests/workspace-publication-invariants.test.js +174 -269
  34. package/runtime/scripts/amalgm-mcp/tests/workspace-reducer-liveness.test.js +26 -0
  35. package/runtime/scripts/amalgm-mcp/tests/workspace-reducer.test.js +2060 -407
  36. package/runtime/scripts/amalgm-mcp/tests/workspace-sync-stats.test.js +119 -0
  37. package/runtime/scripts/amalgm-mcp/tests/workspace-transition.test.js +1446 -0
  38. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-cloud.test.js +5319 -3
  39. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-core.test.js +191 -1
  40. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-store.test.js +3140 -17
  41. package/runtime/scripts/amalgm-mcp/tests/workspace-wall.test.js +135 -637
  42. package/runtime/scripts/amalgm-mcp/workspace/access-store.js +5 -1
  43. package/runtime/scripts/amalgm-mcp/workspace/card.js +7 -7
  44. package/runtime/scripts/amalgm-mcp/workspace/cards.js +36 -12
  45. package/runtime/scripts/amalgm-mcp/workspace/checkpoint.js +436 -173
  46. package/runtime/scripts/amalgm-mcp/workspace/content.js +32 -0
  47. package/runtime/scripts/amalgm-mcp/workspace/durable.js +45 -0
  48. package/runtime/scripts/amalgm-mcp/workspace/git.js +391 -37
  49. package/runtime/scripts/amalgm-mcp/workspace/intent.js +535 -0
  50. package/runtime/scripts/amalgm-mcp/workspace/merge.js +89 -6
  51. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/BUILD.md +31 -0
  52. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/darwin-arm64/amalgm-file-transaction +0 -0
  53. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/linux-x64/amalgm-file-transaction +0 -0
  54. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/build.mjs +72 -0
  55. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/client.js +165 -0
  56. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.mod +5 -0
  57. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.sum +2 -0
  58. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/main.go +2201 -0
  59. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/manifest.json +19 -0
  60. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_darwin.go +18 -0
  61. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_linux.go +18 -0
  62. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_darwin.go +33 -0
  63. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_linux.go +47 -0
  64. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/verify.mjs +43 -0
  65. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_darwin.go +114 -0
  66. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_linux.go +84 -0
  67. package/runtime/scripts/amalgm-mcp/workspace/objects.js +185 -55
  68. package/runtime/scripts/amalgm-mcp/workspace/project-stream.js +616 -168
  69. package/runtime/scripts/amalgm-mcp/workspace/provenance.js +240 -0
  70. package/runtime/scripts/amalgm-mcp/workspace/reducer.js +1979 -570
  71. package/runtime/scripts/amalgm-mcp/workspace/rest.js +49 -28
  72. package/runtime/scripts/amalgm-mcp/workspace/store.js +77 -4
  73. package/runtime/scripts/amalgm-mcp/workspace/sync-stats.js +240 -0
  74. package/runtime/scripts/amalgm-mcp/workspace/transition.js +1729 -192
  75. package/runtime/scripts/amalgm-mcp/workspace/tree/floor.js +100 -0
  76. package/runtime/scripts/amalgm-mcp/workspace/tree/inclusion.js +7 -1
  77. package/runtime/scripts/amalgm-mcp/workspace/tree/local-state.js +73 -61
  78. package/runtime/scripts/amalgm-mcp/workspace/tree/observation-holds.js +127 -0
  79. package/runtime/scripts/amalgm-mcp/workspace/tree/path-state.js +12 -0
  80. package/runtime/scripts/amalgm-mcp/workspace/tree/reducer.js +51 -6
  81. package/runtime/scripts/amalgm-mcp/workspace/tree/root-binding.js +125 -0
  82. package/runtime/scripts/amalgm-mcp/workspace/tree/snapshot.js +79 -8
  83. package/runtime/scripts/amalgm-mcp/workspace/tree/symlinks.js +76 -0
  84. package/runtime/scripts/amalgm-mcp/workspace/tree-cloud.js +3480 -165
  85. package/runtime/scripts/amalgm-mcp/workspace/tree-materialization.js +3766 -0
  86. package/runtime/scripts/amalgm-mcp/workspace/tree-store.js +899 -71
  87. package/runtime/scripts/amalgm-mcp/workspace/wall.js +352 -497
@@ -2,6 +2,7 @@
2
2
 
3
3
  const test = require('node:test');
4
4
  const assert = require('node:assert/strict');
5
+ const crypto = require('crypto');
5
6
  const fs = require('fs');
6
7
  const os = require('os');
7
8
  const path = require('path');
@@ -21,20 +22,22 @@ fs.writeFileSync(
21
22
  );
22
23
 
23
24
  const { closeLocalDb } = require('../state/db');
25
+ const replicas = require('../state/replicas');
24
26
  const {
25
- _test: checkpointTest,
26
27
  CHECKPOINT_CONTRACT,
27
- checkpointFile,
28
28
  sameTransition,
29
29
  } = require('../workspace/checkpoint');
30
- const { parkedForState } = require('../workspace/reducer');
31
- const {
32
- _test: wallTest,
33
- hasLocalContribution,
34
- publicationStatus,
35
- stampCards,
36
- } = require('../workspace/wall');
30
+ const { classifyBranchRefs } = require('../workspace/reducer');
37
31
  const projectStream = require('../workspace/project-stream');
32
+ const wall = require('../workspace/wall');
33
+
34
+ const PROJECT = '018f0000-0000-7000-8000-000000000040';
35
+ const HEAD = 'a'.repeat(40);
36
+ const project = wall.bindProject(
37
+ PROJECT,
38
+ '11111111-1111-4111-8111-111111111111',
39
+ path.join(tempRoot, 'repo'),
40
+ );
38
41
 
39
42
  test.after(() => {
40
43
  closeLocalDb();
@@ -43,308 +46,210 @@ test.after(() => {
43
46
 
44
47
  const rules = {
45
48
  card: {
46
- identity: 'branch-and-commit-content',
47
- ownership: 'originator-publishes',
48
- liveness: 'shared-wall-outbox',
49
- gating: 'defines-winning-card',
50
- },
51
- branch: {
52
- identity: 'ref-name-and-commit-content',
53
- ownership: 'originator-publishes',
54
- liveness: 'shared-wall-outbox',
55
- gating: 'per-ref-rail-order',
49
+ identity: 'HEAD, complete branch map, and checkpoint content',
50
+ ownership: 'local until that exact value returns officially',
51
+ liveness: 'one durable outbox proposal retries',
52
+ gating: 'publish only while current',
56
53
  },
57
54
  checkpoint: {
58
- identity: 'from-and-to-content',
59
- ownership: 'originator-publishes',
60
- liveness: 'shared-wall-outbox',
61
- gating: 'winning-card-only',
62
- },
63
- parked: {
64
- identity: 'commit-and-object-content',
65
- ownership: 'holder-publishes-until-acknowledged',
66
- liveness: 'shared-wall-outbox',
67
- gating: 'inside-winning-card-checkpoint',
55
+ identity: 'exact from and to working-tree content',
56
+ ownership: 'local until that exact value returns officially',
57
+ liveness: 'one durable outbox proposal retries',
58
+ gating: 'compare-and-set from the current card',
68
59
  },
69
60
  snapshot: {
70
- identity: 'state-through-official-version',
71
- ownership: 'authority-derived',
72
- liveness: 'hydrates-then-replays-tail',
73
- gating: 'never-a-new-event',
61
+ identity: 'canonical state through one official version',
62
+ ownership: 'server-derived only',
63
+ liveness: 'hydrate then replay the contiguous tail',
64
+ gating: 'never creates a content event',
65
+ },
66
+ transport: {
67
+ identity: 'content-addressed bytes',
68
+ ownership: 'no repo meaning',
69
+ liveness: 'repair or surface; never wait forever',
70
+ gating: 'all bytes exist before numbering',
74
71
  },
75
72
  };
76
73
 
77
- test('the publication model has one explicit rule for every value and property', () => {
78
- assert.deepEqual(Object.keys(rules), ['card', 'branch', 'checkpoint', 'parked', 'snapshot']);
74
+ test('the complete publication model has four properties and no hidden value type', () => {
75
+ assert.deepEqual(Object.keys(rules), ['card', 'checkpoint', 'snapshot', 'transport']);
79
76
  for (const rule of Object.values(rules)) {
80
77
  assert.deepEqual(Object.keys(rule), ['identity', 'ownership', 'liveness', 'gating']);
81
78
  assert.equal(Object.values(rule).every(Boolean), true);
82
79
  }
83
- assert.deepEqual(
84
- new Set(['card', 'branch', 'checkpoint', 'parked'].map((name) => rules[name].liveness)),
85
- new Set(['shared-wall-outbox']),
86
- );
87
80
  });
88
81
 
89
- test('publication requires one current applied rail position and no unresolved send', () => {
90
- const repoKey = 'root:currentness';
91
- const project = require('../workspace/wall').projectForRepo(repoKey);
92
- const resourceId = project.resourceId;
93
- const file = project.file;
94
- projectStream.writeSnapshot(file, projectStream._test.emptySnapshot(repoKey));
95
- require('../state/replicas').registerReplica({
96
- resourceId,
97
- localResource: `${projectStream.LOCAL_RESOURCE_PREFIX}${resourceId}`,
98
- localPath: file,
82
+ function chunks(byte = 'a', bytes = 1) {
83
+ const list = [{ sha256: byte.repeat(64), bytes }];
84
+ return {
85
+ checksum: crypto.createHash('sha256').update(JSON.stringify(list)).digest('hex'),
86
+ bytes,
87
+ chunks: list,
88
+ };
89
+ }
90
+
91
+ function bundle(oid = HEAD, byte = 'a') {
92
+ return {
93
+ kind: 'bundle',
94
+ contract: projectStream.BUNDLE_CONTRACT,
95
+ resourceId: PROJECT,
96
+ oid,
97
+ ref: `refs/amalgm/exports/${oid}`,
98
+ ...chunks(byte),
99
+ };
100
+ }
101
+
102
+ function cardSet() {
103
+ return {
104
+ kind: 'card.set',
105
+ card: projectStream.CARD_CONTRACT,
106
+ head: { branch: 'main', oid: HEAD, detached: false },
107
+ objects: bundle(),
108
+ branches: [{ name: 'main', oid: HEAD, objects: bundle() }],
109
+ checkpoint: {
110
+ checkpoint: projectStream.CHECKPOINT_CONTRACT,
111
+ baseOid: HEAD,
112
+ branch: 'main',
113
+ value: { revision: null, indexDiff: '', worktreeDiff: '' },
114
+ },
115
+ };
116
+ }
117
+
118
+ test('publication requires one current applied position and no unresolved send', () => {
119
+ projectStream.writeSnapshot(project.file, projectStream.emptySnapshot(PROJECT));
120
+ replicas.registerReplica({
121
+ resourceId: PROJECT,
122
+ localResource: `${projectStream.LOCAL_RESOURCE_PREFIX}${PROJECT}`,
123
+ localPath: project.file,
99
124
  contract: projectStream.STREAM_CONTRACT,
100
- schemaVersion: 1,
125
+ schemaVersion: 2,
101
126
  authorityEpoch: 1,
102
127
  appliedVersion: 12,
128
+ snapshotVersion: 0,
103
129
  });
104
130
 
105
- assert.deepEqual(publicationStatus(repoKey, { appliedThrough: 11 }), {
106
- receivedThrough: 12,
107
- appliedThrough: 11,
108
- pending: 0,
109
- current: false,
110
- });
111
- assert.deepEqual(publicationStatus(repoKey, { appliedThrough: 12 }), {
112
- receivedThrough: 12,
113
- appliedThrough: 12,
114
- pending: 0,
115
- current: true,
116
- });
117
- projectStream.publish(project, {
118
- wall: 'code-project@6',
119
- project: repoKey,
120
- machine: 'machine-a',
121
- mutationId: 'mut_currentness_pending_01',
122
- publishedAt: '2026-07-26T00:00:00.000Z',
123
- cards: [],
124
- });
125
- assert.deepEqual(publicationStatus(repoKey, { appliedThrough: 12 }), {
126
- receivedThrough: 12,
127
- appliedThrough: 12,
128
- pending: 1,
129
- current: false,
130
- });
131
+ assert.equal(wall.publicationStatus(project.repoKey, { appliedThrough: 11 }).current, false);
132
+ assert.equal(wall.publicationStatus(project.repoKey, { appliedThrough: 12 }).current, true);
133
+
134
+ projectStream.publish(project, cardSet(), 'mut_publication_gate_01');
135
+ const waiting = wall.publicationStatus(project.repoKey, { appliedThrough: 12 });
136
+ assert.equal(waiting.pending, 1);
137
+ assert.equal(waiting.current, false);
131
138
  });
132
139
 
133
- test('server rail numbers do not change checkpoint or parked identity', () => {
134
- const oid = 'a'.repeat(40);
140
+ test('server stamps and object locators do not invent new repo meaning', () => {
135
141
  const transition = {
136
142
  checkpoint: CHECKPOINT_CONTRACT,
137
143
  machine: 'machine-a',
138
- repoKey: 'root:test',
144
+ repoKey: project.repoKey,
139
145
  branch: 'main',
140
- baseOid: oid,
146
+ baseOid: HEAD,
141
147
  from: { revision: null, indexDiff: '', worktreeDiff: '' },
142
- to: { revision: 'work-a', indexDiff: '', worktreeDiff: 'patch-a' },
143
- parked: [{
144
- oid: 'b'.repeat(40),
145
- ref: `refs/amalgm/parked/${'b'.repeat(40)}`,
146
- objects: { kind: 'bundle', checksum: 'c'.repeat(64) },
147
- }],
148
+ to: { revision: 'b'.repeat(64), indexDiff: '', worktreeDiff: 'patch-a' },
148
149
  };
149
150
  assert.equal(sameTransition(transition, {
150
151
  ...transition,
151
- mutationId: 'mut_server_metadata',
152
+ mutationId: 'mut_server_metadata_0001',
152
153
  version: 41,
153
- parked: transition.parked.map((entry) => ({ ...entry, version: 41 })),
154
154
  }), true);
155
- assert.equal(sameTransition(transition, {
156
- ...transition,
157
- to: { ...transition.to, revision: 'different-work' },
158
- }), false);
159
- assert.equal(sameTransition(transition, {
160
- ...transition,
161
- parked: transition.parked.map((entry) => ({
162
- ...entry,
163
- objects: { ...entry.objects, checksum: 'd'.repeat(64) },
164
- })),
165
- }), false);
166
- });
167
155
 
168
- test('receivers stay silent and only unacknowledged local parked work republishes', () => {
169
- const head = 'a'.repeat(40);
170
- const local = {
171
- head: { branch: 'main', oid: head, detached: false },
172
- refs: [{ name: 'main', oid: head }],
156
+ const first = {
157
+ head: { branch: 'main', oid: HEAD, detached: false },
158
+ refs: [{ name: 'main', oid: HEAD, objects: bundle(HEAD, 'a') }],
173
159
  };
174
- const transition = {
175
- checkpoint: CHECKPOINT_CONTRACT,
176
- machine: 'machine-a',
177
- repoKey: 'root:test',
178
- branch: 'main',
179
- baseOid: head,
180
- from: { revision: null, indexDiff: '', worktreeDiff: '' },
181
- to: { revision: 'shared-work', indexDiff: '', worktreeDiff: 'patch' },
182
- parked: [],
183
- };
184
- const plan = {
185
- card: { head: { branch: 'main', oid: head, detached: false } },
186
- branches: [{ name: 'main', oid: head }],
187
- transitions: [{ ...transition, version: 9 }],
188
- };
189
- const baseline = {
190
- branch: 'main',
191
- baseOid: head,
192
- branches: [{ name: 'main', oid: head }],
160
+ const second = {
161
+ ...first,
162
+ objects: bundle(HEAD, 'b'),
163
+ refs: [{ ...first.refs[0], objects: bundle(HEAD, 'c') }],
193
164
  };
194
- assert.equal(hasLocalContribution(local, plan, baseline, transition), false);
195
-
196
- const localParked = { oid: 'b'.repeat(40), objects: { kind: 'bundle', checksum: 'local' } };
197
- const unsentParked = { oid: 'c'.repeat(40), objects: { kind: 'bundle', checksum: 'unsent' } };
198
- const peerParked = {
199
- oid: 'd'.repeat(40),
200
- objects: { kind: 'bundle', checksum: 'peer' },
201
- version: 9,
202
- };
203
- assert.deepEqual(
204
- checkpointTest.localParkedEntries(
205
- { ...transition, parked: [localParked] },
206
- { parked: [{ ...localParked, version: 10 }, peerParked, unsentParked] },
207
- local,
208
- ),
209
- [unsentParked],
210
- );
211
- assert.deepEqual(parkedForState([localParked], [], []), [localParked]);
212
- assert.deepEqual(
213
- parkedForState([localParked], [{ ...localParked, version: 10 }], []),
214
- [{ ...localParked, version: 10 }],
215
- );
216
- assert.deepEqual(parkedForState([{ ...localParked, version: 10 }], [], []), []);
165
+ assert.equal(wall._test.sameCardState(first, second), true);
166
+ assert.equal(wall._test.sameCardState(first, {
167
+ ...second,
168
+ refs: [{ ...second.refs[0], oid: 'd'.repeat(40) }],
169
+ }), false);
217
170
  });
218
171
 
219
- test('card, branch, checkpoint, and parked work ride one wall mutation', () => {
220
- const repoKey = 'https://github.com/amalgm-inc/publication-invariant-test';
221
- const head = 'a'.repeat(40);
222
- const parkedOid = 'b'.repeat(40);
223
- const checkpoint = {
224
- checkpoint: CHECKPOINT_CONTRACT,
225
- machine: 'machine-a',
226
- repoKey,
227
- branch: 'main',
228
- baseOid: head,
229
- from: { revision: null, indexDiff: '', worktreeDiff: '' },
230
- to: { revision: 'work-a', indexDiff: '', worktreeDiff: 'patch-a' },
231
- parked: [{
232
- oid: parkedOid,
233
- ref: `refs/amalgm/parked/${parkedOid}`,
234
- objects: { kind: 'bundle', checksum: 'c'.repeat(64) },
235
- }],
172
+ test('only exact durable branch intent can hold a local value against the rail', () => {
173
+ const a = 'a'.repeat(40);
174
+ const b = 'b'.repeat(40);
175
+ const c = 'c'.repeat(40);
176
+ const d = 'd'.repeat(40);
177
+ const card = { head: { branch: 'main', oid: HEAD } };
178
+ const owned = {
179
+ base: {
180
+ card: {
181
+ head: card.head,
182
+ branches: [{ name: 'feature', oid: a }],
183
+ },
184
+ },
185
+ local: {
186
+ card: {
187
+ head: card.head,
188
+ branches: [{ name: 'feature', oid: c }],
189
+ },
190
+ },
236
191
  };
237
- const file = checkpointFile('machine-a', repoKey);
238
- fs.mkdirSync(path.dirname(file), { recursive: true });
239
- fs.writeFileSync(file, `${JSON.stringify(checkpoint)}\n`);
240
192
 
241
- const mutationId = 'mut_one_shared_wall_outbox';
242
- const stamped = stampCards([{
243
- card: 'repo-card@2',
244
- machine: 'machine-a',
245
- replica: 'rpl_publication_test',
246
- kind: 'primary',
247
- repo: { remote: repoKey },
248
- head: { branch: 'main', oid: head, detached: false },
249
- refs: [
250
- { name: 'main', oid: head },
251
- { name: 'feature', oid: head },
193
+ const first = classifyBranchRefs(
194
+ {
195
+ card,
196
+ branches: [
197
+ { name: 'main', oid: HEAD },
198
+ { name: 'feature', oid: b },
199
+ ],
200
+ },
201
+ [
202
+ { name: 'main', oid: HEAD },
203
+ { name: 'feature', oid: c },
252
204
  ],
253
- health: 'healthy',
254
- }], [], null, null, mutationId, {
255
- repoKey,
256
- resourceId: 'shr_publication_invariant_test',
257
- })[0];
258
-
259
- assert.equal(stamped.positionMutationId, mutationId);
260
- assert.equal(stamped.branches.every((ref) => ref.mutationId === mutationId), true);
261
- assert.equal(stamped.checkpoints[0].mutationId, mutationId);
262
- assert.equal(stamped.checkpoints[0].parked[0].oid, parkedOid);
205
+ owned,
206
+ );
207
+ assert.deepEqual(first.changes, []);
208
+ assert.deepEqual(first.pending, [{ name: 'feature', oid: c }]);
209
+
210
+ const acknowledged = classifyBranchRefs(
211
+ {
212
+ card,
213
+ branches: [
214
+ { name: 'main', oid: HEAD },
215
+ { name: 'feature', oid: c },
216
+ ],
217
+ },
218
+ [
219
+ { name: 'main', oid: HEAD },
220
+ { name: 'feature', oid: c },
221
+ ],
222
+ null,
223
+ );
224
+ assert.deepEqual(acknowledged.pending, []);
225
+
226
+ const later = classifyBranchRefs(
227
+ {
228
+ card,
229
+ branches: [
230
+ { name: 'main', oid: HEAD },
231
+ { name: 'feature', oid: d },
232
+ ],
233
+ },
234
+ [
235
+ { name: 'main', oid: HEAD },
236
+ { name: 'feature', oid: c },
237
+ ],
238
+ null,
239
+ );
240
+ assert.deepEqual(later.changes, [{ branch: 'feature', expectedOid: c, oid: d }]);
263
241
  });
264
242
 
265
- test('a new card waits for its bundle instead of publishing transport metadata twice', () => {
266
- const oldOid = 'a'.repeat(40);
267
- const newOid = 'b'.repeat(40);
268
- const plan = {
269
- card: { head: { branch: 'main', oid: oldOid, detached: false } },
270
- branches: [{ name: 'main', oid: oldOid }],
271
- };
243
+ test('a card waits for every referenced commit without creating transport events', () => {
272
244
  const pending = {
273
- head: { branch: 'main', oid: newOid, detached: false },
245
+ head: { branch: 'main', oid: HEAD, detached: false },
274
246
  objects: { kind: 'pending' },
275
- refs: [{ name: 'main', oid: newOid, objects: { kind: 'pending' } }],
247
+ refs: [{ name: 'main', oid: HEAD, objects: { kind: 'pending' } }],
276
248
  };
277
- const ready = {
249
+ assert.equal(wall._test.hasPendingContributionObjects(pending), true);
250
+ assert.equal(wall._test.hasPendingContributionObjects({
278
251
  ...pending,
279
- objects: { kind: 'bundle' },
280
- refs: pending.refs.map((ref) => ({ ...ref, objects: { kind: 'bundle' } })),
281
- };
282
-
283
- assert.equal(wallTest.hasPendingContributionObjects(pending, plan), true);
284
- assert.equal(wallTest.hasPendingContributionObjects(ready, plan), false);
285
- });
286
-
287
- test('an unnumbered branch waits for its bundle before sharing the card', () => {
288
- const oid = 'b'.repeat(40);
289
- const card = {
290
- head: { branch: 'main', oid: 'a'.repeat(40) },
291
- refs: [{ name: 'topic', oid, objects: { kind: 'pending' } }],
292
- };
293
- const plan = {
294
- card: { head: { branch: 'main', oid: 'a'.repeat(40) } },
295
- branches: [{ name: 'topic', oid, version: null }],
296
- };
297
- assert.equal(wallTest.hasPendingContributionObjects(card, plan), true);
298
- plan.branches[0].version = 50;
299
- assert.equal(wallTest.hasPendingContributionObjects(card, plan), false);
300
- });
301
-
302
- test('transport metadata without a real card, branch, or checkpoint change is silent', () => {
303
- const previousMutation = 'mut_previous_content';
304
- const metadataOnly = [{
305
- positionMutationId: previousMutation,
306
- branches: [{ name: 'main', mutationId: previousMutation }],
307
- checkpoints: [{ mutationId: previousMutation }],
308
- }];
309
- assert.equal(wallTest.cardsUseMutation(metadataOnly, 'mut_new_transport_metadata'), false);
310
- assert.equal(wallTest.cardsUseMutation([{
311
- ...metadataOnly[0],
312
- checkpoints: [{ mutationId: 'mut_real_checkpoint' }],
313
- }], 'mut_real_checkpoint'), true);
314
- });
315
-
316
- test('a snapshot is exactly one latest numbered record per machine', () => {
317
- const project = 'root:snapshot';
318
- const snapshot = projectStream._test.emptySnapshot(project);
319
- const record = (machine, mutationId, value) => ({
320
- wall: 'code-project@6',
321
- project,
322
- machine,
323
- mutationId,
324
- publishedAt: '2026-07-26T00:00:00.000Z',
325
- cards: [{ value }],
326
- });
327
- const afterA = projectStream._test.applyRecord(
328
- snapshot,
329
- record('machine-a', 'mut_snapshot_machine_a1', 'old-a'),
330
- 1,
331
- );
332
- const afterB = projectStream._test.applyRecord(
333
- afterA,
334
- record('machine-b', 'mut_snapshot_machine_b1', 'current-b'),
335
- 2,
336
- );
337
- const compacted = projectStream._test.applyRecord(
338
- afterB,
339
- record('machine-a', 'mut_snapshot_machine_a2', 'current-a'),
340
- 3,
341
- );
342
- assert.equal(compacted.version, 3);
343
- assert.deepEqual(
344
- compacted.records.map((entry) => [entry.machine, entry.version, entry.cards[0].value]),
345
- [
346
- ['machine-a', 3, 'current-a'],
347
- ['machine-b', 2, 'current-b'],
348
- ],
349
- );
252
+ objects: bundle(),
253
+ refs: [{ ...pending.refs[0], objects: bundle() }],
254
+ }), false);
350
255
  });
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ const assert = require('node:assert/strict');
4
+ const test = require('node:test');
5
+
6
+ const { repairDelayForPass } = require('../workspace/reducer');
7
+
8
+ test('every non-terminal wait gets the same bounded repair retry', () => {
9
+ assert.equal(
10
+ repairDelayForPass([{ state: 'waiting', reason: 'a-new-reason-the-code-has-never-seen' }]),
11
+ 1_000,
12
+ );
13
+ assert.equal(
14
+ repairDelayForPass([{ state: 'waiting', reason: 'another-reason' }]),
15
+ 1_000,
16
+ );
17
+ });
18
+
19
+ test('a materialization pass is verified again after it moves the repo', () => {
20
+ assert.equal(repairDelayForPass([{ state: 'in-sync' }], true), 1_000);
21
+ });
22
+
23
+ test('settled repos and terminal corruption do not enter a fast retry loop', () => {
24
+ assert.equal(repairDelayForPass([{ state: 'in-sync' }]), null);
25
+ assert.equal(repairDelayForPass([{ state: 'error', reason: 'invalid official payload' }]), null);
26
+ });