@pome-sh/cli 0.23.1 → 0.23.2

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.
package/README.md CHANGED
@@ -79,8 +79,19 @@ Three rules CI must honor:
79
79
  whose criteria could not all be graded exits `1` rather than mapping its
80
80
  partial score to a code — a run whose checks never ran is not a green CI
81
81
  signal. The cost is stated rather than hidden: **`1` cannot tell "the agent
82
- regressed" from "we could not grade it."** Read the verdict word printed
83
- beside the score (`INCOMPLETE` vs a sub-threshold number) to separate them.
82
+ regressed" from "we could not grade it."** To separate them programmatically,
83
+ do not compare `score` against `pass_threshold` yourself a run with a third
84
+ of its criteria unevaluated can still read `score: 100, pass_threshold: 100`
85
+ with nothing in those two fields alone saying so. Read `state` in the
86
+ `verdict.json` a hosted `pome run` writes to
87
+ `<artifacts-dir>/<task-slug>/<session-id>/verdict.json`: `"pass"`, `"fail"`,
88
+ or `"incomplete"` — the same word the terminal prints beside the score, and
89
+ the field to gate on. The `evaluated` / `not_evaluated` / `pre_satisfied` /
90
+ `total` counts alongside it say how much of the task `score` covers:
91
+ **`score` is a percentage over `evaluated` alone**, so `not_evaluated > 0`
92
+ means `score` is silent about part of the run, and `evaluated: 0` means it
93
+ scored nothing at all (the cloud sends `0` there for want of a denominator
94
+ — "nothing was scored", not "nothing was correct").
84
95
  - **Trial groups map as a whole.** `pome run -n k` (k>1) collapses the whole
85
96
  group to one code: `0` = at least one trial completed and every completed
86
97
  trial passed; `1` = at least one completed trial failed its threshold **or was
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "pome-sh",
3
- "version": "0.23.1",
4
- "git_sha": "f57142b584d0bbeaa6b1c3e6194daf2723ed6d3c",
5
- "build_time": "2026-08-10T12:44:52.803Z"
3
+ "version": "0.23.2",
4
+ "git_sha": "9fe20d1ba7f0f9b40cfb7561e4ceab144c22c71d",
5
+ "build_time": "2026-08-10T13:45:05.230Z"
6
6
  }
@@ -1,6 +1,6 @@
1
1
  import { getAvailablePort } from './chunk-XDU6TD4O.js';
2
2
  import { buildEgressAllowlist, readBlockedEgress } from './chunk-CBFKZZBR.js';
3
- import { parseTaskFile, seedStateForTwin, runAgentCommand, writeRunArtifactsCore } from './chunk-Z32CZ45D.js';
3
+ import { parseTaskFile, seedStateForTwin, runAgentCommand, writeRunArtifactsCore } from './chunk-N4UTEHX5.js';
4
4
  import { createRecorder, bootTwin } from './chunk-TG22SRUL.js';
5
5
  import { eventSchema } from './chunk-VBATFCWR.js';
6
6
  import { redactSecrets, redactEvent } from './chunk-SG6ZTIMT.js';
@@ -1265,15 +1265,23 @@ function twinSkipSuffix(result) {
1265
1265
  function criteriaWord(n) {
1266
1266
  return n === 1 ? "criterion" : "criteria";
1267
1267
  }
1268
+ function evaluationCounts(score) {
1269
+ const evaluated = score.total_required;
1270
+ const notEvaluated = score.skipped + score.errored - score.preSatisfied;
1271
+ return {
1272
+ evaluated,
1273
+ notEvaluated,
1274
+ preSatisfied: score.preSatisfied,
1275
+ total: evaluated + notEvaluated + score.preSatisfied
1276
+ };
1277
+ }
1268
1278
  function scoreCountsSummary(score) {
1269
1279
  return `${score.passed ?? 0} passed, ${score.failed ?? 0} failed, ${score.skipped ?? 0} skipped, ${score.errored ?? 0} errored`;
1270
1280
  }
1271
1281
  function runScoreLine(score, passThreshold, unevaluatedNumericLabel) {
1272
1282
  const status = scoreStatus(score, passThreshold);
1273
1283
  if (status === "incomplete") {
1274
- const allExcluded = score.skipped + score.errored;
1275
- const unreached = allExcluded - score.preSatisfied;
1276
- const total = score.total_required + allExcluded;
1284
+ const { notEvaluated: unreached, total } = evaluationCounts(score);
1277
1285
  if (score.total_required === 0 && unreached === 0 && score.preSatisfied > 0) {
1278
1286
  return `score: incomplete \u2014 nothing was at risk (${score.preSatisfied} ${criteriaWord(score.preSatisfied)} already true in the seed); ${scoreCountsSummary(score)}; ${unevaluatedNumericLabel}: ${score.satisfaction}/100`;
1279
1287
  }
@@ -1630,4 +1638,4 @@ function splitCommand(command) {
1630
1638
  return file ? { file, args } : null;
1631
1639
  }
1632
1640
 
1633
- export { createHostedClient, criterionMarkerLabel, isPreSatisfied, markerFor, outcomeOf, parseGitHubSeedState, parseTaskFile, perTwinReturnedByCloud, readCodeCriteria, readConfigTwins, readLatestRun, readMetaSummary, redactJsonl, runAgentCommand, runScoreLine, scoreCountsSummary, scoreFromFinalizeResponse, scoreStatus, seedStateForTwin, toTwinHttpEvent, twinSkipSuffix, uploadRunBlobs, writeRunArtifactsCore };
1641
+ export { createHostedClient, criterionMarkerLabel, evaluationCounts, isPreSatisfied, markerFor, outcomeOf, parseGitHubSeedState, parseTaskFile, perTwinReturnedByCloud, readCodeCriteria, readConfigTwins, readLatestRun, readMetaSummary, redactJsonl, runAgentCommand, runScoreLine, scoreCountsSummary, scoreFromFinalizeResponse, scoreStatus, seedStateForTwin, toTwinHttpEvent, twinSkipSuffix, uploadRunBlobs, writeRunArtifactsCore };
@@ -1,5 +1,5 @@
1
1
  import { readManifest, normalizeManifestTwins } from './chunk-KUVTL4NZ.js';
2
- import { createHostedClient, perTwinReturnedByCloud, parseTaskFile, runAgentCommand, writeRunArtifactsCore, toTwinHttpEvent, redactJsonl, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus } from './chunk-Z32CZ45D.js';
2
+ import { createHostedClient, perTwinReturnedByCloud, parseTaskFile, runAgentCommand, writeRunArtifactsCore, toTwinHttpEvent, redactJsonl, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, evaluationCounts } from './chunk-N4UTEHX5.js';
3
3
  import { MOUNTED_TWINS, HostedAuthError, HostedDiscardRefusedError, HostedQuotaError, HostedOrchError, HostedTrialError, agentResponseSchema } from './chunk-PQYIAA6K.js';
4
4
  import { redactSecrets, redactEvent } from './chunk-SG6ZTIMT.js';
5
5
  import { existsSync } from 'node:fs';
@@ -11,8 +11,13 @@ import { promisify } from 'node:util';
11
11
  import { createInterface } from 'node:readline';
12
12
  import { randomUUID, createHash } from 'node:crypto';
13
13
 
14
- var VERDICT_ARTIFACT_VERSION = 1;
14
+ var VERDICT_ARTIFACT_VERSION = 2;
15
15
  var VERDICT_FILENAME = "verdict.json";
16
+ var VALID_STATES = /* @__PURE__ */ new Set([
17
+ "pass",
18
+ "fail",
19
+ "incomplete"
20
+ ]);
16
21
  async function writeVerdictArtifact(runDir, verdict) {
17
22
  await writeFile(
18
23
  join(runDir, VERDICT_FILENAME),
@@ -21,7 +26,7 @@ async function writeVerdictArtifact(runDir, verdict) {
21
26
  "utf8"
22
27
  );
23
28
  }
24
- function isVerdictArtifact(parsed) {
29
+ function looksLikeVerdictArtifactBase(parsed) {
25
30
  if (typeof parsed !== "object" || parsed === null) return false;
26
31
  const v = parsed;
27
32
  if (v.source !== "cloud-finalize") return false;
@@ -40,33 +45,46 @@ function isVerdictArtifact(parsed) {
40
45
  return typeof criterion === "object" && criterion !== null && typeof criterion.text === "string" && typeof result.reason === "string" && typeof result.passed === "boolean" && typeof result.skipped === "boolean";
41
46
  });
42
47
  }
43
- function normalizeVerdictArtifact(parsed) {
44
- const { scenario_path: legacyPath, task_path: taskPath, ...rest } = parsed;
45
- return { ...rest, task_path: taskPath ?? legacyPath };
48
+ function isVerdictArtifact(parsed) {
49
+ if (!looksLikeVerdictArtifactBase(parsed)) return false;
50
+ const v = parsed;
51
+ if (v.version !== VERDICT_ARTIFACT_VERSION) return false;
52
+ if (typeof v.task_path !== "string") return false;
53
+ if (typeof v.state !== "string" || !VALID_STATES.has(v.state)) return false;
54
+ if (typeof v.evaluated !== "number") return false;
55
+ if (typeof v.not_evaluated !== "number") return false;
56
+ if (typeof v.pre_satisfied !== "number") return false;
57
+ if (typeof v.total !== "number") return false;
58
+ return true;
46
59
  }
47
- async function readVerdictArtifact(runDir) {
60
+ async function readVerdictArtifactDetailed(runDir) {
48
61
  const path = join(runDir, VERDICT_FILENAME);
49
62
  let raw;
50
63
  try {
51
64
  raw = await readFile(path, "utf8");
52
65
  } catch {
53
- return null;
66
+ return { status: "unreadable" };
54
67
  }
68
+ let parsed;
55
69
  try {
56
- const parsed = JSON.parse(raw);
57
- if (!isVerdictArtifact(parsed)) return null;
58
- return { runDir, verdict: normalizeVerdictArtifact(parsed) };
70
+ parsed = JSON.parse(raw);
59
71
  } catch {
60
- return null;
72
+ return { status: "unreadable" };
61
73
  }
74
+ if (!looksLikeVerdictArtifactBase(parsed)) return { status: "unreadable" };
75
+ const version = typeof parsed.version === "number" ? parsed.version : null;
76
+ if (version !== VERDICT_ARTIFACT_VERSION) return { status: "stale-version", version };
77
+ if (!isVerdictArtifact(parsed)) return { status: "unreadable" };
78
+ return { status: "ok", trial: { runDir, verdict: parsed } };
62
79
  }
63
- async function scanVerdictArtifacts(artifactsRoot) {
64
- const found = [];
80
+ async function scanVerdictArtifactsDetailed(artifactsRoot) {
81
+ const trials = [];
82
+ const staleVersionDirs = [];
65
83
  let slugs;
66
84
  try {
67
85
  slugs = await readdir(artifactsRoot);
68
86
  } catch {
69
- return found;
87
+ return { trials, staleVersionDirs };
70
88
  }
71
89
  for (const slug of slugs) {
72
90
  const slugDir = join(artifactsRoot, slug);
@@ -77,11 +95,13 @@ async function scanVerdictArtifacts(artifactsRoot) {
77
95
  continue;
78
96
  }
79
97
  for (const runId of runIds) {
80
- const trial = await readVerdictArtifact(join(slugDir, runId));
81
- if (trial) found.push(trial);
98
+ const runDir = join(slugDir, runId);
99
+ const result = await readVerdictArtifactDetailed(runDir);
100
+ if (result.status === "ok") trials.push(result.trial);
101
+ else if (result.status === "stale-version") staleVersionDirs.push(runDir);
82
102
  }
83
103
  }
84
- return found;
104
+ return { trials, staleVersionDirs };
85
105
  }
86
106
  function groupRunSets(trials) {
87
107
  const byKey = /* @__PURE__ */ new Map();
@@ -116,21 +136,35 @@ function latestFailedRunSet(sets) {
116
136
  return null;
117
137
  }
118
138
  async function discoverRunSet(target) {
119
- const anchor = await readVerdictArtifact(target);
120
- if (anchor) {
139
+ const anchorResult = await readVerdictArtifactDetailed(target);
140
+ if (anchorResult.status === "stale-version") {
141
+ return { kind: "trial-dir", set: null, totalSets: 0, staleVersionCount: 1 };
142
+ }
143
+ if (anchorResult.status === "ok") {
144
+ const anchor = anchorResult.trial;
121
145
  const root = join(target, "..", "..");
122
- const sets2 = groupRunSets(await scanVerdictArtifacts(root));
146
+ const { trials: trials2, staleVersionDirs: staleVersionDirs2 } = await scanVerdictArtifactsDetailed(root);
147
+ const sets2 = groupRunSets(trials2);
123
148
  const own = sets2.find(
124
149
  (s) => anchor.verdict.group_id !== null && s.groupId === anchor.verdict.group_id || anchor.verdict.group_id === null && s.trials.length === 1 && s.trials[0].verdict.session_id === anchor.verdict.session_id
125
150
  ) ?? groupRunSets([anchor])[0];
126
- return { kind: "trial-dir", set: own, totalSets: Math.max(sets2.length, 1) };
151
+ return {
152
+ kind: "trial-dir",
153
+ set: own,
154
+ totalSets: Math.max(sets2.length, 1),
155
+ staleVersionCount: staleVersionDirs2.length
156
+ };
157
+ }
158
+ if (!existsSync(target)) {
159
+ return { kind: "root", set: null, totalSets: 0, staleVersionCount: 0 };
127
160
  }
128
- if (!existsSync(target)) return { kind: "root", set: null, totalSets: 0 };
129
- const sets = groupRunSets(await scanVerdictArtifacts(target));
161
+ const { trials, staleVersionDirs } = await scanVerdictArtifactsDetailed(target);
162
+ const sets = groupRunSets(trials);
130
163
  return {
131
164
  kind: "root",
132
165
  set: latestFailedRunSet(sets),
133
- totalSets: sets.length
166
+ totalSets: sets.length,
167
+ staleVersionCount: staleVersionDirs.length
134
168
  };
135
169
  }
136
170
  async function loadTrialEvents(runDir) {
@@ -1067,6 +1101,7 @@ async function runTaskHosted(options) {
1067
1101
  const verdict = scoreStatus(score, scenario.config.passThreshold);
1068
1102
  const exitCode = verdict === "pass" ? 0 : 1;
1069
1103
  try {
1104
+ const counts = evaluationCounts(score);
1070
1105
  await writeVerdictArtifact(artifacts.runDir, {
1071
1106
  version: VERDICT_ARTIFACT_VERSION,
1072
1107
  source: "cloud-finalize",
@@ -1079,7 +1114,12 @@ async function runTaskHosted(options) {
1079
1114
  judge_model: score.judge_model,
1080
1115
  score: finalized.score,
1081
1116
  pass_threshold: scenario.config.passThreshold,
1117
+ state: verdict,
1082
1118
  passed: exitCode === 0,
1119
+ evaluated: counts.evaluated,
1120
+ not_evaluated: counts.notEvaluated,
1121
+ pre_satisfied: counts.preSatisfied,
1122
+ total: counts.total,
1083
1123
  criteria_results: score.results,
1084
1124
  duration_ms: durationMs,
1085
1125
  finalized_at: (/* @__PURE__ */ new Date()).toISOString()
@@ -1176,4 +1216,4 @@ async function abandonBestEffort(client, sessionId, errorCode) {
1176
1216
  }
1177
1217
  }
1178
1218
 
1179
- export { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, DEFAULT_DOCS_SITE_ORIGIN, clearLocalCredentials, discoverRunSet, ensurePomeGitignored, friendlyHostedError, loadTrialEvents, persistCredentialsAfterLogin, postAgentResolver, readLinkCache, resolveCachedAgentId, resolveCredentials, resolveRunAgentIdentity, resolveSeams, runSessionCreate, runSessionList, runSessionStop, runTaskHosted, writeLinkCache };
1219
+ export { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, DEFAULT_DOCS_SITE_ORIGIN, VERDICT_ARTIFACT_VERSION, clearLocalCredentials, discoverRunSet, ensurePomeGitignored, friendlyHostedError, loadTrialEvents, persistCredentialsAfterLogin, postAgentResolver, readLinkCache, resolveCachedAgentId, resolveCredentials, resolveRunAgentIdentity, resolveSeams, runSessionCreate, runSessionList, runSessionStop, runTaskHosted, writeLinkCache };
@@ -1,9 +1,9 @@
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-54OLERUK.js';
3
+ import { runTask, demoTaskPath, DEMO_TASK_NAME, DEMO_REPO } from './chunk-IQ6LOK4D.js';
4
4
  import { getAvailablePort } from './chunk-XDU6TD4O.js';
5
5
  import './chunk-CBFKZZBR.js';
6
- import { createHostedClient, parseTaskFile, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, outcomeOf } from './chunk-Z32CZ45D.js';
6
+ import { createHostedClient, parseTaskFile, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, outcomeOf } from './chunk-N4UTEHX5.js';
7
7
  import './chunk-NW7HGA2K.js';
8
8
  import { HostedQuotaError, HostedOrchError } from './chunk-PQYIAA6K.js';
9
9
  import './chunk-SGDUD7KK.js';
@@ -1,7 +1,7 @@
1
1
  import { newGroupId, criterionPhrase } from './chunk-RGZBC7NF.js';
2
- import { runTaskHosted, resolveRunAgentIdentity } from './chunk-BCI7KJRH.js';
2
+ import { runTaskHosted, resolveRunAgentIdentity } from './chunk-NRECWO3Y.js';
3
3
  import './chunk-KUVTL4NZ.js';
4
- import { createHostedClient, parseTaskFile, outcomeOf } from './chunk-Z32CZ45D.js';
4
+ import { createHostedClient, parseTaskFile, outcomeOf } from './chunk-N4UTEHX5.js';
5
5
  import './chunk-NW7HGA2K.js';
6
6
  import { HostedQuotaError, HostedTrialError } from './chunk-PQYIAA6K.js';
7
7
  import './chunk-SGDUD7KK.js';
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, runTaskHosted, discoverRunSet, loadTrialEvents, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, resolveCachedAgentId, readLinkCache, postAgentResolver, writeLinkCache, ensurePomeGitignored } from '../../chunk-BCI7KJRH.js';
2
+ import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, runTaskHosted, discoverRunSet, VERDICT_ARTIFACT_VERSION, loadTrialEvents, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, resolveCachedAgentId, readLinkCache, postAgentResolver, writeLinkCache, ensurePomeGitignored } from '../../chunk-NRECWO3Y.js';
3
3
  import { readManifest, writeManifest, MANIFEST_JSON, readRequiredManifest, normalizeManifestTwins } from '../../chunk-KUVTL4NZ.js';
4
- import { assetPath, runTask, resolvePackageRoot, DEMO_TASK_NAME, demoTaskPath } from '../../chunk-54OLERUK.js';
4
+ import { assetPath, runTask, resolvePackageRoot, DEMO_TASK_NAME, demoTaskPath } from '../../chunk-IQ6LOK4D.js';
5
5
  import '../../chunk-XDU6TD4O.js';
6
6
  import '../../chunk-CBFKZZBR.js';
7
- import { parseTaskFile, scoreStatus, runScoreLine, readLatestRun, readMetaSummary, readConfigTwins, scoreCountsSummary, markerFor, outcomeOf, criterionMarkerLabel, twinSkipSuffix, readCodeCriteria, createHostedClient, toTwinHttpEvent, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-Z32CZ45D.js';
7
+ import { parseTaskFile, scoreStatus, runScoreLine, readLatestRun, readMetaSummary, readConfigTwins, scoreCountsSummary, markerFor, outcomeOf, criterionMarkerLabel, twinSkipSuffix, readCodeCriteria, createHostedClient, toTwinHttpEvent, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-N4UTEHX5.js';
8
8
  import '../../chunk-NW7HGA2K.js';
9
9
  import { MOUNTED_TWINS, deriveAgentSlug, exitCodeFor, HostedUsageError, HostedOrchError, HostedAuthError, HostedQuotaError } from '../../chunk-PQYIAA6K.js';
10
10
  import { TAPE_ASSERTABLE_TOOLS } from '../../chunk-FKZZWWYC.js';
@@ -4497,7 +4497,7 @@ var DEFAULT_AGENT_FILE = "examples/agents/scripted-triage-agent.ts";
4497
4497
  var DEFAULT_AGENT_COMMAND = `node ${DEFAULT_AGENT_FILE}`;
4498
4498
  var MANIFEST_SCHEMA_URL = "https://pome.sh/schemas/v1/pome.json";
4499
4499
  function readPackageVersion() {
4500
- if ("0.23.1".length > 0) return "0.23.1";
4500
+ if ("0.23.2".length > 0) return "0.23.2";
4501
4501
  try {
4502
4502
  const here = dirname(fileURLToPath(import.meta.url));
4503
4503
  const candidates = [
@@ -4990,7 +4990,7 @@ function createProgram() {
4990
4990
  taskForRuns.config.runs
4991
4991
  );
4992
4992
  if (k > 1) {
4993
- const { runTrialGroup } = await import('../../runTrialGroup-O7DQIB7T.js');
4993
+ const { runTrialGroup } = await import('../../runTrialGroup-M4CP7WKY.js');
4994
4994
  const fileForRerun = relative(process.cwd(), file);
4995
4995
  const rerunCommand = defaultTask ? options.trials !== void 0 ? `pome run -n ${k}` : "pome run" : `pome run ${fileForRerun && !fileForRerun.startsWith("..") ? fileForRerun : file} -n ${k}`;
4996
4996
  const groupResult = await runTrialGroup({
@@ -5084,7 +5084,7 @@ function createProgram() {
5084
5084
  process.exitCode = 5;
5085
5085
  return;
5086
5086
  }
5087
- const { runDemo } = await import('../../runDemo-Q3WATCYJ.js');
5087
+ const { runDemo } = await import('../../runDemo-NPBMT4BF.js');
5088
5088
  const result = await runDemo({
5089
5089
  apiBase: opts.apiUrl.replace(/\/$/, ""),
5090
5090
  dashboardBase: process.env.POME_DASHBOARD_URL ?? DEFAULT_DASHBOARD_URL,
@@ -5189,10 +5189,17 @@ function createProgram() {
5189
5189
  }
5190
5190
  const root = target ?? "runs";
5191
5191
  const discovery = await discoverRunSet(resolve(root));
5192
- if (discovery.totalSets === 0) {
5192
+ if (discovery.staleVersionCount > 0) {
5193
5193
  console.error(
5194
- `No finalized run sets under ${root} \u2014 hosted \`pome run\` records a verdict.json per trial; run one first (or point fix-prompt at your artifacts dir).`
5194
+ `${discovery.staleVersionCount} verdict.json file(s) under ${root} are not artifact version ${VERDICT_ARTIFACT_VERSION} (the only version this CLI reads) and were skipped \u2014 re-run \`pome run\` to record those trials again.`
5195
5195
  );
5196
+ }
5197
+ if (discovery.totalSets === 0) {
5198
+ if (discovery.staleVersionCount === 0) {
5199
+ console.error(
5200
+ `No finalized run sets under ${root} \u2014 hosted \`pome run\` records a verdict.json per trial; run one first (or point fix-prompt at your artifacts dir).`
5201
+ );
5202
+ }
5196
5203
  process.exitCode = 5;
5197
5204
  return;
5198
5205
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pome-sh/cli",
3
- "version": "0.23.1",
3
+ "version": "0.23.2",
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",