@coreplane/switchboard 1.260.5 → 1.260.6

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 (34) hide show
  1. package/dist/assets/deploy/cloudflare-memory/worker.ts +17 -3
  2. package/dist/assets/package-lock.json +3 -3
  3. package/dist/assets/package.json +1 -1
  4. package/dist/assets/source.json +3 -3
  5. package/dist/assets/src/core/budgets.ts +5 -0
  6. package/dist/assets/src/core/coordinator/driver.ts +43 -6
  7. package/dist/assets/src/core/refusal.ts +1 -1
  8. package/dist/assets/src/core/runLedger/decisions.ts +10 -1
  9. package/dist/assets/src/core/runLedger/types.ts +3 -0
  10. package/dist/assets/src/core/ship/coordinator.ts +29 -6
  11. package/dist/assets/web/dist/.vite/manifest.json +67 -67
  12. package/dist/assets/web/dist/assets/{DeliveryPage-Cf1joUyA.js → DeliveryPage-BUJckSuW.js} +1 -1
  13. package/dist/assets/web/dist/assets/{HomePage-DZEAnCCv.js → HomePage-CBQpcnaW.js} +1 -1
  14. package/dist/assets/web/dist/assets/{PendingTurnRow-4B8JwETU.js → PendingTurnRow-DIC86uWA.js} +1 -1
  15. package/dist/assets/web/dist/assets/{PlanePage-CHU2szQs.js → PlanePage-CfrbMh8t.js} +1 -1
  16. package/dist/assets/web/dist/assets/{ResidentDetailPage-L5SRcN_O.js → ResidentDetailPage-C-SgOUTl.js} +1 -1
  17. package/dist/assets/web/dist/assets/{ResidentsIndexPage-BIFf8qyE.js → ResidentsIndexPage-CiDhvXok.js} +1 -1
  18. package/dist/assets/web/dist/assets/{RunFoldRow-DzPIshJx.js → RunFoldRow-DZ8huwUU.js} +1 -1
  19. package/dist/assets/web/dist/assets/{RunRoutePage-Cru5IVux.js → RunRoutePage-Cp6wicYc.js} +3 -3
  20. package/dist/assets/web/dist/assets/{RunsIndexPage-CBkdPAdj.js → RunsIndexPage-BPXtfwwx.js} +1 -1
  21. package/dist/assets/web/dist/assets/{ScheduledPage-D_R55BDk.js → ScheduledPage-DbvP48HI.js} +1 -1
  22. package/dist/assets/web/dist/assets/{SettingsPage-DlmZvAvf.js → SettingsPage-B87lZaiN.js} +1 -1
  23. package/dist/assets/web/dist/assets/{SilentTurn-PWMDMbMG.js → SilentTurn-CPED_XCV.js} +1 -1
  24. package/dist/assets/web/dist/assets/{StatusDot-Bq0mYMFo.js → StatusDot-CFLn-DZ2.js} +1 -1
  25. package/dist/assets/web/dist/assets/{Tooltip-Bs6zd7yE.js → Tooltip-Dx9YBVEx.js} +1 -1
  26. package/dist/assets/web/dist/assets/{UnitRoutePage-BMGEZCvn.js → UnitRoutePage-d4A2X_o7.js} +1 -1
  27. package/dist/assets/web/dist/assets/budgets-BQgcCyvb.js +1 -0
  28. package/dist/assets/web/dist/assets/{dist-EkKVbIM-.js → dist-Cn51vWpw.js} +1 -1
  29. package/dist/assets/web/dist/assets/{indexRow-5s3hNzZ9.js → indexRow-BsWcHHVh.js} +1 -1
  30. package/dist/assets/web/dist/assets/{main-Disot0n_.js → main-DYwRHh0F.js} +2 -2
  31. package/dist/assets/web/dist/assets/{sseReplay-9gcMpylx.js → sseReplay-DGRDRLua.js} +1 -1
  32. package/dist/cli.js +728 -556
  33. package/package.json +1 -1
  34. package/dist/assets/web/dist/assets/budgets-0szUBIMv.js +0 -1
package/dist/cli.js CHANGED
@@ -597,7 +597,7 @@ function fit(pipeline) {
597
597
  const need = ALLOWANCES.provision + ASKS.coding + reserveMinutes({ kind: "coding", index: 0 }, pipeline);
598
598
  return { ok: pipeline.maxMinutes >= need, need, have: pipeline.maxMinutes };
599
599
  }
600
- var SECOND_MS, secondsToMs, MINUTE_MS, minutesToMs, DAY_MS, WEEK_MS, CONFIRMATION_TTL_MS, QUESTION_TTL_MS, AUTHOR_BINDING_TTL_MS, FIRST_ATTACH_WAIT_MS, ATTACH_REQUEST_MIN_MS, HARNESS_PROBE_WAIT_MS, DRAIN, INTAKE_WINDOW_MAX_MS, INTAKE_RECOVERY_WINDOW_MS, INTAKE_DELIVERY_CLAIM_MS, LOOP_PRESETS, ASKS, PRESET_FLOORS, FLOORS, PULL_SWEEP, PROVIDER_RETRY_BACKOFFS_MS, MODEL_STREAM_HEARTBEAT_MS, HOSTED_DEADLINE_MARGIN_MINUTES, SHIP_WAIT, RESTART_CLAIM_GRACE_MS, PLANE, PACE_WINDOW_MINUTES, ALLOWANCES, POST_STEP_MINUTES, WRAP_UP_WARNING, SANDBOX_CREDENTIAL_WRITE_TIMEOUT_MS, BASH_COMMAND, RUNAWAY_TURNS_PER_MINUTE, DEFAULT_GRANT, GRANT_RENEWALS_MAX, STRUCTURED_RETRIES_MAX, IDLE_DAYS_DEFAULT, IDLE_DAYS_MAX, IDLE_WAKES_MAX;
600
+ var SECOND_MS, secondsToMs, MINUTE_MS, minutesToMs, DAY_MS, WEEK_MS, CONFIRMATION_TTL_MS, QUESTION_TTL_MS, AUTHOR_BINDING_TTL_MS, FIRST_ATTACH_WAIT_MS, ATTACH_REQUEST_MIN_MS, HARNESS_PROBE_WAIT_MS, DRAIN, INTAKE_WINDOW_MAX_MS, INTAKE_RECOVERY_WINDOW_MS, INTAKE_DELIVERY_CLAIM_MS, LOOP_PRESETS, ASKS, PRESET_FLOORS, FLOORS, PULL_SWEEP, PROVIDER_RETRY_BACKOFFS_MS, MODEL_STREAM_HEARTBEAT_MS, HOSTED_DEADLINE_MARGIN_MINUTES, SHIP_WAIT, SHIP_RECORD_VISIBILITY, RESTART_CLAIM_GRACE_MS, PLANE, PACE_WINDOW_MINUTES, ALLOWANCES, POST_STEP_MINUTES, WRAP_UP_WARNING, SANDBOX_CREDENTIAL_WRITE_TIMEOUT_MS, BASH_COMMAND, RUNAWAY_TURNS_PER_MINUTE, DEFAULT_GRANT, GRANT_RENEWALS_MAX, STRUCTURED_RETRIES_MAX, IDLE_DAYS_DEFAULT, IDLE_DAYS_MAX, IDLE_WAKES_MAX;
601
601
  var init_budgets = __esm({
602
602
  "../../src/core/budgets.ts"() {
603
603
  "use strict";
@@ -676,6 +676,7 @@ var init_budgets = __esm({
676
676
  MODEL_STREAM_HEARTBEAT_MS = 15e3;
677
677
  HOSTED_DEADLINE_MARGIN_MINUTES = 60;
678
678
  SHIP_WAIT = { marginMinutes: 5, chunkMinutes: 5, mergeChunkMinutes: 5, busyRetryMinutes: 2 };
679
+ SHIP_RECORD_VISIBILITY = { retries: 3, retryMs: secondsToMs(1) };
679
680
  RESTART_CLAIM_GRACE_MS = minutesToMs(SHIP_WAIT.chunkMinutes);
680
681
  PLANE = {
681
682
  recentMinutes: 60,
@@ -15400,7 +15401,7 @@ var init_refusal = __esm({
15400
15401
  repo_not_onboarded: "request",
15401
15402
  repo_access: "policy",
15402
15403
  pr_head_unknown: "system",
15403
- branch_moved: "system",
15404
+ workspace_head_mismatch: "system",
15404
15405
  coordinator_thread_live: "system",
15405
15406
  live_agent_allowlist: "policy",
15406
15407
  follow_up_refused: "request",
@@ -29134,6 +29135,505 @@ var init_llmOutput = __esm({
29134
29135
  }
29135
29136
  });
29136
29137
 
29138
+ // ../../src/core/dispatch/handBack.ts
29139
+ function renderHandBackLine(line4) {
29140
+ return `${HAND_BACK_PREFIX}
29141
+ \`${line4}\``;
29142
+ }
29143
+ var HAND_BACK_PREFIX;
29144
+ var init_handBack = __esm({
29145
+ "../../src/core/dispatch/handBack.ts"() {
29146
+ "use strict";
29147
+ HAND_BACK_PREFIX = "To run this:";
29148
+ }
29149
+ });
29150
+
29151
+ // ../../src/core/statusCardFrame.ts
29152
+ function activityText(activity) {
29153
+ if (!activity) return void 0;
29154
+ if (activity.kind === "line") return activity.text;
29155
+ return `\u2192 $ ${activity.command.replace(/\s+/g, " ").trim()}`;
29156
+ }
29157
+ function createCardShell(opts) {
29158
+ const verbosity2 = opts.verbosity ?? DEFAULT_VERBOSITY;
29159
+ const notes = [];
29160
+ let link = opts.link;
29161
+ let frame2 = 0;
29162
+ let finishedAt;
29163
+ let setupLabel;
29164
+ const lead = opts.lead ?? [];
29165
+ const base = () => opts.model !== void 0 && shows(verbosity2, "verbose") ? `${opts.label} on \`${opts.model}\`` : opts.label;
29166
+ const label = () => [base(), ...notes.filter((n2) => shows(verbosity2, n2.level)).map((n2) => n2.text)].join(" \xB7 ");
29167
+ const elapsed2 = () => formatDuration((finishedAt ?? opts.now()) - opts.startedAt, "clock");
29168
+ const headline = (icon) => `${icon} ${label()} \xB7 ${elapsed2()}`;
29169
+ const closeDetail = (close, own) => [...shows(verbosity2, "debug") ? [close.shape, close.queued] : [], own].filter(Boolean).join("\n") || void 0;
29170
+ return {
29171
+ get label() {
29172
+ return label();
29173
+ },
29174
+ note(level, text) {
29175
+ notes.push({ level, text });
29176
+ },
29177
+ setLink(next) {
29178
+ link = next;
29179
+ },
29180
+ freeze(at) {
29181
+ finishedAt = at;
29182
+ },
29183
+ setSetupLabel(next) {
29184
+ setupLabel = next;
29185
+ },
29186
+ ack() {
29187
+ const detail = lead.join("\n");
29188
+ return { title: `\u{1F440} ${label()} \xB7 preparing workspace\u2026`, ...detail ? { detail } : {} };
29189
+ },
29190
+ live(parts = {}) {
29191
+ const glyph = SPINNER_GLYPHS[frame2++ % SPINNER_GLYPHS.length];
29192
+ const detail = [...lead, ...parts.detail ?? []].filter(Boolean).join("\n");
29193
+ return {
29194
+ title: headline(glyph) + (setupLabel ? ` \u2014 ${setupLabel}` : "") + (parts.suffix ?? "") + (parts.notice ? ` \xB7 ${parts.notice}` : ""),
29195
+ detail: detail || void 0,
29196
+ ...parts.activity ? { activity: parts.activity } : {},
29197
+ link
29198
+ };
29199
+ },
29200
+ close(close) {
29201
+ const detail = closeDetail(close, close.kind === "done" ? close.detail : void 0);
29202
+ switch (close.kind) {
29203
+ case "done":
29204
+ return { title: headline(close.icon), detail, link };
29205
+ case "not_started":
29206
+ return { title: `${close.icon} ${label()} \xB7 not started (${close.reason}) \xB7 ${elapsed2()}`, detail };
29207
+ case "refused":
29208
+ return { title: `${close.icon} ${label()} \xB7 ${close.reason} \xB7 ${elapsed2()}`, detail };
29209
+ case "setup_failed":
29210
+ return { title: `\u274C setup failed \xB7 ${close.reason} \xB7 ${elapsed2()}`, detail };
29211
+ }
29212
+ }
29213
+ };
29214
+ }
29215
+ var SPINNER_GLYPHS, LIVE_CARD_PREFIXES, ROUTE_REASON_PREFIX;
29216
+ var init_statusCardFrame = __esm({
29217
+ "../../src/core/statusCardFrame.ts"() {
29218
+ "use strict";
29219
+ init_formatDuration();
29220
+ init_verbosity();
29221
+ SPINNER_GLYPHS = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
29222
+ LIVE_CARD_PREFIXES = [...SPINNER_GLYPHS, "\u{1F440}"];
29223
+ ROUTE_REASON_PREFIX = "route reason:";
29224
+ }
29225
+ });
29226
+
29227
+ // ../../src/core/confirmations.ts
29228
+ import { randomUUID } from "node:crypto";
29229
+ import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "node:fs";
29230
+ import { dirname as dirname10, resolve as resolve9 } from "node:path";
29231
+ function newConfirmationId() {
29232
+ return randomUUID();
29233
+ }
29234
+ function renderOffer(offer) {
29235
+ if (offer.question) return `${offer.question.text}
29236
+ Did you mean:
29237
+ \`${offer.line}\`
29238
+
29239
+ ${offer.question.evidence}`;
29240
+ return [offer.line, ...offer.risk ? [offer.risk] : []].join("\n");
29241
+ }
29242
+ function confirmationMessageOf(msg) {
29243
+ const { images: _images, documents: _documents, staged: _staged, ...kept } = msg;
29244
+ return kept;
29245
+ }
29246
+ function isRecord3(v) {
29247
+ return typeof v === "object" && v !== null && !Array.isArray(v);
29248
+ }
29249
+ function isMessage(v) {
29250
+ return isRecord3(v) && typeof v.channelId === "string" && typeof v.userId === "string" && typeof v.threadKey === "string" && typeof v.text === "string";
29251
+ }
29252
+ function isRunShape(v) {
29253
+ return typeof v.id === "string" && isMessage(v.message) && typeof v.command === "string" && isRecord3(v.input) && typeof v.receipt === "string" && typeof v.risk === "string" && typeof v.model === "string";
29254
+ }
29255
+ function isRedispatchShape(v) {
29256
+ return typeof v.id === "string" && isMessage(v.message) && typeof v.line === "string" && typeof v.evidence === "string" && typeof v.code === "string";
29257
+ }
29258
+ function parsePendingConfirmation(v) {
29259
+ if (!isRecord3(v)) return void 0;
29260
+ if (v.kind === "redispatch")
29261
+ return isRedispatchShape(v) ? v : void 0;
29262
+ if (v.kind !== void 0 && v.kind !== "run") return void 0;
29263
+ return isRunShape(v) ? { ...v, kind: "run" } : void 0;
29264
+ }
29265
+ function parseConfirmation(v) {
29266
+ if (!isRecord3(v) || typeof v.expiresAt !== "number") return void 0;
29267
+ const pending2 = parsePendingConfirmation(v);
29268
+ return pending2 ? { ...pending2, expiresAt: v.expiresAt } : void 0;
29269
+ }
29270
+ function isRefusal(v) {
29271
+ return typeof v === "string" && CONFIRMATION_REFUSALS.includes(v);
29272
+ }
29273
+ function judge2(rows, id, actorIds, now, kind) {
29274
+ const row2 = rows.get(id);
29275
+ if (!row2) return { ok: false, refused: "used" };
29276
+ if (kind === "consume" && row2.expiresAt <= now) {
29277
+ rows.delete(id);
29278
+ return { ok: false, refused: "expired", row: row2 };
29279
+ }
29280
+ if (!actorIds.includes(row2.message.userId))
29281
+ return kind === "consume" ? { ok: false, refused: "foreign", row: row2 } : { ok: false, refused: "foreign" };
29282
+ rows.delete(id);
29283
+ return kind === "consume" ? { ok: true, row: row2 } : { ok: true };
29284
+ }
29285
+ function replaceThreadRow(rows, row2) {
29286
+ for (const [id, r] of rows) if (r.message.threadKey === row2.message.threadKey) rows.delete(id);
29287
+ rows.set(row2.id, row2);
29288
+ }
29289
+ function threadRowId(rows, threadKey) {
29290
+ for (const [id, r] of rows) if (r.message.threadKey === threadKey) return id;
29291
+ return void 0;
29292
+ }
29293
+ function buildConfirmationStore(config, secrets, opts) {
29294
+ const worker = config.config.runtimeOverrides?.worker;
29295
+ if (!worker) return new FileConfirmationStore(opts.path);
29296
+ const tokenEnv = worker.tokenEnv ?? "MEMORY_TOKEN";
29297
+ const token2 = secrets.named(tokenEnv);
29298
+ if (!token2) throw new Error(`runtimeOverrides.worker is configured but ${tokenEnv} is not set`);
29299
+ return new WorkerConfirmationStore({
29300
+ baseUrl: worker.baseUrl,
29301
+ token: token2.reveal(),
29302
+ ...opts.fetch ? { fetch: opts.fetch } : {}
29303
+ });
29304
+ }
29305
+ var CONFIRMATION_REFUSALS, UNSHOWABLE_LINE, STORE_UNREACHABLE_LINE, FileConfirmationStore, CONFIRMATION_WORKER_TIMEOUT_MS, WorkerConfirmationStore;
29306
+ var init_confirmations = __esm({
29307
+ "../../src/core/confirmations.ts"() {
29308
+ "use strict";
29309
+ init_clock();
29310
+ CONFIRMATION_REFUSALS = ["used", "expired", "foreign"];
29311
+ UNSHOWABLE_LINE = "this command carries a value that cannot be shown, so no confirmation can be offered; nothing ran";
29312
+ STORE_UNREACHABLE_LINE = "this command needs a confirmation click, and the confirmation store could not be reached; nothing ran \u2014 ask again for the button";
29313
+ FileConfirmationStore = class {
29314
+ path;
29315
+ clock;
29316
+ constructor(path, opts = {}) {
29317
+ this.path = resolve9(path);
29318
+ this.clock = opts.clock ?? systemClock;
29319
+ }
29320
+ read() {
29321
+ const rows = /* @__PURE__ */ new Map();
29322
+ if (!existsSync12(this.path)) return rows;
29323
+ const raw = JSON.parse(readFileSync14(this.path, "utf8"));
29324
+ for (const v of Array.isArray(raw.confirmations) ? raw.confirmations : []) {
29325
+ const row2 = parseConfirmation(v);
29326
+ if (row2) rows.set(row2.id, row2);
29327
+ }
29328
+ return rows;
29329
+ }
29330
+ write(rows) {
29331
+ mkdirSync9(dirname10(this.path), { recursive: true });
29332
+ writeFileSync8(this.path, JSON.stringify({ confirmations: [...rows.values()] }, null, 2));
29333
+ }
29334
+ async put(row2, ttlMs) {
29335
+ const rows = this.read();
29336
+ const stored = { ...row2, expiresAt: this.clock() + ttlMs };
29337
+ replaceThreadRow(rows, stored);
29338
+ this.write(rows);
29339
+ return stored;
29340
+ }
29341
+ async consume(id, actorIds) {
29342
+ const rows = this.read();
29343
+ const out = judge2(rows, id, actorIds, this.clock(), "consume");
29344
+ this.write(rows);
29345
+ return out;
29346
+ }
29347
+ async cancel(id, actorIds) {
29348
+ const rows = this.read();
29349
+ const out = judge2(rows, id, actorIds, this.clock(), "cancel");
29350
+ this.write(rows);
29351
+ return out;
29352
+ }
29353
+ async cancelByThread(threadKey, actorIds) {
29354
+ const rows = this.read();
29355
+ const id = threadRowId(rows, threadKey);
29356
+ if (id === void 0) return { ok: false, refused: "used" };
29357
+ const out = judge2(rows, id, actorIds, this.clock(), "cancel");
29358
+ this.write(rows);
29359
+ return out;
29360
+ }
29361
+ async pendingByThread(threadKey) {
29362
+ const rows = this.read();
29363
+ const id = threadRowId(rows, threadKey);
29364
+ const row2 = id === void 0 ? void 0 : rows.get(id);
29365
+ if (!row2 || row2.expiresAt <= this.clock()) return void 0;
29366
+ return row2;
29367
+ }
29368
+ describe() {
29369
+ return `file ${this.path}`;
29370
+ }
29371
+ };
29372
+ CONFIRMATION_WORKER_TIMEOUT_MS = 8e3;
29373
+ WorkerConfirmationStore = class {
29374
+ constructor(opts) {
29375
+ this.opts = opts;
29376
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
29377
+ this.fetchImpl = opts.fetch ?? fetch;
29378
+ }
29379
+ opts;
29380
+ baseUrl;
29381
+ fetchImpl;
29382
+ async put(row2, ttlMs) {
29383
+ const body = await this.post("/config/confirmations/put", {
29384
+ id: row2.id,
29385
+ threadKey: row2.message.threadKey,
29386
+ requester: row2.message.userId,
29387
+ body: row2,
29388
+ ttlMs
29389
+ });
29390
+ if (typeof body.expiresAt !== "number")
29391
+ throw new Error("confirmation store answered a put without the expiry it stamped");
29392
+ return { ...row2, expiresAt: body.expiresAt };
29393
+ }
29394
+ async consume(id, actorIds) {
29395
+ const body = await this.post("/config/confirmations/consume", { id, actorIds });
29396
+ const stored = isRecord3(body.row) ? body.row : void 0;
29397
+ const row2 = parseConfirmation(
29398
+ stored && isRecord3(stored.body) ? { ...stored.body, expiresAt: stored.expiresAt } : void 0
29399
+ );
29400
+ if (isRefusal(body.refused))
29401
+ return { ok: false, refused: body.refused, ...row2 ? { row: row2 } : {} };
29402
+ if (!row2) throw new Error("confirmation store answered a consume outside its contract");
29403
+ return { ok: true, row: row2 };
29404
+ }
29405
+ async cancel(id, actorIds) {
29406
+ const body = await this.post("/config/confirmations/cancel", { id, actorIds });
29407
+ if (body.ok === true) return { ok: true };
29408
+ if (body.refused === "used" || body.refused === "foreign") return { ok: false, refused: body.refused };
29409
+ throw new Error("confirmation store answered a cancel outside its contract");
29410
+ }
29411
+ async cancelByThread(threadKey, actorIds) {
29412
+ const body = await this.post("/config/confirmations/cancel-by-thread", { threadKey, actorIds });
29413
+ if (body.ok === true) return { ok: true };
29414
+ if (body.refused === "used" || body.refused === "foreign") return { ok: false, refused: body.refused };
29415
+ throw new Error("confirmation store answered a cancel-by-thread outside its contract");
29416
+ }
29417
+ async pendingByThread(threadKey) {
29418
+ const body = await this.post("/config/confirmations/pending-by-thread", { threadKey });
29419
+ if (body.row === null) return void 0;
29420
+ const stored = isRecord3(body.row) ? body.row : void 0;
29421
+ const row2 = parseConfirmation(
29422
+ stored && isRecord3(stored.body) ? { ...stored.body, expiresAt: stored.expiresAt } : void 0
29423
+ );
29424
+ if (!row2) throw new Error("confirmation store answered a pending-by-thread outside its contract");
29425
+ return row2;
29426
+ }
29427
+ describe() {
29428
+ return `state Worker ${this.baseUrl} (ConfigDO confirmations)`;
29429
+ }
29430
+ async post(path, payload2) {
29431
+ let res;
29432
+ try {
29433
+ res = await this.fetchImpl(`${this.baseUrl}${path}`, {
29434
+ method: "POST",
29435
+ headers: { authorization: `Bearer ${this.opts.token}`, "content-type": "application/json" },
29436
+ body: JSON.stringify(payload2),
29437
+ signal: AbortSignal.timeout(CONFIRMATION_WORKER_TIMEOUT_MS)
29438
+ });
29439
+ } catch (err2) {
29440
+ throw new Error(`confirmation store unreachable: ${err2 instanceof Error ? err2.message : String(err2)}`, {
29441
+ cause: err2
29442
+ });
29443
+ }
29444
+ if (!res.ok) throw new Error(`confirmation store answered HTTP ${res.status} on ${path}`);
29445
+ const body = await res.json().catch(() => void 0);
29446
+ if (!isRecord3(body)) throw new Error(`confirmation store returned a non-JSON body on ${path}`);
29447
+ return body;
29448
+ }
29449
+ };
29450
+ }
29451
+ });
29452
+
29453
+ // ../../src/core/dispatch/route.ts
29454
+ function outputCapWithReasoning(visibleAnswerTokens, opts = {}) {
29455
+ return opts.capField !== void 0 && REASONING_COUNTING_CAP_FIELDS.has(opts.capField) ? visibleAnswerTokens + REASONING_OUTPUT_TOKEN_ALLOWANCE : visibleAnswerTokens;
29456
+ }
29457
+ function outputCapRetry(current) {
29458
+ return Math.max(current * 2, REASONING_OUTPUT_TOKEN_ALLOWANCE);
29459
+ }
29460
+ function routedRunsAtOnce(def, confirm, input) {
29461
+ const radius = input === void 0 ? blastRadius(def) : boundBlastRadius(def, input);
29462
+ return radius === "read" || CONFIRM_ORDER[radius] < CONFIRM_ORDER[confirm];
29463
+ }
29464
+ function routeReceipt(def, input) {
29465
+ return redactAndCap(chatInvocation(def, input), ROUTE_RECEIPT_CAP);
29466
+ }
29467
+ function routablePresets() {
29468
+ return Object.values(AGENTS).filter((a) => a.routable !== false).map(({ name, description, machine, identity: identity2, maxMinutes }) => ({
29469
+ name,
29470
+ description,
29471
+ machine,
29472
+ identity: identity2,
29473
+ maxMinutes
29474
+ }));
29475
+ }
29476
+ function routableCommands(commands) {
29477
+ return commands.list().filter((cmd) => CommandRegistry.exposedTo(cmd, "chat")).map((cmd) => ({
29478
+ id: cmd.id,
29479
+ effect: cmd.effect,
29480
+ def: cmd,
29481
+ tool: { name: mcpToolName(cmd.id), description: cmd.describe, inputSchema: jsonSchemaFor(cmd) }
29482
+ }));
29483
+ }
29484
+ function renderPresetTable(presets) {
29485
+ const rows = presets.map(
29486
+ (p) => `| \`${p.name}\` | ${oneLine(p.description)} | ${p.machine} | ${p.identity} | ${p.maxMinutes} min |`
29487
+ );
29488
+ return ["| name | what it does | machine | credential | budget |", "|---|---|---|---|---|", ...rows].join("\n");
29489
+ }
29490
+ function quoteRequest(text) {
29491
+ const cap = 2e3;
29492
+ const bent = text.replace(/<(\/?)request>/gi, "\u2039$1request\u203A");
29493
+ if (bent.length <= cap) return bent;
29494
+ return `${bent.slice(0, cap)}
29495
+ \u2026[truncated: ${bent.length - cap} more characters]`;
29496
+ }
29497
+ function providerStructuredModel(provider, model, opts = {}) {
29498
+ const forced = (opts.answer ?? "tool") === "tool";
29499
+ return async (prompt, call2) => {
29500
+ const tools = [prompt.tool, ...prompt.tools ?? []];
29501
+ const toolChoice = prompt.open ? void 0 : tools.length > 1 ? { type: "any" } : { type: "tool", name: prompt.tool.name };
29502
+ const messages = [
29503
+ { role: "user", content: [{ type: "text", text: prompt.user }] },
29504
+ ...(prompt.retries ?? []).flatMap((r) => [
29505
+ { role: "assistant", content: [{ type: "text", text: r.answer }] },
29506
+ { role: "user", content: [{ type: "text", text: r.violation }] }
29507
+ ])
29508
+ ];
29509
+ const result = await provider.complete({
29510
+ model,
29511
+ system: prompt.system,
29512
+ messages,
29513
+ maxTokens: call2.maxTokens,
29514
+ signal: call2.signal,
29515
+ // The caller's configured effort, card-decided (`turnEffort`): intake's
29516
+ // `intake.effort` or the operator's `defaults.efforts.general`. Absent →
29517
+ // the model's own default.
29518
+ ...opts.effort ? { effort: opts.effort.effort, effortWord: opts.effort.effortWord } : {},
29519
+ ...forced ? { tools, toolChoice } : {}
29520
+ });
29521
+ if (result.stopReason === "max_tokens") throw new OutputCapError(call2.maxTokens);
29522
+ const calls = result.content.filter(
29523
+ (p) => p.type === "tool_use"
29524
+ );
29525
+ if (calls.length > 1) throw new MultiToolCallError(calls.map((c) => ({ tool: c.name, input: c.input })));
29526
+ if (calls.length === 1) return { tool: calls[0].name, input: calls[0].input };
29527
+ return result.content.filter((p) => p.type === "text").map((p) => p.text).join("");
29528
+ };
29529
+ }
29530
+ async function mintConfirmationOffer(args) {
29531
+ const { io, store, msg, origin, def, input, receipt, model } = args;
29532
+ if (!io.offer || !store) return { kind: "no_click" };
29533
+ const line4 = chatInvocation(def, input);
29534
+ if (redactSecrets(line4) !== line4) return { kind: "unshowable" };
29535
+ const risk = def.annotations?.risk?.(input, origin) ?? "";
29536
+ let row2;
29537
+ try {
29538
+ row2 = await store.put(
29539
+ {
29540
+ kind: "run",
29541
+ id: newConfirmationId(),
29542
+ message: confirmationMessageOf(msg),
29543
+ command: def.id,
29544
+ input,
29545
+ receipt,
29546
+ risk,
29547
+ model
29548
+ },
29549
+ CONFIRMATION_TTL_MS
29550
+ );
29551
+ } catch (err2) {
29552
+ console.warn(
29553
+ `[route] ${msg.threadKey} confirmation store unreachable at mint, handing back: ${err2 instanceof Error ? err2.message : String(err2)}`
29554
+ );
29555
+ return { kind: "store_unreachable" };
29556
+ }
29557
+ return { kind: "offered", shown: { id: row2.id, line: line4, risk, expiresAt: row2.expiresAt } };
29558
+ }
29559
+ function redactedInput(input) {
29560
+ const text = (s) => redactAndCap(redactSecrets(s), 200);
29561
+ const leaf = (v) => {
29562
+ if (typeof v === "string") return text(v);
29563
+ if (typeof v === "number" || typeof v === "boolean" || v === null) return v;
29564
+ return v === void 0 ? null : text(JSON.stringify(v) ?? String(v));
29565
+ };
29566
+ const leafOrList = (v) => Array.isArray(v) ? v.map(leaf) : leaf(v);
29567
+ const isRecord11 = (v) => typeof v === "object" && v !== null && (Object.getPrototypeOf(v) === Object.prototype || Object.getPrototypeOf(v) === null);
29568
+ const entries = (v, of) => Object.fromEntries(
29569
+ Object.entries(v).filter(([, x]) => x !== void 0).map(([k, x]) => [k, of(x)])
29570
+ );
29571
+ const object1 = (v) => entries(v, leafOrList);
29572
+ const object2 = (v) => entries(v, (x) => isRecord11(x) ? object1(x) : leafOrList(x));
29573
+ const object3 = (v) => entries(v, (x) => isRecord11(x) ? object2(x) : leafOrList(x));
29574
+ return {
29575
+ ...input.args ? { args: input.args.map(leaf) } : {},
29576
+ ...input.options ? { options: object3(input.options) } : {}
29577
+ };
29578
+ }
29579
+ function routeReasonLabel(reason2, collapsed) {
29580
+ return `${ROUTE_REASON_PREFIX} ${reason2}${collapsed ? ` (compound collapsed: ${collapsed.presets.join("+")})` : ""}`;
29581
+ }
29582
+ function routedPartLines(parts) {
29583
+ return parts.map((p) => {
29584
+ const line4 = p.text.replace(/\s+/g, " ").trim();
29585
+ return `${p.preset}: ${line4.length > ROUTE_PART_LINE_CAP ? `${line4.slice(0, ROUTE_PART_LINE_CAP - 1)}\u2026` : line4}`;
29586
+ });
29587
+ }
29588
+ function compoundBrief(text, parts) {
29589
+ return [
29590
+ text,
29591
+ "",
29592
+ `${COMPOUND_BRIEF_HEADING}: ${parts.length} independent parts. Spawn exactly these children \u2014 one \`spawn_run\` per part, on the preset named, with the part's text as the child's whole prompt (add the repository where the preset needs one) \u2014 then \`await_runs\` them all and compile one answer. Do not merge, drop or add a part.`,
29593
+ ...parts.map((p, i) => `${i + 1}. \`${p.preset}\`: ${p.text}`)
29594
+ ].join("\n");
29595
+ }
29596
+ var REASONING_COUNTING_CAP_FIELDS, REASONING_OUTPUT_TOKEN_ALLOWANCE, OutputCapError, ROUTE_REASON_CAP, ROUTE_MIN_OUTPUT_TOKENS, ROUTE_TIMEOUT_MS, ROUTE_PART_LINE_CAP, ROUTE_RECEIPT_CAP, ROUTED_RECEIPT_PREFIX, COMPOUND_BRIEF_HEADING, MultiToolCallError;
29597
+ var init_route = __esm({
29598
+ "../../src/core/dispatch/route.ts"() {
29599
+ "use strict";
29600
+ init_registry();
29601
+ init_handBack();
29602
+ init_profile();
29603
+ init_redact();
29604
+ init_statusCardFrame();
29605
+ init_commandRegistry();
29606
+ init_commandSurface();
29607
+ init_budgets();
29608
+ init_confirmations();
29609
+ REASONING_COUNTING_CAP_FIELDS = /* @__PURE__ */ new Set(["max_tokens", "max_completion_tokens", "max_output_tokens"]);
29610
+ REASONING_OUTPUT_TOKEN_ALLOWANCE = 4096;
29611
+ OutputCapError = class extends Error {
29612
+ constructor(maxTokens) {
29613
+ super(`answer cut at the output cap (${maxTokens} tokens)`);
29614
+ this.maxTokens = maxTokens;
29615
+ this.name = "OutputCapError";
29616
+ }
29617
+ maxTokens;
29618
+ };
29619
+ ROUTE_REASON_CAP = 120;
29620
+ ROUTE_MIN_OUTPUT_TOKENS = 200;
29621
+ ROUTE_TIMEOUT_MS = 8e3;
29622
+ ROUTE_PART_LINE_CAP = 100;
29623
+ ROUTE_RECEIPT_CAP = 300;
29624
+ ROUTED_RECEIPT_PREFIX = "routed:";
29625
+ COMPOUND_BRIEF_HEADING = "Routed as a compound request";
29626
+ MultiToolCallError = class extends Error {
29627
+ constructor(calls) {
29628
+ super(`answer carried ${calls.length} tool calls; the route is one call`);
29629
+ this.calls = calls;
29630
+ this.name = "MultiToolCallError";
29631
+ }
29632
+ calls;
29633
+ };
29634
+ }
29635
+ });
29636
+
29137
29637
  // ../../src/core/memory/reflection.ts
29138
29638
  import { z as z15 } from "zod";
29139
29639
  function shouldReflect(input) {
@@ -29288,13 +29788,14 @@ async function reflect(deps) {
29288
29788
  const seen = /* @__PURE__ */ new Set();
29289
29789
  const existing = [...await windowP, ...hits].filter((r) => !seen.has(r.id) && (seen.add(r.id), true));
29290
29790
  const text = buildReflectionInput({ history: deps.history, request: deps.request, answer: deps.answer, existing });
29791
+ const maxTokens = outputCapWithReasoning(REFLECTION_MAX_TOKENS, { capField: deps.capField });
29291
29792
  let result;
29292
29793
  try {
29293
29794
  result = await deps.provider.complete({
29294
29795
  model: deps.model,
29295
29796
  system: REFLECTION_SYSTEM,
29296
29797
  messages: [{ role: "user", content: [{ type: "text", text }] }],
29297
- maxTokens: REFLECTION_MAX_TOKENS,
29798
+ maxTokens,
29298
29799
  ...deps.effort !== void 0 ? { effort: deps.effort } : {},
29299
29800
  ...deps.effortWord !== void 0 ? { effortWord: deps.effortWord } : {}
29300
29801
  });
@@ -29303,13 +29804,17 @@ async function reflect(deps) {
29303
29804
  warn(`reflection skipped: ${renderProviderFailure(failure2.cause)}`);
29304
29805
  return;
29305
29806
  }
29807
+ const truncated = result.stopReason === "max_tokens" ? `truncated at ${maxTokens} max tokens` : void 0;
29808
+ if (truncated) {
29809
+ warn(`reflection output rejected (${truncated}); nothing written`);
29810
+ return;
29811
+ }
29306
29812
  const reply = result.content.filter((p) => p.type === "text").map((p) => p.text).join("");
29307
29813
  const prov = { sourceThreadKey: deps.sourceThreadKey, sourceRunId: deps.sourceRunId };
29308
29814
  const parsed = parseReflection(reply, prov, new Set(existing.map((r) => r.id)));
29309
- const truncated = result.stopReason === "max_tokens" ? `truncated at ${REFLECTION_MAX_TOKENS} max tokens` : void 0;
29310
- const stopNote = truncated ?? (result.stopReason === "end_turn" ? void 0 : `stop: ${result.stopReason}`);
29815
+ const stopNote = result.stopReason === "end_turn" ? void 0 : `stop: ${result.stopReason}`;
29311
29816
  if (!parsed.ok) {
29312
- const why = truncated ?? (stopNote ? `${parsed.error}; ${stopNote}` : parsed.error);
29817
+ const why = stopNote ? `${parsed.error}; ${stopNote}` : parsed.error;
29313
29818
  warn(`reflection output rejected (${why}); nothing written`);
29314
29819
  return;
29315
29820
  }
@@ -29380,6 +29885,7 @@ var init_reflection = __esm({
29380
29885
  init_authz();
29381
29886
  init_runEvents();
29382
29887
  init_llmOutput();
29888
+ init_route();
29383
29889
  init_engine();
29384
29890
  init_scorer();
29385
29891
  init_scope2();
@@ -29622,10 +30128,13 @@ function scheduleReflection(input) {
29622
30128
  const info = (m) => console.log(`[memory] ${input.threadKey} ${m}`);
29623
30129
  let provider;
29624
30130
  let model;
30131
+ let capField;
29625
30132
  try {
29626
- const ref = parseModelRef(input.cfg.model ?? input.runModelRef);
30133
+ const modelRef3 = input.cfg.model ?? input.runModelRef;
30134
+ const ref = parseModelRef(modelRef3);
29627
30135
  provider = input.providers.get(ref.provider);
29628
30136
  model = ref.model;
30137
+ capField = resolveModelCard(modelRef3, input.providerBlocks ?? {}, installedModelRegistry).capField;
29629
30138
  } catch (err2) {
29630
30139
  warn(`reflection skipped: ${err2 instanceof Error ? err2.message : String(err2)}`);
29631
30140
  return;
@@ -29637,6 +30146,7 @@ function scheduleReflection(input) {
29637
30146
  provider,
29638
30147
  model,
29639
30148
  ...effort2.request ? { effort: effort2.request.effort, effortWord: effort2.request.effortWord } : {},
30149
+ ...capField !== void 0 ? { capField } : {},
29640
30150
  store: selectMemoryStore(input.cfg, input.store),
29641
30151
  scopeKeys: requestScopeKeys(input.organization, input.userId, { channelId: input.channelId, repo: input.repo }),
29642
30152
  actor: reflectionActor(input.actor, { channelId: input.channelId, repo: input.repo }),
@@ -29693,6 +30203,8 @@ var init_memory = __esm({
29693
30203
  "use strict";
29694
30204
  init_provider();
29695
30205
  init_turnEffort();
30206
+ init_installedModelRegistry();
30207
+ init_modelCard();
29696
30208
  init_scorer();
29697
30209
  init_scope2();
29698
30210
  init_stores();
@@ -31208,7 +31720,7 @@ ${line4}` : ""}`
31208
31720
  });
31209
31721
 
31210
31722
  // ../../src/core/reviewAbridge.ts
31211
- import { resolve as resolve9 } from "node:path";
31723
+ import { resolve as resolve10 } from "node:path";
31212
31724
  function meatArtifactOf(record2) {
31213
31725
  return record2.events.find((e) => isReadingDiff(e) && e.poweredBy === "meat");
31214
31726
  }
@@ -31253,7 +31765,7 @@ function reviewAbridgerFromConfig(config, store, secrets, env, dataDir, warn) {
31253
31765
  github: () => github,
31254
31766
  meat: meatOnHost({
31255
31767
  apiKey: () => anthropicApiKey(config().providers, secrets),
31256
- cacheDir: resolve9(dataDir, "meat-cache"),
31768
+ cacheDir: resolve10(dataDir, "meat-cache"),
31257
31769
  hostEnv: { PATH: env.PATH, HOME: env.HOME }
31258
31770
  }),
31259
31771
  defaultModel: () => {
@@ -34611,7 +35123,7 @@ var init_githubRepoInspect = __esm({
34611
35123
  });
34612
35124
 
34613
35125
  // ../../src/core/commandCatalogue.ts
34614
- import { existsSync as existsSync12, readFileSync as readFileSync14 } from "node:fs";
35126
+ import { existsSync as existsSync13, readFileSync as readFileSync15 } from "node:fs";
34615
35127
  import { readFile as readFile2 } from "node:fs/promises";
34616
35128
  function unstampedStatus() {
34617
35129
  let version2 = "unknown";
@@ -34636,10 +35148,10 @@ function defaultOperations(config, secrets, caller) {
34636
35148
  return null;
34637
35149
  }
34638
35150
  function readSource(source2) {
34639
- return Promise.resolve(readFileSync14(source2 === "-" ? 0 : source2, "utf8"));
35151
+ return Promise.resolve(readFileSync15(source2 === "-" ? 0 : source2, "utf8"));
34640
35152
  }
34641
35153
  async function readOptionalFile(path) {
34642
- return existsSync12(path) ? readFile2(path, "utf8") : void 0;
35154
+ return existsSync13(path) ? readFile2(path, "utf8") : void 0;
34643
35155
  }
34644
35156
  function once(provided) {
34645
35157
  if (typeof provided !== "function") {
@@ -35116,232 +35628,6 @@ var init_trace = __esm({
35116
35628
  }
35117
35629
  });
35118
35630
 
35119
- // ../../src/core/confirmations.ts
35120
- import { randomUUID } from "node:crypto";
35121
- import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
35122
- import { dirname as dirname10, resolve as resolve10 } from "node:path";
35123
- function newConfirmationId() {
35124
- return randomUUID();
35125
- }
35126
- function renderOffer(offer) {
35127
- if (offer.question) return `${offer.question.text}
35128
- Did you mean:
35129
- \`${offer.line}\`
35130
-
35131
- ${offer.question.evidence}`;
35132
- return [offer.line, ...offer.risk ? [offer.risk] : []].join("\n");
35133
- }
35134
- function confirmationMessageOf(msg) {
35135
- const { images: _images, documents: _documents, staged: _staged, ...kept } = msg;
35136
- return kept;
35137
- }
35138
- function isRecord3(v) {
35139
- return typeof v === "object" && v !== null && !Array.isArray(v);
35140
- }
35141
- function isMessage(v) {
35142
- return isRecord3(v) && typeof v.channelId === "string" && typeof v.userId === "string" && typeof v.threadKey === "string" && typeof v.text === "string";
35143
- }
35144
- function isRunShape(v) {
35145
- return typeof v.id === "string" && isMessage(v.message) && typeof v.command === "string" && isRecord3(v.input) && typeof v.receipt === "string" && typeof v.risk === "string" && typeof v.model === "string";
35146
- }
35147
- function isRedispatchShape(v) {
35148
- return typeof v.id === "string" && isMessage(v.message) && typeof v.line === "string" && typeof v.evidence === "string" && typeof v.code === "string";
35149
- }
35150
- function parsePendingConfirmation(v) {
35151
- if (!isRecord3(v)) return void 0;
35152
- if (v.kind === "redispatch")
35153
- return isRedispatchShape(v) ? v : void 0;
35154
- if (v.kind !== void 0 && v.kind !== "run") return void 0;
35155
- return isRunShape(v) ? { ...v, kind: "run" } : void 0;
35156
- }
35157
- function parseConfirmation(v) {
35158
- if (!isRecord3(v) || typeof v.expiresAt !== "number") return void 0;
35159
- const pending2 = parsePendingConfirmation(v);
35160
- return pending2 ? { ...pending2, expiresAt: v.expiresAt } : void 0;
35161
- }
35162
- function isRefusal(v) {
35163
- return typeof v === "string" && CONFIRMATION_REFUSALS.includes(v);
35164
- }
35165
- function judge2(rows, id, actorIds, now, kind) {
35166
- const row2 = rows.get(id);
35167
- if (!row2) return { ok: false, refused: "used" };
35168
- if (kind === "consume" && row2.expiresAt <= now) {
35169
- rows.delete(id);
35170
- return { ok: false, refused: "expired", row: row2 };
35171
- }
35172
- if (!actorIds.includes(row2.message.userId))
35173
- return kind === "consume" ? { ok: false, refused: "foreign", row: row2 } : { ok: false, refused: "foreign" };
35174
- rows.delete(id);
35175
- return kind === "consume" ? { ok: true, row: row2 } : { ok: true };
35176
- }
35177
- function replaceThreadRow(rows, row2) {
35178
- for (const [id, r] of rows) if (r.message.threadKey === row2.message.threadKey) rows.delete(id);
35179
- rows.set(row2.id, row2);
35180
- }
35181
- function threadRowId(rows, threadKey) {
35182
- for (const [id, r] of rows) if (r.message.threadKey === threadKey) return id;
35183
- return void 0;
35184
- }
35185
- function buildConfirmationStore(config, secrets, opts) {
35186
- const worker = config.config.runtimeOverrides?.worker;
35187
- if (!worker) return new FileConfirmationStore(opts.path);
35188
- const tokenEnv = worker.tokenEnv ?? "MEMORY_TOKEN";
35189
- const token2 = secrets.named(tokenEnv);
35190
- if (!token2) throw new Error(`runtimeOverrides.worker is configured but ${tokenEnv} is not set`);
35191
- return new WorkerConfirmationStore({
35192
- baseUrl: worker.baseUrl,
35193
- token: token2.reveal(),
35194
- ...opts.fetch ? { fetch: opts.fetch } : {}
35195
- });
35196
- }
35197
- var CONFIRMATION_REFUSALS, UNSHOWABLE_LINE, STORE_UNREACHABLE_LINE, FileConfirmationStore, CONFIRMATION_WORKER_TIMEOUT_MS, WorkerConfirmationStore;
35198
- var init_confirmations = __esm({
35199
- "../../src/core/confirmations.ts"() {
35200
- "use strict";
35201
- init_clock();
35202
- CONFIRMATION_REFUSALS = ["used", "expired", "foreign"];
35203
- UNSHOWABLE_LINE = "this command carries a value that cannot be shown, so no confirmation can be offered; nothing ran";
35204
- STORE_UNREACHABLE_LINE = "this command needs a confirmation click, and the confirmation store could not be reached; nothing ran \u2014 ask again for the button";
35205
- FileConfirmationStore = class {
35206
- path;
35207
- clock;
35208
- constructor(path, opts = {}) {
35209
- this.path = resolve10(path);
35210
- this.clock = opts.clock ?? systemClock;
35211
- }
35212
- read() {
35213
- const rows = /* @__PURE__ */ new Map();
35214
- if (!existsSync13(this.path)) return rows;
35215
- const raw = JSON.parse(readFileSync15(this.path, "utf8"));
35216
- for (const v of Array.isArray(raw.confirmations) ? raw.confirmations : []) {
35217
- const row2 = parseConfirmation(v);
35218
- if (row2) rows.set(row2.id, row2);
35219
- }
35220
- return rows;
35221
- }
35222
- write(rows) {
35223
- mkdirSync9(dirname10(this.path), { recursive: true });
35224
- writeFileSync8(this.path, JSON.stringify({ confirmations: [...rows.values()] }, null, 2));
35225
- }
35226
- async put(row2, ttlMs) {
35227
- const rows = this.read();
35228
- const stored = { ...row2, expiresAt: this.clock() + ttlMs };
35229
- replaceThreadRow(rows, stored);
35230
- this.write(rows);
35231
- return stored;
35232
- }
35233
- async consume(id, actorIds) {
35234
- const rows = this.read();
35235
- const out = judge2(rows, id, actorIds, this.clock(), "consume");
35236
- this.write(rows);
35237
- return out;
35238
- }
35239
- async cancel(id, actorIds) {
35240
- const rows = this.read();
35241
- const out = judge2(rows, id, actorIds, this.clock(), "cancel");
35242
- this.write(rows);
35243
- return out;
35244
- }
35245
- async cancelByThread(threadKey, actorIds) {
35246
- const rows = this.read();
35247
- const id = threadRowId(rows, threadKey);
35248
- if (id === void 0) return { ok: false, refused: "used" };
35249
- const out = judge2(rows, id, actorIds, this.clock(), "cancel");
35250
- this.write(rows);
35251
- return out;
35252
- }
35253
- async pendingByThread(threadKey) {
35254
- const rows = this.read();
35255
- const id = threadRowId(rows, threadKey);
35256
- const row2 = id === void 0 ? void 0 : rows.get(id);
35257
- if (!row2 || row2.expiresAt <= this.clock()) return void 0;
35258
- return row2;
35259
- }
35260
- describe() {
35261
- return `file ${this.path}`;
35262
- }
35263
- };
35264
- CONFIRMATION_WORKER_TIMEOUT_MS = 8e3;
35265
- WorkerConfirmationStore = class {
35266
- constructor(opts) {
35267
- this.opts = opts;
35268
- this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
35269
- this.fetchImpl = opts.fetch ?? fetch;
35270
- }
35271
- opts;
35272
- baseUrl;
35273
- fetchImpl;
35274
- async put(row2, ttlMs) {
35275
- const body = await this.post("/config/confirmations/put", {
35276
- id: row2.id,
35277
- threadKey: row2.message.threadKey,
35278
- requester: row2.message.userId,
35279
- body: row2,
35280
- ttlMs
35281
- });
35282
- if (typeof body.expiresAt !== "number")
35283
- throw new Error("confirmation store answered a put without the expiry it stamped");
35284
- return { ...row2, expiresAt: body.expiresAt };
35285
- }
35286
- async consume(id, actorIds) {
35287
- const body = await this.post("/config/confirmations/consume", { id, actorIds });
35288
- const stored = isRecord3(body.row) ? body.row : void 0;
35289
- const row2 = parseConfirmation(
35290
- stored && isRecord3(stored.body) ? { ...stored.body, expiresAt: stored.expiresAt } : void 0
35291
- );
35292
- if (isRefusal(body.refused))
35293
- return { ok: false, refused: body.refused, ...row2 ? { row: row2 } : {} };
35294
- if (!row2) throw new Error("confirmation store answered a consume outside its contract");
35295
- return { ok: true, row: row2 };
35296
- }
35297
- async cancel(id, actorIds) {
35298
- const body = await this.post("/config/confirmations/cancel", { id, actorIds });
35299
- if (body.ok === true) return { ok: true };
35300
- if (body.refused === "used" || body.refused === "foreign") return { ok: false, refused: body.refused };
35301
- throw new Error("confirmation store answered a cancel outside its contract");
35302
- }
35303
- async cancelByThread(threadKey, actorIds) {
35304
- const body = await this.post("/config/confirmations/cancel-by-thread", { threadKey, actorIds });
35305
- if (body.ok === true) return { ok: true };
35306
- if (body.refused === "used" || body.refused === "foreign") return { ok: false, refused: body.refused };
35307
- throw new Error("confirmation store answered a cancel-by-thread outside its contract");
35308
- }
35309
- async pendingByThread(threadKey) {
35310
- const body = await this.post("/config/confirmations/pending-by-thread", { threadKey });
35311
- if (body.row === null) return void 0;
35312
- const stored = isRecord3(body.row) ? body.row : void 0;
35313
- const row2 = parseConfirmation(
35314
- stored && isRecord3(stored.body) ? { ...stored.body, expiresAt: stored.expiresAt } : void 0
35315
- );
35316
- if (!row2) throw new Error("confirmation store answered a pending-by-thread outside its contract");
35317
- return row2;
35318
- }
35319
- describe() {
35320
- return `state Worker ${this.baseUrl} (ConfigDO confirmations)`;
35321
- }
35322
- async post(path, payload2) {
35323
- let res;
35324
- try {
35325
- res = await this.fetchImpl(`${this.baseUrl}${path}`, {
35326
- method: "POST",
35327
- headers: { authorization: `Bearer ${this.opts.token}`, "content-type": "application/json" },
35328
- body: JSON.stringify(payload2),
35329
- signal: AbortSignal.timeout(CONFIRMATION_WORKER_TIMEOUT_MS)
35330
- });
35331
- } catch (err2) {
35332
- throw new Error(`confirmation store unreachable: ${err2 instanceof Error ? err2.message : String(err2)}`, {
35333
- cause: err2
35334
- });
35335
- }
35336
- if (!res.ok) throw new Error(`confirmation store answered HTTP ${res.status} on ${path}`);
35337
- const body = await res.json().catch(() => void 0);
35338
- if (!isRecord3(body)) throw new Error(`confirmation store returned a non-JSON body on ${path}`);
35339
- return body;
35340
- }
35341
- };
35342
- }
35343
- });
35344
-
35345
35631
  // ../../src/core/markdownDocument.ts
35346
35632
  function toMarkdownDocument(text) {
35347
35633
  return text.replace(/[\uE000\uE001]/g, "").split(/(```[\s\S]*?```)/g).map((seg, i) => i % 2 === 1 ? seg : hardBreaks(convertProse(seg))).join("");
@@ -36463,30 +36749,62 @@ function checkPrHeadPreflight(input) {
36463
36749
  async function guardAttachedHead(input) {
36464
36750
  const expected = normalizeHead(input.expectedHeadSha);
36465
36751
  if (!expected) return { outcome: "unverified" };
36466
- const attached = normalizeHead(input.attached.sha);
36467
- const source2 = input.attached.source ?? "workspace-observed";
36468
36752
  const where = `${input.pr.repo}#${input.pr.number}`;
36469
- const branch2 = input.attached.ref ?? input.fallbackRef;
36470
- const namedSource = source2 === "resident binding" ? branch2 ? `${source2} for ${branch2}` : source2 : branch2 ? `${source2} HEAD for ${branch2}` : `${source2} HEAD`;
36471
- if (!attached) {
36472
- console.log(`[review] ${input.logKey} not started: ${namedSource} unreadable, PR head ${expected} (${where})`);
36753
+ const namedSource = (observed) => {
36754
+ const source3 = observed.source ?? "workspace-observed";
36755
+ const branch2 = observed.ref ?? input.fallbackRef;
36756
+ return source3 === "resident binding" ? branch2 ? `${source3} for ${branch2}` : source3 : branch2 ? `${source3} HEAD for ${branch2}` : `${source3} HEAD`;
36757
+ };
36758
+ const first = normalizeHead(input.attached.sha);
36759
+ if (first && sameCommit(expected, first)) return { outcome: "verified" };
36760
+ if (first) {
36761
+ const current = normalizeHead(await input.fetchPrHead(input.pr).catch(() => void 0));
36762
+ if (current && sameCommit(first, current)) {
36763
+ console.log(
36764
+ `[review] ${input.logKey} PR head moved since resolution: ${expected} \u2192 ${current}; the ${namedSource(input.attached)} is at the current head \u2014 reviewing it (${where})`
36765
+ );
36766
+ return { outcome: "adopted", headSha: current };
36767
+ }
36768
+ }
36769
+ let retried;
36770
+ let reprovisionFailed = false;
36771
+ try {
36772
+ retried = await input.reprovision(expected);
36773
+ } catch {
36774
+ reprovisionFailed = true;
36775
+ retried = { sha: void 0 };
36776
+ }
36777
+ const checked = normalizeHead(retried.sha);
36778
+ if (checked && sameCommit(expected, checked)) {
36779
+ console.log(`[review] ${input.logKey} workspace reprovisioned at reviewed head ${expected} (${where})`);
36780
+ return { outcome: "verified" };
36781
+ }
36782
+ const initial = first ? `the initial ${namedSource(input.attached)} was at ${first}` : `the initial ${namedSource(input.attached)} could not be read`;
36783
+ if (reprovisionFailed) {
36784
+ console.log(
36785
+ `[review] ${input.logKey} not started: ${initial}; reprovision failed before retry HEAD observation, expected reviewed head ${expected} (${where})`
36786
+ );
36473
36787
  return {
36474
36788
  outcome: "refused",
36475
- reply: `\u{1F500} Review of ${where} not started: ${namedSource} could not be read, so the workspace cannot be verified against PR head ${expected}. This is a bug: the infrastructure failure was not retried automatically. It is not a finding, and nothing was posted to GitHub.`
36789
+ reply: `\u{1F500} Review of ${where} not started: ${initial}, and the automatic reprovision failed before a retry HEAD could be observed; the expected reviewed head is ${expected}. It is not a finding, and nothing was posted to GitHub.`
36476
36790
  };
36477
36791
  }
36478
- if (sameCommit(expected, attached)) return { outcome: "verified" };
36479
- const current = normalizeHead(await input.fetchPrHead(input.pr).catch(() => void 0));
36480
- if (current && sameCommit(attached, current)) {
36792
+ const source2 = namedSource(retried);
36793
+ if (!checked) {
36481
36794
  console.log(
36482
- `[review] ${input.logKey} PR head moved since resolution: ${expected} \u2192 ${current}; the ${namedSource} is at the current head \u2014 reviewing it (${where})`
36795
+ `[review] ${input.logKey} not started: ${initial}; ${source2} unreadable after reprovision, expected reviewed head ${expected} (${where})`
36483
36796
  );
36484
- return { outcome: "adopted", headSha: current };
36797
+ return {
36798
+ outcome: "refused",
36799
+ reply: `\u{1F500} Review of ${where} not started: ${initial}, and the ${source2} could not be read after one automatic reprovision, so it could not be verified; the expected reviewed head is ${expected}. It is not a finding, and nothing was posted to GitHub.`
36800
+ };
36485
36801
  }
36486
- console.log(`[review] ${input.logKey} not started: ${namedSource} ${attached}, PR head ${expected} (${where})`);
36802
+ console.log(
36803
+ `[review] ${input.logKey} not started: ${source2} ${checked} after reprovision, expected reviewed head ${expected} (${where})`
36804
+ );
36487
36805
  return {
36488
36806
  outcome: "refused",
36489
- reply: `\u{1F500} Review of ${where} not started: the ${namedSource} is at ${attached}, but the PR head is ${expected} \u2014 the branch moved while the workspace was being prepared (a push or force-push). This is a bug: the workspace was not reprovisioned automatically at the new head. It is not a finding, and nothing was posted to GitHub.`
36807
+ reply: `\u{1F500} Review of ${where} not started: after one automatic reprovision, the ${source2} is at ${checked}, but the expected reviewed head is ${expected}. It is not a finding, and nothing was posted to GitHub.`
36490
36808
  };
36491
36809
  }
36492
36810
  function makeSystemComposer(input) {
@@ -36964,14 +37282,19 @@ async function authorizePrHead(ctx) {
36964
37282
  }
36965
37283
  return { kind: "allowed" };
36966
37284
  }
37285
+ function reviewCheckoutFacts(repoCtx) {
37286
+ return {
37287
+ remote: `https://github.com/${repoCtx.repo}.git`,
37288
+ helper: `!f() { test -n "$GH_TOKEN" || exit 1; printf '%s\\n' 'username=x-access-token' "password=$GH_TOKEN"; }; f`,
37289
+ refspecs: [
37290
+ "+HEAD:refs/remotes/origin/HEAD",
37291
+ `+refs/pull/${repoCtx.pr}/head:refs/remotes/origin/pull/${repoCtx.pr}/head`,
37292
+ ...repoCtx.baseRef ? [`+refs/heads/${repoCtx.baseRef}:refs/remotes/origin/${repoCtx.baseRef}`] : []
37293
+ ]
37294
+ };
37295
+ }
36967
37296
  function coldReviewCheckoutCommand(repoCtx) {
36968
- const remote = `https://github.com/${repoCtx.repo}.git`;
36969
- const helper = `!f() { test -n "$GH_TOKEN" || exit 1; printf '%s\\n' 'username=x-access-token' "password=$GH_TOKEN"; }; f`;
36970
- const refspecs = [
36971
- "+HEAD:refs/remotes/origin/HEAD",
36972
- `+refs/pull/${repoCtx.pr}/head:refs/remotes/origin/pull/${repoCtx.pr}/head`,
36973
- ...repoCtx.baseRef ? [`+refs/heads/${repoCtx.baseRef}:refs/remotes/origin/${repoCtx.baseRef}`] : []
36974
- ];
37297
+ const { remote, helper, refspecs } = reviewCheckoutFacts(repoCtx);
36975
37298
  return [
36976
37299
  "set -eu",
36977
37300
  "find . -mindepth 1 -maxdepth 1 ! -name attachments -exec rm -rf -- {} +",
@@ -36981,6 +37304,15 @@ function coldReviewCheckoutCommand(repoCtx) {
36981
37304
  `git checkout --detach --force ${shellQuote(repoCtx.headSha)}`
36982
37305
  ].join("\n");
36983
37306
  }
37307
+ function seededReviewCheckoutCommand(repoCtx, workspace) {
37308
+ const { helper, refspecs } = reviewCheckoutFacts(repoCtx);
37309
+ const git2 = `git -C ${shellQuote(workspace)}`;
37310
+ return [
37311
+ "set -eu",
37312
+ `${git2} -c credential.helper= -c credential.helper=${shellQuote(helper)} fetch --force --no-tags origin ${refspecs.map(shellQuote).join(" ")}`,
37313
+ `${git2} checkout --detach --force ${shellQuote(repoCtx.headSha)}`
37314
+ ].join("\n");
37315
+ }
36984
37316
  async function authorizeAttachedHead(deps, ctx) {
36985
37317
  const { msg, refuse: refuse3, card, shell, closeLines, clock: clock4, agent, resume, selection, root } = ctx;
36986
37318
  const { executor, resident, binding } = selection;
@@ -36991,7 +37323,6 @@ async function authorizeAttachedHead(deps, ctx) {
36991
37323
  const pr = { repo: repoCtx.repo, number: repoCtx.pr };
36992
37324
  const expectedHeadSha = repoCtx.headSha;
36993
37325
  const guard = await root.span("dispatch.gate.attached_head", async (span) => {
36994
- const source2 = resident && binding?.sha !== void 0 ? "resident binding" : "workspace-observed";
36995
37326
  const command2 = selection.seeded?.workspace ? `git -C ${shellQuote(selection.seeded.workspace)} rev-parse HEAD` : "git rev-parse HEAD";
36996
37327
  if (!resident && selection.seeded === void 0 && expectedHeadSha !== void 0) {
36997
37328
  await executor.exec(
@@ -36999,13 +37330,48 @@ async function authorizeAttachedHead(deps, ctx) {
36999
37330
  { timeoutMs: BASH_TIMEOUT_MAX_MS }
37000
37331
  );
37001
37332
  }
37002
- const sha = source2 === "resident binding" ? binding?.sha : await executor.exec(command2, { timeoutMs: 3e4 }).then(parseRevParseOutput).catch(() => void 0);
37333
+ const observeHead = () => executor.exec(command2, { timeoutMs: 3e4, span }).then(parseRevParseOutput).catch(() => void 0);
37334
+ const sha = await observeHead();
37003
37335
  const g = await guardAttachedHead({
37004
37336
  pr,
37005
37337
  expectedHeadSha,
37006
- attached: { sha, ref: binding?.ref ?? repoCtx.ref, source: source2 },
37338
+ attached: { sha, ref: binding?.ref ?? repoCtx.ref, source: "workspace-observed" },
37007
37339
  fallbackRef: repoCtx.ref,
37008
37340
  fetchPrHead: deps.fetchPrHead ?? currentPrHeadSha,
37341
+ reprovision: async (headSha) => {
37342
+ if (executor.moveTo) {
37343
+ await executor.moveTo(headSha, { span });
37344
+ const observedSha = await observeHead();
37345
+ if (selection.binding && observedSha !== void 0) {
37346
+ selection.binding = {
37347
+ ...selection.binding,
37348
+ ref: repoCtx.ref ?? selection.binding.ref,
37349
+ sha: observedSha
37350
+ };
37351
+ }
37352
+ return {
37353
+ sha: observedSha,
37354
+ ref: repoCtx.ref,
37355
+ source: "workspace-observed"
37356
+ };
37357
+ }
37358
+ if (selection.seeded?.workspace) {
37359
+ await executor.exec(
37360
+ seededReviewCheckoutCommand(
37361
+ { ...repoCtx, repo: pr.repo, pr: pr.number, headSha },
37362
+ selection.seeded.workspace
37363
+ ),
37364
+ { timeoutMs: BASH_TIMEOUT_MAX_MS, span }
37365
+ );
37366
+ } else {
37367
+ await executor.exec(coldReviewCheckoutCommand({ ...repoCtx, repo: pr.repo, pr: pr.number, headSha }), {
37368
+ timeoutMs: BASH_TIMEOUT_MAX_MS,
37369
+ span
37370
+ });
37371
+ }
37372
+ const retried = await observeHead();
37373
+ return { sha: retried, ref: repoCtx.ref, source: "workspace-observed" };
37374
+ },
37009
37375
  logKey: msg.threadKey
37010
37376
  });
37011
37377
  span.setAttrs({ outcome: g.outcome });
@@ -37018,14 +37384,19 @@ async function authorizeAttachedHead(deps, ctx) {
37018
37384
  verifiedAtAttach = true;
37019
37385
  headAdopted = true;
37020
37386
  } else if (guard.outcome === "refused") {
37021
- await refuse3(refusalOf("branch_moved", guard.reply), async () => {
37387
+ await refuse3(refusalOf("workspace_head_mismatch", guard.reply), async () => {
37022
37388
  if (executor.release) await executor.release("always").catch(() => {
37023
37389
  });
37024
37390
  await card.done(
37025
- shell.close({ kind: "not_started", icon: "\u{1F500}", reason: "branch moved", ...closeLines(clock4(), false) })
37391
+ shell.close({
37392
+ kind: "not_started",
37393
+ icon: "\u{1F500}",
37394
+ reason: "workspace head mismatch",
37395
+ ...closeLines(clock4(), false)
37396
+ })
37026
37397
  );
37027
37398
  });
37028
- return { kind: "refused", reason: "branch_moved" };
37399
+ return { kind: "refused", reason: "workspace_head_mismatch" };
37029
37400
  }
37030
37401
  }
37031
37402
  return { kind: "allowed", repoCtx, verifiedAtAttach, headAdopted };
@@ -37418,6 +37789,10 @@ var init_threadAdmission = __esm({
37418
37789
  get size() {
37419
37790
  return this.pending.length;
37420
37791
  }
37792
+ /** The ledger seqs of the follow-ups still pending, oldest first. */
37793
+ get pendingSeqs() {
37794
+ return this.pending.flatMap((input) => input.ledgerSeq !== void 0 ? [input.ledgerSeq] : []);
37795
+ }
37421
37796
  };
37422
37797
  ThreadAdmission = class {
37423
37798
  live = /* @__PURE__ */ new Map();
@@ -38085,279 +38460,6 @@ var init_commandChat = __esm({
38085
38460
  }
38086
38461
  });
38087
38462
 
38088
- // ../../src/core/dispatch/handBack.ts
38089
- function renderHandBackLine(line4) {
38090
- return `${HAND_BACK_PREFIX}
38091
- \`${line4}\``;
38092
- }
38093
- var HAND_BACK_PREFIX;
38094
- var init_handBack = __esm({
38095
- "../../src/core/dispatch/handBack.ts"() {
38096
- "use strict";
38097
- HAND_BACK_PREFIX = "To run this:";
38098
- }
38099
- });
38100
-
38101
- // ../../src/core/statusCardFrame.ts
38102
- function activityText(activity) {
38103
- if (!activity) return void 0;
38104
- if (activity.kind === "line") return activity.text;
38105
- return `\u2192 $ ${activity.command.replace(/\s+/g, " ").trim()}`;
38106
- }
38107
- function createCardShell(opts) {
38108
- const verbosity2 = opts.verbosity ?? DEFAULT_VERBOSITY;
38109
- const notes = [];
38110
- let link = opts.link;
38111
- let frame2 = 0;
38112
- let finishedAt;
38113
- let setupLabel;
38114
- const lead = opts.lead ?? [];
38115
- const base = () => opts.model !== void 0 && shows(verbosity2, "verbose") ? `${opts.label} on \`${opts.model}\`` : opts.label;
38116
- const label = () => [base(), ...notes.filter((n2) => shows(verbosity2, n2.level)).map((n2) => n2.text)].join(" \xB7 ");
38117
- const elapsed2 = () => formatDuration((finishedAt ?? opts.now()) - opts.startedAt, "clock");
38118
- const headline = (icon) => `${icon} ${label()} \xB7 ${elapsed2()}`;
38119
- const closeDetail = (close, own) => [...shows(verbosity2, "debug") ? [close.shape, close.queued] : [], own].filter(Boolean).join("\n") || void 0;
38120
- return {
38121
- get label() {
38122
- return label();
38123
- },
38124
- note(level, text) {
38125
- notes.push({ level, text });
38126
- },
38127
- setLink(next) {
38128
- link = next;
38129
- },
38130
- freeze(at) {
38131
- finishedAt = at;
38132
- },
38133
- setSetupLabel(next) {
38134
- setupLabel = next;
38135
- },
38136
- ack() {
38137
- const detail = lead.join("\n");
38138
- return { title: `\u{1F440} ${label()} \xB7 preparing workspace\u2026`, ...detail ? { detail } : {} };
38139
- },
38140
- live(parts = {}) {
38141
- const glyph = SPINNER_GLYPHS[frame2++ % SPINNER_GLYPHS.length];
38142
- const detail = [...lead, ...parts.detail ?? []].filter(Boolean).join("\n");
38143
- return {
38144
- title: headline(glyph) + (setupLabel ? ` \u2014 ${setupLabel}` : "") + (parts.suffix ?? "") + (parts.notice ? ` \xB7 ${parts.notice}` : ""),
38145
- detail: detail || void 0,
38146
- ...parts.activity ? { activity: parts.activity } : {},
38147
- link
38148
- };
38149
- },
38150
- close(close) {
38151
- const detail = closeDetail(close, close.kind === "done" ? close.detail : void 0);
38152
- switch (close.kind) {
38153
- case "done":
38154
- return { title: headline(close.icon), detail, link };
38155
- case "not_started":
38156
- return { title: `${close.icon} ${label()} \xB7 not started (${close.reason}) \xB7 ${elapsed2()}`, detail };
38157
- case "refused":
38158
- return { title: `${close.icon} ${label()} \xB7 ${close.reason} \xB7 ${elapsed2()}`, detail };
38159
- case "setup_failed":
38160
- return { title: `\u274C setup failed \xB7 ${close.reason} \xB7 ${elapsed2()}`, detail };
38161
- }
38162
- }
38163
- };
38164
- }
38165
- var SPINNER_GLYPHS, LIVE_CARD_PREFIXES, ROUTE_REASON_PREFIX;
38166
- var init_statusCardFrame = __esm({
38167
- "../../src/core/statusCardFrame.ts"() {
38168
- "use strict";
38169
- init_formatDuration();
38170
- init_verbosity();
38171
- SPINNER_GLYPHS = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
38172
- LIVE_CARD_PREFIXES = [...SPINNER_GLYPHS, "\u{1F440}"];
38173
- ROUTE_REASON_PREFIX = "route reason:";
38174
- }
38175
- });
38176
-
38177
- // ../../src/core/dispatch/route.ts
38178
- function outputCapWithReasoning(visibleAnswerTokens, opts = {}) {
38179
- return opts.capField !== void 0 && REASONING_COUNTING_CAP_FIELDS.has(opts.capField) ? visibleAnswerTokens + REASONING_OUTPUT_TOKEN_ALLOWANCE : visibleAnswerTokens;
38180
- }
38181
- function outputCapRetry(current) {
38182
- return Math.max(current * 2, REASONING_OUTPUT_TOKEN_ALLOWANCE);
38183
- }
38184
- function routedRunsAtOnce(def, confirm, input) {
38185
- const radius = input === void 0 ? blastRadius(def) : boundBlastRadius(def, input);
38186
- return radius === "read" || CONFIRM_ORDER[radius] < CONFIRM_ORDER[confirm];
38187
- }
38188
- function routeReceipt(def, input) {
38189
- return redactAndCap(chatInvocation(def, input), ROUTE_RECEIPT_CAP);
38190
- }
38191
- function routablePresets() {
38192
- return Object.values(AGENTS).filter((a) => a.routable !== false).map(({ name, description, machine, identity: identity2, maxMinutes }) => ({
38193
- name,
38194
- description,
38195
- machine,
38196
- identity: identity2,
38197
- maxMinutes
38198
- }));
38199
- }
38200
- function routableCommands(commands) {
38201
- return commands.list().filter((cmd) => CommandRegistry.exposedTo(cmd, "chat")).map((cmd) => ({
38202
- id: cmd.id,
38203
- effect: cmd.effect,
38204
- def: cmd,
38205
- tool: { name: mcpToolName(cmd.id), description: cmd.describe, inputSchema: jsonSchemaFor(cmd) }
38206
- }));
38207
- }
38208
- function renderPresetTable(presets) {
38209
- const rows = presets.map(
38210
- (p) => `| \`${p.name}\` | ${oneLine(p.description)} | ${p.machine} | ${p.identity} | ${p.maxMinutes} min |`
38211
- );
38212
- return ["| name | what it does | machine | credential | budget |", "|---|---|---|---|---|", ...rows].join("\n");
38213
- }
38214
- function quoteRequest(text) {
38215
- const cap = 2e3;
38216
- const bent = text.replace(/<(\/?)request>/gi, "\u2039$1request\u203A");
38217
- if (bent.length <= cap) return bent;
38218
- return `${bent.slice(0, cap)}
38219
- \u2026[truncated: ${bent.length - cap} more characters]`;
38220
- }
38221
- function providerStructuredModel(provider, model, opts = {}) {
38222
- const forced = (opts.answer ?? "tool") === "tool";
38223
- return async (prompt, call2) => {
38224
- const tools = [prompt.tool, ...prompt.tools ?? []];
38225
- const toolChoice = prompt.open ? void 0 : tools.length > 1 ? { type: "any" } : { type: "tool", name: prompt.tool.name };
38226
- const messages = [
38227
- { role: "user", content: [{ type: "text", text: prompt.user }] },
38228
- ...(prompt.retries ?? []).flatMap((r) => [
38229
- { role: "assistant", content: [{ type: "text", text: r.answer }] },
38230
- { role: "user", content: [{ type: "text", text: r.violation }] }
38231
- ])
38232
- ];
38233
- const result = await provider.complete({
38234
- model,
38235
- system: prompt.system,
38236
- messages,
38237
- maxTokens: call2.maxTokens,
38238
- signal: call2.signal,
38239
- // The caller's configured effort, card-decided (`turnEffort`): intake's
38240
- // `intake.effort` or the operator's `defaults.efforts.general`. Absent →
38241
- // the model's own default.
38242
- ...opts.effort ? { effort: opts.effort.effort, effortWord: opts.effort.effortWord } : {},
38243
- ...forced ? { tools, toolChoice } : {}
38244
- });
38245
- if (result.stopReason === "max_tokens") throw new OutputCapError(call2.maxTokens);
38246
- const calls = result.content.filter(
38247
- (p) => p.type === "tool_use"
38248
- );
38249
- if (calls.length > 1) throw new MultiToolCallError(calls.map((c) => ({ tool: c.name, input: c.input })));
38250
- if (calls.length === 1) return { tool: calls[0].name, input: calls[0].input };
38251
- return result.content.filter((p) => p.type === "text").map((p) => p.text).join("");
38252
- };
38253
- }
38254
- async function mintConfirmationOffer(args) {
38255
- const { io, store, msg, origin, def, input, receipt, model } = args;
38256
- if (!io.offer || !store) return { kind: "no_click" };
38257
- const line4 = chatInvocation(def, input);
38258
- if (redactSecrets(line4) !== line4) return { kind: "unshowable" };
38259
- const risk = def.annotations?.risk?.(input, origin) ?? "";
38260
- let row2;
38261
- try {
38262
- row2 = await store.put(
38263
- {
38264
- kind: "run",
38265
- id: newConfirmationId(),
38266
- message: confirmationMessageOf(msg),
38267
- command: def.id,
38268
- input,
38269
- receipt,
38270
- risk,
38271
- model
38272
- },
38273
- CONFIRMATION_TTL_MS
38274
- );
38275
- } catch (err2) {
38276
- console.warn(
38277
- `[route] ${msg.threadKey} confirmation store unreachable at mint, handing back: ${err2 instanceof Error ? err2.message : String(err2)}`
38278
- );
38279
- return { kind: "store_unreachable" };
38280
- }
38281
- return { kind: "offered", shown: { id: row2.id, line: line4, risk, expiresAt: row2.expiresAt } };
38282
- }
38283
- function redactedInput(input) {
38284
- const text = (s) => redactAndCap(redactSecrets(s), 200);
38285
- const leaf = (v) => {
38286
- if (typeof v === "string") return text(v);
38287
- if (typeof v === "number" || typeof v === "boolean" || v === null) return v;
38288
- return v === void 0 ? null : text(JSON.stringify(v) ?? String(v));
38289
- };
38290
- const leafOrList = (v) => Array.isArray(v) ? v.map(leaf) : leaf(v);
38291
- const isRecord11 = (v) => typeof v === "object" && v !== null && (Object.getPrototypeOf(v) === Object.prototype || Object.getPrototypeOf(v) === null);
38292
- const entries = (v, of) => Object.fromEntries(
38293
- Object.entries(v).filter(([, x]) => x !== void 0).map(([k, x]) => [k, of(x)])
38294
- );
38295
- const object1 = (v) => entries(v, leafOrList);
38296
- const object2 = (v) => entries(v, (x) => isRecord11(x) ? object1(x) : leafOrList(x));
38297
- const object3 = (v) => entries(v, (x) => isRecord11(x) ? object2(x) : leafOrList(x));
38298
- return {
38299
- ...input.args ? { args: input.args.map(leaf) } : {},
38300
- ...input.options ? { options: object3(input.options) } : {}
38301
- };
38302
- }
38303
- function routeReasonLabel(reason2, collapsed) {
38304
- return `${ROUTE_REASON_PREFIX} ${reason2}${collapsed ? ` (compound collapsed: ${collapsed.presets.join("+")})` : ""}`;
38305
- }
38306
- function routedPartLines(parts) {
38307
- return parts.map((p) => {
38308
- const line4 = p.text.replace(/\s+/g, " ").trim();
38309
- return `${p.preset}: ${line4.length > ROUTE_PART_LINE_CAP ? `${line4.slice(0, ROUTE_PART_LINE_CAP - 1)}\u2026` : line4}`;
38310
- });
38311
- }
38312
- function compoundBrief(text, parts) {
38313
- return [
38314
- text,
38315
- "",
38316
- `${COMPOUND_BRIEF_HEADING}: ${parts.length} independent parts. Spawn exactly these children \u2014 one \`spawn_run\` per part, on the preset named, with the part's text as the child's whole prompt (add the repository where the preset needs one) \u2014 then \`await_runs\` them all and compile one answer. Do not merge, drop or add a part.`,
38317
- ...parts.map((p, i) => `${i + 1}. \`${p.preset}\`: ${p.text}`)
38318
- ].join("\n");
38319
- }
38320
- var REASONING_COUNTING_CAP_FIELDS, REASONING_OUTPUT_TOKEN_ALLOWANCE, OutputCapError, ROUTE_REASON_CAP, ROUTE_MIN_OUTPUT_TOKENS, ROUTE_TIMEOUT_MS, ROUTE_PART_LINE_CAP, ROUTE_RECEIPT_CAP, ROUTED_RECEIPT_PREFIX, COMPOUND_BRIEF_HEADING, MultiToolCallError;
38321
- var init_route = __esm({
38322
- "../../src/core/dispatch/route.ts"() {
38323
- "use strict";
38324
- init_registry();
38325
- init_handBack();
38326
- init_profile();
38327
- init_redact();
38328
- init_statusCardFrame();
38329
- init_commandRegistry();
38330
- init_commandSurface();
38331
- init_budgets();
38332
- init_confirmations();
38333
- REASONING_COUNTING_CAP_FIELDS = /* @__PURE__ */ new Set(["max_tokens", "max_completion_tokens", "max_output_tokens"]);
38334
- REASONING_OUTPUT_TOKEN_ALLOWANCE = 4096;
38335
- OutputCapError = class extends Error {
38336
- constructor(maxTokens) {
38337
- super(`answer cut at the output cap (${maxTokens} tokens)`);
38338
- this.maxTokens = maxTokens;
38339
- this.name = "OutputCapError";
38340
- }
38341
- maxTokens;
38342
- };
38343
- ROUTE_REASON_CAP = 120;
38344
- ROUTE_MIN_OUTPUT_TOKENS = 200;
38345
- ROUTE_TIMEOUT_MS = 8e3;
38346
- ROUTE_PART_LINE_CAP = 100;
38347
- ROUTE_RECEIPT_CAP = 300;
38348
- ROUTED_RECEIPT_PREFIX = "routed:";
38349
- COMPOUND_BRIEF_HEADING = "Routed as a compound request";
38350
- MultiToolCallError = class extends Error {
38351
- constructor(calls) {
38352
- super(`answer carried ${calls.length} tool calls; the route is one call`);
38353
- this.calls = calls;
38354
- this.name = "MultiToolCallError";
38355
- }
38356
- calls;
38357
- };
38358
- }
38359
- });
38360
-
38361
38463
  // ../../src/core/runRegistry/runControl.ts
38362
38464
  var RunControl;
38363
38465
  var init_runControl = __esm({
@@ -42112,7 +42214,7 @@ async function reserveRun(deps, ctx) {
42112
42214
  async function attachRound(deps, ctx) {
42113
42215
  const { threadKey, agent, profile, repoCtx, root, clock: clock4, reattach, stopSignal, remainingMs, requester } = ctx;
42114
42216
  const { onSetupNote } = ctx;
42115
- const ownPr = ownPrOf(repoCtx);
42217
+ const ownPr = agent.name === "review" ? void 0 : ownPrOf(repoCtx);
42116
42218
  return root.span("dispatch.workspace.attach", async (span) => {
42117
42219
  const graft = (steps, residentTotalMs) => graftResidentSteps(steps, {
42118
42220
  parent: span,
@@ -45718,6 +45820,18 @@ function decisionRecordTaskKey(...parts) {
45718
45820
  }
45719
45821
  return hash.toString(16).padStart(16, "0");
45720
45822
  }
45823
+ function durableDecisionRecordReservation(store) {
45824
+ return async (repo, taskKey, claimed2, existing) => {
45825
+ try {
45826
+ const reserved = await store.reserveDecisionRecord(repo, taskKey, claimed2, existing);
45827
+ if (!reserved.ok) throw new DecisionRecordReservationUnavailableError();
45828
+ return reserved.number;
45829
+ } catch (error) {
45830
+ if (error instanceof DecisionRecordReservationUnavailableError) throw error;
45831
+ throw new DecisionRecordReservationUnavailableError();
45832
+ }
45833
+ };
45834
+ }
45721
45835
  var DECISION_RECORD_ENV, RECORD_MARKER, POSITIVE_RECORD_INSTRUCTION, NEGATED_INSTRUCTION, DECISION_RECORD_STORE_REFUSAL, DecisionRecordReservationUnavailableError, DecisionRecordAllocator;
45722
45836
  var init_decisionRecordReservation = __esm({
45723
45837
  "../../src/core/decisionRecordReservation.ts"() {
@@ -48614,6 +48728,11 @@ var init_mirror = __esm({
48614
48728
  compactionRows = [];
48615
48729
  /** The highest ledger inbox seq folded in so far (run-history item 40). */
48616
48730
  inboxConsumedSeq = 0;
48731
+ /** The owed seqs the cursor has already passed, ascending; absent when none. */
48732
+ inboxDeferred() {
48733
+ const deferred = [...new Set(this.deps.owedInboxSeqs?.() ?? [])].filter((seq) => seq <= this.inboxConsumedSeq).sort((a, b) => a - b);
48734
+ return deferred.length > 0 ? { inboxDeferredSeqs: deferred } : {};
48735
+ }
48617
48736
  /** Whether a report is owed: the mirror is wired and something happened. */
48618
48737
  get wired() {
48619
48738
  return this.deps.onStep !== void 0;
@@ -48702,7 +48821,8 @@ var init_mirror = __esm({
48702
48821
  turn,
48703
48822
  iteration: this.iteration++,
48704
48823
  remainingMs: Math.max(0, this.deps.remainingMs()),
48705
- inboxConsumedSeq: this.inboxConsumedSeq
48824
+ inboxConsumedSeq: this.inboxConsumedSeq,
48825
+ ...this.inboxDeferred()
48706
48826
  };
48707
48827
  this.idx += turns.length;
48708
48828
  this.lastAssistantIdx = this.idx - 1;
@@ -48729,7 +48849,8 @@ var init_mirror = __esm({
48729
48849
  turn,
48730
48850
  iteration: this.iteration,
48731
48851
  remainingMs: Math.max(0, this.deps.remainingMs()),
48732
- inboxConsumedSeq: this.inboxConsumedSeq
48852
+ inboxConsumedSeq: this.inboxConsumedSeq,
48853
+ ...this.inboxDeferred()
48733
48854
  };
48734
48855
  this.idx += turns.length + 1;
48735
48856
  this.rows.push(...turns);
@@ -49813,6 +49934,7 @@ async function runPiHarnessOpen(deps, run2) {
49813
49934
  let paths;
49814
49935
  let requeueUnechoed = () => {
49815
49936
  };
49937
+ let unechoedSeqs = () => [];
49816
49938
  let dropHeld = () => {
49817
49939
  };
49818
49940
  let loopEnded = false;
@@ -49847,7 +49969,10 @@ async function runPiHarnessOpen(deps, run2) {
49847
49969
  onStep: run2.onStep,
49848
49970
  seedLength: run2.resume ? run2.resume.messages.length + (run2.resume.compactions?.length ?? 0) : run2.messages.length,
49849
49971
  remainingMs: () => deadline - now(),
49850
- ...tail ? { mirroredTail: tail } : {}
49972
+ ...tail ? { mirroredTail: tail } : {},
49973
+ // The rows pi has not read yet: the cursor can pass one when a later row
49974
+ // is consumed first (the plane's provider-up beside an ordinary steer).
49975
+ owedInboxSeqs: () => [...run2.inbox?.pendingSeqs ?? [], ...unechoedSeqs()]
49851
49976
  });
49852
49977
  mirror.inboxConsumedSeq = run2.resume?.inboxConsumedSeq ?? 0;
49853
49978
  placed = (event) => {
@@ -50254,6 +50379,7 @@ async function runPiHarnessOpen(deps, run2) {
50254
50379
  const [echoed] = unechoed.splice(at, 1);
50255
50380
  if (echoed.seq > mirror.inboxConsumedSeq) mirror.inboxConsumedSeq = echoed.seq;
50256
50381
  };
50382
+ unechoedSeqs = () => unechoed.flatMap((u) => u.inputs.flatMap((i) => i.ledgerSeq !== void 0 ? [i.ledgerSeq] : []));
50257
50383
  requeueUnechoed = () => {
50258
50384
  pendingReissue = [];
50259
50385
  run2.inbox?.requeue(unechoed.splice(0).flatMap((u) => u.inputs));
@@ -50935,7 +51061,14 @@ ${stagedLine}` : prompt;
50935
51061
  if (obs.response.success === false) {
50936
51062
  turnParkSettled = false;
50937
51063
  note("harness_error", "the follow-up turn's model retry prompt was refused; the failure remains held");
50938
- } else clearTurnProviderHold();
51064
+ } else {
51065
+ drainTurnReissues();
51066
+ mirror.inboxConsumedSeq = Math.max(
51067
+ mirror.inboxConsumedSeq,
51068
+ ...turnReissueRows.map((item) => item.ledgerSeq ?? 0)
51069
+ );
51070
+ clearTurnProviderHold();
51071
+ }
50939
51072
  }
50940
51073
  }
50941
51074
  if (obs.response?.id === id && obs.response.success === false)
@@ -56806,6 +56939,7 @@ function createLedgerWriteThrough(opts) {
56806
56939
  turnIndex: report2.firstIdx + turns.length,
56807
56940
  inFlight: report2.inFlight,
56808
56941
  inboxConsumedSeq: report2.inboxConsumedSeq,
56942
+ ...report2.inboxDeferredSeqs?.length ? { inboxDeferredSeqs: report2.inboxDeferredSeqs } : {},
56809
56943
  remainingMs: report2.remainingMs,
56810
56944
  turn: report2.turn,
56811
56945
  iteration: report2.iteration
@@ -63023,14 +63157,23 @@ var init_configBoot = __esm({
63023
63157
  });
63024
63158
 
63025
63159
  // ../../src/intakeModel.ts
63160
+ function intakeDecisionDeps(completion, deps) {
63161
+ return {
63162
+ model: completion.model,
63163
+ ...completion.capField !== void 0 ? { capField: completion.capField } : {},
63164
+ ...deps
63165
+ };
63166
+ }
63026
63167
  function intakeCompletion(config, completions, log = console.log) {
63027
63168
  const modelRef3 = intakeModelRef(config);
63028
63169
  if (!modelRef3) return void 0;
63029
63170
  const ref = parseModelRef(modelRef3);
63171
+ const card = resolveModelCard(modelRef3, config.providers, installedModelRegistry);
63030
63172
  const effort2 = turnEffort(modelRef3, config.intake?.effort, config.providers);
63031
63173
  if (effort2.note) log(`[intake] effort: ${effort2.note}`);
63032
63174
  return {
63033
63175
  modelRef: modelRef3,
63176
+ capField: card.capField,
63034
63177
  model: providerStructuredModel(completions.get(ref.provider), ref.model, {
63035
63178
  ...effort2.request ? { effort: effort2.request } : {}
63036
63179
  })
@@ -63042,6 +63185,8 @@ var init_intakeModel = __esm({
63042
63185
  init_config2();
63043
63186
  init_route();
63044
63187
  init_turnEffort();
63188
+ init_installedModelRegistry();
63189
+ init_modelCard();
63045
63190
  init_provider();
63046
63191
  }
63047
63192
  });
@@ -63164,7 +63309,10 @@ async function askModel(input, deps) {
63164
63309
  floor: (violation) => ({ verdict: "silent", reason: violation, source: "error" })
63165
63310
  },
63166
63311
  deps.model,
63167
- { maxTokens: ROUTE_MIN_OUTPUT_TOKENS, signal: AbortSignal.timeout(deps.timeoutMs ?? ROUTE_TIMEOUT_MS) }
63312
+ {
63313
+ maxTokens: outputCapWithReasoning(ROUTE_MIN_OUTPUT_TOKENS, { capField: deps.capField }),
63314
+ signal: AbortSignal.timeout(deps.timeoutMs ?? ROUTE_TIMEOUT_MS)
63315
+ }
63168
63316
  );
63169
63317
  return { ...seam.value, attempts: seam.attempts };
63170
63318
  } catch (err2) {
@@ -63173,8 +63321,18 @@ async function askModel(input, deps) {
63173
63321
  if (timedOut) {
63174
63322
  return {
63175
63323
  verdict: "silent",
63176
- reason: tidyReason("the intake call timed out"),
63324
+ reason: renderProviderFailure("transient", "ended"),
63177
63325
  source: "timeout",
63326
+ providerFailure: "transient",
63327
+ ...attempts ? { attempts } : {}
63328
+ };
63329
+ }
63330
+ const outputCapError = err2 instanceof OutputCapError ? err2 : err2 instanceof StructuredAskError && err2.cause instanceof OutputCapError ? err2.cause : void 0;
63331
+ if (outputCapError) {
63332
+ return {
63333
+ verdict: "silent",
63334
+ reason: tidyReason(outputCapError.message),
63335
+ source: "error",
63178
63336
  ...attempts ? { attempts } : {}
63179
63337
  };
63180
63338
  }
@@ -71424,6 +71582,25 @@ async function childPullRequestState(deps, instance, unit) {
71424
71582
  if (state === void 0) throw new Error(headBranchStateError(instance.repo, row2.pr.number));
71425
71583
  return state;
71426
71584
  }
71585
+ async function isEarlierAttemptRun(deps, current, view, unit) {
71586
+ if (current?.plan === void 0 || view.parentInstanceId === void 0 || unit === void 0) return false;
71587
+ if (unitOfIdempotencyKey(view.idempotencyKey ?? "") !== unit) return false;
71588
+ const prior = await deps.instances.get(view.parentInstanceId);
71589
+ if (prior?.plan === void 0) return false;
71590
+ const currentAttempt = current.attempt ?? 1;
71591
+ const priorAttempt = prior.attempt ?? 1;
71592
+ if (currentAttempt <= priorAttempt || current.plan.id !== prior.plan.id || current.plan.path !== prior.plan.path || current.repo !== prior.repo)
71593
+ return false;
71594
+ const [nextAttempt, currentUnits, priorUnits] = await Promise.all([
71595
+ deps.instances.get(planInstanceId(current.plan.id, currentAttempt + 1)),
71596
+ deps.instances.listUnits(current.id),
71597
+ deps.instances.listUnits(prior.id)
71598
+ ]);
71599
+ if (nextAttempt !== null) return false;
71600
+ const currentUnit = currentUnits.find((row2) => row2.unit === unit);
71601
+ const priorUnit = priorUnits.find((row2) => row2.unit === unit);
71602
+ return currentUnit !== void 0 && priorUnit !== void 0 && currentUnit.branch === priorUnit.branch;
71603
+ }
71427
71604
  async function readRecord(body, deps) {
71428
71605
  const id = parseInstanceId(body.parentInstanceId);
71429
71606
  if (!id.ok) return json3(400, { ok: false, error: id.error });
@@ -71432,10 +71609,11 @@ async function readRecord(body, deps) {
71432
71609
  if (body.unit !== void 0 && (typeof body.unit !== "string" || !UNIT_ID.test(body.unit)))
71433
71610
  return json3(400, { ok: false, error: "unit must be a unit id" });
71434
71611
  const at = (deps.clock ?? systemClock)();
71435
- const res = await deps.runs.getRun(body.runId);
71436
- if (!res.ok || res.value.parentInstanceId !== id.value) return json3(404, { ok: false, error: "not_found" });
71612
+ const [res, instanceRow] = await Promise.all([deps.runs.getRun(body.runId), deps.instances.get(id.value)]);
71613
+ if (!res.ok) return json3(404, { ok: false, error: "not_found" });
71437
71614
  const view = res.value;
71438
- const instanceRow = await deps.instances.get(id.value);
71615
+ if (view.parentInstanceId !== id.value && !await isEarlierAttemptRun(deps, instanceRow, view, typeof body.unit === "string" ? body.unit : void 0))
71616
+ return json3(404, { ok: false, error: "not_found" });
71439
71617
  let pullRequest;
71440
71618
  try {
71441
71619
  pullRequest = await childPullRequestState(deps, instanceRow, typeof body.unit === "string" ? body.unit : void 0);
@@ -73824,11 +74002,7 @@ async function runBot() {
73824
74002
  const coordinatorInstances = buildCoordinatorInstanceStore(runHistoryCfg, processSecrets);
73825
74003
  const decisionRecordAllocator = new DecisionRecordAllocator(
73826
74004
  fetchDecisionRecordClaims,
73827
- async (repo, taskKey, claimed2, existing) => {
73828
- const reserved = await coordinatorInstances.reserveDecisionRecord(repo, taskKey, claimed2, existing);
73829
- if (!reserved.ok) throw new DecisionRecordReservationUnavailableError();
73830
- return reserved.number;
73831
- }
74005
+ durableDecisionRecordReservation(coordinatorInstances)
73832
74006
  );
73833
74007
  let planeAdmitPass;
73834
74008
  const planeEffectExecutor = {
@@ -74100,9 +74274,7 @@ async function runBot() {
74100
74274
  slackIntake = wireIntakeGate({
74101
74275
  intakeModeFor: (threadKey, userId, channelId) => config.intakeModeFor(threadKey, userId, channelId),
74102
74276
  deps: {
74103
- model: intake.model,
74104
- ledger: intakeLedger,
74105
- now: systemClock
74277
+ ...intakeDecisionDeps(intake, { ledger: intakeLedger, now: systemClock })
74106
74278
  },
74107
74279
  modelRef: intake.modelRef,
74108
74280
  gen: PROCESS_STARTED_AT,