@dharma-ai-labs/agent-fabric 0.2.79 → 0.2.80

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.
@@ -7,7 +7,7 @@ import { join } from 'node:path';
7
7
  import test from 'node:test';
8
8
  import { fileURLToPath, pathToFileURL } from 'node:url';
9
9
  import { promisify } from 'node:util';
10
- import { acceptedTrajectoryHead, activateAgyPlugin, attestAgySkillActivation, attestHermesSkillBundleActivation, actionDecisionCapabilityFreshUntil, canonicalFilesystemPath, controlAgentDecisionUrl, installAvailableNativeAgentFabricBootstraps, assertCapsuleAuthorizedByCurrentPolicy, assertRecoveredTaskWorkspacePolicy, assertTaskWorkspacePolicy, assertTaskSkillPin, installNativeAgentFabricBootstrap, installClaudeReadOnlyProjectPermissions, installRepositoryAgentFabricSkill, isDirectExecution, isTransientBootstrapError, loadAgentFabricOnboardingContract, loadOrCreateInstallationId, materializeWorkspacePolicy, applyServerEvidencePolicy, materializeInlineSkillFiles, validateSkillBundleSources, nativeSkillDirectory, nativeSkillDirectoryForWorkspace, nativeSkillRootMatchingAuthorization, normalizeGitRemoteIdentity, postTaskOutcome, parseCliOptions, parseSelectedProviderIds, pathExistsOrThrow, portalUrl, providerHintFromEnvironment, providerHintFromProcessArgv, probeRelayConnection, preflightBootstrapWorkspaceIdentity, rawLocalRetentionDays, requireCompletedBootstrapEvidence, retryBootstrapOnboarding, synchronizeBootstrapEvidence, deferUnavailableRelayRetention, recoverLegacySkillBundleIdAfterAuthorizationFailure, installedBundleIdForSkillPollAfterAuthorizationFailure, recoveredTaskPolicyWasSuperseded, relayProcessState, releaseDailyContentUpload, reserveDailyContentUpload, run, runAssistantCommand, sourceRepositoryFingerprint, stableRepositoryLauncherContents, summarizeBootstrapOrganizationApi, ensureAgyReadOnlyAttestationPermission, attestAgySkillBundleActivation, responseTextFromEvent, taskResponsePreview, taskReceiptSession, taskSkillPinFailureCode, verifyAgentFabricSkillInstallation, waitForRelayReadiness, withWorkspacePolicyRefreshLock, withWorkspaceSkillActivationLock, } from './index.js';
10
+ import { acceptedTrajectoryHead, activateAgyPlugin, attestAgySkillActivation, attestHermesSkillBundleActivation, actionDecisionCapabilityFreshUntil, canonicalFilesystemPath, controlAgentDecisionUrl, installAvailableNativeAgentFabricBootstraps, assertCapsuleAuthorizedByCurrentPolicy, assertRecoveredTaskWorkspacePolicy, assertTaskWorkspacePolicy, assertTaskSkillPin, installNativeAgentFabricBootstrap, installClaudeReadOnlyProjectPermissions, installRepositoryAgentFabricSkill, isDirectExecution, isTransientBootstrapError, loadAgentFabricOnboardingContract, loadOrCreateInstallationId, materializeWorkspacePolicy, applyServerEvidencePolicy, materializeInlineSkillFiles, validateSkillBundleSources, nativeSkillDirectory, nativeSkillDirectoryForWorkspace, nativeSkillRootMatchingAuthorization, normalizeGitRemoteIdentity, postTaskOutcome, parseCliOptions, parseSelectedProviderIds, pathExistsOrThrow, portalUrl, providerHintFromEnvironment, providerHintFromProcessArgv, probeRelayConnection, preflightBootstrapWorkspaceIdentity, rawLocalRetentionDays, syncPendingRetentionCapsules, requireCompletedBootstrapEvidence, retryBootstrapOnboarding, synchronizeBootstrapEvidence, deferUnavailableRelayRetention, recoverLegacySkillBundleIdAfterAuthorizationFailure, installedBundleIdForSkillPollAfterAuthorizationFailure, recoveredTaskPolicyWasSuperseded, relayProcessState, releaseDailyContentUpload, reserveDailyContentUpload, run, runAssistantCommand, sourceRepositoryFingerprint, stableRepositoryLauncherContents, summarizeBootstrapOrganizationApi, ensureAgyReadOnlyAttestationPermission, attestAgySkillBundleActivation, responseTextFromEvent, taskResponsePreview, taskReceiptSession, taskSkillPinFailureCode, verifyAgentFabricSkillInstallation, waitForRelayReadiness, withWorkspacePolicyRefreshLock, withWorkspaceSkillActivationLock, } from './index.js';
11
11
  import { canonicalize, signCanonicalObject } from '@dharma-ai-labs/agent-fabric-contracts';
12
12
  import { buildTrajectoryCapsule } from '@dharma-ai-labs/agent-fabric-evidence-reduction';
13
13
  import { CLI_USAGE } from './usage.js';
@@ -1290,6 +1290,50 @@ test('queued content must match the current signed consent and policy revision',
1290
1290
  assert.throws(() => assertCapsuleAuthorizedByCurrentPolicy({ ...current, redactionReceipt: { disclosureMode: 'customer_authorized_content', policyRevision: 'content-v1', consentReceiptId: 'consent-old' } }, policy), /no longer authorized/);
1291
1291
  assert.throws(() => assertCapsuleAuthorizedByCurrentPolicy(current, { ...policy, evidence: { ...policy.evidence, automaticDisclosure: { mode: 'local_analysis' } } }), /invalid|no longer authorized/);
1292
1292
  });
1293
+ test('queued capsules from a replaced device are retained locally but never sent under the current device signature', async () => {
1294
+ const base = await materializeWorkspacePolicy({
1295
+ workspace: await mkdtemp(join(tmpdir(), 'dharma-rebound-capsules-')),
1296
+ organizationId: 'org_northstar', revision: 'local',
1297
+ });
1298
+ const workspaceId = 'workspace-northstar';
1299
+ const currentDeviceId = '22222222-2222-4222-8222-222222222222';
1300
+ const session = {
1301
+ provider: 'codex', sessionId: 'same-workspace-history', sourcePath: '/private/codex.jsonl',
1302
+ workspace: '/repo', coverage: 'observed',
1303
+ startedAt: '2026-09-23T00:00:00.000Z', endedAt: '2026-09-23T00:00:01.000Z',
1304
+ records: [{ native: { type: 'message' }, sourcePath: '/private/codex.jsonl', line: 1,
1305
+ workspace: '/repo', timestamp: '2026-09-23T00:00:00.000Z', kind: 'metadata' }],
1306
+ };
1307
+ const capsuleFor = (deviceId) => buildTrajectoryCapsule({
1308
+ organizationId: 'org_northstar', deviceId, workspaceId, session, policy: base.policy,
1309
+ rawContentId: `sha256:${'a'.repeat(64)}`, rawBytes: 32,
1310
+ });
1311
+ const old = capsuleFor('11111111-1111-4111-8111-111111111111');
1312
+ const current = capsuleFor(currentDeviceId);
1313
+ const pending = [old, current];
1314
+ const discarded = [];
1315
+ const sent = [];
1316
+ const vault = {
1317
+ listPendingCapsuleSyncs: async () => pending.map(capsule => ({ trajectoryId: capsule.trajectoryId,
1318
+ revision: capsule.revision, capsule })),
1319
+ markCapsuleSynced: (trajectoryId) => { pending.splice(pending.findIndex(c => c.trajectoryId === trajectoryId), 1); },
1320
+ discardPendingCapsuleSync: (trajectoryId, _revision, reason) => {
1321
+ discarded.push({ trajectoryId, reason });
1322
+ pending.splice(pending.findIndex(c => c.trajectoryId === trajectoryId), 1);
1323
+ },
1324
+ };
1325
+ const fabric = { config: { organizationId: 'org_northstar', deviceId: currentDeviceId },
1326
+ syncTrajectory: async (capsule) => {
1327
+ if (capsule.deviceId !== currentDeviceId)
1328
+ throw new Error('trajectory_tenant_mismatch');
1329
+ sent.push(capsule.trajectoryId);
1330
+ } };
1331
+ const count = await syncPendingRetentionCapsules(vault, fabric, base.policy, workspaceId);
1332
+ assert.equal(count, 1);
1333
+ assert.deepEqual(discarded, [{ trajectoryId: old.trajectoryId, reason: 'device_binding_changed' }]);
1334
+ assert.deepEqual(sent, [current.trajectoryId]);
1335
+ assert.equal(old.deviceId, '11111111-1111-4111-8111-111111111111');
1336
+ });
1293
1337
  test('recovered task evidence distinguishes a superseded policy from the current revision', () => {
1294
1338
  const capsule = { redactionReceipt: { policyRevision: 'policy-v1' } };
1295
1339
  assert.equal(recoveredTaskPolicyWasSuperseded(capsule, { revision: 'policy-v2' }), true);
@@ -1570,13 +1614,13 @@ test('relay probe opens an authenticated session without polling or leasing work
1570
1614
  },
1571
1615
  openSession: async (version) => {
1572
1616
  sessions += 1;
1573
- assert.equal(version, '0.2.79');
1617
+ assert.equal(version, '0.2.80');
1574
1618
  return { ok: true };
1575
1619
  },
1576
1620
  }));
1577
1621
  assert.equal(sessions, 1);
1578
1622
  assert.deepEqual(result, {
1579
- ok: true, connected: true, organizationId: 'org_test', deviceId: 'device_test', relayVersion: '0.2.79',
1623
+ ok: true, connected: true, organizationId: 'org_test', deviceId: 'device_test', relayVersion: '0.2.80',
1580
1624
  });
1581
1625
  });
1582
1626
  test('relay probe fails closed when the server does not acknowledge the session', async () => {