@pome-sh/cli 0.42.4 → 0.43.1

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.
Files changed (30) hide show
  1. package/README.md +238 -117
  2. package/dist/build-info.json +3 -3
  3. package/dist/{checks-BKMTBJSO.js → checks-V442KL5O.js} +9 -14
  4. package/dist/{chunk-RPPF2KDQ.js → chunk-4DXTT3RV.js} +7 -7
  5. package/dist/{chunk-6KJC4BTO.js → chunk-5KFDRR53.js} +2 -2
  6. package/dist/{chunk-5NPGY73F.js → chunk-64AWQJ7R.js} +2 -2
  7. package/dist/{chunk-STMGQ7GU.js → chunk-A6AM6KS4.js} +1405 -172
  8. package/dist/{chunk-NNXVR46L.js → chunk-CS7O2ZXB.js} +114 -2
  9. package/dist/{chunk-VPXIGCZW.js → chunk-GQSNU3YP.js} +1 -1
  10. package/dist/{chunk-HRAD7MRX.js → chunk-TWURH7YM.js} +34 -10
  11. package/dist/{runTrialGroup-BP446HIE.js → runTrialGroup-HYGGBLMM.js} +20 -10
  12. package/dist/{server-GDK4TBTL.js → server-2WHSHTUD.js} +2 -2
  13. package/dist/src/cli/main.js +488 -226
  14. package/dist/{src-Z4C4SSDR.js → src-DBOHIQNB.js} +2 -2
  15. package/dist/{src-FUPOFZI4.js → src-FRPUTB2H.js} +2 -2
  16. package/dist/{src-UY4Y75BD.js → src-G6CMFUR6.js} +2 -2
  17. package/dist/{src-SNSK5ENY.js → src-SJDGRXC5.js} +2 -2
  18. package/dist/{src-V3RUKDMQ.js → src-VBXONWR3.js} +2 -2
  19. package/dist/twinHarness-33MAVAXV.js +6 -0
  20. package/dist/{twinSeed-X6VHBOLM.js → twinSeed-J7UAY3GM.js} +1 -1
  21. package/dist/{twinStart-QQU6OIO4.js → twinStart-3Q74IURZ.js} +21 -17
  22. package/package.json +1 -2
  23. package/dist/agent-Q2UTRJYL.js +0 -408
  24. package/dist/chunk-46POYRLY.js +0 -1240
  25. package/dist/chunk-DFOQGAKS.js +0 -116
  26. package/dist/chunk-JNXZBK3O.js +0 -17
  27. package/dist/chunk-WERG4AUH.js +0 -462
  28. package/dist/chunk-ZX4WNSZ5.js +0 -71
  29. package/dist/runDemo-DRDMCG25.js +0 -408
  30. package/dist/twinHarness-ATYQTDA5.js +0 -6
@@ -1,36 +1,35 @@
1
1
  #!/usr/bin/env node
2
- import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, SESSION_TWIN_NAMES, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, runTaskHosted, discoverRunSet, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, resolveCachedAgentId, readLinkCache, postAgentResolver, writeLinkCache, ensurePomeGitignored } from '../../chunk-46POYRLY.js';
3
- import { assetPath, runTask, resolvePackageRoot, DEMO_TASK_NAME, demoTaskPath } from '../../chunk-WERG4AUH.js';
4
- import { parseTaskFile, scoreStatus, runScoreLine, narratorReadingLines, readLatestRun, readMetaSummary, outcomeOf, readConfigTwins, scoreCountsSummary, criterionRowLine, readCodeCriteria, createHostedClient, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-STMGQ7GU.js';
5
- import '../../chunk-VPXIGCZW.js';
2
+ import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, SESSION_TWIN_NAMES, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, parseTaskFile, runTaskHosted, scoreStatus, runScoreLine, narratorReadingLines, readLatestRun, readMetaSummary, discoverRunSet, outcomeOf, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, readConfigTwins, resolveCachedAgentId, readLinkCache, seedStateForTwin, runAgentCommand, scoreCountsSummary, criterionRowLine, readCodeCriteria, postAgentResolver, writeLinkCache, ensurePomeGitignored, writeRunArtifactsCore, createHostedClient, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-A6AM6KS4.js';
3
+ import '../../chunk-GQSNU3YP.js';
6
4
  import '../../chunk-NW7HGA2K.js';
7
5
  import { GMAIL_CHECKS } from '../../chunk-JM6VS62R.js';
8
6
  import '../../chunk-PASFBRK4.js';
9
7
  import { LINEAR_CHECKS } from '../../chunk-TSOSDKXP.js';
10
8
  import '../../chunk-3FZY376K.js';
11
- import '../../chunk-5NPGY73F.js';
12
- import { TWIN_NAME_LIST, TWIN_REGISTRY, createGitHubSmokeApp } from '../../chunk-RPPF2KDQ.js';
13
- import { readManifest, writeManifest, MANIFEST_JSON, readRequiredManifest, normalizeManifestTwins } from '../../chunk-DFOQGAKS.js';
14
- import '../../chunk-XDU6TD4O.js';
15
- import { MOUNTED_TWINS, deriveAgentSlug, exitCodeFor, HostedUsageError, HostedOrchError } from '../../chunk-NNXVR46L.js';
16
- import '../../chunk-CBFKZZBR.js';
9
+ import { createRecorder, bootTwin } from '../../chunk-64AWQJ7R.js';
10
+ import { TWIN_NAME_LIST, TWIN_REGISTRY, createGitHubSmokeApp } from '../../chunk-4DXTT3RV.js';
11
+ import { getAvailablePort } from '../../chunk-XDU6TD4O.js';
12
+ import { MOUNTED_TWINS, readManifest, deriveAgentSlug, writeManifest, MANIFEST_JSON, exitCodeFor, readRequiredManifest, HostedUsageError, HostedOrchError, normalizeManifestTwins } from '../../chunk-CS7O2ZXB.js';
13
+ import { buildEgressAllowlist, readBlockedEgress } from '../../chunk-CBFKZZBR.js';
17
14
  import { TAPE_ASSERTABLE_TOOLS } from '../../chunk-C4BVTUA3.js';
18
15
  import { seedSchema } from '../../chunk-NBOQN5VX.js';
19
16
  import { SLACK_CHECKS } from '../../chunk-2ZGVDTJC.js';
20
17
  import { oneOf, defineCheck, repoRef, VACUITY_SENTINEL_NUMBER, childStatePath, VACUITY_SENTINEL, statePath, templateSlots, renderCheck, checksDigest, checkPattern, checkNearMissPattern } from '../../chunk-JWJYNAWI.js';
21
18
  import '../../chunk-YBWG5JK2.js';
22
- import '../../chunk-HRAD7MRX.js';
23
- import { eventSchema, isLegacyEventRow } from '../../chunk-6KJC4BTO.js';
19
+ import '../../chunk-TWURH7YM.js';
20
+ import { eventSchema, isLegacyEventRow } from '../../chunk-5KFDRR53.js';
24
21
  import { redactSecrets, redactEvent } from '../../chunk-SG6ZTIMT.js';
25
22
  import '../../chunk-2K6BJ3PI.js';
26
23
  import '../../chunk-FBSA5L36.js';
27
24
  import { Command } from 'commander';
28
25
  import { existsSync, readFileSync, realpathSync, statSync, constants } from 'node:fs';
29
26
  import { mkdir, readFile, writeFile, readdir, copyFile, stat, cp } from 'node:fs/promises';
30
- import { dirname, resolve, join, basename, relative, extname } from 'node:path';
27
+ import { dirname, resolve, join, basename, relative, sep, extname } from 'node:path';
31
28
  import { fileURLToPath } from 'node:url';
32
- import { execFile } from 'node:child_process';
33
- import { randomBytes, createHash } from 'node:crypto';
29
+ import { serve } from '@hono/node-server';
30
+ import { randomBytes, randomUUID, createHash } from 'node:crypto';
31
+ import { sign } from 'hono/jwt';
32
+ import { execFile, spawn } from 'node:child_process';
34
33
  import { createServer } from 'node:http';
35
34
  import { createInterface } from 'node:readline';
36
35
  import { z } from 'zod';
@@ -203,6 +202,419 @@ function renderLlmTurn(event2) {
203
202
  ` cache read/create=${cache}${finish}`
204
203
  ];
205
204
  }
205
+ var LISTENING_REGEX = /listening on 127\.0\.0\.1:(\d+)/;
206
+ async function spawnCaptureServerChild(options) {
207
+ const execPath = options.execPath ?? process.execPath;
208
+ const binArgs = options.binArgs ?? defaultBinArgs(options.eventsOut, options.allowHosts, options.egressOut);
209
+ const readyTimeoutMs = options.readyTimeoutMs ?? 5e3;
210
+ const shutdownGraceMs = options.shutdownGraceMs ?? 5e3;
211
+ const child = spawn(execPath, binArgs, {
212
+ stdio: ["ignore", "ignore", "pipe"],
213
+ env: process.env
214
+ });
215
+ let stderrBuf = "";
216
+ let resolved = false;
217
+ const readyPromise = new Promise((resolve7, reject) => {
218
+ const onData = (chunk) => {
219
+ stderrBuf += chunk.toString("utf8");
220
+ if (stderrBuf.length > 8192) stderrBuf = stderrBuf.slice(-8192);
221
+ const match = LISTENING_REGEX.exec(stderrBuf);
222
+ if (match) {
223
+ resolved = true;
224
+ cleanup();
225
+ resolve7(Number(match[1]));
226
+ }
227
+ };
228
+ const onExit = (code, signal) => {
229
+ if (resolved) return;
230
+ cleanup();
231
+ const detail = stderrBuf.trim().slice(0, 2048);
232
+ reject(
233
+ new Error(
234
+ `pome capture-server exited (code=${code} signal=${signal}) before printing the listening line.${detail ? `
235
+ stderr: ${detail}` : ""}`
236
+ )
237
+ );
238
+ };
239
+ const timer = setTimeout(() => {
240
+ if (resolved) return;
241
+ cleanup();
242
+ reject(
243
+ new Error(
244
+ `pome capture-server did not start listening within ${readyTimeoutMs}ms.${stderrBuf ? `
245
+ stderr: ${stderrBuf.trim().slice(0, 2048)}` : ""}`
246
+ )
247
+ );
248
+ }, readyTimeoutMs);
249
+ const cleanup = () => {
250
+ clearTimeout(timer);
251
+ child.stderr?.off("data", onData);
252
+ child.off("exit", onExit);
253
+ };
254
+ child.stderr?.on("data", onData);
255
+ child.once("exit", onExit);
256
+ });
257
+ let port;
258
+ try {
259
+ port = await readyPromise;
260
+ } catch (err) {
261
+ if (!child.killed) child.kill("SIGKILL");
262
+ throw err;
263
+ }
264
+ child.stderr?.on("data", () => {
265
+ });
266
+ const pid = child.pid;
267
+ if (pid === void 0) {
268
+ child.kill("SIGKILL");
269
+ throw new Error("pome capture-server child has no pid after boot");
270
+ }
271
+ return {
272
+ port,
273
+ pid,
274
+ shutdown: makeShutdown(child, shutdownGraceMs)
275
+ };
276
+ }
277
+ function defaultBinArgs(eventsOut, allowHosts, egressOut) {
278
+ const script = process.argv[1];
279
+ if (typeof script !== "string" || script.length === 0) {
280
+ throw new Error(
281
+ "Cannot determine pome binary path (process.argv[1] is empty). Pass `binArgs` explicitly."
282
+ );
283
+ }
284
+ return [script, "capture-server", "--port", "0", "--events-out", eventsOut, ...egressArgs(allowHosts, egressOut)];
285
+ }
286
+ function egressArgs(allowHosts, egressOut) {
287
+ const args = [];
288
+ if (allowHosts && allowHosts.length > 0) args.push("--allow", allowHosts.join(","));
289
+ if (egressOut) args.push("--egress-out", egressOut);
290
+ return args;
291
+ }
292
+ function makeShutdown(child, graceMs) {
293
+ let done = null;
294
+ return () => {
295
+ if (done) return done;
296
+ done = new Promise((resolve7) => {
297
+ if (child.exitCode !== null || child.signalCode !== null) {
298
+ resolve7();
299
+ return;
300
+ }
301
+ const onExit = () => {
302
+ clearTimeout(killTimer);
303
+ resolve7();
304
+ };
305
+ child.once("exit", onExit);
306
+ try {
307
+ child.kill("SIGTERM");
308
+ } catch {
309
+ child.off("exit", onExit);
310
+ resolve7();
311
+ return;
312
+ }
313
+ const killTimer = setTimeout(() => {
314
+ if (child.exitCode === null && child.signalCode === null) {
315
+ try {
316
+ child.kill("SIGKILL");
317
+ } catch {
318
+ }
319
+ }
320
+ }, graceMs);
321
+ });
322
+ return done;
323
+ };
324
+ }
325
+ function resolveTwinHttpParents(rows) {
326
+ const eventIdByToolUseId = /* @__PURE__ */ new Map();
327
+ for (const row of rows) {
328
+ if (row.kind === "ToolUseEvent") eventIdByToolUseId.set(row.tool_use_id, row.event_id);
329
+ }
330
+ if (eventIdByToolUseId.size === 0) return rows;
331
+ return rows.map((row) => {
332
+ if (row.kind !== "TwinHttpEvent") return row;
333
+ if (row.parent_event_id != null) return row;
334
+ const causingToolUseId = row.tool_call_id ?? row.correlation_id ?? null;
335
+ if (causingToolUseId === null) return row;
336
+ const parentEventId = eventIdByToolUseId.get(causingToolUseId);
337
+ return parentEventId === void 0 ? row : { ...row, parent_event_id: parentEventId };
338
+ });
339
+ }
340
+ async function mergeAdapterSignalsIntoEvents(signalsPath, eventsJsonlPath) {
341
+ let rawSignals;
342
+ try {
343
+ rawSignals = await readFile(signalsPath, "utf8");
344
+ } catch {
345
+ return { appended: 0, dropped: 0 };
346
+ }
347
+ let dropped = 0;
348
+ const signalRows = [];
349
+ for (const line of rawSignals.split("\n")) {
350
+ if (line.length === 0) continue;
351
+ let parsed;
352
+ try {
353
+ parsed = JSON.parse(line);
354
+ } catch {
355
+ dropped += 1;
356
+ continue;
357
+ }
358
+ const result = eventSchema.safeParse(parsed);
359
+ if (!result.success) {
360
+ dropped += 1;
361
+ continue;
362
+ }
363
+ signalRows.push(redactEvent(result.data));
364
+ }
365
+ if (signalRows.length === 0) return { appended: 0, dropped };
366
+ let rawEvents;
367
+ try {
368
+ rawEvents = await readFile(eventsJsonlPath, "utf8");
369
+ } catch {
370
+ rawEvents = "";
371
+ }
372
+ const eventRows = [];
373
+ const unparseablePassthrough = [];
374
+ for (const line of rawEvents.split("\n")) {
375
+ if (line.length === 0) continue;
376
+ let parsed;
377
+ try {
378
+ parsed = JSON.parse(line);
379
+ } catch {
380
+ unparseablePassthrough.push(line);
381
+ continue;
382
+ }
383
+ const result = eventSchema.safeParse(parsed);
384
+ if (result.success) {
385
+ eventRows.push(redactEvent(result.data));
386
+ } else {
387
+ unparseablePassthrough.push(line);
388
+ }
389
+ }
390
+ const merged = resolveTwinHttpParents(eventRows.concat(signalRows));
391
+ merged.sort((a, b) => a.ts < b.ts ? -1 : a.ts > b.ts ? 1 : 0);
392
+ const sortedJsonl = merged.map((r) => JSON.stringify(r)).join("\n");
393
+ const head = unparseablePassthrough.length > 0 ? unparseablePassthrough.join("\n") + "\n" : "";
394
+ await writeFile(eventsJsonlPath, head + sortedJsonl + "\n");
395
+ return { appended: signalRows.length, dropped };
396
+ }
397
+
398
+ // src/runner/runTaskCore.ts
399
+ async function writeRunNoScore(input) {
400
+ const artifacts = await writeRunArtifactsCore({
401
+ artifactsDir: input.artifactsDir,
402
+ runId: input.runId,
403
+ scenario: input.scenario,
404
+ startedAt: input.startedAt,
405
+ completedAt: input.completedAt,
406
+ stdout: input.agentStdout,
407
+ stderr: input.agentStderr,
408
+ exitCode: input.agentExitCode,
409
+ events: input.events,
410
+ stateInitial: input.stateInitial,
411
+ stateFinal: input.stateFinal
412
+ });
413
+ const exitCode = input.agentExitCode !== 0 || input.agentTimedOut ? 3 : 0;
414
+ return { artifacts, exitCode };
415
+ }
416
+
417
+ // src/runner/runTask.ts
418
+ function closeServer(server) {
419
+ return new Promise((resolvePromise, reject) => {
420
+ server.close((err) => err ? reject(err) : resolvePromise());
421
+ });
422
+ }
423
+ async function runTask(options) {
424
+ const scenario = await parseTaskFile(options.taskPath);
425
+ const runId = `run_${randomUUID()}`;
426
+ const artifactsDir = options.artifactsDir ?? "runs";
427
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
428
+ const writeRun = writeRunNoScore;
429
+ const runDir = join(artifactsDir, scenario.slug, runId);
430
+ await mkdir(runDir, { recursive: true });
431
+ const signalsPath = join(runDir, "signals.jsonl");
432
+ await writeFile(signalsPath, "");
433
+ const signalsPathForEnv = sep === "\\" ? signalsPath.replace(/\\/g, "/") : signalsPath;
434
+ const eventsJsonlPath = join(runDir, "events.jsonl");
435
+ await writeFile(eventsJsonlPath, "");
436
+ const egressAllowHosts = buildEgressAllowlist(process.env, {
437
+ extraHosts: options.egressExtraHosts
438
+ });
439
+ const egressJsonlPath = join(runDir, "egress.jsonl");
440
+ const captureServer = options.noCapture ? null : await spawnCaptureServerChild({
441
+ eventsOut: resolve(eventsJsonlPath),
442
+ allowHosts: egressAllowHosts,
443
+ egressOut: resolve(egressJsonlPath),
444
+ execPath: options.captureServerCommand?.execPath,
445
+ binArgs: options.captureServerCommand ? [
446
+ ...options.captureServerCommand.prefixArgs,
447
+ "capture-server",
448
+ "--port",
449
+ "0",
450
+ "--events-out",
451
+ resolve(eventsJsonlPath),
452
+ ...egressArgs(egressAllowHosts, resolve(egressJsonlPath))
453
+ ] : void 0
454
+ });
455
+ if (captureServer) options.onCaptureServerSpawned?.(captureServer.pid);
456
+ const collectBlockedEgress = async () => {
457
+ if (!captureServer) return [];
458
+ await captureServer.shutdown();
459
+ return readBlockedEgress(egressJsonlPath);
460
+ };
461
+ const twins = scenario.config.twins.length ? scenario.config.twins : ["github"];
462
+ const primaryTwin2 = twins[0];
463
+ const isMultiTwin = twins.length > 1;
464
+ const sid = runId;
465
+ const authSecret = process.env.TWIN_AUTH_SECRET ?? randomBytes(32).toString("hex");
466
+ process.env.TWIN_AUTH_SECRET = authSecret;
467
+ const recorder = createRecorder({ eventsPath: eventsJsonlPath });
468
+ const booted = [];
469
+ const twinEnv = {};
470
+ const tokenEnvNames = /* @__PURE__ */ new Set();
471
+ const stateInitialByTwin = {};
472
+ let mergedClaims = {};
473
+ for (const twin of twins) {
474
+ const port = await getAvailablePort();
475
+ const baseUrl = `http://127.0.0.1:${port}`;
476
+ const harness = await bootTwin({
477
+ twin,
478
+ seedState: seedStateForTwin(scenario, twin),
479
+ runId,
480
+ twinBaseUrl: baseUrl,
481
+ recorder
482
+ });
483
+ stateInitialByTwin[twin] = await harness.exportState();
484
+ const sessionBase = `${baseUrl}/s/${sid}`;
485
+ twinEnv[`POME_${harness.envName}_REST_URL`] = sessionBase;
486
+ twinEnv[`POME_${harness.envName}_MCP_URL`] = `${sessionBase}/mcp`;
487
+ if (harness.tokenEnvName) tokenEnvNames.add(harness.tokenEnvName);
488
+ mergedClaims = { ...mergedClaims, ...harness.extraClaims ?? {} };
489
+ const server = serve({ fetch: harness.app.fetch, port, hostname: "127.0.0.1" });
490
+ booted.push({ twin, harness, server });
491
+ }
492
+ const stateInitial = stateInitialByTwin[primaryTwin2];
493
+ const token = await sign(
494
+ {
495
+ sid,
496
+ team_id: "tm_local",
497
+ // The self-host agent acts as `pome-agent`, the collaborator the twin
498
+ // seeds onto every repo. Without a login claim the REST merge gate
499
+ // (which checks the authenticated user has push access) rejects merges —
500
+ // the MCP merge path calls the domain directly and never hit this, so it
501
+ // was invisible until a scripted REST agent needed to merge.
502
+ login: "pome-agent",
503
+ // Twin-supplied claims (e.g. Stripe's `account_id`, so the token resolves
504
+ // to the account the seed data lives in) — merged across all twins.
505
+ // github/slack supply none.
506
+ ...mergedClaims,
507
+ exp: Math.floor(Date.now() / 1e3) + Math.max(scenario.config.timeout * 2, 600)
508
+ },
509
+ authSecret
510
+ );
511
+ const proxyEnv = captureServer ? {
512
+ // Agent's outbound traffic flows through the capture-server.
513
+ // Twin traffic is localhost, NO_PROXY excludes it so it stays a
514
+ // TwinHttpEvent (recorded in-process) and isn't double-counted as a
515
+ // proxy-captured LlmCallEvent.
516
+ HTTP_PROXY: `http://127.0.0.1:${captureServer.port}`,
517
+ HTTPS_PROXY: `http://127.0.0.1:${captureServer.port}`,
518
+ NO_PROXY: "127.0.0.1,localhost"
519
+ } : {};
520
+ for (const name of tokenEnvNames) twinEnv[name] = token;
521
+ const env = {
522
+ POME_TASK: scenario.prompt,
523
+ POME_TWIN_NAMES: twins.join(","),
524
+ ...twinEnv,
525
+ POME_AUTH_TOKEN: token,
526
+ POME_RUN_ID: runId,
527
+ POME_ARTIFACTS_DIR: runDir,
528
+ POME_ADAPTER_SIGNALS_PATH: signalsPathForEnv,
529
+ ...options.extraAgentEnv ?? {},
530
+ ...proxyEnv
531
+ };
532
+ const captureFinalStates = async () => {
533
+ const finals = {};
534
+ for (const { twin, harness } of booted) {
535
+ finals[twin] = await harness.exportState();
536
+ }
537
+ if (isMultiTwin) {
538
+ for (const { twin } of booted) {
539
+ if (twin === primaryTwin2) continue;
540
+ try {
541
+ await writeFile(
542
+ join(runDir, `state_final.${twin}.json`),
543
+ `${JSON.stringify(redactSecrets(finals[twin]), null, 2)}
544
+ `
545
+ );
546
+ } catch {
547
+ }
548
+ }
549
+ }
550
+ return finals[primaryTwin2];
551
+ };
552
+ try {
553
+ const preflight = await runAgentCommand({
554
+ command: options.agentCommand,
555
+ env,
556
+ // Cold agent startup can exceed 10s on CI; cap preflight below full scenario
557
+ // timeout but leave enough headroom for toolchain startup.
558
+ timeoutSeconds: Math.min(60, scenario.config.timeout),
559
+ preflight: true
560
+ });
561
+ if (preflight.exitCode !== 0) {
562
+ await recorder.flush?.();
563
+ const stateFinal2 = await captureFinalStates();
564
+ const { artifacts: artifacts2, exitCode: exitCode2 } = await writeRun({
565
+ artifactsDir,
566
+ runId,
567
+ scenario,
568
+ startedAt,
569
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
570
+ agentStdout: preflight.stdout,
571
+ agentStderr: preflight.stderr,
572
+ agentExitCode: preflight.exitCode,
573
+ agentTimedOut: preflight.timedOut ?? false,
574
+ events: recorder.events(),
575
+ stateInitial,
576
+ stateFinal: stateFinal2
577
+ });
578
+ await mergeAdapterSignalsIntoEvents(signalsPath, eventsJsonlPath);
579
+ void exitCode2;
580
+ const blockedEgress2 = await collectBlockedEgress();
581
+ return { scenario, runId, artifacts: artifacts2, agent: preflight, exitCode: 3, blockedEgress: blockedEgress2 };
582
+ }
583
+ const agent = await runAgentCommand({
584
+ command: options.agentCommand,
585
+ env,
586
+ timeoutSeconds: scenario.config.timeout
587
+ });
588
+ await recorder.flush?.();
589
+ const stateFinal = await captureFinalStates();
590
+ const { artifacts, exitCode } = await writeRun({
591
+ artifactsDir,
592
+ runId,
593
+ scenario,
594
+ startedAt,
595
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
596
+ agentStdout: agent.stdout,
597
+ agentStderr: agent.stderr,
598
+ agentExitCode: agent.exitCode,
599
+ agentTimedOut: agent.timedOut ?? false,
600
+ events: recorder.events(),
601
+ stateInitial,
602
+ stateFinal
603
+ });
604
+ await mergeAdapterSignalsIntoEvents(signalsPath, eventsJsonlPath);
605
+ const blockedEgress = await collectBlockedEgress();
606
+ return { scenario, runId, artifacts, agent, exitCode, blockedEgress };
607
+ } finally {
608
+ if (captureServer) await captureServer.shutdown();
609
+ await Promise.all(
610
+ booted.map(async ({ server, harness }) => {
611
+ await closeServer(server);
612
+ await harness.close();
613
+ })
614
+ );
615
+ await recorder.close?.();
616
+ }
617
+ }
206
618
 
207
619
  // src/runner/trialCount.ts
208
620
  var MAX_TRIALS = 20;
@@ -310,8 +722,8 @@ async function startCallbackServer(expectedState) {
310
722
  let rejectCode = null;
311
723
  let settled = false;
312
724
  let deliveredCode = false;
313
- const codePromise = new Promise((resolve6, reject) => {
314
- resolveCode = resolve6;
725
+ const codePromise = new Promise((resolve7, reject) => {
726
+ resolveCode = resolve7;
315
727
  rejectCode = reject;
316
728
  });
317
729
  const fail = (err) => {
@@ -335,7 +747,7 @@ async function startCallbackServer(expectedState) {
335
747
  res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
336
748
  res.end("<h1>Pome login failed</h1><p>You can close this tab.</p>");
337
749
  fail(new Error(`Browser reported error: ${error}`));
338
- void closeServer(server);
750
+ void closeServer2(server);
339
751
  return;
340
752
  }
341
753
  if (!code || state !== expectedState) {
@@ -353,11 +765,11 @@ async function startCallbackServer(expectedState) {
353
765
  res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
354
766
  res.end("<h1>Pome login complete</h1><p>You can close this tab.</p>");
355
767
  succeed(code);
356
- void closeServer(server);
768
+ void closeServer2(server);
357
769
  });
358
- await new Promise((resolve6, reject) => {
770
+ await new Promise((resolve7, reject) => {
359
771
  server?.once("error", reject);
360
- server?.listen(0, "127.0.0.1", resolve6);
772
+ server?.listen(0, "127.0.0.1", resolve7);
361
773
  });
362
774
  const address = server.address();
363
775
  if (!address || typeof address === "string") {
@@ -369,12 +781,12 @@ async function startCallbackServer(expectedState) {
369
781
  "Timed out waiting for browser login (5 min). Run `pome login` again."
370
782
  )
371
783
  );
372
- void closeServer(server);
784
+ void closeServer2(server);
373
785
  }, 5 * 60 * 1e3);
374
786
  timeout.unref();
375
787
  const onInt = () => {
376
788
  fail(new Error("Login cancelled (Ctrl+C). No credentials were changed."));
377
- void closeServer(server);
789
+ void closeServer2(server);
378
790
  };
379
791
  process.once("SIGINT", onInt);
380
792
  codePromise.finally(() => {
@@ -389,26 +801,26 @@ async function startCallbackServer(expectedState) {
389
801
  async close() {
390
802
  clearTimeout(timeout);
391
803
  process.off("SIGINT", onInt);
392
- await closeServer(server);
804
+ await closeServer2(server);
393
805
  }
394
806
  };
395
807
  }
396
- function closeServer(server) {
397
- return new Promise((resolve6) => {
398
- server?.close(() => resolve6());
808
+ function closeServer2(server) {
809
+ return new Promise((resolve7) => {
810
+ server?.close(() => resolve7());
399
811
  });
400
812
  }
401
813
  async function openBrowser(url) {
402
814
  const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "powershell.exe" : "xdg-open";
403
815
  const args = process.platform === "win32" ? ["-NoProfile", "-Command", "Start-Process", url] : [url];
404
- await new Promise((resolve6) => {
816
+ await new Promise((resolve7) => {
405
817
  execFile(command, args, (error) => {
406
818
  if (error) {
407
819
  console.error(
408
820
  "Could not open a browser automatically \u2014 copy the URL above into a browser."
409
821
  );
410
822
  }
411
- resolve6();
823
+ resolve7();
412
824
  });
413
825
  });
414
826
  }
@@ -617,7 +1029,7 @@ function topicMatchesFilter(t, filter) {
617
1029
  return t.id.includes(f) || t.title.toLowerCase().includes(f) || t.keywords.some((k) => k.toLowerCase().includes(f)) || t.path.toLowerCase().includes(f);
618
1030
  }
619
1031
  async function promptLine(rl, q) {
620
- return await new Promise((resolve6) => rl.question(q, resolve6));
1032
+ return await new Promise((resolve7) => rl.question(q, resolve7));
621
1033
  }
622
1034
  function printTopicUrl(topic, site) {
623
1035
  console.log(`${site}${topic.path}`);
@@ -775,7 +1187,7 @@ function extractJsonPayload(text) {
775
1187
 
776
1188
  // src/task/seed-verifier.ts
777
1189
  async function verifySeedWithTwin(seed) {
778
- const { GitHubDomain, openGitHubCloneDatabase } = await import('../../src-UY4Y75BD.js');
1190
+ const { GitHubDomain, openGitHubCloneDatabase } = await import('../../src-G6CMFUR6.js');
779
1191
  const db = openGitHubCloneDatabase(":memory:");
780
1192
  try {
781
1193
  new GitHubDomain(db).seed(seed);
@@ -976,6 +1388,16 @@ function statusStamp(status) {
976
1388
  return "FAIL";
977
1389
  }
978
1390
  }
1391
+ function resolvePackageRoot(importMetaUrl) {
1392
+ let dir = dirname(fileURLToPath(importMetaUrl));
1393
+ for (let i = 0; i < 6; i++) {
1394
+ if (existsSync(join(dir, "package.json"))) return dir;
1395
+ const parent = resolve(dir, "..");
1396
+ if (parent === dir) break;
1397
+ dir = parent;
1398
+ }
1399
+ return void 0;
1400
+ }
979
1401
 
980
1402
  // src/cli/tasks-catalog.ts
981
1403
  var TASK_TWINS = [
@@ -2973,7 +3395,7 @@ function localDigest(twin) {
2973
3395
  }
2974
3396
  function bakedVersions() {
2975
3397
  try {
2976
- return JSON.parse('{"@pome-sh/sdk":"0.11.6","@pome-sh/wire":"0.4.0","@pome-sh/twin-github":"0.12.0","@pome-sh/twin-gmail":"0.4.0","@pome-sh/twin-linear":"0.4.1","@pome-sh/twin-slack":"0.4.1","@pome-sh/twin-stripe":"0.4.7"}');
3398
+ return JSON.parse('{"@pome-sh/sdk":"0.11.6","@pome-sh/wire":"0.4.2","@pome-sh/twin-github":"0.12.0","@pome-sh/twin-gmail":"0.4.0","@pome-sh/twin-linear":"0.4.1","@pome-sh/twin-slack":"0.4.1","@pome-sh/twin-stripe":"0.4.7"}');
2977
3399
  } catch {
2978
3400
  return {};
2979
3401
  }
@@ -3963,6 +4385,29 @@ async function runEvalCommand(runDirArg, opts) {
3963
4385
  process.exitCode = code;
3964
4386
  }
3965
4387
  }
4388
+ function assetPath(...segments) {
4389
+ const root = resolvePackageRoot(import.meta.url);
4390
+ if (!root) {
4391
+ throw new Error(
4392
+ `Could not locate the @pome-sh/cli package root (no enclosing package.json) while resolving the packaged asset ${segments.join("/")}.`
4393
+ );
4394
+ }
4395
+ const candidate = join(root, "assets", ...segments);
4396
+ if (!existsSync(candidate)) {
4397
+ throw new Error(
4398
+ `Packaged asset not found at ${candidate}. This is a packaging bug \u2014 \`assets/\` must be listed in cli/package.json \`files\`.`
4399
+ );
4400
+ }
4401
+ return candidate;
4402
+ }
4403
+
4404
+ // src/demo/task.ts
4405
+ var DEMO_TASK_NAME = "first-run-demo";
4406
+ function demoTaskPath() {
4407
+ return assetPath("demo", "first-run-demo.md");
4408
+ }
4409
+
4410
+ // src/cli/default-task.ts
3966
4411
  var DEFAULT_TASK_TRIALS = 5;
3967
4412
  var DEFAULT_TASK_DIR = "tasks";
3968
4413
  var DEFAULT_TASK_FILENAME = `${DEMO_TASK_NAME}.md`;
@@ -4217,126 +4662,6 @@ async function runRegisterAgent(opts) {
4217
4662
  function stripControlCharacters(value) {
4218
4663
  return value.replace(/[\u0000-\u001f\u007f]/g, "");
4219
4664
  }
4220
- var CLAUDE_SDK_AGENT_RELATIVE = "examples/agents/claude-sdk-agent.ts";
4221
- var CLAUDE_SDK_AGENT_SOURCE = `// SPDX-License-Identifier: Apache-2.0
4222
- //
4223
- // Scaffolded by \`pome init --sdk claude\`. Minimal Claude Agent SDK starter
4224
- // wired through @pome-sh/adapter-claude-sdk so \`pome run\` captures adapter
4225
- // signals. Swap the tool body for your own agent logic.
4226
-
4227
- import { createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
4228
- import { query, tool, withPome } from "@pome-sh/adapter-claude-sdk";
4229
- import { z } from "zod";
4230
-
4231
- withPome();
4232
-
4233
- const restUrl = process.env.POME_GITHUB_REST_URL;
4234
- const authToken = process.env.POME_AUTH_TOKEN;
4235
- const task =
4236
- process.env.POME_TASK?.trim() ||
4237
- "List open issues in acme/api and summarize their titles.";
4238
-
4239
- if (!restUrl) {
4240
- throw new Error(
4241
- "POME_GITHUB_REST_URL is required (injected by \`pome run\`, or set it when driving a twin yourself).",
4242
- );
4243
- }
4244
-
4245
- if (process.env.POME_PREFLIGHT === "1") {
4246
- const res = await fetch(\`\${restUrl.replace(/\\/+$/, "")}/rate_limit\`, {
4247
- headers: {
4248
- accept: "application/vnd.github+json",
4249
- ...(authToken ? { authorization: \`Bearer \${authToken}\` } : {}),
4250
- },
4251
- });
4252
- if (!res.ok) {
4253
- throw new Error(\`preflight failed: HTTP \${res.status}\`);
4254
- }
4255
- console.log("preflight ok");
4256
- process.exit(0);
4257
- }
4258
-
4259
- const listOpenIssues = tool(
4260
- "list_open_issues",
4261
- "List open issues on the GitHub twin for owner/repo.",
4262
- {
4263
- owner: z.string(),
4264
- repo: z.string(),
4265
- },
4266
- async ({ owner, repo }) => {
4267
- const res = await fetch(
4268
- \`\${restUrl.replace(/\\/+$/, "")}/repos/\${owner}/\${repo}/issues?state=open\`,
4269
- {
4270
- headers: {
4271
- accept: "application/vnd.github+json",
4272
- ...(authToken ? { authorization: \`Bearer \${authToken}\` } : {}),
4273
- },
4274
- },
4275
- );
4276
- const body = await res.text();
4277
- if (!res.ok) {
4278
- return {
4279
- content: [{ type: "text" as const, text: \`HTTP \${res.status}: \${body}\` }],
4280
- isError: true,
4281
- };
4282
- }
4283
- return { content: [{ type: "text" as const, text: body }] };
4284
- },
4285
- );
4286
-
4287
- const server = createSdkMcpServer({
4288
- name: "github-twin",
4289
- version: "0.1.0",
4290
- tools: [listOpenIssues],
4291
- });
4292
-
4293
- for await (const message of query({
4294
- prompt: task,
4295
- options: {
4296
- permissionMode: "bypassPermissions",
4297
- maxTurns: 10,
4298
- allowedTools: ["list_open_issues"],
4299
- mcpServers: {
4300
- "github-twin": {
4301
- type: "sdk",
4302
- name: "github-twin",
4303
- instance: server.instance,
4304
- },
4305
- },
4306
- },
4307
- })) {
4308
- if (message.type === "result" && message.subtype === "success" && message.result) {
4309
- console.log(message.result);
4310
- }
4311
- }
4312
- `;
4313
- async function writeSdkScaffold(sdk) {
4314
- switch (sdk) {
4315
- case "claude":
4316
- return writeClaudeSdkScaffold();
4317
- case "claude-managed":
4318
- throw new ClaudeManagedDeferredError();
4319
- }
4320
- }
4321
- async function writeClaudeSdkScaffold() {
4322
- const path = join(process.cwd(), CLAUDE_SDK_AGENT_RELATIVE);
4323
- await mkdir(dirname(path), { recursive: true });
4324
- await writeFile(path, CLAUDE_SDK_AGENT_SOURCE, "utf8");
4325
- return {
4326
- agentSdkValue: "claude-agent-sdk",
4327
- agentCommand: `npx tsx ${CLAUDE_SDK_AGENT_RELATIVE}`,
4328
- exampleAgentRelativePath: CLAUDE_SDK_AGENT_RELATIVE,
4329
- postInstallHint: "Next steps:\n 1. npm install @pome-sh/adapter-claude-sdk @anthropic-ai/claude-agent-sdk zod\n 2. pome login\n 3. pome register agent <name>\n 4. pome run tasks/01-bug-happy-path.md\n\nSee `pome docs getting-started` for a narrative walkthrough."
4330
- };
4331
- }
4332
- var ClaudeManagedDeferredError = class extends Error {
4333
- constructor() {
4334
- super(
4335
- "Claude Managed Agent is not yet supported \u2014 three blockers (no injection point inside Anthropic-hosted runtime, no sidechannel for adapter signals, Managed Agents API still moving). Follow the tracking issue for v2 timing. For now, use `pome init` (without --sdk) or `pome init --sdk claude`."
4336
- );
4337
- this.name = "ClaudeManagedDeferredError";
4338
- }
4339
- };
4340
4665
 
4341
4666
  // src/cli/example-catalog.ts
4342
4667
  var CATALOG_EXAMPLES = [
@@ -4636,7 +4961,7 @@ function firstSentence(description) {
4636
4961
  function resolveExampleRef(env = process.env) {
4637
4962
  const override = env.POME_EXAMPLE_REF?.trim();
4638
4963
  if (override) return override;
4639
- const baked = "8596587c815472aa76ee5c89ddf025c3ab7dd19a".trim() ;
4964
+ const baked = "aa6e8ff0d76f2bfbdd8c01e72239431644cb849a".trim() ;
4640
4965
  return FULL_SHA.test(baked) ? baked : "main";
4641
4966
  }
4642
4967
  function rawUrlFor(example, file, ref) {
@@ -4999,7 +5324,7 @@ var DEFAULT_AGENT_COMMAND = `node ${DEFAULT_AGENT_FILE}`;
4999
5324
  var MANIFEST_SCHEMA_URL = "https://pome.sh/schemas/v1/pome.json";
5000
5325
  var MAX_UNREADABLE_PATHS_SHOWN = 5;
5001
5326
  function readPackageVersion() {
5002
- if ("0.42.4".length > 0) return "0.42.4";
5327
+ if ("0.43.1".length > 0) return "0.43.1";
5003
5328
  try {
5004
5329
  const here = dirname(fileURLToPath(import.meta.url));
5005
5330
  const candidates = [
@@ -5028,13 +5353,10 @@ function createProgram() {
5028
5353
  process.env.POME_API_URL ?? DEFAULT_CONTROL_PLANE_URL
5029
5354
  ).option("--artifacts-dir <dir>", "Directory for run artifacts", "runs");
5030
5355
  program.name("pome").description(
5031
- "Test AI agents against digital twins of real SaaS APIs. Runs are recorded to app.pome.sh. Start with `pome demo`."
5356
+ "Test AI agents against digital twins of real SaaS APIs. Runs are recorded to app.pome.sh. Start with `pome init`."
5032
5357
  ).version(PACKAGE_VERSION).showHelpAfterError("(add --help for usage)");
5033
5358
  program.command("init").summary("Set up Pome in this project").description(
5034
5359
  "Create pome.json, plus starter files in a new project \u2014 or, with --example <id>, fetch a complete runnable example into ./<id>"
5035
- ).option(
5036
- "--sdk <name>",
5037
- "Scaffold for a specific agent SDK (claude | claude-managed). Adds the SDK-specific example file and pre-fills agent.framework so the dashboard badges runs correctly."
5038
5360
  ).option(
5039
5361
  "--bare",
5040
5362
  "Write only the manifest \u2014 skip the starter task library and sample agents. Auto-selected when the current directory already has a package.json (the bring-your-own-agent case)."
@@ -5045,10 +5367,9 @@ function createProgram() {
5045
5367
  "--example <id>",
5046
5368
  `Scaffold a complete bundled example into ./<id> instead of a starter project. Ids: ${exampleIds().join(", ")}.`
5047
5369
  ).action(async (opts) => {
5048
- const sdk = opts.sdk?.trim();
5049
5370
  const exampleId = opts.example?.trim();
5050
5371
  if (exampleId !== void 0) {
5051
- const conflicting = ["sdk", "bare", "starter"].filter(
5372
+ const conflicting = ["bare", "starter"].filter(
5052
5373
  (flag) => opts[flag] !== void 0 && opts[flag] !== false
5053
5374
  );
5054
5375
  if (conflicting.length > 0) {
@@ -5073,18 +5394,6 @@ function createProgram() {
5073
5394
  }
5074
5395
  return;
5075
5396
  }
5076
- if (sdk !== void 0 && sdk !== "claude" && sdk !== "claude-managed") {
5077
- console.error(
5078
- `Unknown --sdk value "${opts.sdk}". Supported: claude, claude-managed.`
5079
- );
5080
- process.exitCode = 2;
5081
- return;
5082
- }
5083
- if (sdk === "claude-managed") {
5084
- console.error(new ClaudeManagedDeferredError().message);
5085
- process.exitCode = 2;
5086
- return;
5087
- }
5088
5397
  if (opts.bare && opts.starter) {
5089
5398
  console.error("Pass at most one of --bare / --starter.");
5090
5399
  process.exitCode = 2;
@@ -5100,22 +5409,13 @@ function createProgram() {
5100
5409
  await mkdir("runs", { recursive: true });
5101
5410
  await copyStarterFiles();
5102
5411
  }
5103
- let command = bare ? void 0 : DEFAULT_AGENT_COMMAND;
5104
- let framework;
5105
- let postInitMessage = bare ? 'Pome initialized (existing project \u2014 starter library skipped).\nNext steps:\n 1. Set "command" in pome.json to your agent\'s launch command\n 2. pome login # one-time, opens the dashboard to sign in\n 3. pome register agent <name> # scopes runs to this project (writes agent.slug to pome.json)\n 4. pome run <your-task>.md\n\nOptional follow-ups:\n - pome tasks github --copy # drop the starter task library into tasks/\n - pome init --sdk claude # scaffold a Claude Agent SDK starter\n\nSee `pome docs getting-started` for a narrative walkthrough.' : "Pome initialized.\nNext steps:\n 1. pome login # one-time, opens the dashboard to sign in\n 2. pome register agent <name> # scopes runs to this project (writes agent.slug to pome.json)\n 3. pome run tasks/01-bug-happy-path.md\n\nOptional follow-ups:\n - pome init --sdk claude # scaffold a Claude Agent SDK starter\n - pome tasks stripe --copy # add Stripe payment tasks when needed\n\nSee `pome docs getting-started` for a narrative walkthrough.";
5106
- if (sdk) {
5107
- const scaffold = await writeSdkScaffold(sdk);
5108
- command = scaffold.agentCommand;
5109
- framework = scaffold.agentSdkValue;
5110
- postInitMessage = `Pome initialized with --sdk ${sdk}. Scaffolded ${scaffold.exampleAgentRelativePath}.
5111
- ` + scaffold.postInstallHint;
5112
- }
5412
+ const command = bare ? void 0 : DEFAULT_AGENT_COMMAND;
5413
+ const postInitMessage = bare ? 'Pome initialized (existing project \u2014 starter library skipped).\nNext steps:\n 1. Set "command" in pome.json to your agent\'s launch command\n 2. pome login # one-time, opens the dashboard to sign in\n 3. pome register agent <name> # scopes runs to this project (writes agent.slug to pome.json)\n 4. pome run <your-task>.md\n\nOptional follow-ups:\n - pome tasks github --copy # drop the starter task library into tasks/\n\nSee `pome docs getting-started` for a narrative walkthrough.' : "Pome initialized.\nNext steps:\n 1. pome login # one-time, opens the dashboard to sign in\n 2. pome register agent <name> # scopes runs to this project (writes agent.slug to pome.json)\n 3. pome run tasks/01-bug-happy-path.md\n\nOptional follow-ups:\n - pome tasks stripe --copy # add Stripe payment tasks when needed\n\nSee `pome docs getting-started` for a narrative walkthrough.";
5113
5414
  const tasksDir = !bare || await hasMarkdownTasks("tasks") ? "tasks" : void 0;
5114
5415
  const existing = await readManifest(process.cwd());
5115
5416
  if (!existing) {
5116
5417
  const slug = deriveAgentSlug(basename(process.cwd())) || "my-agent";
5117
5418
  const agent = { slug };
5118
- if (framework) agent.framework = framework;
5119
5419
  const manifest = {
5120
5420
  $schema: MANIFEST_SCHEMA_URL,
5121
5421
  agent
@@ -5125,15 +5425,6 @@ function createProgram() {
5125
5425
  manifest.artifacts_dir = "runs";
5126
5426
  manifest.pass_threshold = 100;
5127
5427
  await writeManifest(join(process.cwd(), MANIFEST_JSON), "json", manifest);
5128
- } else if (sdk) {
5129
- const priorAgent = typeof existing.raw.agent === "object" && existing.raw.agent !== null ? existing.raw.agent : {};
5130
- const nextAgent = { ...priorAgent };
5131
- if (framework) nextAgent.framework = framework;
5132
- await writeManifest(existing.path, existing.format, {
5133
- ...existing.raw,
5134
- agent: nextAgent,
5135
- command
5136
- });
5137
5428
  }
5138
5429
  console.error(postInitMessage);
5139
5430
  });
@@ -5437,7 +5728,7 @@ function createProgram() {
5437
5728
  return;
5438
5729
  }
5439
5730
  {
5440
- const { runDoctorChecks } = await import('../../checks-BKMTBJSO.js');
5731
+ const { runDoctorChecks } = await import('../../checks-V442KL5O.js');
5441
5732
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
5442
5733
  const doctorReport = await runDoctorChecks({ mode: useLocal ? "full" : "hosted" });
5443
5734
  if (!doctorReport.ok) {
@@ -5475,7 +5766,7 @@ function createProgram() {
5475
5766
  taskForRuns.config.runs
5476
5767
  );
5477
5768
  if (k > 1) {
5478
- const { runTrialGroup } = await import('../../runTrialGroup-BP446HIE.js');
5769
+ const { runTrialGroup } = await import('../../runTrialGroup-HYGGBLMM.js');
5479
5770
  const fileForRerun = relative(process.cwd(), file);
5480
5771
  const rerunCommand = defaultTask ? options.trials !== void 0 ? `pome run -n ${k}` : "pome run" : `pome run ${fileForRerun && !fileForRerun.startsWith("..") ? fileForRerun : file} -n ${k}`;
5481
5772
  const groupResult = await runTrialGroup({
@@ -5554,39 +5845,10 @@ function createProgram() {
5554
5845
  process.exitCode = worstExit;
5555
5846
  }
5556
5847
  );
5557
- program.command("demo").summary("Run a sample task, no account needed").description(
5558
- "Zero-auth first-run demo: boots a local GitHub twin, runs the bundled demo agent for 5 isolated trials (model calls via pome's anonymous demo gateway), and prints per-trial verdicts evaluated in Pome cloud. No signup, no API keys; ends with a no-login preview link."
5559
- ).option(
5560
- "--trials <n>",
5561
- "Number of trials to run, 1 to 10",
5562
- "5"
5563
- ).action(
5564
- async (opts, cmd) => {
5565
- const trials = Number.parseInt(opts.trials, 10);
5566
- if (!Number.isInteger(trials) || trials < 1 || trials > 10) {
5567
- console.error(`Invalid --trials "${opts.trials}" (expected 1-10).`);
5568
- process.exitCode = 5;
5569
- return;
5570
- }
5571
- const { runDemo } = await import('../../runDemo-DRDMCG25.js');
5572
- const result = await runDemo({
5573
- apiBase: globals(cmd).apiUrl.replace(/\/$/, ""),
5574
- dashboardBase: process.env.POME_DASHBOARD_URL ?? DEFAULT_DASHBOARD_URL,
5575
- trials,
5576
- artifactsDir: globals(cmd).artifactsDir
5577
- });
5578
- process.exitCode = result.exitCode;
5579
- }
5580
- );
5581
- program.command("demo-agent", { hidden: true }).description("Internal: the bundled demo agent process (spawned by `pome demo`).").action(async () => {
5582
- const { runDemoAgentCommand } = await import('../../agent-Q2UTRJYL.js');
5583
- const code = await runDemoAgentCommand();
5584
- if (code !== 0) process.exitCode = code;
5585
- });
5586
5848
  program.command("doctor").summary("Check the agent and twin wiring").description(
5587
5849
  "Check the agent\u2194twin wiring: pome.json (or pome.yaml) present + valid, the local twin boots + serves, requests routed to the twin (not a hardcoded production host), egress floor active. On failure prints one named cause (file:line where knowable) + one concrete fix and exits non-zero."
5588
5850
  ).action(async () => {
5589
- const { runDoctorChecks } = await import('../../checks-BKMTBJSO.js');
5851
+ const { runDoctorChecks } = await import('../../checks-V442KL5O.js');
5590
5852
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
5591
5853
  const report = await runDoctorChecks();
5592
5854
  for (const line of renderDoctorReport(report, { passNote: true })) console.error(line);
@@ -5754,13 +6016,13 @@ function createProgram() {
5754
6016
  ).description(
5755
6017
  "Start a standalone twin as a long-lived foreground server (Ctrl-C to stop)"
5756
6018
  ).action(async (name, options) => {
5757
- const { runTwinStartCommand } = await import('../../twinStart-QQU6OIO4.js');
6019
+ const { runTwinStartCommand } = await import('../../twinStart-3Q74IURZ.js');
5758
6020
  await runTwinStartCommand(name, options);
5759
6021
  });
5760
6022
  twin.command("new-seed").argument("<name...>", `Twin name (${TWIN_NAME_LIST.join(" | ")}). Repeat for one file covering several.`).option("--out <path>", "Write to this file instead of stdout. Refuses to overwrite.").summary("Print a new starter seed file for a twin").description(
5761
6023
  "Print a new starter seed file for a twin, generated from the twin's own starting state. One twin is flat, several are the per-twin envelope. Boot it with `twin start <twin> --seed`, seed a sandbox with `sandbox create --twin <twin> --seed`, or drop it beside a task as <task>.seed.json"
5762
6024
  ).action(async (names, options) => {
5763
- const { runTwinSeedCommand } = await import('../../twinSeed-X6VHBOLM.js');
6025
+ const { runTwinSeedCommand } = await import('../../twinSeed-J7UAY3GM.js');
5764
6026
  await runTwinSeedCommand(names, options);
5765
6027
  });
5766
6028
  twin.command("status").summary("Say whether the local twin is running").description(