amalgm 0.1.200 → 0.1.201

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.200",
3
+ "version": "0.1.201",
4
4
  "description": "Amalgm local computer runtime: login, MCP, chat, events, previews, and tunnels.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -40,6 +40,19 @@ test.after(() => {
40
40
  fs.rmSync(tempRoot, { recursive: true, force: true });
41
41
  });
42
42
 
43
+ test('checkpoint publication waits until the reducer finishes writing both repo layers', async () => {
44
+ const { withMaterialization } = require('../workspace/reducer');
45
+ const repoKey = 'https://example.test/repo.git';
46
+
47
+ assert.equal(_test.checkpointMayPublish(repoKey), true);
48
+ await withMaterialization(repoKey, async () => {
49
+ assert.equal(_test.checkpointMayPublish(repoKey), false);
50
+ await Promise.resolve();
51
+ assert.equal(_test.checkpointMayPublish(repoKey), false);
52
+ });
53
+ assert.equal(_test.checkpointMayPublish(repoKey), true);
54
+ });
55
+
43
56
  async function run(cwd, ...args) {
44
57
  await execFileAsync(
45
58
  'git',
@@ -188,6 +188,10 @@ function checkpointBaseReady(card, reduced) {
188
188
  );
189
189
  }
190
190
 
191
+ function checkpointMayPublish(repoKey) {
192
+ return !require('./reducer').isMaterializing(repoKey);
193
+ }
194
+
191
195
  async function publishPass(replicaId = null) {
192
196
  const machine = machineId();
193
197
  const run = { published: 0, skips: 0, waiting: 0, failures: 0 };
@@ -196,6 +200,10 @@ async function publishPass(replicaId = null) {
196
200
  if (card.health !== 'healthy' || card.kind !== 'primary' || card.operation !== 'none') continue;
197
201
  const repoKey = repoKeyOfCard(card);
198
202
  if (!repoKey || !card.head?.oid) continue;
203
+ if (!checkpointMayPublish(repoKey)) {
204
+ run.waiting += 1;
205
+ continue;
206
+ }
199
207
  try {
200
208
  const reduced = require('./reducer').readRepoState(repoKey);
201
209
  if (!checkpointBaseReady(card, reduced)) {
@@ -376,6 +384,7 @@ module.exports = {
376
384
  _test: {
377
385
  checkpointBaseReady,
378
386
  checkpointForSharedState,
387
+ checkpointMayPublish,
379
388
  },
380
389
  CHECKPOINT_CONTRACT,
381
390
  MAX_INLINE_DIFF_BYTES,
@@ -50,6 +50,20 @@ const service = {
50
50
  repos: new Map(),
51
51
  lastPass: null,
52
52
  };
53
+ const materializing = new Set();
54
+
55
+ function isMaterializing(repoKey) {
56
+ return materializing.has(repoKey);
57
+ }
58
+
59
+ async function withMaterialization(repoKey, work) {
60
+ materializing.add(repoKey);
61
+ try {
62
+ return await work();
63
+ } finally {
64
+ materializing.delete(repoKey);
65
+ }
66
+ }
53
67
 
54
68
  function stateFile(repoKey) {
55
69
  const digest = crypto.createHash('sha256').update(repoKey).digest('hex').slice(0, 24);
@@ -587,7 +601,10 @@ async function runReducer() {
587
601
  if (!plan.card) continue;
588
602
  try {
589
603
  if (!local?.head?.oid) {
590
- const hydrated = await hydrateRepo(wall.projectForRepo(repoKey), plan);
604
+ const hydrated = await withMaterialization(
605
+ repoKey,
606
+ () => hydrateRepo(wall.projectForRepo(repoKey), plan),
607
+ );
591
608
  service.repos.set(repoKey, {
592
609
  repoKey,
593
610
  path: wall.projectForRepo(repoKey)?.path || local?.path || null,
@@ -627,7 +644,10 @@ async function runReducer() {
627
644
  service.counters.waiting += 1;
628
645
  continue;
629
646
  }
630
- const outcome = await materializeRepo(refreshed, currentPlan);
647
+ const outcome = await withMaterialization(
648
+ repoKey,
649
+ () => materializeRepo(refreshed, currentPlan),
650
+ );
631
651
  service.repos.set(repoKey, { repoKey, path: local.path, ...outcome, at: new Date().toISOString() });
632
652
  if (outcome.state === 'waiting') service.counters.waiting += 1;
633
653
  if (outcome.moved) {
@@ -718,6 +738,7 @@ module.exports = {
718
738
  advanceIndex,
719
739
  captureIsOnRail,
720
740
  hydrateRepo,
741
+ isMaterializing,
721
742
  localCardMayMaterialize,
722
743
  materializeRepo,
723
744
  readRepoState,
@@ -727,4 +748,5 @@ module.exports = {
727
748
  reducerStats,
728
749
  startWorkspaceReducer,
729
750
  stopWorkspaceReducer,
751
+ withMaterialization,
730
752
  };