@pome-sh/cli 0.43.1 → 0.44.0

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.
@@ -1,15 +1,17 @@
1
1
  #!/usr/bin/env node
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';
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-G3YRDMBE.js';
3
+ import '../../chunk-ZVKPZHFQ.js';
4
+ import '../../chunk-4LQ4IJOC.js';
4
5
  import '../../chunk-NW7HGA2K.js';
5
6
  import { GMAIL_CHECKS } from '../../chunk-JM6VS62R.js';
6
7
  import '../../chunk-PASFBRK4.js';
7
8
  import { LINEAR_CHECKS } from '../../chunk-TSOSDKXP.js';
8
9
  import '../../chunk-3FZY376K.js';
9
- import { createRecorder, bootTwin } from '../../chunk-64AWQJ7R.js';
10
- import { TWIN_NAME_LIST, TWIN_REGISTRY, createGitHubSmokeApp } from '../../chunk-4DXTT3RV.js';
10
+ import { createRecorder, bootTwin } from '../../chunk-3T4FUF43.js';
11
+ import { TWIN_NAME_LIST, TWIN_REGISTRY, createGitHubSmokeApp } from '../../chunk-RYAQ2ZYA.js';
11
12
  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 { readManifest, writeManifest, MANIFEST_JSON, exitCodeFor, readRequiredManifest, HostedUsageError, HostedOrchError, normalizeManifestTwins } from '../../chunk-26UAPLHK.js';
14
+ import { MOUNTED_TWINS, deriveAgentSlug } from '../../chunk-M7ATJ423.js';
13
15
  import { buildEgressAllowlist, readBlockedEgress } from '../../chunk-CBFKZZBR.js';
14
16
  import { TAPE_ASSERTABLE_TOOLS } from '../../chunk-C4BVTUA3.js';
15
17
  import { seedSchema } from '../../chunk-NBOQN5VX.js';
@@ -17,14 +19,14 @@ import { SLACK_CHECKS } from '../../chunk-2ZGVDTJC.js';
17
19
  import { oneOf, defineCheck, repoRef, VACUITY_SENTINEL_NUMBER, childStatePath, VACUITY_SENTINEL, statePath, templateSlots, renderCheck, checksDigest, checkPattern, checkNearMissPattern } from '../../chunk-JWJYNAWI.js';
18
20
  import '../../chunk-YBWG5JK2.js';
19
21
  import '../../chunk-TWURH7YM.js';
20
- import { eventSchema, isLegacyEventRow } from '../../chunk-5KFDRR53.js';
22
+ import { eventSchema, isLegacyEventRow } from '../../chunk-7VZBAHQ2.js';
21
23
  import { redactSecrets, redactEvent } from '../../chunk-SG6ZTIMT.js';
22
24
  import '../../chunk-2K6BJ3PI.js';
23
25
  import '../../chunk-FBSA5L36.js';
24
26
  import { Command } from 'commander';
25
27
  import { existsSync, readFileSync, realpathSync, statSync, constants } from 'node:fs';
26
28
  import { mkdir, readFile, writeFile, readdir, copyFile, stat, cp } from 'node:fs/promises';
27
- import { dirname, resolve, join, basename, relative, sep, extname } from 'node:path';
29
+ import { dirname, resolve, join, basename, relative, extname } from 'node:path';
28
30
  import { fileURLToPath } from 'node:url';
29
31
  import { serve } from '@hono/node-server';
30
32
  import { randomBytes, randomUUID, createHash } from 'node:crypto';
@@ -322,78 +324,6 @@ function makeShutdown(child, graceMs) {
322
324
  return done;
323
325
  };
324
326
  }
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
327
 
398
328
  // src/runner/runTaskCore.ts
399
329
  async function writeRunNoScore(input) {
@@ -428,9 +358,6 @@ async function runTask(options) {
428
358
  const writeRun = writeRunNoScore;
429
359
  const runDir = join(artifactsDir, scenario.slug, runId);
430
360
  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
361
  const eventsJsonlPath = join(runDir, "events.jsonl");
435
362
  await writeFile(eventsJsonlPath, "");
436
363
  const egressAllowHosts = buildEgressAllowlist(process.env, {
@@ -525,7 +452,6 @@ async function runTask(options) {
525
452
  POME_AUTH_TOKEN: token,
526
453
  POME_RUN_ID: runId,
527
454
  POME_ARTIFACTS_DIR: runDir,
528
- POME_ADAPTER_SIGNALS_PATH: signalsPathForEnv,
529
455
  ...options.extraAgentEnv ?? {},
530
456
  ...proxyEnv
531
457
  };
@@ -575,7 +501,6 @@ async function runTask(options) {
575
501
  stateInitial,
576
502
  stateFinal: stateFinal2
577
503
  });
578
- await mergeAdapterSignalsIntoEvents(signalsPath, eventsJsonlPath);
579
504
  void exitCode2;
580
505
  const blockedEgress2 = await collectBlockedEgress();
581
506
  return { scenario, runId, artifacts: artifacts2, agent: preflight, exitCode: 3, blockedEgress: blockedEgress2 };
@@ -601,7 +526,6 @@ async function runTask(options) {
601
526
  stateInitial,
602
527
  stateFinal
603
528
  });
604
- await mergeAdapterSignalsIntoEvents(signalsPath, eventsJsonlPath);
605
529
  const blockedEgress = await collectBlockedEgress();
606
530
  return { scenario, runId, artifacts, agent, exitCode, blockedEgress };
607
531
  } finally {
@@ -1187,7 +1111,7 @@ function extractJsonPayload(text) {
1187
1111
 
1188
1112
  // src/task/seed-verifier.ts
1189
1113
  async function verifySeedWithTwin(seed) {
1190
- const { GitHubDomain, openGitHubCloneDatabase } = await import('../../src-G6CMFUR6.js');
1114
+ const { GitHubDomain, openGitHubCloneDatabase } = await import('../../src-252X4AEZ.js');
1191
1115
  const db = openGitHubCloneDatabase(":memory:");
1192
1116
  try {
1193
1117
  new GitHubDomain(db).seed(seed);
@@ -4093,13 +4017,13 @@ function validateJsonl(name, raw) {
4093
4017
  `pome eval: ${name} is corrupt \u2014 line ${i + 1} is not valid JSON.`
4094
4018
  );
4095
4019
  }
4096
- if (name === "events.jsonl" && isLegacyEventRow(parsed)) {
4020
+ if (isLegacyEventRow(parsed)) {
4097
4021
  throw new HostedUsageError(
4098
4022
  `pome eval: events.jsonl line ${i + 1} has no "kind" \u2014 it was recorded before the unified event shape, and the control plane refuses it. Re-run the task to record the trace again.`
4099
4023
  );
4100
4024
  }
4101
4025
  }
4102
- if (name === "events.jsonl" && nonEmpty === 0) {
4026
+ if (nonEmpty === 0) {
4103
4027
  throw new HostedUsageError(
4104
4028
  "pome eval: events.jsonl is empty \u2014 the run captured no trace to evaluate."
4105
4029
  );
@@ -4120,24 +4044,12 @@ async function readRunDirArtifacts(runDir) {
4120
4044
  parseJsonFile("state_initial.json", stateInitialJson);
4121
4045
  const stateFinalJson = await readRequiredFile(runDir, "state_final.json");
4122
4046
  parseJsonFile("state_final.json", stateFinalJson);
4123
- let signalsJsonl = null;
4124
- try {
4125
- signalsJsonl = await readFile(join(runDir, "signals.jsonl"), "utf8");
4126
- } catch (err) {
4127
- if (err.code !== "ENOENT") {
4128
- throw new HostedUsageError(
4129
- `pome eval: signals.jsonl could not be read: ${err instanceof Error ? err.message : String(err)}`
4130
- );
4131
- }
4132
- }
4133
- if (signalsJsonl !== null) validateJsonl("signals.jsonl", signalsJsonl);
4134
4047
  return {
4135
4048
  runDir,
4136
4049
  meta,
4137
4050
  eventsJsonl,
4138
4051
  stateInitialJson,
4139
4052
  stateFinalJson,
4140
- signalsJsonl,
4141
4053
  metaJson: metaRaw
4142
4054
  };
4143
4055
  }
@@ -4239,7 +4151,6 @@ async function runEval(options) {
4239
4151
  stateFinalJson: JSON.stringify(
4240
4152
  redactSecrets(JSON.parse(artifacts.stateFinalJson))
4241
4153
  ),
4242
- signalsJsonl: redactJsonl(artifacts.signalsJsonl ?? ""),
4243
4154
  // D18.1 — already validated as parseable JSON in readRunDirArtifacts.
4244
4155
  // Re-serialize with the SAME formatting writeRunArtifactsCore's writeJson
4245
4156
  // uses (2-space indent + trailing newline) so the bytes `pome eval`
@@ -4284,8 +4195,7 @@ async function runEval(options) {
4284
4195
  expectedBehavior: "",
4285
4196
  traceStorageKey: keys.eventsKey ?? void 0,
4286
4197
  stateInitialStorageKey: keys.stateInitialKey ?? void 0,
4287
- stateFinalStorageKey: keys.stateFinalKey ?? void 0,
4288
- signalsStorageKey: keys.signalsKey ?? void 0
4198
+ stateFinalStorageKey: keys.stateFinalKey ?? void 0
4289
4199
  });
4290
4200
  }
4291
4201
  let finalized;
@@ -4961,7 +4871,7 @@ function firstSentence(description) {
4961
4871
  function resolveExampleRef(env = process.env) {
4962
4872
  const override = env.POME_EXAMPLE_REF?.trim();
4963
4873
  if (override) return override;
4964
- const baked = "aa6e8ff0d76f2bfbdd8c01e72239431644cb849a".trim() ;
4874
+ const baked = "a80259dcddd5ec6f1a16dba3a6f252539996ebb7".trim() ;
4965
4875
  return FULL_SHA.test(baked) ? baked : "main";
4966
4876
  }
4967
4877
  function rawUrlFor(example, file, ref) {
@@ -5324,7 +5234,7 @@ var DEFAULT_AGENT_COMMAND = `node ${DEFAULT_AGENT_FILE}`;
5324
5234
  var MANIFEST_SCHEMA_URL = "https://pome.sh/schemas/v1/pome.json";
5325
5235
  var MAX_UNREADABLE_PATHS_SHOWN = 5;
5326
5236
  function readPackageVersion() {
5327
- if ("0.43.1".length > 0) return "0.43.1";
5237
+ if ("0.44.0".length > 0) return "0.44.0";
5328
5238
  try {
5329
5239
  const here = dirname(fileURLToPath(import.meta.url));
5330
5240
  const candidates = [
@@ -5728,7 +5638,7 @@ function createProgram() {
5728
5638
  return;
5729
5639
  }
5730
5640
  {
5731
- const { runDoctorChecks } = await import('../../checks-V442KL5O.js');
5641
+ const { runDoctorChecks } = await import('../../checks-BOOQNOGJ.js');
5732
5642
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
5733
5643
  const doctorReport = await runDoctorChecks({ mode: useLocal ? "full" : "hosted" });
5734
5644
  if (!doctorReport.ok) {
@@ -5766,7 +5676,7 @@ function createProgram() {
5766
5676
  taskForRuns.config.runs
5767
5677
  );
5768
5678
  if (k > 1) {
5769
- const { runTrialGroup } = await import('../../runTrialGroup-HYGGBLMM.js');
5679
+ const { runTrialGroup } = await import('../../runTrialGroup-I3PC2AST.js');
5770
5680
  const fileForRerun = relative(process.cwd(), file);
5771
5681
  const rerunCommand = defaultTask ? options.trials !== void 0 ? `pome run -n ${k}` : "pome run" : `pome run ${fileForRerun && !fileForRerun.startsWith("..") ? fileForRerun : file} -n ${k}`;
5772
5682
  const groupResult = await runTrialGroup({
@@ -5848,7 +5758,7 @@ function createProgram() {
5848
5758
  program.command("doctor").summary("Check the agent and twin wiring").description(
5849
5759
  "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."
5850
5760
  ).action(async () => {
5851
- const { runDoctorChecks } = await import('../../checks-V442KL5O.js');
5761
+ const { runDoctorChecks } = await import('../../checks-BOOQNOGJ.js');
5852
5762
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
5853
5763
  const report = await runDoctorChecks();
5854
5764
  for (const line of renderDoctorReport(report, { passNote: true })) console.error(line);
@@ -5999,64 +5909,85 @@ function createProgram() {
5999
5909
  })
6000
5910
  );
6001
5911
  });
6002
- const twin = program.command("twin").summary("Run a twin on this machine").description("Start a twin on this machine, print its status or a starter seed file");
5912
+ const twin = program.command("twin").summary("Run a twin on this machine").description(
5913
+ "Start a twin on this machine, print its status, show its tape, or write a starter seed file"
5914
+ );
6003
5915
  twin.command("start").argument(
6004
- "[name]",
6005
- `Twin name (${TWIN_NAME_LIST.join(" | ")}). Optional when --seed names exactly one twin.`
5916
+ "[names...]",
5917
+ `Twin names (${TWIN_NAME_LIST.join(" | ")}). One, or several to boot together (each on its own port). Optional when --seed names exactly one twin.`
6006
5918
  ).option(
6007
5919
  "--port <port>",
6008
5920
  // Built from the registry rather than restated: the per-twin overrides
6009
5921
  // are the registry's to add, and this text went stale when linear's did.
6010
5922
  `Port to bind (default: $PORT, else ${TWIN_NAME_LIST.filter(
6011
5923
  (twin2) => TWIN_REGISTRY[twin2].portEnvName
6012
- ).map((twin2) => `${TWIN_REGISTRY[twin2].portEnvName}/${TWIN_REGISTRY[twin2].defaultPort} for ${twin2}`).join(", ")}, otherwise 3333)`
5924
+ ).map((twin2) => `${TWIN_REGISTRY[twin2].portEnvName}/${TWIN_REGISTRY[twin2].defaultPort} for ${twin2}`).join(", ")}, otherwise 3333). With several twins: the first twin's port; the rest take the next free ports above it. Without it, each twin takes its default port, else the next free one.`
6013
5925
  ).option(
6014
5926
  "--seed <path>",
6015
- "Boot this twin from a JSON or YAML seed file instead of its default. A seed REPLACES the default; it does not merge. Takes the per-twin envelope { <twin>: { \u2026 } } or one twin's flat seed. Overrides POME_SEED_JSON."
5927
+ "Boot from a JSON or YAML seed file instead of the default. A seed REPLACES the default; it does not merge. Takes the per-twin envelope { <twin>: { \u2026 } } or one twin's flat seed (several twins need the envelope, one entry per named twin). Overrides POME_SEED_JSON."
6016
5928
  ).description(
6017
- "Start a standalone twin as a long-lived foreground server (Ctrl-C to stop)"
6018
- ).action(async (name, options) => {
6019
- const { runTwinStartCommand } = await import('../../twinStart-3Q74IURZ.js');
6020
- await runTwinStartCommand(name, options);
5929
+ "Start one or more standalone twins as a long-lived foreground server (Ctrl-C to stop)"
5930
+ ).action(async (names, options) => {
5931
+ const { runTwinStartCommand } = await import('../../twinStart-E5R26SF4.js');
5932
+ await runTwinStartCommand(names, options);
6021
5933
  });
6022
5934
  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(
6023
5935
  "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"
6024
5936
  ).action(async (names, options) => {
6025
- const { runTwinSeedCommand } = await import('../../twinSeed-J7UAY3GM.js');
5937
+ const { runTwinSeedCommand } = await import('../../twinSeed-ADWQ62CA.js');
6026
5938
  await runTwinSeedCommand(names, options);
6027
5939
  });
6028
- twin.command("status").summary("Say whether the local twin is running").description(
6029
- "Say whether the twin `pome twin start` last booted here is still running, and print its paste-able env lines"
5940
+ twin.command("status").summary("Say whether the local twins are running").description(
5941
+ "Say whether each twin `pome twin start` booted here is still running, and print its paste-able env lines"
6030
5942
  ).action(async () => {
6031
5943
  const statusPath = ".pome/twin-status.json";
6032
5944
  if (!existsSync(statusPath)) {
6033
5945
  console.log("No standalone twin status found.");
6034
5946
  return;
6035
5947
  }
6036
- let status;
6037
- let origin;
5948
+ const { standaloneStatusEntries } = await import('../../twinStart-E5R26SF4.js');
5949
+ let entries;
6038
5950
  try {
6039
- status = JSON.parse(await readFile(statusPath, "utf8"));
6040
- if (typeof status.name !== "string" || status.name === "") throw new Error("no name");
6041
- origin = new URL(status.rest_url).origin;
5951
+ entries = standaloneStatusEntries(JSON.parse(await readFile(statusPath, "utf8"))).map(
5952
+ (status) => ({ ...status, origin: new URL(status.rest_url).origin })
5953
+ );
5954
+ if (entries.length === 0 || entries.some((status) => status.name === "")) {
5955
+ throw new Error("no twins");
5956
+ }
6042
5957
  } catch {
6043
5958
  throw new Error(
6044
5959
  `pome twin status: ${statusPath} is unreadable \u2014 start a twin with \`pome twin start <${TWIN_NAME_LIST.join("|")}>\`.`
6045
5960
  );
6046
5961
  }
6047
- const running = await fetch(`${origin}/healthz`, {
6048
- signal: AbortSignal.timeout(1e3)
6049
- }).then(
6050
- async (res) => res.ok && (await res.json().catch(() => ({}))).twin === status.name,
6051
- () => false
6052
- );
6053
- console.log(
6054
- running ? `${status.name} twin \u2014 running` : `${status.name} twin \u2014 not running (stale ${statusPath})`
6055
- );
6056
- const envName = TWIN_REGISTRY[status.name]?.envName ?? status.name.toUpperCase();
6057
- console.log(`POME_${envName}_REST_URL=${status.rest_url}`);
6058
- console.log(`POME_${envName}_MCP_URL=${status.mcp_url}`);
6059
- console.log(`POME_AUTH_TOKEN=${status.auth_token}`);
5962
+ for (const [index, status] of entries.entries()) {
5963
+ const running = await fetch(`${status.origin}/healthz`, {
5964
+ signal: AbortSignal.timeout(1e3)
5965
+ }).then(
5966
+ async (res) => res.ok && (await res.json().catch(() => ({}))).twin === status.name,
5967
+ () => false
5968
+ );
5969
+ if (index > 0) console.log("");
5970
+ console.log(
5971
+ running ? `${status.name} twin \u2014 running` : `${status.name} twin \u2014 not running (stale ${statusPath})`
5972
+ );
5973
+ const envName = TWIN_REGISTRY[status.name]?.envName ?? status.name.toUpperCase();
5974
+ console.log(`POME_${envName}_REST_URL=${status.rest_url}`);
5975
+ console.log(`POME_${envName}_MCP_URL=${status.mcp_url}`);
5976
+ console.log(`POME_AUTH_TOKEN=${status.auth_token}`);
5977
+ }
5978
+ });
5979
+ twin.command("tape").argument(
5980
+ "[name]",
5981
+ `Twin name (${TWIN_NAME_LIST.join(" | ")}). Optional when one twin is recorded in .pome/twin-status.json.`
5982
+ ).option(
5983
+ "--diff",
5984
+ "Also print the state diff since the twin booted \u2014 its seed, default or --seed \u2014 per collection: added, changed, removed.",
5985
+ false
5986
+ ).option("--json", "Print the tape (and the diff, with --diff) as one JSON envelope.", false).summary("Show what the agent did on a local twin").description(
5987
+ "Print the running twin's tape: one line per request with status, fidelity and whether state changed, so a call that claimed success but landed nothing stands out. Reads the twin's address and token from .pome/twin-status.json; no account, no hosted call."
5988
+ ).action(async (name, options) => {
5989
+ const { runTwinTapeCommand } = await import('../../twinTape-3XNU3GRW.js');
5990
+ await runTwinTapeCommand(name, options);
6060
5991
  });
6061
5992
  program.command("capture-server").summary("Record the agent's model calls").description(
6062
5993
  "Boot an HTTP CONNECT-tunnel proxy that appends one LlmCallEvent per tunnel to events.jsonl. Spawned by `pome run`; agent traffic flows via HTTPS_PROXY."
@@ -3,7 +3,7 @@ import { defaultSeedState, parseSeed } from './chunk-NBOQN5VX.js';
3
3
  export { defaultSeedState, parseSeed, seedSchema } from './chunk-NBOQN5VX.js';
4
4
  import { routeInputDeclarer, integerInput, mountDeclaredRoute, UndeclaredInputError, MalformedBodyError } from './chunk-IZFM7W2V.js';
5
5
  import { loadMcpToolFixture, defineTwin, twinBuildInfo, deriveMcpToolTable, UnknownToolError, openTwinDatabase, createApp, typeDisagreements } from './chunk-TWURH7YM.js';
6
- import './chunk-5KFDRR53.js';
6
+ import './chunk-7VZBAHQ2.js';
7
7
  import './chunk-SG6ZTIMT.js';
8
8
  import './chunk-FBSA5L36.js';
9
9
  import { z, ZodError } from 'zod';
@@ -4,7 +4,7 @@ export { DEFAULT_GMAIL_AGENT_EMAIL, GmailError, SEARCH_MAILBOX_MESSAGE_BUDGET, a
4
4
  import './chunk-JWJYNAWI.js';
5
5
  import { routeInputDeclarer, integerInput, booleanInput, repeatedInput, mountDeclaredRoute, UndeclaredInputError, MalformedBodyError } from './chunk-IZFM7W2V.js';
6
6
  import { loadMcpToolFixture, deriveMcpToolTable, defineTwin, openTwinDatabase, createApp } from './chunk-TWURH7YM.js';
7
- import './chunk-5KFDRR53.js';
7
+ import './chunk-7VZBAHQ2.js';
8
8
  import './chunk-SG6ZTIMT.js';
9
9
  import './chunk-FBSA5L36.js';
10
10
  import { createHash, createHmac, timingSafeEqual, randomBytes } from 'node:crypto';
@@ -4,7 +4,7 @@ export { DEFAULT_LINEAR_CLOCK, DEFAULT_LINEAR_EMAIL, DEFAULT_LINEAR_PORT, DEFAUL
4
4
  import './chunk-JWJYNAWI.js';
5
5
  import { routeInputDeclarer, mountDeclaredRoute, UndeclaredInputError } from './chunk-IZFM7W2V.js';
6
6
  import { loadMcpToolFixture, deriveMcpToolTable, openTwinDatabase, defineTwin, createApp } from './chunk-TWURH7YM.js';
7
- import './chunk-5KFDRR53.js';
7
+ import './chunk-7VZBAHQ2.js';
8
8
  import './chunk-SG6ZTIMT.js';
9
9
  import './chunk-FBSA5L36.js';
10
10
  import { createHmac, timingSafeEqual, createHash, randomBytes } from 'node:crypto';
@@ -4,7 +4,7 @@ import { defaultSeedState, parseSeed } from './chunk-YBWG5JK2.js';
4
4
  export { defaultSeedState, loadSeedFromEnv, parseSeed, seedSchema } from './chunk-YBWG5JK2.js';
5
5
  import { routeInputDeclarer, booleanInput, integerInput, mountDeclaredRoute, UndeclaredInputError } from './chunk-IZFM7W2V.js';
6
6
  import { loadMcpToolFixture, defineTwin, queryTokenResolver, formTokenResolver, deriveMcpToolTable, UnknownToolError, openTwinDatabase, createApp, typeDisagreements } from './chunk-TWURH7YM.js';
7
- import './chunk-5KFDRR53.js';
7
+ import './chunk-7VZBAHQ2.js';
8
8
  import './chunk-SG6ZTIMT.js';
9
9
  import './chunk-FBSA5L36.js';
10
10
  import { z, ZodError } from 'zod';
@@ -1,6 +1,6 @@
1
1
  import { routeInputDeclarer, bracketedQuery, integerInput, booleanInput, mountDeclaredRoute, UndeclaredInputError } from './chunk-IZFM7W2V.js';
2
2
  import { loadMcpToolFixture, openTwinDatabase, defineTwin, twinBuildInfo, deriveMcpToolTable, failureInjectionMiddleware, createApp, recordedRequestHeaders, UnknownToolError } from './chunk-TWURH7YM.js';
3
- import './chunk-5KFDRR53.js';
3
+ import './chunk-7VZBAHQ2.js';
4
4
  import './chunk-SG6ZTIMT.js';
5
5
  import { defaultSeed, seedSchema } from './chunk-2K6BJ3PI.js';
6
6
  export { DEFAULT_API_KEY, DEFAULT_SID, defaultSeed, loadSeedFromEnv, parseSeed, seedSchema } from './chunk-2K6BJ3PI.js';
@@ -0,0 +1,6 @@
1
+ export { UnsupportedTwinError, bootTwin } from './chunk-3T4FUF43.js';
2
+ export { STRIPE_LOCAL_ACCOUNT_ID } from './chunk-RYAQ2ZYA.js';
3
+ import './chunk-TWURH7YM.js';
4
+ import './chunk-7VZBAHQ2.js';
5
+ import './chunk-SG6ZTIMT.js';
6
+ import './chunk-FBSA5L36.js';
@@ -1,4 +1,4 @@
1
- import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-4DXTT3RV.js';
1
+ import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-RYAQ2ZYA.js';
2
2
  import { writeFile } from 'node:fs/promises';
3
3
 
4
4
  async function generateSeedFile(twins) {