@kky42/pievo-server 4.2.0 → 5.0.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.
Files changed (38) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{MarkdownView-C9-AzIkl.js → MarkdownView-T28pBEgh.js} +1 -1
  3. package/.output/public/assets/{actionUi-D47jwMfh.js → actionUi-CY207nNM.js} +1 -1
  4. package/.output/public/assets/app-Cye1TgwS.css +2 -0
  5. package/.output/public/assets/index-BxXrF3gW.js +10 -0
  6. package/.output/public/assets/loops._loopId-DuSEcu38.js +2 -0
  7. package/.output/public/assets/{loops._loopId_.runs._runId-DW2HPjtj.js → loops._loopId_.runs._runId-vjQaPXEe.js} +2 -2
  8. package/.output/public/assets/{preload-helper-CbYqBpY9.js → preload-helper-B7p1iHUP.js} +2 -2
  9. package/.output/public/assets/routes-BUMEAWuS.js +1 -0
  10. package/.output/public/assets/routes-BrqOpUEi.js +1 -0
  11. package/.output/server/_ssr/{MachinesModal-DwHy2cis.mjs → MachinesModal-CB8rpDG2.mjs} +24 -12
  12. package/.output/server/_ssr/{actionUi-CszQXDSN.mjs → actionUi-CPYgZIr7.mjs} +40 -62
  13. package/.output/server/_ssr/{artifactFiles-DJiK99sF.mjs → artifactFiles-DLfSRhrV.mjs} +3 -3
  14. package/.output/server/_ssr/{artifactKind-DYMU0q3N.mjs → artifactKind-C0oXLA23.mjs} +2 -2
  15. package/.output/server/_ssr/{boot-CecCDRoH.mjs → boot-jtVCf_pN.mjs} +27 -91
  16. package/.output/server/_ssr/{loopApi-uEiBQ5YX.mjs → loopApi-0nR35Kh2.mjs} +8 -8
  17. package/.output/server/_ssr/{loopProjection-Bo54jjGd.mjs → loopProjection-ZNfSmA5e.mjs} +2 -2
  18. package/.output/server/_ssr/{loops._loopId-c1oRP7cr.mjs → loops._loopId-CcJ3rxCU.mjs} +9 -65
  19. package/.output/server/_ssr/{loops._loopId_.runs._runId-czMVvNsk.mjs → loops._loopId_.runs._runId-DFlrV3dJ.mjs} +2 -2
  20. package/.output/server/_ssr/{loops._loopId_.runs._runId-Dl0SwOlC.mjs → loops._loopId_.runs._runId-XkGF7HKo.mjs} +4 -4
  21. package/.output/server/_ssr/{machineFns-aw9xe5oz.mjs → machineFns-D-97a_hz.mjs} +2 -2
  22. package/.output/server/_ssr/{router-3OQ849sN.mjs → router-CZ9CFWS2.mjs} +15 -15
  23. package/.output/server/_ssr/{routes-CL4y6AEv.mjs → routes-BBmuVs6n.mjs} +2 -2
  24. package/.output/server/_ssr/{routes-nU2PDK3W.mjs → routes-JxTh5mbj.mjs} +2 -2
  25. package/.output/server/_ssr/{routes-CT5IdoiP.mjs → routes-fHRtSpkH.mjs} +5 -5
  26. package/.output/server/_ssr/ssr.mjs +22 -22
  27. package/.output/server/{_tanstack-start-manifest_v-_nMS2ozp.mjs → _tanstack-start-manifest_v-C9JsxlwC.mjs} +8 -8
  28. package/.output/server/drizzle/0003_run_status_ok.sql +13 -0
  29. package/.output/server/drizzle/meta/_journal.json +7 -0
  30. package/.output/server/index.mjs +47 -47
  31. package/drizzle/0003_run_status_ok.sql +13 -0
  32. package/drizzle/meta/_journal.json +7 -0
  33. package/package.json +1 -1
  34. package/.output/public/assets/app-C5xfpeJe.css +0 -2
  35. package/.output/public/assets/index-BgNjFXWE.js +0 -10
  36. package/.output/public/assets/loops._loopId-Bo63FXPQ.js +0 -2
  37. package/.output/public/assets/routes-C88oSApK.js +0 -1
  38. package/.output/public/assets/routes-CTCh8xYm.js +0 -1
@@ -1,6 +1,6 @@
1
1
  import { o as __toESM } from "../_runtime.mjs";
2
2
  import { g as require_react, h as require_jsx_runtime } from "../_libs/@base-ui/react+[...].mjs";
3
- //#region node_modules/.nitro/vite/services/ssr/assets/actionUi-CszQXDSN.js
3
+ //#region node_modules/.nitro/vite/services/ssr/assets/actionUi-CPYgZIr7.js
4
4
  var import_react = /* @__PURE__ */ __toESM(require_react());
5
5
  var import_jsx_runtime = require_jsx_runtime();
6
6
  var fmt = (t) => t ? new Date(t).toLocaleString() : "—";
@@ -78,13 +78,9 @@ function humanBytes(n) {
78
78
  return `${(abs / (1024 * 1024)).toFixed(1)} MB`;
79
79
  }
80
80
  var ST = {
81
- keep: {
82
- c: "var(--color-run-keep)",
83
- label: "Keep"
84
- },
85
- "no-change": {
86
- c: "var(--color-run-no-change)",
87
- label: "No change"
81
+ ok: {
82
+ c: "var(--color-run-ok)",
83
+ label: "OK"
88
84
  },
89
85
  block: {
90
86
  c: "var(--color-run-block)",
@@ -94,10 +90,6 @@ var ST = {
94
90
  c: "var(--color-run-error)",
95
91
  label: "Error"
96
92
  },
97
- warning: {
98
- c: "var(--color-run-warning)",
99
- label: "Missing status"
100
- },
101
93
  canceled: {
102
94
  c: "var(--color-run-canceled)",
103
95
  label: "Canceled"
@@ -107,7 +99,7 @@ var ST = {
107
99
  label: "Queued"
108
100
  },
109
101
  reconciling: {
110
- c: "var(--color-run-warning)",
102
+ c: "var(--color-run-reconciling)",
111
103
  label: "Reconciling…"
112
104
  },
113
105
  active: {
@@ -115,48 +107,45 @@ var ST = {
115
107
  label: "Running…"
116
108
  }
117
109
  };
118
- var statusMeta = (k) => k === "keep" || k === "no-change" || k === "block" ? ST[k] : void 0;
110
+ /** The run's ink, for text and borders. Fills use `runSwatch`. */
119
111
  function dotColor(r) {
120
112
  if (r.reconciliation) return ST.reconciling.c;
121
113
  if (r.phase === "running") return ST.active.c;
122
114
  if (r.phase === "error") return ST.error.c;
123
- if (r.status === "block") return ST.block.c;
124
115
  if (r.phase === "pending") return ST.queued.c;
125
116
  if (r.phase === "canceled") return ST.canceled.c;
126
- if (r.phase === "done" && !statusMeta(r.status)) return ST.warning.c;
127
- return (statusMeta(r.status) ?? ST["no-change"]).c;
117
+ return r.status === "block" ? ST.block.c : ST.ok.c;
128
118
  }
129
- function dotOpacity(r) {
130
- if (r.attention) return 1;
131
- if (r.reconciliation || r.phase === "running" || r.status === "block" || r.phase === "error") return 1;
132
- if (r.phase === "pending") return .7;
133
- if (r.phase === "canceled") return .5;
134
- if (r.phase === "done" && !statusMeta(r.status)) return .9;
135
- if (r.status === "no-change") return .55;
136
- return 1;
119
+ var runPulseAnim = { animation: "runPulse 1.1s ease-in-out infinite" };
120
+ /** Fill, outline, and motion for a run block or dot. */
121
+ function runSwatch(r) {
122
+ const ink = dotColor(r);
123
+ if (r.reconciliation) return {
124
+ outline: `1.5px dashed ${ink}`,
125
+ outlineOffset: "-1.5px",
126
+ animation: "runWait 2.4s ease-in-out infinite"
127
+ };
128
+ if (r.phase === "running") return {
129
+ background: ink,
130
+ ...runPulseAnim
131
+ };
132
+ if (r.phase === "pending") return { boxShadow: `inset 0 0 0 1.5px ${ink}` };
133
+ if (r.phase === "canceled") return {
134
+ background: ink,
135
+ opacity: .5
136
+ };
137
+ if (r.phase === "error") return { background: `repeating-linear-gradient(135deg, ${ink} 0 3px, var(--color-run-error-stripe) 3px 6px)` };
138
+ return { background: ink };
137
139
  }
138
140
  function dotLabel(r) {
139
141
  if (r.reconciliation === "blocking") return "Waiting for machine recovery";
140
142
  if (r.reconciliation === "report-only") return "Awaiting late report";
141
143
  if (r.phase === "pending") return ST.queued.label;
142
- if (r.phase === "running") {
143
- if (r.cancelRequested) return "Stopping…";
144
- return ST.active.label;
145
- }
146
- if (r.phase === "error") {
147
- if (r.cancelRequested) return "Failed while stopping";
148
- return ST.error.label;
149
- }
144
+ if (r.phase === "running") return r.cancelRequested ? "Stopping…" : ST.active.label;
145
+ if (r.phase === "error") return r.cancelRequested ? "Failed while stopping" : ST.error.label;
146
+ if (r.phase === "canceled") return ST.canceled.label;
150
147
  if (r.status === "block") return ST.block.label;
151
- if (r.phase === "canceled") {
152
- if (r.error === "stopped by user") return "Canceled";
153
- return "Canceled";
154
- }
155
- if (r.cancelRequested && r.phase === "done") return "Succeeded while stopping";
156
- if (r.status === "keep") return ST.keep.label;
157
- if (r.status === "no-change") return ST["no-change"].label;
158
- if (r.phase === "done") return ST.warning.label;
159
- return ST["no-change"].label;
148
+ return r.cancelRequested ? "Succeeded while stopping" : ST.ok.label;
160
149
  }
161
150
  /** The newest finished run, whose attention reason the loop card surfaces until a
162
151
  * later run finishes without one. */
@@ -178,14 +167,10 @@ var sectionHeadCls = "text-label font-semibold text-secondary";
178
167
  var labelCls = "mb-1.5 mt-3 block text-label font-medium text-secondary";
179
168
  var inputCls = `w-full rounded-control border border-wire bg-surface px-3 py-2.5 text-sm text-primary outline-none transition-shadow focus:border-transparent focus:shadow-focus`;
180
169
  var selectCls = `${inputCls} lp-select cursor-pointer`;
181
- /**
182
- * The live "running" pulse — a display-ink fill breathing via the `runPulse`
183
- * keyframe (app.css). Shared so the in-flight timeline block and the Running
184
- * badge stay in lockstep. Spread into a `style` prop.
185
- */
186
- var runPulseAnim = { animation: "runPulse 1.1s ease-in-out infinite" };
170
+ /** The live "running" indicator outside the timeline: the same ink fill and
171
+ * `runPulse` breath as the in-flight run block. Spread into a `style` prop. */
187
172
  var runPulseStyle = {
188
- background: "var(--color-rubik-yellow)",
173
+ background: "var(--color-run-active)",
189
174
  ...runPulseAnim
190
175
  };
191
176
  function ErrorBanner({ message, onDismiss, className = "mb-2" }) {
@@ -210,20 +195,16 @@ var PILL_TONES = {
210
195
  neutral: "bg-raised text-secondary",
211
196
  ink: "bg-raised text-primary",
212
197
  outline: "border border-hairline text-secondary",
213
- running: "bg-running-soft text-running",
214
- attention: "bg-running-soft text-running",
198
+ attention: "bg-attention-soft text-attention",
215
199
  success: "bg-success-soft text-success",
216
200
  accent: "bg-accent-soft text-accent",
217
201
  warn: "bg-warn-soft text-warn"
218
202
  };
219
- function Pill({ tone = "neutral", dot, title, className = "", children }) {
220
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
203
+ function Pill({ tone = "neutral", title, className = "", children }) {
204
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
221
205
  title,
222
206
  className: `inline-flex h-[22px] items-center gap-1.5 rounded-full px-2.5 text-caption font-medium ${PILL_TONES[tone]} ${className}`,
223
- children: [dot && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
224
- className: "size-1.5 rounded-full",
225
- style: dot === "pulse" ? runPulseStyle : { background: "var(--color-rubik-green)" }
226
- }), children]
207
+ children
227
208
  });
228
209
  }
229
210
  function Loading({ className = "" }) {
@@ -252,10 +233,7 @@ function StatusPill({ run, colorText }) {
252
233
  style: colorText ? { color: dotColor(run) } : void 0,
253
234
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
254
235
  className: "size-2 rounded-full",
255
- style: {
256
- background: dotColor(run),
257
- opacity: dotOpacity(run)
258
- }
236
+ style: runSwatch(run)
259
237
  }), dotLabel(run)]
260
238
  });
261
239
  }
@@ -371,4 +349,4 @@ function useFlash() {
371
349
  return [flash, setFlash];
372
350
  }
373
351
  //#endregion
374
- export { sectionHeadCls as A, labelCls as C, runPulseAnim as D, rel as E, useHydrated as F, tsShort as M, until as N, runPulseStyle as O, useFlash as P, inputCls as S, lastRunOf as T, dur as _, LoadErrorCard as a, focusRing as b, StatusPill as c, btnPrimary as d, btnQuiet as f, dotOpacity as g, dotLabel as h, FlashLine as i, selectCls as j, scheduleText as k, btn as l, dotColor as m, ConfirmBar as n, Loading as o, btnSm as p, ErrorBanner as r, Pill as s, AttentionMark as t, btnDanger as u, fmt as v, lastFinishedRun as w, humanBytes as x, fnum as y };
352
+ export { tsShort as A, lastRunOf as C, scheduleText as D, runSwatch as E, useFlash as M, useHydrated as N, sectionHeadCls as O, lastFinishedRun as S, runPulseStyle as T, fnum as _, LoadErrorCard as a, inputCls as b, StatusPill as c, btnPrimary as d, btnQuiet as f, fmt as g, dur as h, FlashLine as i, until as j, selectCls as k, btn as l, dotLabel as m, ConfirmBar as n, Loading as o, btnSm as p, ErrorBanner as r, Pill as s, AttentionMark as t, btnDanger as u, focusRing as v, rel as w, labelCls as x, humanBytes as y };
@@ -1,6 +1,6 @@
1
- import { D as listArtifacts, M as loopFileNames, b as getArtifactFile, c as getLoopFiles, x as getLoop } from "./boot-CecCDRoH.mjs";
2
- import { n as toArtifactSummary } from "./loopProjection-Bo54jjGd.mjs";
3
- //#region node_modules/.nitro/vite/services/ssr/assets/artifactFiles-DJiK99sF.js
1
+ import { D as listArtifacts, M as loopFileNames, b as getArtifactFile, c as getLoopFiles, x as getLoop } from "./boot-jtVCf_pN.mjs";
2
+ import { n as toArtifactSummary } from "./loopProjection-ZNfSmA5e.mjs";
3
+ //#region node_modules/.nitro/vite/services/ssr/assets/artifactFiles-DLfSRhrV.js
4
4
  /** Read-only access to a loop's current files, shared by the dashboard server
5
5
  * functions and the download route. Bytes are decoded as text, never interpreted. */
6
6
  async function listLoopArtifacts(loopId) {
@@ -1,6 +1,6 @@
1
1
  import { c as createFileRoute, s as lazyRouteComponent } from "../_libs/@tanstack/react-router+[...].mjs";
2
- //#region node_modules/.nitro/vite/services/ssr/assets/artifactKind-DYMU0q3N.js
3
- var $$splitComponentImporter = () => import("./loops._loopId-c1oRP7cr.mjs");
2
+ //#region node_modules/.nitro/vite/services/ssr/assets/artifactKind-C0oXLA23.js
3
+ var $$splitComponentImporter = () => import("./loops._loopId-CcJ3rxCU.mjs");
4
4
  var Route = createFileRoute("/loops/$loopId")({
5
5
  ssr: false,
6
6
  component: lazyRouteComponent($$splitComponentImporter, "component")
@@ -11,8 +11,8 @@ import { fileURLToPath } from "node:url";
11
11
  import path from "node:path";
12
12
  import os from "node:os";
13
13
  import fs$1 from "node:fs/promises";
14
- //#region node_modules/.nitro/vite/services/ssr/assets/loopTags-Bi7Bm7v8.js
15
- var loopTags_Bi7Bm7v8_exports = /* @__PURE__ */ __exportAll$1({
14
+ //#region node_modules/.nitro/vite/services/ssr/assets/loopTags-CI_aMcqh.js
15
+ var loopTags_CI_aMcqh_exports = /* @__PURE__ */ __exportAll$1({
16
16
  $: () => loopIdsWithSnapshots,
17
17
  $t: () => logger_exports,
18
18
  A: () => enqueueRun,
@@ -217,9 +217,6 @@ var loops = pgTable("loops", {
217
217
  name: text("name").notNull(),
218
218
  tags: text("tags").array().notNull().default(sql`ARRAY[]::text[]`),
219
219
  prompt: text("prompt").notNull(),
220
- statusKeep: text("status_keep").notNull(),
221
- statusNoChange: text("status_no_change").notNull(),
222
- statusBlock: text("status_block").notNull(),
223
220
  /** Configured artifact names, in addition to the always-present MEMORY.md.
224
221
  * See `gateway/loopFiles.ts`. */
225
222
  artifacts: jsonb("artifacts").$type().notNull().default([]),
@@ -283,11 +280,7 @@ var runs = pgTable("runs", {
283
280
  ts: text("ts").notNull(),
284
281
  createdAt: text("created_at").notNull().default(sql`CURRENT_TIMESTAMP::text`),
285
282
  updatedAt: text("updated_at").notNull().default(sql`CURRENT_TIMESTAMP::text`),
286
- status: text("status", { enum: [
287
- "keep",
288
- "no-change",
289
- "block"
290
- ] }),
283
+ status: text("status", { enum: ["ok", "block"] }),
291
284
  message: text("message"),
292
285
  /** Owner-facing reason from the final response's ATTENTION line. Independent
293
286
  * of status: it never pauses the loop. */
@@ -321,7 +314,8 @@ var runs = pgTable("runs", {
321
314
  check("runs_agent_check", sql`${t.agent} IS NULL OR ${t.agent} IN ('claude-code', 'codex', 'pi')`),
322
315
  check("runs_phase_check", sql`${t.phase} IN ('pending', 'running', 'done', 'error', 'canceled')`),
323
316
  check("runs_requested_by_check", sql`${t.requestedBy} IN ('owner', 'system')`),
324
- check("runs_status_check", sql`${t.status} IS NULL OR ${t.status} IN ('keep', 'no-change', 'block')`)
317
+ check("runs_status_check", sql`${t.status} IS NULL OR ${t.status} IN ('ok', 'block')`),
318
+ check("runs_done_status_check", sql`(${t.phase} = 'done') = (${t.status} IS NOT NULL)`)
325
319
  ]);
326
320
  var runLeases = pgTable("run_leases", {
327
321
  tokenHash: text("token_hash").primaryKey(),
@@ -2268,8 +2262,8 @@ function validateLoopTags(value) {
2268
2262
  };
2269
2263
  }
2270
2264
  //#endregion
2271
- //#region node_modules/.nitro/vite/services/ssr/assets/boot-CecCDRoH.js
2272
- var boot_CecCDRoH_exports = /* @__PURE__ */ __exportAll$1({
2265
+ //#region node_modules/.nitro/vite/services/ssr/assets/boot-jtVCf_pN.js
2266
+ var boot_jtVCf_pN_exports = /* @__PURE__ */ __exportAll$1({
2273
2267
  _: () => validOptionalPollString,
2274
2268
  a: () => POLL_HTTP_BODY_FIELDS,
2275
2269
  c: () => MIN_DAEMON_VERSION,
@@ -2372,11 +2366,11 @@ function clipText(s, cap) {
2372
2366
  /** Literal placeholder the daemon replaces with the run's absolute loop-file
2373
2367
  * directory before launch (and exports as an env var of the same name). */
2374
2368
  var LOOP_DIR_PLACEHOLDER = "$PIEVO_LOOP_DIR";
2375
- var STATUS_LINE_RE = /^STATUS:\s*(keep|no-change|block)\.?$/i;
2369
+ var STATUS_LINE_RE = /^STATUS:\s*(ok|block)\.?$/i;
2376
2370
  var ATTENTION_LINE_RE = /^ATTENTION:\s*(.*)$/i;
2377
2371
  /**
2378
- * Deliver the user's prompt unchanged, followed by the status definitions, the
2379
- * loop-file contract, and the final-line status contract. The run index
2372
+ * Deliver the user's prompt unchanged, followed by the loop-file contract and the
2373
+ * final-line status contract. The run index
2380
2374
  * intentionally remains an internal history fact.
2381
2375
  */
2382
2376
  function buildRunTask(loop, previousNotices = []) {
@@ -2384,12 +2378,6 @@ function buildRunTask(loop, previousNotices = []) {
2384
2378
  const notices = previousNotices.length ? `\n\nNotices from the previous run:\n${previousNotices.map((notice) => `- ${notice}`).join("\n")}` : "";
2385
2379
  return `${loop.prompt}
2386
2380
 
2387
- Status definitions:
2388
- - keep: ${loop.statusKeep}
2389
- - no-change: ${loop.statusNoChange}
2390
- - block: ${loop.statusBlock}
2391
- A block pauses the loop until the owner restarts it.
2392
-
2393
2381
  Loop files in ${LOOP_DIR_PLACEHOLDER}:
2394
2382
  ${files.join("\n")}
2395
2383
  A file over its limit is rejected and its previous version kept. Other files in that directory are discarded.${notices}
@@ -2397,7 +2385,9 @@ A file over its limit is rejected and its previous version kept. Other files in
2397
2385
  Be concise in everything you write: lead with what changed or needs action; prefer tables and short lists; no filler or restated instructions.
2398
2386
 
2399
2387
  Your final response is only: a summary of at most five short lines (no headings, no repeated tables or file contents); if the owner should look at something, one line \`ATTENTION: <reason>\`; then exactly one last line:
2400
- STATUS: keep|no-change|block`;
2388
+ STATUS: ok|block
2389
+ - ok: the loop keeps running on schedule. Findings and alerts are ok; flag them with ATTENTION.
2390
+ - block: the loop must stop until the owner acts, because the task says to stop or the next run cannot proceed safely (missing access, broken environment, unsafe next step). Block pauses the loop.`;
2401
2391
  }
2402
2392
  var bareLine = (line) => line.trim().replace(/^[*_`>\s]+|[*_`\s]+$/g, "");
2403
2393
  /**
@@ -2640,7 +2630,6 @@ var LOOP_CONFIG_FIELDS = [
2640
2630
  "model",
2641
2631
  "reasoningEffort",
2642
2632
  "prompt",
2643
- "statusDefinitions",
2644
2633
  "artifacts",
2645
2634
  "enabled"
2646
2635
  ];
@@ -2816,36 +2805,6 @@ function validateSchedule(value) {
2816
2805
  detail: "schedule.mode must be cron|continuous"
2817
2806
  };
2818
2807
  }
2819
- function validateStatusDefinitions(value) {
2820
- const raw = object(value);
2821
- if (!raw) return {
2822
- ok: false,
2823
- detail: "statusDefinitions is required"
2824
- };
2825
- const unknown = Object.keys(raw).filter((key) => ![
2826
- "keep",
2827
- "noChange",
2828
- "block"
2829
- ].includes(key));
2830
- if (unknown.length) return {
2831
- ok: false,
2832
- detail: `statusDefinitions has unknown field(s): ${unknown.join(", ")}`
2833
- };
2834
- const keep = requiredText(raw.keep, "statusDefinitions.keep", true);
2835
- if (!keep.ok) return keep;
2836
- const noChange = requiredText(raw.noChange, "statusDefinitions.noChange", true);
2837
- if (!noChange.ok) return noChange;
2838
- const block = requiredText(raw.block, "statusDefinitions.block", true);
2839
- if (!block.ok) return block;
2840
- return {
2841
- ok: true,
2842
- value: {
2843
- keep: keep.value,
2844
- noChange: noChange.value,
2845
- block: block.value
2846
- }
2847
- };
2848
- }
2849
2808
  function validateArtifactNames(value) {
2850
2809
  if (value === void 0 || value === null) return {
2851
2810
  ok: true,
@@ -2910,18 +2869,10 @@ function scheduleFromLoop(loop) {
2910
2869
  }
2911
2870
  throw new Error(`invariant: loop ${loop.id} has unknown schedule mode: ${String(loop.scheduleMode)}`);
2912
2871
  }
2913
- function statusDefinitionsFromLoop(loop) {
2914
- return {
2915
- keep: loop.statusKeep,
2916
- noChange: loop.statusNoChange,
2917
- block: loop.statusBlock
2918
- };
2919
- }
2920
2872
  function canonicalLoopEnvelope(loop) {
2921
2873
  return {
2922
2874
  ...canonicalLoopSummary(loop),
2923
2875
  prompt: loop.prompt,
2924
- statusDefinitions: statusDefinitionsFromLoop(loop),
2925
2876
  artifacts: loop.artifacts,
2926
2877
  enabled: loop.enabled
2927
2878
  };
@@ -2959,8 +2910,6 @@ function validateLoopCreate(value) {
2959
2910
  if (!prompt.ok) return prompt;
2960
2911
  const schedule = validateSchedule(raw.schedule);
2961
2912
  if (!schedule.ok) return schedule;
2962
- const statusDefinitions = validateStatusDefinitions(raw.statusDefinitions);
2963
- if (!statusDefinitions.ok) return statusDefinitions;
2964
2913
  const artifacts = validateArtifactNames(raw.artifacts);
2965
2914
  if (!artifacts.ok) return artifacts;
2966
2915
  const model = optionalProvider(raw.model, "model");
@@ -2985,7 +2934,6 @@ function validateLoopCreate(value) {
2985
2934
  model: model.value,
2986
2935
  reasoningEffort: reasoningEffort.value,
2987
2936
  prompt: prompt.value,
2988
- statusDefinitions: statusDefinitions.value,
2989
2937
  artifacts: artifacts.value,
2990
2938
  enabled: raw.enabled !== false
2991
2939
  };
@@ -3002,9 +2950,6 @@ function validateLoopCreate(value) {
3002
2950
  model: config.model,
3003
2951
  reasoningEffort: config.reasoningEffort,
3004
2952
  prompt: config.prompt,
3005
- statusKeep: config.statusDefinitions.keep,
3006
- statusNoChange: config.statusDefinitions.noChange,
3007
- statusBlock: config.statusDefinitions.block,
3008
2953
  artifacts: config.artifacts,
3009
2954
  enabled: config.enabled
3010
2955
  }
@@ -3048,13 +2993,6 @@ function validateLoopEdit(loop, value) {
3048
2993
  if (!result.ok) return result;
3049
2994
  Object.assign(update, rowSchedule(result.value, loop.cron));
3050
2995
  }
3051
- if (raw.statusDefinitions !== void 0) {
3052
- const result = validateStatusDefinitions(raw.statusDefinitions);
3053
- if (!result.ok) return result;
3054
- update.statusKeep = result.value.keep;
3055
- update.statusNoChange = result.value.noChange;
3056
- update.statusBlock = result.value.block;
3057
- }
3058
2996
  if (raw.artifacts !== void 0) {
3059
2997
  const result = validateArtifactNames(raw.artifacts);
3060
2998
  if (!result.ok) return result;
@@ -3284,7 +3222,7 @@ function incidentDiagnosis(code, issues, reportId, payloadDigest) {
3284
3222
  recommendedAction
3285
3223
  };
3286
3224
  }
3287
- var MISSING_STATUS_ERROR = "run protocol incomplete: the final response has no \"STATUS: keep|no-change|block\" line";
3225
+ var MISSING_STATUS_ERROR = "run protocol incomplete: the final response has no \"STATUS: ok|block\" line";
3288
3226
  /** The run outcome a terminal report establishes. Only a successful provider
3289
3227
  * exit is read for a status; a successful exit without one is a protocol error. */
3290
3228
  function reportOutcome(body) {
@@ -4356,10 +4294,8 @@ function renderLoopsText(loops, fields) {
4356
4294
  return doc(countLine(loops.length), listBlock("loops", fields, loops.map((l) => fields.map((f) => loopCell(l, f)))), helpBlock(["Run `pievo show <id>` to see a loop's full config", "Run `pievo log <id>` to see a loop's recent runs"]));
4357
4295
  }
4358
4296
  function runResultToken(r) {
4359
- if (r.status === "block") return `block/${r.phase}`;
4360
- if (r.phase === "canceled") return "canceled";
4361
- const base = r.phase === "error" ? "failed" : r.phase === "done" ? "ok" : r.phase;
4362
- return r.status ? `${base}/${r.status}` : `${base}/missing-status`;
4297
+ if (r.phase === "error") return "failed";
4298
+ return r.status ?? r.phase;
4363
4299
  }
4364
4300
  /** Stable JSON with recursively sorted object keys — so two structurally-equal values
4365
4301
  * serialize identically regardless of key ordering (pg `jsonb` normalizes key order). */
@@ -4589,11 +4525,7 @@ var TERMINAL_PHASES = [
4589
4525
  "error",
4590
4526
  "canceled"
4591
4527
  ];
4592
- var STATUSES = [
4593
- "keep",
4594
- "no-change",
4595
- "block"
4596
- ];
4528
+ var STATUSES = ["ok", "block"];
4597
4529
  var LOG_FLAGS = new Set([
4598
4530
  "_",
4599
4531
  "loop",
@@ -4651,7 +4583,7 @@ function parseHistoryFlags(flags) {
4651
4583
  const status = flags.status;
4652
4584
  if (status !== void 0 && (typeof status !== "string" || !STATUSES.includes(status))) return {
4653
4585
  ok: false,
4654
- error: "--status must be keep|no-change|block"
4586
+ error: "--status must be ok|block"
4655
4587
  };
4656
4588
  const phase = flags.phase;
4657
4589
  if (phase !== void 0 && (typeof phase !== "string" || !TERMINAL_PHASES.includes(phase))) return {
@@ -4720,6 +4652,7 @@ function boundedText(value, cap = HISTORY_DETAIL_TEXT_CAP) {
4720
4652
  }
4721
4653
  function normalizedListRun(run) {
4722
4654
  const message = boundedText(run.message ?? null, 500);
4655
+ const error = boundedText(run.error ?? null, 500);
4723
4656
  return {
4724
4657
  runIndex: run.runIndex,
4725
4658
  terminalAt: run.ts,
@@ -4730,6 +4663,8 @@ function normalizedListRun(run) {
4730
4663
  tokenUsage: totalTokenUsage(run.usage ?? null),
4731
4664
  message: message.value,
4732
4665
  messageTruncated: message.truncated,
4666
+ error: error.value,
4667
+ errorTruncated: error.truncated,
4733
4668
  finalTextAvailable: !!run.finalText?.trim()
4734
4669
  };
4735
4670
  }
@@ -4784,6 +4719,7 @@ async function listHistory(loop, q) {
4784
4719
  "durationMs",
4785
4720
  "tokenUsage",
4786
4721
  "message",
4722
+ "error",
4787
4723
  "finalTextAvailable"
4788
4724
  ], rows.map((run) => [
4789
4725
  run.runIndex,
@@ -4794,6 +4730,7 @@ async function listHistory(loop, q) {
4794
4730
  run.durationMs ?? null,
4795
4731
  totalTokenUsage(run.usage ?? null),
4796
4732
  run.message ? truncate(run.message, 500, "use --run for detail").value : null,
4733
+ run.error ? truncate(run.error, 500, "use --run for detail").value : null,
4797
4734
  !!run.finalText?.trim()
4798
4735
  ])) : emptyList("runs");
4799
4736
  return response(doc(`loop: ${scalar(loop.name)} (${loop.id})`, `count: ${rows.length} of ${Number(counted[0]?.n ?? 0)} matching`, table, helpBlock(["Use `pievo log --run <index>` for one run"])));
@@ -5286,7 +5223,7 @@ var CliGateway = class {
5286
5223
  })), scoped.elsewhere, await recentMachineRuns(loops, 3));
5287
5224
  }
5288
5225
  };
5289
- var RUN_HAS_NO_CLI = "pievo commands are not available inside a run; end your final response with a summary and a last line `STATUS: keep|no-change|block`";
5226
+ var RUN_HAS_NO_CLI = "pievo commands are not available inside a run; end your final response with a summary and a last line `STATUS: ok|block`";
5290
5227
  var FILE_USAGE = "pievo file list <loop> | file get <loop> <name> | file set <loop> <name> --from <path>";
5291
5228
  var PAUSED_FINISHING = "loop paused; current run is finishing";
5292
5229
  var STOP_UPGRADE_REQUIRED = "Daemon upgrade required to stop a running process. Run `npm install -g @kky42/pievo@latest`, then `pievo daemon restart`.";
@@ -5356,7 +5293,7 @@ var DEVICE_VERB_HELP = {
5356
5293
  new: {
5357
5294
  syntax: "new --json '<config>' [--dry-run]",
5358
5295
  summary: `create a loop from the canonical envelope (keys: ${[...EDITABLE_LOOP_FIELDS].join(", ")}; agent required)`,
5359
- help: ["Run `pievo new --json '{\"name\":\"Daily check\",\"schedule\":{\"mode\":\"cron\",\"cron\":\"0 8 * * *\",\"timezone\":\"UTC\",\"overlap\":\"skip\"},\"workdir\":\"<path>\",\"agent\":\"claude-code\",\"prompt\":\"Check the project.\",\"statusDefinitions\":{\"keep\":\"result retained\",\"noChange\":\"nothing changed\",\"block\":\"owner input required\"}}'` to create a loop", "Run `pievo new --json '{...}' --dry-run` to validate without creating"]
5296
+ help: ["Run `pievo new --json '{\"name\":\"Daily check\",\"schedule\":{\"mode\":\"cron\",\"cron\":\"0 8 * * *\",\"timezone\":\"UTC\",\"overlap\":\"skip\"},\"workdir\":\"<path>\",\"agent\":\"claude-code\",\"prompt\":\"Check the project.\"}'` to create a loop", "Run `pievo new --json '{...}' --dry-run` to validate without creating"]
5360
5297
  },
5361
5298
  loops: {
5362
5299
  syntax: "loops [--fields a,b] [--json]",
@@ -5404,7 +5341,7 @@ var DEVICE_VERB_HELP = {
5404
5341
  help: ["Run `pievo file get <id> MEMORY.md` to read the loop's memory", "An edit made while a run is executing wins over that run's version of the file"]
5405
5342
  },
5406
5343
  log: {
5407
- syntax: "log [<id>] [--limit 1..20] [--since ISO] [--until ISO] [--status keep|no-change|block] [--phase done|error|canceled] [--run <index|UUID> [--diff]] [--json]",
5344
+ syntax: "log [<id>] [--limit 1..20] [--since ISO] [--until ISO] [--status ok|block] [--phase done|error|canceled] [--run <index|UUID> [--diff]] [--json]",
5408
5345
  summary: "bounded terminal history or one detailed run",
5409
5346
  help: ["Run `pievo log <id> --json` for structured history", "Run `pievo log <id> --run 12 --diff` for bounded run detail and artifact diff"]
5410
5347
  }
@@ -5441,7 +5378,6 @@ function renderShowText(loop, env, totalRuns, lastRun, opts = {}) {
5441
5378
  ["model", env.model == null ? { raw: "default" } : env.model],
5442
5379
  ["reasoningEffort", env.reasoningEffort == null ? { raw: "default" } : env.reasoningEffort],
5443
5380
  ["prompt", contentField(loop.prompt, full)],
5444
- ["statusDefinitions", { raw: JSON.stringify(env.statusDefinitions) }],
5445
5381
  ["artifacts", { raw: JSON.stringify(env.artifacts) }],
5446
5382
  ["enabled", env.enabled]
5447
5383
  ]);
@@ -5727,4 +5663,4 @@ async function getCliGateway() {
5727
5663
  return (await ensureServer()).cliGateway;
5728
5664
  }
5729
5665
  //#endregion
5730
- export { listRuns as A, reconciliationStatesForRuns as B, getRun as C, listArtifacts as D, isOutdated as E, machineIdFromToken as F, stopLoop as G, requestRunCancel as H, machinePresence as I, updateMachine as J, tryDeleteLoop as K, mintDeviceToken as L, loopFileNames as M, loopTags_Bi7Bm7v8_exports as N, listLoops as O, loopsForMachine as P, pauseLoop as R, getMachine as S, hasRunningRun as T, sha256 as U, requestDeleteLoop as V, startLoop as W, validateLoopTags as Y, createMachine as _, canonicalLoopSummary as a, getArtifactFile as b, getLoopFiles as c, validOptionalPollString as d, validPollCurrentRun as f, countRuns as g, CODING_AGENTS as h, canonicalLoopEnvelope as i, listRunsBefore as j, listMachines as k, readByteBody as l, validateLoopEdit as m, POLL_HTTP_BODY_FIELDS as n, daemonNeedsUpdate as o, validPollWireId as p, updateLoop as q, boot_CecCDRoH_exports as r, ensureServer as s, MIN_DAEMON_VERSION as t, readJsonBody as u, forceDeleteLoop as v, hasPendingRun as w, getLoop as x, forceDeleteMachine as y, recentLoopUsage as z };
5666
+ export { listRuns as A, reconciliationStatesForRuns as B, getRun as C, listArtifacts as D, isOutdated as E, machineIdFromToken as F, stopLoop as G, requestRunCancel as H, machinePresence as I, updateMachine as J, tryDeleteLoop as K, mintDeviceToken as L, loopFileNames as M, loopTags_CI_aMcqh_exports as N, listLoops as O, loopsForMachine as P, pauseLoop as R, getMachine as S, hasRunningRun as T, sha256 as U, requestDeleteLoop as V, startLoop as W, validateLoopTags as Y, createMachine as _, canonicalLoopSummary as a, getArtifactFile as b, getLoopFiles as c, validOptionalPollString as d, validPollCurrentRun as f, countRuns as g, CODING_AGENTS as h, canonicalLoopEnvelope as i, listRunsBefore as j, listMachines as k, readByteBody as l, validateLoopEdit as m, POLL_HTTP_BODY_FIELDS as n, daemonNeedsUpdate as o, validPollWireId as p, updateLoop as q, boot_jtVCf_pN_exports as r, ensureServer as s, MIN_DAEMON_VERSION as t, readJsonBody as u, forceDeleteLoop as v, hasPendingRun as w, getLoop as x, forceDeleteMachine as y, recentLoopUsage as z };
@@ -1,8 +1,8 @@
1
- import { C as getRun, G as stopLoop$1, H as requestRunCancel, I as machinePresence, K as tryDeleteLoop, O as listLoops$1, R as pauseLoop$1, S as getMachine, T as hasRunningRun, V as requestDeleteLoop, W as startLoop$1, j as listRunsBefore, k as listMachines, m as validateLoopEdit, q as updateLoop, s as ensureServer, v as forceDeleteLoop, x as getLoop } from "./boot-CecCDRoH.mjs";
2
- import { a as toRunSummaries, i as toLoopSummaries, r as toLoopDetail, t as sortLoopSummariesByRecentRun } from "./loopProjection-Bo54jjGd.mjs";
1
+ import { C as getRun, G as stopLoop$1, H as requestRunCancel, I as machinePresence, K as tryDeleteLoop, O as listLoops$1, R as pauseLoop$1, S as getMachine, T as hasRunningRun, V as requestDeleteLoop, W as startLoop$1, j as listRunsBefore, k as listMachines, m as validateLoopEdit, q as updateLoop, s as ensureServer, v as forceDeleteLoop, x as getLoop } from "./boot-jtVCf_pN.mjs";
2
+ import { a as toRunSummaries, i as toLoopSummaries, r as toLoopDetail, t as sortLoopSummariesByRecentRun } from "./loopProjection-ZNfSmA5e.mjs";
3
3
  import { r as createServerFn } from "./ssr.mjs";
4
4
  import { t as createServerRpc } from "./createServerRpc-BD8Xn_0_.mjs";
5
- //#region node_modules/.nitro/vite/services/ssr/assets/loopApi-uEiBQ5YX.js
5
+ //#region node_modules/.nitro/vite/services/ssr/assets/loopApi-0nR35Kh2.js
6
6
  /**
7
7
  * Server functions backing the dashboard. They run server-side (createServerFn
8
8
  * → RPC) and call the IN-PROCESS scheduler + store directly — the scheduler
@@ -75,7 +75,7 @@ var getArtifacts_createServerFn_handler = createServerRpc({
75
75
  var getArtifacts = createServerFn({ method: "GET" }).validator((d) => d).handler(getArtifacts_createServerFn_handler, async ({ data }) => {
76
76
  await backend();
77
77
  if (!await findLoop(data.loopId)) return [];
78
- const { listLoopArtifacts } = await import("./artifactFiles-DJiK99sF.mjs");
78
+ const { listLoopArtifacts } = await import("./artifactFiles-DLfSRhrV.mjs");
79
79
  return listLoopArtifacts(data.loopId);
80
80
  });
81
81
  var getArtifact_createServerFn_handler = createServerRpc({
@@ -86,7 +86,7 @@ var getArtifact_createServerFn_handler = createServerRpc({
86
86
  var getArtifact = createServerFn({ method: "GET" }).validator((d) => d).handler(getArtifact_createServerFn_handler, async ({ data }) => {
87
87
  await backend();
88
88
  if (!await findLoop(data.loopId)) return { error: "file not found" };
89
- const { readLoopArtifact } = await import("./artifactFiles-DJiK99sF.mjs");
89
+ const { readLoopArtifact } = await import("./artifactFiles-DLfSRhrV.mjs");
90
90
  return readLoopArtifact(data.loopId, data.path);
91
91
  });
92
92
  var getRunDiff_createServerFn_handler = createServerRpc({
@@ -105,7 +105,7 @@ var getRunDiff = createServerFn({ method: "GET" }).validator((d) => d).handler(g
105
105
  hasSnapshot: false,
106
106
  files: []
107
107
  };
108
- const { computeRunDiff } = await import("./boot-CecCDRoH.mjs").then((n) => n.r).then((n) => n.i);
108
+ const { computeRunDiff } = await import("./boot-jtVCf_pN.mjs").then((n) => n.r).then((n) => n.i);
109
109
  return computeRunDiff(data.runId);
110
110
  });
111
111
  var patchLoop_createServerFn_handler = createServerRpc({
@@ -191,7 +191,7 @@ var deleteLoop = createServerFn({ method: "POST" }).validator((id) => id).handle
191
191
  if (!await requestDeleteLoop(id)) return { error: "not found" };
192
192
  if (unreachable) {
193
193
  if (!await forceDeleteLoop(id)) return { error: "delete failed; server data was not deleted" };
194
- const { logger } = await import("./boot-CecCDRoH.mjs").then((n) => n.N).then((n) => n.$t);
194
+ const { logger } = await import("./boot-jtVCf_pN.mjs").then((n) => n.N).then((n) => n.$t);
195
195
  logger.child({ mod: "loop-lifecycle" }).warn({
196
196
  action: "unreachable-delete",
197
197
  loopId: id,
@@ -250,7 +250,7 @@ var mintConnectKey_createServerFn_handler = createServerRpc({
250
250
  }, (opts) => mintConnectKey.__executeServer(opts));
251
251
  var mintConnectKey = createServerFn({ method: "POST" }).handler(mintConnectKey_createServerFn_handler, async () => {
252
252
  await backend();
253
- const { mintDeviceToken, rememberConnectKey } = await import("./boot-CecCDRoH.mjs").then((n) => n.N).then((n) => n.g);
253
+ const { mintDeviceToken, rememberConnectKey } = await import("./boot-jtVCf_pN.mjs").then((n) => n.N).then((n) => n.g);
254
254
  const token = mintDeviceToken();
255
255
  await rememberConnectKey(token);
256
256
  return { token };
@@ -1,5 +1,5 @@
1
- import { A as listRuns, B as reconciliationStatesForRuns, I as machinePresence, S as getMachine, T as hasRunningRun, a as canonicalLoopSummary, g as countRuns, i as canonicalLoopEnvelope, o as daemonNeedsUpdate, t as MIN_DAEMON_VERSION, w as hasPendingRun, z as recentLoopUsage } from "./boot-CecCDRoH.mjs";
2
- //#region node_modules/.nitro/vite/services/ssr/assets/loopProjection-Bo54jjGd.js
1
+ import { A as listRuns, B as reconciliationStatesForRuns, I as machinePresence, S as getMachine, T as hasRunningRun, a as canonicalLoopSummary, g as countRuns, i as canonicalLoopEnvelope, o as daemonNeedsUpdate, t as MIN_DAEMON_VERSION, w as hasPendingRun, z as recentLoopUsage } from "./boot-jtVCf_pN.mjs";
2
+ //#region node_modules/.nitro/vite/services/ssr/assets/loopProjection-ZNfSmA5e.js
3
3
  var SUMMARY_RUNS = 18;
4
4
  var RECENT_USAGE_WINDOW_MS = 10080 * 60 * 1e3;
5
5
  /** Dashboard order: loops with runs first, most recent run first. The incoming