amalgm 0.1.209 → 0.1.211

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.209",
3
+ "version": "0.1.211",
4
4
  "description": "Amalgm local computer runtime: login, MCP, chat, events, previews, and tunnels.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -146,10 +146,25 @@ test('only a value different from both the materialized baseline and the rail is
146
146
  baseline,
147
147
  null,
148
148
  {
149
+ positionVersion: 10,
149
150
  head: { branch: 'main', oid: oidB, detached: false },
150
- branches: [{ name: 'main', oid: oidB }],
151
+ branches: [{ name: 'main', oid: oidB, version: 10 }],
151
152
  },
152
153
  ), false);
154
+ assert.equal(hasLocalContribution(
155
+ {
156
+ head: { branch: 'main', oid: oidB, detached: false },
157
+ refs: [{ name: 'main', oid: oidB }],
158
+ },
159
+ remoteAdvance,
160
+ baseline,
161
+ null,
162
+ {
163
+ positionVersion: null,
164
+ head: { branch: 'main', oid: oidB, detached: false },
165
+ branches: [{ name: 'main', oid: oidB, version: null }],
166
+ },
167
+ ), true);
153
168
  assert.equal(hasLocalContribution(
154
169
  local,
155
170
  plan,
@@ -161,8 +176,8 @@ test('only a value different from both the materialized baseline and the rail is
161
176
  {
162
177
  head: { branch: 'main', oid: oidA, detached: false },
163
178
  branches: [
164
- { name: 'main', oid: oidA },
165
- { name: 'feature', oid: oidB },
179
+ { name: 'main', oid: oidA, version: 10 },
180
+ { name: 'feature', oid: oidB, version: 10 },
166
181
  ],
167
182
  },
168
183
  ), true);
@@ -285,6 +300,13 @@ test('a repo project appends immutable machine records', async () => {
285
300
  assert.equal(entries[0].cards[0].positionMutationId, first.mutationId);
286
301
  assert.equal(entries[0].cards[0].positionVersion, null);
287
302
  assert.equal(publishedCardFor(refreshed.cards[0]), null);
303
+ const awaitingNumber = publishWall(repoKey);
304
+ assert.equal(awaitingNumber.published, false);
305
+ assert.equal(awaitingNumber.reason, 'unchanged');
306
+ assert.equal(
307
+ require('../workspace/reducer').localCardMayMaterialize(null, awaitingNumber),
308
+ false,
309
+ );
288
310
 
289
311
  acknowledgeCloudMutation(project.resourceId, first.mutationId, {
290
312
  version: 1,
@@ -663,3 +685,27 @@ test('a restarted wall publishes once even when the project is already attached'
663
685
  > before.publishes + before.publishSkips,
664
686
  );
665
687
  });
688
+
689
+ test('the periodic project check retries an unsent wall', async () => {
690
+ const originalSetInterval = global.setInterval;
691
+ let periodicCheck = null;
692
+ global.setInterval = (callback) => {
693
+ periodicCheck = callback;
694
+ return { unref() {} };
695
+ };
696
+ try {
697
+ startWallService();
698
+ await new Promise((resolve) => setTimeout(resolve, 100));
699
+ const before = wallStats();
700
+ periodicCheck();
701
+ await new Promise((resolve) => setTimeout(resolve, 100));
702
+ const after = wallStats();
703
+ assert.ok(
704
+ after.publishes + after.publishSkips
705
+ > before.publishes + before.publishSkips,
706
+ );
707
+ } finally {
708
+ stopWallService();
709
+ global.setInterval = originalSetInterval;
710
+ }
711
+ });
@@ -144,6 +144,27 @@ function parseWallLine(line) {
144
144
  }
145
145
  }
146
146
 
147
+ function sealCardVersions(project, card) {
148
+ return {
149
+ ...card,
150
+ positionVersion: validVersion(card.positionVersion)
151
+ ? card.positionVersion
152
+ : officialVersion(project.resourceId, card.positionMutationId),
153
+ branches: (card.branches || []).map((ref) => ({
154
+ ...ref,
155
+ version: validVersion(ref.version)
156
+ ? ref.version
157
+ : officialVersion(project.resourceId, ref.mutationId),
158
+ })),
159
+ checkpoints: (card.checkpoints || []).map((checkpoint) => ({
160
+ ...checkpoint,
161
+ version: validVersion(checkpoint.version)
162
+ ? checkpoint.version
163
+ : officialVersion(project.resourceId, checkpoint.mutationId),
164
+ })),
165
+ };
166
+ }
167
+
147
168
  function readProjectWall(project) {
148
169
  if (!fs.existsSync(project.file)) return [];
149
170
  const entries = new Map();
@@ -154,24 +175,7 @@ function readProjectWall(project) {
154
175
  entries.set(entry.machine, {
155
176
  ...entry,
156
177
  resourceId: project.resourceId,
157
- cards: entry.cards.map((card) => ({
158
- ...card,
159
- positionVersion: validVersion(card.positionVersion)
160
- ? card.positionVersion
161
- : officialVersion(project.resourceId, card.positionMutationId),
162
- branches: (card.branches || []).map((ref) => ({
163
- ...ref,
164
- version: validVersion(ref.version)
165
- ? ref.version
166
- : officialVersion(project.resourceId, ref.mutationId),
167
- })),
168
- checkpoints: (card.checkpoints || []).map((checkpoint) => ({
169
- ...checkpoint,
170
- version: validVersion(checkpoint.version)
171
- ? checkpoint.version
172
- : officialVersion(project.resourceId, checkpoint.mutationId),
173
- })),
174
- })),
178
+ cards: entry.cards.map((card) => sealCardVersions(project, card)),
175
179
  });
176
180
  }
177
181
  return [...entries.values()];
@@ -231,8 +235,10 @@ function hasLocalContribution(card, plan, baseline, checkpoint = null, previousC
231
235
  const atBaseline = baseline
232
236
  && card.head?.branch === baseline.branch
233
237
  && card.head?.oid === baseline.baseOid;
234
- const alreadyPublished = previousCard && samePosition(card, previousCard);
238
+ const alreadyPublished = validVersion(previousCard?.positionVersion)
239
+ && samePosition(card, previousCard);
235
240
  const reversesPublishedSharedPosition = previousCard
241
+ && validVersion(previousCard.positionVersion)
236
242
  && samePosition(previousCard, plan.card)
237
243
  && !alreadyPublished;
238
244
  if ((!onRail && !atBaseline && !alreadyPublished) || reversesPublishedSharedPosition) return true;
@@ -240,7 +246,9 @@ function hasLocalContribution(card, plan, baseline, checkpoint = null, previousC
240
246
  const currentRefs = oidMap(card.refs);
241
247
  const railRefs = oidMap(plan.branches);
242
248
  const baselineRefs = oidMap(baseline?.branches);
243
- const previousRefs = oidMap(previousCard?.branches || previousCard?.refs);
249
+ const previousRefs = new Map(
250
+ (previousCard?.branches || previousCard?.refs || []).map((ref) => [ref.name, ref]),
251
+ );
244
252
  for (const name of new Set([
245
253
  ...currentRefs.keys(),
246
254
  ...baselineRefs.keys(),
@@ -249,10 +257,11 @@ function hasLocalContribution(card, plan, baseline, checkpoint = null, previousC
249
257
  const current = currentRefs.get(name) ?? null;
250
258
  const shared = railRefs.get(name) ?? null;
251
259
  const previous = baselineRefs.get(name) ?? null;
252
- const published = previousRefs.get(name) ?? null;
260
+ const publishedRef = previousRefs.get(name);
261
+ const published = publishedRef?.oid ?? null;
253
262
  const matchesBaseline = baselineRefs.has(name) && current === previous;
254
- const matchesPublished = previousRefs.has(name) && current === published;
255
- const reversesPublishedSharedValue = previousRefs.has(name)
263
+ const matchesPublished = validVersion(publishedRef?.version) && current === published;
264
+ const reversesPublishedSharedValue = validVersion(publishedRef?.version)
256
265
  && published === shared
257
266
  && current !== published;
258
267
  if (
@@ -519,12 +528,13 @@ function publishProject(project, rawCards) {
519
528
  const reducer = require('./reducer');
520
529
  const sharedPlan = reducer.reduceWall(readProjectWall(project)).get(project.repoKey);
521
530
  const baseline = reducer.readRepoState(project.repoKey);
522
- const previousReplicas = new Set((previousEntry?.cards || []).map((card) => card.replica));
531
+ const previousCards = (previousEntry?.cards || []).map((card) => sealCardVersions(project, card));
532
+ const previousReplicas = new Set(previousCards.map((card) => card.replica));
523
533
  const currentReplicas = new Set(rawCards.map((card) => card.replica));
524
534
  const removed = [...previousReplicas].some((replica) => !currentReplicas.has(replica));
525
535
  const contributes = rawCards.some((card) => {
526
536
  const checkpoint = readCheckpoint(machineId(), project.repoKey);
527
- const previousCard = previousEntry?.cards?.find((entry) => entry.replica === card.replica);
537
+ const previousCard = previousCards.find((entry) => entry.replica === card.replica);
528
538
  return hasLocalContribution(card, sharedPlan, baseline, checkpoint, previousCard)
529
539
  || hasObjectUpgrade(card, sharedPlan);
530
540
  });
@@ -535,7 +545,7 @@ function publishProject(project, rawCards) {
535
545
  const mutationId = `mut_project_${crypto.randomBytes(16).toString('base64url')}`;
536
546
  const cards = stampCards(
537
547
  rawCards,
538
- previousEntry?.cards,
548
+ previousCards,
539
549
  sharedPlan,
540
550
  baseline,
541
551
  mutationId,
@@ -704,7 +714,10 @@ function startWallService() {
704
714
  schedulePublish();
705
715
  }
706
716
  });
707
- service.ensureInterval = setInterval(() => ensureProjects().catch(() => {}), ENSURE_INTERVAL_MS);
717
+ service.ensureInterval = setInterval(() => {
718
+ ensureProjects().catch(() => {});
719
+ schedulePublish();
720
+ }, ENSURE_INTERVAL_MS);
708
721
  service.ensureInterval.unref?.();
709
722
  ensureProjects().catch(() => {});
710
723
  schedulePublish();