@pome-sh/cli 0.28.0 → 0.29.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,6 +1,6 @@
1
1
  {
2
2
  "package": "pome-sh",
3
- "version": "0.28.0",
4
- "git_sha": "fe45f413881e8c19ab370dd63e03fbf118ac8edb",
5
- "build_time": "2026-08-26T19:10:23.010Z"
3
+ "version": "0.29.0",
4
+ "git_sha": "b065b0336a80c35d63c53bed262be6b037bfec76",
5
+ "build_time": "2026-08-26T21:23:55.631Z"
6
6
  }
@@ -1,6 +1,6 @@
1
- import { findManifestPath, readManifest } from './chunk-QOMNBXMQ.js';
1
+ import { findManifestPath, readManifest } from './chunk-VO2XUPZC.js';
2
2
  import { getAvailablePort } from './chunk-XDU6TD4O.js';
3
- import './chunk-D5PXUPG4.js';
3
+ import './chunk-E7WJ3SRP.js';
4
4
  import { buildEgressAllowlist } from './chunk-CBFKZZBR.js';
5
5
  import './chunk-6KJC4BTO.js';
6
6
  import './chunk-SG6ZTIMT.js';
@@ -183,7 +183,7 @@ async function checkTwinReachable(_configDir) {
183
183
  });
184
184
  let harness;
185
185
  try {
186
- const { bootTwin } = await import('./twinHarness-YOVJR72F.js');
186
+ const { bootTwin } = await import('./twinHarness-CUVRO5IV.js');
187
187
  harness = await bootTwin({
188
188
  twin: "github",
189
189
  seedState: void 0,
@@ -0,0 +1,105 @@
1
+ import { isTwinName, TWIN_REGISTRY, TWIN_NAMES } from './chunk-SRG22BIH.js';
2
+ import { readFileSync } from 'node:fs';
3
+ import { parse } from 'yaml';
4
+
5
+ function readSeedFileText(path, flag = "--seed") {
6
+ try {
7
+ return readFileSync(path, "utf8");
8
+ } catch (err) {
9
+ throw new Error(`${flag}: cannot read ${path}: ${err.message}`);
10
+ }
11
+ }
12
+ function parseSeedFileText(raw, origin) {
13
+ let parsed;
14
+ try {
15
+ parsed = parse(raw);
16
+ } catch (err) {
17
+ throw new Error(`${origin} is not valid JSON or YAML: ${err.message}`);
18
+ }
19
+ if (Array.isArray(parsed)) {
20
+ throw new Error(`${origin} is not a seed file: its top level is an array, not an object.`);
21
+ }
22
+ if (parsed === null || typeof parsed !== "object") {
23
+ throw new Error(
24
+ `${origin} is not a seed file: its top level is ${parsed === null ? "null" : typeof parsed}, not an object.`
25
+ );
26
+ }
27
+ const { _meta, ...rest } = parsed;
28
+ const keys = Object.keys(rest);
29
+ const twinKeys = keys.filter((key) => isTwinName(key));
30
+ if (twinKeys.length === 0) return { shape: "flat", seed: rest };
31
+ if (twinKeys.length !== keys.length) {
32
+ const others = keys.filter((key) => !isTwinName(key));
33
+ throw new Error(
34
+ `${origin} mixes twin ids (${twinKeys.join(", ")}) with other keys (${others.join(", ")}). A seed file is either one twin's flat seed or a per-twin envelope { <twin>: <seed> }, not both.`
35
+ );
36
+ }
37
+ return { shape: "envelope", byTwin: rest };
38
+ }
39
+ function twinsNamedBy(file) {
40
+ if (file.shape === "flat") return [];
41
+ return Object.keys(file.byTwin).filter((key) => isTwinName(key));
42
+ }
43
+ function soleTwinOf(file) {
44
+ const named = twinsNamedBy(file);
45
+ return named.length === 1 ? named[0] : void 0;
46
+ }
47
+ async function seedFieldsFor(twin) {
48
+ return TWIN_REGISTRY[twin].seedFields();
49
+ }
50
+ async function seedForTwin(file, twin, origin, opts = {}) {
51
+ if (file.shape === "flat") return parseWith(twin, file.seed, origin, file);
52
+ assertOnlyAsked(file, opts.asked, origin);
53
+ const named = twinsNamedBy(file);
54
+ if (!(twin in file.byTwin)) {
55
+ throw new Error(
56
+ `${origin} declares no ${twin} seed (it names ${named.join(", ")}). Add a "${twin}" key, or start the twin it names.`
57
+ );
58
+ }
59
+ return parseWith(twin, file.byTwin[twin], `${origin} ("${twin}")`, file);
60
+ }
61
+ async function seedsForTwins(file, twins, origin) {
62
+ if (file.shape === "flat") {
63
+ if (twins.length !== 1) {
64
+ throw new Error(
65
+ `${origin} is a flat seed and this sandbox has ${twins.length} twins (${twins.join(", ")}), so nothing says which one it is for. Wrap it in a per-twin envelope: { "${twins[0] ?? "<twin>"}": { \u2026 } }.`
66
+ );
67
+ }
68
+ return { [twins[0]]: await parseWith(twins[0], file.seed, origin, file) };
69
+ }
70
+ assertOnlyAsked(file, twins, origin);
71
+ const out = {};
72
+ for (const twin of twins) {
73
+ if (twin in file.byTwin) {
74
+ out[twin] = await parseWith(twin, file.byTwin[twin], `${origin} ("${twin}")`, file);
75
+ }
76
+ }
77
+ return out;
78
+ }
79
+ function assertOnlyAsked(file, asked, origin) {
80
+ if (asked === void 0 || file.shape !== "envelope") return;
81
+ const extras = twinsNamedBy(file).filter((twin) => !asked.includes(twin));
82
+ if (extras.length === 0) return;
83
+ throw new Error(
84
+ `${origin} names ${extras.join(", ")}, which this command was not asked for (asked: ${asked.length ? asked.join(", ") : "none"}). Add --twin for each, or remove them from the file.`
85
+ );
86
+ }
87
+ async function parseWith(twin, seed, where, file) {
88
+ try {
89
+ return await TWIN_REGISTRY[twin].parseSeed(seed);
90
+ } catch (err) {
91
+ const hint = file.shape === "flat" ? await notSeedFieldsHint(twin, file.seed) : "";
92
+ throw new Error(`${where} is not a seed this twin can boot: ${err.message}${hint}`);
93
+ }
94
+ }
95
+ async function notSeedFieldsHint(twin, seed) {
96
+ if (seed === null || typeof seed !== "object" || Array.isArray(seed)) return "";
97
+ const keys = Object.keys(seed);
98
+ if (keys.length === 0) return "";
99
+ const fields = new Set(await seedFieldsFor(twin));
100
+ if (keys.some((key) => fields.has(key))) return "";
101
+ return `
102
+ None of its top-level keys (${keys.join(", ")}) is a field of the ${twin} seed. If this file is a per-twin envelope, its keys must be twin ids: ${TWIN_NAMES.join(", ")}.`;
103
+ }
104
+
105
+ export { parseSeedFileText, readSeedFileText, seedForTwin, seedsForTwins, soleTwinOf, twinsNamedBy };
@@ -736,6 +736,9 @@ z.record(
736
736
  z.string(),
737
737
  z.record(z.string(), z.unknown())
738
738
  );
739
+ function isMultiTwinSeedEnvelope(twins) {
740
+ return twins.length > 1;
741
+ }
739
742
  var taskClassSchema = z.enum(["conformance", "restraint", "adversarial"]);
740
743
  var taskConfigSchema = z.object({
741
744
  twins: z.array(z.string()).default(["github"]),
@@ -1264,4 +1267,4 @@ function exitCodeFor(err) {
1264
1267
  return 2;
1265
1268
  }
1266
1269
 
1267
- export { HostedAuthError, HostedDiscardRefusedError, HostedOrchError, HostedQuotaError, HostedTrialError, HostedUsageError, MOUNTED_TWINS, SLUG_RE, agentResponseSchema, createEvalSessionResponseSchema, createSessionResponseSchema, criterionSchema, deriveAgentSlug, exitCodeFor, finalizeResponseSchema, manifestSchema, sessionPublicSchema, submitResultResponseSchema };
1270
+ export { HostedAuthError, HostedDiscardRefusedError, HostedOrchError, HostedQuotaError, HostedTrialError, HostedUsageError, MOUNTED_TWINS, SLUG_RE, agentResponseSchema, createEvalSessionResponseSchema, createSessionResponseSchema, criterionSchema, deriveAgentSlug, exitCodeFor, finalizeResponseSchema, isMultiTwinSeedEnvelope, manifestSchema, sessionPublicSchema, submitResultResponseSchema };
@@ -1,5 +1,5 @@
1
- import { parseTaskFile, seedStateForTwin, runAgentCommand, writeRunArtifactsCore } from './chunk-CWNRE2OU.js';
2
- import { createRecorder, bootTwin } from './chunk-IK2F7ZA3.js';
1
+ import { parseTaskFile, seedStateForTwin, runAgentCommand, writeRunArtifactsCore } from './chunk-XAQGX7K2.js';
2
+ import { createRecorder, bootTwin } from './chunk-S6JLWI4S.js';
3
3
  import { getAvailablePort } from './chunk-XDU6TD4O.js';
4
4
  import { buildEgressAllowlist, readBlockedEgress } from './chunk-CBFKZZBR.js';
5
5
  import { eventSchema } from './chunk-6KJC4BTO.js';
@@ -1,6 +1,7 @@
1
- import { createHostedClient, perTwinReturnedByCloud, parseTaskFile, runAgentCommand, writeRunArtifactsCore, toTwinHttpEvent, redactJsonl, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, evaluationCounts } from './chunk-CWNRE2OU.js';
2
- import { readManifest, normalizeManifestTwins } from './chunk-QOMNBXMQ.js';
3
- import { MOUNTED_TWINS, HostedAuthError, HostedDiscardRefusedError, HostedQuotaError, HostedOrchError, HostedTrialError, agentResponseSchema } from './chunk-D5PXUPG4.js';
1
+ import { createHostedClient, perTwinReturnedByCloud, parseTaskFile, runAgentCommand, writeRunArtifactsCore, toTwinHttpEvent, redactJsonl, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, evaluationCounts } from './chunk-XAQGX7K2.js';
2
+ import { readSeedFileText, parseSeedFileText, soleTwinOf, seedsForTwins } from './chunk-B7PA7UDX.js';
3
+ import { readManifest, normalizeManifestTwins } from './chunk-VO2XUPZC.js';
4
+ import { MOUNTED_TWINS, HostedAuthError, HostedDiscardRefusedError, HostedQuotaError, HostedOrchError, HostedTrialError, agentResponseSchema, isMultiTwinSeedEnvelope } from './chunk-E7WJ3SRP.js';
4
5
  import { redactSecrets, redactEvent } from './chunk-SG6ZTIMT.js';
5
6
  import { randomUUID, createHash } from 'node:crypto';
6
7
  import { rm, readFile, stat, mkdir, writeFile, chmod, mkdtemp, readdir, rename } from 'node:fs/promises';
@@ -697,8 +698,22 @@ function normalizeSessionTwins(raw) {
697
698
  }
698
699
  return deduped;
699
700
  }
701
+ async function resolveSessionSeed(seedPath, requestedTwins) {
702
+ const raw = readSeedFileText(seedPath, "pome sandbox create --seed");
703
+ const origin = `--seed ${seedPath}`;
704
+ const file = parseSeedFileText(raw, origin);
705
+ const twins = normalizeSessionTwins(
706
+ requestedTwins.length > 0 ? requestedTwins : [soleTwinOf(file) ?? ""].filter(Boolean)
707
+ );
708
+ const byTwin = await seedsForTwins(file, twins, origin);
709
+ return {
710
+ twins,
711
+ seed: isMultiTwinSeedEnvelope(twins) ? byTwin : byTwin[twins[0]]
712
+ };
713
+ }
700
714
  async function runSessionCreate(opts) {
701
- const twins = normalizeSessionTwins(opts.twins);
715
+ const resolvedSeed = opts.seedPath === void 0 ? void 0 : await resolveSessionSeed(opts.seedPath, opts.twins);
716
+ const twins = resolvedSeed?.twins ?? normalizeSessionTwins(opts.twins);
702
717
  const creds = await resolveCredentials({ apiBaseUrl: opts.apiBaseUrl });
703
718
  const client = createHostedClient({
704
719
  baseUrl: creds.apiBaseUrl,
@@ -713,7 +728,8 @@ async function runSessionCreate(opts) {
713
728
  taskSource: "# ..\n",
714
729
  idempotencyKey: randomUUID(),
715
730
  agentId: identity.agentId,
716
- agentVersion: identity.agentVersion
731
+ agentVersion: identity.agentVersion,
732
+ ...resolvedSeed ? { seed: resolvedSeed.seed } : {}
717
733
  });
718
734
  if (opts.secretsFile) {
719
735
  await writeSecretsFile(opts.secretsFile, formatEnvExport(session, twins));
@@ -736,6 +752,9 @@ async function runSessionCreate(opts) {
736
752
  }
737
753
  console.error(`Session: ${session.session_id}`);
738
754
  console.error(`Expires: ${session.expires_at}`);
755
+ if (opts.seedPath !== void 0) {
756
+ console.error(`Seed: ${opts.seedPath} (replaces the default for ${twins.join(", ")}).`);
757
+ }
739
758
  let printedAny = false;
740
759
  const mcpFromCloud = perTwinReturnedByCloud(session);
741
760
  for (const twin of twins) {
@@ -1,4 +1,4 @@
1
- import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-JE4H5ODK.js';
1
+ import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-SRG22BIH.js';
2
2
  import { createFileBackedRecorderStore, createRecorderStore } from './chunk-E665XWYU.js';
3
3
 
4
4
  // src/recorder/recorder.ts
@@ -30,10 +30,9 @@ var TWIN_REGISTRY = {
30
30
  envName: "GITHUB",
31
31
  defaultPort: 3333,
32
32
  version: package_default.version,
33
- // The github twin's own `defaultSeedState()` is applied by `boot` below
34
- // when no seed is supplied — the pre-existing standalone behavior.
35
- defaultSeed: async () => void 0,
33
+ defaultSeed: async () => (await import('./seed-BG5HMSBM.js')).defaultSeedState(),
36
34
  parseSeed: async (input) => (await import('./seed-BG5HMSBM.js')).parseSeed(input),
35
+ seedFields: async () => Object.keys((await import('./seed-BG5HMSBM.js')).seedSchema.shape),
37
36
  async boot({ seedState, runId, recorder }) {
38
37
  const {
39
38
  createGitHubCloneApp,
@@ -60,8 +59,9 @@ var TWIN_REGISTRY = {
60
59
  envName: "SLACK",
61
60
  defaultPort: 3333,
62
61
  version: package_default2.version,
63
- defaultSeed: async () => (await import('./src-SKCWAMVQ.js')).defaultSeedState(),
62
+ defaultSeed: async () => (await import('./seed-IIMBJHAJ.js')).defaultSeedState(),
64
63
  parseSeed: async (input) => (await import('./seed-IIMBJHAJ.js')).parseSeed(input),
64
+ seedFields: async () => Object.keys((await import('./seed-IIMBJHAJ.js')).seedSchema.shape),
65
65
  async boot({ seedState, runId, recorder }) {
66
66
  const { createSlackTwinApp, openSlackTwinDatabase, SlackDomain } = await import('./src-SKCWAMVQ.js');
67
67
  const db = openSlackTwinDatabase(":memory:");
@@ -86,8 +86,9 @@ var TWIN_REGISTRY = {
86
86
  envName: "STRIPE",
87
87
  defaultPort: 3333,
88
88
  version: package_default3.version,
89
- defaultSeed: async () => (await import('./src-PW7U25ZX.js')).defaultSeed(),
89
+ defaultSeed: async () => (await import('./seed-YWDTT2WL.js')).defaultSeed(),
90
90
  parseSeed: async (input) => (await import('./seed-YWDTT2WL.js')).parseSeed(input),
91
+ seedFields: async () => Object.keys((await import('./seed-YWDTT2WL.js')).seedSchema.shape),
91
92
  async boot({ seedState, runId, recorder, twinBaseUrl }) {
92
93
  const stripeTwin = await import('./src-PW7U25ZX.js');
93
94
  const { createApp } = await import('./server-DMLORMOV.js');
@@ -131,8 +132,9 @@ var TWIN_REGISTRY = {
131
132
  portEnvName: "GMAIL_TWIN_PORT",
132
133
  tokenEnvName: "POME_GMAIL_TOKEN",
133
134
  version: package_default4.version,
134
- defaultSeed: async () => (await import('./src-KSLAF3I4.js')).defaultSeedState(),
135
+ defaultSeed: async () => (await import('./seed-NR6RUKXV.js')).defaultSeedState(),
135
136
  parseSeed: async (input) => (await import('./seed-NR6RUKXV.js')).parseSeed(input),
137
+ seedFields: async () => Object.keys((await import('./seed-NR6RUKXV.js')).gmailSeedSchema.shape),
136
138
  async boot({ seedState, runId, recorder }) {
137
139
  const { createGmailTwinApp, GmailDomain, openGmailTwinDatabase, parseSeed } = await import('./src-KSLAF3I4.js');
138
140
  const db = openGmailTwinDatabase(":memory:");
@@ -153,8 +155,9 @@ var TWIN_REGISTRY = {
153
155
  portEnvName: "LINEAR_TWIN_PORT",
154
156
  tokenEnvName: "POME_LINEAR_TOKEN",
155
157
  version: package_default5.version,
156
- defaultSeed: async () => (await import('./src-JRBHNT4Y.js')).defaultSeedState(),
157
- parseSeed: async (input) => (await import('./seed-3ZTWKLBE.js')).parseSeed(input),
158
+ defaultSeed: async () => (await import('./seed-F7RNI55S.js')).defaultSeedState(),
159
+ parseSeed: async (input) => (await import('./seed-F7RNI55S.js')).parseSeed(input),
160
+ seedFields: async () => Object.keys((await import('./seed-F7RNI55S.js')).linearSeedSchema.shape),
158
161
  async boot({ seedState, runId, recorder }) {
159
162
  const {
160
163
  createLinearTwinApp,
@@ -162,7 +165,7 @@ var TWIN_REGISTRY = {
162
165
  LinearDomain,
163
166
  openLinearTwinDatabase,
164
167
  parseSeed
165
- } = await import('./src-JRBHNT4Y.js');
168
+ } = await import('./src-5YCI6VIR.js');
166
169
  const db = openLinearTwinDatabase(":memory:");
167
170
  const seed = parseSeed(seedState);
168
171
  const domain = new LinearDomain(db);
@@ -1,4 +1,4 @@
1
- import { HostedOrchError, manifestSchema, deriveAgentSlug, SLUG_RE } from './chunk-D5PXUPG4.js';
1
+ import { HostedOrchError, manifestSchema, deriveAgentSlug, SLUG_RE } from './chunk-E7WJ3SRP.js';
2
2
  import { readFile, writeFile } from 'node:fs/promises';
3
3
  import { resolve, join, dirname } from 'node:path';
4
4
  import { stringify, parse } from 'yaml';
@@ -1,7 +1,7 @@
1
1
  import { gmailSeedSchema, defaultSeedState } from './chunk-3T5XN64P.js';
2
- import { linearSeedSchema, defaultSeedState as defaultSeedState$1 } from './chunk-G6GOCYIT.js';
3
- import { isTwinName, TWIN_REGISTRY } from './chunk-JE4H5ODK.js';
4
- import { criterionSchema, finalizeResponseSchema, HostedDiscardRefusedError, HostedOrchError, HostedAuthError, HostedQuotaError, submitResultResponseSchema, createEvalSessionResponseSchema, createSessionResponseSchema, sessionPublicSchema } from './chunk-D5PXUPG4.js';
2
+ import { linearSeedSchema, defaultSeedState as defaultSeedState$1 } from './chunk-Q5NBPR57.js';
3
+ import { isTwinName, TWIN_REGISTRY } from './chunk-SRG22BIH.js';
4
+ import { criterionSchema, finalizeResponseSchema, HostedDiscardRefusedError, HostedOrchError, HostedAuthError, HostedQuotaError, submitResultResponseSchema, createEvalSessionResponseSchema, createSessionResponseSchema, sessionPublicSchema } from './chunk-E7WJ3SRP.js';
5
5
  import { seedSchema, parseSeed, defaultSeedState as defaultSeedState$2 } from './chunk-HJX25USP.js';
6
6
  import { toTwinHttpEventRow } from './chunk-E665XWYU.js';
7
7
  import { redactEvent, redactSecrets } from './chunk-SG6ZTIMT.js';
@@ -1,14 +1,14 @@
1
1
  import { newGroupId, reassuranceBox, twinReadyLine, trialsHeaderLine, trialLine, summaryLines, evaluatingLine, criterionPhrase } from './chunk-RGZBC7NF.js';
2
2
  import { DemoCapacityError, capacityLabel, parseCapacityMarker, capacityKindFrom } from './chunk-ZX4WNSZ5.js';
3
- import { runTask, demoTaskPath, DEMO_TASK_NAME, DEMO_REPO } from './chunk-MOZU3NOM.js';
4
- import { createHostedClient, parseTaskFile, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, outcomeOf } from './chunk-CWNRE2OU.js';
3
+ import { runTask, demoTaskPath, DEMO_TASK_NAME, DEMO_REPO } from './chunk-IYMDPMMZ.js';
4
+ import { createHostedClient, parseTaskFile, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, outcomeOf } from './chunk-XAQGX7K2.js';
5
5
  import './chunk-NW7HGA2K.js';
6
6
  import './chunk-3T5XN64P.js';
7
- import './chunk-G6GOCYIT.js';
8
- import { bootTwin } from './chunk-IK2F7ZA3.js';
9
- import './chunk-JE4H5ODK.js';
7
+ import './chunk-Q5NBPR57.js';
8
+ import { bootTwin } from './chunk-S6JLWI4S.js';
9
+ import './chunk-SRG22BIH.js';
10
10
  import { getAvailablePort } from './chunk-XDU6TD4O.js';
11
- import { HostedQuotaError, HostedOrchError } from './chunk-D5PXUPG4.js';
11
+ import { HostedQuotaError, HostedOrchError } from './chunk-E7WJ3SRP.js';
12
12
  import './chunk-CBFKZZBR.js';
13
13
  import './chunk-HJX25USP.js';
14
14
  import './chunk-E665XWYU.js';
@@ -1,12 +1,13 @@
1
1
  import { newGroupId, criterionPhrase } from './chunk-RGZBC7NF.js';
2
- import { runTaskHosted, resolveRunAgentIdentity } from './chunk-JW3DHRNX.js';
3
- import { createHostedClient, parseTaskFile, outcomeOf } from './chunk-CWNRE2OU.js';
2
+ import { runTaskHosted, resolveRunAgentIdentity } from './chunk-MRCYOSBM.js';
3
+ import { createHostedClient, parseTaskFile, outcomeOf } from './chunk-XAQGX7K2.js';
4
+ import './chunk-B7PA7UDX.js';
4
5
  import './chunk-NW7HGA2K.js';
5
6
  import './chunk-3T5XN64P.js';
6
- import './chunk-G6GOCYIT.js';
7
- import './chunk-JE4H5ODK.js';
8
- import './chunk-QOMNBXMQ.js';
9
- import { HostedQuotaError, HostedTrialError } from './chunk-D5PXUPG4.js';
7
+ import './chunk-Q5NBPR57.js';
8
+ import './chunk-SRG22BIH.js';
9
+ import './chunk-VO2XUPZC.js';
10
+ import { HostedQuotaError, HostedTrialError } from './chunk-E7WJ3SRP.js';
10
11
  import './chunk-HJX25USP.js';
11
12
  import './chunk-E665XWYU.js';
12
13
  import './chunk-6KJC4BTO.js';
@@ -1 +1 @@
1
- export { defaultSeedState, linearSeedSchema, loadSeedFromEnv, parseSeed } from './chunk-G6GOCYIT.js';
1
+ export { defaultSeedState, linearSeedSchema, loadSeedFromEnv, parseSeed } from './chunk-Q5NBPR57.js';
@@ -1,17 +1,18 @@
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, VERDICT_ARTIFACT_VERSION, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, resolveCachedAgentId, readLinkCache, postAgentResolver, writeLinkCache, ensurePomeGitignored } from '../../chunk-JW3DHRNX.js';
3
- import { assetPath, runTask, resolvePackageRoot, DEMO_TASK_NAME, demoTaskPath } from '../../chunk-MOZU3NOM.js';
4
- import { parseTaskFile, scoreStatus, runScoreLine, readLatestRun, readMetaSummary, outcomeOf, readConfigTwins, scoreCountsSummary, markerFor, criterionMarkerLabel, twinSkipSuffix, readCodeCriteria, createHostedClient, toTwinHttpEvent, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-CWNRE2OU.js';
2
+ import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, SESSION_TWIN_NAMES, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, runTaskHosted, discoverRunSet, VERDICT_ARTIFACT_VERSION, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, resolveCachedAgentId, readLinkCache, postAgentResolver, writeLinkCache, ensurePomeGitignored } from '../../chunk-MRCYOSBM.js';
3
+ import { assetPath, runTask, resolvePackageRoot, DEMO_TASK_NAME, demoTaskPath } from '../../chunk-IYMDPMMZ.js';
4
+ import { parseTaskFile, scoreStatus, runScoreLine, readLatestRun, readMetaSummary, outcomeOf, readConfigTwins, scoreCountsSummary, markerFor, criterionMarkerLabel, twinSkipSuffix, readCodeCriteria, createHostedClient, toTwinHttpEvent, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-XAQGX7K2.js';
5
+ import '../../chunk-B7PA7UDX.js';
5
6
  import '../../chunk-NW7HGA2K.js';
6
7
  import { GMAIL_CHECKS } from '../../chunk-JM6VS62R.js';
7
8
  import '../../chunk-3T5XN64P.js';
8
9
  import { LINEAR_CHECKS } from '../../chunk-XBT6ZLBG.js';
9
- import '../../chunk-G6GOCYIT.js';
10
- import '../../chunk-IK2F7ZA3.js';
11
- import { TWIN_NAME_LIST, isTwinName, createGitHubSmokeApp } from '../../chunk-JE4H5ODK.js';
12
- import { readManifest, writeManifest, MANIFEST_JSON, readRequiredManifest, normalizeManifestTwins } from '../../chunk-QOMNBXMQ.js';
10
+ import '../../chunk-Q5NBPR57.js';
11
+ import '../../chunk-S6JLWI4S.js';
12
+ import { TWIN_NAME_LIST, isTwinName, createGitHubSmokeApp } from '../../chunk-SRG22BIH.js';
13
+ import { readManifest, writeManifest, MANIFEST_JSON, readRequiredManifest, normalizeManifestTwins } from '../../chunk-VO2XUPZC.js';
13
14
  import '../../chunk-XDU6TD4O.js';
14
- import { MOUNTED_TWINS, deriveAgentSlug, exitCodeFor, HostedUsageError, HostedOrchError, HostedAuthError, HostedQuotaError } from '../../chunk-D5PXUPG4.js';
15
+ import { MOUNTED_TWINS, deriveAgentSlug, exitCodeFor, HostedUsageError, HostedOrchError, HostedAuthError, HostedQuotaError } from '../../chunk-E7WJ3SRP.js';
15
16
  import '../../chunk-CBFKZZBR.js';
16
17
  import { TAPE_ASSERTABLE_TOOLS } from '../../chunk-C4BVTUA3.js';
17
18
  import { seedSchema } from '../../chunk-HJX25USP.js';
@@ -4652,7 +4653,7 @@ var DEFAULT_AGENT_COMMAND = `node ${DEFAULT_AGENT_FILE}`;
4652
4653
  var MANIFEST_SCHEMA_URL = "https://pome.sh/schemas/v1/pome.json";
4653
4654
  var MAX_UNREADABLE_PATHS_SHOWN = 5;
4654
4655
  function readPackageVersion() {
4655
- if ("0.28.0".length > 0) return "0.28.0";
4656
+ if ("0.29.0".length > 0) return "0.29.0";
4656
4657
  try {
4657
4658
  const here = dirname(fileURLToPath(import.meta.url));
4658
4659
  const candidates = [
@@ -4896,7 +4897,7 @@ function createProgram() {
4896
4897
  const session = program.command("session").alias("sandbox").description(
4897
4898
  "Hosted sandbox sessions (same API as the dashboard Twins page \u2014 requires login)"
4898
4899
  );
4899
- session.command("create").description("Create a hosted sandbox session for one or more twins and print its connection info").requiredOption(
4900
+ session.command("create").description("Create a hosted sandbox session for one or more twins and print its connection info").option(
4900
4901
  "--twin <name>",
4901
4902
  // The enumeration is derived, never typed: this line is the public
4902
4903
  // discovery surface for which twins exist, and a hand-written copy of the
@@ -4904,8 +4905,17 @@ function createProgram() {
4904
4905
  // stays editorial — github+gmail is the pairing bundled task 27 exercises —
4905
4906
  // and `session-twin-help.test.ts` runs the twins it names through the same
4906
4907
  // validator, so it cannot rot either.
4907
- `${SESSION_TWIN_NAMES.join(" | ")}. Repeat the flag for a multi-twin session (e.g. --twin github --twin gmail).`,
4908
+ //
4909
+ // No longer `requiredOption`: a `--seed` file whose envelope names exactly
4910
+ // one twin already says which twin the sandbox is for. Commander would
4911
+ // reject the invocation before the action runs, so the check moved into
4912
+ // `runSessionCreate`, which fails with the same "No twin specified"
4913
+ // sentence when neither source supplies one.
4914
+ `${SESSION_TWIN_NAMES.join(" | ")}. Repeat the flag for a multi-twin session (e.g. --twin github --twin gmail). Optional when --seed names exactly one twin.`,
4908
4915
  (value, previous = []) => [...previous, value]
4916
+ ).option(
4917
+ "--seed <path>",
4918
+ "Start the sandbox from a JSON or YAML seed file instead of each twin's default. A seed REPLACES the default; it does not merge. Same file `pome twin start --seed` takes; write one with `pome twin seed <name>`."
4909
4919
  ).option(
4910
4920
  "--api-url <url>",
4911
4921
  "Control-plane URL",
@@ -4928,10 +4938,11 @@ function createProgram() {
4928
4938
  }
4929
4939
  await runSessionCreate({
4930
4940
  apiBaseUrl: opts.apiUrl,
4931
- twins: opts.twin,
4941
+ twins: opts.twin ?? [],
4932
4942
  showSecrets: opts.showSecrets,
4933
4943
  format,
4934
- secretsFile: opts.secretsFile
4944
+ secretsFile: opts.secretsFile,
4945
+ seedPath: opts.seed
4935
4946
  });
4936
4947
  } catch (err) {
4937
4948
  console.error(friendlyHostedError(err));
@@ -5103,7 +5114,7 @@ function createProgram() {
5103
5114
  return;
5104
5115
  }
5105
5116
  {
5106
- const { runDoctorChecks } = await import('../../checks-XPLJ2MKP.js');
5117
+ const { runDoctorChecks } = await import('../../checks-JR4OEKZM.js');
5107
5118
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
5108
5119
  const doctorReport = await runDoctorChecks({ mode: useLocal ? "full" : "hosted" });
5109
5120
  if (!doctorReport.ok) {
@@ -5141,7 +5152,7 @@ function createProgram() {
5141
5152
  taskForRuns.config.runs
5142
5153
  );
5143
5154
  if (k > 1) {
5144
- const { runTrialGroup } = await import('../../runTrialGroup-TPDWP2LN.js');
5155
+ const { runTrialGroup } = await import('../../runTrialGroup-XEBG225L.js');
5145
5156
  const fileForRerun = relative(process.cwd(), file);
5146
5157
  const rerunCommand = defaultTask ? options.trials !== void 0 ? `pome run -n ${k}` : "pome run" : `pome run ${fileForRerun && !fileForRerun.startsWith("..") ? fileForRerun : file} -n ${k}`;
5147
5158
  const groupResult = await runTrialGroup({
@@ -5235,7 +5246,7 @@ function createProgram() {
5235
5246
  process.exitCode = 5;
5236
5247
  return;
5237
5248
  }
5238
- const { runDemo } = await import('../../runDemo-YY5F6FP2.js');
5249
+ const { runDemo } = await import('../../runDemo-GBPVF5AA.js');
5239
5250
  const result = await runDemo({
5240
5251
  apiBase: opts.apiUrl.replace(/\/$/, ""),
5241
5252
  dashboardBase: process.env.POME_DASHBOARD_URL ?? DEFAULT_DASHBOARD_URL,
@@ -5253,7 +5264,7 @@ function createProgram() {
5253
5264
  program.command("doctor").description(
5254
5265
  "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."
5255
5266
  ).action(async () => {
5256
- const { runDoctorChecks } = await import('../../checks-XPLJ2MKP.js');
5267
+ const { runDoctorChecks } = await import('../../checks-JR4OEKZM.js');
5257
5268
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
5258
5269
  const report = await runDoctorChecks();
5259
5270
  for (const line of renderDoctorReport(report, { passNote: true })) console.error(line);
@@ -5423,18 +5434,27 @@ function createProgram() {
5423
5434
  );
5424
5435
  });
5425
5436
  const twin = program.command("twin").description("Manage local twins");
5426
- twin.command("start").argument("<name>", `Twin name (${TWIN_NAME_LIST.join(" | ")})`).option(
5437
+ twin.command("start").argument(
5438
+ "[name]",
5439
+ `Twin name (${TWIN_NAME_LIST.join(" | ")}). Optional when --seed names exactly one twin.`
5440
+ ).option(
5427
5441
  "--port <port>",
5428
5442
  "Port to bind (default: $PORT, else GMAIL_TWIN_PORT/3336 for gmail, else 3333)"
5429
5443
  ).option(
5430
5444
  "--seed <path>",
5431
- "Boot this twin's world from a JSON or YAML file instead of its default. Overrides POME_SEED_JSON."
5445
+ "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."
5432
5446
  ).description(
5433
5447
  "Start a standalone twin as a long-lived foreground server (Ctrl-C to stop)"
5434
5448
  ).action(async (name, options) => {
5435
- const { runTwinStartCommand } = await import('../../twinStart-PDL53BY5.js');
5449
+ const { runTwinStartCommand } = await import('../../twinStart-ZDWFU6M4.js');
5436
5450
  await runTwinStartCommand(name, options);
5437
5451
  });
5452
+ twin.command("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.").description(
5453
+ "Print a starter seed file for a twin, generated from the twin's own starting state"
5454
+ ).action(async (names, options) => {
5455
+ const { runTwinSeedCommand } = await import('../../twinSeed-MOQXJDEG.js');
5456
+ await runTwinSeedCommand(names, options);
5457
+ });
5438
5458
  twin.command("reset").argument("[name]", "Twin name (default: github)", "github").description("Reset standalone twin state").action(async (name) => {
5439
5459
  if (!isTwinName(name)) {
5440
5460
  throw new Error(`Unknown twin '${name}'. Supported: ${TWIN_NAME_LIST.join(", ")}.`);
@@ -1,6 +1,6 @@
1
1
  export { LINEAR_CHECKS } from './chunk-XBT6ZLBG.js';
2
- import { MCP_PAGE_MAX, defaultSeedState, linearSeedSchema, notFound, badUserInput, MCP_PAGE_DEFAULT, DEFAULT_LINEAR_EMAIL, RELAY_PAGE_MAX, RELAY_PAGE_DEFAULT, STATE_EXPORT_CAP, parseSeed, DEFAULT_LINEAR_CLOCK, LINEAR_PROVIDER_TOKEN_PREFIX, DEFAULT_LINEAR_SID, DEFAULT_SCOPES, linearErrorEnvelope, unauthorizedEnvelope, unsupportedEnvelope, forbiddenEnvelope, assertWebhookUrl, ACCESS_TOKEN_TTL_SECONDS, OAUTH_CODE_TTL_SECONDS, TITLE_MAX_BYTES, BODY_MAX_BYTES, LinearTwinError, GRAPHQL_QUERY_MAX_BYTES, GRAPHQL_SELECTION_DEPTH_MAX } from './chunk-G6GOCYIT.js';
3
- export { DEFAULT_LINEAR_CLOCK, DEFAULT_LINEAR_EMAIL, DEFAULT_LINEAR_PORT, DEFAULT_LINEAR_SID, DEFAULT_LINEAR_TOKEN, LINEAR_PROVIDER_TOKEN_PREFIX, LinearTwinError, STATE_EXPORT_CAP, assertWebhookUrl, defaultSeedState, linearErrorEnvelope, linearSeedSchema, loadSeedFromEnv, parseSeed, unauthorizedEnvelope, unsupportedEnvelope, webhookUrlError } from './chunk-G6GOCYIT.js';
2
+ import { MCP_PAGE_MAX, defaultSeedState, linearSeedSchema, notFound, badUserInput, MCP_PAGE_DEFAULT, DEFAULT_LINEAR_EMAIL, RELAY_PAGE_MAX, RELAY_PAGE_DEFAULT, STATE_EXPORT_CAP, parseSeed, DEFAULT_LINEAR_CLOCK, LINEAR_PROVIDER_TOKEN_PREFIX, DEFAULT_LINEAR_SID, DEFAULT_SCOPES, linearErrorEnvelope, unauthorizedEnvelope, unsupportedEnvelope, forbiddenEnvelope, assertWebhookUrl, ACCESS_TOKEN_TTL_SECONDS, OAUTH_CODE_TTL_SECONDS, TITLE_MAX_BYTES, BODY_MAX_BYTES, LinearTwinError, GRAPHQL_QUERY_MAX_BYTES, GRAPHQL_SELECTION_DEPTH_MAX } from './chunk-Q5NBPR57.js';
3
+ export { DEFAULT_LINEAR_CLOCK, DEFAULT_LINEAR_EMAIL, DEFAULT_LINEAR_PORT, DEFAULT_LINEAR_SID, DEFAULT_LINEAR_TOKEN, LINEAR_PROVIDER_TOKEN_PREFIX, LinearTwinError, STATE_EXPORT_CAP, assertWebhookUrl, defaultSeedState, linearErrorEnvelope, linearSeedSchema, loadSeedFromEnv, parseSeed, unauthorizedEnvelope, unsupportedEnvelope, webhookUrlError } from './chunk-Q5NBPR57.js';
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-E665XWYU.js';
@@ -0,0 +1,6 @@
1
+ export { UnsupportedTwinError, bootTwin } from './chunk-S6JLWI4S.js';
2
+ export { STRIPE_LOCAL_ACCOUNT_ID } from './chunk-SRG22BIH.js';
3
+ import './chunk-E665XWYU.js';
4
+ import './chunk-6KJC4BTO.js';
5
+ import './chunk-SG6ZTIMT.js';
6
+ import './chunk-CF6EIU2U.js';
@@ -0,0 +1,48 @@
1
+ import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-SRG22BIH.js';
2
+ import { writeFile } from 'node:fs/promises';
3
+
4
+ async function generateSeedFile(twins) {
5
+ if (twins.length === 0) {
6
+ throw new Error(`No twin specified. Pass at least one of: ${TWIN_NAMES.join(", ")}.`);
7
+ }
8
+ for (const twin of twins) {
9
+ if (!isTwinName(twin)) {
10
+ throw new Error(`Unknown twin '${twin}'. Supported: ${TWIN_NAMES.join(", ")}.`);
11
+ }
12
+ }
13
+ const duplicates = twins.filter((twin, i) => twins.indexOf(twin) !== i);
14
+ if (duplicates.length > 0) {
15
+ throw new Error(`A seed file has one entry per twin, and this one is named twice: ${[...new Set(duplicates)].join(", ")}.`);
16
+ }
17
+ const envelope = {};
18
+ for (const twin of twins) {
19
+ const entry = TWIN_REGISTRY[twin];
20
+ envelope[twin] = await entry.parseSeed(await entry.defaultSeed());
21
+ }
22
+ return `${JSON.stringify(envelope, null, 2)}
23
+ `;
24
+ }
25
+ async function writeSeedFile(path, text) {
26
+ try {
27
+ await writeFile(path, text, { flag: "wx" });
28
+ } catch (err) {
29
+ if (err.code === "EEXIST") {
30
+ throw new Error(
31
+ `${path} already exists \u2014 delete it or pass a different --out. A seed file is authored content once it is on disk.`
32
+ );
33
+ }
34
+ throw err;
35
+ }
36
+ }
37
+ async function runTwinSeedCommand(names, options = {}) {
38
+ const text = await generateSeedFile(names);
39
+ if (options.out === void 0) {
40
+ process.stdout.write(text);
41
+ return;
42
+ }
43
+ await writeSeedFile(options.out, text);
44
+ console.error(`Wrote ${options.out} \u2014 the ${names.join(" + ")} starting seed.`);
45
+ console.error(`Boot it: pome twin start ${names[0]} --seed ${options.out}`);
46
+ }
47
+
48
+ export { generateSeedFile, runTwinSeedCommand, writeSeedFile };
@@ -1,5 +1,6 @@
1
- import { bootTwin } from './chunk-IK2F7ZA3.js';
2
- import { TWIN_REGISTRY, isTwinName, TWIN_NAMES, defaultPortFor } from './chunk-JE4H5ODK.js';
1
+ import { readSeedFileText, seedForTwin, parseSeedFileText, soleTwinOf, twinsNamedBy } from './chunk-B7PA7UDX.js';
2
+ import { bootTwin } from './chunk-S6JLWI4S.js';
3
+ import { TWIN_REGISTRY, isTwinName, TWIN_NAMES, defaultPortFor } from './chunk-SRG22BIH.js';
3
4
  import './chunk-E665XWYU.js';
4
5
  import './chunk-6KJC4BTO.js';
5
6
  import './chunk-SG6ZTIMT.js';
@@ -10,7 +11,6 @@ import { mkdir, writeFile } from 'node:fs/promises';
10
11
  import { join } from 'node:path';
11
12
  import { serve } from '@hono/node-server';
12
13
  import { sign } from 'hono/jwt';
13
- import { parse } from 'yaml';
14
14
 
15
15
  var STANDALONE_SID = "standalone";
16
16
  function resolveStandaloneAuthSecret(twin, env = process.env) {
@@ -35,59 +35,59 @@ function resolveStandaloneAuthSecret(twin, env = process.env) {
35
35
  }
36
36
  return { secret: randomBytes(32).toString("hex"), source: "ephemeral" };
37
37
  }
38
- async function resolveStandaloneSeed(twin, seedPath, env = process.env) {
39
- const entry = TWIN_REGISTRY[twin];
38
+ async function resolveStandaloneSeed(twin, seedPath, env = process.env, seedText) {
40
39
  if (seedPath !== void 0) {
41
- let raw;
42
- try {
43
- raw = readFileSync(seedPath, "utf8");
44
- } catch (err) {
45
- throw new Error(
46
- `pome twin start --seed: cannot read ${seedPath}: ${err.message}`
47
- );
48
- }
40
+ const raw = seedText ?? readSeedFileText(seedPath, "pome twin start --seed");
41
+ const origin = `--seed ${seedPath}`;
49
42
  return {
50
- seedState: await parseWorld(entry, raw, `--seed ${seedPath}`),
43
+ seedState: await seedForTwin(parseSeedFileText(raw, origin), twin, origin),
51
44
  source: "file",
52
45
  path: seedPath
53
46
  };
54
47
  }
55
48
  const fromEnv = env.POME_SEED_JSON;
56
49
  if (fromEnv !== void 0 && fromEnv !== "") {
57
- return { seedState: await parseWorld(entry, fromEnv, "POME_SEED_JSON"), source: "env" };
58
- }
59
- return { seedState: await entry.defaultSeed(), source: "default" };
60
- }
61
- function stripSidecarMeta(seed) {
62
- if (seed && typeof seed === "object" && !Array.isArray(seed)) {
63
- const { _meta, ...rest } = seed;
64
- return rest;
50
+ return {
51
+ seedState: await seedForTwin(
52
+ parseSeedFileText(fromEnv, "POME_SEED_JSON"),
53
+ twin,
54
+ "POME_SEED_JSON"
55
+ ),
56
+ source: "env"
57
+ };
65
58
  }
66
- return seed;
59
+ return { seedState: await TWIN_REGISTRY[twin].defaultSeed(), source: "default" };
67
60
  }
68
- async function parseWorld(entry, raw, origin) {
69
- let parsed;
70
- try {
71
- parsed = parse(raw);
72
- } catch (err) {
73
- throw new Error(`${origin} is not valid JSON or YAML: ${err.message}`);
61
+ function resolveStandaloneTwin(name, seedPath, seedText) {
62
+ if (name !== void 0) {
63
+ if (!isTwinName(name)) {
64
+ throw new Error(`Unknown twin '${name}'. Supported: ${TWIN_NAMES.join(", ")}.`);
65
+ }
66
+ return name;
74
67
  }
75
- try {
76
- return await entry.parseSeed(stripSidecarMeta(parsed));
77
- } catch (err) {
78
- throw new Error(`${origin} is not a world this twin can boot: ${err.message}`);
68
+ if (seedPath === void 0 || seedText === void 0) {
69
+ throw new Error(
70
+ `pome twin start: name a twin (${TWIN_NAMES.join(", ")}), or pass a --seed file whose envelope names exactly one.`
71
+ );
79
72
  }
73
+ const origin = `--seed ${seedPath}`;
74
+ const file = parseSeedFileText(seedText, origin);
75
+ const sole = soleTwinOf(file);
76
+ if (sole !== void 0) return sole;
77
+ const named = twinsNamedBy(file);
78
+ throw new Error(
79
+ named.length === 0 ? `${origin} is a flat seed, so it does not name a twin. Pass the name: pome twin start <${TWIN_NAMES.join("|")}> --seed ${seedPath}` : `${origin} names ${named.length} twins (${named.join(", ")}), so it does not say which one to start. Pass the name: pome twin start ${named[0]} --seed ${seedPath}`
80
+ );
80
81
  }
81
- async function runTwinStartCommand(name, options) {
82
- if (!isTwinName(name)) {
83
- throw new Error(`Unknown twin '${name}'. Supported: ${TWIN_NAMES.join(", ")}.`);
84
- }
82
+ async function runTwinStartCommand(nameArg, options) {
83
+ const seedText = options.seed === void 0 ? void 0 : readSeedFileText(options.seed, "pome twin start --seed");
84
+ const name = resolveStandaloneTwin(nameArg, options.seed, seedText);
85
85
  const portRaw = options.port ?? defaultPortFor(name, process.env);
86
86
  const port = Number(portRaw);
87
87
  if (!Number.isInteger(port) || port < 1 || port > 65535) {
88
88
  throw new Error(`pome twin start: invalid --port "${portRaw}"`);
89
89
  }
90
- const world = await resolveStandaloneSeed(name, options.seed);
90
+ const world = await resolveStandaloneSeed(name, options.seed, process.env, seedText);
91
91
  const resolved = resolveStandaloneAuthSecret(name);
92
92
  process.env.TWIN_AUTH_SECRET = resolved.secret;
93
93
  const baseUrl = `http://127.0.0.1:${port}`;
@@ -130,11 +130,15 @@ async function runTwinStartCommand(name, options) {
130
130
  }
131
131
  console.log(`Pome ${name} twin listening at ${restUrl}`);
132
132
  if (world.source === "file") {
133
- console.log(`World: seeded from ${world.path}.`);
133
+ console.log(`Seed: ${world.path} (replaces the ${name} twin's default).`);
134
134
  } else if (world.source === "env") {
135
- console.log("World: seeded from POME_SEED_JSON (--seed <path> overrides it).");
135
+ console.log(
136
+ `Seed: POME_SEED_JSON (replaces the ${name} twin's default; --seed <path> overrides it).`
137
+ );
136
138
  } else {
137
- console.log(`World: the ${name} twin's default (pass --seed <path> for your own).`);
139
+ console.log(
140
+ `Seed: the ${name} twin's default (pass --seed <path>, or write one with \`pome twin seed ${name}\`).`
141
+ );
138
142
  }
139
143
  if (resolved.source === "persisted") {
140
144
  console.log(
@@ -161,4 +165,4 @@ async function runTwinStartCommand(name, options) {
161
165
  process.once("SIGTERM", shutdown);
162
166
  }
163
167
 
164
- export { resolveStandaloneAuthSecret, resolveStandaloneSeed, runTwinStartCommand };
168
+ export { resolveStandaloneAuthSecret, resolveStandaloneSeed, resolveStandaloneTwin, runTwinStartCommand };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pome-sh/cli",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "Digital-twin testing for AI agents \u2014 run tasks against resettable local or hosted twins and record tool-call traces for evaluation on pome.sh.",
5
5
  "keywords": [
6
6
  "ai",
@@ -1,6 +0,0 @@
1
- export { UnsupportedTwinError, bootTwin } from './chunk-IK2F7ZA3.js';
2
- export { STRIPE_LOCAL_ACCOUNT_ID } from './chunk-JE4H5ODK.js';
3
- import './chunk-E665XWYU.js';
4
- import './chunk-6KJC4BTO.js';
5
- import './chunk-SG6ZTIMT.js';
6
- import './chunk-CF6EIU2U.js';
File without changes