@dharma-ai-labs/agent-fabric 0.2.67 → 0.2.68

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, 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, 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';
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';
@@ -790,6 +790,9 @@ test('workspace registration reuses a normalized repository identity across loca
790
790
  const listed = await run(['repositories', 'list', '--verbose']);
791
791
  assert.equal(listed.repositories.length, 3);
792
792
  assert.equal(listed.repositories.every((entry) => entry.connected === false), true);
793
+ const selected = await run(['repositories', 'list', '--repo', second]);
794
+ assert.deepEqual(selected.repositories.map((entry) => entry.workspaceId), [right.workspaceId]);
795
+ await assert.rejects(() => run(['repositories', 'list', '--workspace-id', 'missing']), /not registered/);
793
796
  }
794
797
  finally {
795
798
  if (previous === undefined)
@@ -923,12 +926,12 @@ test('repository onboarding skill records scoped API metadata without local path
923
926
  });
924
927
  const skill = await readFile(join(workspace, result.skillPath), 'utf8');
925
928
  const connection = await readFile(join(workspace, result.connectionPath), 'utf8');
926
- assert.match(skill, /structured, task-bound handoff/);
927
- assert.match(skill, /local deterministic self-analysis/);
929
+ assert.ok(skill.includes((await loadAgentFabricOnboardingContract()).markdown));
930
+ assert.match(skill, /bounded, task-related question/);
928
931
  assert.match(skill, /dharma skills verify --provider codex --workspace \./);
929
932
  assert.match(skill, /dharma skills verify --provider claude --workspace \./);
930
933
  assert.match(skill, /dharma skills verify --provider agy --workspace \./);
931
- assert.equal(skill.includes('<provider>'), false);
934
+ assert.doesNotMatch(skill, /--grant|bootstrapGrant|organizationApiToken/);
932
935
  assert.match(connection, /workspace-northstar/);
933
936
  assert.equal(connection.includes(workspace), false);
934
937
  assert.equal(/token|secret/i.test(connection), false);
@@ -1567,13 +1570,13 @@ test('relay probe opens an authenticated session without polling or leasing work
1567
1570
  },
1568
1571
  openSession: async (version) => {
1569
1572
  sessions += 1;
1570
- assert.equal(version, '0.2.67');
1573
+ assert.equal(version, '0.2.68');
1571
1574
  return { ok: true };
1572
1575
  },
1573
1576
  }));
1574
1577
  assert.equal(sessions, 1);
1575
1578
  assert.deepEqual(result, {
1576
- ok: true, connected: true, organizationId: 'org_test', deviceId: 'device_test', relayVersion: '0.2.67',
1579
+ ok: true, connected: true, organizationId: 'org_test', deviceId: 'device_test', relayVersion: '0.2.68',
1577
1580
  });
1578
1581
  });
1579
1582
  test('relay probe fails closed when the server does not acknowledge the session', async () => {
@@ -1746,6 +1749,83 @@ test('signed native ownership rejects a foreign workspace marker', async () => {
1746
1749
  assert.equal(verified.nativeInstalled, false);
1747
1750
  assert.equal(verified.nativeManaged, false);
1748
1751
  });
1752
+ test('a second Codex workspace uses its repository skill without replacing the first signed skill', async () => {
1753
+ const root = await mkdtemp(join(tmpdir(), 'dharma-codex-multiworkspace-'));
1754
+ const home = join(root, 'home');
1755
+ const workspace = join(root, 'second-repo');
1756
+ const workspaceId = 'workspace_second';
1757
+ await mkdir(workspace, { recursive: true });
1758
+ const globalSkill = join(nativeSkillDirectory('codex', {}, home), 'dharma-agent-fabric');
1759
+ await mkdir(globalSkill, { recursive: true });
1760
+ await writeFile(join(globalSkill, 'SKILL.md'), '# First signed workspace\n');
1761
+ await writeFile(join(globalSkill, '.dharma-agent-fabric.json'), JSON.stringify({
1762
+ bundleId: '11111111-1111-4111-8111-111111111111',
1763
+ skillId: 'dharma-agent-fabric', workspaceId: 'workspace_first',
1764
+ }));
1765
+ await installRepositoryAgentFabricSkill({
1766
+ workspace, hqUrl: 'https://www.dharma-ai.io', organizationId: 'org_test',
1767
+ workspaceId, policyRevision: 'agent-fabric-policy-v1',
1768
+ });
1769
+ const projectRoot = join(workspace, '.agents', 'skills');
1770
+ assert.equal(await nativeSkillDirectoryForWorkspace({ provider: 'codex', workspaceId, workspace, home }), projectRoot);
1771
+ const installed = await installNativeAgentFabricBootstrap({
1772
+ provider: 'codex', workspace, workspaceId, organizationId: 'org_test',
1773
+ hqUrl: 'https://www.dharma-ai.io', home,
1774
+ });
1775
+ assert.equal(installed.nativeSkillDirectory, projectRoot);
1776
+ assert.equal((await verifyAgentFabricSkillInstallation({ provider: 'codex', workspace, home })).ready, true);
1777
+ assert.equal(await readFile(join(globalSkill, 'SKILL.md'), 'utf8'), '# First signed workspace\n');
1778
+ const projectSkill = join(projectRoot, 'dharma-agent-fabric');
1779
+ await writeFile(join(projectSkill, 'SKILL.md'), '# Second signed workspace\n');
1780
+ await writeFile(join(projectSkill, '.dharma-agent-fabric.json'), JSON.stringify({
1781
+ bundleId: '22222222-2222-4222-8222-222222222222', skillId: 'dharma-agent-fabric', workspaceId,
1782
+ }));
1783
+ await installRepositoryAgentFabricSkill({
1784
+ workspace, hqUrl: 'https://www.dharma-ai.io', organizationId: 'org_test',
1785
+ workspaceId, policyRevision: 'agent-fabric-policy-v1',
1786
+ });
1787
+ await installNativeAgentFabricBootstrap({
1788
+ provider: 'codex', workspace, workspaceId, organizationId: 'org_test',
1789
+ hqUrl: 'https://www.dharma-ai.io', home,
1790
+ });
1791
+ assert.equal(await readFile(join(projectSkill, 'SKILL.md'), 'utf8'), '# Second signed workspace\n');
1792
+ assert.equal(await readFile(join(globalSkill, 'SKILL.md'), 'utf8'), '# First signed workspace\n');
1793
+ });
1794
+ test('Claude uses its project skill when another workspace owns the global skill', async () => {
1795
+ const root = await mkdtemp(join(tmpdir(), 'dharma-claude-multiworkspace-'));
1796
+ const home = join(root, 'home');
1797
+ const workspace = join(root, 'second-repo');
1798
+ await mkdir(workspace, { recursive: true });
1799
+ const globalSkill = join(nativeSkillDirectory('claude', {}, home), 'dharma-agent-fabric');
1800
+ await mkdir(globalSkill, { recursive: true });
1801
+ await writeFile(join(globalSkill, 'SKILL.md'), '# First signed workspace\n');
1802
+ await writeFile(join(globalSkill, '.dharma-agent-fabric.json'), JSON.stringify({
1803
+ bundleId: '11111111-1111-4111-8111-111111111111',
1804
+ skillId: 'dharma-agent-fabric', workspaceId: 'workspace_first',
1805
+ }));
1806
+ await installRepositoryAgentFabricSkill({
1807
+ workspace, hqUrl: 'https://www.dharma-ai.io', organizationId: 'org_test',
1808
+ workspaceId: 'workspace_second', policyRevision: 'agent-fabric-policy-v1',
1809
+ });
1810
+ const installed = await installNativeAgentFabricBootstrap({
1811
+ provider: 'claude', workspace, workspaceId: 'workspace_second', organizationId: 'org_test',
1812
+ hqUrl: 'https://www.dharma-ai.io', home,
1813
+ });
1814
+ assert.equal(installed.nativeSkillDirectory, join(workspace, '.claude', 'skills'));
1815
+ assert.equal((await verifyAgentFabricSkillInstallation({ provider: 'claude', workspace, home })).ready, true);
1816
+ assert.equal(await readFile(join(globalSkill, 'SKILL.md'), 'utf8'), '# First signed workspace\n');
1817
+ });
1818
+ test('project-scoped skill resolution rejects a linked native directory', async () => {
1819
+ const root = await mkdtemp(join(tmpdir(), 'dharma-linked-native-root-'));
1820
+ const workspace = join(root, 'repo');
1821
+ const outside = join(root, 'outside');
1822
+ await mkdir(workspace);
1823
+ await mkdir(outside);
1824
+ await symlink(outside, join(workspace, '.claude'));
1825
+ await assert.rejects(() => nativeSkillDirectoryForWorkspace({
1826
+ provider: 'claude', workspaceId: 'workspace_second', workspace, home: join(root, 'home'),
1827
+ }), /must not contain a link/);
1828
+ });
1749
1829
  test('native Claude bootstrap installs the bounded project completion policy', async () => {
1750
1830
  const root = await mkdtemp(join(tmpdir(), 'dharma-native-claude-skill-'));
1751
1831
  const home = join(root, 'home');