@dharma-ai-labs/agent-fabric 0.2.85 → 0.2.87

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.
@@ -1334,6 +1334,76 @@ test('queued capsules from a replaced device are retained locally but never sent
1334
1334
  assert.deepEqual(sent, [current.trajectoryId]);
1335
1335
  assert.equal(old.deviceId, '11111111-1111-4111-8111-111111111111');
1336
1336
  });
1337
+ test('oversized queued current-device revision is retired only after checking the accepted head', async () => {
1338
+ const base = await materializeWorkspacePolicy({
1339
+ workspace: await mkdtemp(join(tmpdir(), 'dharma-oversized-capsule-')),
1340
+ organizationId: 'org_northstar', revision: 'local',
1341
+ });
1342
+ const session = {
1343
+ provider: 'codex', sessionId: 'oversized-pending', sourcePath: '/private/codex.jsonl',
1344
+ workspace: '/repo', coverage: 'observed',
1345
+ startedAt: '2026-09-24T00:00:00.000Z', endedAt: '2026-09-24T00:00:01.000Z',
1346
+ records: [{ native: { type: 'message' }, sourcePath: '/private/codex.jsonl', line: 1,
1347
+ workspace: '/repo', timestamp: '2026-09-24T00:00:00.000Z', kind: 'metadata' }],
1348
+ };
1349
+ const previousRevisionHash = `sha256:${'a'.repeat(64)}`;
1350
+ const capsule = buildTrajectoryCapsule({
1351
+ organizationId: 'org_northstar', deviceId: '22222222-2222-4222-8222-222222222222',
1352
+ workspaceId: 'workspace-northstar', session, policy: base.policy,
1353
+ rawContentId: `sha256:${'b'.repeat(64)}`, rawBytes: 32,
1354
+ revision: 4, previousRevisionHash,
1355
+ });
1356
+ const capsuleBytes = Buffer.byteLength(canonicalize(capsule));
1357
+ const policyWithSmallerCap = {
1358
+ ...base.policy,
1359
+ evidence: { ...base.policy.evidence, maximumCapsuleBytes: capsuleBytes - 1 },
1360
+ };
1361
+ const pending = [{ trajectoryId: capsule.trajectoryId, revision: 4, capsule }];
1362
+ const discarded = [];
1363
+ let synced = 0;
1364
+ let head = {
1365
+ revision: 3, capsuleHash: previousRevisionHash,
1366
+ };
1367
+ let headUnavailable = false;
1368
+ const vault = {
1369
+ listPendingCapsuleSyncs: async () => [...pending],
1370
+ markCapsuleSynced: () => { synced += 1; pending.length = 0; },
1371
+ discardPendingCapsuleSync: (_trajectoryId, _revision, reason) => {
1372
+ discarded.push(reason);
1373
+ pending.length = 0;
1374
+ },
1375
+ };
1376
+ const fabric = {
1377
+ config: { organizationId: 'org_northstar', deviceId: capsule.deviceId },
1378
+ getTrajectoryHead: async () => {
1379
+ if (headUnavailable)
1380
+ throw new Error('provider unavailable');
1381
+ return { trajectoryId: capsule.trajectoryId, head };
1382
+ },
1383
+ syncTrajectory: async () => { throw new Error('oversized capsule must not be uploaded'); },
1384
+ };
1385
+ assert.equal(await syncPendingRetentionCapsules(vault, fabric, policyWithSmallerCap, 'workspace-northstar'), 0);
1386
+ assert.deepEqual(discarded, ['capsule_size_limit_superseded']);
1387
+ assert.equal(synced, 0);
1388
+ assert.equal(capsule.capsuleHash, buildTrajectoryCapsule({
1389
+ organizationId: 'org_northstar', deviceId: capsule.deviceId, workspaceId: 'workspace-northstar',
1390
+ session, policy: base.policy, rawContentId: `sha256:${'b'.repeat(64)}`, rawBytes: 32,
1391
+ revision: 4, previousRevisionHash,
1392
+ }).capsuleHash);
1393
+ pending.push({ trajectoryId: capsule.trajectoryId, revision: 4, capsule });
1394
+ head = { revision: 4, capsuleHash: capsule.capsuleHash };
1395
+ assert.equal(await syncPendingRetentionCapsules(vault, fabric, policyWithSmallerCap, 'workspace-northstar'), 1);
1396
+ assert.equal(synced, 1);
1397
+ assert.deepEqual(discarded, ['capsule_size_limit_superseded']);
1398
+ pending.push({ trajectoryId: capsule.trajectoryId, revision: 4, capsule });
1399
+ headUnavailable = true;
1400
+ await assert.rejects(() => syncPendingRetentionCapsules(vault, fabric, policyWithSmallerCap, 'workspace-northstar'), /provider unavailable/);
1401
+ assert.equal(pending.length, 1);
1402
+ headUnavailable = false;
1403
+ head = { revision: 2, capsuleHash: previousRevisionHash };
1404
+ await assert.rejects(() => syncPendingRetentionCapsules(vault, fabric, policyWithSmallerCap, 'workspace-northstar'), /conflicts with the accepted server head/);
1405
+ assert.equal(pending.length, 1);
1406
+ });
1337
1407
  test('recovered task evidence distinguishes a superseded policy from the current revision', () => {
1338
1408
  const capsule = { redactionReceipt: { policyRevision: 'policy-v1' } };
1339
1409
  assert.equal(recoveredTaskPolicyWasSuperseded(capsule, { revision: 'policy-v2' }), true);
@@ -1614,13 +1684,13 @@ test('relay probe opens an authenticated session without polling or leasing work
1614
1684
  },
1615
1685
  openSession: async (version) => {
1616
1686
  sessions += 1;
1617
- assert.equal(version, '0.2.85');
1687
+ assert.equal(version, '0.2.87');
1618
1688
  return { ok: true };
1619
1689
  },
1620
1690
  }));
1621
1691
  assert.equal(sessions, 1);
1622
1692
  assert.deepEqual(result, {
1623
- ok: true, connected: true, organizationId: 'org_test', deviceId: 'device_test', relayVersion: '0.2.85',
1693
+ ok: true, connected: true, organizationId: 'org_test', deviceId: 'device_test', relayVersion: '0.2.87',
1624
1694
  });
1625
1695
  });
1626
1696
  test('relay probe fails closed when the server does not acknowledge the session', async () => {