@wix/pathgrade 1.0.28 → 1.0.29

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.
@@ -88,10 +88,11 @@ export class ClaudeAgent extends BaseAgent {
88
88
  hostEnv,
89
89
  sandboxProfile: this.deps.sandboxProfile,
90
90
  });
91
- const claudeCodeExecutable = resolveClaudeCodeExecutable({
92
- agentOptionsExecutable: this.opts.claudeCodeExecutable,
93
- envExecutable,
94
- });
91
+ const claudeCodeExecutable = sessionOptions?.admittedClaudeCodeExecutable
92
+ ?? resolveClaudeCodeExecutable({
93
+ agentOptionsExecutable: this.opts.claudeCodeExecutable,
94
+ envExecutable,
95
+ });
95
96
  const mcpMountOptions = {
96
97
  workspacePath,
97
98
  mcpConfigPath: sessionOptions?.mcpConfigPath,
@@ -2,7 +2,7 @@ import { type McpSdkServerConfigWithInstance, type Options as ClaudeSdkOptions,
2
2
  import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
3
3
  import { type CleanupReport } from './cleanup.js';
4
4
  import { type MaterializedProjection } from './materialize.js';
5
- import type { EvidenceEnvelope, ScenarioArtifact, ScenarioMachineV2 } from './types.js';
5
+ import type { AdmittedRuntimeProfile, EvidenceEnvelope, ScenarioArtifact, ScenarioMachineV2 } from './types.js';
6
6
  export declare const CLAUDE_DIRECT_MCP_FLAG = "PATHGRADE_INTERNAL_CLAUDE_DIRECT_MCP_V2";
7
7
  export type ClaudeDirectMcpChecks = {
8
8
  runtimeAdmitted: boolean;
@@ -19,6 +19,7 @@ export type ClaudeDirectMcpChecks = {
19
19
  export type ClaudeDirectMcpTrialResult = {
20
20
  selected: true;
21
21
  profileFingerprint: string;
22
+ runtimeProfile: AdmittedRuntimeProfile;
22
23
  artifact: ScenarioArtifact;
23
24
  evidence: readonly EvidenceEnvelope[];
24
25
  checks: ClaudeDirectMcpChecks;
@@ -11,19 +11,35 @@ import { compileScenario } from './compiler.js';
11
11
  import { IdempotentTrialCleaner, persistTrialArtifact, TrialExecutionError, TrialResourceRegistry, scanBearerSurfaces } from './cleanup.js';
12
12
  import { PrivateReplayVault, replayPrivateEvidence, verifyEvidenceChain } from './evidence.js';
13
13
  import { ScenarioHostReducer } from './host-reducer.js';
14
+ import { sha256Canonical } from './json.js';
14
15
  import { materializeProjection } from './materialize.js';
15
16
  import { projectEndpoints } from './projection.js';
16
- import { admitRuntimeProfile } from './runtime-profile.js';
17
+ import { admitRuntimeLock } from './runtime-lock.js';
17
18
  import { createInvocationBarrier, startScenarioHttpHost } from './scenario-http-host.js';
18
- import { CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE, CLAUDE_DIRECT_MCP_NORMALIZED_HANDSHAKE } from './claude-profile.js';
19
+ import { observeClaudeRuntimeControlPlane, resolveClaudeScenarioExecutable, selectClaudeRuntimeTarget, } from './claude-profile.js';
19
20
  export const CLAUDE_DIRECT_MCP_FLAG = 'PATHGRADE_INTERNAL_CLAUDE_DIRECT_MCP_V2';
20
21
  const disabledProfiles = new Map();
22
+ function runtimeLockFingerprint(lock) {
23
+ return sha256Canonical(lock);
24
+ }
21
25
  export function isClaudeDirectMcpSelected(environment = process.env) {
22
- const fingerprint = CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.profileFingerprint;
23
- return environment[CLAUDE_DIRECT_MCP_FLAG] === '1' && !disabledProfiles.has(fingerprint);
26
+ if (environment[CLAUDE_DIRECT_MCP_FLAG] !== '1')
27
+ return false;
28
+ try {
29
+ const fingerprint = selectClaudeRuntimeTarget().lock;
30
+ return !disabledProfiles.has(runtimeLockFingerprint(fingerprint));
31
+ }
32
+ catch {
33
+ return false;
34
+ }
24
35
  }
25
36
  export function claudeDirectMcpDisableReason() {
26
- return disabledProfiles.get(CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.profileFingerprint);
37
+ try {
38
+ return disabledProfiles.get(runtimeLockFingerprint(selectClaudeRuntimeTarget().lock));
39
+ }
40
+ catch {
41
+ return undefined;
42
+ }
27
43
  }
28
44
  /** Test-only reset for proving the fail-closed process latch. */
29
45
  // oxlint-disable-next-line inhuman/no-empty-wrappers -- This test seam exposes Map.clear without exposing mutable production state.
@@ -82,17 +98,18 @@ export function createClaudeParentBridges(options) {
82
98
  }
83
99
  export async function runClaudeDirectMcpTrial(options) {
84
100
  const environment = options.environment ?? process.env;
85
- const profile = CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE;
101
+ const target = selectClaudeRuntimeTarget();
102
+ const fingerprint = runtimeLockFingerprint(target.lock);
86
103
  if (!isClaudeDirectMcpSelected(environment)) {
87
- const reason = disabledProfiles.get(profile.profileFingerprint);
104
+ const reason = disabledProfiles.get(fingerprint);
88
105
  throw new Error(reason ? `Claude direct MCP disabled for admitted profile: ${reason}` : `${CLAUDE_DIRECT_MCP_FLAG} is disabled`);
89
106
  }
90
107
  try {
91
- return await executeTrial({ ...options, environment });
108
+ return await executeTrial({ ...options, environment, target });
92
109
  }
93
110
  catch (error) {
94
111
  const reason = error instanceof Error ? error.message : String(error);
95
- disabledProfiles.set(profile.profileFingerprint, reason.slice(0, 500));
112
+ disabledProfiles.set(fingerprint, reason.slice(0, 500));
96
113
  throw error;
97
114
  }
98
115
  }
@@ -179,21 +196,21 @@ async function executeTrial(options) {
179
196
  zeroBearer: () => { host.bearer.fill(0); macKey.fill(0); replayVault.dispose(); },
180
197
  });
181
198
  try {
182
- const admission = await admitRuntimeProfile(CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE, {
199
+ const admission = await admitRuntimeLock(options.target.lock, {
183
200
  provider: 'claude',
184
201
  platform: process.platform,
185
202
  architecture: process.arch,
203
+ resolvedExecutable: await resolveClaudeScenarioExecutable(options.target),
186
204
  environment: runtimeEnv,
187
205
  forbiddenSecrets: [host.bearer.toString(), `Bearer ${host.bearer.toString()}`],
188
206
  initializeControlPlane: async () => {
189
207
  await options.initializeControlPlane?.();
190
- if (typeof createSdkMcpServer !== 'function' || typeof (options.query ?? sdkQuery) !== 'function')
191
- throw new Error('Claude SDK parent bridge methods unavailable');
192
- return { normalizedHandshake: CLAUDE_DIRECT_MCP_NORMALIZED_HANDSHAKE, capabilities: CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.requiredCapabilities, close: async () => undefined };
208
+ return observeClaudeRuntimeControlPlane({
209
+ createSdkMcpServer,
210
+ query: options.query ?? sdkQuery,
211
+ });
193
212
  },
194
213
  });
195
- if (!admission.ok)
196
- throw new Error(`RUNTIME_NOT_ADMITTED: ${admission.reason}`);
197
214
  reducer.markAdmitted();
198
215
  const projected = projectEndpoints(host.endpoints, admission.profile);
199
216
  if (!Array.isArray(projected))
@@ -212,7 +229,7 @@ async function executeTrial(options) {
212
229
  }
213
230
  reducer.markReady();
214
231
  const query = options.query ?? sdkQuery;
215
- const queryOptions = { query, runtimeEnv, workspacePath, model: options.model, profilePath: CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.command.absolutePath, mcpServers: bridges, spawnClaudeCodeProcess };
232
+ const queryOptions = { query, runtimeEnv, workspacePath, model: options.model, profilePath: admission.commandPath, mcpServers: bridges, spawnClaudeCodeProcess };
216
233
  reducer.beginTurn('direct-call', 'claude');
217
234
  const normal = await runQuery(queryOptions, `Invoke mcp__demo__${effectfulCase.pureToolId} exactly once with ${JSON.stringify(effectfulCase.pureArgs)}, then invoke mcp__demo__${effectfulCase.effectfulToolId} exactly once with ${JSON.stringify(effectfulCase.errorArgs)}. Wait for both results and do not use any other tool.`);
218
235
  if (normal.status !== 'success')
@@ -262,7 +279,8 @@ async function executeTrial(options) {
262
279
  throw new Error(`CLEANUP_FAILED: ${JSON.stringify(cleanup.failures)}`);
263
280
  return {
264
281
  selected: true,
265
- profileFingerprint: CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.profileFingerprint,
282
+ profileFingerprint: admission.identity.lockFingerprint,
283
+ runtimeProfile: admission.profile,
266
284
  artifact: compiled.artifact,
267
285
  evidence: reducer.ledger.events(),
268
286
  checks: { runtimeAdmitted: true, secretFreeProject: true, directCall: true, structuredToolError: true, fencedCancellation: true, providerTerminal: true, hostQuiescent: hostQuiescentBeforeCleanup, postCancelReuse: true, privateReplay: true, cleanup: true },
@@ -1,9 +1,35 @@
1
- import type { RuntimeLock } from './runtime-lock.js';
2
- import type { JsonObject, RuntimeCapabilityProfile } from './types.js';
1
+ import type { RuntimeLock, RuntimeLockControlPlane } from './runtime-lock.js';
2
+ import type { JsonObject } from './types.js';
3
3
  export declare const CLAUDE_DIRECT_MCP_NORMALIZED_HANDSHAKE: JsonObject;
4
- /** Reviewed macOS arm64 pin captured by RFC 0006. Other platforms fail closed. */
5
- export declare const CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE: RuntimeCapabilityProfile;
6
- /** Code-owned relocatable identity lock for the admitted public Claude SDK slice. */
4
+ export declare const CLAUDE_DIRECT_MCP_CAPABILITIES: {
5
+ readonly streamableHttp: true;
6
+ readonly controlPlaneHeaders: true;
7
+ readonly parentOwnedSdkMcp: true;
8
+ readonly cancellation: "abort-controller";
9
+ };
10
+ /** Code-owned relocatable identity lock captured by RFC 0006. */
7
11
  export declare const CLAUDE_DIRECT_MCP_DARWIN_ARM64_LOCK: RuntimeLock;
8
- /** Resolve the bundled platform binary relative to the installed SDK package. */
9
- export declare function resolveClaudeScenarioExecutable(): Promise<string>;
12
+ /** Provisional Linux x64 glibc lock; CI re-verifies every artifact before admission. */
13
+ export declare const CLAUDE_DIRECT_MCP_LINUX_X64_GLIBC_LOCK: RuntimeLock;
14
+ export type ClaudeRuntimeTarget = {
15
+ id: 'darwin-arm64' | 'linux-x64-glibc';
16
+ platform: 'darwin' | 'linux';
17
+ architecture: 'arm64' | 'x64';
18
+ libc?: 'glibc';
19
+ packageName: string;
20
+ lock: RuntimeLock;
21
+ };
22
+ export declare const CLAUDE_RUNTIME_TARGETS: readonly ClaudeRuntimeTarget[];
23
+ export type ClaudeRuntimeEnvironment = {
24
+ platform: string;
25
+ architecture: string;
26
+ libc?: string;
27
+ };
28
+ export declare function detectClaudeRuntimeEnvironment(): ClaudeRuntimeEnvironment;
29
+ export declare function selectClaudeRuntimeTarget(environment?: ClaudeRuntimeEnvironment): ClaudeRuntimeTarget;
30
+ /** Resolve the selected optional-package binary through Node package resolution. */
31
+ export declare function resolveClaudeScenarioExecutable(target?: ClaudeRuntimeTarget): Promise<string>;
32
+ export declare function observeClaudeRuntimeControlPlane(options: {
33
+ createSdkMcpServer: unknown;
34
+ query: unknown;
35
+ }): RuntimeLockControlPlane;
@@ -1,5 +1,5 @@
1
- import { access, realpath } from 'node:fs/promises';
2
1
  import { constants } from 'node:fs';
2
+ import { access, realpath } from 'node:fs/promises';
3
3
  import { createRequire } from 'node:module';
4
4
  import { dirname, join } from 'node:path';
5
5
  export const CLAUDE_DIRECT_MCP_NORMALIZED_HANDSHAKE = {
@@ -13,85 +13,117 @@ export const CLAUDE_DIRECT_MCP_NORMALIZED_HANDSHAKE = {
13
13
  cancellation: 'abort-controller',
14
14
  sdkMethods: ['createSdkMcpServer', 'query'],
15
15
  };
16
- /** Reviewed macOS arm64 pin captured by RFC 0006. Other platforms fail closed. */
17
- export const CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE = {
18
- format: 'pathgrade-direct-mcp-runtime-profile-v1',
19
- provider: 'claude',
20
- platform: 'darwin',
21
- architecture: 'arm64',
22
- controlPlane: 'native-sdk-parent-bridge',
23
- command: {
24
- absolutePath: '/Users/nadavlac/projects/agent-evals/node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64/claude',
16
+ export const CLAUDE_DIRECT_MCP_CAPABILITIES = {
17
+ streamableHttp: true,
18
+ controlPlaneHeaders: true,
19
+ parentOwnedSdkMcp: true,
20
+ cancellation: 'abort-controller',
21
+ };
22
+ const SDK_SHA256 = '48bde6aeabf7e71ad5528bf52c8feb1642c21f505ea2495c70f39db7df226d97';
23
+ const ZOD_SHA256 = '2a3455cecff4f7021c92d0a3e2e5fc170c0448dc5cc261160127e08f4888a9c2';
24
+ const NORMALIZED_HANDSHAKE_SHA256 = '990b779b75145c8d7bcc8cfebcb5b9c1aae30eb1436393b38e7e997941ecc162';
25
+ const CLAUDE_VERSION = '2.1.141 (Claude Code)';
26
+ const COMMAND_ARTIFACT = 'claude-code-bundled-2.1.141';
27
+ function claudeLock(options) {
28
+ return {
29
+ format: 'pathgrade-direct-mcp-runtime-lock-v1',
30
+ provider: 'claude',
31
+ platform: options.platform,
32
+ architecture: options.architecture,
33
+ controlPlane: 'native-sdk-parent-bridge',
34
+ version: CLAUDE_VERSION,
35
+ commandArtifact: COMMAND_ARTIFACT,
25
36
  args: [],
26
37
  versionArgs: ['--version'],
27
- },
28
- expectedVersion: '2.1.141 (Claude Code)',
29
- artifacts: [
30
- {
31
- label: 'claude-agent-sdk-0.2.141',
32
- absolutePath: '/Users/nadavlac/projects/agent-evals/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs',
33
- sha256: '48bde6aeabf7e71ad5528bf52c8feb1642c21f505ea2495c70f39db7df226d97',
34
- },
35
- {
36
- label: 'claude-code-bundled-2.1.141',
37
- absolutePath: '/Users/nadavlac/projects/agent-evals/node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64/claude',
38
- sha256: '31ac95bb19a33b1d0cddd3f3ff594bf8bfd2be5051cd2af7867109641cab705e',
39
- },
40
- {
41
- label: 'zod-4.3.6-commonjs-entry',
42
- absolutePath: '/Users/nadavlac/projects/agent-evals/node_modules/zod/index.cjs',
43
- sha256: '2a3455cecff4f7021c92d0a3e2e5fc170c0448dc5cc261160127e08f4888a9c2',
44
- },
45
- ],
46
- requiredCapabilities: {
47
- streamableHttp: true,
48
- controlPlaneHeaders: true,
49
- parentOwnedSdkMcp: true,
50
- cancellation: 'abort-controller',
51
- },
52
- profileFingerprint: '463d1485d70e542cf2a356cae007469a7d94d0e848a26d9e9b7470dbc5262104',
53
- runtimeCapabilityFingerprint: '990b779b75145c8d7bcc8cfebcb5b9c1aae30eb1436393b38e7e997941ecc162',
54
- };
55
- /** Code-owned relocatable identity lock for the admitted public Claude SDK slice. */
56
- export const CLAUDE_DIRECT_MCP_DARWIN_ARM64_LOCK = {
57
- format: 'pathgrade-direct-mcp-runtime-lock-v1',
58
- provider: 'claude',
38
+ artifacts: [
39
+ { id: 'claude-agent-sdk-0.2.141', relativePath: '@anthropic-ai/claude-agent-sdk/sdk.mjs', sha256: SDK_SHA256 },
40
+ { id: COMMAND_ARTIFACT, relativePath: `${options.packageName}/claude`, sha256: options.commandSha256 },
41
+ { id: 'zod-4.3.6-commonjs-entry', relativePath: 'zod/index.cjs', sha256: ZOD_SHA256 },
42
+ ],
43
+ capabilities: CLAUDE_DIRECT_MCP_CAPABILITIES,
44
+ normalizedHandshakeSha256: NORMALIZED_HANDSHAKE_SHA256,
45
+ };
46
+ }
47
+ /** Code-owned relocatable identity lock captured by RFC 0006. */
48
+ export const CLAUDE_DIRECT_MCP_DARWIN_ARM64_LOCK = claudeLock({
59
49
  platform: 'darwin',
60
50
  architecture: 'arm64',
61
- controlPlane: 'native-sdk-parent-bridge',
62
- version: CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.expectedVersion,
63
- commandArtifact: 'claude-code-bundled-2.1.141',
64
- args: CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.command.args,
65
- versionArgs: CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.command.versionArgs,
66
- artifacts: [
67
- {
68
- id: 'claude-agent-sdk-0.2.141',
69
- relativePath: '@anthropic-ai/claude-agent-sdk/sdk.mjs',
70
- sha256: CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.artifacts[0].sha256,
71
- },
72
- {
73
- id: 'claude-code-bundled-2.1.141',
74
- relativePath: '@anthropic-ai/claude-agent-sdk-darwin-arm64/claude',
75
- sha256: CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.artifacts[1].sha256,
76
- },
77
- {
78
- id: 'zod-4.3.6-commonjs-entry',
79
- relativePath: 'zod/index.cjs',
80
- sha256: CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.artifacts[2].sha256,
81
- },
82
- ],
83
- capabilities: CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.requiredCapabilities,
84
- normalizedHandshakeSha256: CLAUDE_DIRECT_MCP_DARWIN_ARM64_PROFILE.runtimeCapabilityFingerprint,
85
- };
86
- /** Resolve the bundled platform binary relative to the installed SDK package. */
87
- export async function resolveClaudeScenarioExecutable() {
88
- const sdkEntry = createRequire(import.meta.url).resolve('@anthropic-ai/claude-agent-sdk');
89
- const candidate = join(dirname(sdkEntry), '..', 'claude-agent-sdk-darwin-arm64', 'claude');
51
+ packageName: '@anthropic-ai/claude-agent-sdk-darwin-arm64',
52
+ commandSha256: '31ac95bb19a33b1d0cddd3f3ff594bf8bfd2be5051cd2af7867109641cab705e',
53
+ });
54
+ /** Provisional Linux x64 glibc lock; CI re-verifies every artifact before admission. */
55
+ export const CLAUDE_DIRECT_MCP_LINUX_X64_GLIBC_LOCK = claudeLock({
56
+ platform: 'linux',
57
+ architecture: 'x64',
58
+ packageName: '@anthropic-ai/claude-agent-sdk-linux-x64',
59
+ commandSha256: '832be26e8f15b2ae99e520a22b034fc4bfad1cb5b84de6b706487072c56bb42e',
60
+ });
61
+ export const CLAUDE_RUNTIME_TARGETS = [
62
+ {
63
+ id: 'darwin-arm64',
64
+ platform: 'darwin',
65
+ architecture: 'arm64',
66
+ packageName: '@anthropic-ai/claude-agent-sdk-darwin-arm64',
67
+ lock: CLAUDE_DIRECT_MCP_DARWIN_ARM64_LOCK,
68
+ },
69
+ {
70
+ id: 'linux-x64-glibc',
71
+ platform: 'linux',
72
+ architecture: 'x64',
73
+ libc: 'glibc',
74
+ packageName: '@anthropic-ai/claude-agent-sdk-linux-x64',
75
+ lock: CLAUDE_DIRECT_MCP_LINUX_X64_GLIBC_LOCK,
76
+ },
77
+ ];
78
+ export function detectClaudeRuntimeEnvironment() {
79
+ if (process.platform !== 'linux')
80
+ return { platform: process.platform, architecture: process.arch };
81
+ const report = process.report?.getReport();
82
+ const glibc = report?.header?.glibcVersionRuntime;
83
+ return {
84
+ platform: process.platform,
85
+ architecture: process.arch,
86
+ libc: typeof glibc === 'string' && glibc.length > 0 ? 'glibc' : 'unknown',
87
+ };
88
+ }
89
+ export function selectClaudeRuntimeTarget(environment = detectClaudeRuntimeEnvironment()) {
90
+ const target = CLAUDE_RUNTIME_TARGETS.find((candidate) => (candidate.platform === environment.platform
91
+ && candidate.architecture === environment.architecture
92
+ && candidate.libc === environment.libc));
93
+ if (!target) {
94
+ const identity = [environment.platform, environment.architecture, environment.libc].filter(Boolean).join('-');
95
+ throw new Error(`RUNTIME_NOT_ADMITTED: unsupported Claude runtime target: ${identity}`);
96
+ }
97
+ return target;
98
+ }
99
+ /** Resolve the selected optional-package binary through Node package resolution. */
100
+ export async function resolveClaudeScenarioExecutable(target = selectClaudeRuntimeTarget()) {
101
+ let packageJson;
102
+ try {
103
+ packageJson = createRequire(import.meta.url).resolve(`${target.packageName}/package.json`);
104
+ }
105
+ catch {
106
+ throw new Error(`RUNTIME_NOT_ADMITTED: missing Claude runtime package: ${target.packageName}`);
107
+ }
108
+ const candidate = join(dirname(packageJson), 'claude');
90
109
  try {
91
110
  await access(candidate, constants.X_OK);
92
111
  return realpath(candidate);
93
112
  }
94
113
  catch {
95
- throw new Error('RUNTIME_NOT_ADMITTED: no bundled Claude executable was discovered');
114
+ throw new Error(`RUNTIME_NOT_ADMITTED: Claude runtime executable is unavailable: ${target.id}`);
115
+ }
116
+ }
117
+ export function observeClaudeRuntimeControlPlane(options) {
118
+ if (typeof options.createSdkMcpServer !== 'function' || typeof options.query !== 'function') {
119
+ throw new Error('Claude SDK parent bridge methods unavailable');
120
+ }
121
+ if (typeof AbortController !== 'function' || typeof AbortController.prototype.abort !== 'function') {
122
+ throw new Error('Claude AbortController cancellation unavailable');
96
123
  }
124
+ return {
125
+ normalizedHandshake: CLAUDE_DIRECT_MCP_NORMALIZED_HANDSHAKE,
126
+ capabilities: CLAUDE_DIRECT_MCP_CAPABILITIES,
127
+ close: async () => undefined,
128
+ };
97
129
  }
@@ -8,7 +8,7 @@ import { projectEndpoints } from './projection.js';
8
8
  import { admitRuntimeLock } from './runtime-lock.js';
9
9
  import { startScenarioHttpHost } from './scenario-http-host.js';
10
10
  import { createClaudeParentBridges } from './claude-direct-mcp.js';
11
- import { CLAUDE_DIRECT_MCP_DARWIN_ARM64_LOCK, CLAUDE_DIRECT_MCP_NORMALIZED_HANDSHAKE, resolveClaudeScenarioExecutable } from './claude-profile.js';
11
+ import { observeClaudeRuntimeControlPlane, resolveClaudeScenarioExecutable, selectClaudeRuntimeTarget } from './claude-profile.js';
12
12
  const defaultCoordinatorDependencies = {
13
13
  startHost: startScenarioHttpHost,
14
14
  scanBearerSurfaces,
@@ -286,8 +286,10 @@ function scenarioScanRoots(workspacePath, environment) {
286
286
  ].filter((path) => typeof path === 'string' && path.length > 0))];
287
287
  }
288
288
  export async function startPublicClaudeScenarioRuntime(options, dependencies = {}) {
289
- const lock = dependencies.lock ?? CLAUDE_DIRECT_MCP_DARWIN_ARM64_LOCK;
290
- const resolveExecutable = dependencies.resolveExecutable ?? resolveClaudeScenarioExecutable;
289
+ const target = dependencies.lock ? undefined : selectClaudeRuntimeTarget();
290
+ const lock = dependencies.lock ?? target.lock;
291
+ const resolveExecutable = dependencies.resolveExecutable
292
+ ?? (async () => resolveClaudeScenarioExecutable(target));
291
293
  const coordinator = await startScenarioCoordinator({
292
294
  ...options,
293
295
  provider: 'claude',
@@ -301,16 +303,10 @@ export async function startPublicClaudeScenarioRuntime(options, dependencies = {
301
303
  environment: options.environment,
302
304
  forbiddenSecrets: [bearer.slice('Bearer '.length), bearer],
303
305
  ...(dependencies.commandVersion ? { commandVersion: dependencies.commandVersion } : {}),
304
- initializeControlPlane: async () => {
305
- if (typeof createSdkMcpServer !== 'function' || typeof sdkQuery !== 'function') {
306
- throw new Error('Claude SDK parent bridge methods unavailable');
307
- }
308
- return {
309
- normalizedHandshake: CLAUDE_DIRECT_MCP_NORMALIZED_HANDSHAKE,
310
- capabilities: lock.capabilities,
311
- close: async () => undefined,
312
- };
313
- },
306
+ initializeControlPlane: async () => observeClaudeRuntimeControlPlane({
307
+ createSdkMcpServer,
308
+ query: sdkQuery,
309
+ }),
314
310
  });
315
311
  const projected = projectEndpoints(context.endpoints, admission.profile);
316
312
  if (!Array.isArray(projected))
@@ -320,7 +316,7 @@ export async function startPublicClaudeScenarioRuntime(options, dependencies = {
320
316
  }));
321
317
  const bridges = createClaudeParentBridges({ artifact: options.artifact, projections: materialized });
322
318
  return {
323
- value: bridges,
319
+ value: { bridges, commandPath: admission.commandPath },
324
320
  async interrupt() { },
325
321
  async waitForTerminal() { },
326
322
  async close() {
@@ -340,9 +336,10 @@ export async function startPublicClaudeScenarioRuntime(options, dependencies = {
340
336
  },
341
337
  });
342
338
  return {
343
- claudeServers: coordinator.attachment,
339
+ claudeServers: coordinator.attachment.bridges,
344
340
  configureSession(sessionOptions) {
345
- sessionOptions.scenarioMcpServers = coordinator.attachment;
341
+ sessionOptions.scenarioMcpServers = coordinator.attachment.bridges;
342
+ sessionOptions.admittedClaudeCodeExecutable = coordinator.attachment.commandPath;
346
343
  },
347
344
  beginTurn: coordinator.beginTurn,
348
345
  settleTurn: coordinator.settleTurn,
package/dist/types.d.ts CHANGED
@@ -423,6 +423,8 @@ export interface AgentSessionOptions {
423
423
  scriptedMcpHost?: import('./providers/scripted-mcp-mock-host.js').ScriptedMcpMockHost;
424
424
  /** Parent-owned public ScenarioMachineV2 bridge; never serialized into child config. */
425
425
  scenarioMcpServers?: Record<string, import('@anthropic-ai/claude-agent-sdk').McpSdkServerConfigWithInstance>;
426
+ /** RuntimeLock-admitted Claude executable; wins over developer overrides for ScenarioMachineV2 sessions. */
427
+ admittedClaudeCodeExecutable?: string;
426
428
  /** Parent-owned admitted Codex app-server mount; projected only into thread/start memory. */
427
429
  codexScenarioMount?: import('./agents/codex-app-server/scenario-mount.js').CodexScenarioMount;
428
430
  /** Runtime-only values inherited by drivers and persistence sinks for redaction. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/pathgrade",
3
- "version": "1.0.28",
3
+ "version": "1.0.29",
4
4
  "packageManager": "yarn@4.12.0",
5
5
  "description": "Evaluate whether AI agents discover and use your skills correctly",
6
6
  "exports": {
@@ -140,5 +140,5 @@
140
140
  "typescript": "^5.9.3",
141
141
  "zod": "4.3.6"
142
142
  },
143
- "falconPackageHash": "f8df1d8950a1ce263fb945ab13722fdb8328a2f761153de0df90d0e9"
143
+ "falconPackageHash": "126198d020df14b3e6fceef3b0325ac5e84411c5e1b544a0167de604"
144
144
  }