amalgm 0.1.179 → 0.1.180

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.179",
3
+ "version": "0.1.180",
4
4
  "description": "Amalgm local computer runtime: login, MCP, chat, events, previews, and tunnels.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -26,7 +26,12 @@ const { closeLocalDb } = require('../state/db');
26
26
  const { captureCheckpoint, captureWorktreeDiff } = require('../workspace/git');
27
27
  const merge = require('../workspace/merge');
28
28
  const { applyPatch } = require('../workspace/transition');
29
- const { checkpointFile, revisionOf } = require('../workspace/checkpoint');
29
+ const {
30
+ checkpointFile,
31
+ checkpointValueReady,
32
+ readCheckpointValue,
33
+ revisionOf,
34
+ } = require('../workspace/checkpoint');
30
35
 
31
36
  test.after(() => {
32
37
  closeLocalDb();
@@ -161,3 +166,17 @@ test('checkpoint captures are local cache; their operations travel on the one wa
161
166
  assert.notEqual(first, checkpointFile('m1', 'https://github.com/a/c'));
162
167
  assert.match(first, /repo-checkpoints-v5/);
163
168
  });
169
+
170
+ test('an uploading checkpoint payload is not published as a transition', () => {
171
+ const pending = {
172
+ revision: 'a'.repeat(64),
173
+ payload: {
174
+ kind: 'pending',
175
+ contract: 'opaque-chunks@1',
176
+ checksum: 'b'.repeat(64),
177
+ },
178
+ };
179
+ assert.equal(checkpointValueReady(pending), false);
180
+ assert.equal(readCheckpointValue('c'.repeat(40), pending).state, 'payload-pending');
181
+ assert.equal(checkpointValueReady({ revision: null, indexDiff: '', worktreeDiff: '' }), true);
182
+ });
@@ -22,7 +22,13 @@ fs.writeFileSync(
22
22
 
23
23
  const { closeLocalDb } = require('../state/db');
24
24
  const { revisionOf } = require('../workspace/checkpoint');
25
- const { hydrateRepo, materializeRepo, readRepoState, reduceWall } = require('../workspace/reducer');
25
+ const {
26
+ hydrateRepo,
27
+ materializeRepo,
28
+ readRepoState,
29
+ reduceCheckpoint,
30
+ reduceWall,
31
+ } = require('../workspace/reducer');
26
32
 
27
33
  test.after(() => {
28
34
  closeLocalDb();
@@ -123,6 +129,24 @@ test('a stale lower rail card cannot roll back a newer branch and commit', () =>
123
129
  assert.equal(plan.card.positionVersion, 12);
124
130
  });
125
131
 
132
+ test('an old pending payload does not block the later complete checkpoint transition', async () => {
133
+ const { repo, oid } = await makeRepo('pending-payload');
134
+ const diff = await patchFor(repo, { 'a.txt': 'a1\n' });
135
+ const pending = transition('machine-a', 2, oid, '', '');
136
+ pending.from = {
137
+ revision: 'a'.repeat(64),
138
+ payload: { kind: 'pending', contract: 'opaque-chunks@1', checksum: 'b'.repeat(64) },
139
+ };
140
+ pending.to = pending.from;
141
+ const complete = transition('machine-a', 3, oid, '', diff);
142
+ const reduced = await reduceCheckpoint(
143
+ { path: repo },
144
+ { card: card(repo, oid, 1), transitions: [pending, complete] },
145
+ );
146
+ assert.equal(reduced.state, 'ready');
147
+ assert.match(reduced.indexDiff, /a1/);
148
+ });
149
+
126
150
  test('an empty project folder hydrates from the winning card bundle without cloning', async () => {
127
151
  const sourceRepo = await makeRepo('hydrate-source');
128
152
  const source = sourceRepo.repo;
@@ -119,10 +119,17 @@ function checkpointValue(machine, repoKey, baseOid, indexDiff, worktreeDiff) {
119
119
  };
120
120
  }
121
121
 
122
+ function checkpointValueReady(value) {
123
+ return !value?.payload || value.payload.kind === 'chunks';
124
+ }
125
+
122
126
  function readCheckpointValue(baseOid, value) {
123
127
  let indexDiff = typeof value?.indexDiff === 'string' ? value.indexDiff : '';
124
128
  let worktreeDiff = typeof value?.worktreeDiff === 'string' ? value.worktreeDiff : '';
125
129
  if (value?.payload) {
130
+ if (value.payload.kind === 'pending') {
131
+ return { state: 'payload-pending', indexDiff: null, worktreeDiff: null };
132
+ }
126
133
  const payload = require('./objects').readPayload(value.payload);
127
134
  if (payload.state !== 'ready') {
128
135
  return { state: payload.state, indexDiff: null, worktreeDiff: null };
@@ -203,26 +210,32 @@ async function publishPass(replicaId = null) {
203
210
  continue;
204
211
  }
205
212
 
213
+ const from = checkpointValue(
214
+ machine,
215
+ repoKey,
216
+ card.head.oid,
217
+ reduced.indexDiff,
218
+ reduced.worktreeDiff,
219
+ );
220
+ const to = checkpointValue(
221
+ machine,
222
+ repoKey,
223
+ card.head.oid,
224
+ captured.indexDiff,
225
+ captured.worktreeDiff,
226
+ );
227
+ if (!checkpointValueReady(from) || !checkpointValueReady(to)) {
228
+ run.waiting += 1;
229
+ continue;
230
+ }
206
231
  const envelope = {
207
232
  checkpoint: CHECKPOINT_CONTRACT,
208
233
  machine,
209
234
  repoKey,
210
235
  branch: card.head.branch,
211
236
  baseOid: card.head.oid,
212
- from: checkpointValue(
213
- machine,
214
- repoKey,
215
- card.head.oid,
216
- reduced.indexDiff,
217
- reduced.worktreeDiff,
218
- ),
219
- to: checkpointValue(
220
- machine,
221
- repoKey,
222
- card.head.oid,
223
- captured.indexDiff,
224
- captured.worktreeDiff,
225
- ),
237
+ from,
238
+ to,
226
239
  parked,
227
240
  capturedAt: new Date().toISOString(),
228
241
  };
@@ -322,6 +335,7 @@ module.exports = {
322
335
  MAX_INLINE_DIFF_BYTES,
323
336
  checkpointFile,
324
337
  checkpointStats,
338
+ checkpointValueReady,
325
339
  parseCheckpoint,
326
340
  publishCheckpoints,
327
341
  readCheckpoint,
@@ -378,6 +378,7 @@ async function reduceCheckpoint(localCard, plan) {
378
378
  for (const operation of plan.transitions) {
379
379
  const from = readCheckpointValue(baseOid, operation.from);
380
380
  const to = readCheckpointValue(baseOid, operation.to);
381
+ if (from.state === 'payload-pending' || to.state === 'payload-pending') continue;
381
382
  if (from.state !== 'ready' || to.state !== 'ready') {
382
383
  return { state: 'waiting', reason: `checkpoint-${from.state !== 'ready' ? from.state : to.state}` };
383
384
  }
@@ -644,6 +645,7 @@ module.exports = {
644
645
  hydrateRepo,
645
646
  materializeRepo,
646
647
  readRepoState,
648
+ reduceCheckpoint,
647
649
  reduceNow,
648
650
  reduceWall,
649
651
  reducerStats,