@alecsibilia/luca 14.0.0-alpha.2 → 14.0.0-alpha.21

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 (321) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +7 -2
  3. package/board/client/board-look.ts +31 -1
  4. package/board/client/board-panel-parts.tsx +150 -0
  5. package/board/client/board-panel-stages.ts +99 -0
  6. package/board/client/board-panel-styles.ts +223 -0
  7. package/board/client/board-panel.tsx +77 -1275
  8. package/board/client/engine-life.ts +48 -0
  9. package/board/client/final-review-stack.tsx +144 -0
  10. package/board/client/heartbeat.tsx +61 -0
  11. package/board/client/helper-lines.tsx +69 -0
  12. package/board/client/live-feed.tsx +86 -0
  13. package/board/client/live-line.ts +73 -0
  14. package/board/client/model-line.tsx +178 -0
  15. package/board/client/needs-you-section.tsx +133 -0
  16. package/board/client/one-line.tsx +193 -0
  17. package/board/client/repo-wait-banner.tsx +69 -0
  18. package/board/client/run-footer.tsx +68 -0
  19. package/board/client/run-header.tsx +189 -0
  20. package/board/client/run-picker.tsx +98 -0
  21. package/board/client/status-bar.tsx +131 -0
  22. package/board/client/step-dots.tsx +127 -0
  23. package/board/client/stuck-actions.tsx +269 -0
  24. package/board/client/ticket-card-view.tsx +238 -0
  25. package/board/client/ticket-detail.tsx +87 -0
  26. package/board/client/ticket-stack.tsx +119 -0
  27. package/board/client/ticket-wait.ts +188 -0
  28. package/board/client/timeline-rows.tsx +41 -14
  29. package/board/client/usage-line.tsx +51 -0
  30. package/board/client/wait-line.tsx +39 -0
  31. package/board/index.client.tsx +1 -1
  32. package/board/index.server.ts +7 -1
  33. package/board/package.json +1 -1
  34. package/board/server/board-panel-state-helpers.ts +67 -0
  35. package/board/server/board-server-check.ts +294 -0
  36. package/board/server/board-server-engine.ts +129 -0
  37. package/board/server/board-server-events.ts +134 -0
  38. package/board/server/board-server-read.ts +190 -0
  39. package/board/server/board-server-resume.ts +164 -0
  40. package/board/server/board-server-start.ts +174 -0
  41. package/board/server/board-server-store.ts +281 -0
  42. package/board/server/board-server-types.ts +114 -0
  43. package/board/server/board-server-util.ts +4 -0
  44. package/board/server/board-server.ts +52 -943
  45. package/board/server/board-vocabulary-engine.ts +144 -0
  46. package/board/server/board-vocabulary-review.ts +115 -0
  47. package/board/server/board-vocabulary-run.ts +145 -0
  48. package/board/server/board-vocabulary-shapes.ts +153 -0
  49. package/board/server/board-vocabulary.ts +20 -375
  50. package/board/server/current-step-panel-helpers.ts +108 -0
  51. package/board/server/describe-record.ts +403 -0
  52. package/board/server/engine-launch.ts +20 -3
  53. package/board/server/engine-restart-helpers.ts +105 -0
  54. package/board/server/engine-watch.ts +45 -5
  55. package/board/server/journal-rebuild-helpers.ts +169 -0
  56. package/board/server/live-file.ts +130 -0
  57. package/board/server/luca-version.ts +1 -1
  58. package/board/server/make-rows.ts +14 -629
  59. package/board/server/record-texts.ts +350 -0
  60. package/board/server/reduce-board-agent-start.ts +224 -0
  61. package/board/server/reduce-board-agents.ts +160 -0
  62. package/board/server/reduce-board-counters.ts +138 -0
  63. package/board/server/reduce-board-create.ts +148 -0
  64. package/board/server/reduce-board-final-review.ts +174 -0
  65. package/board/server/reduce-board-needs-you.ts +283 -0
  66. package/board/server/reduce-board-reasons.ts +59 -0
  67. package/board/server/reduce-board-run.ts +255 -0
  68. package/board/server/reduce-board-settle.ts +88 -0
  69. package/board/server/reduce-board-steps.ts +226 -0
  70. package/board/server/reduce-board-text.ts +139 -0
  71. package/board/server/reduce-board-ticket-checks.ts +168 -0
  72. package/board/server/reduce-board-ticket-join.ts +144 -0
  73. package/board/server/reduce-board-ticket-start.ts +132 -0
  74. package/board/server/reduce-board-update.ts +117 -0
  75. package/board/server/reduce-board-usage.ts +247 -0
  76. package/board/server/reduce-board.ts +100 -1917
  77. package/board/server/reply-post.ts +407 -0
  78. package/board/server/run-registry.ts +8 -4
  79. package/board/server/ticket-stages-panel-helpers.ts +296 -0
  80. package/board/shared/board-rows.ts +9 -0
  81. package/board/shared/board-rpc.ts +42 -0
  82. package/board/shared/board-state-counts.ts +77 -0
  83. package/board/shared/board-state-live.ts +99 -0
  84. package/board/shared/board-state-review.ts +59 -0
  85. package/board/shared/board-state-run.ts +236 -0
  86. package/board/shared/board-state-ticket.ts +257 -0
  87. package/board/shared/board-state-usage.ts +107 -0
  88. package/board/shared/board-state.ts +97 -567
  89. package/board/shared/reply-actions.ts +207 -0
  90. package/engine/agents/agent-launcher.ts +27 -4
  91. package/engine/agents/claude-launcher-helpers.ts +233 -0
  92. package/engine/agents/claude-launcher.ts +28 -669
  93. package/engine/agents/claude-messages.ts +212 -0
  94. package/engine/agents/claude-options.ts +43 -8
  95. package/engine/agents/common-instructions.ts +138 -0
  96. package/engine/agents/input-channel.ts +36 -0
  97. package/engine/agents/launch-paths.ts +29 -0
  98. package/engine/agents/launch-session.ts +227 -0
  99. package/engine/agents/learner-instructions.ts +31 -0
  100. package/engine/agents/open-session.ts +210 -0
  101. package/engine/agents/prompt-sections.ts +95 -0
  102. package/engine/agents/rejoin-prompts.ts +135 -0
  103. package/engine/agents/reviewer-instructions.ts +99 -0
  104. package/engine/agents/role-instructions.ts +31 -244
  105. package/engine/agents/role-prompts.ts +39 -109
  106. package/engine/agents/role-results.ts +106 -7
  107. package/engine/agents/scripted-launcher.ts +21 -6
  108. package/engine/agents/session-pool.ts +124 -0
  109. package/engine/agents/turn-progress.ts +283 -0
  110. package/engine/agents/writer-instructions.ts +151 -0
  111. package/engine/cli/computer-adapters-real.ts +15 -3
  112. package/engine/cli/computer-adapters.ts +2 -0
  113. package/engine/cli/computer-checks.ts +87 -4
  114. package/engine/cli/config-reload-text.ts +39 -0
  115. package/engine/cli/decision-model-setup.ts +70 -0
  116. package/engine/cli/doctor-command.ts +1 -0
  117. package/engine/cli/doctor.ts +21 -3
  118. package/engine/cli/going-runs.ts +192 -36
  119. package/engine/cli/init-command.ts +1 -0
  120. package/engine/cli/init.ts +23 -1
  121. package/engine/cli/live-runs.ts +73 -0
  122. package/engine/cli/luca-run.ts +42 -7
  123. package/engine/cli/luca-skills.ts +183 -0
  124. package/engine/cli/luca.ts +8 -1
  125. package/engine/cli/models-command.ts +119 -0
  126. package/engine/cli/read-run.ts +81 -0
  127. package/engine/cli/run-args.ts +33 -6
  128. package/engine/cli/run-demo.ts +143 -0
  129. package/engine/cli/run-end.ts +184 -0
  130. package/engine/cli/run-modes-helpers.ts +81 -0
  131. package/engine/cli/run-modes.ts +62 -439
  132. package/engine/cli/setup.ts +5 -48
  133. package/engine/cli/unfinished-runs.ts +122 -0
  134. package/engine/cli/upgrade-command.ts +212 -30
  135. package/engine/cli/upgrade-finish.ts +149 -0
  136. package/engine/cli/upgrade.ts +112 -71
  137. package/engine/config/config-fields.ts +127 -0
  138. package/engine/config/config-reload.ts +250 -0
  139. package/engine/config/engine-config-schema.ts +235 -0
  140. package/engine/config/engine-config.ts +72 -142
  141. package/engine/config/test-commands.ts +102 -0
  142. package/engine/core/agent-guards-helpers.ts +84 -0
  143. package/engine/core/agent-turn.ts +395 -0
  144. package/engine/core/already-done.ts +44 -1
  145. package/engine/core/build-action.ts +214 -0
  146. package/engine/core/build-context.ts +135 -0
  147. package/engine/core/build-launch.ts +259 -0
  148. package/engine/core/commit-in.ts +282 -0
  149. package/engine/core/decide-build-early.ts +108 -0
  150. package/engine/core/decide-build-ending.ts +145 -0
  151. package/engine/core/decide-build-helpers.ts +87 -0
  152. package/engine/core/decide-build-tickets.ts +207 -0
  153. package/engine/core/decide-build-view.ts +103 -0
  154. package/engine/core/decide-build.ts +101 -1368
  155. package/engine/core/decide-final-fix.ts +203 -0
  156. package/engine/core/decide-final-review.ts +55 -310
  157. package/engine/core/decide-red-green.ts +398 -0
  158. package/engine/core/decide-rejoin.ts +259 -0
  159. package/engine/core/decide-repo-wait.ts +129 -0
  160. package/engine/core/decide-run-budget.ts +86 -12
  161. package/engine/core/decide-stuck-helpers.ts +127 -0
  162. package/engine/core/decide-stuck.ts +60 -8
  163. package/engine/core/decide-ticket-review.ts +95 -0
  164. package/engine/core/decide-ticket.ts +267 -0
  165. package/engine/core/decide-waits.ts +47 -0
  166. package/engine/core/decide.ts +74 -23
  167. package/engine/core/engine-chores.ts +163 -0
  168. package/engine/core/environment-rerun.ts +83 -0
  169. package/engine/core/evidence-text.ts +84 -0
  170. package/engine/core/execute-action.ts +303 -0
  171. package/engine/core/execute-already-done-check.ts +133 -0
  172. package/engine/core/execute-build.ts +68 -944
  173. package/engine/core/execute-changeset.ts +5 -7
  174. package/engine/core/execute-final-review.ts +125 -13
  175. package/engine/core/execute-gates.ts +182 -0
  176. package/engine/core/execute-intake.ts +130 -0
  177. package/engine/core/execute-join.ts +276 -0
  178. package/engine/core/execute-memory.ts +12 -0
  179. package/engine/core/execute-pull-request.ts +84 -0
  180. package/engine/core/execute-red-check.ts +219 -0
  181. package/engine/core/execute-repo-wait.ts +129 -0
  182. package/engine/core/execute-stuck.ts +25 -10
  183. package/engine/core/execute-waits.ts +158 -0
  184. package/engine/core/execute-with-jev.ts +118 -0
  185. package/engine/core/execute.ts +124 -831
  186. package/engine/core/final-failure-cap.ts +38 -0
  187. package/engine/core/final-review-action.ts +125 -0
  188. package/engine/core/final-review-text.ts +63 -17
  189. package/engine/core/final-stuck-text.ts +86 -0
  190. package/engine/core/fix-loop-text.ts +49 -2
  191. package/engine/core/left-out.ts +120 -0
  192. package/engine/core/live-file.ts +372 -0
  193. package/engine/core/loop-caps.ts +25 -2
  194. package/engine/core/not-in-run.ts +7 -3
  195. package/engine/core/pull-request-text.ts +255 -6
  196. package/engine/core/repo-wait-text.ts +81 -0
  197. package/engine/core/review-text.ts +55 -1
  198. package/engine/core/run-crash-recovery-helpers.ts +16 -0
  199. package/engine/core/run-session-close-helpers.ts +96 -0
  200. package/engine/core/run-start.ts +148 -0
  201. package/engine/core/run-stuck-text.ts +86 -0
  202. package/engine/core/schedule-rules.ts +193 -0
  203. package/engine/core/stuck-detail-text.ts +89 -0
  204. package/engine/core/stuck-format.ts +22 -0
  205. package/engine/core/stuck-text.ts +29 -332
  206. package/engine/core/ticket-stuck-text.ts +192 -0
  207. package/engine/core/worktree-changes.ts +106 -0
  208. package/engine/gates/already-done-check.ts +120 -0
  209. package/engine/gates/feature-map.ts +96 -0
  210. package/engine/gates/gate-runner.ts +108 -108
  211. package/engine/gates/gate-schemas.ts +61 -2
  212. package/engine/gates/leftover-scan.ts +154 -31
  213. package/engine/gates/new-tests.ts +45 -0
  214. package/engine/gates/own-files-check.ts +98 -0
  215. package/engine/gates/prepare-check.ts +60 -0
  216. package/engine/gates/prepare-slots.ts +99 -0
  217. package/engine/gates/red-check.ts +184 -16
  218. package/engine/gates/shell-check.ts +64 -0
  219. package/engine/gates/slot-waits.ts +55 -0
  220. package/engine/gates/slow-test-runner.ts +59 -0
  221. package/engine/gates/test-checks.ts +161 -0
  222. package/engine/gates/test-runner.ts +164 -5
  223. package/engine/gates/test-slots.ts +48 -0
  224. package/engine/git/git-adapter.ts +55 -396
  225. package/engine/git/git-commits.ts +132 -0
  226. package/engine/git/git-join.ts +139 -0
  227. package/engine/git/git-read.ts +123 -0
  228. package/engine/git/git-run.ts +32 -0
  229. package/engine/git/git-worktrees.ts +143 -0
  230. package/engine/git/outside-links.ts +55 -0
  231. package/engine/guards/after-turn-check.ts +31 -5
  232. package/engine/guards/guard-hook.ts +60 -12
  233. package/engine/guards/guard-roles.ts +68 -0
  234. package/engine/guards/helper-rules.ts +92 -0
  235. package/engine/guards/permission-rules.ts +161 -0
  236. package/engine/guards/role-rules-helpers.ts +48 -0
  237. package/engine/guards/role-rules.ts +34 -606
  238. package/engine/guards/shell-rules.ts +344 -0
  239. package/engine/guards/worktree-git.ts +208 -0
  240. package/engine/guards/worktree-snapshot.ts +412 -0
  241. package/engine/guards/worktree-state.ts +28 -825
  242. package/engine/guards/worktree-undo.ts +260 -0
  243. package/engine/guards/write-rules.ts +149 -0
  244. package/engine/index.ts +30 -9
  245. package/engine/intake/criteria-checks.ts +114 -0
  246. package/engine/intake/intake-checks.ts +164 -30
  247. package/engine/intake/intake-schemas.ts +37 -2
  248. package/engine/jev/clef-client.ts +259 -0
  249. package/engine/jev/decision-model-credentials.ts +212 -0
  250. package/engine/jev/jev-jobs.ts +144 -60
  251. package/engine/jev/jev-schemas.ts +86 -5
  252. package/engine/jev/jev-shadow-helpers.ts +218 -0
  253. package/engine/jev/jev-shadow.ts +109 -64
  254. package/engine/jev/model-pick.ts +275 -0
  255. package/engine/journal/agent-entries.ts +167 -0
  256. package/engine/journal/agent-message-entries.ts +72 -0
  257. package/engine/journal/agent-turn-replay.ts +203 -0
  258. package/engine/journal/already-done-entries.ts +55 -0
  259. package/engine/journal/commit-entries.ts +56 -0
  260. package/engine/journal/cross-ticket-replay.ts +222 -0
  261. package/engine/journal/decision-model-entries.ts +86 -0
  262. package/engine/journal/entry-fields.ts +10 -0
  263. package/engine/journal/final-review-entries.ts +128 -0
  264. package/engine/journal/final-review-replay.ts +324 -0
  265. package/engine/journal/final-review-round.ts +320 -0
  266. package/engine/journal/final-review-state.ts +180 -0
  267. package/engine/journal/gate-entries.ts +81 -0
  268. package/engine/journal/intake-entries.ts +87 -0
  269. package/engine/journal/join-entries.ts +126 -0
  270. package/engine/journal/journal-entry-schema.ts +218 -0
  271. package/engine/journal/journal-kinds.ts +97 -0
  272. package/engine/journal/journal-record-schema.ts +218 -0
  273. package/engine/journal/journal-record.ts +43 -1400
  274. package/engine/journal/journal.ts +6 -1
  275. package/engine/journal/limit-entries.ts +90 -0
  276. package/engine/journal/memory-entries.ts +124 -0
  277. package/engine/journal/memory-replay.ts +157 -0
  278. package/engine/journal/plan-replay.ts +139 -0
  279. package/engine/journal/pull-request-entries.ts +41 -0
  280. package/engine/journal/replay.ts +157 -2144
  281. package/engine/journal/reply-replay.ts +144 -0
  282. package/engine/journal/repo-wait-entries.ts +53 -0
  283. package/engine/journal/run-entries.ts +172 -0
  284. package/engine/journal/run-state.ts +264 -0
  285. package/engine/journal/shared-failure-replay.ts +133 -0
  286. package/engine/journal/stuck-entries.ts +193 -0
  287. package/engine/journal/ticket-progress.ts +392 -0
  288. package/engine/journal/ticket-replay.ts +411 -0
  289. package/engine/journal/ticket-result-replay.ts +364 -0
  290. package/engine/journal/ticket-retry-replay.ts +142 -0
  291. package/engine/journal/worktree-entries.ts +122 -0
  292. package/engine/models/model-score.ts +512 -0
  293. package/engine/shell/run-command.ts +187 -18
  294. package/engine/testing/agent-turn-fixtures.ts +287 -0
  295. package/engine/testing/already-done-fixtures.ts +97 -0
  296. package/engine/testing/build-fixtures.ts +68 -973
  297. package/engine/testing/checkouts-fixtures.ts +48 -0
  298. package/engine/testing/final-review-fixtures.ts +62 -1
  299. package/engine/testing/final-review-steps.ts +143 -0
  300. package/engine/testing/limit-fixtures.ts +85 -0
  301. package/engine/testing/live-file-fixtures.ts +57 -0
  302. package/engine/testing/practice-repo.ts +10 -4
  303. package/engine/testing/practice-run.ts +1 -1
  304. package/engine/testing/reply-fixtures.ts +88 -0
  305. package/engine/testing/run-budget-fixtures.ts +165 -0
  306. package/engine/testing/run-fixtures.ts +219 -0
  307. package/engine/testing/sdk-play.ts +177 -0
  308. package/engine/testing/setup-repo.ts +194 -0
  309. package/engine/testing/step-record-fixtures.ts +55 -0
  310. package/engine/testing/ticket-step-fixtures.ts +272 -0
  311. package/engine/testing/wait-scenarios.ts +186 -0
  312. package/engine/tracker/gh-retry.ts +217 -0
  313. package/engine/tracker/github-tracker.ts +310 -90
  314. package/engine/tracker/in-memory-tracker.ts +8 -4
  315. package/engine/tracker/tracker.ts +131 -6
  316. package/package.json +2 -1
  317. package/skills/luca-retro/SKILL.md +74 -0
  318. package/skills/luca-retro/scripts/retro-summary.ts +1356 -0
  319. package/skills/luca-unstick/SKILL.md +153 -0
  320. package/skills/luca-unstick/scripts/stuck-summary.ts +1063 -0
  321. package/engine/jev/jev-client.ts +0 -173
@@ -1,1401 +1,44 @@
1
- import { z } from 'zod'
2
-
3
- import { AgentSessionSchema } from '../agents/agent-launcher'
4
- import {
5
- AgentRoleSchema,
6
- LensNameSchema,
7
- RoleResultSchema,
8
- } from '../agents/role-results'
9
- import { EngineConfigSchema } from '../config/engine-config'
10
- import {
11
- GateCheckSchema,
12
- LeftoverHitSchema,
13
- RedCheckResultSchema,
14
- TestRunSchema,
15
- } from '../gates/gate-schemas'
16
- import {
17
- IntakeProblemSchema,
18
- IntakeReadSchema,
19
- SpecSnapshotSchema,
20
- TicketSnapshotSchema,
21
- } from '../intake/intake-schemas'
22
- import {
23
- JevAnswerSchema,
24
- JevFailureReasonSchema,
25
- JevFixedSchema,
26
- JevJobSchema,
27
- JevRequestSchema,
28
- } from '../jev/jev-schemas'
29
- import { UsageRecordSchema } from '../limits/plan-usage'
30
- import {
31
- MemoryFeedbackSchema,
32
- MemorySaveSchema,
33
- RecalledMemorySchema,
34
- RecallPointSchema,
35
- VaultSearchSchema,
36
- } from '../memory/memory-schemas'
37
-
38
- const ENTRY_FIELDS = {
39
- /** The ticket (or spec) a record is about, `null` for the whole run. */
40
- ticket: z.number().int().positive().nullable(),
41
- /** The role that produced the record, `null` for the engine itself. */
42
- role: z.string().nullable(),
43
- }
44
-
45
- const STAMP_FIELDS = {
46
- /** 1, 2, 3, ... in the order records were appended. */
47
- seq: z.number().int().min(1),
48
- time: z.iso.datetime(),
49
- }
50
-
51
- const RunStartedEntrySchema = z.object({
52
- ...ENTRY_FIELDS,
53
- kind: z.literal('run_started'),
54
- content: z.object({
55
- spec_number: z.number().int().positive(),
56
- config: EngineConfigSchema,
57
- /** The branch the run branch starts from and its PR merges into. */
58
- base_branch: z.string().min(1).default('main'),
59
- /**
60
- * Memory for this run (#370): on, with the project's vault (`null`
61
- * searches only `default`), or `null` for off. Off leaves the run
62
- * exactly as it was before memory.
63
- */
64
- memory: z
65
- .object({ project_vault: z.string().min(1).nullable() })
66
- .nullable()
67
- .default(null),
68
- /**
69
- * The repo the run is on, as an absolute path, so `luca-run --resume`
70
- * can find it. `null` in older journals.
71
- */
72
- repo: z.string().min(1).nullable().default(null),
73
- /**
74
- * Luca's version the run started on (#460). `null` in older
75
- * journals.
76
- */
77
- luca_version: z.string().min(1).nullable().default(null),
78
- }),
79
- })
80
-
81
- /**
82
- * The engine started again on the run's journal (#460), on Luca's version
83
- * `luca_version`, which may differ from the one in `run_started`. Journaled
84
- * once per resume, before the engine's first step. Nothing reads it but
85
- * the board.
86
- */
87
- const EngineResumedEntrySchema = z.object({
88
- ...ENTRY_FIELDS,
89
- kind: z.literal('engine_resumed'),
90
- content: z.object({ luca_version: z.string().min(1) }),
91
- })
92
-
93
- const IntakeReadEntrySchema = z.object({
94
- ...ENTRY_FIELDS,
95
- kind: z.literal('intake_read'),
96
- content: IntakeReadSchema,
97
- })
98
-
99
- const IntakeRefusedEntrySchema = z.object({
100
- ...ENTRY_FIELDS,
101
- kind: z.literal('intake_refused'),
102
- content: z.object({ problems: z.array(IntakeProblemSchema) }),
103
- })
104
-
105
- /**
106
- * The run ends with nothing to do: at intake, as every ticket of the spec
107
- * is closed, or after it, as every ticket's work was already on the base
108
- * branch (`already_done`, #484; the engine closed those tickets).
109
- */
110
- const NothingToDoEntrySchema = z.object({
111
- ...ENTRY_FIELDS,
112
- kind: z.literal('nothing_to_do'),
113
- content: z.object({
114
- closed_tickets: z.array(z.number().int()),
115
- already_done: z.array(z.number().int().positive()).default([]),
116
- }),
117
- })
118
-
119
- const SpecSnapshotEntrySchema = z.object({
120
- ...ENTRY_FIELDS,
121
- kind: z.literal('spec_snapshot'),
122
- content: z.object({
123
- spec: SpecSnapshotSchema,
124
- /** The open tickets in blocker order; one `ticket_snapshot` each. */
125
- ticket_order: z.array(z.number().int().positive()),
126
- closed_tickets: z.array(z.number().int().positive()),
127
- }),
128
- })
129
-
130
- const TicketSnapshotEntrySchema = z.object({
131
- ...ENTRY_FIELDS,
132
- kind: z.literal('ticket_snapshot'),
133
- content: TicketSnapshotSchema,
134
- })
135
-
136
- /** A git worktree the engine made: where, on which branch, from which commit. */
137
- const WorktreeSchema = z.object({
138
- branch: z.string().min(1),
139
- path: z.string().min(1),
140
- base_sha: z.string().min(1),
141
- })
142
-
143
- /**
144
- * The run branch's worktree. `changesets` is true when the repo had
145
- * `.changeset/config.json` there, so the engine writes a changeset before
146
- * the PR (#461).
147
- */
148
- const RunBranchCreatedEntrySchema = z.object({
149
- ...ENTRY_FIELDS,
150
- kind: z.literal('run_branch_created'),
151
- content: WorktreeSchema.extend({
152
- changesets: z.boolean().default(false),
153
- }),
154
- })
155
-
156
- const TicketWorktreeCreatedEntrySchema = z.object({
157
- ...ENTRY_FIELDS,
158
- kind: z.literal('ticket_worktree_created'),
159
- content: WorktreeSchema,
160
- })
161
-
162
- /**
163
- * The config's prepare command (#481), run in a new ticket worktree before
164
- * its baseline tests. Journaled only with a prepare command. A failed one
165
- * leaves the baseline tests unrun.
166
- */
167
- const BaselinePreparedEntrySchema = z.object({
168
- ...ENTRY_FIELDS,
169
- kind: z.literal('baseline_prepared'),
170
- content: z.object({ check: GateCheckSchema }),
171
- })
172
-
173
- /**
174
- * New untracked paths a run of the config's prepare command made in a
175
- * checkout (#486): there after it ran, not before, such as a symlinked
176
- * tools folder or a build file the repo's `.gitignore` misses. They are not
177
- * an agent's work, so the engine never commits them or judges them by role
178
- * rules, in any checkout of the run. Journaled right after the prepare run
179
- * (at the baseline, the red check, or the gates), only when it made any.
180
- * `ticket` is the step's, as on its `gates_run`: `null` in the final review.
181
- */
182
- const PrepareMadeEntrySchema = z.object({
183
- ...ENTRY_FIELDS,
184
- kind: z.literal('prepare_made'),
185
- content: z.object({
186
- /** Worktree-relative, as git lists them (`git ls-files --others`). */
187
- paths: z.array(z.string()),
188
- }),
189
- })
190
-
191
- /** The tests as they stood before any agent worked on a ticket. */
192
- const BaselineTestsEntrySchema = z.object({
193
- ...ENTRY_FIELDS,
194
- kind: z.literal('baseline_tests'),
195
- content: TestRunSchema,
196
- })
197
-
198
- /**
199
- * A ticket took another ticket's baseline instead of running the tests
200
- * again: both worktrees started from the same run-branch commit, `base_sha`.
201
- */
202
- const BaselineReusedEntrySchema = z.object({
203
- ...ENTRY_FIELDS,
204
- kind: z.literal('baseline_reused'),
205
- content: z.object({
206
- from_ticket: z.number().int().positive(),
207
- base_sha: z.string().min(1),
208
- }),
209
- })
210
-
211
- /**
212
- * An agent turn was started, with its prompt word for word. A follow-up in a
213
- * fix loop names the session it went to in `follow_up_of`, and `prompt` holds
214
- * the follow-up message.
215
- */
216
- const AgentStartedEntrySchema = z.object({
217
- ...ENTRY_FIELDS,
218
- kind: z.literal('agent_started'),
219
- content: z.object({
220
- role: AgentRoleSchema,
221
- prompt: z.string(),
222
- follow_up_of: z.string().nullable().default(null),
223
- }),
224
- })
225
-
226
- /** The session an agent turn ran in; `null` in journals from before #363. */
227
- const SESSION_FIELDS = { session_id: z.string().nullable().default(null) }
228
-
229
- /**
230
- * An agent finished with a result that fits its role's schema. One option
231
- * per role: keep it in step with `RoleResultSchema` (a test checks every
232
- * role parses).
233
- */
234
- const AgentFinishedEntrySchema = z.object({
235
- ...ENTRY_FIELDS,
236
- kind: z.literal('agent_finished'),
237
- content: z.discriminatedUnion('role', [
238
- RoleResultSchema.options[0].extend(SESSION_FIELDS),
239
- RoleResultSchema.options[1].extend(SESSION_FIELDS),
240
- RoleResultSchema.options[2].extend(SESSION_FIELDS),
241
- RoleResultSchema.options[3].extend(SESSION_FIELDS),
242
- RoleResultSchema.options[4].extend(SESSION_FIELDS),
243
- RoleResultSchema.options[5].extend(SESSION_FIELDS),
244
- RoleResultSchema.options[6].extend(SESSION_FIELDS),
245
- RoleResultSchema.options[7].extend(SESSION_FIELDS),
246
- RoleResultSchema.options[8].extend(SESSION_FIELDS),
247
- ]),
248
- })
249
-
250
- /**
251
- * How an agent's turn failed:
252
- * - `agent`: the turn itself failed (an error result, a timeout).
253
- * - `result`: no structured output, or output that misfits the role's schema.
254
- * - `guard`: the after-turn check found a change the role may not make.
255
- * - `engine`: the engine's side failed (the SDK crashed, or a follow-up's
256
- * session is gone).
257
- *
258
- * The decision step counts the first three as failed tries; an engine
259
- * failure starts a fresh agent without using one.
260
- */
261
- export const AgentFailureSchema = z.enum(['agent', 'result', 'guard', 'engine'])
262
-
263
- export type AgentFailure = z.infer<typeof AgentFailureSchema>
264
-
265
- /** An agent's turn failed, journaled once per turn with how it failed. */
266
- const AgentFailedEntrySchema = z.object({
267
- ...ENTRY_FIELDS,
268
- kind: z.literal('agent_failed'),
269
- content: z.object({
270
- role: AgentRoleSchema,
271
- error: z.string(),
272
- failure: AgentFailureSchema.default('agent'),
273
- ...SESSION_FIELDS,
274
- }),
275
- })
276
-
277
- /** The launcher's summary of one agent turn's model session. */
278
- const AgentSessionEntrySchema = z.object({
279
- ...ENTRY_FIELDS,
280
- kind: z.literal('agent_session'),
281
- content: z.object({ role: AgentRoleSchema, session: AgentSessionSchema }),
282
- })
283
-
284
- /**
285
- * The engine closed an agent's session: nothing can send it a follow-up
286
- * anymore (its step's result was accepted, or its step ended another way).
287
- * The decision step never follows up a closed session; a fix round that
288
- * would have gone to it goes to a fresh agent.
289
- */
290
- const AgentSessionClosedEntrySchema = z.object({
291
- ...ENTRY_FIELDS,
292
- kind: z.literal('agent_session_closed'),
293
- content: z.object({ role: AgentRoleSchema, session_id: z.string() }),
294
- })
295
-
296
- /**
297
- * Shared `.git` files changed during an agent's turn by something the
298
- * engine can't attribute to the agent: config outside the ticket branch's
299
- * own section, `info/exclude`, or hooks, such as another agent's
300
- * `git push -u` in the same repo. The change is neither blamed on the agent
301
- * nor undone; this record only notes it.
302
- */
303
- const SharedGitChangedEntrySchema = z.object({
304
- ...ENTRY_FIELDS,
305
- kind: z.literal('shared_git_changed'),
306
- content: z.object({
307
- role: AgentRoleSchema,
308
- /** What changed, such as `the shared .git/config changed`. */
309
- changes: z.array(z.string()),
310
- }),
311
- })
312
-
313
- /**
314
- * The run stopped because going on was unsafe: the wrong credentials or
315
- * plan, the wrong model, or a foreign MCP server. A later `runEngine` on the
316
- * same journal picks the step up again.
317
- *
318
- * A `billing` stop (overage, or a billing error) sticks: the run never goes
319
- * on, however often the engine is started again on its journal.
320
- */
321
- const RunStoppedEntrySchema = z.object({
322
- ...ENTRY_FIELDS,
323
- kind: z.literal('run_stopped'),
324
- content: z.object({
325
- reason: z.string(),
326
- role: AgentRoleSchema.nullable().default(null),
327
- billing: z.boolean().default(false),
328
- /**
329
- * The same step was cut off by a crash `MAX_CRASHES` times in a row
330
- * on a run-level key: like a billing stop, it sticks.
331
- */
332
- crashed: z.boolean().default(false),
333
- }),
334
- })
335
-
336
- /**
337
- * The scheduler is about to carry out one step: an action it started, other
338
- * than a wait. `key` is the scheduler's key for it (a ticket's number,
339
- * `final`, `lens:<lens>`, `replies`, or `run`), and `step` its action type,
340
- * plus `:<role>` for an agent's turn. `first_seq` is the `step_started` seq
341
- * of this step's first try when a crash cut off an earlier try of it, else
342
- * `null`. `ticket` is the action's ticket, and `role` the agent's role.
343
- */
344
- const StepStartedEntrySchema = z.object({
345
- ...ENTRY_FIELDS,
346
- kind: z.literal('step_started'),
347
- content: z.object({
348
- key: z.string().min(1),
349
- step: z.string().min(1),
350
- first_seq: z.number().int().min(1).nullable().default(null),
351
- }),
352
- })
353
-
354
- /**
355
- * The step under `key` settled: its own records are in the journal, so it
356
- * is a checkpoint. Not written when the step threw.
357
- */
358
- const StepEndedEntrySchema = z.object({
359
- ...ENTRY_FIELDS,
360
- kind: z.literal('step_ended'),
361
- content: z.object({
362
- key: z.string().min(1),
363
- step: z.string().min(1),
364
- }),
365
- })
366
-
367
- /** One step a crash cut off: its `step_started` had no `step_ended`. */
368
- export const InterruptedStepSchema = z.object({
369
- key: z.string().min(1),
370
- step: z.string().min(1),
371
- ticket: z.number().int().positive().nullable(),
372
- role: z.string().nullable(),
373
- /** The seq of the cut-off step's `step_started`. */
374
- started_seq: z.number().int().min(1),
375
- /** That record's `first_seq`: the step's first try, if it was a redo. */
376
- first_seq: z.number().int().min(1).nullable(),
377
- })
378
-
379
- export type InterruptedStep = z.infer<typeof InterruptedStepSchema>
380
-
381
- /**
382
- * A restarted engine found steps a crash cut off, journaled once before its
383
- * first step. Each is taken again, an agent's turn in a fresh session.
384
- */
385
- const RunResumedEntrySchema = z.object({
386
- ...ENTRY_FIELDS,
387
- kind: z.literal('run_resumed'),
388
- content: z.object({ interrupted: z.array(InterruptedStepSchema) }),
389
- })
390
-
391
- /**
392
- * A plan window was used up (a rejected rate limit), so the whole run waits
393
- * until `until`: the window's reset plus a margin, or a default wait when the
394
- * reading named no reset. Written with `ticket: null`; the agent whose turn
395
- * hit the limit is `hit_ticket` and `hit_role`.
396
- */
397
- const LimitWaitStartedEntrySchema = z.object({
398
- ...ENTRY_FIELDS,
399
- kind: z.literal('limit_wait_started'),
400
- content: z.object({
401
- /** When the window resets, if the reading said. */
402
- resets_at: z.iso.datetime().nullable(),
403
- /** When the engine wakes and carries on. */
404
- until: z.iso.datetime(),
405
- /** The window, such as `five_hour`, `seven_day`, or `seven_day_opus`. */
406
- rate_limit_type: z.string().nullable(),
407
- hit_ticket: z.number().int().positive().nullable(),
408
- hit_role: AgentRoleSchema.nullable(),
409
- }),
410
- })
411
-
412
- /** The limit wait is over; the run carries on where it was cut off. */
413
- const LimitWaitEndedEntrySchema = z.object({
414
- ...ENTRY_FIELDS,
415
- kind: z.literal('limit_wait_ended'),
416
- content: z.object({ until: z.iso.datetime() }),
417
- })
418
-
419
- /** The plan windows a usage line guards: all-models weekly, and 5-hour. */
420
- export const UsageLineWindowSchema = z.enum(['seven_day', 'five_hour'])
421
-
422
- export type UsageLineWindow = z.infer<typeof UsageLineWindowSchema>
423
-
424
- /**
425
- * The newest plan-window reading was at or over its **usage line**, so the
426
- * whole run pauses until `until`: the window's reset plus a margin. The wait
427
- * ends sooner once the line is raised above `percent`.
428
- */
429
- const UsageLineWaitStartedEntrySchema = z.object({
430
- ...ENTRY_FIELDS,
431
- kind: z.literal('usage_line_wait_started'),
432
- content: z.object({
433
- window: UsageLineWindowSchema,
434
- /** The line, in percent of the window. */
435
- line: z.number(),
436
- /** The reading's fill level, in percent. */
437
- percent: z.number(),
438
- /** When the window resets. */
439
- resets_at: z.iso.datetime(),
440
- /** When the engine wakes and carries on, at the latest. */
441
- until: z.iso.datetime(),
442
- }),
443
- })
444
-
445
- /**
446
- * The usage-line wait is over: the window reset (`reset`), or the line was
447
- * raised above the reading (`line_raised`).
448
- */
449
- const UsageLineWaitEndedEntrySchema = z.object({
450
- ...ENTRY_FIELDS,
451
- kind: z.literal('usage_line_wait_ended'),
452
- content: z.object({
453
- until: z.iso.datetime(),
454
- reason: z.enum(['reset', 'line_raised']),
455
- }),
456
- })
457
-
458
- /**
459
- * The plan usage of one ticket (when it was pushed, or got stuck) or of the
460
- * whole run (when it ended): tokens from its agent sessions, and how far
461
- * each plan window moved. A retried ticket that finishes again gets another,
462
- * over all of its sessions: the latest is its whole usage.
463
- */
464
- const UsageRecordedEntrySchema = z.object({
465
- ...ENTRY_FIELDS,
466
- kind: z.literal('usage_recorded'),
467
- content: UsageRecordSchema,
468
- })
469
-
470
- const RedCheckEntrySchema = z.object({
471
- ...ENTRY_FIELDS,
472
- kind: z.literal('red_check'),
473
- content: RedCheckResultSchema.extend({ tests: TestRunSchema }),
474
- })
475
-
476
- /**
477
- * The commits the engine makes on a ticket: tests first (`red`), then code
478
- * (`green`), then one per review fix round (`fix`).
479
- */
480
- export const CommitStageSchema = z.enum(['red', 'green', 'fix'])
481
-
482
- export type CommitStage = z.infer<typeof CommitStageSchema>
483
-
484
- /** The leftover scan before an engine commit. Any hit blocks the commit. */
485
- const LeftoverScanEntrySchema = z.object({
486
- ...ENTRY_FIELDS,
487
- kind: z.literal('leftover_scan'),
488
- content: z.object({
489
- stage: CommitStageSchema,
490
- hits: z.array(LeftoverHitSchema),
491
- }),
492
- })
493
-
494
- const CommitMadeEntrySchema = z.object({
495
- ...ENTRY_FIELDS,
496
- kind: z.literal('commit_made'),
497
- content: z.object({
498
- stage: CommitStageSchema,
499
- sha: z.string().min(1),
500
- message: z.string(),
501
- files: z.array(z.string()),
502
- }),
503
- })
504
-
505
- /** Where the gates or the install ran: a ticket's worktree, or the run branch. */
506
- export const GateTargetSchema = z.enum(['ticket', 'run_branch'])
507
-
508
- export type GateTarget = z.infer<typeof GateTargetSchema>
509
-
510
- /**
511
- * The engine threw away every uncommitted change in a ticket's worktree, back
512
- * to `sha`, so a fresh test-writer starts clean after a bad test.
513
- */
514
- const WorktreeResetEntrySchema = z.object({
515
- ...ENTRY_FIELDS,
516
- kind: z.literal('worktree_reset'),
517
- content: z.object({ sha: z.string().min(1) }),
518
- })
519
-
520
- /**
521
- * The engine installed the dependencies from the lockfile, without changing
522
- * it, in a new ticket worktree or the run branch's checkout, before any agent
523
- * or gate ran there. `check` is `null` when there is no `package.json`, so
524
- * nothing to install. The run branch's record has no ticket.
525
- */
526
- const DependenciesInstalledEntrySchema = z.object({
527
- ...ENTRY_FIELDS,
528
- kind: z.literal('dependencies_installed'),
529
- content: z.object({
530
- target: GateTargetSchema,
531
- check: GateCheckSchema.nullable(),
532
- }),
533
- })
534
-
535
- const GatesRunEntrySchema = z.object({
536
- ...ENTRY_FIELDS,
537
- kind: z.literal('gates_run'),
538
- content: z.object({
539
- target: GateTargetSchema,
540
- ok: z.boolean(),
541
- checks: z.array(GateCheckSchema),
542
- }),
543
- })
544
-
545
- /** An approved ticket's commits, replayed onto the run branch (or not). */
546
- const TicketJoinedEntrySchema = z.object({
547
- ...ENTRY_FIELDS,
548
- kind: z.literal('ticket_joined'),
549
- content: z.discriminatedUnion('ok', [
550
- z.object({
551
- ok: z.literal(true),
552
- /** The new commits on the run branch, oldest first. */
553
- shas: z.array(z.string().min(1)),
554
- }),
555
- z.object({ ok: z.literal(false), error: z.string() }),
556
- ]),
557
- })
558
-
559
- /**
560
- * A ticket's join is about to replay its commits onto the run branch, which
561
- * stands at `run_branch_sha`. A join a crash cut off (no `ticket_joined`
562
- * after this) is redone from there: the run branch is reset to it first.
563
- */
564
- const JoinStartedEntrySchema = z.object({
565
- ...ENTRY_FIELDS,
566
- kind: z.literal('join_started'),
567
- content: z.object({ run_branch_sha: z.string().min(1) }),
568
- })
569
-
570
- /**
571
- * Why a joined ticket went back to be fixed on top of the run branch: its
572
- * commits clashed with it, or the gates failed after it joined.
573
- */
574
- export const RejoinCauseSchema = z.enum(['clash', 'join_gates'])
575
-
576
- export type RejoinCause = z.infer<typeof RejoinCauseSchema>
577
-
578
- /**
579
- * The engine put a ticket's whole change back on top of the run branch, as
580
- * uncommitted changes in its worktree, after a clash or failed gates after
581
- * joining. `base_sha` is the run branch commit it now starts from. `tests`
582
- * and `code` are the files that clashed (conflict markers left in them),
583
- * split by the config's test file patterns. `undone` are the run branch
584
- * commits the engine undid first (a join whose gates failed), and
585
- * `reinstall` says whether the worktree needs its install again.
586
- */
587
- const TicketRebasedEntrySchema = z.object({
588
- ...ENTRY_FIELDS,
589
- kind: z.literal('ticket_rebased'),
590
- content: z.object({
591
- cause: RejoinCauseSchema,
592
- base_sha: z.string().min(1),
593
- tests: z.array(z.string()),
594
- code: z.array(z.string()),
595
- undone: z.array(z.string()),
596
- /**
597
- * The dependency files (manifests, lockfiles) differ between the
598
- * worktree's old base and the new one, and the ticket's own change
599
- * touches no manifest: the worktree gets its frozen install again.
600
- * (A ticket that changes a manifest gets the install in its gates.)
601
- */
602
- reinstall: z.boolean().default(false),
603
- }),
604
- })
605
-
606
- /**
607
- * The engine removed these git worktrees at the end of a run. Their branches
608
- * and the journal are kept.
609
- */
610
- const WorktreesRemovedEntrySchema = z.object({
611
- ...ENTRY_FIELDS,
612
- kind: z.literal('worktrees_removed'),
613
- content: z.object({ paths: z.array(z.string().min(1)) }),
614
- })
615
-
616
- const RunBranchPushedEntrySchema = z.object({
617
- ...ENTRY_FIELDS,
618
- kind: z.literal('run_branch_pushed'),
619
- content: z.object({ branch: z.string(), sha: z.string() }),
620
- })
621
-
622
- /**
623
- * Why a ticket (or the final review) is stuck. A failed red check or gate is only stuck once its
624
- * fix loop reaches its cap, and a bad test only on its second bounce.
625
- */
626
- export const StuckReasonSchema = z.enum([
627
- 'agent_failed',
628
- 'red_check_failed',
629
- 'nothing_new_to_test',
630
- 'leftovers_found',
631
- 'gates_failed',
632
- 'bad_test',
633
- 'changes_requested',
634
- 'join_failed',
635
- 'join_gates_failed',
636
- 'install_failed',
637
- 'prepare_failed',
638
- 'setup_change_needed',
639
- 'crashed',
640
- ])
641
-
642
- export type StuckReason = z.infer<typeof StuckReasonSchema>
643
-
644
- const TicketStuckEntrySchema = z.object({
645
- ...ENTRY_FIELDS,
646
- kind: z.literal('ticket_stuck'),
647
- content: z.object({ reason: StuckReasonSchema, detail: z.string() }),
648
- })
649
-
650
- /** Why the whole run is stuck: it used up its run budget of tokens. */
651
- export const RunStuckReasonSchema = z.enum(['run_budget'])
652
-
653
- export type RunStuckReason = z.infer<typeof RunStuckReasonSchema>
654
-
655
- /**
656
- * The whole run is stuck (`ticket: null`): nothing new starts until the
657
- * spec owner replies `retry` (one more full run budget) or `stop`.
658
- */
659
- const RunStuckEntrySchema = z.object({
660
- ...ENTRY_FIELDS,
661
- kind: z.literal('run_stuck'),
662
- content: z.object({ reason: RunStuckReasonSchema, detail: z.string() }),
663
- })
664
-
665
- /**
666
- * The engine told the spec issue that a ticket (or, with `ticket: null`,
667
- * the stuck run, else the final review) is stuck, in its comment
668
- * `comment_id`, and now waits for the spec owner's reply.
669
- */
670
- const StuckReportedEntrySchema = z.object({
671
- ...ENTRY_FIELDS,
672
- kind: z.literal('stuck_reported'),
673
- content: z.object({
674
- comment_id: z.number().int(),
675
- body: z.string(),
676
- }),
677
- })
678
-
679
- /**
680
- * A comment the engine read on the spec issue while it waited for a reply,
681
- * word for word, whoever wrote it. Only the spec owner's count as replies.
682
- */
683
- const CommentReadEntrySchema = z.object({
684
- ...ENTRY_FIELDS,
685
- kind: z.literal('comment_read'),
686
- content: z.object({
687
- comment_id: z.number().int(),
688
- author: z.string(),
689
- body: z.string(),
690
- }),
691
- })
692
-
693
- /**
694
- * The one-word replies the spec owner can give to stuck work: `retry`,
695
- * `skip`, and `stop` for a ticket; `retry`, `stop`, and `ship` for the
696
- * final review.
697
- */
698
- export const ReplyWordSchema = z.enum(['retry', 'skip', 'stop', 'ship'])
699
-
700
- export type ReplyWord = z.infer<typeof ReplyWordSchema>
701
-
702
- /**
703
- * The engine took the spec owner's reply: `retry` or `skip` for `ticket`,
704
- * `stop` for the whole run, `retry` for the run stuck on its budget, or
705
- * `retry` or `ship` for the stuck final review (`ticket` is `null` for
706
- * these).
707
- */
708
- const ReplyReceivedEntrySchema = z.object({
709
- ...ENTRY_FIELDS,
710
- kind: z.literal('reply_received'),
711
- content: z.object({
712
- word: ReplyWordSchema,
713
- ticket: z.number().int().positive().nullable(),
714
- comment_id: z.number().int(),
715
- author: z.string(),
716
- }),
717
- })
718
-
719
- /**
720
- * Why the spec owner's reply could not be used: it named no ticket while
721
- * more than one is stuck, named a ticket that isn't stuck, or was `ship`
722
- * (the final review's word) while no final review is stuck, or was `skip`
723
- * for the final review, which can't be skipped.
724
- */
725
- export const ReplyProblemSchema = z.enum([
726
- 'no_ticket_named',
727
- 'not_stuck',
728
- 'nothing_stuck',
729
- 'ship_needs_final_review',
730
- 'skip_not_for_final_review',
731
- ])
732
-
733
- export type ReplyProblem = z.infer<typeof ReplyProblemSchema>
734
-
735
- /**
736
- * The spec owner's reply could not be used; the engine said why on the spec
737
- * issue, in its comment `answer_id`.
738
- */
739
- const ReplyIgnoredEntrySchema = z.object({
740
- ...ENTRY_FIELDS,
741
- kind: z.literal('reply_ignored'),
742
- content: z.object({
743
- comment_id: z.number().int(),
744
- reason: ReplyProblemSchema,
745
- answer_id: z.number().int().nullable(),
746
- }),
747
- })
748
-
749
- /**
750
- * How a `retry` went:
751
- * - `resume`: the ticket's text and labels are unchanged, so it picks up
752
- * where it stopped, with a fresh agent and fresh counts, keeping any
753
- * code the user changed in its worktree.
754
- * - `restart`: the ticket's text or labels changed, so its new copy (a
755
- * `ticket_snapshot` just before) is built from scratch, in its worktree
756
- * reset to the run branch's tip `base_sha`.
757
- * - `refused`: the changed ticket is not ready to build (`problems`); the
758
- * engine said so on the spec issue (`answer_id`), and it stays stuck.
759
- */
760
- const TicketRetriedEntrySchema = z.object({
761
- ...ENTRY_FIELDS,
762
- kind: z.literal('ticket_retried'),
763
- content: z.object({
764
- mode: z.enum(['resume', 'restart', 'refused']),
765
- base_sha: z.string().nullable(),
766
- problems: z.array(z.string()),
767
- answer_id: z.number().int().nullable(),
768
- }),
769
- })
770
-
771
- /**
772
- * A ticket left out of the run: the stuck ticket the owner skipped
773
- * (`because` is `null`), or one that waits on a skipped ticket. It stays
774
- * open, with a comment saying why.
775
- */
776
- const TicketSkippedEntrySchema = z.object({
777
- ...ENTRY_FIELDS,
778
- kind: z.literal('ticket_skipped'),
779
- content: z.object({
780
- because: z.number().int().positive().nullable(),
781
- }),
782
- })
783
-
784
- /**
785
- * A ticket whose work is already on the base branch (#484): its
786
- * test-writer answered `already_done`, and `shas` are the commits that did
787
- * the work. The ticket counts as done, not stuck, and tickets that wait on
788
- * it go on. The engine said so on the spec issue, in its comment
789
- * `comment_id`. The run's PR closes it; with no PR, `ticket_closed` follows.
790
- */
791
- const TicketAlreadyDoneEntrySchema = z.object({
792
- ...ENTRY_FIELDS,
793
- kind: z.literal('ticket_already_done'),
794
- content: z.object({
795
- shas: z.array(z.string().min(1)),
796
- comment_id: z.number().int(),
797
- }),
798
- })
799
-
800
- /**
801
- * The engine closed an already-done ticket itself, as the run opens no PR
802
- * to close it, after its comment `comment_id` on the ticket said why.
803
- */
804
- const TicketClosedEntrySchema = z.object({
805
- ...ENTRY_FIELDS,
806
- kind: z.literal('ticket_closed'),
807
- content: z.object({ comment_id: z.number().int() }),
808
- })
809
-
810
- /**
811
- * The owner replied `retry` to the stuck final review: its open fix round
812
- * starts over as round 1 with fresh fixers and fresh counts, keeping any
813
- * edits the owner made in the run branch's worktree.
814
- */
815
- const FinalReviewRetriedEntrySchema = z.object({
816
- ...ENTRY_FIELDS,
817
- kind: z.literal('final_review_retried'),
818
- content: z.object({}),
819
- })
820
-
821
- /**
822
- * A stuck ticket's join was undone on the run branch (its commits were
823
- * never pushed), so no other ticket builds on them.
824
- */
825
- const JoinUndoneEntrySchema = z.object({
826
- ...ENTRY_FIELDS,
827
- kind: z.literal('join_undone'),
828
- content: z.object({ shas: z.array(z.string()) }),
829
- })
830
-
831
- /** A changeset's bump: from the spec's `release:*` label, patch with none. */
832
- export const ChangesetBumpSchema = z.enum(['patch', 'minor', 'major', 'none'])
833
-
834
- export type ChangesetBump = z.infer<typeof ChangesetBumpSchema>
835
-
836
- /**
837
- * The engine committed the run's one changeset (#461) at `path` on the run
838
- * branch and pushed it (`sha` is the run branch's HEAD after). `packages`
839
- * are the ones it names. `path` is `null` when nothing was written: the
840
- * spec is `release:none` (#476), or the repo no longer had a changesets
841
- * config.
842
- */
843
- const ChangesetWrittenEntrySchema = z.object({
844
- ...ENTRY_FIELDS,
845
- kind: z.literal('changeset_written'),
846
- content: z.object({
847
- path: z.string().nullable(),
848
- bump: ChangesetBumpSchema,
849
- packages: z.array(z.string()),
850
- sha: z.string(),
851
- }),
852
- })
853
-
854
- const PullRequestOpenedEntrySchema = z.object({
855
- ...ENTRY_FIELDS,
856
- kind: z.literal('pull_request_opened'),
857
- content: z.object({
858
- number: z.number().int().positive(),
859
- url: z.string(),
860
- head: z.string(),
861
- base: z.string(),
862
- title: z.string(),
863
- body: z.string(),
864
- }),
865
- })
866
-
867
- /**
868
- * A final review round started: the run branch is reviewed from `from_sha`
869
- * (round 1: where the run branch started; later rounds: the previous
870
- * round's `head_sha`) to `head_sha`, its HEAD now. `lenses` are the lenses
871
- * due this round (every lens in round 1, then only those that had blocking
872
- * findings), `files` the files that diff changes, and `rules` the rule files
873
- * of the engine config, read by the engine word for word (`text` is `null`
874
- * for a file it could not read), for the rules lens. Written with
875
- * `ticket: null`.
876
- */
877
- const FinalReviewStartedEntrySchema = z.object({
878
- ...ENTRY_FIELDS,
879
- kind: z.literal('final_review_started'),
880
- content: z.object({
881
- round: z.number().int().min(1),
882
- from_sha: z.string().min(1),
883
- head_sha: z.string().min(1),
884
- lenses: z.array(LensNameSchema),
885
- files: z.array(z.string()).default([]),
886
- rules: z.array(
887
- z.object({ path: z.string(), text: z.string().nullable() })
888
- ),
889
- }),
890
- })
891
-
892
- /** A lens's reviewer is about to start, right before its `agent_started`. */
893
- const LensStartedEntrySchema = z.object({
894
- ...ENTRY_FIELDS,
895
- kind: z.literal('lens_started'),
896
- content: z.object({
897
- lens: LensNameSchema,
898
- round: z.number().int().min(1),
899
- }),
900
- })
901
-
902
- /**
903
- * A lens's reviewer finished, right after its `agent_finished`: its findings
904
- * counted by severity. Not written for a failed turn.
905
- */
906
- const LensFinishedEntrySchema = z.object({
907
- ...ENTRY_FIELDS,
908
- kind: z.literal('lens_finished'),
909
- content: z.object({
910
- lens: LensNameSchema,
911
- round: z.number().int().min(1),
912
- findings: z.object({
913
- blocker: z.number().int().min(0),
914
- should_fix: z.number().int().min(0),
915
- nit: z.number().int().min(0),
916
- }),
917
- }),
918
- })
919
-
920
- /** A final review fix round starts, before its first fixer. */
921
- const FinalReviewFixingEntrySchema = z.object({
922
- ...ENTRY_FIELDS,
923
- kind: z.literal('final_review_fixing'),
924
- content: z.object({ round: z.number().int().min(1) }),
925
- })
926
-
927
- /** The final review is stuck: the PR waits for a person's reply (#366). */
928
- const FinalReviewStuckEntrySchema = z.object({
929
- ...ENTRY_FIELDS,
930
- kind: z.literal('final_review_stuck'),
931
- content: z.object({ reason: StuckReasonSchema, detail: z.string() }),
932
- })
933
-
934
- /** Every lens due in the latest round approved; the PR opens next. */
935
- const FinalReviewPassedEntrySchema = z.object({
936
- ...ENTRY_FIELDS,
937
- kind: z.literal('final_review_passed'),
938
- content: z.object({}),
939
- })
940
-
941
- /**
942
- * The person replied `ship` to the stuck final review: the PR opens with the
943
- * findings still open listed at the top. Appended by the reply reader (#366)
944
- * through `shipFinalReview`.
945
- */
946
- const FinalReviewShippedEntrySchema = z.object({
947
- ...ENTRY_FIELDS,
948
- kind: z.literal('final_review_shipped'),
949
- content: z.object({}),
950
- })
951
-
952
- /**
953
- * The engine searched memory at a **recall point**: the vaults it searched
954
- * (each with how it went and how many it found), and the memories it will
955
- * show, merged by score, at most `MAX_MEMORIES_PER_RECALL`, each with its
956
- * vault and score. `key` names the moment (such as `ticket:11`), so each is
957
- * searched once. `ticket` is the ticket's, or `null` for the run's start
958
- * and the final review.
959
- */
960
- const MemoryRecalledEntrySchema = z.object({
961
- ...ENTRY_FIELDS,
962
- kind: z.literal('memory_recalled'),
963
- content: z.object({
964
- point: RecallPointSchema,
965
- key: z.string().min(1),
966
- query: z.string(),
967
- vaults: z.array(VaultSearchSchema),
968
- memories: z.array(RecalledMemorySchema),
969
- }),
970
- })
971
-
972
- /**
973
- * The learner's proposed memories were saved (or refused, or failed), each
974
- * with its vault, what became of it, and the similar memory the engine
975
- * found first; then the helped / didn't-help feedback on each memory shown
976
- * in the run. Written once per run, with `ticket: null`.
977
- */
978
- const MemoriesSavedEntrySchema = z.object({
979
- ...ENTRY_FIELDS,
980
- kind: z.literal('memories_saved'),
981
- content: z.object({
982
- saves: z.array(MemorySaveSchema),
983
- feedback: z.array(MemoryFeedbackSchema),
984
- }),
985
- })
986
-
987
- /**
988
- * The engine is about to make one MuninnDB write of `save_memories` (#369):
989
- * a save (`update_id` names the similar memory it updates, `muninn_evolve`;
990
- * `null` adds a new one, `muninn_remember` with `op_id`) or a feedback on a
991
- * shown memory. `write_key` names it within its step: `save:<op_id>` or
992
- * `feedback:<vault>:<id>`. A redo of the step repeats a save started but
993
- * not done the same way, and never sends such a feedback again.
994
- */
995
- const MemoryWriteStartedEntrySchema = z.object({
996
- ...ENTRY_FIELDS,
997
- kind: z.literal('memory_write_started'),
998
- content: z.discriminatedUnion('what', [
999
- z.object({
1000
- write_key: z.string().min(1),
1001
- what: z.literal('save'),
1002
- vault: z.string().min(1),
1003
- concept: z.string(),
1004
- op_id: z.string().min(1),
1005
- update_id: z.string().nullable(),
1006
- similar: MemorySaveSchema.shape.similar,
1007
- }),
1008
- z.object({
1009
- write_key: z.string().min(1),
1010
- what: z.literal('feedback'),
1011
- vault: z.string().min(1),
1012
- id: z.string().min(1),
1013
- useful: z.boolean(),
1014
- }),
1015
- ]),
1016
- })
1017
-
1018
- /**
1019
- * One MuninnDB write of `save_memories` settled (or a save failed before
1020
- * its write): its outcome, which a redo of the step reuses as it is. Its
1021
- * step's `memories_saved` lists them all.
1022
- */
1023
- const MemoryWriteDoneEntrySchema = z.object({
1024
- ...ENTRY_FIELDS,
1025
- kind: z.literal('memory_write_done'),
1026
- content: z.discriminatedUnion('what', [
1027
- z.object({
1028
- write_key: z.string().min(1),
1029
- what: z.literal('save'),
1030
- save: MemorySaveSchema,
1031
- }),
1032
- z.object({
1033
- write_key: z.string().min(1),
1034
- what: z.literal('feedback'),
1035
- feedback: MemoryFeedbackSchema,
1036
- }),
1037
- ]),
1038
- })
1039
-
1040
- /** The learner never gave a usable answer; the run ends without it. */
1041
- const LearningSkippedEntrySchema = z.object({
1042
- ...ENTRY_FIELDS,
1043
- kind: z.literal('learning_skipped'),
1044
- content: z.object({ reason: z.string() }),
1045
- })
1046
-
1047
1
  /**
1048
- * With no PR to list them in, the new memories went on the spec issue in
1049
- * the engine's comment `comment_id`.
1050
- */
1051
- const MemoriesReportedEntrySchema = z.object({
1052
- ...ENTRY_FIELDS,
1053
- kind: z.literal('memories_reported'),
1054
- content: z.object({
1055
- comment_id: z.number().int(),
1056
- count: z.number().int().min(0),
1057
- }),
1058
- })
1059
-
1060
- /** The engine asked Jev, in shadow mode, with its own fixed choice beside. */
1061
- const JevAskedEntrySchema = z.object({
1062
- ...ENTRY_FIELDS,
1063
- kind: z.literal('jev_asked'),
1064
- content: z.object({
1065
- job: JevJobSchema,
1066
- request: JevRequestSchema,
1067
- fixed: JevFixedSchema,
1068
- }),
1069
- })
1070
-
1071
- /** Jev's answers to the `jev_asked` record at `asked_seq`. The engine ignores them. */
1072
- const JevAnsweredEntrySchema = z.object({
1073
- ...ENTRY_FIELDS,
1074
- kind: z.literal('jev_answered'),
1075
- content: z.object({
1076
- job: JevJobSchema,
1077
- asked_seq: z.number().int().min(1),
1078
- answers: z.record(z.string(), JevAnswerSchema),
1079
- /** How long the call took. */
1080
- ms: z.number().min(0),
1081
- }),
1082
- })
1083
-
1084
- /** The Jev call at `asked_seq` gave no answers. The run goes on regardless. */
1085
- const JevFailedEntrySchema = z.object({
1086
- ...ENTRY_FIELDS,
1087
- kind: z.literal('jev_failed'),
1088
- content: z.object({
1089
- job: JevJobSchema,
1090
- asked_seq: z.number().int().min(1),
1091
- reason: JevFailureReasonSchema,
1092
- error: z.string(),
1093
- ms: z.number().min(0),
1094
- }),
1095
- })
1096
-
1097
- /**
1098
- * What an agent message did when it was sent:
1099
- * - `queued`: it waits for its recipients' next tool calls.
1100
- * - `not_delivered`: nobody can get it (the receiver's ticket is over, or
1101
- * `all` found no one); it stays in the journal.
1102
- * - `refused`: it broke a rule (a reviewer, a bad address, the cap).
1103
- */
1104
- export const AgentMessageStatusSchema = z.enum([
1105
- 'queued',
1106
- 'not_delivered',
1107
- 'refused',
1108
- ])
1109
-
1110
- export type AgentMessageStatus = z.infer<typeof AgentMessageStatusSchema>
1111
-
1112
- /**
1113
- * One agent message, word for word, as it was sent. Addresses look like
1114
- * `implementer#11`: a role and a ticket.
1115
- */
1116
- export const AgentMessageSchema = z.object({
1117
- /** `msg-<n>`: n is 1 + the earlier `agent_message` records in the journal. */
1118
- id: z.string().min(1),
1119
- /** The sender's address. */
1120
- from: z.string(),
1121
- /** What the sender asked for: an address, or `all`. */
1122
- to: z.string(),
1123
- text: z.string(),
1124
- status: AgentMessageStatusSchema,
1125
- /** The addresses it waits for; empty unless queued. */
1126
- recipients: z.array(z.string()),
1127
- /** Why it was refused or not delivered; `null` when queued. */
1128
- reason: z.string().nullable(),
1129
- })
1130
-
1131
- export type AgentMessage = z.infer<typeof AgentMessageSchema>
1132
-
1133
- /** An agent sent a message. `ticket` and `role` are the sender's. */
1134
- const AgentMessageEntrySchema = z.object({
1135
- ...ENTRY_FIELDS,
1136
- kind: z.literal('agent_message'),
1137
- content: AgentMessageSchema,
1138
- })
1139
-
1140
- /** Messages handed to their receiver at one tool call, word for word. */
1141
- export const AgentMessageDeliveredSchema = z.object({
1142
- /** The receiver's address. */
1143
- to: z.string(),
1144
- /** The ids of the messages handed over together. */
1145
- ids: z.array(z.string()),
1146
- /** The tool call they rode on. */
1147
- tool_name: z.string().nullable(),
1148
- /** The additional context the agent got, word for word. */
1149
- text: z.string(),
1150
- })
1151
-
1152
- export type AgentMessageDelivered = z.infer<typeof AgentMessageDeliveredSchema>
1153
-
1154
- /**
1155
- * Agent messages reached their receiver. `ticket` and `role` are the
1156
- * receiver's; the record's time is when it saw them.
1157
- */
1158
- const AgentMessageDeliveredEntrySchema = z.object({
1159
- ...ENTRY_FIELDS,
1160
- kind: z.literal('agent_message_delivered'),
1161
- content: AgentMessageDeliveredSchema,
1162
- })
1163
-
1164
- /**
1165
- * What a caller hands the journal to append: a kind, its content, and who it
1166
- * is about. The journal adds `seq` and `time`.
1167
- *
1168
- * Later tickets add kinds here.
1169
- */
1170
- export const JournalEntrySchema = z.discriminatedUnion('kind', [
1171
- RunStartedEntrySchema,
1172
- IntakeReadEntrySchema,
1173
- IntakeRefusedEntrySchema,
1174
- NothingToDoEntrySchema,
1175
- SpecSnapshotEntrySchema,
1176
- TicketSnapshotEntrySchema,
1177
- RunBranchCreatedEntrySchema,
1178
- TicketWorktreeCreatedEntrySchema,
1179
- BaselinePreparedEntrySchema,
1180
- PrepareMadeEntrySchema,
1181
- BaselineTestsEntrySchema,
1182
- BaselineReusedEntrySchema,
1183
- AgentStartedEntrySchema,
1184
- AgentFinishedEntrySchema,
1185
- AgentFailedEntrySchema,
1186
- RedCheckEntrySchema,
1187
- LeftoverScanEntrySchema,
1188
- CommitMadeEntrySchema,
1189
- WorktreeResetEntrySchema,
1190
- DependenciesInstalledEntrySchema,
1191
- GatesRunEntrySchema,
1192
- TicketJoinedEntrySchema,
1193
- TicketRebasedEntrySchema,
1194
- RunBranchPushedEntrySchema,
1195
- TicketStuckEntrySchema,
1196
- RunStuckEntrySchema,
1197
- ChangesetWrittenEntrySchema,
1198
- PullRequestOpenedEntrySchema,
1199
- JevAskedEntrySchema,
1200
- JevAnsweredEntrySchema,
1201
- JevFailedEntrySchema,
1202
- AgentSessionEntrySchema,
1203
- AgentSessionClosedEntrySchema,
1204
- SharedGitChangedEntrySchema,
1205
- RunStoppedEntrySchema,
1206
- LimitWaitStartedEntrySchema,
1207
- LimitWaitEndedEntrySchema,
1208
- UsageLineWaitStartedEntrySchema,
1209
- UsageLineWaitEndedEntrySchema,
1210
- UsageRecordedEntrySchema,
1211
- WorktreesRemovedEntrySchema,
1212
- AgentMessageEntrySchema,
1213
- AgentMessageDeliveredEntrySchema,
1214
- FinalReviewStartedEntrySchema,
1215
- LensStartedEntrySchema,
1216
- LensFinishedEntrySchema,
1217
- FinalReviewFixingEntrySchema,
1218
- FinalReviewStuckEntrySchema,
1219
- FinalReviewPassedEntrySchema,
1220
- FinalReviewShippedEntrySchema,
1221
- StuckReportedEntrySchema,
1222
- CommentReadEntrySchema,
1223
- ReplyReceivedEntrySchema,
1224
- ReplyIgnoredEntrySchema,
1225
- TicketRetriedEntrySchema,
1226
- TicketSkippedEntrySchema,
1227
- TicketAlreadyDoneEntrySchema,
1228
- TicketClosedEntrySchema,
1229
- JoinUndoneEntrySchema,
1230
- FinalReviewRetriedEntrySchema,
1231
- MemoryRecalledEntrySchema,
1232
- MemoryWriteStartedEntrySchema,
1233
- MemoryWriteDoneEntrySchema,
1234
- MemoriesSavedEntrySchema,
1235
- LearningSkippedEntrySchema,
1236
- MemoriesReportedEntrySchema,
1237
- StepStartedEntrySchema,
1238
- StepEndedEntrySchema,
1239
- RunResumedEntrySchema,
1240
- JoinStartedEntrySchema,
1241
- EngineResumedEntrySchema,
1242
- ])
1243
-
1244
- /** A journal entry as callers write it; schema defaults fill the rest. */
1245
- export type JournalEntry = z.input<typeof JournalEntrySchema>
1246
-
1247
- /** One line of a run's journal. */
1248
- export const JournalRecordSchema = z.discriminatedUnion('kind', [
1249
- RunStartedEntrySchema.extend(STAMP_FIELDS),
1250
- IntakeReadEntrySchema.extend(STAMP_FIELDS),
1251
- IntakeRefusedEntrySchema.extend(STAMP_FIELDS),
1252
- NothingToDoEntrySchema.extend(STAMP_FIELDS),
1253
- SpecSnapshotEntrySchema.extend(STAMP_FIELDS),
1254
- TicketSnapshotEntrySchema.extend(STAMP_FIELDS),
1255
- RunBranchCreatedEntrySchema.extend(STAMP_FIELDS),
1256
- TicketWorktreeCreatedEntrySchema.extend(STAMP_FIELDS),
1257
- BaselinePreparedEntrySchema.extend(STAMP_FIELDS),
1258
- PrepareMadeEntrySchema.extend(STAMP_FIELDS),
1259
- BaselineTestsEntrySchema.extend(STAMP_FIELDS),
1260
- BaselineReusedEntrySchema.extend(STAMP_FIELDS),
1261
- AgentStartedEntrySchema.extend(STAMP_FIELDS),
1262
- AgentFinishedEntrySchema.extend(STAMP_FIELDS),
1263
- AgentFailedEntrySchema.extend(STAMP_FIELDS),
1264
- RedCheckEntrySchema.extend(STAMP_FIELDS),
1265
- LeftoverScanEntrySchema.extend(STAMP_FIELDS),
1266
- CommitMadeEntrySchema.extend(STAMP_FIELDS),
1267
- WorktreeResetEntrySchema.extend(STAMP_FIELDS),
1268
- DependenciesInstalledEntrySchema.extend(STAMP_FIELDS),
1269
- GatesRunEntrySchema.extend(STAMP_FIELDS),
1270
- TicketJoinedEntrySchema.extend(STAMP_FIELDS),
1271
- TicketRebasedEntrySchema.extend(STAMP_FIELDS),
1272
- RunBranchPushedEntrySchema.extend(STAMP_FIELDS),
1273
- TicketStuckEntrySchema.extend(STAMP_FIELDS),
1274
- RunStuckEntrySchema.extend(STAMP_FIELDS),
1275
- ChangesetWrittenEntrySchema.extend(STAMP_FIELDS),
1276
- PullRequestOpenedEntrySchema.extend(STAMP_FIELDS),
1277
- JevAskedEntrySchema.extend(STAMP_FIELDS),
1278
- JevAnsweredEntrySchema.extend(STAMP_FIELDS),
1279
- JevFailedEntrySchema.extend(STAMP_FIELDS),
1280
- AgentSessionEntrySchema.extend(STAMP_FIELDS),
1281
- AgentSessionClosedEntrySchema.extend(STAMP_FIELDS),
1282
- SharedGitChangedEntrySchema.extend(STAMP_FIELDS),
1283
- RunStoppedEntrySchema.extend(STAMP_FIELDS),
1284
- LimitWaitStartedEntrySchema.extend(STAMP_FIELDS),
1285
- LimitWaitEndedEntrySchema.extend(STAMP_FIELDS),
1286
- UsageLineWaitStartedEntrySchema.extend(STAMP_FIELDS),
1287
- UsageLineWaitEndedEntrySchema.extend(STAMP_FIELDS),
1288
- UsageRecordedEntrySchema.extend(STAMP_FIELDS),
1289
- WorktreesRemovedEntrySchema.extend(STAMP_FIELDS),
1290
- AgentMessageEntrySchema.extend(STAMP_FIELDS),
1291
- AgentMessageDeliveredEntrySchema.extend(STAMP_FIELDS),
1292
- FinalReviewStartedEntrySchema.extend(STAMP_FIELDS),
1293
- LensStartedEntrySchema.extend(STAMP_FIELDS),
1294
- LensFinishedEntrySchema.extend(STAMP_FIELDS),
1295
- FinalReviewFixingEntrySchema.extend(STAMP_FIELDS),
1296
- FinalReviewStuckEntrySchema.extend(STAMP_FIELDS),
1297
- FinalReviewPassedEntrySchema.extend(STAMP_FIELDS),
1298
- FinalReviewShippedEntrySchema.extend(STAMP_FIELDS),
1299
- StuckReportedEntrySchema.extend(STAMP_FIELDS),
1300
- CommentReadEntrySchema.extend(STAMP_FIELDS),
1301
- ReplyReceivedEntrySchema.extend(STAMP_FIELDS),
1302
- ReplyIgnoredEntrySchema.extend(STAMP_FIELDS),
1303
- TicketRetriedEntrySchema.extend(STAMP_FIELDS),
1304
- TicketSkippedEntrySchema.extend(STAMP_FIELDS),
1305
- TicketAlreadyDoneEntrySchema.extend(STAMP_FIELDS),
1306
- TicketClosedEntrySchema.extend(STAMP_FIELDS),
1307
- JoinUndoneEntrySchema.extend(STAMP_FIELDS),
1308
- FinalReviewRetriedEntrySchema.extend(STAMP_FIELDS),
1309
- MemoryRecalledEntrySchema.extend(STAMP_FIELDS),
1310
- MemoryWriteStartedEntrySchema.extend(STAMP_FIELDS),
1311
- MemoryWriteDoneEntrySchema.extend(STAMP_FIELDS),
1312
- MemoriesSavedEntrySchema.extend(STAMP_FIELDS),
1313
- LearningSkippedEntrySchema.extend(STAMP_FIELDS),
1314
- MemoriesReportedEntrySchema.extend(STAMP_FIELDS),
1315
- StepStartedEntrySchema.extend(STAMP_FIELDS),
1316
- StepEndedEntrySchema.extend(STAMP_FIELDS),
1317
- RunResumedEntrySchema.extend(STAMP_FIELDS),
1318
- JoinStartedEntrySchema.extend(STAMP_FIELDS),
1319
- EngineResumedEntrySchema.extend(STAMP_FIELDS),
1320
- ])
1321
-
1322
- export type JournalRecord = z.infer<typeof JournalRecordSchema>
1323
-
1324
- /** Every record kind the journal knows so far. */
1325
- export const JournalKindSchema = z.enum([
1326
- 'run_started',
1327
- 'intake_read',
1328
- 'intake_refused',
1329
- 'nothing_to_do',
1330
- 'spec_snapshot',
1331
- 'ticket_snapshot',
1332
- 'run_branch_created',
1333
- 'ticket_worktree_created',
1334
- 'baseline_prepared',
1335
- 'prepare_made',
1336
- 'baseline_tests',
1337
- 'baseline_reused',
1338
- 'agent_started',
1339
- 'agent_finished',
1340
- 'agent_failed',
1341
- 'red_check',
1342
- 'leftover_scan',
1343
- 'commit_made',
1344
- 'worktree_reset',
1345
- 'dependencies_installed',
1346
- 'gates_run',
1347
- 'ticket_joined',
1348
- 'ticket_rebased',
1349
- 'run_branch_pushed',
1350
- 'ticket_stuck',
1351
- 'run_stuck',
1352
- 'changeset_written',
1353
- 'pull_request_opened',
1354
- 'jev_asked',
1355
- 'jev_answered',
1356
- 'jev_failed',
1357
- 'agent_session',
1358
- 'agent_session_closed',
1359
- 'shared_git_changed',
1360
- 'run_stopped',
1361
- 'limit_wait_started',
1362
- 'limit_wait_ended',
1363
- 'usage_line_wait_started',
1364
- 'usage_line_wait_ended',
1365
- 'usage_recorded',
1366
- 'worktrees_removed',
1367
- 'agent_message',
1368
- 'agent_message_delivered',
1369
- 'final_review_started',
1370
- 'lens_started',
1371
- 'lens_finished',
1372
- 'final_review_fixing',
1373
- 'final_review_stuck',
1374
- 'final_review_passed',
1375
- 'final_review_shipped',
1376
- 'stuck_reported',
1377
- 'comment_read',
1378
- 'reply_received',
1379
- 'reply_ignored',
1380
- 'ticket_retried',
1381
- 'ticket_skipped',
1382
- 'ticket_already_done',
1383
- 'ticket_closed',
1384
- 'join_undone',
1385
- 'final_review_retried',
1386
- 'memory_recalled',
1387
- 'memory_write_started',
1388
- 'memory_write_done',
1389
- 'memories_saved',
1390
- 'learning_skipped',
1391
- 'memories_reported',
1392
- 'step_started',
1393
- 'step_ended',
1394
- 'run_resumed',
1395
- 'join_started',
1396
- 'engine_resumed',
1397
- ])
1398
-
1399
- export type JournalKind = z.infer<typeof JournalKindSchema>
1400
-
1401
- export const JOURNAL_KINDS = JournalKindSchema.options
2
+ * The journal's record kinds and their content, as Zod schemas. The union a
3
+ * caller appends (`JournalEntrySchema`), the union of a journal line
4
+ * (`JournalRecordSchema`), and the list of kinds (`JournalKindSchema`) live in
5
+ * their own modules; this one re-exports them, and the small schemas the
6
+ * entries share.
7
+ */
8
+ export { JournalEntrySchema, type JournalEntry } from './journal-entry-schema'
9
+ export {
10
+ JOURNAL_KINDS,
11
+ JournalKindSchema,
12
+ type JournalKind,
13
+ } from './journal-kinds'
14
+ export {
15
+ JournalRecordSchema,
16
+ type JournalRecord,
17
+ } from './journal-record-schema'
18
+
19
+ export { AgentFailureSchema, type AgentFailure } from './agent-entries'
20
+ export {
21
+ AgentMessageDeliveredSchema,
22
+ AgentMessageSchema,
23
+ AgentMessageStatusSchema,
24
+ type AgentMessage,
25
+ type AgentMessageDelivered,
26
+ type AgentMessageStatus,
27
+ } from './agent-message-entries'
28
+ export { CommitStageSchema, type CommitStage } from './commit-entries'
29
+ export { GateTargetSchema, type GateTarget } from './gate-entries'
30
+ export { LabelFailureSchema, type LabelFailure } from './intake-entries'
31
+ export { RejoinCauseSchema, type RejoinCause } from './join-entries'
32
+ export { UsageLineWindowSchema, type UsageLineWindow } from './limit-entries'
33
+ export { ChangesetBumpSchema, type ChangesetBump } from './pull-request-entries'
34
+ export { InterruptedStepSchema, type InterruptedStep } from './run-entries'
35
+ export {
36
+ ReplyProblemSchema,
37
+ ReplyWordSchema,
38
+ RunStuckReasonSchema,
39
+ StuckReasonSchema,
40
+ type ReplyProblem,
41
+ type ReplyWord,
42
+ type RunStuckReason,
43
+ type StuckReason,
44
+ } from './stuck-entries'