@kubitnodes/stellaris 0.3.22 → 0.3.23

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 (54) hide show
  1. package/README.md +4 -4
  2. package/dist/cli/index.js +556 -413
  3. package/dist/server/index.js +666 -473
  4. package/package.json +1 -1
  5. package/web/dist/assets/BackLink-DGYs80bb.js +1 -0
  6. package/web/dist/assets/{Button-Yoe21NQ2.js → Button-f4jgBZY1.js} +1 -1
  7. package/web/dist/assets/{ChannelForms-55otlg-m.js → ChannelForms-q9zdj4p2.js} +1 -1
  8. package/web/dist/assets/{ChannelView-DJvLzg0N.js → ChannelView-CGs_aWL3.js} +2 -2
  9. package/web/dist/assets/{CitizenView-m1K2aTvK.js → CitizenView-gcIo_sKt.js} +2 -2
  10. package/web/dist/assets/CitizensView-DZ7S8vnJ.js +1 -0
  11. package/web/dist/assets/{CliIcon-DbMYJdlU.js → CliIcon-CLHaA65A.js} +1 -1
  12. package/web/dist/assets/{CronsView-B4kXk5Ld.js → CronsView-1wns6Uwv.js} +1 -1
  13. package/web/dist/assets/{KnowledgeView-aSGxDDKy.js → KnowledgeView-Cxfi2-Pt.js} +1 -1
  14. package/web/dist/assets/Markdown-BhtIFcWc.js +30 -0
  15. package/web/dist/assets/MessageItem-Bk9eBp1U.js +1 -0
  16. package/web/dist/assets/MetricsView-CTEH6rJn.js +1 -0
  17. package/web/dist/assets/NeedsYouView-2VNqH2Sb.js +1 -0
  18. package/web/dist/assets/{Overview-BveU1yJj.js → Overview-CS9HCSmm.js} +1 -1
  19. package/web/dist/assets/{Pane-CLjdfBMM.js → Pane-CJYRVkwh.js} +1 -1
  20. package/web/dist/assets/{Picker-CXOe5Xdu.js → Picker-DoxCN6C7.js} +1 -1
  21. package/web/dist/assets/{ProjectView-oa4Z46ED.js → ProjectView-CJ3r4UdN.js} +1 -1
  22. package/web/dist/assets/ProposalView-DLn9dNPp.js +2 -0
  23. package/web/dist/assets/{ProposalsView-BZHivSEm.js → ProposalsView-B-cOxTsQ.js} +1 -1
  24. package/web/dist/assets/{Quota-BC7dpnwd.js → Quota-Bo7UdWTV.js} +1 -1
  25. package/web/dist/assets/{RunnersView-BrJF-aLU.js → RunnersView-DlQruhwp.js} +1 -1
  26. package/web/dist/assets/{SocietyView-C1yosPuf.js → SocietyView-Bl4ErnV8.js} +1 -1
  27. package/web/dist/assets/{StickyList-7tAlUDCN.js → StickyList-MVP34ytV.js} +1 -1
  28. package/web/dist/assets/{SubjectThread-CCq6ZAnR.js → SubjectThread-BFFnHxIF.js} +1 -1
  29. package/web/dist/assets/{TaskFileView-BEXQJQQ6.js → TaskFileView-GZ0eQFUb.js} +2 -2
  30. package/web/dist/assets/{TaskView-Cfhb7NuO.js → TaskView-DppFelLW.js} +2 -2
  31. package/web/dist/assets/{TasksView-3XljXcoi.js → TasksView-DDNXzeG4.js} +1 -1
  32. package/web/dist/assets/{ThreadForms-D2y5dXSC.js → ThreadForms-C846TvtS.js} +1 -1
  33. package/web/dist/assets/{ThreadItem-DeIhhmyu.js → ThreadItem-C8cou6wD.js} +1 -1
  34. package/web/dist/assets/{ThreadView-CbUnt9WL.js → ThreadView-DvSGDYoD.js} +1 -1
  35. package/web/dist/assets/{citizen--bqux6i_.js → citizen-B2Dlbcpe.js} +1 -1
  36. package/web/dist/assets/{compose-DNc3_c5x.js → compose-BmqQmcZH.js} +1 -1
  37. package/web/dist/assets/{format-B6fjC0_a.js → format-DT52SbbR.js} +1 -1
  38. package/web/dist/assets/{governance-RBQ4Lam0.js → governance-Cr5OlQnw.js} +1 -1
  39. package/web/dist/assets/index-BTVy_xFF.js +23 -0
  40. package/web/dist/assets/index-DzV6CCnG.css +2 -0
  41. package/web/dist/assets/{mentions-B2Qchd_6.js → mentions-D5hNgtg6.js} +1 -1
  42. package/web/dist/assets/{tasks-DCUj5w_d.js → tasks-R3YgpYTe.js} +1 -1
  43. package/web/dist/assets/useMatch-pEF6RJ6Q.js +1 -0
  44. package/web/dist/index.html +9 -9
  45. package/web/dist/assets/BackLink-CD-iuy-h.js +0 -1
  46. package/web/dist/assets/CitizensView-BeTgmrKE.js +0 -1
  47. package/web/dist/assets/Markdown-c9bCCLHg.js +0 -30
  48. package/web/dist/assets/MessageItem-DKJKMqs-.js +0 -1
  49. package/web/dist/assets/MetricsView-D2TTry5O.js +0 -1
  50. package/web/dist/assets/NeedsYouView-C3celRei.js +0 -1
  51. package/web/dist/assets/ProposalView-B4T-EoX9.js +0 -2
  52. package/web/dist/assets/index-CyCty7a2.js +0 -23
  53. package/web/dist/assets/index-GRqxKN35.css +0 -2
  54. package/web/dist/assets/useMatch-CfbBQirn.js +0 -1
package/dist/cli/index.js CHANGED
@@ -9,7 +9,7 @@ import { Command } from "commander";
9
9
  import { chmod as chmod2, cp, mkdir as mkdir4, readdir as readdir3, readFile as readFile4, rename as rename3, rm as rm2, stat as stat3, writeFile as writeFile4 } from "node:fs/promises";
10
10
  import path6 from "node:path";
11
11
  import { decodeTime, monotonicFactory } from "ulid";
12
- import { z as z15 } from "zod";
12
+ import { z as z16 } from "zod";
13
13
 
14
14
  // packages/shared/dist/ids.js
15
15
  import { z } from "zod";
@@ -64,7 +64,8 @@ var VERB_NAMES = [
64
64
  "create_cron",
65
65
  "update_cron",
66
66
  "remove_cron",
67
- "remove_skill"
67
+ "remove_skill",
68
+ "upload_image"
68
69
  ];
69
70
  var VerbNameSchema = z2.enum(VERB_NAMES);
70
71
  var CharterTriggerSchema = z2.enum(["user_post", "ops_event", "heartbeat"]);
@@ -93,6 +94,7 @@ var USER_ROLE = "user";
93
94
  var USER_NAME = "user";
94
95
  var MEMBER_VERBS = [
95
96
  "post_message",
97
+ "upload_image",
96
98
  "read_inbox",
97
99
  "search",
98
100
  "open_thread",
@@ -985,130 +987,169 @@ var DecisionSchema = z5.object({
985
987
  });
986
988
 
987
989
  // packages/shared/dist/verbs.js
990
+ import { z as z7 } from "zod";
991
+
992
+ // packages/shared/dist/images.js
988
993
  import { z as z6 } from "zod";
989
- var MomentSchema = z6.iso.datetime({ offset: true });
990
- var CronTitleSchema = z6.string().trim().min(1).max(120);
991
- var CronNoteSchema = z6.string().trim().min(1).max(4e3);
994
+ var IMAGE_LIMIT_BYTES = 8 * 1024 * 1024;
995
+ var ImageTypeSchema = z6.enum(["png", "jpeg", "gif", "webp"]);
996
+ function startsWith(bytes, prefix, at = 0) {
997
+ for (let index = 0; index < prefix.length; index += 1) {
998
+ if (bytes[at + index] !== prefix[index]) {
999
+ return false;
1000
+ }
1001
+ }
1002
+ return true;
1003
+ }
1004
+ var ascii = (text) => new TextEncoder().encode(text);
1005
+ function imageTypeOf(bytes) {
1006
+ if (startsWith(bytes, [137, 80, 78, 71, 13, 10, 26, 10])) {
1007
+ return "png";
1008
+ }
1009
+ if (startsWith(bytes, [255, 216, 255])) {
1010
+ return "jpeg";
1011
+ }
1012
+ if (startsWith(bytes, ascii("GIF87a")) || startsWith(bytes, ascii("GIF89a"))) {
1013
+ return "gif";
1014
+ }
1015
+ if (startsWith(bytes, ascii("RIFF")) && startsWith(bytes, ascii("WEBP"), 8)) {
1016
+ return "webp";
1017
+ }
1018
+ return null;
1019
+ }
1020
+ var ImagePathSchema = z6.string().min(1).max(4096).refine((value) => !value.includes("\0"), { message: "a path with no NUL character" });
1021
+ var IMAGE_SCHEME = "image:";
1022
+ var UploadedImageSchema = z6.object({
1023
+ id: UlidSchema,
1024
+ type: ImageTypeSchema,
1025
+ size: z6.number().int().positive(),
1026
+ markdown: z6.string()
1027
+ });
1028
+
1029
+ // packages/shared/dist/verbs.js
1030
+ var MomentSchema = z7.iso.datetime({ offset: true });
1031
+ var CronTitleSchema = z7.string().trim().min(1).max(120);
1032
+ var CronNoteSchema = z7.string().trim().min(1).max(4e3);
992
1033
  var VerbInputs = {
993
- post_message: z6.object({
1034
+ post_message: z7.object({
994
1035
  /** Required outside a thread; in one it may be left out, and must otherwise be the thread's. */
995
1036
  channel: ChannelRefSchema.optional(),
996
- body: z6.string().min(1),
1037
+ body: z7.string().min(1),
997
1038
  thread_id: UlidSchema.optional()
998
1039
  }),
999
- read_inbox: z6.object({
1040
+ read_inbox: z7.object({
1000
1041
  since_cursor: UlidSchema.nullable().optional(),
1001
- limit: z6.number().int().positive().max(200).default(50),
1002
- advance: z6.boolean().default(true)
1042
+ limit: z7.number().int().positive().max(200).default(50),
1043
+ advance: z7.boolean().default(true)
1003
1044
  }),
1004
- search: z6.object({
1005
- query: z6.string().min(1),
1045
+ search: z7.object({
1046
+ query: z7.string().min(1),
1006
1047
  project: NameSchema.optional(),
1007
1048
  channel: ChannelRefSchema.optional(),
1008
- limit: z6.number().int().positive().max(100).default(20)
1049
+ limit: z7.number().int().positive().max(100).default(20)
1009
1050
  }),
1010
1051
  /** On a task or a proposal, whose id the thread takes, or on a channel with a title. */
1011
- open_thread: z6.object({
1052
+ open_thread: z7.object({
1012
1053
  task_id: UlidSchema.optional(),
1013
1054
  proposal_id: UlidSchema.optional(),
1014
1055
  channel: ChannelRefSchema.optional(),
1015
- title: z6.string().min(1).max(200).optional()
1056
+ title: z7.string().min(1).max(200).optional()
1016
1057
  }),
1017
- close_thread: z6.object({ thread_id: UlidSchema, summary: z6.string().min(1) }),
1018
- create_task: z6.object({
1058
+ close_thread: z7.object({ thread_id: UlidSchema, summary: z7.string().min(1) }),
1059
+ create_task: z7.object({
1019
1060
  project: NameSchema,
1020
- title: z6.string().min(1).max(200),
1021
- body: z6.string().default(""),
1061
+ title: z7.string().min(1).max(200),
1062
+ body: z7.string().default(""),
1022
1063
  parent_id: UlidSchema.optional(),
1023
- required_capabilities: z6.array(z6.string()).default([]),
1064
+ required_capabilities: z7.array(z7.string()).default([]),
1024
1065
  /** The plan; without it the task gets one stage, work, that anyone in the project may take. */
1025
- stages: z6.array(PlanStageSchema).min(1).optional(),
1066
+ stages: z7.array(PlanStageSchema).min(1).optional(),
1026
1067
  /** A channel of the project the task belongs to, such as a release's; its thread opens there. */
1027
1068
  channel: NameSchema.default("general")
1028
1069
  }),
1029
- claim_task: z6.object({ task_id: UlidSchema }),
1030
- release_task: z6.object({ task_id: UlidSchema }),
1031
- update_task: z6.object({
1070
+ claim_task: z7.object({ task_id: UlidSchema }),
1071
+ release_task: z7.object({ task_id: UlidSchema }),
1072
+ update_task: z7.object({
1032
1073
  task_id: UlidSchema,
1033
1074
  /** Move the task back to this earlier stage. */
1034
1075
  stage: StageIdSchema.optional(),
1035
- status: z6.enum(["abandoned"]).optional(),
1076
+ status: z7.enum(["abandoned"]).optional(),
1036
1077
  /** Posted to the task's thread as the caller, marked with the step when the task moved. */
1037
- note: z6.string().min(1).optional(),
1038
- blocked_by: z6.array(UlidSchema).optional(),
1078
+ note: z7.string().min(1).optional(),
1079
+ blocked_by: z7.array(UlidSchema).optional(),
1039
1080
  /**
1040
1081
  * The pull request a `ghpr` task lands through, on its project's repository, with the merge
1041
1082
  * commit's subject and body; null unlinks it.
1042
1083
  */
1043
- pull_request: z6.object({
1084
+ pull_request: z7.object({
1044
1085
  url: PullRequestUrlSchema,
1045
1086
  merge_subject: MergeSubjectSchema.optional(),
1046
- merge_body: z6.string().max(2e4).optional()
1087
+ merge_body: z7.string().max(2e4).optional()
1047
1088
  }).nullable().optional()
1048
1089
  }),
1049
- get_task: z6.object({ task_id: UlidSchema }),
1050
- subscribe: z6.object({ channel: ChannelRefSchema }),
1051
- unsubscribe: z6.object({ channel: ChannelRefSchema }),
1052
- propose: z6.object({
1090
+ get_task: z7.object({ task_id: UlidSchema }),
1091
+ subscribe: z7.object({ channel: ChannelRefSchema }),
1092
+ unsubscribe: z7.object({ channel: ChannelRefSchema }),
1093
+ propose: z7.object({
1053
1094
  kind: ProposalKindSchema,
1054
- charter: z6.record(z6.string(), z6.unknown()),
1055
- rationale: z6.string().default("")
1095
+ charter: z7.record(z7.string(), z7.unknown()),
1096
+ rationale: z7.string().default("")
1056
1097
  }),
1057
- approve: z6.object({ proposal_id: UlidSchema, reason: z6.string().optional() }),
1058
- reject: z6.object({ proposal_id: UlidSchema, reason: z6.string().min(1) }),
1059
- create_project: z6.object({
1098
+ approve: z7.object({ proposal_id: UlidSchema, reason: z7.string().optional() }),
1099
+ reject: z7.object({ proposal_id: UlidSchema, reason: z7.string().min(1) }),
1100
+ create_project: z7.object({
1060
1101
  slug: NameSchema,
1061
- name: z6.string().min(1).optional(),
1062
- repo: z6.string().min(1).nullable().default(null),
1102
+ name: z7.string().min(1).optional(),
1103
+ repo: z7.string().min(1).nullable().default(null),
1063
1104
  default_branch: DefaultBranchSchema.default("main"),
1064
1105
  on_done: CompletionEffectSchema.optional()
1065
1106
  }),
1066
- join_project: z6.object({ project: NameSchema, agent: NameSchema.optional() }),
1067
- leave_project: z6.object({ project: NameSchema, agent: NameSchema.optional() }),
1068
- write_knowledge: z6.object({
1107
+ join_project: z7.object({ project: NameSchema, agent: NameSchema.optional() }),
1108
+ leave_project: z7.object({ project: NameSchema, agent: NameSchema.optional() }),
1109
+ write_knowledge: z7.object({
1069
1110
  /** A project you belong to, or null for society knowledge, which the steward and the user curate. */
1070
1111
  project: NameSchema.nullable().default(null),
1071
1112
  topic: NameSchema,
1072
- body: z6.string().min(1),
1113
+ body: z7.string().min(1),
1073
1114
  /** The `revision` in the frontmatter of the topic you read, 0 when it names none or for a new topic. */
1074
- revision: z6.number().int().min(0)
1115
+ revision: z7.number().int().min(0)
1075
1116
  }),
1076
- remove_knowledge: z6.object({
1117
+ remove_knowledge: z7.object({
1077
1118
  /** As for write_knowledge: a project you belong to, or null for society knowledge. */
1078
1119
  project: NameSchema.nullable().default(null),
1079
1120
  topic: NameSchema
1080
1121
  }),
1081
- plan_task: z6.object({
1122
+ plan_task: z7.object({
1082
1123
  task_id: UlidSchema,
1083
- stages: z6.array(PlanEditStageSchema),
1124
+ stages: z7.array(PlanEditStageSchema),
1084
1125
  on_done: CompletionEffectSchema.optional()
1085
1126
  }),
1086
1127
  /** The note is posted to the task's thread as the caller, marked with the step. */
1087
- advance_task: z6.object({ task_id: UlidSchema, note: z6.string().min(1).optional() }),
1088
- configure_project: z6.object({
1128
+ advance_task: z7.object({ task_id: UlidSchema, note: z7.string().min(1).optional() }),
1129
+ configure_project: z7.object({
1089
1130
  project: NameSchema,
1090
1131
  on_done: CompletionEffectSchema.optional(),
1091
1132
  /** A new display name; the slug, which everything refers to the project by, never changes. */
1092
- name: z6.string().trim().min(1).max(120).optional(),
1133
+ name: z7.string().trim().min(1).max(120).optional(),
1093
1134
  /** The branch tasks start from and land on from now; tasks in play keep their branches. */
1094
1135
  default_branch: DefaultBranchSchema.optional()
1095
1136
  }),
1096
- archive_project: z6.object({ project: NameSchema, reason: z6.string().min(1) }),
1097
- create_channel: z6.object({
1137
+ archive_project: z7.object({ project: NameSchema, reason: z7.string().min(1) }),
1138
+ create_channel: z7.object({
1098
1139
  /** A project, or null for a channel of the society. */
1099
1140
  project: NameSchema.nullable().default(null),
1100
1141
  name: NameSchema,
1101
- purpose: z6.string().min(1)
1142
+ purpose: z7.string().min(1)
1102
1143
  }),
1103
- archive_channel: z6.object({ channel: ChannelRefSchema, reason: z6.string().min(1) }),
1104
- update_dashboard: z6.object({
1144
+ archive_channel: z7.object({ channel: ChannelRefSchema, reason: z7.string().min(1) }),
1145
+ update_dashboard: z7.object({
1105
1146
  project: NameSchema,
1106
1147
  /** The whole dashboard as markdown; the board keeps its frontmatter. */
1107
- body: z6.string().min(1),
1148
+ body: z7.string().min(1),
1108
1149
  /** The `revision` in the frontmatter of the dashboard you read, 0 when it names none. */
1109
- revision: z6.number().int().min(0)
1150
+ revision: z7.number().int().min(0)
1110
1151
  }),
1111
- create_cron: z6.object({
1152
+ create_cron: z7.object({
1112
1153
  title: CronTitleSchema,
1113
1154
  /** What to do when it fires; quoted in the prompt of every turn it starts. */
1114
1155
  note: CronNoteSchema,
@@ -1127,10 +1168,10 @@ var VerbInputs = {
1127
1168
  /** An open channel of that place other than general, whose conversation it fires in. */
1128
1169
  channel: NameSchema.optional()
1129
1170
  }),
1130
- update_cron: z6.object({
1171
+ update_cron: z7.object({
1131
1172
  cron_id: UlidSchema,
1132
1173
  /** Pause it, or resume it, which starts its schedule afresh from now. */
1133
- paused: z6.boolean().optional(),
1174
+ paused: z7.boolean().optional(),
1134
1175
  title: CronTitleSchema.optional(),
1135
1176
  note: CronNoteSchema.optional(),
1136
1177
  /** A new expression, or `at` for one time; either starts the schedule afresh. */
@@ -1139,12 +1180,16 @@ var VerbInputs = {
1139
1180
  timezone: TimeZoneSchema.nullable().optional(),
1140
1181
  at: MomentSchema.optional()
1141
1182
  }),
1142
- remove_cron: z6.object({ cron_id: UlidSchema, reason: z6.string().trim().min(1) }),
1143
- remove_skill: z6.object({ name: NameSchema, reason: z6.string().trim().min(1) })
1183
+ remove_cron: z7.object({ cron_id: UlidSchema, reason: z7.string().trim().min(1) }),
1184
+ remove_skill: z7.object({ name: NameSchema, reason: z7.string().trim().min(1) }),
1185
+ upload_image: z7.object({
1186
+ /** The image file on the machine your turn runs on: absolute, or relative to your working directory. */
1187
+ path: ImagePathSchema
1188
+ })
1144
1189
  };
1145
1190
 
1146
1191
  // packages/shared/dist/events.js
1147
- import { z as z7 } from "zod";
1192
+ import { z as z8 } from "zod";
1148
1193
  var BOARD_EVENT_TYPES = [
1149
1194
  "society.initialized",
1150
1195
  "project.added",
@@ -1208,21 +1253,22 @@ var BOARD_EVENT_TYPES = [
1208
1253
  "cron.updated",
1209
1254
  "cron.fired",
1210
1255
  "cron.skipped",
1211
- "cron.ended"
1256
+ "cron.ended",
1257
+ "image.uploaded"
1212
1258
  ];
1213
- var BoardEventTypeSchema = z7.enum(BOARD_EVENT_TYPES);
1214
- var BoardEventSchema = z7.object({
1259
+ var BoardEventTypeSchema = z8.enum(BOARD_EVENT_TYPES);
1260
+ var BoardEventSchema = z8.object({
1215
1261
  id: UlidSchema,
1216
1262
  ts: IsoDateTimeSchema,
1217
1263
  type: BoardEventTypeSchema,
1218
1264
  actor: NameSchema,
1219
- payload: z7.record(z7.string(), z7.unknown())
1265
+ payload: z8.record(z8.string(), z8.unknown())
1220
1266
  });
1221
- var UsageSchema = z7.object({
1222
- inputTokens: z7.number().int().nonnegative(),
1223
- outputTokens: z7.number().int().nonnegative(),
1224
- cacheReadTokens: z7.number().int().nonnegative().default(0),
1225
- cacheWriteTokens: z7.number().int().nonnegative().default(0)
1267
+ var UsageSchema = z8.object({
1268
+ inputTokens: z8.number().int().nonnegative(),
1269
+ outputTokens: z8.number().int().nonnegative(),
1270
+ cacheReadTokens: z8.number().int().nonnegative().default(0),
1271
+ cacheWriteTokens: z8.number().int().nonnegative().default(0)
1226
1272
  });
1227
1273
  function addUsage(a, b) {
1228
1274
  return {
@@ -1232,14 +1278,14 @@ function addUsage(a, b) {
1232
1278
  cacheWriteTokens: a.cacheWriteTokens + b.cacheWriteTokens
1233
1279
  };
1234
1280
  }
1235
- var TurnStatusSchema = z7.object({
1236
- summary: z7.string().min(1),
1237
- claimsHeld: z7.array(UlidSchema).default([]),
1238
- blockedOn: z7.array(z7.string()).default([]),
1239
- needsUserDecision: z7.boolean().default(false),
1240
- memoryUpdated: z7.boolean().default(false)
1241
- });
1242
- var TurnExitReasonSchema = z7.enum([
1281
+ var TurnStatusSchema = z8.object({
1282
+ summary: z8.string().min(1),
1283
+ claimsHeld: z8.array(UlidSchema).default([]),
1284
+ blockedOn: z8.array(z8.string()).default([]),
1285
+ needsUserDecision: z8.boolean().default(false),
1286
+ memoryUpdated: z8.boolean().default(false)
1287
+ });
1288
+ var TurnExitReasonSchema = z8.enum([
1243
1289
  "completed",
1244
1290
  "timeout",
1245
1291
  "error",
@@ -1247,50 +1293,50 @@ var TurnExitReasonSchema = z7.enum([
1247
1293
  "blocked",
1248
1294
  "stopped"
1249
1295
  ]);
1250
- var AgentEventSchema = z7.discriminatedUnion("type", [
1251
- z7.object({
1252
- type: z7.literal("turn_started"),
1296
+ var AgentEventSchema = z8.discriminatedUnion("type", [
1297
+ z8.object({
1298
+ type: z8.literal("turn_started"),
1253
1299
  agent: NameSchema,
1254
- session: z7.string(),
1300
+ session: z8.string(),
1255
1301
  runner: NameSchema,
1256
1302
  /** The model the CLI reports running, when it reports one. */
1257
- model: z7.string().optional()
1303
+ model: z8.string().optional()
1258
1304
  }),
1259
1305
  /**
1260
1306
  * The CLI took a steer into the running turn. Adapters name the steer; the server adds the
1261
1307
  * messages it delivered and the text the CLI was given.
1262
1308
  */
1263
- z7.object({
1264
- type: z7.literal("steered"),
1265
- steer: z7.string().min(1),
1266
- messages: z7.array(UlidSchema).optional(),
1267
- text: z7.string().optional()
1309
+ z8.object({
1310
+ type: z8.literal("steered"),
1311
+ steer: z8.string().min(1),
1312
+ messages: z8.array(UlidSchema).optional(),
1313
+ text: z8.string().optional()
1268
1314
  }),
1269
- z7.object({ type: z7.literal("text"), delta: z7.string() }),
1270
- z7.object({ type: z7.literal("tool_call"), name: z7.string(), input: z7.unknown() }),
1271
- z7.object({
1272
- type: z7.literal("tool_result"),
1273
- name: z7.string(),
1274
- ok: z7.boolean(),
1315
+ z8.object({ type: z8.literal("text"), delta: z8.string() }),
1316
+ z8.object({ type: z8.literal("tool_call"), name: z8.string(), input: z8.unknown() }),
1317
+ z8.object({
1318
+ type: z8.literal("tool_result"),
1319
+ name: z8.string(),
1320
+ ok: z8.boolean(),
1275
1321
  /** What the tool returned, cut to `OUTPUT_LIMIT` characters by `capOutput`. */
1276
- output: z7.string().optional()
1322
+ output: z8.string().optional()
1277
1323
  }),
1278
- z7.object({ type: z7.literal("approval_requested"), kind: z7.string(), detail: z7.unknown() }),
1279
- z7.object({
1280
- type: z7.literal("turn_completed"),
1324
+ z8.object({ type: z8.literal("approval_requested"), kind: z8.string(), detail: z8.unknown() }),
1325
+ z8.object({
1326
+ type: z8.literal("turn_completed"),
1281
1327
  usage: UsageSchema,
1282
- costUsd: z7.number().nonnegative(),
1328
+ costUsd: z8.number().nonnegative(),
1283
1329
  status: TurnStatusSchema.nullable(),
1284
1330
  exitReason: TurnExitReasonSchema
1285
1331
  }),
1286
- z7.object({ type: z7.literal("error"), message: z7.string() })
1332
+ z8.object({ type: z8.literal("error"), message: z8.string() })
1287
1333
  ]);
1288
- var TranscriptEntrySchema = z7.object({
1334
+ var TranscriptEntrySchema = z8.object({
1289
1335
  ts: IsoDateTimeSchema,
1290
1336
  event: AgentEventSchema
1291
1337
  });
1292
- var LiveTurnEventSchema = z7.object({
1293
- seq: z7.number().int().positive(),
1338
+ var LiveTurnEventSchema = z8.object({
1339
+ seq: z8.number().int().positive(),
1294
1340
  ts: IsoDateTimeSchema,
1295
1341
  agent: NameSchema,
1296
1342
  project: NameSchema,
@@ -1302,105 +1348,107 @@ var LiveTurnEventSchema = z7.object({
1302
1348
  });
1303
1349
 
1304
1350
  // packages/shared/dist/turns.js
1305
- import { z as z9 } from "zod";
1351
+ import { z as z10 } from "zod";
1306
1352
 
1307
1353
  // packages/shared/dist/runner.js
1308
- import { z as z8 } from "zod";
1354
+ import { z as z9 } from "zod";
1309
1355
  var HOME_SCRATCH = "scratch";
1310
1356
  var HOME_FILE_LIMIT_BYTES = 8 * 1024 * 1024;
1311
- var RunnerHelloSchema = z8.object({
1312
- protocol: z8.number().int().positive(),
1313
- version: z8.string().min(1),
1357
+ var RunnerHelloSchema = z9.object({
1358
+ protocol: z9.number().int().positive(),
1359
+ version: z9.string().min(1),
1314
1360
  os: RunnerOsSchema,
1315
- clis: z8.array(CliKindSchema),
1361
+ clis: z9.array(CliKindSchema),
1316
1362
  /** The CLIs whose adapter can keep a session warm between turns. */
1317
- residentClis: z8.array(CliKindSchema).default([]),
1363
+ residentClis: z9.array(CliKindSchema).default([]),
1318
1364
  /** The CLIs whose adapter can take input into a running turn; the server steers only these. */
1319
- steerableClis: z8.array(CliKindSchema).default([]),
1365
+ steerableClis: z9.array(CliKindSchema).default([]),
1320
1366
  /** The CLIs whose adapter can stop a running turn; the server stops only these. */
1321
- stoppableClis: z8.array(CliKindSchema).default([]),
1367
+ stoppableClis: z9.array(CliKindSchema).default([]),
1322
1368
  /** Whether the runner answers file reads on its projects' branches; one from before never does. */
1323
- branchReads: z8.boolean().default(false),
1369
+ branchReads: z9.boolean().default(false),
1324
1370
  /** Whether the runner lists what a branch changed; one from before never does. */
1325
- branchChanges: z8.boolean().default(false),
1371
+ branchChanges: z9.boolean().default(false),
1326
1372
  /** Whether the runner answers a read of a CLI's quota; one from before never does. */
1327
- quotaReads: z8.boolean().default(false),
1328
- capabilities: z8.array(z8.string()).default([]),
1373
+ quotaReads: z9.boolean().default(false),
1374
+ /** Whether the runner reads an image a turn running there uploads; one from before never does. */
1375
+ imageReads: z9.boolean().default(false),
1376
+ capabilities: z9.array(z9.string()).default([]),
1329
1377
  /**
1330
1378
  * What the runner's account lacks of the git identity citizens' own commits carry, checked
1331
1379
  * before each hello outside any repository; empty when it has both. Absent from a runner from
1332
1380
  * before the check, which no default fills in, so the board marks only what a runner reported.
1333
1381
  */
1334
- gitIdentityMissing: z8.array(GitIdentityPartSchema).optional(),
1382
+ gitIdentityMissing: z9.array(GitIdentityPartSchema).optional(),
1335
1383
  /** Turns the runner runs at once, or null for no limit. */
1336
- slots: z8.number().int().positive().nullable(),
1384
+ slots: z9.number().int().positive().nullable(),
1337
1385
  /** Turns the runner is still running, when it registers again; the server fails the rest of its turns. */
1338
- turns: z8.array(UlidSchema).default([])
1386
+ turns: z9.array(UlidSchema).default([])
1339
1387
  });
1340
- var RunnerWelcomeSchema = z8.object({ name: NameSchema, version: z8.string() });
1341
- var RunnerEnrollRequestSchema = z8.object({
1342
- protocol: z8.number().int().positive(),
1343
- version: z8.string().min(1).max(64),
1344
- hostname: z8.string().min(1).max(253),
1388
+ var RunnerWelcomeSchema = z9.object({ name: NameSchema, version: z9.string() });
1389
+ var RunnerEnrollRequestSchema = z9.object({
1390
+ protocol: z9.number().int().positive(),
1391
+ version: z9.string().min(1).max(64),
1392
+ hostname: z9.string().min(1).max(253),
1345
1393
  os: RunnerOsSchema,
1346
- clis: z8.array(CliKindSchema).max(8),
1347
- capabilities: z8.array(z8.string().min(1).max(64)).max(32).default([])
1394
+ clis: z9.array(CliKindSchema).max(8),
1395
+ capabilities: z9.array(z9.string().min(1).max(64)).max(32).default([])
1348
1396
  });
1349
- var RunnerEnrollmentSchema = z8.object({
1350
- deviceCode: z8.string().min(1),
1351
- userCode: z8.string().min(1),
1397
+ var RunnerEnrollmentSchema = z9.object({
1398
+ deviceCode: z9.string().min(1),
1399
+ userCode: z9.string().min(1),
1352
1400
  expiresAt: IsoDateTimeSchema,
1353
- intervalMs: z8.number().int().positive()
1401
+ intervalMs: z9.number().int().positive()
1354
1402
  });
1355
- var RunnerEnrollPollSchema = z8.object({ deviceCode: z8.string().min(1) });
1356
- var RunnerEnrollStatusSchema = z8.discriminatedUnion("status", [
1357
- z8.object({ status: z8.literal("pending") }),
1358
- z8.object({ status: z8.literal("approved"), name: NameSchema, token: z8.string().min(1) }),
1359
- z8.object({ status: z8.literal("denied") })
1403
+ var RunnerEnrollPollSchema = z9.object({ deviceCode: z9.string().min(1) });
1404
+ var RunnerEnrollStatusSchema = z9.discriminatedUnion("status", [
1405
+ z9.object({ status: z9.literal("pending") }),
1406
+ z9.object({ status: z9.literal("approved"), name: NameSchema, token: z9.string().min(1) }),
1407
+ z9.object({ status: z9.literal("denied") })
1360
1408
  ]);
1361
- var PendingEnrollmentSchema = z8.object({
1362
- userCode: z8.string().min(1),
1363
- hostname: z8.string(),
1409
+ var PendingEnrollmentSchema = z9.object({
1410
+ userCode: z9.string().min(1),
1411
+ hostname: z9.string(),
1364
1412
  os: RunnerOsSchema,
1365
- clis: z8.array(CliKindSchema),
1366
- capabilities: z8.array(z8.string()),
1367
- version: z8.string(),
1413
+ clis: z9.array(CliKindSchema),
1414
+ capabilities: z9.array(z9.string()),
1415
+ version: z9.string(),
1368
1416
  requestedAt: IsoDateTimeSchema,
1369
1417
  expiresAt: IsoDateTimeSchema
1370
1418
  });
1371
- var ProjectRepoSchema = z8.object({
1419
+ var ProjectRepoSchema = z9.object({
1372
1420
  slug: NameSchema,
1373
- origin: z8.string().nullable(),
1374
- defaultBranch: z8.string().min(1),
1421
+ origin: z9.string().nullable(),
1422
+ defaultBranch: z9.string().min(1),
1375
1423
  /**
1376
1424
  * The board lands finished tasks on the default branch, itself or through their pull requests,
1377
1425
  * so the runner lets nothing else move it.
1378
1426
  */
1379
- boardLands: z8.boolean()
1427
+ boardLands: z9.boolean()
1380
1428
  });
1381
- var TurnWorkspaceSchema = z8.discriminatedUnion("kind", [
1382
- z8.object({
1383
- kind: z8.literal("home"),
1429
+ var TurnWorkspaceSchema = z9.discriminatedUnion("kind", [
1430
+ z9.object({
1431
+ kind: z9.literal("home"),
1384
1432
  thread: UlidSchema.optional(),
1385
1433
  channel: NameSchema.optional()
1386
1434
  }),
1387
- z8.object({
1388
- kind: z8.literal("project"),
1435
+ z9.object({
1436
+ kind: z9.literal("project"),
1389
1437
  repo: ProjectRepoSchema,
1390
- branches: z8.array(z8.string().min(1)),
1438
+ branches: z9.array(z9.string().min(1)),
1391
1439
  thread: UlidSchema.optional(),
1392
1440
  channel: NameSchema.optional()
1393
1441
  }),
1394
- z8.object({ kind: z8.literal("task"), repo: ProjectRepoSchema, taskId: UlidSchema })
1442
+ z9.object({ kind: z9.literal("task"), repo: ProjectRepoSchema, taskId: UlidSchema })
1395
1443
  ]);
1396
- var TurnJobSchema = z8.object({
1444
+ var TurnJobSchema = z9.object({
1397
1445
  turnId: UlidSchema,
1398
1446
  agent: NameSchema,
1399
1447
  role: NameSchema,
1400
1448
  cli: CliKindSchema,
1401
- model: z8.string().optional(),
1449
+ model: z9.string().optional(),
1402
1450
  /** The reasoning effort set on the agent; absent for the model's own default. */
1403
- effort: z8.string().optional(),
1451
+ effort: z9.string().optional(),
1404
1452
  /** A project slug, or the society scope. */
1405
1453
  scope: NameSchema,
1406
1454
  /** The thread whose conversation the turn is in; absent for the home conversation. */
@@ -1411,130 +1459,130 @@ var TurnJobSchema = z8.object({
1411
1459
  * The session to resume, or null to start one: the CLI's adapter picks a fresh session's id, and
1412
1460
  * the outcome reports it.
1413
1461
  */
1414
- session: z8.string().min(1).nullable(),
1462
+ session: z9.string().min(1).nullable(),
1415
1463
  /** The running total the session reported after its last turn, which a resumed session starts from. */
1416
- costSoFarUsd: z8.number().nonnegative(),
1464
+ costSoFarUsd: z9.number().nonnegative(),
1417
1465
  /** The rendered charter, norms, memory core, and skills index, with `PATH_TOKENS` for places. */
1418
- instructions: z8.string(),
1419
- prompt: z8.string(),
1420
- mcp: z8.object({ url: z8.string().min(1), token: z8.string().min(1) }),
1421
- limits: z8.object({
1422
- timeoutMs: z8.number().int().positive().nullable(),
1423
- maxTurns: z8.number().int().positive().nullable()
1466
+ instructions: z9.string(),
1467
+ prompt: z9.string(),
1468
+ mcp: z9.object({ url: z9.string().min(1), token: z9.string().min(1) }),
1469
+ limits: z9.object({
1470
+ timeoutMs: z9.number().int().positive().nullable(),
1471
+ maxTurns: z9.number().int().positive().nullable()
1424
1472
  }),
1425
1473
  /** Present when the runner keeps the conversation's session warm between turns, under `key`. */
1426
- resident: z8.object({ key: z8.string().min(1), idleMs: z8.number().int().positive() }).optional(),
1474
+ resident: z9.object({ key: z9.string().min(1), idleMs: z9.number().int().positive() }).optional(),
1427
1475
  workspace: TurnWorkspaceSchema
1428
1476
  });
1429
- var TurnWorkSchema = z8.object({ branch: z8.string().min(1), head: z8.string().min(1) });
1430
- var TurnEventsSchema = z8.object({ entries: z8.array(TranscriptEntrySchema) });
1431
- var TurnOutcomeSchema = z8.object({
1477
+ var TurnWorkSchema = z9.object({ branch: z9.string().min(1), head: z9.string().min(1) });
1478
+ var TurnEventsSchema = z9.object({ entries: z9.array(TranscriptEntrySchema) });
1479
+ var TurnOutcomeSchema = z9.object({
1432
1480
  exitReason: TurnExitReasonSchema,
1433
1481
  status: TurnStatusSchema.nullable(),
1434
- error: z8.string().nullable(),
1482
+ error: z9.string().nullable(),
1435
1483
  usage: UsageSchema,
1436
- costUsd: z8.number().nonnegative(),
1484
+ costUsd: z9.number().nonnegative(),
1437
1485
  /** The session's running total after this turn, for CLIs that report one. */
1438
- sessionCostUsd: z8.number().nonnegative().optional(),
1486
+ sessionCostUsd: z9.number().nonnegative().optional(),
1439
1487
  /** The session the CLI used, which differs from the job's for CLIs that assign their own ids. */
1440
- session: z8.string().min(1),
1488
+ session: z9.string().min(1),
1441
1489
  /** The model the CLI reported, when it reported one. */
1442
- model: z8.string().nullable(),
1490
+ model: z9.string().nullable(),
1443
1491
  work: TurnWorkSchema.nullable(),
1444
1492
  /**
1445
1493
  * Whether the turn's own workspace, a thread's, a channel's, or a task's, holds work on no
1446
1494
  * branch after the hand-back: uncommitted changes, or commits no branch contains.
1447
1495
  */
1448
- leftovers: z8.boolean().default(false),
1496
+ leftovers: z9.boolean().default(false),
1449
1497
  /**
1450
1498
  * The CLI's plan quota as the turn's stream last reported it, when it reported any; a runner from
1451
1499
  * before never sends it.
1452
1500
  */
1453
1501
  quota: CliQuotaSchema.optional()
1454
1502
  });
1455
- var TurnAckSchema = z8.object({ dropWorkspace: z8.boolean() });
1456
- var LandRequestSchema = z8.object({
1503
+ var TurnAckSchema = z9.object({ dropWorkspace: z9.boolean() });
1504
+ var LandRequestSchema = z9.object({
1457
1505
  repo: ProjectRepoSchema,
1458
- branch: z8.string().min(1),
1506
+ branch: z9.string().min(1),
1459
1507
  /**
1460
1508
  * For a `ghpr` task, the pull request to merge in place of the branch, which must hold the
1461
1509
  * branch's files, and the merge commit's subject and body, the pull request's title and an
1462
1510
  * empty body when left out.
1463
1511
  */
1464
- pullRequest: z8.object({
1465
- url: z8.string().min(1),
1466
- subject: z8.string().min(1).optional(),
1467
- body: z8.string().optional()
1512
+ pullRequest: z9.object({
1513
+ url: z9.string().min(1),
1514
+ subject: z9.string().min(1).optional(),
1515
+ body: z9.string().optional()
1468
1516
  }).optional()
1469
1517
  });
1470
- var CloseRequestSchema = z8.object({
1518
+ var CloseRequestSchema = z9.object({
1471
1519
  repo: ProjectRepoSchema,
1472
- url: z8.string().min(1),
1473
- comment: z8.string().min(1)
1520
+ url: z9.string().min(1),
1521
+ comment: z9.string().min(1)
1474
1522
  });
1475
- var MergeOutcomeSchema = z8.object({ ok: z8.boolean(), detail: z8.string() });
1476
- var ModelListSchema = z8.array(ModelOptionSchema);
1523
+ var MergeOutcomeSchema = z9.object({ ok: z9.boolean(), detail: z9.string() });
1524
+ var ModelListSchema = z9.array(ModelOptionSchema);
1477
1525
  var BRANCH_FILE_LIMIT_BYTES = 8 * 1024 * 1024;
1478
- var BranchPathSchema = z8.string().max(4096).refine((value) => value === "" || value.split("/").every((segment) => segment !== "" && segment !== "." && segment !== ".." && !segment.includes("\0")), { message: "a path inside the branch, with no empty, `.`, or `..` segment" });
1479
- var BranchNameSchema = z8.string().regex(/^[A-Za-z0-9][A-Za-z0-9._/-]*$/);
1480
- var BranchReadSchema = z8.object({
1526
+ var BranchPathSchema = z9.string().max(4096).refine((value) => value === "" || value.split("/").every((segment) => segment !== "" && segment !== "." && segment !== ".." && !segment.includes("\0")), { message: "a path inside the branch, with no empty, `.`, or `..` segment" });
1527
+ var BranchNameSchema = z9.string().regex(/^[A-Za-z0-9][A-Za-z0-9._/-]*$/);
1528
+ var BranchReadSchema = z9.object({
1481
1529
  repo: ProjectRepoSchema,
1482
1530
  branch: BranchNameSchema,
1483
1531
  path: BranchPathSchema
1484
1532
  });
1485
- var BranchCommitSchema = z8.object({
1486
- id: z8.string().min(1),
1533
+ var BranchCommitSchema = z9.object({
1534
+ id: z9.string().min(1),
1487
1535
  at: IsoDateTimeSchema,
1488
- author: z8.string()
1536
+ author: z9.string()
1489
1537
  });
1490
- var BranchFileSchema = z8.discriminatedUnion("kind", [
1491
- z8.object({
1492
- kind: z8.literal("file"),
1538
+ var BranchFileSchema = z9.discriminatedUnion("kind", [
1539
+ z9.object({
1540
+ kind: z9.literal("file"),
1493
1541
  path: BranchPathSchema,
1494
1542
  commit: BranchCommitSchema,
1495
- size: z8.number().int().nonnegative(),
1496
- content: z8.string().nullable()
1543
+ size: z9.number().int().nonnegative(),
1544
+ content: z9.string().nullable()
1497
1545
  }),
1498
- z8.object({
1499
- kind: z8.literal("dir"),
1546
+ z9.object({
1547
+ kind: z9.literal("dir"),
1500
1548
  path: BranchPathSchema,
1501
1549
  commit: BranchCommitSchema,
1502
- entries: z8.array(z8.object({
1503
- name: z8.string().min(1),
1504
- kind: z8.enum(["file", "dir"]),
1505
- size: z8.number().int().nonnegative().nullable()
1550
+ entries: z9.array(z9.object({
1551
+ name: z9.string().min(1),
1552
+ kind: z9.enum(["file", "dir"]),
1553
+ size: z9.number().int().nonnegative().nullable()
1506
1554
  }))
1507
1555
  })
1508
1556
  ]);
1509
- var BranchChangesReadSchema = z8.object({
1557
+ var BranchChangesReadSchema = z9.object({
1510
1558
  repo: ProjectRepoSchema,
1511
1559
  branch: BranchNameSchema
1512
1560
  });
1513
- var BranchFileChangeSchema = z8.object({
1514
- path: z8.string().min(1),
1515
- status: z8.enum(["added", "modified", "deleted"]),
1561
+ var BranchFileChangeSchema = z9.object({
1562
+ path: z9.string().min(1),
1563
+ status: z9.enum(["added", "modified", "deleted"]),
1516
1564
  /** Lines added and removed, or null for a binary file. */
1517
- added: z8.number().int().nonnegative().nullable(),
1518
- removed: z8.number().int().nonnegative().nullable(),
1565
+ added: z9.number().int().nonnegative().nullable(),
1566
+ removed: z9.number().int().nonnegative().nullable(),
1519
1567
  /** Absent when the file changed only through a merge of another branch. */
1520
- lastChange: z8.object({ author: z8.string(), at: IsoDateTimeSchema }).optional()
1568
+ lastChange: z9.object({ author: z9.string(), at: IsoDateTimeSchema }).optional()
1521
1569
  });
1522
- var BranchChangesSchema = z8.object({
1570
+ var BranchChangesSchema = z9.object({
1523
1571
  head: BranchCommitSchema,
1524
- files: z8.array(BranchFileChangeSchema),
1525
- total: z8.number().int().nonnegative()
1572
+ files: z9.array(BranchFileChangeSchema),
1573
+ total: z9.number().int().nonnegative()
1526
1574
  });
1527
- var BranchDiffReadSchema = z8.object({
1575
+ var BranchDiffReadSchema = z9.object({
1528
1576
  repo: ProjectRepoSchema,
1529
1577
  branch: BranchNameSchema,
1530
1578
  path: BranchPathSchema.min(1)
1531
1579
  });
1532
- var BranchFileDiffSchema = z8.object({
1580
+ var BranchFileDiffSchema = z9.object({
1533
1581
  head: BranchCommitSchema,
1534
1582
  path: BranchPathSchema,
1535
1583
  status: BranchFileChangeSchema.shape.status,
1536
- patch: z8.string().nullable(),
1537
- truncated: z8.boolean()
1584
+ patch: z9.string().nullable(),
1585
+ truncated: z9.boolean()
1538
1586
  });
1539
1587
  function patchHunks(patch, limit) {
1540
1588
  if (/^Binary files .* differ$/m.test(patch)) {
@@ -1548,69 +1596,88 @@ function patchHunks(patch, limit) {
1548
1596
  const cut = hunks.lastIndexOf("\n", limit);
1549
1597
  return { patch: hunks.slice(0, cut === -1 ? limit : cut), truncated: true };
1550
1598
  }
1551
- var WorkspaceConversationSchema = z8.discriminatedUnion("kind", [
1552
- z8.object({ kind: z8.literal("thread"), id: UlidSchema }),
1553
- z8.object({ kind: z8.literal("channel"), scope: NameSchema, name: NameSchema })
1599
+ var TurnImageReadSchema = z9.object({
1600
+ turnId: UlidSchema,
1601
+ path: ImagePathSchema
1602
+ });
1603
+ var ImageRefusalSchema = z9.enum(["missing", "outside", "not_image", "too_big"]);
1604
+ var TurnImageSchema = z9.discriminatedUnion("kind", [
1605
+ z9.object({
1606
+ kind: z9.literal("image"),
1607
+ type: ImageTypeSchema,
1608
+ size: z9.number().int().positive(),
1609
+ content: z9.string()
1610
+ }),
1611
+ z9.object({ kind: z9.literal("refused"), why: ImageRefusalSchema, detail: z9.string() })
1612
+ ]);
1613
+ var WorkspaceConversationSchema = z9.discriminatedUnion("kind", [
1614
+ z9.object({ kind: z9.literal("thread"), id: UlidSchema }),
1615
+ z9.object({ kind: z9.literal("channel"), scope: NameSchema, name: NameSchema })
1554
1616
  ]);
1555
- var HeldWorkspaceSchema = z8.object({
1617
+ var HeldWorkspaceSchema = z9.object({
1556
1618
  agent: NameSchema,
1557
1619
  scope: NameSchema,
1558
1620
  conversation: WorkspaceConversationSchema
1559
1621
  });
1560
- var HeldWorkspacesSchema = z8.object({ workspaces: z8.array(HeldWorkspaceSchema) });
1561
- var SweepResultSchema = z8.object({ kept: z8.array(HeldWorkspaceSchema) });
1562
- var TurnSteerSchema = z8.object({ id: z8.uuid(), text: z8.string().min(1) });
1563
- var RunnerMessageSchema = z8.discriminatedUnion("type", [
1564
- z8.object({ type: z8.literal("turn"), job: TurnJobSchema }),
1565
- z8.object({ type: z8.literal("land"), request: z8.string().min(1), land: LandRequestSchema }),
1622
+ var HeldWorkspacesSchema = z9.object({ workspaces: z9.array(HeldWorkspaceSchema) });
1623
+ var SweepResultSchema = z9.object({ kept: z9.array(HeldWorkspaceSchema) });
1624
+ var TurnSteerSchema = z9.object({ id: z9.uuid(), text: z9.string().min(1) });
1625
+ var RunnerMessageSchema = z9.discriminatedUnion("type", [
1626
+ z9.object({ type: z9.literal("turn"), job: TurnJobSchema }),
1627
+ z9.object({ type: z9.literal("land"), request: z9.string().min(1), land: LandRequestSchema }),
1566
1628
  /** Answered with a `MergeOutcome`. */
1567
- z8.object({ type: z8.literal("close"), request: z8.string().min(1), close: CloseRequestSchema }),
1568
- z8.object({ type: z8.literal("models"), request: z8.string().min(1), cli: CliKindSchema }),
1629
+ z9.object({ type: z9.literal("close"), request: z9.string().min(1), close: CloseRequestSchema }),
1630
+ z9.object({ type: z9.literal("models"), request: z9.string().min(1), cli: CliKindSchema }),
1569
1631
  /**
1570
1632
  * Answered with a `CliQuota` read from the CLI without a turn, or null when its adapter cannot
1571
1633
  * read one. Sent only to runners whose hello says `quotaReads`.
1572
1634
  */
1573
- z8.object({ type: z8.literal("quota"), request: z8.string().min(1), cli: CliKindSchema }),
1635
+ z9.object({ type: z9.literal("quota"), request: z9.string().min(1), cli: CliKindSchema }),
1574
1636
  /** Answered with a `BranchFile`, or null when the branch or the path does not exist. */
1575
- z8.object({ type: z8.literal("file"), request: z8.string().min(1), read: BranchReadSchema }),
1637
+ z9.object({ type: z9.literal("file"), request: z9.string().min(1), read: BranchReadSchema }),
1576
1638
  /** Answered with `BranchChanges`, or null when the repository or the branch does not exist. */
1577
- z8.object({
1578
- type: z8.literal("changes"),
1579
- request: z8.string().min(1),
1639
+ z9.object({
1640
+ type: z9.literal("changes"),
1641
+ request: z9.string().min(1),
1580
1642
  read: BranchChangesReadSchema
1581
1643
  }),
1582
1644
  /** Answered with a `BranchFileDiff`, or null when the branch does not exist or left the path alone. */
1583
- z8.object({ type: z8.literal("diff"), request: z8.string().min(1), read: BranchDiffReadSchema }),
1645
+ z9.object({ type: z9.literal("diff"), request: z9.string().min(1), read: BranchDiffReadSchema }),
1646
+ /**
1647
+ * Answered with a `TurnImage`, or null when the turn is not running there. Sent only to runners
1648
+ * whose hello says `imageReads`.
1649
+ */
1650
+ z9.object({ type: z9.literal("image"), request: z9.string().min(1), read: TurnImageReadSchema }),
1584
1651
  /** Answered with whether the CLI accepted it; that it took it comes as a `steered` event. */
1585
- z8.object({
1586
- type: z8.literal("steer"),
1587
- request: z8.string().min(1),
1652
+ z9.object({
1653
+ type: z9.literal("steer"),
1654
+ request: z9.string().min(1),
1588
1655
  turnId: UlidSchema,
1589
1656
  steer: TurnSteerSchema
1590
1657
  }),
1591
1658
  /** Answered with whether the turn was there to stop; it ends `stopped`. */
1592
- z8.object({ type: z8.literal("stop"), request: z8.string().min(1), turnId: UlidSchema }),
1659
+ z9.object({ type: z9.literal("stop"), request: z9.string().min(1), turnId: UlidSchema }),
1593
1660
  /**
1594
1661
  * A conversation ended: the runner removes every citizen's workspace for it but those a turn
1595
1662
  * still uses, and answers with a `SweepResult` naming those it kept for holding work on no branch.
1596
1663
  */
1597
- z8.object({
1598
- type: z8.literal("sweep"),
1599
- request: z8.string().min(1),
1664
+ z9.object({
1665
+ type: z9.literal("sweep"),
1666
+ request: z9.string().min(1),
1600
1667
  conversation: WorkspaceConversationSchema
1601
1668
  })
1602
1669
  ]);
1603
- var RunnerAnswerSchema = z8.discriminatedUnion("ok", [
1604
- z8.object({ ok: z8.literal(true), value: z8.unknown() }),
1605
- z8.object({ ok: z8.literal(false), error: z8.string() })
1670
+ var RunnerAnswerSchema = z9.discriminatedUnion("ok", [
1671
+ z9.object({ ok: z9.literal(true), value: z9.unknown() }),
1672
+ z9.object({ ok: z9.literal(false), error: z9.string() })
1606
1673
  ]);
1607
- var WarmSessionsSchema = z8.object({ warm: z8.array(z8.string()) });
1608
- var FileManifestSchema = z8.object({ files: z8.record(z8.string(), z8.string()) });
1674
+ var WarmSessionsSchema = z9.object({ warm: z9.array(z9.string()) });
1675
+ var FileManifestSchema = z9.object({ files: z9.record(z9.string(), z9.string()) });
1609
1676
  function fileVersion(sha, executable) {
1610
1677
  return executable ? `${sha}+x` : sha;
1611
1678
  }
1612
- var FileReadSchema = z8.object({ paths: z8.array(z8.string()) });
1613
- var FileContentsSchema = z8.object({ files: z8.record(z8.string(), z8.string()) });
1679
+ var FileReadSchema = z9.object({ paths: z9.array(z9.string()) });
1680
+ var FileContentsSchema = z9.object({ files: z9.record(z9.string(), z9.string()) });
1614
1681
  function isSafeRelativePath(file) {
1615
1682
  if (file.length === 0 || file.startsWith("/") || file.includes("\\") || file.includes("\0")) {
1616
1683
  return false;
@@ -1619,7 +1686,7 @@ function isSafeRelativePath(file) {
1619
1686
  }
1620
1687
 
1621
1688
  // packages/shared/dist/turns.js
1622
- var TriggerKindSchema = z9.enum([
1689
+ var TriggerKindSchema = z10.enum([
1623
1690
  "mention",
1624
1691
  "stage",
1625
1692
  "task_done",
@@ -1633,11 +1700,11 @@ var TriggerKindSchema = z9.enum([
1633
1700
  "closing",
1634
1701
  "cron"
1635
1702
  ]);
1636
- var TriggerSchema = z9.object({
1703
+ var TriggerSchema = z10.object({
1637
1704
  kind: TriggerKindSchema,
1638
1705
  from: NameSchema.optional(),
1639
- fromUser: z9.boolean().default(false),
1640
- reason: z9.string().default(""),
1706
+ fromUser: z10.boolean().default(false),
1707
+ reason: z10.string().default(""),
1641
1708
  taskId: UlidSchema.optional(),
1642
1709
  messageId: UlidSchema.optional(),
1643
1710
  /** The channel the waking message was posted in. */
@@ -1645,17 +1712,17 @@ var TriggerSchema = z9.object({
1645
1712
  /** The cron that came due, for a `cron` wake. */
1646
1713
  cronId: UlidSchema.optional()
1647
1714
  });
1648
- var TurnThreadSchema = z9.object({ id: UlidSchema, task: z9.boolean() });
1649
- var TurnDispatchSchema = z9.object({
1715
+ var TurnThreadSchema = z10.object({ id: UlidSchema, task: z10.boolean() });
1716
+ var TurnDispatchSchema = z10.object({
1650
1717
  agent: NameSchema,
1651
1718
  project: NameSchema,
1652
1719
  thread: TurnThreadSchema.optional(),
1653
1720
  channel: NameSchema.optional(),
1654
1721
  trigger: TriggerSchema,
1655
- priority: z9.number().int().min(0).max(2),
1656
- onboarding: z9.boolean().default(false),
1722
+ priority: z10.number().int().min(0).max(2),
1723
+ onboarding: z10.boolean().default(false),
1657
1724
  /** Every cron that came due for this turn, whatever wake it merged into; its prompt quotes each. */
1658
- crons: z9.array(UlidSchema).optional()
1725
+ crons: z10.array(UlidSchema).optional()
1659
1726
  });
1660
1727
  function conversationPart(conversation) {
1661
1728
  return conversation.thread ?? (conversation.channel === void 0 ? void 0 : `#${conversation.channel}`);
@@ -1666,7 +1733,7 @@ function channelConversation(scope, channel) {
1666
1733
  const name = at < 0 ? channel : channel.slice(at + 1);
1667
1734
  return place === scope && name !== "general" ? name : void 0;
1668
1735
  }
1669
- var TurnRecordSchema = z9.object({
1736
+ var TurnRecordSchema = z10.object({
1670
1737
  /** Assigned by the board when the turn begins; the turn's transcript is filed under it. */
1671
1738
  id: UlidSchema.optional(),
1672
1739
  agent: NameSchema,
@@ -1677,31 +1744,31 @@ var TurnRecordSchema = z9.object({
1677
1744
  channel: NameSchema.optional(),
1678
1745
  runner: NameSchema,
1679
1746
  cli: CliKindSchema.nullable(),
1680
- session: z9.string().nullable(),
1747
+ session: z10.string().nullable(),
1681
1748
  trigger: TriggerSchema,
1682
1749
  startedAt: IsoDateTimeSchema,
1683
1750
  endedAt: IsoDateTimeSchema.nullable(),
1684
1751
  exitReason: TurnExitReasonSchema.nullable(),
1685
1752
  status: TurnStatusSchema.nullable(),
1686
- error: z9.string().nullable(),
1753
+ error: z10.string().nullable(),
1687
1754
  usage: UsageSchema.nullable(),
1688
- costUsd: z9.number().nonnegative().default(0),
1755
+ costUsd: z10.number().nonnegative().default(0),
1689
1756
  /**
1690
1757
  * The running total the CLI reported for the session after this turn, when it reports one. A
1691
1758
  * resumed session starts from it, so the next turn's own cost is measured from here.
1692
1759
  */
1693
- sessionCostUsd: z9.number().nonnegative().optional(),
1694
- toolCalls: z9.number().int().nonnegative().default(0),
1760
+ sessionCostUsd: z10.number().nonnegative().optional(),
1761
+ toolCalls: z10.number().int().nonnegative().default(0),
1695
1762
  /** The model the CLI reported for this turn, else the model configured for the agent, else null. */
1696
- model: z9.string().nullable().default(null),
1763
+ model: z10.string().nullable().default(null),
1697
1764
  /** The task branch the turn left work on, with its commit, as the runner reported it. */
1698
1765
  work: TurnWorkSchema.optional(),
1699
1766
  /** Who stopped the turn, for one that ended `stopped`. */
1700
1767
  stoppedBy: NameSchema.optional(),
1701
1768
  /** The crons whose fire started the turn, which record how it ended. */
1702
- crons: z9.array(UlidSchema).optional()
1769
+ crons: z10.array(UlidSchema).optional()
1703
1770
  });
1704
- var RunningTurnSchema = z9.object({
1771
+ var RunningTurnSchema = z10.object({
1705
1772
  turnId: UlidSchema,
1706
1773
  agent: NameSchema,
1707
1774
  scope: NameSchema,
@@ -1709,49 +1776,49 @@ var RunningTurnSchema = z9.object({
1709
1776
  channel: NameSchema.optional(),
1710
1777
  cli: CliKindSchema,
1711
1778
  askedIn: ChannelRefSchema.optional(),
1712
- steerable: z9.boolean(),
1713
- stoppable: z9.boolean()
1779
+ steerable: z10.boolean(),
1780
+ stoppable: z10.boolean()
1714
1781
  });
1715
- var SessionsFileSchema = z9.object({
1716
- claude: z9.string().optional(),
1717
- codex: z9.string().optional(),
1782
+ var SessionsFileSchema = z10.object({
1783
+ claude: z10.string().optional(),
1784
+ codex: z10.string().optional(),
1718
1785
  runner: NameSchema.optional()
1719
1786
  });
1720
- var WakeRequestSchema = z9.object({
1787
+ var WakeRequestSchema = z10.object({
1721
1788
  agent: NameSchema,
1722
1789
  project: NameSchema,
1723
- reason: z9.string().default("manual wake"),
1790
+ reason: z10.string().default("manual wake"),
1724
1791
  /** A manual wake, or a reflection turn requested ahead of the cadence. */
1725
- kind: z9.enum(["manual", "reflection"]).default("manual")
1792
+ kind: z10.enum(["manual", "reflection"]).default("manual")
1726
1793
  });
1727
- var TurnHistoryEntrySchema = z9.object({
1794
+ var TurnHistoryEntrySchema = z10.object({
1728
1795
  /** The id of the event that ended the turn. */
1729
1796
  id: UlidSchema,
1730
1797
  /** The turn's own id, when it has a transcript to open; turns before transcripts have none. */
1731
1798
  turnId: UlidSchema.optional(),
1732
1799
  ts: IsoDateTimeSchema,
1733
- outcome: z9.enum(["completed", "failed"]),
1800
+ outcome: z10.enum(["completed", "failed"]),
1734
1801
  /** A project slug, or the society scope. */
1735
1802
  project: NameSchema,
1736
1803
  /** The thread whose conversation the turn was in; absent for the home conversation. */
1737
1804
  thread: UlidSchema.optional(),
1738
1805
  /** The channel, never general, whose conversation the turn was in. */
1739
1806
  channel: NameSchema.optional(),
1740
- trigger: z9.string(),
1741
- exitReason: z9.string().nullable(),
1742
- costUsd: z9.number(),
1807
+ trigger: z10.string(),
1808
+ exitReason: z10.string().nullable(),
1809
+ costUsd: z10.number(),
1743
1810
  /** The tokens the turn used; absent for turns logged before turns recorded them. */
1744
1811
  usage: UsageSchema.optional(),
1745
- model: z9.string().nullable(),
1746
- summary: z9.string().nullable(),
1747
- error: z9.string().nullable(),
1812
+ model: z10.string().nullable(),
1813
+ summary: z10.string().nullable(),
1814
+ error: z10.string().nullable(),
1748
1815
  /** When the log recorded the turn's start; absent when the start is missing from the log. */
1749
1816
  startedAt: IsoDateTimeSchema.optional(),
1750
- toolCalls: z9.number().int().nonnegative().optional()
1817
+ toolCalls: z10.number().int().nonnegative().optional()
1751
1818
  });
1752
1819
 
1753
1820
  // packages/shared/dist/ops.js
1754
- import { z as z10 } from "zod";
1821
+ import { z as z11 } from "zod";
1755
1822
  var OPS_SIGNAL_KINDS = [
1756
1823
  "waiting_stage",
1757
1824
  "backlog",
@@ -1767,16 +1834,16 @@ var OPS_SIGNAL_KINDS = [
1767
1834
  "stuck_workspace",
1768
1835
  "cron_failing"
1769
1836
  ];
1770
- var OpsSignalKindSchema = z10.enum(OPS_SIGNAL_KINDS);
1771
- var OpsSignalSchema = z10.object({
1837
+ var OpsSignalKindSchema = z11.enum(OPS_SIGNAL_KINDS);
1838
+ var OpsSignalSchema = z11.object({
1772
1839
  kind: OpsSignalKindSchema,
1773
1840
  /** Identifies the condition, for example `backlog:demo:engineer`, so a persisting one is not logged again every pass. */
1774
- key: z10.string().min(1),
1841
+ key: z11.string().min(1),
1775
1842
  /** One line a reader can act on. */
1776
- summary: z10.string().min(1),
1843
+ summary: z11.string().min(1),
1777
1844
  /** The counter or timer value behind the signal. */
1778
- value: z10.number(),
1779
- threshold: z10.number().optional(),
1845
+ value: z11.number(),
1846
+ threshold: z11.number().optional(),
1780
1847
  project: NameSchema.optional(),
1781
1848
  agent: NameSchema.optional(),
1782
1849
  role: NameSchema.optional(),
@@ -1784,8 +1851,8 @@ var OpsSignalSchema = z10.object({
1784
1851
  });
1785
1852
 
1786
1853
  // packages/shared/dist/metrics.js
1787
- import { z as z11 } from "zod";
1788
- var MetricsWindowSchema = z11.enum(["24h", "7d", "all"]);
1854
+ import { z as z12 } from "zod";
1855
+ var MetricsWindowSchema = z12.enum(["24h", "7d", "all"]);
1789
1856
  var METRICS_WINDOW_MS = {
1790
1857
  "24h": 24 * 36e5,
1791
1858
  "7d": 7 * 24 * 36e5,
@@ -1796,9 +1863,9 @@ function isBoardAction(tool) {
1796
1863
  const verb = /^mcp__board__(.+)$/.exec(tool)?.[1];
1797
1864
  return verb !== void 0 && !READ_VERBS.some((read2) => read2 === verb);
1798
1865
  }
1799
- var CountSchema = z11.number().int().nonnegative();
1800
- var MsSchema = z11.number().nonnegative();
1801
- var MetricsSchema = z11.object({
1866
+ var CountSchema = z12.number().int().nonnegative();
1867
+ var MsSchema = z12.number().nonnegative();
1868
+ var MetricsSchema = z12.object({
1802
1869
  window: MetricsWindowSchema,
1803
1870
  since: IsoDateTimeSchema.nullable(),
1804
1871
  until: IsoDateTimeSchema,
@@ -1806,12 +1873,12 @@ var MetricsSchema = z11.object({
1806
1873
  * Finished turns that changed nothing on the board. Reflections are left out, since they write
1807
1874
  * memory, not the board; turns without a transcript are counted apart, their actions unknown.
1808
1875
  */
1809
- idle: z11.object({
1876
+ idle: z12.object({
1810
1877
  turns: CountSchema,
1811
1878
  idle: CountSchema,
1812
1879
  unknown: CountSchema,
1813
- byTrigger: z11.array(z11.object({ trigger: z11.string(), turns: CountSchema, idle: CountSchema })),
1814
- byAgent: z11.array(z11.object({
1880
+ byTrigger: z12.array(z12.object({ trigger: z12.string(), turns: CountSchema, idle: CountSchema })),
1881
+ byAgent: z12.array(z12.object({
1815
1882
  agent: NameSchema,
1816
1883
  role: NameSchema.nullable(),
1817
1884
  turns: CountSchema,
@@ -1819,33 +1886,33 @@ var MetricsSchema = z11.object({
1819
1886
  }))
1820
1887
  }),
1821
1888
  /** Work sent back to an earlier stage: over the tasks finished in the window, and by where. */
1822
- sentBack: z11.object({
1889
+ sentBack: z12.object({
1823
1890
  finished: CountSchema,
1824
1891
  sendBacks: CountSchema,
1825
1892
  tasksSentBack: CountSchema,
1826
- byStage: z11.array(z11.object({ project: NameSchema, stage: z11.string(), count: CountSchema })),
1827
- bySender: z11.array(z11.object({ agent: NameSchema, count: CountSchema }))
1893
+ byStage: z12.array(z12.object({ project: NameSchema, stage: z12.string(), count: CountSchema })),
1894
+ bySender: z12.array(z12.object({ agent: NameSchema, count: CountSchema }))
1828
1895
  }),
1829
1896
  /** Posts in the threads of the tasks finished in the window, the board's own notices left out. */
1830
- messages: z11.object({
1897
+ messages: z12.object({
1831
1898
  finished: CountSchema,
1832
1899
  messages: CountSchema,
1833
- byProject: z11.array(z11.object({ project: NameSchema, finished: CountSchema, messages: CountSchema })),
1834
- busiest: z11.array(z11.object({
1900
+ byProject: z12.array(z12.object({ project: NameSchema, finished: CountSchema, messages: CountSchema })),
1901
+ busiest: z12.array(z12.object({
1835
1902
  taskId: UlidSchema,
1836
- title: z11.string(),
1903
+ title: z12.string(),
1837
1904
  project: NameSchema,
1838
1905
  messages: CountSchema
1839
1906
  }))
1840
1907
  }),
1841
1908
  /** Time from a mention to the start of the turn it woke, in the conversation it was made in. */
1842
- latency: z11.object({
1909
+ latency: z12.object({
1843
1910
  mentions: CountSchema,
1844
1911
  /** Mentions no turn has followed yet. */
1845
1912
  unanswered: CountSchema,
1846
1913
  medianMs: MsSchema.nullable(),
1847
1914
  slowestMs: MsSchema.nullable(),
1848
- byAgent: z11.array(z11.object({
1915
+ byAgent: z12.array(z12.object({
1849
1916
  agent: NameSchema,
1850
1917
  mentions: CountSchema,
1851
1918
  medianMs: MsSchema,
@@ -1853,93 +1920,93 @@ var MetricsSchema = z11.object({
1853
1920
  }))
1854
1921
  }),
1855
1922
  /** The user's decisions: proposals decided, questions answered, and stages passed or sent back. */
1856
- decisions: z11.object({
1923
+ decisions: z12.object({
1857
1924
  total: CountSchema,
1858
- byDay: z11.array(z11.object({
1859
- day: z11.string(),
1925
+ byDay: z12.array(z12.object({
1926
+ day: z12.string(),
1860
1927
  proposals: CountSchema,
1861
1928
  answers: CountSchema,
1862
1929
  stages: CountSchema
1863
1930
  }))
1864
1931
  }),
1865
1932
  /** Tasks that needed a capability no connected runner offered, and whether they still do. */
1866
- blocked: z11.array(z11.object({
1933
+ blocked: z12.array(z12.object({
1867
1934
  taskId: UlidSchema,
1868
- title: z11.string().nullable(),
1935
+ title: z12.string().nullable(),
1869
1936
  project: NameSchema.nullable(),
1870
- summary: z11.string(),
1937
+ summary: z12.string(),
1871
1938
  firstAt: IsoDateTimeSchema,
1872
1939
  lastAt: IsoDateTimeSchema,
1873
- holds: z11.boolean()
1940
+ holds: z12.boolean()
1874
1941
  }))
1875
1942
  });
1876
- var CitizenTokensSchema = z11.object({
1943
+ var CitizenTokensSchema = z12.object({
1877
1944
  agent: NameSchema,
1878
1945
  turns: CountSchema,
1879
1946
  withUsage: CountSchema,
1880
1947
  usage: UsageSchema.nullable()
1881
1948
  });
1882
- var TokenUseSchema = z11.object({
1949
+ var TokenUseSchema = z12.object({
1883
1950
  window: MetricsWindowSchema,
1884
1951
  since: IsoDateTimeSchema.nullable(),
1885
1952
  until: IsoDateTimeSchema,
1886
- citizens: z11.array(CitizenTokensSchema)
1953
+ citizens: z12.array(CitizenTokensSchema)
1887
1954
  });
1888
1955
 
1889
1956
  // packages/shared/dist/config.js
1890
- import { z as z12 } from "zod";
1891
- var LogLevelSchema = z12.enum(["trace", "debug", "info", "warn", "error", "fatal"]);
1892
- var GithubSignInSchema = z12.object({
1893
- clientId: z12.string().min(1),
1894
- clientSecret: z12.string().min(1),
1957
+ import { z as z13 } from "zod";
1958
+ var LogLevelSchema = z13.enum(["trace", "debug", "info", "warn", "error", "fatal"]);
1959
+ var GithubSignInSchema = z13.object({
1960
+ clientId: z13.string().min(1),
1961
+ clientSecret: z13.string().min(1),
1895
1962
  /** Logins, lowercased; GitHub logins are case-insensitive. */
1896
- users: z12.array(z12.string().min(1)).min(1)
1963
+ users: z13.array(z13.string().min(1)).min(1)
1897
1964
  });
1898
- var ServerConfigSchema = z12.object({
1899
- dataDir: z12.string().min(1),
1900
- host: z12.string().min(1),
1901
- port: z12.number().int().positive().max(65535),
1965
+ var ServerConfigSchema = z13.object({
1966
+ dataDir: z13.string().min(1),
1967
+ host: z13.string().min(1),
1968
+ port: z13.number().int().positive().max(65535),
1902
1969
  /**
1903
1970
  * An address every runner's agents reach this server at, for example https://board.example, or
1904
1971
  * null for each runner to use the address it reaches the server at itself.
1905
1972
  */
1906
- publicUrl: z12.string().min(1).nullable(),
1973
+ publicUrl: z13.string().min(1).nullable(),
1907
1974
  logLevel: LogLevelSchema,
1908
1975
  /** Turns running at once across every runner, or null for no limit beyond each runner's own. */
1909
- concurrency: z12.number().int().positive().nullable(),
1976
+ concurrency: z13.number().int().positive().nullable(),
1910
1977
  /** How long one turn may run before it is stopped, or null for no limit. */
1911
- turnTimeoutMs: z12.number().int().positive().nullable(),
1978
+ turnTimeoutMs: z13.number().int().positive().nullable(),
1912
1979
  /** Rounds of tool calls one Claude turn may take, or null for no limit. */
1913
- toolRounds: z12.number().int().positive().nullable(),
1980
+ toolRounds: z13.number().int().positive().nullable(),
1914
1981
  /** How long a resident session stays warm after its last turn. */
1915
- residentIdleMs: z12.number().int().positive(),
1982
+ residentIdleMs: z13.number().int().positive(),
1916
1983
  /** Signing in to the board with GitHub, or null when only a token lets anyone in. */
1917
1984
  github: GithubSignInSchema.nullable(),
1918
1985
  /**
1919
1986
  * Reverse proxies in front of the server whose X-Forwarded-For entries name the client, for the
1920
1987
  * rate limits on what anyone may ask without a token: 0 when clients connect directly.
1921
1988
  */
1922
- trustedProxies: z12.number().int().min(0).max(16)
1989
+ trustedProxies: z13.number().int().min(0).max(16)
1923
1990
  });
1924
- var RunnerConfigSchema = z12.object({
1991
+ var RunnerConfigSchema = z13.object({
1925
1992
  /** The board server, for example http://127.0.0.1:4700. */
1926
- serverUrl: z12.string().url(),
1993
+ serverUrl: z13.string().url(),
1927
1994
  /**
1928
1995
  * The runner's token, from `runner add`, or null for the one it saved when it was enrolled, or
1929
1996
  * to enroll it.
1930
1997
  */
1931
- token: z12.string().min(1).nullable(),
1998
+ token: z13.string().min(1).nullable(),
1932
1999
  /** The runner's own data directory: the board mirror, agent homes, repositories, worktrees. */
1933
- dataDir: z12.string().min(1),
2000
+ dataDir: z13.string().min(1),
1934
2001
  logLevel: LogLevelSchema,
1935
2002
  /** Turns this machine runs at once, or null for no limit. */
1936
- slots: z12.number().int().positive().nullable(),
1937
- clis: z12.array(CliKindSchema).min(1),
1938
- capabilities: z12.array(z12.string())
2003
+ slots: z13.number().int().positive().nullable(),
2004
+ clis: z13.array(CliKindSchema).min(1),
2005
+ capabilities: z13.array(z13.string())
1939
2006
  });
1940
2007
 
1941
2008
  // packages/shared/dist/version.js
1942
- var STELLARIS_VERSION = "0.3.22";
2009
+ var STELLARIS_VERSION = "0.3.23";
1943
2010
 
1944
2011
  // packages/shared/dist/mentions.js
1945
2012
  import { parse, postprocess, preprocess } from "micromark";
@@ -2657,32 +2724,32 @@ function postMentions(body) {
2657
2724
  }
2658
2725
 
2659
2726
  // packages/board-core/dist/metrics.js
2660
- import { z as z13 } from "zod";
2661
- var TurnPayload = z13.object({
2662
- turnId: z13.string().optional(),
2663
- project: z13.string(),
2664
- thread: z13.string().optional(),
2665
- channel: z13.string().optional(),
2666
- trigger: z13.string()
2667
- });
2668
- var TaskPayload = z13.object({
2669
- taskId: z13.string(),
2670
- project: z13.string(),
2671
- from: z13.string().optional()
2672
- });
2673
- var MessagePayload = z13.object({
2674
- id: z13.string().optional(),
2675
- channel: z13.string(),
2676
- thread: z13.string().nullable().optional(),
2677
- mentions: z13.array(z13.string()).default([])
2678
- });
2679
- var SteeredPayload = z13.object({ messages: z13.array(z13.string()) });
2680
- var SignalPayload = z13.object({
2681
- kind: z13.string(),
2682
- key: z13.string(),
2683
- summary: z13.string(),
2684
- taskId: z13.string().optional(),
2685
- project: z13.string().optional()
2727
+ import { z as z14 } from "zod";
2728
+ var TurnPayload = z14.object({
2729
+ turnId: z14.string().optional(),
2730
+ project: z14.string(),
2731
+ thread: z14.string().optional(),
2732
+ channel: z14.string().optional(),
2733
+ trigger: z14.string()
2734
+ });
2735
+ var TaskPayload = z14.object({
2736
+ taskId: z14.string(),
2737
+ project: z14.string(),
2738
+ from: z14.string().optional()
2739
+ });
2740
+ var MessagePayload = z14.object({
2741
+ id: z14.string().optional(),
2742
+ channel: z14.string(),
2743
+ thread: z14.string().nullable().optional(),
2744
+ mentions: z14.array(z14.string()).default([])
2745
+ });
2746
+ var SteeredPayload = z14.object({ messages: z14.array(z14.string()) });
2747
+ var SignalPayload = z14.object({
2748
+ kind: z14.string(),
2749
+ key: z14.string(),
2750
+ summary: z14.string(),
2751
+ taskId: z14.string().optional(),
2752
+ project: z14.string().optional()
2686
2753
  });
2687
2754
  function median(values) {
2688
2755
  const sorted = values.toSorted((a, b) => a - b);
@@ -2972,19 +3039,19 @@ function computeMetrics(input) {
2972
3039
  }
2973
3040
 
2974
3041
  // packages/board-core/dist/turn-history.js
2975
- import { z as z14 } from "zod";
2976
- var TurnHistoryPayloadSchema = z14.object({
3042
+ import { z as z15 } from "zod";
3043
+ var TurnHistoryPayloadSchema = z15.object({
2977
3044
  project: NameSchema,
2978
3045
  thread: UlidSchema.optional(),
2979
3046
  channel: NameSchema.optional(),
2980
- trigger: z14.string().default("manual"),
2981
- exitReason: z14.string().nullable().default(null),
2982
- costUsd: z14.number().default(0),
3047
+ trigger: z15.string().default("manual"),
3048
+ exitReason: z15.string().nullable().default(null),
3049
+ costUsd: z15.number().default(0),
2983
3050
  usage: UsageSchema.optional(),
2984
- model: z14.string().nullable().default(null),
2985
- summary: z14.string().nullable().default(null),
2986
- error: z14.string().nullable().default(null),
2987
- toolCalls: z14.number().int().nonnegative().optional(),
3051
+ model: z15.string().nullable().default(null),
3052
+ summary: z15.string().nullable().default(null),
3053
+ error: z15.string().nullable().default(null),
3054
+ toolCalls: z15.number().int().nonnegative().optional(),
2988
3055
  turnId: UlidSchema.optional()
2989
3056
  });
2990
3057
  function tokenUse(events, window, now) {
@@ -3230,6 +3297,13 @@ var BoardPaths = class {
3230
3297
  eventLog() {
3231
3298
  return path5.join(this.events(), "log.jsonl");
3232
3299
  }
3300
+ /** Images citizens uploaded, by id: outside the projection, which every runner mirrors. */
3301
+ images() {
3302
+ return path5.join(this.dataDir, "images");
3303
+ }
3304
+ image(id) {
3305
+ return path5.join(this.images(), id);
3306
+ }
3233
3307
  state() {
3234
3308
  return path5.join(this.dataDir, "state");
3235
3309
  }
@@ -3265,27 +3339,27 @@ function namesList(names) {
3265
3339
  return names.length <= 1 ? names[0] ?? "" : `${names.slice(0, -1).join(", ")} and ${names.at(-1) ?? ""}`;
3266
3340
  }
3267
3341
  var SKIPPED_IN_HOME = /* @__PURE__ */ new Set([".git", "turns", ".claude", ".codex"]);
3268
- var RunnerTokensSchema = z15.object({
3269
- runners: z15.record(z15.string(), z15.object({ tokenHash: z15.string().min(1) }))
3342
+ var RunnerTokensSchema = z16.object({
3343
+ runners: z16.record(z16.string(), z16.object({ tokenHash: z16.string().min(1) }))
3270
3344
  });
3271
- var SignInsSchema = z15.object({
3272
- signIns: z15.array(z15.object({
3273
- tokenHash: z15.string().min(1),
3274
- login: z15.string().min(1),
3345
+ var SignInsSchema = z16.object({
3346
+ signIns: z16.array(z16.object({
3347
+ tokenHash: z16.string().min(1),
3348
+ login: z16.string().min(1),
3275
3349
  /** The account's picture at the identity provider; sign-ins from before it have none. */
3276
- avatarUrl: z15.url().optional(),
3350
+ avatarUrl: z16.url().optional(),
3277
3351
  createdAt: IsoDateTimeSchema,
3278
3352
  expiresAt: IsoDateTimeSchema
3279
3353
  })).default([])
3280
3354
  });
3281
- var TurnStartPayloadSchema = z15.object({ project: NameSchema, turnId: UlidSchema.optional() });
3282
- var CursorsSchema = z15.object({
3283
- digest: z15.string().nullable(),
3284
- scopes: z15.record(z15.string(), z15.string()).default({}),
3285
- threadsFrom: z15.record(z15.string(), z15.string().nullable()).default({}),
3286
- channelsFrom: z15.record(z15.string(), z15.string().nullable()).default({}),
3355
+ var TurnStartPayloadSchema = z16.object({ project: NameSchema, turnId: UlidSchema.optional() });
3356
+ var CursorsSchema = z16.object({
3357
+ digest: z16.string().nullable(),
3358
+ scopes: z16.record(z16.string(), z16.string()).default({}),
3359
+ threadsFrom: z16.record(z16.string(), z16.string().nullable()).default({}),
3360
+ channelsFrom: z16.record(z16.string(), z16.string().nullable()).default({}),
3287
3361
  /** How far a work role has read news, which goes to whichever of its general conversations reads first. */
3288
- news: z15.string().optional()
3362
+ news: z16.string().optional()
3289
3363
  });
3290
3364
  var NO_CURSORS = { digest: null, scopes: {}, threadsFrom: {}, channelsFrom: {} };
3291
3365
  function conversationKey(scope, part) {
@@ -3324,7 +3398,7 @@ function byId(a, b) {
3324
3398
  function turnTime(record) {
3325
3399
  return record.endedAt ?? record.startedAt;
3326
3400
  }
3327
- var PausedSchema = z15.object({ paused: z15.boolean() });
3401
+ var PausedSchema = z16.object({ paused: z16.boolean() });
3328
3402
  var DEFAULT_LEASE_MS = 30 * 60 * 1e3;
3329
3403
  function withoutMentions(text) {
3330
3404
  return text.replaceAll(MENTION_PATTERN, "$1$2");
@@ -3349,7 +3423,7 @@ var OPS_WAKE_TRIGGER = "ops_event";
3349
3423
  var FRONT_DESK_TRIGGER = "user_post";
3350
3424
  var OPS_CHANNELS = ["governance"];
3351
3425
  var FRONT_DESK_CHANNELS = [ASK_CHANNEL];
3352
- var AlignmentsSchema = z15.object({ applied: z15.array(z15.string()).default([]) });
3426
+ var AlignmentsSchema = z16.object({ applied: z16.array(z16.string()).default([]) });
3353
3427
  var FOLLOW_DECISIONS = "ops-readers-follow-decisions";
3354
3428
  var THREAD_RECORDS = "threads-as-records";
3355
3429
  var DIGEST_CURSORS = "digest-replaces-inbox";
@@ -3363,10 +3437,11 @@ var CHANNEL_CONVERSATIONS = "channel-conversations";
3363
3437
  var DASHBOARD_UPDATES = "dashboard-updates-granted";
3364
3438
  var CRON_VERBS = "cron-verbs-granted";
3365
3439
  var KNOWLEDGE_NOTICES = "knowledge-notices";
3366
- var KnowledgeEventSchema = z15.object({
3440
+ var IMAGE_UPLOADS = "image-uploads-granted";
3441
+ var KnowledgeEventSchema = z16.object({
3367
3442
  topic: NameSchema,
3368
3443
  project: NameSchema.nullable(),
3369
- replaced: z15.boolean().optional()
3444
+ replaced: z16.boolean().optional()
3370
3445
  });
3371
3446
  var CRON_VERB_NAMES = ["create_cron", "update_cron", "remove_cron"];
3372
3447
  var OLD_DASHBOARD_LINE = "Agents may edit this file. It is rendered by the board UI.";
@@ -3498,6 +3573,7 @@ var Board = class _Board {
3498
3573
  mutex = new Mutex();
3499
3574
  /** The turns in flight, which the server hosting them supplies; none until it does. */
3500
3575
  turnsInFlight = () => [];
3576
+ imageSource = null;
3501
3577
  newId = monotonicFactory();
3502
3578
  events;
3503
3579
  actionCounts = /* @__PURE__ */ new Map();
@@ -3562,7 +3638,8 @@ var Board = class _Board {
3562
3638
  CHANNEL_CONVERSATIONS,
3563
3639
  DASHBOARD_UPDATES,
3564
3640
  CRON_VERBS,
3565
- KNOWLEDGE_NOTICES
3641
+ KNOWLEDGE_NOTICES,
3642
+ IMAGE_UPLOADS
3566
3643
  ].filter((name) => !applied.includes(name));
3567
3644
  if (pending.length === 0) {
3568
3645
  return;
@@ -3592,13 +3669,13 @@ var Board = class _Board {
3592
3669
  await this.openAsksChannel();
3593
3670
  }
3594
3671
  if (pending.includes(KNOWLEDGE_REMOVAL)) {
3595
- await this.grantBesideKnowledge("remove_knowledge");
3672
+ await this.grantBeside("write_knowledge", "remove_knowledge");
3596
3673
  }
3597
3674
  if (pending.includes(CHANNEL_CONVERSATIONS)) {
3598
3675
  await this.startChannelCursors();
3599
3676
  }
3600
3677
  if (pending.includes(DASHBOARD_UPDATES)) {
3601
- await this.grantBesideKnowledge("update_dashboard");
3678
+ await this.grantBeside("write_knowledge", "update_dashboard");
3602
3679
  await this.rewordDashboards();
3603
3680
  }
3604
3681
  if (pending.includes(CRON_VERBS)) {
@@ -3607,6 +3684,9 @@ var Board = class _Board {
3607
3684
  if (pending.includes(KNOWLEDGE_NOTICES)) {
3608
3685
  await this.noticeKnowledgeNotes();
3609
3686
  }
3687
+ if (pending.includes(IMAGE_UPLOADS)) {
3688
+ await this.grantBeside("post_message", "upload_image");
3689
+ }
3610
3690
  await writeJson(file, { applied: [...applied, ...pending] });
3611
3691
  }
3612
3692
  /**
@@ -3648,12 +3728,12 @@ var Board = class _Board {
3648
3728
  }
3649
3729
  }
3650
3730
  /**
3651
- * Grants `verb` once to every charter granting `write_knowledge`, the work roles' charters in
3652
- * practice; seed roles have it from their seed.
3731
+ * Grants `verb` once to every charter granting `beside`, the work roles' charters in practice;
3732
+ * seed roles have it from their seed.
3653
3733
  */
3654
- async grantBesideKnowledge(verb) {
3734
+ async grantBeside(beside, verb) {
3655
3735
  for (const charter of await this.listRoles()) {
3656
- if (charter.verbs.includes("write_knowledge") && !charter.verbs.includes(verb)) {
3736
+ if (charter.verbs.includes(beside) && !charter.verbs.includes(verb)) {
3657
3737
  await this.writeRoleUnlocked(USER_NAME, { ...charter, verbs: [...charter.verbs, verb] }, { verbsAdded: [verb] });
3658
3738
  }
3659
3739
  }
@@ -3811,7 +3891,7 @@ var Board = class _Board {
3811
3891
  }
3812
3892
  }
3813
3893
  for (const file of await listFiles(this.paths.tasks(slug))) {
3814
- const raw = await readMarkdown(path6.join(this.paths.tasks(slug), file), z15.record(z15.string(), z15.unknown()));
3894
+ const raw = await readMarkdown(path6.join(this.paths.tasks(slug), file), z16.record(z16.string(), z16.unknown()));
3815
3895
  const legacy = raw.data["thread"];
3816
3896
  if (legacy === void 0) {
3817
3897
  continue;
@@ -3889,7 +3969,7 @@ var Board = class _Board {
3889
3969
  * turns, so it follows nothing now.
3890
3970
  */
3891
3971
  async renameInboxCursors() {
3892
- const Legacy = z15.object({ inbox: z15.string().nullable() });
3972
+ const Legacy = z16.object({ inbox: z16.string().nullable() });
3893
3973
  for (const agent2 of await this.listAgents()) {
3894
3974
  const file = this.paths.agentCursors(agent2.name);
3895
3975
  if (await exists(file)) {
@@ -3935,7 +4015,7 @@ ${charter.purpose}
3935
4015
  */
3936
4016
  async alignSeedRole(seed) {
3937
4017
  const file = this.paths.role(seed.name);
3938
- const raw = await readMarkdown(file, z15.record(z15.string(), z15.unknown()));
4018
+ const raw = await readMarkdown(file, z16.record(z16.string(), z16.unknown()));
3939
4019
  const current = RoleCharterSchema.parse(raw.data);
3940
4020
  const verbsAdded = seed.verbs.filter((verb) => !current.verbs.includes(verb));
3941
4021
  const fieldsAligned = RoleCharterSchema.keyof().options.filter((key) => key === "verbs" || seed[key] === void 0 ? false : seed.name === USER_ROLE ? JSON.stringify(seed[key]) !== JSON.stringify(current[key]) : !(key in raw.data));
@@ -4252,7 +4332,7 @@ ${charter.purpose}
4252
4332
  /** The society's norms, the one knowledge topic every turn loads. Empty until the steward writes it. */
4253
4333
  async readSocietyNorms() {
4254
4334
  const file = this.paths.societyKnowledgeFile("norms");
4255
- return await exists(file) ? (await readMarkdown(file, z15.record(z15.string(), z15.unknown()))).body : "";
4335
+ return await exists(file) ? (await readMarkdown(file, z16.record(z16.string(), z16.unknown()))).body : "";
4256
4336
  }
4257
4337
  /** Knowledge topics of a project, or of the society when the project is null. */
4258
4338
  async listKnowledge(project2) {
@@ -4272,7 +4352,7 @@ ${charter.purpose}
4272
4352
  */
4273
4353
  async knowledgeAt(file, project2, topic) {
4274
4354
  const { data, body } = await readLooseMarkdown(file);
4275
- const revision = z15.number().int().min(0).safeParse(data["revision"]);
4355
+ const revision = z16.number().int().min(0).safeParse(data["revision"]);
4276
4356
  const updatedBy = NameSchema.safeParse(data["updatedBy"]);
4277
4357
  const updatedAt = IsoDateTimeSchema.safeParse(data["updatedAt"]);
4278
4358
  return {
@@ -5235,6 +5315,60 @@ ${current.body}`);
5235
5315
  return updated;
5236
5316
  });
5237
5317
  }
5318
+ /**
5319
+ * Keeps an image a citizen's turn names by its path, read on the runner the turn runs on, which
5320
+ * refuses a file outside the turn's worktree, the citizen's home, and the system temp folder.
5321
+ * Only the bytes of a PNG, JPEG, GIF, or WebP of at most `IMAGE_LIMIT_BYTES` are kept, checked
5322
+ * here again whatever the runner said, under a new id outside the projection, so no runner
5323
+ * mirrors them and no prompt carries them: a post shows the image by its `image:` address.
5324
+ */
5325
+ async uploadImage(actor, input) {
5326
+ const args = VerbInputs.upload_image.parse(input);
5327
+ await this.authorize(actor, "upload_image");
5328
+ if (actor.scope === void 0) {
5329
+ throw new BoardError("INVALID_STATE", "upload_image reads the file on the machine a turn runs on, so only a turn can call it");
5330
+ }
5331
+ if (this.imageSource === null) {
5332
+ throw new BoardError("NOT_FOUND", "this board has no runners to read an image from");
5333
+ }
5334
+ const bytes = await this.imageSource(actor, args.path);
5335
+ const type = imageTypeOf(bytes);
5336
+ if (type === null) {
5337
+ throw new BoardError("VALIDATION", `${args.path} is not a PNG, JPEG, GIF, or WebP image by its first bytes`);
5338
+ }
5339
+ if (bytes.byteLength > IMAGE_LIMIT_BYTES) {
5340
+ throw new BoardError("VALIDATION", `${args.path} is ${bytes.byteLength} bytes, over the ${IMAGE_LIMIT_BYTES} an image may be`);
5341
+ }
5342
+ return this.mutex.run(async () => {
5343
+ const id = this.newId();
5344
+ await writeFileAtomic(this.paths.image(id), bytes);
5345
+ await this.events.append("image.uploaded", actor.name, {
5346
+ id,
5347
+ type,
5348
+ size: bytes.byteLength
5349
+ });
5350
+ const name = path6.basename(args.path).replaceAll(/[[\]\\\r\n]/g, "");
5351
+ return {
5352
+ id,
5353
+ type,
5354
+ size: bytes.byteLength,
5355
+ markdown: `![${name}](${IMAGE_SCHEME}${id})`
5356
+ };
5357
+ });
5358
+ }
5359
+ /** An uploaded image's bytes and kind, which its first bytes tell. */
5360
+ async readImage(id) {
5361
+ const file = this.paths.image(UlidSchema.parse(id));
5362
+ if (!await exists(file)) {
5363
+ throw new BoardError("NOT_FOUND", `image ${id} not found`);
5364
+ }
5365
+ const bytes = await readFile4(file);
5366
+ const type = imageTypeOf(bytes);
5367
+ if (type === null) {
5368
+ throw new BoardError("NOT_FOUND", `image ${id} is not an image the board shows`);
5369
+ }
5370
+ return { type, bytes };
5371
+ }
5238
5372
  /** Every cron, ended ones included, oldest first. */
5239
5373
  async listCrons() {
5240
5374
  const crons = [];
@@ -5626,6 +5760,13 @@ ${current.body}`);
5626
5760
  watchTurns(source) {
5627
5761
  this.turnsInFlight = source;
5628
5762
  }
5763
+ /**
5764
+ * Where `upload_image` reads a file from: the runner the calling turn runs on, through the server
5765
+ * that hosts the runners. Without one, as in the admin CLI, nothing can be uploaded.
5766
+ */
5767
+ readImagesWith(source) {
5768
+ this.imageSource = source;
5769
+ }
5629
5770
  /**
5630
5771
  * Refuses to end conversations while another citizen's turn is in one of them: `cut` picks the
5631
5772
  * turns that would lose theirs. The caller's own turn is exempt, since ending a conversation
@@ -6455,6 +6596,8 @@ ${rationale}`}`);
6455
6596
  return this.updateCron(actor, VerbInputs.update_cron.parse(input));
6456
6597
  case "remove_cron":
6457
6598
  return this.removeCron(actor, VerbInputs.remove_cron.parse(input));
6599
+ case "upload_image":
6600
+ return this.uploadImage(actor, VerbInputs.upload_image.parse(input));
6458
6601
  default:
6459
6602
  throw new BoardError("VALIDATION", `unknown verb ${String(verb)}`);
6460
6603
  }
@@ -6501,7 +6644,7 @@ ${rationale}`}`);
6501
6644
  }
6502
6645
  async readAgentRoleBody(agent2) {
6503
6646
  const file = this.paths.agentRole(agent2);
6504
- return await exists(file) ? (await readMarkdown(file, z15.record(z15.string(), z15.unknown()))).body : "";
6647
+ return await exists(file) ? (await readMarkdown(file, z16.record(z16.string(), z16.unknown()))).body : "";
6505
6648
  }
6506
6649
  /** The steps of one finished turn, as the runner handed them over when it ended. */
6507
6650
  /**
@@ -6909,7 +7052,7 @@ ${rationale}`}`);
6909
7052
  return { project: slug, revision: 0, body: "" };
6910
7053
  }
6911
7054
  const { data, body } = await readLooseMarkdown(file);
6912
- const revision = z15.number().int().min(0).safeParse(data["revision"]);
7055
+ const revision = z16.number().int().min(0).safeParse(data["revision"]);
6913
7056
  const updatedBy = NameSchema.safeParse(data["updatedBy"]);
6914
7057
  const updatedAt = IsoDateTimeSchema.safeParse(data["updatedAt"]);
6915
7058
  return {
@@ -7183,7 +7326,7 @@ ${charter.purpose}
7183
7326
 
7184
7327
  ${charter.purpose}
7185
7328
 
7186
- Route every lesson with one question: about me, my craft, or the user, it goes in memory/core.md; about this codebase, it goes in the project's knowledge directory; something everyone should know, post it.
7329
+ Route every lesson with one question: about me, my craft, or the user, it goes in memory/core.md; about how this codebase behaves, it goes in the repo's AGENTS.md or README; about this project as a place (runners, access, flow, where results live), it goes in the project's knowledge; something everyone should know, post it.
7187
7330
  ` + (seed.length === 0 ? "" : `
7188
7331
  ${SEED_INSTRUCTIONS_HEADING}
7189
7332
 
@@ -7200,7 +7343,7 @@ ${seed}
7200
7343
  continue;
7201
7344
  }
7202
7345
  const file = this.paths.agentRole(agent2.name);
7203
- const body = await exists(file) ? (await readMarkdown(file, z15.record(z15.string(), z15.unknown()))).body : "";
7346
+ const body = await exists(file) ? (await readMarkdown(file, z16.record(z16.string(), z16.unknown()))).body : "";
7204
7347
  const at = body.indexOf(`
7205
7348
  ${SEED_INSTRUCTIONS_HEADING}
7206
7349
  `);