impel-cli 0.20.42 → 0.20.44

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,14 +7,22 @@ import os from "node:os";
7
7
  import path from "node:path";
8
8
  import { fileURLToPath } from "node:url";
9
9
 
10
+ import {
11
+ MANAGED_AGENT_MCP_SERVER,
12
+ NATIVE_AGENT_ANSWER_TOOL,
13
+ nativeToolNamespace,
14
+ resolveManagedCodexAgentProfile,
15
+ } from "../src/agents.js";
10
16
  import { nativeSpawnInvocation } from "../src/nativeProcess.js";
11
- import { summarizeRawAttempt } from "./analyze-native-codex.mjs";
17
+ import { parseStrictJsonLines, summarizeRawAttempt } from "./analyze-native-codex.mjs";
12
18
 
13
19
  const PROFILE_SCHEMA = "impel.native-codex-profile.v1";
14
20
  const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;
15
21
  const DEFAULT_GRACE_MS = 5_000;
16
22
  const MAX_CAPTURE_BYTES = 256 * 1024 * 1024;
23
+ const MAX_CONFIG_BYTES = 1024 * 1024;
17
24
  const TENANT_PREFLIGHT_RETRY_DELAYS_MS = [250, 750, 1_500];
25
+ const ISOLATED_PROFILE_PREFIX = "impel-native-codex-benchmark-";
18
26
 
19
27
  function privateDirectory(directory) {
20
28
  if (fs.existsSync(directory) && fs.lstatSync(directory).isSymbolicLink()) {
@@ -29,6 +37,16 @@ function privateWrite(filePath, contents) {
29
37
  try { fs.chmodSync(filePath, 0o600); } catch { /* Best effort on Windows. */ }
30
38
  }
31
39
 
40
+ function privateCopy(source, destination) {
41
+ const stat = fs.lstatSync(source);
42
+ if (!stat.isFile() || stat.size > MAX_CONFIG_BYTES) {
43
+ throw new Error("the selected Impel config must be a bounded regular file");
44
+ }
45
+ privateDirectory(path.dirname(destination));
46
+ fs.copyFileSync(source, destination, fs.constants.COPYFILE_EXCL);
47
+ try { fs.chmodSync(destination, 0o600); } catch { /* Best effort on Windows. */ }
48
+ }
49
+
32
50
  function openPrivate(filePath) {
33
51
  const descriptor = fs.openSync(filePath, "wx", 0o600);
34
52
  try { fs.chmodSync(filePath, 0o600); } catch { /* Best effort on Windows. */ }
@@ -233,6 +251,350 @@ export async function assertExpectedTenant({ expectedTenant, impelBinary = "impe
233
251
  return actual;
234
252
  }
235
253
 
254
+ function selectedConfigPath(environment = process.env) {
255
+ const home = environment.HOME || environment.USERPROFILE || os.homedir();
256
+ const root = environment.IMPEL_CONFIG_DIR || path.join(home, ".config", "impel");
257
+ return path.join(root, "config.json");
258
+ }
259
+
260
+ function isolatedBenchmarkPaths(root, tenantId) {
261
+ const home = path.join(root, "home");
262
+ const configRoot = path.join(root, "config");
263
+ return {
264
+ root,
265
+ home,
266
+ configRoot,
267
+ codexHome: path.join(configRoot, "cli", "tenants", tenantId, "codex"),
268
+ nativeCodexHome: path.join(root, "native-codex"),
269
+ appHome: path.join(root, "apps"),
270
+ };
271
+ }
272
+
273
+ function isolatedBenchmarkEnvironment(options, paths, telemetryPath, baseEnvironment) {
274
+ return {
275
+ ...baseEnvironment,
276
+ HOME: paths.home,
277
+ USERPROFILE: paths.home,
278
+ XDG_CONFIG_HOME: path.join(paths.home, ".config"),
279
+ IMPEL_CONFIG_DIR: paths.configRoot,
280
+ IMPEL_APP_HOME: paths.appHome,
281
+ // `impel codex` runs against the tenant's generated profile directory. An
282
+ // explicit CODEX_HOME overrides that derivation, so it must point at the
283
+ // isolated tenant profile; pointing it anywhere else starts Codex with no
284
+ // MCP servers, and the cohort silently measures model prose instead of
285
+ // agent latency.
286
+ CODEX_HOME: paths.codexHome,
287
+ IMPEL_SKIP_UPDATE_CHECK: "1",
288
+ IMPEL_NATIVE_AGENT_TELEMETRY_PATH: telemetryPath,
289
+ IMPEL_NATIVE_HOST: options.mode === "direct"
290
+ ? "codex-direct-profile"
291
+ : "codex-compatible-agent",
292
+ IMPEL_NATIVE_HOST_BUILD: options.hostBuild,
293
+ IMPEL_NATIVE_BENCHMARK: "1",
294
+ };
295
+ }
296
+
297
+ function profileEnvironmentEntry(contents, name, value) {
298
+ return contents.includes(`${JSON.stringify(name)} = ${JSON.stringify(value)}`);
299
+ }
300
+
301
+ function regularFileContents(filePath, missingMessage) {
302
+ try {
303
+ const stat = fs.lstatSync(filePath);
304
+ if (!stat.isFile() || stat.isSymbolicLink()) throw new Error();
305
+ return fs.readFileSync(filePath, "utf8");
306
+ } catch {
307
+ throw new Error(missingMessage);
308
+ }
309
+ }
310
+
311
+ function tomlSection(contents, sectionName) {
312
+ const header = `[${sectionName}]`;
313
+ const lines = contents.split(/\r?\n/u);
314
+ const matches = lines.flatMap((line, index) => line.trim() === header ? [index] : []);
315
+ if (matches.length !== 1) return null;
316
+ const start = matches[0] + 1;
317
+ const relativeEnd = lines.slice(start).findIndex((line) => /^\s*\[/u.test(line));
318
+ return lines.slice(start, relativeEnd === -1 ? lines.length : start + relativeEnd).join("\n");
319
+ }
320
+
321
+ function tomlAssignment(section, name) {
322
+ if (section === null) return null;
323
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
324
+ const matches = [...section.matchAll(new RegExp(`^\\s*${escaped}\\s*=\\s*(.+?)\\s*$`, "gmu"))];
325
+ return matches.length === 1 ? matches[0][1] : null;
326
+ }
327
+
328
+ function tomlStringList(value) {
329
+ if (typeof value !== "string" || !/^\s*\[.*\]\s*$/su.test(value)) return null;
330
+ try {
331
+ const parsed = JSON.parse(value);
332
+ return Array.isArray(parsed) && parsed.every((entry) => typeof entry === "string")
333
+ ? parsed
334
+ : null;
335
+ } catch {
336
+ return null;
337
+ }
338
+ }
339
+
340
+ function assertSelectedProfileContract(contents, environment, policyFingerprint) {
341
+ const mcpSectionName = `mcp_servers.${MANAGED_AGENT_MCP_SERVER}`;
342
+ const mcpSection = tomlSection(contents, mcpSectionName);
343
+ if (mcpSection === null) {
344
+ throw new Error(`the isolated managed Codex agent profile has no [${mcpSectionName}] block`);
345
+ }
346
+ if (!tomlAssignment(mcpSection, "command") || !tomlAssignment(mcpSection, "args")) {
347
+ throw new Error("the isolated managed Codex agent profile has an incomplete MCP command binding");
348
+ }
349
+ if (tomlAssignment(mcpSection, "tool_timeout_sec") !== "120") {
350
+ throw new Error("the isolated managed Codex agent profile has no reviewed MCP tool timeout");
351
+ }
352
+ const enabledTools = tomlStringList(tomlAssignment(mcpSection, "enabled_tools"));
353
+ if (!enabledTools?.includes(NATIVE_AGENT_ANSWER_TOOL)) {
354
+ throw new Error(
355
+ `the isolated managed Codex agent profile does not enable ${NATIVE_AGENT_ANSWER_TOOL}`,
356
+ );
357
+ }
358
+ const mcpEnvironment = tomlAssignment(mcpSection, "env");
359
+ for (const name of [
360
+ "IMPEL_NATIVE_AGENT_TELEMETRY_PATH",
361
+ "IMPEL_NATIVE_HOST",
362
+ "IMPEL_NATIVE_HOST_BUILD",
363
+ "IMPEL_NATIVE_BENCHMARK",
364
+ ]) {
365
+ if (!profileEnvironmentEntry(mcpEnvironment || "", name, environment[name])) {
366
+ throw new Error(`the isolated managed Codex agent MCP env did not bake ${name}`);
367
+ }
368
+ }
369
+ const mcpArgs = tomlAssignment(mcpSection, "args") || "";
370
+ if (!mcpArgs.includes(JSON.stringify("--policy-fingerprint"))
371
+ || !mcpArgs.includes(JSON.stringify(policyFingerprint))) {
372
+ throw new Error("the isolated managed Codex agent profile lost its policy fingerprint binding");
373
+ }
374
+
375
+ const codeModeSection = tomlSection(contents, "features.code_mode");
376
+ if (tomlAssignment(codeModeSection, "enabled") !== "true") {
377
+ throw new Error("the isolated managed Codex agent profile does not enable reviewed code mode");
378
+ }
379
+ const namespaces = tomlStringList(
380
+ tomlAssignment(codeModeSection, "direct_only_tool_namespaces"),
381
+ );
382
+ if (!namespaces?.includes(nativeToolNamespace())) {
383
+ throw new Error(
384
+ `the isolated managed Codex agent profile does not bind ${nativeToolNamespace()} as a direct-only namespace`,
385
+ );
386
+ }
387
+ }
388
+
389
+ export function verifyIsolatedBenchmarkProfile({
390
+ codexHome,
391
+ expectedTenant,
392
+ agent,
393
+ environment,
394
+ }) {
395
+ const manifestPath = path.join(codexHome, "agents", "impel-managed", ".manifest.json");
396
+ let manifest;
397
+ try {
398
+ const stat = fs.lstatSync(manifestPath);
399
+ if (!stat.isFile() || stat.isSymbolicLink()) throw new Error();
400
+ manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
401
+ } catch {
402
+ throw new Error("the isolated managed Codex agent manifest was not generated");
403
+ }
404
+ if (manifest?.client !== "codex"
405
+ || manifest.tenantId !== expectedTenant
406
+ || manifest.directProfiles !== true
407
+ || manifest.directCodeMode !== true
408
+ || manifest.nativeBenchmark !== true
409
+ || !Array.isArray(manifest.files)
410
+ || !Array.isArray(manifest.profiles)
411
+ || !manifest.contentDigests
412
+ || typeof manifest.contentDigests !== "object"
413
+ || Array.isArray(manifest.contentDigests)
414
+ || !manifest.nativeAgentTelemetryEnvironment
415
+ || typeof manifest.nativeAgentTelemetryEnvironment !== "object"
416
+ || Array.isArray(manifest.nativeAgentTelemetryEnvironment)) {
417
+ throw new Error("the isolated managed Codex agent manifest is missing its benchmark telemetry contract");
418
+ }
419
+ for (const name of [
420
+ "IMPEL_NATIVE_AGENT_TELEMETRY_PATH",
421
+ "IMPEL_NATIVE_HOST",
422
+ "IMPEL_NATIVE_HOST_BUILD",
423
+ ]) {
424
+ if (manifest.nativeAgentTelemetryEnvironment[name] !== environment[name]) {
425
+ throw new Error(`the isolated managed Codex agent manifest did not retain ${name}`);
426
+ }
427
+ }
428
+ const matches = (Array.isArray(manifest.agents) ? manifest.agents : []).filter((record) =>
429
+ record
430
+ && !record.retired
431
+ && [record.agentId, record.title, record.profileName].includes(agent)
432
+ );
433
+ if (matches.length !== 1) {
434
+ throw new Error(`the isolated managed Codex agent ${JSON.stringify(agent)} was not generated exactly once`);
435
+ }
436
+ const [record] = matches;
437
+ if (!/^[a-f0-9]{64}$/u.test(record.policyFingerprint || "")) {
438
+ throw new Error("the isolated managed Codex agent manifest has no policy fingerprint");
439
+ }
440
+ let resolved;
441
+ try {
442
+ resolved = resolveManagedCodexAgentProfile(codexHome, expectedTenant, agent);
443
+ } catch (error) {
444
+ throw new Error(`the isolated managed Codex agent profile failed its managed integrity check: ${error.message}`);
445
+ }
446
+ const profileFileName = resolved.profileFileName;
447
+ if (typeof profileFileName !== "string"
448
+ || path.basename(profileFileName) !== profileFileName
449
+ || !profileFileName.endsWith(".config.toml")) {
450
+ throw new Error("the isolated managed Codex agent profile mapping is invalid");
451
+ }
452
+ const profilePath = path.join(codexHome, profileFileName);
453
+ const contents = regularFileContents(
454
+ profilePath,
455
+ "the isolated managed Codex agent profile was not written as a regular file",
456
+ );
457
+ const definitionFileName = `${resolved.profileName}.toml`;
458
+ if (!manifest.files.includes(definitionFileName)) {
459
+ throw new Error("the isolated managed Codex agent definition is absent from its manifest");
460
+ }
461
+ const definitionPath = path.join(codexHome, "agents", definitionFileName);
462
+ const definitionContents = regularFileContents(
463
+ definitionPath,
464
+ "the isolated managed Codex agent definition was not written as a regular file",
465
+ );
466
+ if (manifest.contentDigests?.[`agents/${definitionFileName}`]
467
+ !== crypto.createHash("sha256").update(fs.readFileSync(definitionPath)).digest("hex")) {
468
+ throw new Error("the isolated managed Codex agent definition failed its managed integrity check");
469
+ }
470
+ assertSelectedProfileContract(contents, environment, record.policyFingerprint);
471
+ try {
472
+ assertSelectedProfileContract(definitionContents, environment, record.policyFingerprint);
473
+ } catch (error) {
474
+ throw new Error(error.message.replace("agent profile", "agent definition"));
475
+ }
476
+ return { manifestPath, profilePath, profileFileName, definitionPath };
477
+ }
478
+
479
+ async function generateIsolatedBenchmarkProfile(options, isolation) {
480
+ // `managedSkillProfiles` only emits the "Impel isolated Codex" target when a
481
+ // tenant is selected AND its profile directory already exists, so a fresh
482
+ // isolated root would otherwise generate the native profile only — leaving
483
+ // Codex with no impel_agent MCP server and the cohort measuring model prose.
484
+ const select = impelInvocation(options.impelBinary, [
485
+ "tenant",
486
+ "use",
487
+ options.expectedTenant,
488
+ ], isolation.environment);
489
+ const selected = await runCaptured(select.command, select.args, {
490
+ environment: isolation.environment,
491
+ });
492
+ if (selected.code !== 0) {
493
+ throw new Error(
494
+ `\`impel tenant use ${options.expectedTenant}\` exited with status ${selected.code ?? "unknown"}`,
495
+ );
496
+ }
497
+ fs.mkdirSync(isolation.codexHome, { recursive: true, mode: 0o700 });
498
+
499
+ const invocation = impelInvocation(options.impelBinary, [
500
+ "agents",
501
+ "sync",
502
+ "codex",
503
+ "--skip-apps",
504
+ ], isolation.environment);
505
+ const result = await runCaptured(invocation.command, invocation.args, {
506
+ environment: isolation.environment,
507
+ });
508
+ if (result.code !== 0) {
509
+ throw new Error(`\`impel agents sync codex\` exited with status ${result.code ?? "unknown"}`);
510
+ }
511
+ }
512
+
513
+ /**
514
+ * Run a cohort with the CLI's existing IMPEL_CONFIG_DIR override pointed at a
515
+ * private temporary root. Only config.json is copied in for authentication;
516
+ * no managed profile from the operator's config root is read or written.
517
+ */
518
+ export async function withIsolatedBenchmarkProfile(options, sessionDir, callback, {
519
+ baseEnvironment = process.env,
520
+ operatorConfigPath = selectedConfigPath(baseEnvironment),
521
+ prepareProfile = generateIsolatedBenchmarkProfile,
522
+ assertTenant = assertExpectedTenant,
523
+ stderr = process.stderr,
524
+ temporaryParent = os.tmpdir(),
525
+ } = {}) {
526
+ const root = fs.mkdtempSync(path.join(temporaryParent, ISOLATED_PROFILE_PREFIX));
527
+ const paths = isolatedBenchmarkPaths(root, options.expectedTenant);
528
+ const telemetryPath = path.join(sessionDir, "telemetry.jsonl");
529
+ const environment = isolatedBenchmarkEnvironment(
530
+ options,
531
+ paths,
532
+ telemetryPath,
533
+ baseEnvironment,
534
+ );
535
+ let removed = false;
536
+ const removeRoot = () => {
537
+ if (removed) return;
538
+ removed = true;
539
+ fs.rmSync(root, { recursive: true, force: true });
540
+ };
541
+ // Synchronous exit cleanup also covers Ctrl-C/termination paths where the
542
+ // event loop cannot continue far enough to unwind the async callback.
543
+ process.once("exit", removeRoot);
544
+ let prepared = false;
545
+ try {
546
+ privateDirectory(paths.home);
547
+ privateDirectory(paths.configRoot);
548
+ stderr.write(
549
+ `Using isolated benchmark profile ${paths.codexHome}; cohort telemetry: ${telemetryPath}\n`,
550
+ );
551
+ try {
552
+ privateCopy(operatorConfigPath, path.join(paths.configRoot, "config.json"));
553
+ // Explicit sync discovers initialized isolated CLI roots. Creating only
554
+ // this empty destination lets the production sync command generate the
555
+ // complete agent catalog without launching Codex or touching a live
556
+ // profile.
557
+ privateDirectory(paths.codexHome);
558
+ await assertTenant({
559
+ expectedTenant: options.expectedTenant,
560
+ impelBinary: options.impelBinary,
561
+ environment,
562
+ });
563
+ await prepareProfile(options, {
564
+ ...paths,
565
+ telemetryPath,
566
+ environment,
567
+ });
568
+ const verified = verifyIsolatedBenchmarkProfile({
569
+ codexHome: paths.codexHome,
570
+ expectedTenant: options.expectedTenant,
571
+ agent: options.agent,
572
+ environment,
573
+ });
574
+ // Profile preparation must not contribute any events to the measured
575
+ // cohort. The generated profile keeps pointing at this same path.
576
+ fs.rmSync(telemetryPath, { force: true });
577
+ prepared = true;
578
+ return await callback({
579
+ ...paths,
580
+ ...verified,
581
+ telemetryPath,
582
+ environment,
583
+ });
584
+ } catch (error) {
585
+ if (prepared) throw error;
586
+ throw new Error(
587
+ `could not generate the isolated benchmark profile for tenant ${JSON.stringify(options.expectedTenant)}: `
588
+ + `${error?.message || error}. Verify Impel auth, network access, the selected tenant, and `
589
+ + "that `impel agents sync codex` can fetch this tenant's agent catalog.",
590
+ );
591
+ }
592
+ } finally {
593
+ process.off("exit", removeRoot);
594
+ removeRoot();
595
+ }
596
+ }
597
+
236
598
  function listRollouts(root, startedAtMs, endedAtMs) {
237
599
  if (!fs.existsSync(root)) return [];
238
600
  const results = [];
@@ -439,35 +801,141 @@ export function safeAttemptRecord({ options, index, processResult, summary, json
439
801
  };
440
802
  }
441
803
 
804
+ export function profiledCodexAttemptOptions(options, telemetryPath, environment = process.env) {
805
+ return {
806
+ codexArgs: [
807
+ "codex",
808
+ "--benchmark",
809
+ ...(options.mode === "direct" ? ["--agent", options.agent] : []),
810
+ "exec",
811
+ "--json",
812
+ ...options.extraArgs,
813
+ "-",
814
+ ],
815
+ environment: {
816
+ ...environment,
817
+ IMPEL_NATIVE_AGENT_TELEMETRY_PATH: telemetryPath,
818
+ IMPEL_NATIVE_HOST: options.mode === "direct" ? "codex-direct-profile" : "codex-compatible-agent",
819
+ IMPEL_NATIVE_HOST_BUILD: options.hostBuild,
820
+ IMPEL_NATIVE_BENCHMARK: "1",
821
+ },
822
+ };
823
+ }
824
+
825
+ function attemptTelemetryWindow(attempt, index) {
826
+ const startedAtMs = attempt?.processResult?.startedAtMs ?? Date.parse(attempt?.startedAt || "");
827
+ const endedAtMs = attempt?.processResult?.endedAtMs ?? Date.parse(attempt?.endedAt || "");
828
+ if (!Number.isFinite(startedAtMs) || !Number.isFinite(endedAtMs) || endedAtMs < startedAtMs) {
829
+ throw new Error(`attempt ${index + 1} has an invalid telemetry window`);
830
+ }
831
+ return { index, startedAtMs, endedAtMs };
832
+ }
833
+
834
+ function eventTimestampMs(event) {
835
+ const value = Date.parse(event?.timestamp || "");
836
+ return Number.isFinite(value) ? value : null;
837
+ }
838
+
839
+ function windowOwner(windows, timestampMs) {
840
+ if (timestampMs === null) return null;
841
+ const candidates = windows.filter(({ startedAtMs, endedAtMs }) =>
842
+ timestampMs >= startedAtMs && timestampMs <= endedAtMs
843
+ );
844
+ if (candidates.length === 0) return null;
845
+ // Concurrent attempts can overlap. Prefer the attempt whose process start is
846
+ // closest to the event, then use input order as a stable tie breaker.
847
+ return candidates.sort((left, right) =>
848
+ (timestampMs - left.startedAtMs) - (timestampMs - right.startedAtMs)
849
+ || left.index - right.index
850
+ )[0].index;
851
+ }
852
+
853
+ /**
854
+ * Attribute a shared cohort telemetry stream without duplicating events.
855
+ * A correlation's first timestamp anchors the whole correlation to one
856
+ * attempt; records without a correlation ID fall back to attempt windows.
857
+ */
858
+ export function splitCohortTelemetryEvents(attempts, telemetryText) {
859
+ const windows = attempts.map(attemptTelemetryWindow);
860
+ const split = attempts.map(() => []);
861
+ const events = telemetryText.trim()
862
+ ? parseStrictJsonLines(telemetryText, "native-agent cohort telemetry")
863
+ : [];
864
+ const correlationOwner = new Map();
865
+ for (const event of events) {
866
+ if (typeof event.correlationId !== "string" || !event.correlationId) continue;
867
+ if (!correlationOwner.has(event.correlationId)) {
868
+ correlationOwner.set(
869
+ event.correlationId,
870
+ windowOwner(windows, eventTimestampMs(event)),
871
+ );
872
+ } else if (correlationOwner.get(event.correlationId) === null) {
873
+ const owner = windowOwner(windows, eventTimestampMs(event));
874
+ if (owner !== null) correlationOwner.set(event.correlationId, owner);
875
+ }
876
+ }
877
+ for (const event of events) {
878
+ const owner = typeof event.correlationId === "string" && event.correlationId
879
+ ? correlationOwner.get(event.correlationId) ?? null
880
+ : windowOwner(windows, eventTimestampMs(event));
881
+ if (owner !== null) split[owner].push(event);
882
+ }
883
+ return split;
884
+ }
885
+
886
+ export function finalizeProfileAttempts(attempts, telemetryText) {
887
+ const telemetryByAttempt = splitCohortTelemetryEvents(attempts, telemetryText);
888
+ return attempts.map((attempt, attemptIndex) => {
889
+ if (attempt?.profileAttempt !== true) return attempt;
890
+ const attributedTelemetryText = telemetryByAttempt[attemptIndex]
891
+ .map((event) => JSON.stringify(event))
892
+ .join("\n");
893
+ let summary = null;
894
+ let parseError = null;
895
+ try {
896
+ summary = summarizeRawAttempt({
897
+ stdoutText: attempt.stdoutText,
898
+ telemetryText: attributedTelemetryText,
899
+ rolloutTexts: attempt.rolloutTexts,
900
+ });
901
+ } catch (error) {
902
+ parseError = error;
903
+ }
904
+ const record = safeAttemptRecord({
905
+ options: attempt.options,
906
+ index: attempt.index,
907
+ processResult: attempt.processResult,
908
+ summary,
909
+ jsonValid: parseError === null,
910
+ parseError,
911
+ });
912
+ privateWrite(path.join(attempt.attemptDir, "record.json"), `${JSON.stringify(record, null, 2)}\n`);
913
+ return record;
914
+ });
915
+ }
916
+
442
917
  async function profileAttempt(options, sessionDir, index) {
918
+ const environment = options.environment || process.env;
443
919
  await assertExpectedTenant({
444
920
  expectedTenant: options.expectedTenant,
445
921
  impelBinary: options.impelBinary,
446
- environment: process.env,
922
+ environment,
447
923
  });
448
924
  const attemptName = `${options.cohort}-${String(index + 1 + options.attemptOffset).padStart(3, "0")}`;
449
925
  const attemptDir = path.join(sessionDir, attemptName);
450
926
  privateDirectory(attemptDir);
451
927
  const stdoutPath = path.join(attemptDir, "stdout.jsonl");
452
928
  const stderrPath = path.join(attemptDir, "stderr.log");
453
- const telemetryPath = path.join(attemptDir, "telemetry.jsonl");
454
- const codexArgs = [
455
- "codex",
456
- ...(options.mode === "direct" ? ["--agent", options.agent] : []),
457
- "exec",
458
- "--json",
459
- ...options.extraArgs,
460
- "-",
461
- ];
462
- const invocation = impelInvocation(options.impelBinary, codexArgs, process.env);
929
+ const attemptOptions = profiledCodexAttemptOptions(
930
+ options,
931
+ options.telemetryPath,
932
+ environment,
933
+ );
934
+ const { codexArgs } = attemptOptions;
935
+ const invocation = impelInvocation(options.impelBinary, codexArgs, attemptOptions.environment);
463
936
  const processResult = await runProfiledProcess({
464
937
  ...invocation,
465
- environment: {
466
- ...process.env,
467
- IMPEL_NATIVE_AGENT_TELEMETRY_PATH: telemetryPath,
468
- IMPEL_NATIVE_HOST: options.mode === "direct" ? "codex-direct-profile" : "codex-compatible-agent",
469
- IMPEL_NATIVE_HOST_BUILD: options.hostBuild,
470
- },
938
+ environment: attemptOptions.environment,
471
939
  input: options.prompt,
472
940
  stdoutPath,
473
941
  stderrPath,
@@ -481,27 +949,15 @@ async function profileAttempt(options, sessionDir, index) {
481
949
  stdoutText,
482
950
  destination: path.join(attemptDir, "rollouts"),
483
951
  });
484
- let summary = null;
485
- let parseError = null;
486
- try {
487
- summary = summarizeRawAttempt({
488
- stdoutText,
489
- telemetryText: fs.existsSync(telemetryPath) ? fs.readFileSync(telemetryPath, "utf8") : "",
490
- rolloutTexts: rolloutPaths.map((rolloutPath) => fs.readFileSync(rolloutPath, "utf8")),
491
- });
492
- } catch (error) {
493
- parseError = error;
494
- }
495
- const record = safeAttemptRecord({
952
+ return {
953
+ profileAttempt: true,
496
954
  options,
497
955
  index,
956
+ attemptDir,
498
957
  processResult,
499
- summary,
500
- jsonValid: parseError === null,
501
- parseError,
502
- });
503
- privateWrite(path.join(attemptDir, "record.json"), `${JSON.stringify(record, null, 2)}\n`);
504
- return record;
958
+ stdoutText,
959
+ rolloutTexts: rolloutPaths.map((rolloutPath) => fs.readFileSync(rolloutPath, "utf8")),
960
+ };
505
961
  }
506
962
 
507
963
  function profilerFailureClass(error) {
@@ -514,16 +970,20 @@ function profilerFailureClass(error) {
514
970
  return "attempt-infrastructure";
515
971
  }
516
972
 
517
- export async function runWorkers(options, sessionDir, profileAttemptImpl = profileAttempt) {
973
+ export async function runWorkers(options, sessionDir, profileAttemptImpl = profileAttempt, {
974
+ startIndex = 0,
975
+ endIndex = options.attempts,
976
+ concurrency = options.concurrency,
977
+ } = {}) {
518
978
  const results = new Array(options.attempts);
519
- let next = 0;
979
+ let next = startIndex;
520
980
  let abort = null;
521
981
  const worker = async () => {
522
982
  for (;;) {
523
983
  if (abort) return;
524
984
  const index = next;
525
985
  next += 1;
526
- if (index >= options.attempts) return;
986
+ if (index >= endIndex) return;
527
987
  try {
528
988
  results[index] = await profileAttemptImpl(options, sessionDir, index);
529
989
  } catch (error) {
@@ -534,10 +994,98 @@ export async function runWorkers(options, sessionDir, profileAttemptImpl = profi
534
994
  }
535
995
  }
536
996
  };
537
- await Promise.all(Array.from({ length: options.concurrency }, () => worker()));
997
+ const workerCount = Math.min(concurrency, Math.max(0, endIndex - startIndex));
998
+ await Promise.all(Array.from({ length: workerCount }, () => worker()));
538
999
  return { attempts: results.filter(Boolean), abort };
539
1000
  }
540
1001
 
1002
+ const MISSING_MANAGED_AGENT_MESSAGE =
1003
+ "the isolated profile did not expose the managed agent tool; the cohort would measure model prose, not agent latency";
1004
+
1005
+ export function firstAttemptIntegrityAbort(record) {
1006
+ const answerCalls = record?.toolCounts?.[NATIVE_AGENT_ANSWER_TOOL] || 0;
1007
+ const terminalResults = record?.terminalResults || 0;
1008
+ if (answerCalls > 0 && terminalResults > 0) return null;
1009
+ return {
1010
+ failureClass: "managed-agent-integrity",
1011
+ attemptId: record?.attemptId || null,
1012
+ message: `${MISSING_MANAGED_AGENT_MESSAGE} (first attempt: ${answerCalls} ${NATIVE_AGENT_ANSWER_TOOL} call${answerCalls === 1 ? "" : "s"}, ${terminalResults} terminal result${terminalResults === 1 ? "" : "s"}); aborting remaining attempts`,
1013
+ };
1014
+ }
1015
+
1016
+ function readTelemetryText(telemetryPath) {
1017
+ return fs.existsSync(telemetryPath) ? fs.readFileSync(telemetryPath, "utf8") : "";
1018
+ }
1019
+
1020
+ /**
1021
+ * The first attempt is deliberately run alone. Until its rollout proves that
1022
+ * the fixed answer tool reached a terminal result, starting concurrent work
1023
+ * would risk collecting a whole cohort of plausible-looking model prose.
1024
+ */
1025
+ export async function runGuardedCohort(options, sessionDir, {
1026
+ profileAttemptImpl = profileAttempt,
1027
+ readTelemetry = readTelemetryText,
1028
+ } = {}) {
1029
+ const first = await runWorkers(options, sessionDir, profileAttemptImpl, {
1030
+ startIndex: 0,
1031
+ endIndex: 1,
1032
+ concurrency: 1,
1033
+ });
1034
+ const firstRecords = finalizeProfileAttempts(
1035
+ first.attempts,
1036
+ readTelemetry(options.telemetryPath),
1037
+ );
1038
+ if (first.abort) return { attempts: firstRecords, abort: first.abort };
1039
+ const integrityAbort = firstAttemptIntegrityAbort(firstRecords[0]);
1040
+ if (integrityAbort) return { attempts: firstRecords, abort: integrityAbort };
1041
+ if (options.attempts === 1) return { attempts: firstRecords, abort: null };
1042
+
1043
+ const remaining = await runWorkers(options, sessionDir, profileAttemptImpl, {
1044
+ startIndex: 1,
1045
+ endIndex: options.attempts,
1046
+ concurrency: options.concurrency,
1047
+ });
1048
+ const remainingRecords = finalizeProfileAttempts(
1049
+ remaining.attempts,
1050
+ readTelemetry(options.telemetryPath),
1051
+ );
1052
+ return {
1053
+ attempts: [...firstRecords, ...remainingRecords],
1054
+ abort: remaining.abort,
1055
+ };
1056
+ }
1057
+
1058
+ export function buildProfileAggregate({ sessionId, generatedAt, options, result }) {
1059
+ const telemetryCaptured = result.attempts.some(
1060
+ (attempt) => (attempt.telemetryEventCount || 0) > 0,
1061
+ );
1062
+ return {
1063
+ schema: PROFILE_SCHEMA,
1064
+ sessionId,
1065
+ generatedAt,
1066
+ tenantId: options.expectedTenant,
1067
+ sloClass: options.sloClass,
1068
+ mode: options.mode,
1069
+ cohort: options.cohort,
1070
+ cliVersion: options.hostBuild,
1071
+ promptSha256: options.promptSha256,
1072
+ complete: result.abort === null && result.attempts.length === options.attempts,
1073
+ telemetryCaptured,
1074
+ expectedAttempts: options.attempts,
1075
+ abort: result.abort,
1076
+ attempts: result.attempts,
1077
+ };
1078
+ }
1079
+
1080
+ export function telemetryCaptureWarning(aggregate) {
1081
+ const terminalResults = aggregate.attempts.reduce(
1082
+ (total, attempt) => total + (attempt.terminalResults || 0),
1083
+ 0,
1084
+ );
1085
+ if (!aggregate.complete || aggregate.telemetryCaptured || terminalResults === 0) return null;
1086
+ return "WARNING: the cohort completed with managed-agent terminal results but captured zero telemetry events; aggregate telemetryCaptured=false";
1087
+ }
1088
+
541
1089
  async function restoreTenant(originalTenant, options) {
542
1090
  let actual;
543
1091
  try { actual = await currentTenant(options.impelBinary, process.env); } catch { return false; }
@@ -572,8 +1120,6 @@ async function main(argv) {
572
1120
  throw new Error("could not establish the Impel CLI build under test");
573
1121
  }
574
1122
  options.hostBuild = version.stdout.trim();
575
- const configRoot = process.env.IMPEL_CONFIG_DIR || path.join(os.homedir(), ".config", "impel");
576
- options.rolloutRoot = path.join(configRoot, "cli", "tenants", options.expectedTenant, "codex", "sessions");
577
1123
  const outputRoot = path.resolve(options.outputDir);
578
1124
  privateDirectory(outputRoot);
579
1125
  const sessionId = `codex-${new Date().toISOString().replace(/[:.]/gu, "-")}-${crypto.randomBytes(4).toString("hex")}`;
@@ -581,28 +1127,29 @@ async function main(argv) {
581
1127
  privateDirectory(sessionDir);
582
1128
  let restored = false;
583
1129
  try {
584
- const result = await runWorkers(options, sessionDir);
585
- const aggregate = {
586
- schema: PROFILE_SCHEMA,
1130
+ const result = await withIsolatedBenchmarkProfile(options, sessionDir, async (isolation) => {
1131
+ options.environment = isolation.environment;
1132
+ options.telemetryPath = isolation.telemetryPath;
1133
+ options.rolloutRoot = path.join(isolation.codexHome, "sessions");
1134
+ return runGuardedCohort(options, sessionDir);
1135
+ });
1136
+ const aggregate = buildProfileAggregate({
587
1137
  sessionId,
588
1138
  generatedAt: new Date().toISOString(),
589
- tenantId: options.expectedTenant,
590
- sloClass: options.sloClass,
591
- mode: options.mode,
592
- cohort: options.cohort,
593
- cliVersion: options.hostBuild,
594
- promptSha256: options.promptSha256,
595
- complete: result.abort === null && result.attempts.length === options.attempts,
596
- expectedAttempts: options.attempts,
597
- abort: result.abort,
598
- attempts: result.attempts,
599
- };
1139
+ options,
1140
+ result,
1141
+ });
600
1142
  const aggregatePath = path.join(sessionDir, "aggregate.json");
601
1143
  privateWrite(aggregatePath, `${JSON.stringify(aggregate, null, 2)}\n`);
602
1144
  process.stderr.write(`Private Codex profile written under ${sessionDir}\n`);
1145
+ const telemetryWarning = telemetryCaptureWarning(aggregate);
1146
+ if (telemetryWarning) process.stderr.write(`${telemetryWarning}\n`);
603
1147
  process.stdout.write(`${JSON.stringify(aggregate)}\n`);
604
1148
  if (!aggregate.complete) {
605
- throw new Error(`cohort aborted (${aggregate.abort?.failureClass || "incomplete"}); partial aggregate retained`);
1149
+ const detail = aggregate.abort?.message ? `: ${aggregate.abort.message}` : "";
1150
+ throw new Error(
1151
+ `cohort aborted (${aggregate.abort?.failureClass || "incomplete"})${detail}; partial aggregate retained`,
1152
+ );
606
1153
  }
607
1154
  } finally {
608
1155
  restored = await restoreTenant(originalTenant, options);