amalgm 0.1.213 → 0.1.215
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 +1 -1
- package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint.test.js +31 -0
- package/runtime/scripts/amalgm-mcp/tests/workspace-reducer.test.js +38 -0
- package/runtime/scripts/amalgm-mcp/tests/workspace-wall.test.js +9 -0
- package/runtime/scripts/amalgm-mcp/workspace/checkpoint.js +13 -1
- package/runtime/scripts/amalgm-mcp/workspace/reducer.js +18 -5
- package/runtime/scripts/amalgm-mcp/workspace/wall.js +2 -1
package/package.json
CHANGED
|
@@ -243,6 +243,37 @@ test('a clean losing commit travels as parked metadata on a no-op checkpoint', (
|
|
|
243
243
|
assert.deepEqual(checkpoint.parked, parked);
|
|
244
244
|
});
|
|
245
245
|
|
|
246
|
+
test('only this machine keeps announcing its parked commits', () => {
|
|
247
|
+
const baseOid = 'a'.repeat(40);
|
|
248
|
+
const localOid = 'b'.repeat(40);
|
|
249
|
+
const peerOid = 'c'.repeat(40);
|
|
250
|
+
const pendingOid = 'd'.repeat(40);
|
|
251
|
+
const existing = {
|
|
252
|
+
branch: 'main',
|
|
253
|
+
baseOid,
|
|
254
|
+
parked: [{ oid: localOid, objects: { kind: 'pending' } }],
|
|
255
|
+
};
|
|
256
|
+
const reduced = {
|
|
257
|
+
parked: [
|
|
258
|
+
{ oid: localOid, version: 10, objects: { kind: 'pending' } },
|
|
259
|
+
{ oid: peerOid, version: 11, objects: { kind: 'bundle' } },
|
|
260
|
+
{ oid: pendingOid, objects: { kind: 'pending' } },
|
|
261
|
+
],
|
|
262
|
+
};
|
|
263
|
+
const card = { head: { branch: 'main', oid: baseOid } };
|
|
264
|
+
|
|
265
|
+
assert.deepEqual(
|
|
266
|
+
_test.localParkedEntries(existing, reduced, card).map((entry) => entry.oid),
|
|
267
|
+
[localOid, pendingOid],
|
|
268
|
+
);
|
|
269
|
+
assert.deepEqual(
|
|
270
|
+
_test.localParkedEntries(existing, reduced, {
|
|
271
|
+
head: { branch: 'main', oid: 'e'.repeat(40) },
|
|
272
|
+
}).map((entry) => entry.oid),
|
|
273
|
+
[pendingOid],
|
|
274
|
+
);
|
|
275
|
+
});
|
|
276
|
+
|
|
246
277
|
test('a server rail number does not turn the same parked checkpoint into new work', () => {
|
|
247
278
|
const value = { revision: null, indexDiff: '', worktreeDiff: '' };
|
|
248
279
|
const checkpoint = {
|
|
@@ -28,6 +28,7 @@ const {
|
|
|
28
28
|
hydrateRepo,
|
|
29
29
|
localCardMayMaterialize,
|
|
30
30
|
materializeRepo,
|
|
31
|
+
parkedForState,
|
|
31
32
|
pathForRepo,
|
|
32
33
|
readRepoState,
|
|
33
34
|
reduceCheckpoint,
|
|
@@ -175,6 +176,17 @@ test('a ready parked bundle never regresses to pending', () => {
|
|
|
175
176
|
assert.equal(plan.parked[0].objects.kind, 'bundle');
|
|
176
177
|
});
|
|
177
178
|
|
|
179
|
+
test('an unpublished local parked commit stays active until the rail records it', () => {
|
|
180
|
+
const oid = 'f'.repeat(40);
|
|
181
|
+
const local = { oid, objects: { kind: 'bundle', checksum: 'local' } };
|
|
182
|
+
assert.deepEqual(parkedForState([local], [], []), [local]);
|
|
183
|
+
assert.deepEqual(parkedForState([local], [{ ...local, version: 7 }], []), [{
|
|
184
|
+
...local,
|
|
185
|
+
version: 7,
|
|
186
|
+
}]);
|
|
187
|
+
assert.deepEqual(parkedForState([{ ...local, version: 7 }], [], []), []);
|
|
188
|
+
});
|
|
189
|
+
|
|
178
190
|
test('a stale lower rail card cannot roll back a newer branch and commit', () => {
|
|
179
191
|
const newer = card('/newer', 'b'.repeat(40), 12);
|
|
180
192
|
newer.head.branch = 'feature';
|
|
@@ -507,6 +519,32 @@ test('a losing commit is parked, the winning card lands exactly, and losing work
|
|
|
507
519
|
assert.equal(fs.readFileSync(path.join(repo, 'local-dirty.txt'), 'utf8'), 'also uncommitted\n');
|
|
508
520
|
assert.equal((await git(repo, 'status', '--porcelain')).trim().length > 0, true);
|
|
509
521
|
assert.deepEqual(readRepoState('root:test').parked.map((entry) => entry.oid), [losingOid]);
|
|
522
|
+
|
|
523
|
+
const sharedParked = readRepoState('root:test').parked.map((entry) => ({
|
|
524
|
+
...entry,
|
|
525
|
+
version: 2,
|
|
526
|
+
}));
|
|
527
|
+
await materializeRepo(card(repo, winningOid, 2), {
|
|
528
|
+
repoKey: 'root:test',
|
|
529
|
+
card: winningCard,
|
|
530
|
+
transitions: [],
|
|
531
|
+
parked: sharedParked,
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
await git(repo, 'add', '.');
|
|
535
|
+
await git(repo, 'commit', '-m', 'fold parked work');
|
|
536
|
+
const foldedOid = (await git(repo, 'rev-parse', 'HEAD')).trim();
|
|
537
|
+
const foldedCard = card(repo, foldedOid, 3);
|
|
538
|
+
const folded = await materializeRepo(foldedCard, {
|
|
539
|
+
repoKey: 'root:test',
|
|
540
|
+
card: foldedCard,
|
|
541
|
+
transitions: [],
|
|
542
|
+
parked: [],
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
assert.equal(folded.state, 'in-sync');
|
|
546
|
+
assert.deepEqual(readRepoState('root:test').parked, []);
|
|
547
|
+
assert.equal((await git(repo, 'rev-parse', `refs/amalgm/parked/${losingOid}`)).trim(), losingOid);
|
|
510
548
|
});
|
|
511
549
|
|
|
512
550
|
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 },
|
|
@@ -157,6 +157,17 @@ function checkpointForSharedState(existing, {
|
|
|
157
157
|
};
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
function localParkedEntries(existing, reduced, card) {
|
|
161
|
+
const held = existing?.baseOid === card.head?.oid
|
|
162
|
+
&& existing.branch === card.head?.branch
|
|
163
|
+
? existing.parked || []
|
|
164
|
+
: [];
|
|
165
|
+
const unpublished = (reduced?.parked || []).filter((entry) => (
|
|
166
|
+
!Number.isInteger(entry.version) || entry.version < 1
|
|
167
|
+
));
|
|
168
|
+
return [...new Map([...held, ...unpublished].map((entry) => [entry.oid, entry])).values()];
|
|
169
|
+
}
|
|
170
|
+
|
|
160
171
|
function readCheckpointValue(baseOid, value) {
|
|
161
172
|
let indexDiff = typeof value?.indexDiff === 'string' ? value.indexDiff : '';
|
|
162
173
|
let worktreeDiff = typeof value?.worktreeDiff === 'string' ? value.worktreeDiff : '';
|
|
@@ -228,7 +239,7 @@ async function publishPass(replicaId = null) {
|
|
|
228
239
|
const localRevision = revisionOf(card.head.oid, captured.indexDiff, captured.worktreeDiff);
|
|
229
240
|
const file = checkpointFile(machine, repoKey);
|
|
230
241
|
const existing = readCheckpoint(machine, repoKey);
|
|
231
|
-
const parked = await Promise.all((reduced
|
|
242
|
+
const parked = await Promise.all(localParkedEntries(existing, reduced, card).map(async (entry) => ({
|
|
232
243
|
...entry,
|
|
233
244
|
objects: await require('./objects').bundleSourceFor(card.path, repoKey, entry.oid),
|
|
234
245
|
})));
|
|
@@ -393,6 +404,7 @@ module.exports = {
|
|
|
393
404
|
checkpointBaseReady,
|
|
394
405
|
checkpointForSharedState,
|
|
395
406
|
checkpointMayPublish,
|
|
407
|
+
localParkedEntries,
|
|
396
408
|
},
|
|
397
409
|
CHECKPOINT_CONTRACT,
|
|
398
410
|
MAX_INLINE_DIFF_BYTES,
|
|
@@ -176,6 +176,18 @@ function uniqueParked(entries) {
|
|
|
176
176
|
return order.map((oid) => byOid.get(oid));
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
function parkedForState(previous, shared, discovered) {
|
|
180
|
+
const sharedOids = new Set((shared || []).map((entry) => entry.oid));
|
|
181
|
+
const unpublished = (previous || []).filter((entry) => (
|
|
182
|
+
!validVersion(entry.version) && !sharedOids.has(entry.oid)
|
|
183
|
+
));
|
|
184
|
+
return uniqueParked([
|
|
185
|
+
...(shared || []),
|
|
186
|
+
...unpublished,
|
|
187
|
+
...(discovered || []),
|
|
188
|
+
]);
|
|
189
|
+
}
|
|
190
|
+
|
|
179
191
|
async function obtainCardObjects(localCard, targetCard) {
|
|
180
192
|
const oid = targetCard.head?.oid;
|
|
181
193
|
if (!oid || await hasCommit(localCard.path, oid)) return { state: 'ready' };
|
|
@@ -512,11 +524,11 @@ async function materializeRepo(localCardInput, plan) {
|
|
|
512
524
|
? await refreshRepoCard(refreshed.replica) || refreshed
|
|
513
525
|
: refreshed;
|
|
514
526
|
const previous = readRepoState(plan.repoKey);
|
|
515
|
-
const parked =
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
527
|
+
const parked = parkedForState(
|
|
528
|
+
previous?.parked,
|
|
529
|
+
plan.parked,
|
|
530
|
+
cardResult.parked,
|
|
531
|
+
);
|
|
520
532
|
const parkedWaiting = await materializeParked(localCard, parked);
|
|
521
533
|
const planParked = new Set((plan.parked || []).map((entry) => entry.oid));
|
|
522
534
|
const requiredParkedWaiting = parkedWaiting.filter((entry) => planParked.has(entry.oid));
|
|
@@ -785,6 +797,7 @@ module.exports = {
|
|
|
785
797
|
localCardMayMaterialize,
|
|
786
798
|
materializeRepo,
|
|
787
799
|
pathForRepo,
|
|
800
|
+
parkedForState,
|
|
788
801
|
readRepoState,
|
|
789
802
|
reduceCheckpoint,
|
|
790
803
|
reduceNow,
|