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

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.
@@ -9,7 +9,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
9
9
  import { promisify } from 'node:util';
10
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
- import { buildTrajectoryCapsule } from '@dharma-ai-labs/agent-fabric-evidence-reduction';
12
+ import { buildTrajectoryCapsule, trajectoryCapsuleHash } from '@dharma-ai-labs/agent-fabric-evidence-reduction';
13
13
  import { CLI_USAGE } from './usage.js';
14
14
  import { isSupportedNodeVersion, launchWithRuntime, nodeRuntimeCandidates, runtimeBootstrapHint, } from './runtime-bootstrap.js';
15
15
  test('installation identity is durable per DHARMA_HOME and rejects corrupt state', async () => {
@@ -1404,6 +1404,74 @@ test('oversized queued current-device revision is retired only after checking th
1404
1404
  await assert.rejects(() => syncPendingRetentionCapsules(vault, fabric, policyWithSmallerCap, 'workspace-northstar'), /conflicts with the accepted server head/);
1405
1405
  assert.equal(pending.length, 1);
1406
1406
  });
1407
+ test('queued native recipient paths retire only an unsent revision without uploading it', async () => {
1408
+ const workspace = await mkdtemp(join(tmpdir(), 'dharma-recipient-path-capsule-'));
1409
+ const signed = signedPolicyAuthorization({
1410
+ revision: 'content-v1', evidence: {
1411
+ automaticDisclosure: { mode: 'customer_authorized_content', consentReceiptId: 'consent-recipient', allowedContentClasses: ['native_provider_payload'] },
1412
+ maximumCapsuleBytes: 500_000, maximumDailyUploadBytes: 50_000_000,
1413
+ },
1414
+ });
1415
+ const base = await materializeWorkspacePolicy({
1416
+ workspace, organizationId: 'org_northstar', revision: 'portal-bootstrap',
1417
+ serverPolicyAuthorization: signed.envelope, serverPublicKeyEd25519: signed.publicKeyEd25519,
1418
+ workspaceId: 'workspace-northstar', secureStore: memorySecureStore(),
1419
+ });
1420
+ const capsule = buildTrajectoryCapsule({
1421
+ organizationId: 'org_northstar', deviceId: '22222222-2222-4222-8222-222222222222',
1422
+ workspaceId: 'workspace-northstar', policy: base.policy,
1423
+ session: {
1424
+ provider: 'codex', sessionId: 'recipient-path-pending', sourcePath: '/private/codex.jsonl',
1425
+ workspace: '/repo', coverage: 'observed', startedAt: '2026-09-24T00:00:00.000Z',
1426
+ endedAt: '2026-09-24T00:00:01.000Z',
1427
+ records: [{ native: { type: 'tool_call', payload: { recipient: 'peer' } }, sourcePath: '/private/codex.jsonl',
1428
+ line: 1, workspace: '/repo', timestamp: '2026-09-24T00:00:00.000Z', kind: 'tool_call' }],
1429
+ },
1430
+ rawContentId: `sha256:${'b'.repeat(64)}`, rawBytes: 32,
1431
+ });
1432
+ const native = capsule.events[0].payload.nativeProviderPayload;
1433
+ native.payload.recipient = '/home';
1434
+ capsule.capsuleHash = trajectoryCapsuleHash(capsule);
1435
+ const pending = [{ trajectoryId: capsule.trajectoryId, revision: 1, capsule }];
1436
+ const discarded = [];
1437
+ let synced = 0;
1438
+ let head = null;
1439
+ let unavailable = false;
1440
+ const vault = {
1441
+ listPendingCapsuleSyncs: async () => [...pending],
1442
+ markCapsuleSynced: () => { synced += 1; pending.length = 0; },
1443
+ discardPendingCapsuleSync: (_trajectoryId, _revision, reason) => {
1444
+ discarded.push(reason);
1445
+ pending.length = 0;
1446
+ },
1447
+ };
1448
+ const fabric = {
1449
+ config: { organizationId: 'org_northstar', deviceId: capsule.deviceId },
1450
+ getTrajectoryHead: async () => {
1451
+ if (unavailable)
1452
+ throw new Error('provider unavailable');
1453
+ return { trajectoryId: capsule.trajectoryId, head };
1454
+ },
1455
+ syncTrajectory: async () => { throw new Error('path-bearing capsule must not be uploaded'); },
1456
+ };
1457
+ assert.equal(await syncPendingRetentionCapsules(vault, fabric, base.policy, 'workspace-northstar'), 0);
1458
+ assert.deepEqual(discarded, ['local_path_disclosure_superseded']);
1459
+ assert.equal(synced, 0);
1460
+ assert.equal(native.payload.recipient, '/home');
1461
+ pending.push({ trajectoryId: capsule.trajectoryId, revision: 1, capsule });
1462
+ head = { revision: 1, capsuleHash: capsule.capsuleHash };
1463
+ assert.equal(await syncPendingRetentionCapsules(vault, fabric, base.policy, 'workspace-northstar'), 1);
1464
+ assert.equal(synced, 1);
1465
+ assert.deepEqual(discarded, ['local_path_disclosure_superseded']);
1466
+ pending.push({ trajectoryId: capsule.trajectoryId, revision: 1, capsule });
1467
+ head = { revision: 2, capsuleHash: capsule.capsuleHash };
1468
+ await assert.rejects(() => syncPendingRetentionCapsules(vault, fabric, base.policy, 'workspace-northstar'), /conflicts with the accepted server head/);
1469
+ assert.equal(pending.length, 1);
1470
+ head = null;
1471
+ unavailable = true;
1472
+ await assert.rejects(() => syncPendingRetentionCapsules(vault, fabric, base.policy, 'workspace-northstar'), /provider unavailable/);
1473
+ assert.equal(pending.length, 1);
1474
+ });
1407
1475
  test('recovered task evidence distinguishes a superseded policy from the current revision', () => {
1408
1476
  const capsule = { redactionReceipt: { policyRevision: 'policy-v1' } };
1409
1477
  assert.equal(recoveredTaskPolicyWasSuperseded(capsule, { revision: 'policy-v2' }), true);
@@ -1684,13 +1752,13 @@ test('relay probe opens an authenticated session without polling or leasing work
1684
1752
  },
1685
1753
  openSession: async (version) => {
1686
1754
  sessions += 1;
1687
- assert.equal(version, '0.2.87');
1755
+ assert.equal(version, '0.2.88');
1688
1756
  return { ok: true };
1689
1757
  },
1690
1758
  }));
1691
1759
  assert.equal(sessions, 1);
1692
1760
  assert.deepEqual(result, {
1693
- ok: true, connected: true, organizationId: 'org_test', deviceId: 'device_test', relayVersion: '0.2.87',
1761
+ ok: true, connected: true, organizationId: 'org_test', deviceId: 'device_test', relayVersion: '0.2.88',
1694
1762
  });
1695
1763
  });
1696
1764
  test('relay probe fails closed when the server does not acknowledge the session', async () => {