amalgm 0.1.212 → 0.1.214

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amalgm",
3
- "version": "0.1.212",
3
+ "version": "0.1.214",
4
4
  "description": "Amalgm local computer runtime: login, MCP, chat, events, previews, and tunnels.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -33,6 +33,7 @@ const {
33
33
  checkpointValueReady,
34
34
  readCheckpointValue,
35
35
  revisionOf,
36
+ sameTransition,
36
37
  } = require('../workspace/checkpoint');
37
38
 
38
39
  test.after(() => {
@@ -241,3 +242,31 @@ test('a clean losing commit travels as parked metadata on a no-op checkpoint', (
241
242
  assert.deepEqual(checkpoint.to, sharedValue);
242
243
  assert.deepEqual(checkpoint.parked, parked);
243
244
  });
245
+
246
+ test('a server rail number does not turn the same parked checkpoint into new work', () => {
247
+ const value = { revision: null, indexDiff: '', worktreeDiff: '' };
248
+ const checkpoint = {
249
+ branch: 'main',
250
+ baseOid: 'a'.repeat(40),
251
+ from: value,
252
+ to: value,
253
+ parked: [{
254
+ oid: 'b'.repeat(40),
255
+ ref: `refs/amalgm/parked/${'b'.repeat(40)}`,
256
+ objects: { kind: 'bundle', checksum: 'c'.repeat(64) },
257
+ version: 12,
258
+ }],
259
+ };
260
+
261
+ assert.equal(sameTransition(checkpoint, {
262
+ ...checkpoint,
263
+ parked: checkpoint.parked.map((entry) => ({ ...entry, version: 37 })),
264
+ }), true);
265
+ assert.equal(sameTransition(checkpoint, {
266
+ ...checkpoint,
267
+ parked: checkpoint.parked.map((entry) => ({
268
+ ...entry,
269
+ objects: { ...entry.objects, checksum: 'd'.repeat(64) },
270
+ })),
271
+ }), false);
272
+ });
@@ -507,6 +507,21 @@ test('a losing commit is parked, the winning card lands exactly, and losing work
507
507
  assert.equal(fs.readFileSync(path.join(repo, 'local-dirty.txt'), 'utf8'), 'also uncommitted\n');
508
508
  assert.equal((await git(repo, 'status', '--porcelain')).trim().length > 0, true);
509
509
  assert.deepEqual(readRepoState('root:test').parked.map((entry) => entry.oid), [losingOid]);
510
+
511
+ await git(repo, 'add', '.');
512
+ await git(repo, 'commit', '-m', 'fold parked work');
513
+ const foldedOid = (await git(repo, 'rev-parse', 'HEAD')).trim();
514
+ const foldedCard = card(repo, foldedOid, 3);
515
+ const folded = await materializeRepo(foldedCard, {
516
+ repoKey: 'root:test',
517
+ card: foldedCard,
518
+ transitions: [],
519
+ parked: [],
520
+ });
521
+
522
+ assert.equal(folded.state, 'in-sync');
523
+ assert.deepEqual(readRepoState('root:test').parked, []);
524
+ assert.equal((await git(repo, 'rev-parse', `refs/amalgm/parked/${losingOid}`)).trim(), losingOid);
510
525
  });
511
526
 
512
527
  test('rail-parked peer commits become one staged checkpoint on every machine', async () => {
@@ -120,6 +120,15 @@ test('only a value different from both the materialized baseline and the rail is
120
120
  branches: [{ name: 'main', oid: oidC }],
121
121
  };
122
122
  assert.equal(hasLocalContribution(local, remoteAdvance, baseline), false);
123
+ assert.equal(hasLocalContribution(local, remoteAdvance, baseline, {
124
+ checkpoint: 'repo-checkpoint@7',
125
+ machine: 'machine-a',
126
+ branch: 'main',
127
+ baseOid: oidA,
128
+ from: { revision: null, indexDiff: '', worktreeDiff: '' },
129
+ to: { revision: 'old-work', indexDiff: '', worktreeDiff: 'patch' },
130
+ parked: [],
131
+ }), false);
123
132
  assert.equal(hasLocalContribution(
124
133
  {
125
134
  head: { branch: 'main', oid: oidB, detached: false },
@@ -96,13 +96,21 @@ function valueIdentity(value) {
96
96
  });
97
97
  }
98
98
 
99
+ function parkedIdentity(parked) {
100
+ return JSON.stringify((parked || []).map((entry) => {
101
+ const stable = { ...entry };
102
+ delete stable.version;
103
+ return stable;
104
+ }));
105
+ }
106
+
99
107
  function sameTransition(left, right) {
100
108
  return left
101
109
  && left.baseOid === right.baseOid
102
110
  && left.branch === right.branch
103
111
  && valueIdentity(left.from) === valueIdentity(right.from)
104
112
  && valueIdentity(left.to) === valueIdentity(right.to)
105
- && JSON.stringify(left.parked || []) === JSON.stringify(right.parked || []);
113
+ && parkedIdentity(left.parked) === parkedIdentity(right.parked);
106
114
  }
107
115
 
108
116
  function checkpointValue(machine, repoKey, baseOid, indexDiff, worktreeDiff) {
@@ -397,6 +405,7 @@ module.exports = {
397
405
  readCheckpointValue,
398
406
  repoKeyOfCard,
399
407
  revisionOf,
408
+ sameTransition,
400
409
  startCheckpointService,
401
410
  stopCheckpointService,
402
411
  };
@@ -513,7 +513,6 @@ async function materializeRepo(localCardInput, plan) {
513
513
  : refreshed;
514
514
  const previous = readRepoState(plan.repoKey);
515
515
  const parked = uniqueParked([
516
- ...(previous?.parked || []),
517
516
  ...(plan.parked || []),
518
517
  ...(cardResult.parked || []),
519
518
  ]);
@@ -17,7 +17,7 @@ const { AMALGM_DIR } = require('../config');
17
17
  const { subscribeStateEvents } = require('../state/events');
18
18
  const { machineId, userId } = require('./identity');
19
19
  const { listRepoCards } = require('./cards');
20
- const { readCheckpoint, repoKeyOfCard } = require('./checkpoint');
20
+ const { readCheckpoint, repoKeyOfCard, sameTransition } = require('./checkpoint');
21
21
 
22
22
  const WALL_CONTRACT = 'code-project@3';
23
23
  const PROJECT_DIR = path.join(AMALGM_DIR, 'state', 'code-projects');
@@ -209,17 +209,6 @@ function samePosition(left, right) {
209
209
  && Boolean(left?.head?.detached) === Boolean(right?.head?.detached);
210
210
  }
211
211
 
212
- function checkpointIdentity(checkpoint) {
213
- if (!checkpoint) return null;
214
- return JSON.stringify({
215
- baseOid: checkpoint.baseOid,
216
- branch: checkpoint.branch,
217
- from: checkpoint.from,
218
- to: checkpoint.to,
219
- parked: checkpoint.parked || [],
220
- });
221
- }
222
-
223
212
  function oidMap(refs) {
224
213
  return new Map((refs || []).map((ref) => [ref.name, ref.oid ?? null]));
225
214
  }
@@ -271,14 +260,15 @@ function hasLocalContribution(card, plan, baseline, checkpoint = null, previousC
271
260
  }
272
261
 
273
262
  if (
274
- checkpoint
263
+ onRail
264
+ && checkpoint
275
265
  && checkpoint.baseOid === card.head?.oid
276
266
  && checkpoint.branch === card.head?.branch
277
267
  ) {
278
268
  const latest = [...(plan.transitions || [])]
279
269
  .reverse()
280
270
  .find((entry) => entry.machine === checkpoint.machine);
281
- if (checkpointIdentity(latest) !== checkpointIdentity(checkpoint)) return true;
271
+ if (!sameTransition(latest, checkpoint)) return true;
282
272
  }
283
273
  return false;
284
274
  }
@@ -444,7 +434,7 @@ function stampCards(cards, previousCards, sharedPlan, baseline, mutationId, proj
444
434
  : [];
445
435
  const last = history.at(-1);
446
436
  const checkpoints = currentCheckpoint
447
- ? (checkpointIdentity(last) === checkpointIdentity(currentCheckpoint)
437
+ ? (sameTransition(last, currentCheckpoint)
448
438
  ? history
449
439
  : [...history, { ...currentCheckpoint, mutationId }])
450
440
  : history;