@coreplane/switchboard 1.216.2 → 1.217.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 (23) hide show
  1. package/dist/assets/deploy/cloudflare/package.json +1 -1
  2. package/dist/assets/deploy/cloudflare-docs/package.json +1 -1
  3. package/dist/assets/deploy/cloudflare-memory/package.json +1 -1
  4. package/dist/assets/deploy/cloudflare-resident/package.json +1 -1
  5. package/dist/assets/deploy/cloudflare-sandbox/package.json +1 -1
  6. package/dist/assets/package-lock.json +5676 -7966
  7. package/dist/assets/package.json +2 -2
  8. package/dist/assets/source.json +3 -3
  9. package/dist/assets/src/core/runEvents.ts +7 -0
  10. package/dist/assets/src/core/runRecord.ts +4 -2
  11. package/dist/assets/web/dist/.vite/manifest.json +18 -18
  12. package/dist/assets/web/dist/assets/{ResidentDetailPage-CvwjhjlG.js → ResidentDetailPage-CWyEd5fq.js} +1 -1
  13. package/dist/assets/web/dist/assets/{ResidentsIndexPage-DoN6XuNx.js → ResidentsIndexPage-DqFqRTWb.js} +1 -1
  14. package/dist/assets/web/dist/assets/{RunRoutePage-FzLNexjF.js → RunRoutePage-CghwVr_X.js} +3 -3
  15. package/dist/assets/web/dist/assets/{RunsIndexPage-DhSUbF9k.js → RunsIndexPage-BcYehvW5.js} +1 -1
  16. package/dist/assets/web/dist/assets/{ScheduledPage-Bq0Yg4nT.js → ScheduledPage-mKa20Qdd.js} +1 -1
  17. package/dist/assets/web/dist/assets/{StatusDot-D8Wwt1KC.js → StatusDot-QMofJG-E.js} +1 -1
  18. package/dist/assets/web/dist/assets/{Tooltip-DpDK7jWZ.js → Tooltip-D-zVPexc.js} +1 -1
  19. package/dist/assets/web/dist/assets/dist-D43zKxNV.js +1542 -0
  20. package/dist/assets/web/dist/assets/{main-BFkEOy3K.js → main-ClTMtz8n.js} +2 -2
  21. package/dist/cli.js +731 -273
  22. package/package.json +1 -1
  23. package/dist/assets/web/dist/assets/dist-B7BVkB7x.js +0 -1547
package/dist/cli.js CHANGED
@@ -2167,8 +2167,8 @@ var init_effort = __esm({
2167
2167
  });
2168
2168
 
2169
2169
  // ../../src/core/dashboardAuthConfig.ts
2170
- function resolveDashboardAuthMode(configured2, accessConfigured) {
2171
- if (configured2 !== void 0) return configured2;
2170
+ function resolveDashboardAuthMode(configured3, accessConfigured) {
2171
+ if (configured3 !== void 0) return configured3;
2172
2172
  return accessConfigured ? "access" : "none";
2173
2173
  }
2174
2174
  function tokenSubjectOf(actor) {
@@ -7582,6 +7582,159 @@ var init_imagesHost = __esm({
7582
7582
  }
7583
7583
  });
7584
7584
 
7585
+ // ../../src/deploy/artifactsBucket.ts
7586
+ function lifecycleRulesFor(retentionDays) {
7587
+ if (!Number.isInteger(retentionDays) || retentionDays < 1) {
7588
+ throw new Error(`retentionDays must be an integer >= 1, got ${String(retentionDays)}`);
7589
+ }
7590
+ return [
7591
+ {
7592
+ id: EXPIRE_RULE_ID,
7593
+ enabled: true,
7594
+ conditions: { prefix: "" },
7595
+ deleteObjectsTransition: { condition: { type: "Age", maxAge: retentionDays * DAY_SECONDS } }
7596
+ },
7597
+ {
7598
+ id: ABORT_RULE_ID,
7599
+ enabled: true,
7600
+ conditions: { prefix: "" },
7601
+ abortMultipartUploadsTransition: { condition: { type: "Age", maxAge: ABORT_MULTIPART_AFTER_DAYS * DAY_SECONDS } }
7602
+ }
7603
+ ];
7604
+ }
7605
+ function describeRules(rules) {
7606
+ return rules.map((r) => {
7607
+ const days = (s) => `${s / DAY_SECONDS} day${s === DAY_SECONDS ? "" : "s"}`;
7608
+ if (r.deleteObjectsTransition)
7609
+ return `${r.id}: delete every object ${days(r.deleteObjectsTransition.condition.maxAge)} after it was written`;
7610
+ if (r.abortMultipartUploadsTransition)
7611
+ return `${r.id}: abort an incomplete multipart upload after ${days(r.abortMultipartUploadsTransition.condition.maxAge)}`;
7612
+ return `${r.id}: (no transition)`;
7613
+ });
7614
+ }
7615
+ function rulesMatch(readBack, wanted) {
7616
+ const rules = Array.isArray(readBack?.rules) ? readBack.rules : null;
7617
+ if (!rules) return { ok: false, problem: "the read-back carries no `rules` array" };
7618
+ const problems = [];
7619
+ for (const want of wanted) {
7620
+ const got = rules.find((r) => r?.id === want.id);
7621
+ if (!got) {
7622
+ problems.push(`rule ${want.id} is missing`);
7623
+ continue;
7624
+ }
7625
+ if (got.enabled !== true) problems.push(`rule ${want.id} is not enabled`);
7626
+ const wantAge = want.deleteObjectsTransition?.condition.maxAge ?? want.abortMultipartUploadsTransition?.condition.maxAge;
7627
+ const gotAge = got.deleteObjectsTransition?.condition?.maxAge ?? got.abortMultipartUploadsTransition?.condition?.maxAge;
7628
+ if (gotAge !== wantAge) problems.push(`rule ${want.id} has maxAge ${String(gotAge)}, not ${String(wantAge)}`);
7629
+ }
7630
+ return problems.length === 0 ? { ok: true } : { ok: false, problem: problems.join("; ") };
7631
+ }
7632
+ function privacyOf(managed, custom) {
7633
+ const open = [];
7634
+ if (managed.enabled) open.push(`the managed r2.dev domain ${managed.domain} is enabled`);
7635
+ for (const d of custom) if (d.enabled) open.push(`the custom domain ${d.domain} is enabled`);
7636
+ return open.length === 0 ? { private: true, open: [] } : { private: false, open };
7637
+ }
7638
+ function bucketTokenMissingProblem() {
7639
+ return `${API_TOKEN_ENV} is not set \u2014 the bucket's lifecycle rules and domain settings are read and written with a Cloudflare API token holding Workers R2 Storage: Edit (Read suffices for \`artifacts check\`); the bot's ARTIFACTS_R2_* token cannot do this and is never used here`;
7640
+ }
7641
+ function bucketCallProblem(method, url, status3, text) {
7642
+ const words = text.trim().slice(0, 300);
7643
+ const permission = status3 === 401 || status3 === 403 ? ` \u2014 the token lacks the permission (Workers R2 Storage: ${method === "GET" ? "Read" : "Edit"} on this account)` : "";
7644
+ return `${method} ${url} answered HTTP ${status3}${permission}${words ? `: ${words}` : ""}`;
7645
+ }
7646
+ function artifactsBucketHost(options = {}) {
7647
+ const env = options.env ?? process.env;
7648
+ const fetchImpl = options.fetch ?? fetch;
7649
+ const call2 = async (method, path, body) => {
7650
+ const token2 = env[API_TOKEN_ENV]?.trim();
7651
+ if (!token2) return { ok: false, problem: bucketTokenMissingProblem() };
7652
+ const url = `${API}${path}`;
7653
+ let res;
7654
+ try {
7655
+ res = await fetchImpl(url, {
7656
+ method,
7657
+ headers: {
7658
+ authorization: `Bearer ${token2}`,
7659
+ ...body !== void 0 ? { "content-type": "application/json" } : {}
7660
+ },
7661
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
7662
+ });
7663
+ } catch (err2) {
7664
+ return { ok: false, problem: `${method} ${url} failed \u2014 ${err2 instanceof Error ? err2.message : String(err2)}` };
7665
+ }
7666
+ const text = await res.text().catch(() => "");
7667
+ if (!res.ok) return { ok: false, problem: bucketCallProblem(method, url, res.status, text) };
7668
+ let envelope;
7669
+ try {
7670
+ envelope = JSON.parse(text);
7671
+ } catch {
7672
+ return { ok: false, problem: `${method} ${url} answered HTTP ${res.status} with a body that is not JSON` };
7673
+ }
7674
+ if (envelope.success !== true) {
7675
+ const errors = Array.isArray(envelope.errors) ? envelope.errors.map((e) => e?.message ?? JSON.stringify(e)).join("; ") : "no error given";
7676
+ return { ok: false, problem: `${method} ${url} answered success: false \u2014 ${errors}` };
7677
+ }
7678
+ return { ok: true, value: envelope.result };
7679
+ };
7680
+ const bucketPath = (account2, bucket, tail) => `/accounts/${encodeURIComponent(account2)}/r2/buckets/${encodeURIComponent(bucket)}/${tail}`;
7681
+ return {
7682
+ async putLifecycle(account2, bucket, rules) {
7683
+ const r = await call2("PUT", bucketPath(account2, bucket, "lifecycle"), { rules });
7684
+ return r.ok ? { ok: true, value: void 0 } : r;
7685
+ },
7686
+ getLifecycle(account2, bucket) {
7687
+ return call2("GET", bucketPath(account2, bucket, "lifecycle"));
7688
+ },
7689
+ async managedDomain(account2, bucket) {
7690
+ const r = await call2("GET", bucketPath(account2, bucket, "domains/managed"));
7691
+ if (!r.ok) return r;
7692
+ const v = r.value;
7693
+ if (!v || typeof v.domain !== "string" || typeof v.enabled !== "boolean") {
7694
+ return {
7695
+ ok: false,
7696
+ problem: `the managed-domain answer has no domain/enabled: ${JSON.stringify(r.value).slice(0, 200)}`
7697
+ };
7698
+ }
7699
+ return { ok: true, value: { domain: v.domain, enabled: v.enabled } };
7700
+ },
7701
+ async customDomains(account2, bucket) {
7702
+ const r = await call2("GET", bucketPath(account2, bucket, "domains/custom"));
7703
+ if (!r.ok) return r;
7704
+ const list = r.value?.domains;
7705
+ if (!Array.isArray(list)) {
7706
+ return {
7707
+ ok: false,
7708
+ problem: `the custom-domains answer has no domains array: ${JSON.stringify(r.value).slice(0, 200)}`
7709
+ };
7710
+ }
7711
+ const domains = [];
7712
+ for (const d of list) {
7713
+ if (typeof d?.domain !== "string" || typeof d.enabled !== "boolean") {
7714
+ return {
7715
+ ok: false,
7716
+ problem: `a custom domain entry has no domain/enabled: ${JSON.stringify(d).slice(0, 200)}`
7717
+ };
7718
+ }
7719
+ domains.push({ domain: d.domain, enabled: d.enabled });
7720
+ }
7721
+ return { ok: true, value: domains };
7722
+ }
7723
+ };
7724
+ }
7725
+ var ABORT_MULTIPART_AFTER_DAYS, DAY_SECONDS, EXPIRE_RULE_ID, ABORT_RULE_ID, API;
7726
+ var init_artifactsBucket = __esm({
7727
+ "../../src/deploy/artifactsBucket.ts"() {
7728
+ "use strict";
7729
+ init_imagesHost();
7730
+ ABORT_MULTIPART_AFTER_DAYS = 1;
7731
+ DAY_SECONDS = 86400;
7732
+ EXPIRE_RULE_ID = "switchboard-artifacts-expire";
7733
+ ABORT_RULE_ID = "switchboard-artifacts-abort-multipart";
7734
+ API = "https://api.cloudflare.com/client/v4";
7735
+ }
7736
+ });
7737
+
7585
7738
  // ../../src/deploy/secrets.ts
7586
7739
  import { z as z3 } from "zod";
7587
7740
  function isOptionalOn(secret2, worker) {
@@ -7842,6 +7995,7 @@ var init_runEvents = __esm({
7842
7995
  "mcp_unavailable",
7843
7996
  "follow_up",
7844
7997
  "resumed",
7998
+ "seed",
7845
7999
  "description_turn",
7846
8000
  "cold_sandbox",
7847
8001
  "pr_not_opened",
@@ -11997,8 +12151,110 @@ var init_commandRegistry = __esm({
11997
12151
  }
11998
12152
  });
11999
12153
 
12000
- // ../../src/core/commands/config.ts
12154
+ // ../../src/core/commands/artifacts.ts
12001
12155
  import { z as z5 } from "zod";
12156
+ async function configured2(deps) {
12157
+ const cfg = await deps.artifacts.config();
12158
+ if (!cfg) {
12159
+ throw new CommandError(
12160
+ "unavailable",
12161
+ "artifacts: is not configured \u2014 name the bucket under `artifacts.r2` in config.yaml before managing it (docs/how-to/store-run-artifacts.md)"
12162
+ );
12163
+ }
12164
+ return cfg;
12165
+ }
12166
+ function registerArtifactsCommands(registry) {
12167
+ for (const cmd of artifactsCommands) registry.register(cmd);
12168
+ }
12169
+ var defineCommand2, lifecycleOptions, artifactsLifecycle, artifactsCheck, artifactsCommands;
12170
+ var init_artifacts = __esm({
12171
+ "../../src/core/commands/artifacts.ts"() {
12172
+ "use strict";
12173
+ init_config();
12174
+ init_artifactsBucket();
12175
+ init_commandRegistry();
12176
+ defineCommand2 = commandDefiner();
12177
+ lifecycleOptions = z5.object({
12178
+ dryRun: flag.optional().describe("print the rules that would be applied and touch nothing")
12179
+ });
12180
+ artifactsLifecycle = defineCommand2({
12181
+ id: "artifacts.lifecycle",
12182
+ options: lifecycleOptions,
12183
+ action: "deploy:write",
12184
+ effect: "write",
12185
+ surfaces: { chat: false, mcp: false, http: false },
12186
+ describe: "Apply the artifacts bucket's lifecycle rules from config.yaml \u2014 objects expire after `artifacts.retentionDays` (default 30), incomplete multipart uploads abort after one day \u2014 and read them back; `--dry-run` prints the rules and touches nothing. Operator-side: CLOUDFLARE_API_TOKEN with Workers R2 Storage: Edit, never the bot's token.",
12187
+ render: (output) => {
12188
+ const o = output;
12189
+ const lines = describeRules(o.rules).map((l) => ` - ${l}`);
12190
+ const head = o.applied ? `applied ${o.rules.length} lifecycle rule(s) to ${o.bucket} (account ${o.account}) and read them back equal:` : `dry run \u2014 would apply ${o.rules.length} lifecycle rule(s) to ${o.bucket} (account ${o.account}); nothing touched:`;
12191
+ return [head, ...lines].join("\n");
12192
+ },
12193
+ handler: async ({ options, deps }) => {
12194
+ const cfg = await configured2(deps);
12195
+ const retentionDays = cfg.retentionDays ?? ARTIFACT_DEFAULTS.retentionDays;
12196
+ const rules = lifecycleRulesFor(retentionDays);
12197
+ const { accountId: account2, bucket } = cfg.r2;
12198
+ const out = { account: account2, bucket, retentionDays, rules, applied: false, readBack: false };
12199
+ if (options.dryRun) return out;
12200
+ const put = await deps.artifacts.bucket.putLifecycle(account2, bucket, rules);
12201
+ if (!put.ok)
12202
+ throw new CommandError("unavailable", `applying the lifecycle rules to ${bucket} failed \u2014 ${put.problem}`);
12203
+ const read = await deps.artifacts.bucket.getLifecycle(account2, bucket);
12204
+ if (!read.ok)
12205
+ throw new CommandError(
12206
+ "unavailable",
12207
+ `the rules were applied to ${bucket} but reading them back failed \u2014 ${read.problem}; run \`artifacts lifecycle\` again to confirm`
12208
+ );
12209
+ const match = rulesMatch(read.value, rules);
12210
+ if (!match.ok)
12211
+ throw new CommandError(
12212
+ "unavailable",
12213
+ `the rules were applied to ${bucket} but the read-back differs \u2014 ${match.problem}; the bucket's configuration is not what config.yaml says`
12214
+ );
12215
+ return { ...out, applied: true, readBack: true };
12216
+ }
12217
+ });
12218
+ artifactsCheck = defineCommand2({
12219
+ id: "artifacts.check",
12220
+ action: "deploy:write",
12221
+ effect: "read",
12222
+ surfaces: { chat: false, mcp: false, http: false },
12223
+ describe: "Report whether the artifacts bucket is private: its managed r2.dev domain must be disabled and no custom domain enabled \u2014 the two ways R2 serves a bucket without a signature. Operator-side: CLOUDFLARE_API_TOKEN with Workers R2 Storage: Read, never the bot's token.",
12224
+ render: (output) => {
12225
+ const o = output;
12226
+ if (o.private) {
12227
+ return `${o.bucket} (account ${o.account}) is private: the managed domain ${o.managedDomain.domain} is disabled and ${o.customDomains.length === 0 ? "no custom domain is attached" : `none of its ${o.customDomains.length} custom domain(s) is enabled`}`;
12228
+ }
12229
+ return [`${o.bucket} (account ${o.account}) is NOT private:`, ...o.open.map((l) => ` - ${l}`)].join("\n");
12230
+ },
12231
+ handler: async ({ deps }) => {
12232
+ const cfg = await configured2(deps);
12233
+ const { accountId: account2, bucket } = cfg.r2;
12234
+ const managed = await deps.artifacts.bucket.managedDomain(account2, bucket);
12235
+ if (!managed.ok)
12236
+ throw new CommandError("unavailable", `reading ${bucket}'s managed domain failed \u2014 ${managed.problem}`);
12237
+ const custom = await deps.artifacts.bucket.customDomains(account2, bucket);
12238
+ if (!custom.ok)
12239
+ throw new CommandError("unavailable", `reading ${bucket}'s custom domains failed \u2014 ${custom.problem}`);
12240
+ const verdict = privacyOf(managed.value, custom.value);
12241
+ const out = {
12242
+ account: account2,
12243
+ bucket,
12244
+ private: verdict.private,
12245
+ open: [...verdict.open],
12246
+ managedDomain: managed.value,
12247
+ customDomains: custom.value
12248
+ };
12249
+ return out;
12250
+ }
12251
+ });
12252
+ artifactsCommands = [artifactsLifecycle, artifactsCheck];
12253
+ }
12254
+ });
12255
+
12256
+ // ../../src/core/commands/config.ts
12257
+ import { z as z6 } from "zod";
12002
12258
  function targetChannel(caller, channel) {
12003
12259
  const target = channel ?? caller.origin?.channelId;
12004
12260
  if (!target) throw new CommandError("invalid_input", "channel: required on this surface \u2014 pass --channel <id>");
@@ -12018,7 +12274,7 @@ function summarizeScope(s) {
12018
12274
  function registerConfigCommands(registry) {
12019
12275
  for (const cmd of configCommands) registry.register(cmd);
12020
12276
  }
12021
- var defineCommand2, scopeArg, channelOption, effort, effortLevels, modelRef, boundaryOption, who, configShow, configSet, configClear, quote, configInstructions, configCommands;
12277
+ var defineCommand3, scopeArg, channelOption, effort, effortLevels, modelRef, boundaryOption, who, configShow, configSet, configClear, quote, configInstructions, configCommands;
12022
12278
  var init_config4 = __esm({
12023
12279
  "../../src/core/commands/config.ts"() {
12024
12280
  "use strict";
@@ -12028,25 +12284,25 @@ var init_config4 = __esm({
12028
12284
  init_effort();
12029
12285
  init_authorize();
12030
12286
  init_commandRegistry();
12031
- defineCommand2 = commandDefiner();
12287
+ defineCommand3 = commandDefiner();
12032
12288
  scopeArg = {
12033
12289
  name: "scope",
12034
- schema: z5.enum(["channel", "me"]),
12290
+ schema: z6.enum(["channel", "me"]),
12035
12291
  describe: "`channel` (everyone here) or `me` (your own runs)"
12036
12292
  };
12037
- channelOption = z5.string().optional().describe("target channel (default: the channel you are speaking in)");
12038
- effort = z5.enum(EFFORT_LEVELS);
12293
+ channelOption = z6.string().optional().describe("target channel (default: the channel you are speaking in)");
12294
+ effort = z6.enum(EFFORT_LEVELS);
12039
12295
  effortLevels = `<${EFFORT_LEVELS.join("|")}>`;
12040
- modelRef = z5.string().min(1);
12041
- boundaryOption = z5.object({
12042
- maxMinutes: z5.coerce.number().int().min(MIN_BOUNDARY_MINUTES).optional().describe(`cap the wall-clock budget of every run in this scope (minutes, >= ${MIN_BOUNDARY_MINUTES})`),
12043
- maxIdentity: z5.enum(IDENTITIES).optional().describe(`cap the identity runs may act as <${IDENTITIES.join("|")}> \u2014 a preset above it is refused`),
12044
- machines: z5.string().optional().describe(`the machine classes runs may execute on, comma-separated from ${MACHINE_CLASSES.join(", ")}`)
12296
+ modelRef = z6.string().min(1);
12297
+ boundaryOption = z6.object({
12298
+ maxMinutes: z6.coerce.number().int().min(MIN_BOUNDARY_MINUTES).optional().describe(`cap the wall-clock budget of every run in this scope (minutes, >= ${MIN_BOUNDARY_MINUTES})`),
12299
+ maxIdentity: z6.enum(IDENTITIES).optional().describe(`cap the identity runs may act as <${IDENTITIES.join("|")}> \u2014 a preset above it is refused`),
12300
+ machines: z6.string().optional().describe(`the machine classes runs may execute on, comma-separated from ${MACHINE_CLASSES.join(", ")}`)
12045
12301
  }).optional();
12046
12302
  who = (scope) => scope === "channel" ? "channel" : "your";
12047
- configShow = defineCommand2({
12303
+ configShow = defineCommand3({
12048
12304
  id: "config.show",
12049
- options: z5.object({ channel: channelOption }),
12305
+ options: z6.object({ channel: channelOption }),
12050
12306
  action: "config:read",
12051
12307
  effect: "read",
12052
12308
  describe: "The effective agent/model/effort for you in this channel, the defaults, both scopes, and what is restricted.",
@@ -12060,15 +12316,15 @@ var init_config4 = __esm({
12060
12316
  return description;
12061
12317
  }
12062
12318
  });
12063
- configSet = defineCommand2({
12319
+ configSet = defineCommand3({
12064
12320
  id: "config.set",
12065
12321
  args: [scopeArg],
12066
- options: z5.object({
12067
- agent: z5.string().min(1).optional().describe("force which agent handles requests in this scope"),
12322
+ options: z6.object({
12323
+ agent: z6.string().min(1).optional().describe("force which agent handles requests in this scope"),
12068
12324
  model: modelRef.optional().describe("force a model (provider/model) regardless of agent"),
12069
- models: z5.record(z5.string(), modelRef).optional().describe("per-agent model: --models.<agent> provider/model"),
12325
+ models: z6.record(z6.string(), modelRef).optional().describe("per-agent model: --models.<agent> provider/model"),
12070
12326
  effort: effort.optional().describe(`force a model effort ${effortLevels}`),
12071
- efforts: z5.record(z5.string(), effort).optional().describe(`per-agent effort: --efforts.<agent> ${effortLevels}`),
12327
+ efforts: z6.record(z6.string(), effort).optional().describe(`per-agent effort: --efforts.<agent> ${effortLevels}`),
12072
12328
  boundary: boundaryOption,
12073
12329
  channel: channelOption
12074
12330
  }),
@@ -12135,10 +12391,10 @@ var init_config4 = __esm({
12135
12391
  return { scope: args.scope, effective: summarizeScope(effective) };
12136
12392
  }
12137
12393
  });
12138
- configClear = defineCommand2({
12394
+ configClear = defineCommand3({
12139
12395
  id: "config.clear",
12140
12396
  args: [scopeArg],
12141
- options: z5.object({ channel: channelOption }),
12397
+ options: z6.object({ channel: channelOption }),
12142
12398
  action: "config:write",
12143
12399
  effect: "write",
12144
12400
  describe: "Drop every runtime override of a channel (gated) or of yourself; static config.yaml values show through again.",
@@ -12155,18 +12411,18 @@ var init_config4 = __esm({
12155
12411
  }
12156
12412
  });
12157
12413
  quote = (text) => `> ${text.replace(/\n/g, "\n> ")}`;
12158
- configInstructions = defineCommand2({
12414
+ configInstructions = defineCommand3({
12159
12415
  id: "config.instructions",
12160
12416
  args: [
12161
12417
  scopeArg,
12162
12418
  {
12163
12419
  name: "text",
12164
- schema: z5.string().optional(),
12420
+ schema: z6.string().optional(),
12165
12421
  describe: 'the instructions; omit to show the current text, pass "" to clear',
12166
12422
  rest: true
12167
12423
  }
12168
12424
  ],
12169
- options: z5.object({ channel: channelOption }),
12425
+ options: z6.object({ channel: channelOption }),
12170
12426
  action: "config:write",
12171
12427
  effect: "write",
12172
12428
  describe: "Custom instructions for a channel (gated) or for yourself \u2014 advisory prompt content that never changes agent, model, or permissions.",
@@ -12227,7 +12483,7 @@ ${quote(current ?? "")}`;
12227
12483
 
12228
12484
  // ../../src/core/commands/contract.ts
12229
12485
  import { basename, dirname as dirname8, join as join10 } from "node:path";
12230
- import { z as z6 } from "zod";
12486
+ import { z as z7 } from "zod";
12231
12487
  function repoRootOfPlan(planPath) {
12232
12488
  const plans = dirname8(planPath);
12233
12489
  const docs = dirname8(plans);
@@ -12245,24 +12501,24 @@ function renderOutput(output) {
12245
12501
  function registerContractCommands(registry) {
12246
12502
  for (const cmd of contractCommands) registry.register(cmd);
12247
12503
  }
12248
- var defineCommand3, SPECS_DIR, RULES_FILES, contractRender, contractCommands;
12504
+ var defineCommand4, SPECS_DIR, RULES_FILES, contractRender, contractCommands;
12249
12505
  var init_contract2 = __esm({
12250
12506
  "../../src/core/commands/contract.ts"() {
12251
12507
  "use strict";
12252
12508
  init_commandRegistry();
12253
12509
  init_contract();
12254
- defineCommand3 = commandDefiner();
12510
+ defineCommand4 = commandDefiner();
12255
12511
  SPECS_DIR = join10("docs", "reference", "specs");
12256
12512
  RULES_FILES = ["AGENTS.md", "CLAUDE.md"];
12257
- contractRender = defineCommand3({
12513
+ contractRender = defineCommand4({
12258
12514
  id: "contract.render",
12259
- options: z6.object({
12260
- plan: z6.string().min(1).describe("path of the plan record (docs/plans/<file>.md)"),
12261
- unit: z6.string().regex(/^U\d+$/, "expected a unit id like U<n>").describe("the unit to render, as its heading spells it (U<n>)"),
12262
- root: z6.string().min(1).optional().describe("the repository root the specs and rules are read under (default: the root the plan path implies)"),
12263
- branch: z6.string().min(1).optional().describe("the unit's branch, named in the first instruction"),
12264
- onto: z6.string().min(1).optional().describe("the merged parent the branch is rebased onto"),
12265
- maxChars: z6.coerce.number().int().positive().optional().describe(`the rendered block's budget in characters (default ${DEFAULT_CONTRACT_MAX_CHARS})`)
12515
+ options: z7.object({
12516
+ plan: z7.string().min(1).describe("path of the plan record (docs/plans/<file>.md)"),
12517
+ unit: z7.string().regex(/^U\d+$/, "expected a unit id like U<n>").describe("the unit to render, as its heading spells it (U<n>)"),
12518
+ root: z7.string().min(1).optional().describe("the repository root the specs and rules are read under (default: the root the plan path implies)"),
12519
+ branch: z7.string().min(1).optional().describe("the unit's branch, named in the first instruction"),
12520
+ onto: z7.string().min(1).optional().describe("the merged parent the branch is rebased onto"),
12521
+ maxChars: z7.coerce.number().int().positive().optional().describe(`the rendered block's budget in characters (default ${DEFAULT_CONTRACT_MAX_CHARS})`)
12266
12522
  }),
12267
12523
  action: "contract:read",
12268
12524
  effect: "read",
@@ -13909,7 +14165,7 @@ var init_runRecord = __esm({
13909
14165
  RUN_STATUSES = ["completed", "stopped_soft", "stopped_hard", "failed", "interrupted"];
13910
14166
  RUN_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
13911
14167
  REVIEW_HEAD_PATTERN = /^[0-9a-f]{7,40}$/;
13912
- RUN_SEEDS = ["channel", "parent"];
14168
+ RUN_SEEDS = ["channel", "parent", "session"];
13913
14169
  SESSION_KEY_PATTERN = /^[A-Za-z0-9_.:@+/-]{1,512}$/;
13914
14170
  isIndex = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0;
13915
14171
  MACHINE_CLASSES_IN_RECORD = {
@@ -13954,11 +14210,11 @@ var init_runRecord = __esm({
13954
14210
  });
13955
14211
 
13956
14212
  // ../../src/core/commands/delivery.ts
13957
- import { z as z7 } from "zod";
14213
+ import { z as z8 } from "zod";
13958
14214
  function registerDeliveryCommands(registry) {
13959
14215
  for (const cmd of deliveryCommands) registry.register(cmd);
13960
14216
  }
13961
- var defineCommand4, REPO_SLUG3, ISO_DAY3, asJson, deliveryReport, deliveryCommands;
14217
+ var defineCommand5, REPO_SLUG3, ISO_DAY3, asJson, deliveryReport, deliveryCommands;
13962
14218
  var init_delivery2 = __esm({
13963
14219
  "../../src/core/commands/delivery.ts"() {
13964
14220
  "use strict";
@@ -13966,16 +14222,16 @@ var init_delivery2 = __esm({
13966
14222
  init_commandRegistry();
13967
14223
  init_delivery();
13968
14224
  init_runRecord();
13969
- defineCommand4 = commandDefiner();
14225
+ defineCommand5 = commandDefiner();
13970
14226
  REPO_SLUG3 = /^(?!\.+\/)[\w.-]+\/(?!\.+$)[\w.-]+$/;
13971
14227
  ISO_DAY3 = /^\d{4}-\d{2}-\d{2}$/;
13972
14228
  asJson = (v) => v;
13973
- deliveryReport = defineCommand4({
14229
+ deliveryReport = defineCommand5({
13974
14230
  id: "delivery.report",
13975
- options: z7.object({
13976
- repo: z7.string().regex(REPO_SLUG3).optional().describe("the repository (`owner/name`); default: the first under `delivery.repos`"),
13977
- since: z7.string().regex(ISO_DAY3).optional().describe("the first day of the range (`YYYY-MM-DD`, UTC); the range ends today"),
13978
- weeks: z7.coerce.number().int().min(1).max(MAX_WEEKS).optional().describe(
14231
+ options: z8.object({
14232
+ repo: z8.string().regex(REPO_SLUG3).optional().describe("the repository (`owner/name`); default: the first under `delivery.repos`"),
14233
+ since: z8.string().regex(ISO_DAY3).optional().describe("the first day of the range (`YYYY-MM-DD`, UTC); the range ends today"),
14234
+ weeks: z8.coerce.number().int().min(1).max(MAX_WEEKS).optional().describe(
13979
14235
  `Monday-start weeks back from this one (default 4, at most ${MAX_WEEKS}); --since, when given, decides instead`
13980
14236
  ),
13981
14237
  fresh: flag.optional().describe("read GitHub now instead of the repository's snapshot, and refresh the snapshot")
@@ -14020,7 +14276,7 @@ var init_delivery2 = __esm({
14020
14276
  });
14021
14277
 
14022
14278
  // ../../src/core/commands/deploy.ts
14023
- import { z as z8 } from "zod";
14279
+ import { z as z9 } from "zod";
14024
14280
  function toOptions(o, dryRun, affected) {
14025
14281
  return {
14026
14282
  only: o.only,
@@ -14130,7 +14386,7 @@ async function copyImages(copies, account2, deps) {
14130
14386
  function registerDeployCommands(registry) {
14131
14387
  for (const cmd of deployCommands) registry.register(cmd);
14132
14388
  }
14133
- var defineCommand5, workerList, positiveInt, gitRef, deployOptions, planJson, deployPlan, allOptions, copiedImage, listCopies, deployAll, restartOptions, deployRestart, initOptions, deployInit, configOptions, deployConfig, secretNames, secretsOptions, deploySecrets, imagesOptions, deployImages, deployCommands;
14389
+ var defineCommand6, workerList, positiveInt, gitRef, deployOptions, planJson, deployPlan, allOptions, copiedImage, listCopies, deployAll, restartOptions, deployRestart, initOptions, deployInit, configOptions, deployConfig, secretNames, secretsOptions, deploySecrets, imagesOptions, deployImages, deployCommands;
14134
14390
  var init_deploy = __esm({
14135
14391
  "../../src/core/commands/deploy.ts"() {
14136
14392
  "use strict";
@@ -14143,16 +14399,16 @@ var init_deploy = __esm({
14143
14399
  init_wranglerTemplate();
14144
14400
  init_secrets();
14145
14401
  init_commandRegistry();
14146
- defineCommand5 = commandDefiner();
14147
- workerList = z8.string().transform(
14402
+ defineCommand6 = commandDefiner();
14403
+ workerList = z9.string().transform(
14148
14404
  (s) => s.split(",").map((x) => x.trim()).filter(Boolean)
14149
14405
  ).refine(
14150
14406
  (names) => names.every((n2) => DEPLOY_ORDER.includes(n2)),
14151
14407
  `expected a comma list of Workers (${DEPLOY_ORDER.join(", ")})`
14152
14408
  ).transform((names) => [...new Set(names)]);
14153
- positiveInt = z8.coerce.number().int().positive();
14154
- gitRef = z8.string().regex(/^[A-Za-z0-9_./^~@{}][A-Za-z0-9_./^~@{}-]{0,199}$/, "expected a git revision (a sha, tag, branch, or HEAD^)");
14155
- deployOptions = z8.object({
14409
+ positiveInt = z9.coerce.number().int().positive();
14410
+ gitRef = z9.string().regex(/^[A-Za-z0-9_./^~@{}][A-Za-z0-9_./^~@{}-]{0,199}$/, "expected a git revision (a sha, tag, branch, or HEAD^)");
14411
+ deployOptions = z9.object({
14156
14412
  only: workerList.optional().describe(
14157
14413
  `deploy only these Workers (comma list of ${DEPLOY_ORDER.join(", ")}); with --affected, only those of them that are affected`
14158
14414
  ),
@@ -14171,7 +14427,7 @@ var init_deploy = __esm({
14171
14427
  poll: positiveInt.optional().describe("seconds between preflight retries (default 60)")
14172
14428
  });
14173
14429
  planJson = (plan3) => plan3;
14174
- deployPlan = defineCommand5({
14430
+ deployPlan = defineCommand6({
14175
14431
  id: "deploy.plan",
14176
14432
  options: deployOptions,
14177
14433
  action: "deploy:read",
@@ -14187,7 +14443,7 @@ var init_deploy = __esm({
14187
14443
  });
14188
14444
  copiedImage = (c) => ({ kind: c.kind, source: c.source, target: c.target });
14189
14445
  listCopies = (copies) => copies.map((c) => `${c.kind} \u2190 ${c.source}`).join(", ");
14190
- deployAll = defineCommand5({
14446
+ deployAll = defineCommand6({
14191
14447
  id: "deploy.all",
14192
14448
  options: allOptions,
14193
14449
  action: "deploy:write",
@@ -14238,15 +14494,15 @@ ${formatDeployResults(result.results, result.notAttempted)}`
14238
14494
  return output(result.results, copies, []);
14239
14495
  }
14240
14496
  });
14241
- restartOptions = z8.object({
14242
- only: z8.enum(["bot"]).optional().describe("the Worker to restart \u2014 only `bot` has a long-lived container (default bot)"),
14497
+ restartOptions = z9.object({
14498
+ only: z9.enum(["bot"]).optional().describe("the Worker to restart \u2014 only `bot` has a long-lived container (default bot)"),
14243
14499
  force: flag.optional().describe(
14244
14500
  "restart even when the bot cannot be consulted (no JSON on /healthz) \u2014 the fail-closed cases; runs in flight never refuse, they hand off"
14245
14501
  ),
14246
14502
  waitMax: positiveInt.optional().describe("minutes to wait out a refusal (the bot not answering with JSON) before giving up (default 10)"),
14247
14503
  poll: positiveInt.optional().describe("seconds between retries while refused (default 60)")
14248
14504
  });
14249
- deployRestart = defineCommand5({
14505
+ deployRestart = defineCommand6({
14250
14506
  id: "deploy.restart",
14251
14507
  options: restartOptions,
14252
14508
  action: "deploy:write",
@@ -14287,12 +14543,12 @@ ${formatDeployResults(result.results, result.notAttempted)}`
14287
14543
  };
14288
14544
  }
14289
14545
  });
14290
- initOptions = z8.object({
14546
+ initOptions = z9.object({
14291
14547
  check: flag.optional().describe(
14292
14548
  "compare only: report each rendered file that differs from the one on disk and fail when any does (the `deploy:check` gate); nothing is written"
14293
14549
  )
14294
14550
  });
14295
- deployInit = defineCommand5({
14551
+ deployInit = defineCommand6({
14296
14552
  id: "deploy.init",
14297
14553
  options: initOptions,
14298
14554
  action: "deploy:write",
@@ -14339,12 +14595,12 @@ ${formatDeployResults(result.results, result.notAttempted)}`
14339
14595
  return output;
14340
14596
  }
14341
14597
  });
14342
- configOptions = z8.object({
14343
- source: z8.string().min(1).optional().describe(
14598
+ configOptions = z9.object({
14599
+ source: z9.string().min(1).optional().describe(
14344
14600
  "read the config from this source instead of the profile's configSource (a path, github://owner/repo/path@ref, or op://Vault/Item/field)"
14345
14601
  )
14346
14602
  });
14347
- deployConfig = defineCommand5({
14603
+ deployConfig = defineCommand6({
14348
14604
  id: "deploy.config",
14349
14605
  options: configOptions,
14350
14606
  action: "deploy:write",
@@ -14379,21 +14635,21 @@ the bot reads it on its next start: \`deploy restart\``;
14379
14635
  return output;
14380
14636
  }
14381
14637
  });
14382
- secretNames = z8.string().transform(
14638
+ secretNames = z9.string().transform(
14383
14639
  (s) => s.split(",").map((x) => x.trim()).filter(Boolean)
14384
14640
  ).refine(
14385
14641
  (names) => names.length > 0 && names.every((n2) => /^[A-Z][A-Z0-9_]*$/.test(n2)),
14386
14642
  "expected a comma list of secret names (SCREAMING_SNAKE)"
14387
14643
  ).transform((names) => [...new Set(names)]);
14388
- secretsOptions = z8.object({
14644
+ secretsOptions = z9.object({
14389
14645
  only: secretNames.optional().describe("put only these secrets (comma list of names from deploy/secrets.manifest.json)")
14390
14646
  });
14391
- deploySecrets = defineCommand5({
14647
+ deploySecrets = defineCommand6({
14392
14648
  id: "deploy.secrets",
14393
14649
  args: [
14394
14650
  {
14395
14651
  name: "worker",
14396
- schema: z8.enum(DEPLOY_ORDER),
14652
+ schema: z9.enum(DEPLOY_ORDER),
14397
14653
  describe: `the Worker to provision (${DEPLOY_ORDER.join(", ")})`
14398
14654
  }
14399
14655
  ],
@@ -14455,12 +14711,12 @@ the bot reads it on its next start: \`deploy restart\``;
14455
14711
  return output;
14456
14712
  }
14457
14713
  });
14458
- imagesOptions = z8.object({
14714
+ imagesOptions = z9.object({
14459
14715
  dryRun: flag.optional().describe(
14460
14716
  "say which images the account registry already holds at the version and which would be copied; nothing is copied"
14461
14717
  )
14462
14718
  });
14463
- deployImages = defineCommand5({
14719
+ deployImages = defineCommand6({
14464
14720
  id: "deploy.images",
14465
14721
  options: imagesOptions,
14466
14722
  action: "deploy:write",
@@ -14511,25 +14767,25 @@ the bot reads it on its next start: \`deploy restart\``;
14511
14767
  });
14512
14768
 
14513
14769
  // ../../src/core/commands/env.ts
14514
- import { z as z9 } from "zod";
14770
+ import { z as z10 } from "zod";
14515
14771
  function registerEnvCommands(registry) {
14516
14772
  for (const cmd of envCommands) registry.register(cmd);
14517
14773
  }
14518
- var defineCommand6, envBootstrap, envCommands;
14774
+ var defineCommand7, envBootstrap, envCommands;
14519
14775
  var init_env = __esm({
14520
14776
  "../../src/core/commands/env.ts"() {
14521
14777
  "use strict";
14522
14778
  init_bootstrap();
14523
14779
  init_commandRegistry();
14524
- defineCommand6 = commandDefiner();
14525
- envBootstrap = defineCommand6({
14780
+ defineCommand7 = commandDefiner();
14781
+ envBootstrap = defineCommand7({
14526
14782
  id: "env.bootstrap",
14527
- options: z9.object({
14528
- env: z9.string().min(1).describe("environment to materialize (UAT only; anything else is refused)"),
14529
- service: z9.string().min(1).describe("which downstream service's toolchain env to fill"),
14783
+ options: z10.object({
14784
+ env: z10.string().min(1).describe("environment to materialize (UAT only; anything else is refused)"),
14785
+ service: z10.string().min(1).describe("which downstream service's toolchain env to fill"),
14530
14786
  apply: flag.optional().describe("resolve the refs and WRITE the chmod-600 env file (default: dry-run)"),
14531
- out: z9.string().min(1).optional().describe("env-file path (default .agent-env/<service>.<env>.env)"),
14532
- manifest: z9.string().min(1).optional().describe(`manifest path (default ${DEFAULT_MANIFEST_PATH})`)
14787
+ out: z10.string().min(1).optional().describe("env-file path (default .agent-env/<service>.<env>.env)"),
14788
+ manifest: z10.string().min(1).optional().describe(`manifest path (default ${DEFAULT_MANIFEST_PATH})`)
14533
14789
  }),
14534
14790
  action: "env:write",
14535
14791
  effect: "write",
@@ -15263,7 +15519,7 @@ var init_selfImprovement = __esm({
15263
15519
  });
15264
15520
 
15265
15521
  // ../../src/core/commands/friction.ts
15266
- import { z as z10 } from "zod";
15522
+ import { z as z11 } from "zod";
15267
15523
  async function ledgerOf(deps) {
15268
15524
  let ledger;
15269
15525
  try {
@@ -15291,7 +15547,7 @@ function inProgressHint(diagnosis, finished) {
15291
15547
  function registerFrictionCommands(registry) {
15292
15548
  for (const cmd of frictionCommands) registry.register(cmd);
15293
15549
  }
15294
- var defineCommand7, positiveInt2, repoSlug, NO_LEDGER_MESSAGE, NO_REPO_MESSAGE, asJson2, render, visibleRuns, frictionReport, frictionPropose, frictionAnalyze, frictionCommands;
15550
+ var defineCommand8, positiveInt2, repoSlug, NO_LEDGER_MESSAGE, NO_REPO_MESSAGE, asJson2, render, visibleRuns, frictionReport, frictionPropose, frictionAnalyze, frictionCommands;
15295
15551
  var init_friction = __esm({
15296
15552
  "../../src/core/commands/friction.ts"() {
15297
15553
  "use strict";
@@ -15302,19 +15558,19 @@ var init_friction = __esm({
15302
15558
  init_runEventLines();
15303
15559
  init_runFriction();
15304
15560
  init_selfImprovement();
15305
- defineCommand7 = commandDefiner();
15306
- positiveInt2 = z10.coerce.number().int().positive();
15307
- repoSlug = z10.string().refine((s) => /^[\w.-]+\/[\w.-]+$/.test(s), "expected an owner/name slug");
15561
+ defineCommand8 = commandDefiner();
15562
+ positiveInt2 = z11.coerce.number().int().positive();
15563
+ repoSlug = z11.string().refine((s) => /^[\w.-]+\/[\w.-]+$/.test(s), "expected an owner/name slug");
15308
15564
  NO_LEDGER_MESSAGE = "Run history is not configured in this deployment (`runHistory`), so there are no recent runs to analyze.";
15309
15565
  NO_REPO_MESSAGE = "Set `selfImprovement.repo` (an `owner/name`) in config.yaml to tell `friction propose` where to file issues.";
15310
15566
  asJson2 = (r) => r;
15311
15567
  render = (output) => formatSelfImprovementReport(output);
15312
15568
  visibleRuns = (caller) => predicateFor(caller.actor, "runs:read", "run");
15313
- frictionReport = defineCommand7({
15569
+ frictionReport = defineCommand8({
15314
15570
  id: "friction.report",
15315
15571
  enabledWhen: (caps) => caps.runHistory,
15316
- options: z10.object({
15317
- sinceMs: z10.coerce.number().int().nonnegative().optional().describe("only runs finished at or after this epoch ms"),
15572
+ options: z11.object({
15573
+ sinceMs: z11.coerce.number().int().nonnegative().optional().describe("only runs finished at or after this epoch ms"),
15318
15574
  limit: positiveInt2.optional().describe("newest n runs (default: the ledger's retained window)"),
15319
15575
  minRuns: positiveInt2.optional().describe("distinct runs a pattern must recur in (default selfImprovement.minRuns, else 2)")
15320
15576
  }),
@@ -15340,10 +15596,10 @@ var init_friction = __esm({
15340
15596
  });
15341
15597
  }
15342
15598
  });
15343
- frictionPropose = defineCommand7({
15599
+ frictionPropose = defineCommand8({
15344
15600
  id: "friction.propose",
15345
15601
  enabledWhen: (caps) => caps.runHistory,
15346
- options: z10.object({
15602
+ options: z11.object({
15347
15603
  dryRun: flag.optional().describe("compute and report everything, file nothing"),
15348
15604
  top: positiveInt2.optional().describe("proposals filed per pass (default selfImprovement.top, else 3)"),
15349
15605
  minRuns: positiveInt2.optional().describe("distinct runs a pattern must recur in (default selfImprovement.minRuns, else 2)"),
@@ -15375,17 +15631,17 @@ var init_friction = __esm({
15375
15631
  }
15376
15632
  }
15377
15633
  });
15378
- frictionAnalyze = defineCommand7({
15634
+ frictionAnalyze = defineCommand8({
15379
15635
  id: "friction.analyze",
15380
15636
  args: [
15381
15637
  {
15382
15638
  name: "source",
15383
- schema: z10.string().optional(),
15639
+ schema: z11.string().optional(),
15384
15640
  describe: "a saved run stream: JSON lines of run events or a curl'ed /runs/:id/events SSE capture (default: stdin)"
15385
15641
  }
15386
15642
  ],
15387
- options: z10.object({
15388
- slowMs: z10.coerce.number().nonnegative().optional().describe("a tool call slower than this many ms is a slow-tool finding"),
15643
+ options: z11.object({
15644
+ slowMs: z11.coerce.number().nonnegative().optional().describe("a tool call slower than this many ms is a slow-tool finding"),
15389
15645
  inProgress: flag.optional().describe("the capture was taken mid-run: a trailing call without a result is still executing, not a dead run")
15390
15646
  }),
15391
15647
  action: "friction:read",
@@ -15438,7 +15694,7 @@ var init_friction = __esm({
15438
15694
  });
15439
15695
 
15440
15696
  // ../../src/core/commandSurface.ts
15441
- import { z as z11 } from "zod";
15697
+ import { z as z12 } from "zod";
15442
15698
  function camelToKebab(s) {
15443
15699
  return s.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
15444
15700
  }
@@ -15510,7 +15766,7 @@ function isBooleanSchema(schema) {
15510
15766
  return false;
15511
15767
  }
15512
15768
  function jsonSchemaOf(schema) {
15513
- const out = z11.toJSONSchema(unwrap(schema), { io: "input" });
15769
+ const out = z12.toJSONSchema(unwrap(schema), { io: "input" });
15514
15770
  delete out.$schema;
15515
15771
  return out;
15516
15772
  }
@@ -15522,7 +15778,7 @@ function jsonSchemaFor(cmd) {
15522
15778
  if (!acceptsUndefined(arg.schema)) required.push(arg.name);
15523
15779
  }
15524
15780
  if (cmd.options) {
15525
- const opts = z11.toJSONSchema(cmd.options, { io: "input" });
15781
+ const opts = z12.toJSONSchema(cmd.options, { io: "input" });
15526
15782
  Object.assign(properties, opts.properties ?? {});
15527
15783
  required.push(...opts.required ?? []);
15528
15784
  }
@@ -15762,17 +16018,17 @@ function chatCommandList(commands) {
15762
16018
  function registerHelpCommands(registry) {
15763
16019
  for (const cmd of helpCommands) registry.register(cmd);
15764
16020
  }
15765
- var defineCommand8, COMMANDS_REFERENCE_URL, DIRECTIVES_HELP, helpShow, helpCommandsList, helpCommands;
16021
+ var defineCommand9, COMMANDS_REFERENCE_URL, DIRECTIVES_HELP, helpShow, helpCommandsList, helpCommands;
15766
16022
  var init_help = __esm({
15767
16023
  "../../src/core/commands/help.ts"() {
15768
16024
  "use strict";
15769
16025
  init_commandRegistry();
15770
16026
  init_commandSurface();
15771
16027
  init_docsLink();
15772
- defineCommand8 = commandDefiner();
16028
+ defineCommand9 = commandDefiner();
15773
16029
  COMMANDS_REFERENCE_URL = `${PROJECT_DOCS_URL}/reference/slack-commands`;
15774
16030
  DIRECTIVES_HELP = "`agent:review model:anthropic/claude-opus-5 effort:low budget:20 look at PR 42` (effort: low | medium | high \u2014 lower = faster turns; budget: whole minutes, at least 2 \u2014 narrows this run's wall clock, never widens it)";
15775
- helpShow = defineCommand8({
16031
+ helpShow = defineCommand9({
15776
16032
  id: "help.show",
15777
16033
  action: "help:read",
15778
16034
  effect: "read",
@@ -15783,7 +16039,7 @@ var init_help = __esm({
15783
16039
  commandsReference: COMMANDS_REFERENCE_URL
15784
16040
  })
15785
16041
  });
15786
- helpCommandsList = defineCommand8({
16042
+ helpCommandsList = defineCommand9({
15787
16043
  id: "help.commands",
15788
16044
  action: "help:read",
15789
16045
  effect: "read",
@@ -17520,7 +17776,7 @@ var init_service = __esm({
17520
17776
  });
17521
17777
 
17522
17778
  // ../../src/core/commands/mcp.ts
17523
- import { z as z12 } from "zod";
17779
+ import { z as z13 } from "zod";
17524
17780
  async function serviceOf(deps) {
17525
17781
  const svc = await deps.mcp.service();
17526
17782
  if ("unavailable" in svc) throw new CommandError("unavailable", svc.unavailable);
@@ -17614,7 +17870,7 @@ function renderShow(output) {
17614
17870
  function registerMcpCommands(registry) {
17615
17871
  for (const cmd of MCP_COMMANDS) registry.register(cmd);
17616
17872
  }
17617
- var defineCommand9, serverName, serverUrl, scopeOption, channelOption2, nameArg, mcpList, mcpAdd, mcpConnect, mcpShow, mcpRemove, MCP_COMMANDS;
17873
+ var defineCommand10, serverName, serverUrl, scopeOption, channelOption2, nameArg, mcpList, mcpAdd, mcpConnect, mcpShow, mcpRemove, MCP_COMMANDS;
17618
17874
  var init_mcp = __esm({
17619
17875
  "../../src/core/commands/mcp.ts"() {
17620
17876
  "use strict";
@@ -17622,18 +17878,18 @@ var init_mcp = __esm({
17622
17878
  init_service();
17623
17879
  init_authorize();
17624
17880
  init_commandRegistry();
17625
- defineCommand9 = commandDefiner();
17626
- serverName = z12.string().refine((s) => MCP_SERVER_NAME_PATTERN.test(s), "expected a slug: lowercase letters, digits, dashes (\u2264 32 chars)");
17627
- serverUrl = z12.string().refine((s) => /^https?:\/\/\S+$/.test(s), "expected an http(s) URL");
17628
- scopeOption = z12.enum(["me", "channel", "org"]).optional().describe(
17881
+ defineCommand10 = commandDefiner();
17882
+ serverName = z13.string().refine((s) => MCP_SERVER_NAME_PATTERN.test(s), "expected a slug: lowercase letters, digits, dashes (\u2264 32 chars)");
17883
+ serverUrl = z13.string().refine((s) => /^https?:\/\/\S+$/.test(s), "expected an http(s) URL");
17884
+ scopeOption = z13.enum(["me", "channel", "org"]).optional().describe(
17629
17885
  "whose server: yours (`me`, default), this channel's (`channel`, channel-config rights), or org-wide (`org`, admins)"
17630
17886
  );
17631
- channelOption2 = z12.string().optional().describe("target channel for `--scope channel` and for `list` (default: the channel you are speaking in)");
17887
+ channelOption2 = z13.string().optional().describe("target channel for `--scope channel` and for `list` (default: the channel you are speaking in)");
17632
17888
  nameArg = { name: "name", schema: serverName, describe: "the server's name (see `mcp list`)" };
17633
- mcpList = defineCommand9({
17889
+ mcpList = defineCommand10({
17634
17890
  id: "mcp.list",
17635
17891
  enabledWhen: (caps) => caps.mcp,
17636
- options: z12.object({ channel: channelOption2 }),
17892
+ options: z13.object({ channel: channelOption2 }),
17637
17893
  action: "mcp:read",
17638
17894
  effect: "read",
17639
17895
  describe: "External MCP servers your runs in this channel can use \u2014 org-wide, this channel's, and your own \u2014 with state and agents; never a credential.",
@@ -17645,7 +17901,7 @@ var init_mcp = __esm({
17645
17901
  return { servers };
17646
17902
  }
17647
17903
  });
17648
- mcpAdd = defineCommand9({
17904
+ mcpAdd = defineCommand10({
17649
17905
  id: "mcp.add",
17650
17906
  enabledWhen: (caps) => caps.mcp,
17651
17907
  args: [
@@ -17655,15 +17911,15 @@ var init_mcp = __esm({
17655
17911
  describe: "a short slug for the server (becomes the tool prefix mcp__<name>__)"
17656
17912
  }
17657
17913
  ],
17658
- options: z12.object({
17914
+ options: z13.object({
17659
17915
  url: serverUrl.describe("the server's Streamable-HTTP endpoint (https://\u2026/mcp)"),
17660
17916
  scope: scopeOption,
17661
- agents: z12.string().transform(
17917
+ agents: z13.string().transform(
17662
17918
  (s) => s.split(",").map((a) => a.trim()).filter(Boolean)
17663
17919
  ).optional().describe(
17664
17920
  "comma-separated agents that may use it (default general,research; only org servers may name coding/review/ship)"
17665
17921
  ),
17666
- auth: z12.enum(["oauth", "bearer", "none"]).optional().describe(
17922
+ auth: z13.enum(["oauth", "bearer", "none"]).optional().describe(
17667
17923
  "how the server authenticates: `oauth` (you sign in on a one-time link), `bearer` (you paste a token on a one-time link), or `none`; omit to detect it from the server"
17668
17924
  ),
17669
17925
  channel: channelOption2
@@ -17688,11 +17944,11 @@ var init_mcp = __esm({
17688
17944
  );
17689
17945
  }
17690
17946
  });
17691
- mcpConnect = defineCommand9({
17947
+ mcpConnect = defineCommand10({
17692
17948
  id: "mcp.connect",
17693
17949
  enabledWhen: (caps) => caps.mcp,
17694
17950
  args: [nameArg],
17695
- options: z12.object({ scope: scopeOption, channel: channelOption2 }),
17951
+ options: z13.object({ scope: scopeOption, channel: channelOption2 }),
17696
17952
  action: "mcp:write",
17697
17953
  effect: "write",
17698
17954
  describe: "A fresh one-time link to sign in to an OAuth server or enter (or replace) a bearer server's token \u2014 only you can complete it; it expires in 10 minutes.",
@@ -17706,11 +17962,11 @@ var init_mcp = __esm({
17706
17962
  return await via(() => svc.connect(actor, target, args.name));
17707
17963
  }
17708
17964
  });
17709
- mcpShow = defineCommand9({
17965
+ mcpShow = defineCommand10({
17710
17966
  id: "mcp.show",
17711
17967
  enabledWhen: (caps) => caps.mcp,
17712
17968
  args: [nameArg],
17713
- options: z12.object({ scope: scopeOption, channel: channelOption2 }),
17969
+ options: z13.object({ scope: scopeOption, channel: channelOption2 }),
17714
17970
  action: "mcp:read",
17715
17971
  effect: "read",
17716
17972
  describe: "One MCP server's entry plus a live probe of the tools it offers (names, read-only flags); never a credential.",
@@ -17726,11 +17982,11 @@ var init_mcp = __esm({
17726
17982
  return await via(() => svc.show(actor, target, args.name));
17727
17983
  }
17728
17984
  });
17729
- mcpRemove = defineCommand9({
17985
+ mcpRemove = defineCommand10({
17730
17986
  id: "mcp.remove",
17731
17987
  enabledWhen: (caps) => caps.mcp,
17732
17988
  args: [nameArg],
17733
- options: z12.object({ scope: scopeOption, channel: channelOption2 }),
17989
+ options: z13.object({ scope: scopeOption, channel: channelOption2 }),
17734
17990
  action: "mcp:write",
17735
17991
  effect: "write",
17736
17992
  describe: "Remove an MCP server you added and its stored credential (yours freely; channel ones need channel-config rights, org-wide ones admin rights).",
@@ -18168,7 +18424,7 @@ var init_llmOutput = __esm({
18168
18424
  });
18169
18425
 
18170
18426
  // ../../src/core/memory/reflection.ts
18171
- import { z as z13 } from "zod";
18427
+ import { z as z14 } from "zod";
18172
18428
  function shouldReflect(input) {
18173
18429
  if (input.agentName !== void 0 && NO_REFLECT_AGENTS.has(input.agentName)) return false;
18174
18430
  return input.toolCalls > 0 || input.historyTurns >= REFLECT_MIN_TURNS;
@@ -18387,7 +18643,7 @@ var init_reflection = __esm({
18387
18643
  "Output raw JSON with no code fence and no prose."
18388
18644
  ].join("\n");
18389
18645
  SUMMARY_INHERITANCE = ["user", "repo", "channel"];
18390
- REFLECTION_ENVELOPE = jsonOutput(z13.object({ facts: z13.array(z13.unknown()), summary: z13.unknown().optional() }), {
18646
+ REFLECTION_ENVELOPE = jsonOutput(z14.object({ facts: z14.array(z14.unknown()), summary: z14.unknown().optional() }), {
18391
18647
  name: "reflection-envelope"
18392
18648
  });
18393
18649
  SCOPE_KINDS = ["org", "user", "repo", "channel"];
@@ -18507,11 +18763,11 @@ var init_workerStore = __esm({
18507
18763
  });
18508
18764
 
18509
18765
  // ../../src/core/memory/buildStore.ts
18510
- function resolveScopeCap(configured2, warn) {
18511
- if (configured2 === void 0) return DEFAULT_SCOPE_CAP;
18512
- if (Number.isInteger(configured2) && configured2 >= 1 && configured2 <= MAX_SCOPE_CAP) return configured2;
18766
+ function resolveScopeCap(configured3, warn) {
18767
+ if (configured3 === void 0) return DEFAULT_SCOPE_CAP;
18768
+ if (Number.isInteger(configured3) && configured3 >= 1 && configured3 <= MAX_SCOPE_CAP) return configured3;
18513
18769
  warn(
18514
- `memory.maxRecordsPerScope must be an integer between 1 and ${MAX_SCOPE_CAP} (got ${String(configured2)}) \u2014 using the default ${DEFAULT_SCOPE_CAP}.`
18770
+ `memory.maxRecordsPerScope must be an integer between 1 and ${MAX_SCOPE_CAP} (got ${String(configured3)}) \u2014 using the default ${DEFAULT_SCOPE_CAP}.`
18515
18771
  );
18516
18772
  return DEFAULT_SCOPE_CAP;
18517
18773
  }
@@ -18619,7 +18875,7 @@ var init_memory = __esm({
18619
18875
  });
18620
18876
 
18621
18877
  // ../../src/core/commands/memory.ts
18622
- import { z as z14 } from "zod";
18878
+ import { z as z15 } from "zod";
18623
18879
  function scopeKeyOfMemoryId(id) {
18624
18880
  const m = /^mem:(.+):\d+$/.exec(id);
18625
18881
  return m ? m[1] : void 0;
@@ -18673,18 +18929,18 @@ _(limit ${limit} reached \u2014 there may be more; narrow with words or raise \`
18673
18929
  function registerMemoryCommands(registry) {
18674
18930
  for (const cmd of memoryCommands) registry.register(cmd);
18675
18931
  }
18676
- var defineCommand10, MEMORY_LIST_LIMIT, MEMORY_LIST_MAX_LIMIT, MEMORY_OFF_MESSAGE, memoryId, repoScopeKey, channelScopeKey, isSharedScope, LIST_SCOPES, memoryList, memoryForget, memoryCommands;
18932
+ var defineCommand11, MEMORY_LIST_LIMIT, MEMORY_LIST_MAX_LIMIT, MEMORY_OFF_MESSAGE, memoryId, repoScopeKey, channelScopeKey, isSharedScope, LIST_SCOPES, memoryList, memoryForget, memoryCommands;
18677
18933
  var init_memory2 = __esm({
18678
18934
  "../../src/core/commands/memory.ts"() {
18679
18935
  "use strict";
18680
18936
  init_authorize();
18681
18937
  init_commandRegistry();
18682
18938
  init_memory();
18683
- defineCommand10 = commandDefiner();
18939
+ defineCommand11 = commandDefiner();
18684
18940
  MEMORY_LIST_LIMIT = 20;
18685
18941
  MEMORY_LIST_MAX_LIMIT = 50;
18686
18942
  MEMORY_OFF_MESSAGE = "Memory is off in this deployment (`memory.enabled` is not set), so there is nothing to list or forget.";
18687
- memoryId = z14.string().refine(
18943
+ memoryId = z15.string().refine(
18688
18944
  (id) => scopeKeyOfMemoryId(id) !== void 0,
18689
18945
  "expected a memory id like mem:<scope>:<n> (see `memory list`)"
18690
18946
  );
@@ -18692,21 +18948,21 @@ var init_memory2 = __esm({
18692
18948
  channelScopeKey = (channelId) => deriveScopeKey("channel", { channelId });
18693
18949
  isSharedScope = (key, keys) => key === keys.org || key.startsWith("repo:") || key.startsWith("channel:");
18694
18950
  LIST_SCOPES = ["me", "org", "repo", "channel", "all"];
18695
- memoryList = defineCommand10({
18951
+ memoryList = defineCommand11({
18696
18952
  id: "memory.list",
18697
18953
  enabledWhen: (caps) => caps.memory,
18698
18954
  args: [
18699
18955
  {
18700
18956
  name: "query",
18701
- schema: z14.string().optional(),
18957
+ schema: z15.string().optional(),
18702
18958
  describe: "words a record must mention (whole-token match)",
18703
18959
  rest: true
18704
18960
  }
18705
18961
  ],
18706
- options: z14.object({
18707
- scope: z14.enum(LIST_SCOPES).optional().describe("which scopes to list (default all: yours, this repo's, this channel's, and the shared org scope)"),
18708
- limit: z14.coerce.number().int().min(1).max(MEMORY_LIST_MAX_LIMIT).optional().describe(`records per scope (default ${MEMORY_LIST_LIMIT}, max ${MEMORY_LIST_MAX_LIMIT})`),
18709
- repo: z14.string().refine((s) => /^[\w.-]+\/[\w.-]+$/.test(s), "expected an owner/name slug").optional().describe("the repo whose scope to list (default: the repo this thread is bound to)")
18962
+ options: z15.object({
18963
+ scope: z15.enum(LIST_SCOPES).optional().describe("which scopes to list (default all: yours, this repo's, this channel's, and the shared org scope)"),
18964
+ limit: z15.coerce.number().int().min(1).max(MEMORY_LIST_MAX_LIMIT).optional().describe(`records per scope (default ${MEMORY_LIST_LIMIT}, max ${MEMORY_LIST_MAX_LIMIT})`),
18965
+ repo: z15.string().refine((s) => /^[\w.-]+\/[\w.-]+$/.test(s), "expected an owner/name slug").optional().describe("the repo whose scope to list (default: the repo this thread is bound to)")
18710
18966
  }),
18711
18967
  action: "memory:read",
18712
18968
  effect: "read",
@@ -18760,7 +19016,7 @@ var init_memory2 = __esm({
18760
19016
  };
18761
19017
  }
18762
19018
  });
18763
- memoryForget = defineCommand10({
19019
+ memoryForget = defineCommand11({
18764
19020
  id: "memory.forget",
18765
19021
  enabledWhen: (caps) => caps.memory,
18766
19022
  args: [{ name: "id", schema: memoryId, describe: "the record id (`mem:<scope>:<n>`, from `memory list`)" }],
@@ -18895,7 +19151,7 @@ var init_residentDiskBudget = __esm({
18895
19151
  });
18896
19152
 
18897
19153
  // ../../src/core/commands/repo.ts
18898
- import { z as z15 } from "zod";
19154
+ import { z as z16 } from "zod";
18899
19155
  async function adminOf(deps, span) {
18900
19156
  const api = await deps.repo.admin();
18901
19157
  if ("unavailable" in api) throw new CommandError("unavailable", api.unavailable);
@@ -19003,7 +19259,7 @@ ${clipOpOutput(text)}
19003
19259
  \`\`\`` : `${icon} ${str4(o.summary)}`;
19004
19260
  }
19005
19261
  function defineOp(op) {
19006
- return defineCommand11({
19262
+ return defineCommand12({
19007
19263
  id: `repo.${op}`,
19008
19264
  // The op needs a backend: the resident service, or the local workspace (`defaultOperations`).
19009
19265
  enabledWhen: (caps) => caps.residents || caps.execution === "local",
@@ -19061,7 +19317,7 @@ function defineOp(op) {
19061
19317
  function registerRepoCommands(registry) {
19062
19318
  for (const cmd of repoCommands) registry.register(cmd);
19063
19319
  }
19064
- var defineCommand11, DEFAULT_COMMANDS, DEFAULT_REF, SETTLE_POLL_MS, SETTLE_MAX_MS, repoSlug2, gitRef2, command, slugArg, n, obj, str4, repoList, repoOnboard, COMMAND_KEYS, dryRunOptions, repoOffboard, repoRebuild, repoReconfigure, NO_OPS_BACKEND_MESSAGE, repoTest, repoBuild, repoCommands;
19320
+ var defineCommand12, DEFAULT_COMMANDS, DEFAULT_REF, SETTLE_POLL_MS, SETTLE_MAX_MS, repoSlug2, gitRef2, command, slugArg, n, obj, str4, repoList, repoOnboard, COMMAND_KEYS, dryRunOptions, repoOffboard, repoRebuild, repoReconfigure, NO_OPS_BACKEND_MESSAGE, repoTest, repoBuild, repoCommands;
19065
19321
  var init_repo = __esm({
19066
19322
  "../../src/core/commands/repo.ts"() {
19067
19323
  "use strict";
@@ -19069,19 +19325,19 @@ var init_repo = __esm({
19069
19325
  init_residentAdmin();
19070
19326
  init_repoToolchain();
19071
19327
  init_residentDiskBudget();
19072
- defineCommand11 = commandDefiner();
19328
+ defineCommand12 = commandDefiner();
19073
19329
  DEFAULT_COMMANDS = NPM_FALLBACK_COMMANDS;
19074
19330
  DEFAULT_REF = "main";
19075
19331
  SETTLE_POLL_MS = 1e4;
19076
19332
  SETTLE_MAX_MS = 12 * 6e4;
19077
- repoSlug2 = z15.string().refine((s) => parseSlug(s) !== void 0, "expected a GitHub owner/name slug").transform((s) => parseSlug(s));
19078
- gitRef2 = z15.string().refine((s) => validRef(s) !== void 0, "expected a plausible git branch ref (e.g. main)");
19079
- command = z15.string().min(1);
19333
+ repoSlug2 = z16.string().refine((s) => parseSlug(s) !== void 0, "expected a GitHub owner/name slug").transform((s) => parseSlug(s));
19334
+ gitRef2 = z16.string().refine((s) => validRef(s) !== void 0, "expected a plausible git branch ref (e.g. main)");
19335
+ command = z16.string().min(1);
19080
19336
  slugArg = { name: "slug", schema: repoSlug2, describe: "GitHub owner/name of the repo" };
19081
19337
  n = (v) => String(typeof v === "number" ? v : v ?? "?");
19082
19338
  obj = (v) => typeof v === "object" && v !== null && !Array.isArray(v) ? v : {};
19083
19339
  str4 = (v) => typeof v === "string" ? v : String(v ?? "?");
19084
- repoList = defineCommand11({
19340
+ repoList = defineCommand12({
19085
19341
  id: "repo.list",
19086
19342
  enabledWhen: (caps) => caps.residents,
19087
19343
  action: "repo:read",
@@ -19098,11 +19354,11 @@ var init_repo = __esm({
19098
19354
  return res.data;
19099
19355
  }
19100
19356
  });
19101
- repoOnboard = defineCommand11({
19357
+ repoOnboard = defineCommand12({
19102
19358
  id: "repo.onboard",
19103
19359
  enabledWhen: (caps) => caps.residents,
19104
19360
  args: [slugArg],
19105
- options: z15.object({
19361
+ options: z16.object({
19106
19362
  ref: gitRef2.optional().describe(`default branch to keep warm (default ${DEFAULT_REF})`),
19107
19363
  test: command.optional().describe(
19108
19364
  "the repo's test command (default: detected from the repo root \u2014 `<pm> test`, or a no-op without a test script)"
@@ -19189,10 +19445,10 @@ var init_repo = __esm({
19189
19445
  settle: (output, { deps }) => settleProvisioning(deps, str4(output.slug))
19190
19446
  });
19191
19447
  COMMAND_KEYS = ["install", "build", "test"];
19192
- dryRunOptions = z15.object({
19448
+ dryRunOptions = z16.object({
19193
19449
  dryRun: flag.optional().describe("compute and return the itemized plan without executing")
19194
19450
  });
19195
- repoOffboard = defineCommand11({
19451
+ repoOffboard = defineCommand12({
19196
19452
  id: "repo.offboard",
19197
19453
  enabledWhen: (caps) => caps.residents,
19198
19454
  args: [slugArg],
@@ -19226,7 +19482,7 @@ var init_repo = __esm({
19226
19482
  return { ...r.data, slug: args.slug, dryRun };
19227
19483
  }
19228
19484
  });
19229
- repoRebuild = defineCommand11({
19485
+ repoRebuild = defineCommand12({
19230
19486
  id: "repo.rebuild",
19231
19487
  enabledWhen: (caps) => caps.residents,
19232
19488
  args: [slugArg],
@@ -19265,11 +19521,11 @@ var init_repo = __esm({
19265
19521
  return { ...r.data, slug: args.slug, dryRun };
19266
19522
  }
19267
19523
  });
19268
- repoReconfigure = defineCommand11({
19524
+ repoReconfigure = defineCommand12({
19269
19525
  id: "repo.reconfigure",
19270
19526
  enabledWhen: (caps) => caps.residents,
19271
19527
  args: [slugArg],
19272
- options: z15.object({
19528
+ options: z16.object({
19273
19529
  ref: gitRef2.optional().describe("new default branch"),
19274
19530
  test: command.optional().describe("new test command"),
19275
19531
  build: command.optional().describe("new build command"),
@@ -20239,7 +20495,7 @@ var init_runsService = __esm({
20239
20495
  });
20240
20496
 
20241
20497
  // ../../src/core/commands/review.ts
20242
- import { z as z16 } from "zod";
20498
+ import { z as z17 } from "zod";
20243
20499
  function artifactJson(a) {
20244
20500
  return {
20245
20501
  ...a.model !== void 0 ? { model: a.model } : {},
@@ -20308,7 +20564,7 @@ function refused2(err2) {
20308
20564
  function registerReviewCommands(registry) {
20309
20565
  for (const cmd of reviewCommands) registry.register(cmd);
20310
20566
  }
20311
- var defineCommand12, runId, ABRIDGE_OFF_MESSAGE, reviewAbridge, reviewCommands;
20567
+ var defineCommand13, runId, ABRIDGE_OFF_MESSAGE, reviewAbridge, reviewCommands;
20312
20568
  var init_review = __esm({
20313
20569
  "../../src/core/commands/review.ts"() {
20314
20570
  "use strict";
@@ -20317,17 +20573,17 @@ var init_review = __esm({
20317
20573
  init_reviewAbridge();
20318
20574
  init_runRecord();
20319
20575
  init_runsService();
20320
- defineCommand12 = commandDefiner();
20321
- runId = z16.string().regex(RUN_ID_PATTERN);
20576
+ defineCommand13 = commandDefiner();
20577
+ runId = z17.string().regex(RUN_ID_PATTERN);
20322
20578
  ABRIDGE_OFF_MESSAGE = "The abridged reading diff is off in this deployment: it needs the `meat` binary on the bot host, the Anthropic provider's credential, `review.readingDiff.provider` not `off`, and run history to store it.";
20323
- reviewAbridge = defineCommand12({
20579
+ reviewAbridge = defineCommand13({
20324
20580
  id: "review.abridge",
20325
20581
  // Hidden unless the abridging can happen here (the binary, the credential,
20326
20582
  // the switch) AND there is a record to append to.
20327
20583
  enabledWhen: (caps) => caps.runHistory && caps.readingDiffAbridge,
20328
20584
  args: [{ name: "id", schema: runId, describe: "run id of a finished PR review" }],
20329
- options: z16.object({
20330
- model: z16.string().min(1).optional().describe("meat's model (default review.readingDiff.meatModel, else claude-opus-5)"),
20585
+ options: z17.object({
20586
+ model: z17.string().min(1).optional().describe("meat's model (default review.readingDiff.meatModel, else claude-opus-5)"),
20331
20587
  force: flag.optional().describe("recompute even when an abridged diff is already stored, or retry a failed one"),
20332
20588
  wait: flag.optional().describe("block until the abridging finishes and answer the outcome instead of `running`")
20333
20589
  }),
@@ -20359,7 +20615,7 @@ var init_review = __esm({
20359
20615
  });
20360
20616
 
20361
20617
  // ../../src/core/commands/runs.ts
20362
- import { z as z17 } from "zod";
20618
+ import { z as z18 } from "zod";
20363
20619
  function unwrap2(res) {
20364
20620
  if (res.ok) return res.value;
20365
20621
  throw new CommandError(res.error, res.error === "not_found" ? "run not found" : "run already finished");
@@ -20400,7 +20656,7 @@ function wrapEvent(e) {
20400
20656
  function registerRunsCommands(registry) {
20401
20657
  for (const cmd of runsCommands) registry.register(cmd);
20402
20658
  }
20403
- var defineCommand13, runId2, positiveInt3, idArg, logDenied, asJson3, runsList, runsGet, runsEvents, runsFriction, runsStop, runsCommands;
20659
+ var defineCommand14, runId2, positiveInt3, idArg, logDenied, asJson3, runsList, runsGet, runsEvents, runsFriction, runsStop, runsCommands;
20404
20660
  var init_runs = __esm({
20405
20661
  "../../src/core/commands/runs.ts"() {
20406
20662
  "use strict";
@@ -20409,21 +20665,24 @@ var init_runs = __esm({
20409
20665
  init_commandRegistry();
20410
20666
  init_runRecord();
20411
20667
  init_runsService();
20412
- defineCommand13 = commandDefiner();
20413
- runId2 = z17.string().regex(RUN_ID_PATTERN);
20414
- positiveInt3 = z17.coerce.number().int().positive();
20668
+ defineCommand14 = commandDefiner();
20669
+ runId2 = z18.string().regex(RUN_ID_PATTERN);
20670
+ positiveInt3 = z18.coerce.number().int().positive();
20415
20671
  idArg = { name: "id", schema: runId2, describe: "run id" };
20416
20672
  logDenied = (entry) => console.log(JSON.stringify({ audit: "authz", ...entry }));
20417
20673
  asJson3 = (v) => v;
20418
- runsList = defineCommand13({
20674
+ runsList = defineCommand14({
20419
20675
  id: "runs.list",
20420
- options: z17.object({
20421
- status: z17.enum(["active", "finished", "all"]).default("active").describe("which runs: live (default), persisted, or both"),
20422
- agent: z17.string().min(1).optional().describe("only runs of this agent"),
20423
- channel: z17.string().min(1).optional().describe("only runs in this platform-namespaced channel (`slack:C0123`, `http:ops`)"),
20424
- sinceMs: z17.coerce.number().int().nonnegative().optional().describe("only runs started at or after this epoch ms"),
20676
+ options: z18.object({
20677
+ status: z18.enum(["active", "finished", "all"]).default("active").describe("which runs: live (default), persisted, or both"),
20678
+ agent: z18.string().min(1).optional().describe("only runs of this agent"),
20679
+ channel: z18.string().min(1).optional().describe("only runs in this platform-namespaced channel (`slack:C0123`, `http:ops`)"),
20680
+ thread: z18.string().min(1).optional().describe(
20681
+ "only runs in this thread, newest first (`slack:C0123:1712.34` \u2014 a thread's story, its sessions' runs)"
20682
+ ),
20683
+ sinceMs: z18.coerce.number().int().nonnegative().optional().describe("only runs started at or after this epoch ms"),
20425
20684
  limit: positiveInt3.max(RUN_LIST_MAX_LIMIT).optional().describe(`page size (max ${RUN_LIST_MAX_LIMIT})`),
20426
- before: z17.coerce.number().int().nonnegative().optional().describe("page cursor: runs finished before this epoch ms"),
20685
+ before: z18.coerce.number().int().nonnegative().optional().describe("page cursor: runs finished before this epoch ms"),
20427
20686
  beforeId: runId2.optional().describe("page cursor tie-breaker: the last id of the previous page")
20428
20687
  }),
20429
20688
  action: "runs:read",
@@ -20431,14 +20690,17 @@ var init_runs = __esm({
20431
20690
  describe: "List runs (live and persisted, newest first) \u2014 metadata only, never message text.",
20432
20691
  handler: async ({ options, caller, deps }) => {
20433
20692
  const visibleTo = predicateFor(caller.actor, "runs:read", "run");
20434
- return asJson3(await (await deps.runs()).listRuns({ ...options, visibleTo }));
20693
+ const { thread, ...rest } = options;
20694
+ return asJson3(
20695
+ await (await deps.runs()).listRuns({ ...rest, ...thread !== void 0 ? { threadKey: thread } : {}, visibleTo })
20696
+ );
20435
20697
  }
20436
20698
  });
20437
- runsGet = defineCommand13({
20699
+ runsGet = defineCommand14({
20438
20700
  id: "runs.get",
20439
20701
  args: [idArg],
20440
- options: z17.object({
20441
- include: z17.enum(["messages"]).optional().describe("add the run's events, free text wrapped as untrusted content")
20702
+ options: z18.object({
20703
+ include: z18.enum(["messages"]).optional().describe("add the run's events, free text wrapped as untrusted content")
20442
20704
  }),
20443
20705
  action: "runs:read",
20444
20706
  effect: "read",
@@ -20458,11 +20720,11 @@ var init_runs = __esm({
20458
20720
  return asJson3(view);
20459
20721
  }
20460
20722
  });
20461
- runsEvents = defineCommand13({
20723
+ runsEvents = defineCommand14({
20462
20724
  id: "runs.events",
20463
20725
  args: [idArg],
20464
- options: z17.object({
20465
- afterSeq: z17.coerce.number().int().nonnegative().optional().describe("events with seq greater than this"),
20726
+ options: z18.object({
20727
+ afterSeq: z18.coerce.number().int().nonnegative().optional().describe("events with seq greater than this"),
20466
20728
  limit: positiveInt3.max(MAX_EVENTS_PAGE).optional().describe(`page size (max ${MAX_EVENTS_PAGE})`)
20467
20729
  }),
20468
20730
  action: "runs:read",
@@ -20476,7 +20738,7 @@ var init_runs = __esm({
20476
20738
  return asJson3({ ...page2, events: page2.events.map(wrapEvent) });
20477
20739
  }
20478
20740
  });
20479
- runsFriction = defineCommand13({
20741
+ runsFriction = defineCommand14({
20480
20742
  id: "runs.friction",
20481
20743
  args: [idArg],
20482
20744
  action: "runs:read",
@@ -20489,10 +20751,10 @@ var init_runs = __esm({
20489
20751
  return asJson3(unwrap2(await runs.getRunFriction(args.id)));
20490
20752
  }
20491
20753
  });
20492
- runsStop = defineCommand13({
20754
+ runsStop = defineCommand14({
20493
20755
  id: "runs.stop",
20494
20756
  args: [idArg],
20495
- options: z17.object({ mode: z17.enum(["soft", "hard"]).describe("soft = finish the current step; hard = abort now") }),
20757
+ options: z18.object({ mode: z18.enum(["soft", "hard"]).describe("soft = finish the current step; hard = abort now") }),
20496
20758
  action: "runs:write",
20497
20759
  effect: "write",
20498
20760
  describe: "Request a live run to stop (`--mode soft` = finish the current step; `hard` = abort now). Records the caller as the actor.",
@@ -20516,16 +20778,16 @@ var init_runs = __esm({
20516
20778
  function registerScheduleCommands(registry) {
20517
20779
  for (const cmd of scheduleCommands) registry.register(cmd);
20518
20780
  }
20519
- var defineCommand14, ACTION_LABEL, utc, scheduleList, scheduleCommands;
20781
+ var defineCommand15, ACTION_LABEL, utc, scheduleList, scheduleCommands;
20520
20782
  var init_schedule = __esm({
20521
20783
  "../../src/core/commands/schedule.ts"() {
20522
20784
  "use strict";
20523
20785
  init_commandRegistry();
20524
20786
  init_schedules();
20525
- defineCommand14 = commandDefiner();
20787
+ defineCommand15 = commandDefiner();
20526
20788
  ACTION_LABEL = { healthz: "keep-alive", watchdog: "resident watchdog" };
20527
20789
  utc = (ms) => `${new Date(ms).toISOString().slice(0, 16).replace("T", " ")} UTC`;
20528
- scheduleList = defineCommand14({
20790
+ scheduleList = defineCommand15({
20529
20791
  id: "schedule.list",
20530
20792
  enabledWhen: (caps) => caps.schedules,
20531
20793
  action: "schedule:read",
@@ -20789,7 +21051,7 @@ var init_plan2 = __esm({
20789
21051
  });
20790
21052
 
20791
21053
  // ../../src/core/commands/setup.ts
20792
- import { z as z18 } from "zod";
21054
+ import { z as z19 } from "zod";
20793
21055
  async function gatherAnswers(o, setup) {
20794
21056
  const ask = setup.prompt;
20795
21057
  const given = (v) => v !== void 0;
@@ -20859,33 +21121,33 @@ function capabilityLine(c) {
20859
21121
  function registerSetupCommands(registry) {
20860
21122
  for (const cmd of setupCommands) registry.register(cmd);
20861
21123
  }
20862
- var defineCommand15, secret, digits, workerName, hostname2, httpUrl, account, initOptions2, DEFAULT_NAME, setupInit, ASK, setupCommands;
21124
+ var defineCommand16, secret, digits, workerName, hostname2, httpUrl, account, initOptions2, DEFAULT_NAME, setupInit, ASK, setupCommands;
20863
21125
  var init_setup = __esm({
20864
21126
  "../../src/core/commands/setup.ts"() {
20865
21127
  "use strict";
20866
21128
  init_plan2();
20867
21129
  init_commandRegistry();
20868
21130
  init_deploy();
20869
- defineCommand15 = commandDefiner();
20870
- secret = z18.string().min(1);
20871
- digits = z18.string().regex(/^\d+$/, "expected a number");
20872
- workerName = z18.string().regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/, "expected a Worker name: lowercase letters, digits, hyphens");
20873
- hostname2 = z18.string().regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/, "expected a bare DNS name (example.com)");
20874
- httpUrl = z18.string().regex(/^https?:\/\/\S+$/, "expected an http(s) URL");
20875
- account = z18.string().regex(/^[0-9a-f]{32}$/, "expected a Cloudflare account id: 32 hex characters");
20876
- initOptions2 = z18.object({
20877
- organization: z18.string().min(1).optional().describe("the GitHub organization (or user) this installation serves \u2014 config.yaml's `organization`"),
21131
+ defineCommand16 = commandDefiner();
21132
+ secret = z19.string().min(1);
21133
+ digits = z19.string().regex(/^\d+$/, "expected a number");
21134
+ workerName = z19.string().regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/, "expected a Worker name: lowercase letters, digits, hyphens");
21135
+ hostname2 = z19.string().regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/, "expected a bare DNS name (example.com)");
21136
+ httpUrl = z19.string().regex(/^https?:\/\/\S+$/, "expected an http(s) URL");
21137
+ account = z19.string().regex(/^[0-9a-f]{32}$/, "expected a Cloudflare account id: 32 hex characters");
21138
+ initOptions2 = z19.object({
21139
+ organization: z19.string().min(1).optional().describe("the GitHub organization (or user) this installation serves \u2014 config.yaml's `organization`"),
20878
21140
  anthropicKey: secret.optional().describe("an Anthropic API key \u2192 ANTHROPIC_API_KEY and the `anthropic` provider"),
20879
21141
  openaiCompatible: httpUrl.optional().describe(
20880
21142
  "an OpenAI-compatible endpoint's base URL (https://api.openai.com/v1, http://localhost:11434/v1) \u2192 the `openai` provider"
20881
21143
  ),
20882
- model: z18.string().min(1).optional().describe("with --openai-compatible: the model every agent runs on at that endpoint (openai/<model>)"),
21144
+ model: z19.string().min(1).optional().describe("with --openai-compatible: the model every agent runs on at that endpoint (openai/<model>)"),
20883
21145
  modelKey: secret.optional().describe("with --openai-compatible: the endpoint's key \u2192 OPENAI_API_KEY (a local endpoint needs none)"),
20884
21146
  slackAppToken: secret.optional().describe("the Slack app-level token (xapp-\u2026) \u2192 SLACK_APP_TOKEN"),
20885
21147
  slackBotToken: secret.optional().describe("the Slack bot token (xoxb-\u2026) \u2192 SLACK_BOT_TOKEN"),
20886
21148
  githubAppId: digits.optional().describe("the GitHub App's id \u2192 GITHUB_APP_ID"),
20887
21149
  githubInstallationId: digits.optional().describe("the GitHub App's installation id \u2192 GITHUB_APP_INSTALLATION_ID"),
20888
- githubPrivateKeyFile: z18.string().min(1).optional().describe("path to the GitHub App's private key (PEM) \u2192 GITHUB_APP_PRIVATE_KEY, one quoted line"),
21150
+ githubPrivateKeyFile: z19.string().min(1).optional().describe("path to the GitHub App's private key (PEM) \u2192 GITHUB_APP_PRIVATE_KEY, one quoted line"),
20889
21151
  cloudflare: account.optional().describe(
20890
21152
  "a Cloudflare account id: also write deploy/profile.json and render the Worker configs (needs --zone; from a checkout's root, or anywhere when this CLI is the published package)"
20891
21153
  ),
@@ -20895,7 +21157,7 @@ var init_setup = __esm({
20895
21157
  dryRun: flag.optional().describe("write nothing; print each file as it would be written, secrets masked")
20896
21158
  });
20897
21159
  DEFAULT_NAME = "switchboard";
20898
- setupInit = defineCommand15({
21160
+ setupInit = defineCommand16({
20899
21161
  id: "setup.init",
20900
21162
  options: initOptions2,
20901
21163
  action: "setup:write",
@@ -20995,13 +21257,13 @@ function renderStatus(output) {
20995
21257
  function registerStatusCommands(registry) {
20996
21258
  for (const cmd of statusCommands) registry.register(cmd);
20997
21259
  }
20998
- var defineCommand16, statusShow, statusCommands;
21260
+ var defineCommand17, statusShow, statusCommands;
20999
21261
  var init_status = __esm({
21000
21262
  "../../src/core/commands/status.ts"() {
21001
21263
  "use strict";
21002
21264
  init_commandRegistry();
21003
- defineCommand16 = commandDefiner();
21004
- statusShow = defineCommand16({
21265
+ defineCommand17 = commandDefiner();
21266
+ statusShow = defineCommand17({
21005
21267
  id: "status.show",
21006
21268
  action: "status:read",
21007
21269
  effect: "read",
@@ -21040,6 +21302,7 @@ function registerCoreCommands(registry) {
21040
21302
  registerSetupCommands(registry);
21041
21303
  registerContractCommands(registry);
21042
21304
  registerDeliveryCommands(registry);
21305
+ registerArtifactsCommands(registry);
21043
21306
  }
21044
21307
  function coreCommandGroups() {
21045
21308
  const registry = new CommandRegistry({ audit: () => {
@@ -21051,6 +21314,7 @@ var init_all = __esm({
21051
21314
  "../../src/core/commands/all.ts"() {
21052
21315
  "use strict";
21053
21316
  init_commandRegistry();
21317
+ init_artifacts();
21054
21318
  init_config4();
21055
21319
  init_contract2();
21056
21320
  init_delivery2();
@@ -21334,6 +21598,11 @@ function buildCoreCommands(config, store, wiring) {
21334
21598
  images: imagesHostIO({ log: (l) => console.log(l), now: wiring.now ?? systemClock }),
21335
21599
  cliVersion: cliVersionOnHost
21336
21600
  },
21601
+ // `artifacts lifecycle` / `artifacts check`: the config's section and the operator's Cloudflare calls.
21602
+ artifacts: {
21603
+ config: async () => (await cfg()).config.artifacts,
21604
+ bucket: artifactsBucketHost()
21605
+ },
21337
21606
  env: { bootstrap: bootstrapOnHost },
21338
21607
  status: { snapshot: () => (wiring.status ?? unstampedStatus)() },
21339
21608
  // `setup init` writes the operator's working directory — the one the CLI runs in.
@@ -21367,6 +21636,7 @@ var init_commandCatalogue = __esm({
21367
21636
  init_clock();
21368
21637
  init_run();
21369
21638
  init_imagesHost();
21639
+ init_artifactsBucket();
21370
21640
  init_secretsHost();
21371
21641
  init_host3();
21372
21642
  init_executor();
@@ -21585,6 +21855,12 @@ function runPageLink(id) {
21585
21855
  if (!base) return void 0;
21586
21856
  return `${base.replace(/\/+$/, "")}/runs/${encodeURIComponent(id)}`;
21587
21857
  }
21858
+ function artifactLink(id, key, token2) {
21859
+ const page2 = runPageLink(id);
21860
+ if (!page2) return void 0;
21861
+ const path = key.split("/").map(encodeURIComponent).join("/");
21862
+ return `${page2}/artifacts/${path}${token2 ? `?t=${encodeURIComponent(token2)}` : ""}`;
21863
+ }
21588
21864
  function stripPlatformPrefix(id) {
21589
21865
  const i = id.indexOf(":");
21590
21866
  return i === -1 ? id : id.slice(i + 1);
@@ -24257,7 +24533,8 @@ async function readRequest(ctx) {
24257
24533
  }
24258
24534
  function resolveRun(deps, ctx) {
24259
24535
  const { msg, directives, history } = ctx;
24260
- const sticky = lastThreadDirectives(history);
24536
+ const fromTurns = lastThreadDirectives(history);
24537
+ const sticky = ctx.stickyAgent !== void 0 ? { ...fromTurns, agent: ctx.stickyAgent } : fromTurns;
24261
24538
  const resolved = deps.config.resolve({
24262
24539
  channelId: msg.channelId,
24263
24540
  userId: msg.userId,
@@ -25082,7 +25359,7 @@ var init_tracingExecutor = __esm({
25082
25359
  });
25083
25360
 
25084
25361
  // ../../src/core/prDescription.ts
25085
- import { z as z19 } from "zod";
25362
+ import { z as z20 } from "zod";
25086
25363
  function parsePrDescription(input) {
25087
25364
  return PrDescriptionSchema.parse(input);
25088
25365
  }
@@ -25370,34 +25647,34 @@ var init_prDescription = __esm({
25370
25647
  "../../src/core/prDescription.ts"() {
25371
25648
  "use strict";
25372
25649
  init_redact();
25373
- line2 = z19.string().trim().min(1).refine((s) => !/[\r\n]/.test(s), "must be a single line (no embedded newlines)");
25374
- prose = z19.string().trim().min(1);
25375
- TourAnchorSchema = z19.object({
25650
+ line2 = z20.string().trim().min(1).refine((s) => !/[\r\n]/.test(s), "must be a single line (no embedded newlines)");
25651
+ prose = z20.string().trim().min(1);
25652
+ TourAnchorSchema = z20.object({
25376
25653
  // Repo-relative: no leading `/`, no `..` SEGMENT (a filename like `a..b.ts` is fine).
25377
- path: z19.string().trim().min(1).refine((p) => !p.startsWith("/") && !p.split("/").includes(".."), "path must be repo-relative"),
25378
- from: z19.number().int().positive(),
25379
- to: z19.number().int().positive()
25654
+ path: z20.string().trim().min(1).refine((p) => !p.startsWith("/") && !p.split("/").includes(".."), "path must be repo-relative"),
25655
+ from: z20.number().int().positive(),
25656
+ to: z20.number().int().positive()
25380
25657
  }).refine((a) => a.to >= a.from, "to must be >= from");
25381
- TourStepSchema = z19.object({
25658
+ TourStepSchema = z20.object({
25382
25659
  title: line2,
25383
25660
  description: prose,
25384
25661
  lookFor: prose.optional(),
25385
25662
  anchor: TourAnchorSchema
25386
25663
  });
25387
- PrDescriptionSchema = z19.object({
25664
+ PrDescriptionSchema = z20.object({
25388
25665
  /** The PR title's single source. Metadata for the PR's own title field —
25389
25666
  * never rendered into the body (GitHub shows the title itself). */
25390
25667
  title: line2,
25391
25668
  tldr: prose,
25392
25669
  whatWhy: prose,
25393
- tour: z19.array(TourStepSchema).min(1),
25670
+ tour: z20.array(TourStepSchema).min(1),
25394
25671
  /** Every touched file the Tour steps did not cover, one line each. */
25395
- remaining: z19.array(z19.object({ path: line2, note: prose })),
25396
- decisions: z19.array(z19.object({ title: line2, rationale: prose })).min(1),
25672
+ remaining: z20.array(z20.object({ path: line2, note: prose })),
25673
+ decisions: z20.array(z20.object({ title: line2, rationale: prose })).min(1),
25397
25674
  risks: prose,
25398
- validation: z19.object({
25675
+ validation: z20.object({
25399
25676
  summary: prose.optional(),
25400
- criteria: z19.array(z19.object({ criterion: prose, proof: prose })).min(1)
25677
+ criteria: z20.array(z20.object({ criterion: prose, proof: prose })).min(1)
25401
25678
  })
25402
25679
  });
25403
25680
  REPO_RE = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
@@ -26169,10 +26446,11 @@ async function attachThroughStore(path, name, lead, artifacts, ctx) {
26169
26446
  }
26170
26447
  ctx.publish?.({ type: "artifact", direction: "out", key, name, size, contentType });
26171
26448
  if (!ctx.uploadTicket) {
26172
- const where = artifacts.runUrl ? ` \u2014 ${artifacts.runUrl}` : "";
26449
+ const link = artifacts.artifactUrl?.(key);
26450
+ const where = link ? ` \u2014 ${link}` : ` is on the run page as ${key}`;
26173
26451
  await artifacts.reply(`${lead}
26174
- \u{1F4CE} ${name} (${size} bytes) is on the run page${where}`);
26175
- return `attached ${name} (${size} bytes) to the run page; this conversation's channel takes no file uploads, so the lead and the page's link were posted instead`;
26452
+ \u{1F4CE} ${name} (${size} bytes)${where}`);
26453
+ return `attached ${name} (${size} bytes) to the run page as ${key}; this conversation's channel takes no file uploads, so the lead and the file's link were posted instead`;
26176
26454
  }
26177
26455
  const kept = "the file is kept on the run page";
26178
26456
  let ticket;
@@ -26639,7 +26917,7 @@ var init_runs2 = __esm({
26639
26917
  });
26640
26918
 
26641
26919
  // ../../src/tools/workspace.ts
26642
- import { z as z20 } from "zod";
26920
+ import { z as z21 } from "zod";
26643
26921
  var bashTool, readFileTool, writeFileTool, NAME_STATUS_MARK, NAME_STATUS_MARK_LINE, OUTPUT_CUT_RE, diffDigestTool, submitVerdictTool, submitDispositionsTool, submitPrDescriptionTool, handoffEntry, submitHandoffTool, updateStatusTool, TOOLSETS;
26644
26922
  var init_workspace = __esm({
26645
26923
  "../../src/tools/workspace.ts"() {
@@ -26938,7 +27216,7 @@ ${raw.trim()}`;
26938
27216
  try {
26939
27217
  desc = parsePrDescription(input);
26940
27218
  } catch (err2) {
26941
- const detail = err2 instanceof z20.ZodError ? err2.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ") : String(err2);
27219
+ const detail = err2 instanceof z21.ZodError ? err2.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ") : String(err2);
26942
27220
  return `error: invalid PR description \u2014 ${detail}`;
26943
27221
  }
26944
27222
  ctx.onPrDescription?.(desc);
@@ -29483,7 +29761,8 @@ async function claimRun(deps, ctx) {
29483
29761
  parentRunId,
29484
29762
  coordinator,
29485
29763
  seed,
29486
- route: route3
29764
+ route: route3,
29765
+ seedLog
29487
29766
  } = ctx;
29488
29767
  const { resident, binding } = selection;
29489
29768
  let ledgerRun = ctx.ledgerRun;
@@ -29528,8 +29807,9 @@ async function claimRun(deps, ctx) {
29528
29807
  ({ name, description, inputSchema }) => ({ name, description, inputSchema })
29529
29808
  ),
29530
29809
  // The seed carries the EFFECTIVE budget, so a resume runs on what
29531
- // this run was admitted with, not on the preset's own number.
29532
- seed: { messages, budgetMs: profile.minutes * 6e4 },
29810
+ // this run was admitted with, not on the preset's own number — and,
29811
+ // for a seed read from the log, the rows it reuses (session-log item 9).
29812
+ seed: { messages, budgetMs: profile.minutes * 6e4, ...seedLog ? { log: seedLog } : {} },
29533
29813
  // A stop asked of another container (`/runs/stop` there) reaches this
29534
29814
  // run through its heartbeat and is honored like a local one; a fence
29535
29815
  // (another generation took the run) is a hard stop — nothing more may
@@ -29599,7 +29879,7 @@ function writeFileScripts(path, content) {
29599
29879
  chunks.push(content.slice(i, i + WRITE_CHUNK_CHARS));
29600
29880
  const dir = path.slice(0, path.lastIndexOf("/")) || ".";
29601
29881
  return chunks.map(
29602
- (chunk, i) => i === 0 ? `mkdir -p ${shellQuote(dir)} && umask 077 && printf '%s' ${shellQuote(chunk)} > ${shellQuote(path)}` : `printf '%s' ${shellQuote(chunk)} >> ${shellQuote(path)}`
29882
+ (chunk, i) => i === 0 ? `umask 077 && mkdir -p ${shellQuote(dir)} && printf '%s' ${shellQuote(chunk)} > ${shellQuote(path)}` : `printf '%s' ${shellQuote(chunk)} >> ${shellQuote(path)}`
29603
29883
  );
29604
29884
  }
29605
29885
  function startScript(start3) {
@@ -29610,7 +29890,7 @@ function startScript(start3) {
29610
29890
  `pi ${args.map(shellQuote).join(" ")} <&3 2>>${shellQuote(paths.errLog)} | ${LOG_FILTER} >> ${shellQuote(paths.log)}`
29611
29891
  ].join("; ");
29612
29892
  return [
29613
- `mkdir -p ${shellQuote(paths.dir)} ${shellQuote(paths.sessionDir)} ${shellQuote(paths.commandDir)}`,
29893
+ `(umask 077 && mkdir -p ${shellQuote(paths.dir)} ${shellQuote(paths.sessionDir)} ${shellQuote(paths.commandDir)})`,
29614
29894
  `rm -f ${shellQuote(paths.fifo)}`,
29615
29895
  `mkfifo -m 600 ${shellQuote(paths.fifo)}`,
29616
29896
  `: > ${shellQuote(paths.log)}`,
@@ -29638,6 +29918,9 @@ function killScript(pid) {
29638
29918
  function tailScript(path, bytes) {
29639
29919
  return `tail -c ${bytes} ${shellQuote(path)} 2>/dev/null || true`;
29640
29920
  }
29921
+ function removeScript(dir) {
29922
+ return `rm -rf ${shellQuote(dir)}`;
29923
+ }
29641
29924
  function stdoutOf(operation, out) {
29642
29925
  const exit = parseExitPrefix(out);
29643
29926
  if (exit.failed) throw new PiContainerError(operation, out);
@@ -29706,6 +29989,9 @@ var init_container = __esm({
29706
29989
  return "";
29707
29990
  }
29708
29991
  }
29992
+ async remove(paths) {
29993
+ stdoutOf("remove", await this.exec(removeScript(paths.dir)));
29994
+ }
29709
29995
  exec(script, env) {
29710
29996
  return this.executor.exec(script, { timeoutMs: OP_TIMEOUT_MS, ...env ? { env } : {} });
29711
29997
  }
@@ -30382,9 +30668,8 @@ function piBuiltinToolsFor(identity2) {
30382
30668
  function piThinkingLevel(effort2) {
30383
30669
  return effort2;
30384
30670
  }
30385
- function piRunPaths(runId3, user) {
30386
- const root = user ? `/tmp/switchboard-pi-${user}` : "/tmp/switchboard-pi";
30387
- const dir = `${root}/${runId3}`;
30671
+ function piRunPaths(runId3) {
30672
+ const dir = `/tmp/switchboard-pi-${runId3}`;
30388
30673
  return {
30389
30674
  dir,
30390
30675
  agentDir: `${dir}/agent`,
@@ -30631,7 +30916,7 @@ async function runPiHarness(deps, run2) {
30631
30916
  emit({ type: "run_note", kind, summary, ...mode ? { mode } : {} });
30632
30917
  };
30633
30918
  const bridge = new PiBridge({ emit, onProgress: run2.onProgress, agentSpan, clock: clock3 });
30634
- const paths = piRunPaths(run2.runId, run2.user);
30919
+ const paths = piRunPaths(run2.runId);
30635
30920
  const remainingMs = run2.resume?.remainingMs ?? run2.agent.maxMinutes * 6e4;
30636
30921
  const deadline = now() + remainingMs;
30637
30922
  const warnAt = deadline - Math.min(3 * 6e4, run2.agent.maxMinutes * 15e3);
@@ -30903,6 +31188,8 @@ async function runPiHarness(deps, run2) {
30903
31188
  forget();
30904
31189
  if (pid !== void 0) await container.kill(pid).catch(() => {
30905
31190
  });
31191
+ await container.remove(paths).catch(() => {
31192
+ });
30906
31193
  agentSpan?.end(hardStopped || bypass ? "error" : "ok");
30907
31194
  }
30908
31195
  }
@@ -31577,12 +31864,11 @@ async function runLoop2(deps, ctx) {
31577
31864
  const uploadTicket = io.uploadTicket?.bind(io);
31578
31865
  const nextStagedIndex = ctx.stagingIndex ?? stagingIndex();
31579
31866
  let artifactSeq = 0;
31580
- const runUrl = runPageLink(run2.id);
31581
31867
  const artifacts = deps.artifacts ? {
31582
31868
  store: deps.artifacts,
31583
31869
  runId: run2.id,
31584
31870
  nextSeq: () => ++artifactSeq,
31585
- ...runUrl ? { runUrl } : {},
31871
+ artifactUrl: (key) => artifactLink(run2.id, key, run2.token),
31586
31872
  reply: (text) => io.reply(text)
31587
31873
  } : void 0;
31588
31874
  const toolContext = {
@@ -31651,10 +31937,6 @@ async function runLoop2(deps, ctx) {
31651
31937
  ...ownBranch !== void 0 ? { branch: ownBranch } : {},
31652
31938
  protectedBranches
31653
31939
  },
31654
- // The resident runs this thread's commands as its pool user: pi's
31655
- // files go under that user's own root, never one another thread's
31656
- // user created (harness-pi.md item 4).
31657
- ...binding?.user ? { user: binding.user } : {},
31658
31940
  ...round2.selection.backend ? { backend: round2.selection.backend } : {},
31659
31941
  span: root,
31660
31942
  control: run2.control,
@@ -33326,15 +33608,7 @@ var init_settle = __esm({
33326
33608
  });
33327
33609
 
33328
33610
  // ../../src/core/dispatch/lineage.ts
33329
- async function threadLineage(service, threadKey) {
33330
- let newest;
33331
- try {
33332
- const page2 = await service.listRuns({ status: "all", visibleTo: { kind: "all" }, threadKey, limit: 1 });
33333
- newest = page2.runs[0];
33334
- } catch (err2) {
33335
- console.warn(`[lineage] ${threadKey}: thread read failed \u2014 ${err2 instanceof Error ? err2.message : String(err2)}`);
33336
- return void 0;
33337
- }
33611
+ function lineageOf(newest) {
33338
33612
  if (newest === void 0 || newest.parentRunId === void 0) return void 0;
33339
33613
  return {
33340
33614
  parentRunId: newest.parentRunId,
@@ -33391,6 +33665,161 @@ var init_lineage = __esm({
33391
33665
  }
33392
33666
  });
33393
33667
 
33668
+ // ../../src/core/runLedger/sessionLog.ts
33669
+ function sessionKey(threadKey, agent) {
33670
+ return `${threadKey}:${agent ?? "-"}`;
33671
+ }
33672
+ function requestIndex(seed) {
33673
+ for (let i = seed.length - 1; i >= 0; i--) if (seed[i].role === "user") return i;
33674
+ return 0;
33675
+ }
33676
+ var DEFAULT_SESSION_LOG_MAX_BYTES;
33677
+ var init_sessionLog = __esm({
33678
+ "../../src/core/runLedger/sessionLog.ts"() {
33679
+ "use strict";
33680
+ init_runRecord();
33681
+ init_runRecord();
33682
+ DEFAULT_SESSION_LOG_MAX_BYTES = DEFAULT_RETENTION_POLICY.sessionLogMaxBytes;
33683
+ }
33684
+ });
33685
+
33686
+ // ../../src/core/dispatch/thread.ts
33687
+ async function readThread(service, threadKey) {
33688
+ try {
33689
+ const page2 = await service.listRuns({
33690
+ status: "all",
33691
+ visibleTo: { kind: "all" },
33692
+ threadKey,
33693
+ limit: THREAD_READ_LIMIT
33694
+ });
33695
+ return page2.runs;
33696
+ } catch (err2) {
33697
+ console.warn(`[thread] ${threadKey}: thread read failed \u2014 ${err2 instanceof Error ? err2.message : String(err2)}`);
33698
+ return void 0;
33699
+ }
33700
+ }
33701
+ function continuable(run2) {
33702
+ return run2.finished && run2.session !== void 0 && run2.agent !== void 0;
33703
+ }
33704
+ function stickyAgentOf(runs, onPi) {
33705
+ const newest = runs[0];
33706
+ if (newest === void 0 || !continuable(newest) || !onPi(newest.agent)) return void 0;
33707
+ return newest.agent;
33708
+ }
33709
+ function previousRunOf(runs, agent) {
33710
+ const run2 = runs.find((r) => r.agent === agent && continuable(r));
33711
+ if (run2 === void 0) return void 0;
33712
+ return {
33713
+ ...run2.finishedAt !== void 0 ? { finishedAt: run2.finishedAt } : {},
33714
+ broken: run2.session.range === "broken"
33715
+ };
33716
+ }
33717
+ var THREAD_READ_LIMIT;
33718
+ var init_thread = __esm({
33719
+ "../../src/core/dispatch/thread.ts"() {
33720
+ "use strict";
33721
+ THREAD_READ_LIMIT = 8;
33722
+ }
33723
+ });
33724
+
33725
+ // ../../src/core/dispatch/seed.ts
33726
+ function sessionSeed(input) {
33727
+ const { tail, previous, history, request } = input;
33728
+ const { from, transcript } = tail;
33729
+ if (from === 0 && transcript.turns === 0) return void 0;
33730
+ const notes = [];
33731
+ const messages = [];
33732
+ const compactions = transcript.compactions;
33733
+ const afterCompaction = compactions.reduce((n2, c) => Math.max(n2, c.before), 0);
33734
+ let start3 = -1;
33735
+ for (let i = afterCompaction; i < transcript.messages.length; i++) {
33736
+ const m = transcript.messages[i];
33737
+ if (m.role === "user" && m.content.some((p) => p.type === "text")) {
33738
+ start3 = i;
33739
+ break;
33740
+ }
33741
+ }
33742
+ const summary = compactions.length ? compactions[compactions.length - 1].entry.summary : void 0;
33743
+ const logFrom = start3 < 0 ? from + transcript.turns : from + start3 + compactions.length;
33744
+ const kept = start3 < 0 ? [] : transcript.messages.slice(start3).map(withoutThinking);
33745
+ if (kept.length === 0) {
33746
+ notes.push(
33747
+ transcript.turns === 0 ? "session seed: the log's newest turn alone is over the seed budget \u2014 the run starts from the request" : "session seed: no user text turn in the tail within the seed budget \u2014 the run starts from the request"
33748
+ );
33749
+ }
33750
+ messages.push(...kept);
33751
+ const last = kept[kept.length - 1];
33752
+ if (last?.role === "assistant") {
33753
+ const calls = last.content.filter((p) => p.type === "tool_use");
33754
+ if (calls.length > 0) {
33755
+ messages.push({
33756
+ role: "user",
33757
+ content: calls.map((c) => ({
33758
+ type: "tool_result",
33759
+ toolUseId: c.id,
33760
+ content: settledResult(c.name),
33761
+ isError: true
33762
+ }))
33763
+ });
33764
+ }
33765
+ }
33766
+ if (previous?.broken) messages.push({ role: "user", content: [{ type: "text", text: GAP_MARKER }] });
33767
+ if (previous?.finishedAt === void 0) {
33768
+ notes.push(
33769
+ "session seed: the previous run's end is unknown, so the lines written since could not be told apart \u2014 only the request follows the tail"
33770
+ );
33771
+ } else {
33772
+ const end = previous.finishedAt;
33773
+ for (const h of history) {
33774
+ if (h.role !== "user" || h.at === void 0 || h.at <= end) continue;
33775
+ messages.push({ role: "user", content: turnContent(h.text, h.images, h.documents) });
33776
+ }
33777
+ }
33778
+ messages.push({ role: "user", content: turnContent(request.text, request.images, request.documents) });
33779
+ return {
33780
+ messages,
33781
+ log: { from: logFrom, turns: kept.length },
33782
+ ...summary !== void 0 ? { summary } : {},
33783
+ notes
33784
+ };
33785
+ }
33786
+ async function sessionSeedFor(input) {
33787
+ const key = sessionKey(input.threadKey, input.agent);
33788
+ let tail;
33789
+ try {
33790
+ tail = await input.ledger.readSessionTail(key, SEED_BUDGET_BYTES);
33791
+ } catch (err2) {
33792
+ const why = err2 instanceof Error ? err2.message : String(err2);
33793
+ return { notes: [`session seed: the log ${key} could not be read (${why}) \u2014 the run seeds from the channel`] };
33794
+ }
33795
+ const seed = sessionSeed({
33796
+ tail,
33797
+ previous: previousRunOf(input.thread, input.agent),
33798
+ history: input.history,
33799
+ request: input.request
33800
+ });
33801
+ return seed ? { seed, notes: seed.notes } : { notes: [] };
33802
+ }
33803
+ function withoutThinking(message2) {
33804
+ if (message2.role !== "assistant") return message2;
33805
+ const content = message2.content.filter((p) => p.type !== "thinking" && p.type !== "redacted_thinking");
33806
+ if (content.length === message2.content.length) return message2;
33807
+ return { ...message2, content: content.length ? content : [{ type: "text", text: "(reasoning omitted)" }] };
33808
+ }
33809
+ var SEED_BUDGET_TOKENS, SEED_BUDGET_BYTES, GAP_MARKER, settledResult;
33810
+ var init_seed = __esm({
33811
+ "../../src/core/dispatch/seed.ts"() {
33812
+ "use strict";
33813
+ init_sessionLog();
33814
+ init_messages();
33815
+ init_thread();
33816
+ SEED_BUDGET_TOKENS = 6e4;
33817
+ SEED_BUDGET_BYTES = SEED_BUDGET_TOKENS * 4;
33818
+ GAP_MARKER = "[The log of this conversation ends short of what the previous run saw: its connection to the ledger broke, so its later turns and its final reply are not here.]";
33819
+ settledResult = (toolName) => `The run that made this call ended before this ${toolName} call's result was recorded; its effects are unknown \u2014 re-check them before repeating it.`;
33820
+ }
33821
+ });
33822
+
33394
33823
  // ../../src/core/runEnding.ts
33395
33824
  function createRunEnding(deps) {
33396
33825
  const log = deps.log ?? console.error;
@@ -33528,7 +33957,8 @@ async function dispatch(deps, msg, io, opts = {}) {
33528
33957
  const { directives, history } = await readRequest({ msg, io, root });
33529
33958
  if (await answerOperation(deps, { msg, io, ending, trace, directives, history })) return ended;
33530
33959
  const runsService = deps.runs ?? createRunsService({ registry, store: deps.runStore });
33531
- const lineage = opts.parent || opts.coordinator || resume || restart ? void 0 : await threadLineage(runsService, msg.threadKey);
33960
+ const thread = opts.parent || opts.coordinator || resume || restart || history.length === 0 ? void 0 : await readThread(runsService, msg.threadKey);
33961
+ const lineage = lineageOf(thread?.[0]);
33532
33962
  const parent = opts.parent ?? (lineage ? lineageParent(lineage) : void 0);
33533
33963
  const tellLineage = async (heard) => {
33534
33964
  if (!lineage) return;
@@ -33539,7 +33969,18 @@ async function dispatch(deps, msg, io, opts = {}) {
33539
33969
  heard
33540
33970
  );
33541
33971
  };
33542
- const settled = resolveRun(deps, { msg, directives, history });
33972
+ const harnessBlock = deps.config.config.harness;
33973
+ const onPi = (name) => {
33974
+ const def = AGENTS[name];
33975
+ return def !== void 0 && effectiveHarness(def, harnessBlock) === "pi";
33976
+ };
33977
+ const stickyAgent = thread ? stickyAgentOf(thread, onPi) : void 0;
33978
+ const settled = resolveRun(deps, {
33979
+ msg,
33980
+ directives,
33981
+ history,
33982
+ ...stickyAgent !== void 0 ? { stickyAgent } : {}
33983
+ });
33543
33984
  const { sticky } = settled;
33544
33985
  let { resolved, agentSource } = settled;
33545
33986
  let route3;
@@ -33677,8 +34118,23 @@ async function dispatch(deps, msg, io, opts = {}) {
33677
34118
  }
33678
34119
  const contractBlock = opts.contract ? renderContract(opts.contract, { maxChars: DEFAULT_CONTRACT_MAX_CHARS }).text : void 0;
33679
34120
  const requestText = route3?.parts ? compoundBrief(directives.text, route3.parts) : directives.text;
33680
- const seed = opts.seed ? "parent" : "channel";
33681
- const built = buildMessages(opts.seed ?? history, requestText, msg.images, msg.documents);
34121
+ const fromSession = !resume && !opts.seed && thread && effectiveHarness(agent, harnessBlock) === "pi" ? await sessionSeedFor({
34122
+ ledger: deps.runLedger,
34123
+ threadKey: msg.threadKey,
34124
+ agent: agent.name,
34125
+ thread,
34126
+ history,
34127
+ request: {
34128
+ text: requestText,
34129
+ ...msg.images ? { images: msg.images } : {},
34130
+ ...msg.documents ? { documents: msg.documents } : {}
34131
+ }
34132
+ }) : void 0;
34133
+ const session = fromSession?.seed;
34134
+ const seedNotes = fromSession?.notes ?? [];
34135
+ const seed = opts.seed ? "parent" : session ? "session" : "channel";
34136
+ const seedTurns = opts.seed ?? (session ? textTurnsOf(session.messages.slice(0, -1)) : void 0);
34137
+ const built = session ? session.messages : buildMessages(opts.seed ?? history, requestText, msg.images, msg.documents);
33682
34138
  const messages = resume ? resume.plan.messages : contractBlock !== void 0 && agent.name !== "review" ? withContractInFirstUserTurn(built, contractBlock) : built;
33683
34139
  const headPreflight = await authorizePrHead({
33684
34140
  msg,
@@ -33716,12 +34172,14 @@ async function dispatch(deps, msg, io, opts = {}) {
33716
34172
  parentRunId,
33717
34173
  coordinator,
33718
34174
  seed,
33719
- ...opts.seed ? { seedTurns: opts.seed } : {},
34175
+ ...seedTurns ? { seedTurns } : {},
33720
34176
  agentSource,
33721
34177
  ...routeEvent ? { route: routeEvent } : {}
33722
34178
  });
33723
34179
  const { run: run2, runId: runId3, channelVisibility, liveUrl, publishText, publishMeta } = registration;
33724
34180
  registered = run2;
34181
+ for (const summary of seedNotes)
34182
+ registry.publish(run2.id, { type: "run_note", kind: "seed", summary: oneLine(summary), at: clock3() });
33725
34183
  await tellLineage({ kind: "started", runId: runId3 });
33726
34184
  const staged = !resume && deps.artifacts && msg.staged && msg.staged.length > 0 ? msg.staged : [];
33727
34185
  const nextStagedIndex = stagingIndex();
@@ -33886,7 +34344,8 @@ async function dispatch(deps, msg, io, opts = {}) {
33886
34344
  root,
33887
34345
  parentRunId,
33888
34346
  coordinator,
33889
- seed
34347
+ seed,
34348
+ ...session ? { seedLog: session.log } : {}
33890
34349
  });
33891
34350
  const { spawn: spawn7, runs, steer, wait } = runToolCapabilities(
33892
34351
  { core: deps, dispatch, registry, clock: clock3 },
@@ -34067,6 +34526,9 @@ var init_dispatcher = __esm({
34067
34526
  init_codingChild();
34068
34527
  init_settle();
34069
34528
  init_lineage();
34529
+ init_seed();
34530
+ init_thread();
34531
+ init_select();
34070
34532
  init_spawn();
34071
34533
  init_runsService();
34072
34534
  init_runRegistry();
@@ -34468,24 +34930,6 @@ var init_flusher = __esm({
34468
34930
  }
34469
34931
  });
34470
34932
 
34471
- // ../../src/core/runLedger/sessionLog.ts
34472
- function sessionKey(threadKey, agent) {
34473
- return `${threadKey}:${agent ?? "-"}`;
34474
- }
34475
- function requestIndex(seed) {
34476
- for (let i = seed.length - 1; i >= 0; i--) if (seed[i].role === "user") return i;
34477
- return 0;
34478
- }
34479
- var DEFAULT_SESSION_LOG_MAX_BYTES;
34480
- var init_sessionLog = __esm({
34481
- "../../src/core/runLedger/sessionLog.ts"() {
34482
- "use strict";
34483
- init_runRecord();
34484
- init_runRecord();
34485
- DEFAULT_SESSION_LOG_MAX_BYTES = DEFAULT_RETENTION_POLICY.sessionLogMaxBytes;
34486
- }
34487
- });
34488
-
34489
34933
  // ../../src/core/runLedger/types.ts
34490
34934
  var LEASE_MS, HEARTBEAT_MS, APPEND_FLUSH_MS, APPEND_FLUSH_EVENTS, TRANSCRIPT_REQUEST_BYTES, TRANSCRIPT_PART_BYTES, ATTACHMENT_REF_BYTES, GEN_PATTERN;
34491
34935
  var init_types5 = __esm({
@@ -34538,7 +34982,15 @@ function createLedgerWriteThrough(opts) {
34538
34982
  if (opts2.seed) {
34539
34983
  const key = sessionKey(req.threadKey, req.meta.agent);
34540
34984
  const next = await ledger.sessionTail(key);
34541
- session = { key, seedFrom: next, request: next + requestIndex(opts2.seed), range: { from: next } };
34985
+ let seedFrom = next;
34986
+ if (opts2.log) {
34987
+ if (opts2.log.from + opts2.log.turns === next) seedFrom = opts2.log.from;
34988
+ else
34989
+ warn(
34990
+ `[ledger] ${req.threadKey} run ${req.runId}: the seed names log rows ${opts2.log.from}..${opts2.log.from + opts2.log.turns - 1} but the log's tail is ${next} \u2014 the whole seed is written as new rows`
34991
+ );
34992
+ }
34993
+ session = { key, seedFrom, request: seedFrom + requestIndex(opts2.seed), range: { from: next } };
34542
34994
  }
34543
34995
  const result = await ledger.claim({
34544
34996
  runId: req.runId,
@@ -34699,7 +35151,8 @@ function createLedgerWriteThrough(opts) {
34699
35151
  * closes `interrupted`. */
34700
35152
  async seed(messages, budgetMs) {
34701
35153
  const base = this.session?.seedFrom ?? 0;
34702
- const turns = messages.map((message2, i) => ({ idx: base + i, message: message2 }));
35154
+ const reused = this.session && this.session.range !== "broken" ? this.session.range.from - this.session.seedFrom : 0;
35155
+ const turns = messages.slice(reused).map((message2, i) => ({ idx: base + reused + i, message: message2 }));
34703
35156
  try {
34704
35157
  const seeded = await ledger.seed(this.runId, gen, turns, this.session?.key);
34705
35158
  if (!seeded.ok) {
@@ -34869,7 +35322,7 @@ function createLedgerWriteThrough(opts) {
34869
35322
  const seed = req.seed?.messages;
34870
35323
  if (reserved instanceof TrackedRun) {
34871
35324
  if (!reserved.tracked()) return void 0;
34872
- const claimed3 = await claim(req, seed ? { seed } : {});
35325
+ const claimed3 = await claim(req, seed ? { seed, ...req.seed?.log ? { log: req.seed.log } : {} } : {});
34873
35326
  if (claimed3.outcome === "fenced") {
34874
35327
  reserved.detach("promotion refused (fenced)");
34875
35328
  return void 0;
@@ -34883,7 +35336,7 @@ function createLedgerWriteThrough(opts) {
34883
35336
  if (req.seed) await reserved.seed(req.seed.messages, req.seed.budgetMs);
34884
35337
  return reserved;
34885
35338
  }
34886
- const claimed2 = await claim(req, seed ? { seed } : {});
35339
+ const claimed2 = await claim(req, seed ? { seed, ...req.seed?.log ? { log: req.seed.log } : {} } : {});
34887
35340
  if (claimed2.outcome === "fenced") {
34888
35341
  warn(`[ledger] ${req.threadKey} not tracked: run ${req.runId} is live under another generation`);
34889
35342
  return void 0;
@@ -34932,6 +35385,7 @@ function createLedgerWriteThrough(opts) {
34932
35385
  return [];
34933
35386
  }
34934
35387
  },
35388
+ readSessionTail: (key, maxBytes) => ledger.readSessionTail(key, maxBytes),
34935
35389
  async handoff() {
34936
35390
  const candidates = [...live].filter((r) => r.resumable && r.tracked() && !r.handedOff);
34937
35391
  if (candidates.length === 0) return { marked: [] };
@@ -34982,6 +35436,9 @@ var init_writeThrough = __esm({
34982
35436
  async readInbox(_runId, _afterSeq) {
34983
35437
  return [];
34984
35438
  }
35439
+ async readSessionTail(_key, _maxBytes) {
35440
+ return { from: 0, transcript: { complete: true, turns: 0, messages: [], compactions: [] } };
35441
+ }
34985
35442
  async handoff() {
34986
35443
  return { marked: [] };
34987
35444
  }
@@ -36895,7 +37352,8 @@ ${file.text}`));
36895
37352
  if (STATUS_PREFIXES.some((p) => text.startsWith(p))) continue;
36896
37353
  const files = mm.bot_id ? void 0 : mm.files;
36897
37354
  if (!text && !files?.length) continue;
36898
- kept.push({ role: mm.bot_id ? "assistant" : "user", text, files });
37355
+ const at = mm.ts !== void 0 && Number.isFinite(Number(mm.ts)) ? Math.round(Number(mm.ts) * 1e3) : void 0;
37356
+ kept.push({ role: mm.bot_id ? "assistant" : "user", text, ...at !== void 0 ? { at } : {}, files });
36899
37357
  }
36900
37358
  const imagesByIndex = [];
36901
37359
  const documentsByIndex = [];
@@ -36922,11 +37380,11 @@ ${file.text}`));
36922
37380
  }
36923
37381
  }
36924
37382
  for (let i = 0; i < kept.length; i++) {
36925
- const { role, text } = kept[i];
37383
+ const { role, text, at } = kept[i];
36926
37384
  const images = imagesByIndex[i];
36927
37385
  const documents = documentsByIndex[i];
36928
37386
  if (!text && !images && !documents) continue;
36929
- items.push({ role, text, images, documents });
37387
+ items.push({ role, text, ...at !== void 0 ? { at } : {}, images, documents });
36930
37388
  }
36931
37389
  } catch {
36932
37390
  }