@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.
- package/CHANGELOG.md +76 -0
- package/README.md +7 -2
- package/board/client/board-look.ts +31 -1
- package/board/client/board-panel-parts.tsx +150 -0
- package/board/client/board-panel-stages.ts +99 -0
- package/board/client/board-panel-styles.ts +223 -0
- package/board/client/board-panel.tsx +77 -1275
- package/board/client/engine-life.ts +48 -0
- package/board/client/final-review-stack.tsx +144 -0
- package/board/client/heartbeat.tsx +61 -0
- package/board/client/helper-lines.tsx +69 -0
- package/board/client/live-feed.tsx +86 -0
- package/board/client/live-line.ts +73 -0
- package/board/client/model-line.tsx +178 -0
- package/board/client/needs-you-section.tsx +133 -0
- package/board/client/one-line.tsx +193 -0
- package/board/client/repo-wait-banner.tsx +69 -0
- package/board/client/run-footer.tsx +68 -0
- package/board/client/run-header.tsx +189 -0
- package/board/client/run-picker.tsx +98 -0
- package/board/client/status-bar.tsx +131 -0
- package/board/client/step-dots.tsx +127 -0
- package/board/client/stuck-actions.tsx +269 -0
- package/board/client/ticket-card-view.tsx +238 -0
- package/board/client/ticket-detail.tsx +87 -0
- package/board/client/ticket-stack.tsx +119 -0
- package/board/client/ticket-wait.ts +188 -0
- package/board/client/timeline-rows.tsx +41 -14
- package/board/client/usage-line.tsx +51 -0
- package/board/client/wait-line.tsx +39 -0
- package/board/index.client.tsx +1 -1
- package/board/index.server.ts +7 -1
- package/board/package.json +1 -1
- package/board/server/board-panel-state-helpers.ts +67 -0
- package/board/server/board-server-check.ts +294 -0
- package/board/server/board-server-engine.ts +129 -0
- package/board/server/board-server-events.ts +134 -0
- package/board/server/board-server-read.ts +190 -0
- package/board/server/board-server-resume.ts +164 -0
- package/board/server/board-server-start.ts +174 -0
- package/board/server/board-server-store.ts +281 -0
- package/board/server/board-server-types.ts +114 -0
- package/board/server/board-server-util.ts +4 -0
- package/board/server/board-server.ts +52 -943
- package/board/server/board-vocabulary-engine.ts +144 -0
- package/board/server/board-vocabulary-review.ts +115 -0
- package/board/server/board-vocabulary-run.ts +145 -0
- package/board/server/board-vocabulary-shapes.ts +153 -0
- package/board/server/board-vocabulary.ts +20 -375
- package/board/server/current-step-panel-helpers.ts +108 -0
- package/board/server/describe-record.ts +403 -0
- package/board/server/engine-launch.ts +20 -3
- package/board/server/engine-restart-helpers.ts +105 -0
- package/board/server/engine-watch.ts +45 -5
- package/board/server/journal-rebuild-helpers.ts +169 -0
- package/board/server/live-file.ts +130 -0
- package/board/server/luca-version.ts +1 -1
- package/board/server/make-rows.ts +14 -629
- package/board/server/record-texts.ts +350 -0
- package/board/server/reduce-board-agent-start.ts +224 -0
- package/board/server/reduce-board-agents.ts +160 -0
- package/board/server/reduce-board-counters.ts +138 -0
- package/board/server/reduce-board-create.ts +148 -0
- package/board/server/reduce-board-final-review.ts +174 -0
- package/board/server/reduce-board-needs-you.ts +283 -0
- package/board/server/reduce-board-reasons.ts +59 -0
- package/board/server/reduce-board-run.ts +255 -0
- package/board/server/reduce-board-settle.ts +88 -0
- package/board/server/reduce-board-steps.ts +226 -0
- package/board/server/reduce-board-text.ts +139 -0
- package/board/server/reduce-board-ticket-checks.ts +168 -0
- package/board/server/reduce-board-ticket-join.ts +144 -0
- package/board/server/reduce-board-ticket-start.ts +132 -0
- package/board/server/reduce-board-update.ts +117 -0
- package/board/server/reduce-board-usage.ts +247 -0
- package/board/server/reduce-board.ts +100 -1917
- package/board/server/reply-post.ts +407 -0
- package/board/server/run-registry.ts +8 -4
- package/board/server/ticket-stages-panel-helpers.ts +296 -0
- package/board/shared/board-rows.ts +9 -0
- package/board/shared/board-rpc.ts +42 -0
- package/board/shared/board-state-counts.ts +77 -0
- package/board/shared/board-state-live.ts +99 -0
- package/board/shared/board-state-review.ts +59 -0
- package/board/shared/board-state-run.ts +236 -0
- package/board/shared/board-state-ticket.ts +257 -0
- package/board/shared/board-state-usage.ts +107 -0
- package/board/shared/board-state.ts +97 -567
- package/board/shared/reply-actions.ts +207 -0
- package/engine/agents/agent-launcher.ts +27 -4
- package/engine/agents/claude-launcher-helpers.ts +233 -0
- package/engine/agents/claude-launcher.ts +28 -669
- package/engine/agents/claude-messages.ts +212 -0
- package/engine/agents/claude-options.ts +43 -8
- package/engine/agents/common-instructions.ts +138 -0
- package/engine/agents/input-channel.ts +36 -0
- package/engine/agents/launch-paths.ts +29 -0
- package/engine/agents/launch-session.ts +227 -0
- package/engine/agents/learner-instructions.ts +31 -0
- package/engine/agents/open-session.ts +210 -0
- package/engine/agents/prompt-sections.ts +95 -0
- package/engine/agents/rejoin-prompts.ts +135 -0
- package/engine/agents/reviewer-instructions.ts +99 -0
- package/engine/agents/role-instructions.ts +31 -244
- package/engine/agents/role-prompts.ts +39 -109
- package/engine/agents/role-results.ts +106 -7
- package/engine/agents/scripted-launcher.ts +21 -6
- package/engine/agents/session-pool.ts +124 -0
- package/engine/agents/turn-progress.ts +283 -0
- package/engine/agents/writer-instructions.ts +151 -0
- package/engine/cli/computer-adapters-real.ts +15 -3
- package/engine/cli/computer-adapters.ts +2 -0
- package/engine/cli/computer-checks.ts +87 -4
- package/engine/cli/config-reload-text.ts +39 -0
- package/engine/cli/decision-model-setup.ts +70 -0
- package/engine/cli/doctor-command.ts +1 -0
- package/engine/cli/doctor.ts +21 -3
- package/engine/cli/going-runs.ts +192 -36
- package/engine/cli/init-command.ts +1 -0
- package/engine/cli/init.ts +23 -1
- package/engine/cli/live-runs.ts +73 -0
- package/engine/cli/luca-run.ts +42 -7
- package/engine/cli/luca-skills.ts +183 -0
- package/engine/cli/luca.ts +8 -1
- package/engine/cli/models-command.ts +119 -0
- package/engine/cli/read-run.ts +81 -0
- package/engine/cli/run-args.ts +33 -6
- package/engine/cli/run-demo.ts +143 -0
- package/engine/cli/run-end.ts +184 -0
- package/engine/cli/run-modes-helpers.ts +81 -0
- package/engine/cli/run-modes.ts +62 -439
- package/engine/cli/setup.ts +5 -48
- package/engine/cli/unfinished-runs.ts +122 -0
- package/engine/cli/upgrade-command.ts +212 -30
- package/engine/cli/upgrade-finish.ts +149 -0
- package/engine/cli/upgrade.ts +112 -71
- package/engine/config/config-fields.ts +127 -0
- package/engine/config/config-reload.ts +250 -0
- package/engine/config/engine-config-schema.ts +235 -0
- package/engine/config/engine-config.ts +72 -142
- package/engine/config/test-commands.ts +102 -0
- package/engine/core/agent-guards-helpers.ts +84 -0
- package/engine/core/agent-turn.ts +395 -0
- package/engine/core/already-done.ts +44 -1
- package/engine/core/build-action.ts +214 -0
- package/engine/core/build-context.ts +135 -0
- package/engine/core/build-launch.ts +259 -0
- package/engine/core/commit-in.ts +282 -0
- package/engine/core/decide-build-early.ts +108 -0
- package/engine/core/decide-build-ending.ts +145 -0
- package/engine/core/decide-build-helpers.ts +87 -0
- package/engine/core/decide-build-tickets.ts +207 -0
- package/engine/core/decide-build-view.ts +103 -0
- package/engine/core/decide-build.ts +101 -1368
- package/engine/core/decide-final-fix.ts +203 -0
- package/engine/core/decide-final-review.ts +55 -310
- package/engine/core/decide-red-green.ts +398 -0
- package/engine/core/decide-rejoin.ts +259 -0
- package/engine/core/decide-repo-wait.ts +129 -0
- package/engine/core/decide-run-budget.ts +86 -12
- package/engine/core/decide-stuck-helpers.ts +127 -0
- package/engine/core/decide-stuck.ts +60 -8
- package/engine/core/decide-ticket-review.ts +95 -0
- package/engine/core/decide-ticket.ts +267 -0
- package/engine/core/decide-waits.ts +47 -0
- package/engine/core/decide.ts +74 -23
- package/engine/core/engine-chores.ts +163 -0
- package/engine/core/environment-rerun.ts +83 -0
- package/engine/core/evidence-text.ts +84 -0
- package/engine/core/execute-action.ts +303 -0
- package/engine/core/execute-already-done-check.ts +133 -0
- package/engine/core/execute-build.ts +68 -944
- package/engine/core/execute-changeset.ts +5 -7
- package/engine/core/execute-final-review.ts +125 -13
- package/engine/core/execute-gates.ts +182 -0
- package/engine/core/execute-intake.ts +130 -0
- package/engine/core/execute-join.ts +276 -0
- package/engine/core/execute-memory.ts +12 -0
- package/engine/core/execute-pull-request.ts +84 -0
- package/engine/core/execute-red-check.ts +219 -0
- package/engine/core/execute-repo-wait.ts +129 -0
- package/engine/core/execute-stuck.ts +25 -10
- package/engine/core/execute-waits.ts +158 -0
- package/engine/core/execute-with-jev.ts +118 -0
- package/engine/core/execute.ts +124 -831
- package/engine/core/final-failure-cap.ts +38 -0
- package/engine/core/final-review-action.ts +125 -0
- package/engine/core/final-review-text.ts +63 -17
- package/engine/core/final-stuck-text.ts +86 -0
- package/engine/core/fix-loop-text.ts +49 -2
- package/engine/core/left-out.ts +120 -0
- package/engine/core/live-file.ts +372 -0
- package/engine/core/loop-caps.ts +25 -2
- package/engine/core/not-in-run.ts +7 -3
- package/engine/core/pull-request-text.ts +255 -6
- package/engine/core/repo-wait-text.ts +81 -0
- package/engine/core/review-text.ts +55 -1
- package/engine/core/run-crash-recovery-helpers.ts +16 -0
- package/engine/core/run-session-close-helpers.ts +96 -0
- package/engine/core/run-start.ts +148 -0
- package/engine/core/run-stuck-text.ts +86 -0
- package/engine/core/schedule-rules.ts +193 -0
- package/engine/core/stuck-detail-text.ts +89 -0
- package/engine/core/stuck-format.ts +22 -0
- package/engine/core/stuck-text.ts +29 -332
- package/engine/core/ticket-stuck-text.ts +192 -0
- package/engine/core/worktree-changes.ts +106 -0
- package/engine/gates/already-done-check.ts +120 -0
- package/engine/gates/feature-map.ts +96 -0
- package/engine/gates/gate-runner.ts +108 -108
- package/engine/gates/gate-schemas.ts +61 -2
- package/engine/gates/leftover-scan.ts +154 -31
- package/engine/gates/new-tests.ts +45 -0
- package/engine/gates/own-files-check.ts +98 -0
- package/engine/gates/prepare-check.ts +60 -0
- package/engine/gates/prepare-slots.ts +99 -0
- package/engine/gates/red-check.ts +184 -16
- package/engine/gates/shell-check.ts +64 -0
- package/engine/gates/slot-waits.ts +55 -0
- package/engine/gates/slow-test-runner.ts +59 -0
- package/engine/gates/test-checks.ts +161 -0
- package/engine/gates/test-runner.ts +164 -5
- package/engine/gates/test-slots.ts +48 -0
- package/engine/git/git-adapter.ts +55 -396
- package/engine/git/git-commits.ts +132 -0
- package/engine/git/git-join.ts +139 -0
- package/engine/git/git-read.ts +123 -0
- package/engine/git/git-run.ts +32 -0
- package/engine/git/git-worktrees.ts +143 -0
- package/engine/git/outside-links.ts +55 -0
- package/engine/guards/after-turn-check.ts +31 -5
- package/engine/guards/guard-hook.ts +60 -12
- package/engine/guards/guard-roles.ts +68 -0
- package/engine/guards/helper-rules.ts +92 -0
- package/engine/guards/permission-rules.ts +161 -0
- package/engine/guards/role-rules-helpers.ts +48 -0
- package/engine/guards/role-rules.ts +34 -606
- package/engine/guards/shell-rules.ts +344 -0
- package/engine/guards/worktree-git.ts +208 -0
- package/engine/guards/worktree-snapshot.ts +412 -0
- package/engine/guards/worktree-state.ts +28 -825
- package/engine/guards/worktree-undo.ts +260 -0
- package/engine/guards/write-rules.ts +149 -0
- package/engine/index.ts +30 -9
- package/engine/intake/criteria-checks.ts +114 -0
- package/engine/intake/intake-checks.ts +164 -30
- package/engine/intake/intake-schemas.ts +37 -2
- package/engine/jev/clef-client.ts +259 -0
- package/engine/jev/decision-model-credentials.ts +212 -0
- package/engine/jev/jev-jobs.ts +144 -60
- package/engine/jev/jev-schemas.ts +86 -5
- package/engine/jev/jev-shadow-helpers.ts +218 -0
- package/engine/jev/jev-shadow.ts +109 -64
- package/engine/jev/model-pick.ts +275 -0
- package/engine/journal/agent-entries.ts +167 -0
- package/engine/journal/agent-message-entries.ts +72 -0
- package/engine/journal/agent-turn-replay.ts +203 -0
- package/engine/journal/already-done-entries.ts +55 -0
- package/engine/journal/commit-entries.ts +56 -0
- package/engine/journal/cross-ticket-replay.ts +222 -0
- package/engine/journal/decision-model-entries.ts +86 -0
- package/engine/journal/entry-fields.ts +10 -0
- package/engine/journal/final-review-entries.ts +128 -0
- package/engine/journal/final-review-replay.ts +324 -0
- package/engine/journal/final-review-round.ts +320 -0
- package/engine/journal/final-review-state.ts +180 -0
- package/engine/journal/gate-entries.ts +81 -0
- package/engine/journal/intake-entries.ts +87 -0
- package/engine/journal/join-entries.ts +126 -0
- package/engine/journal/journal-entry-schema.ts +218 -0
- package/engine/journal/journal-kinds.ts +97 -0
- package/engine/journal/journal-record-schema.ts +218 -0
- package/engine/journal/journal-record.ts +43 -1400
- package/engine/journal/journal.ts +6 -1
- package/engine/journal/limit-entries.ts +90 -0
- package/engine/journal/memory-entries.ts +124 -0
- package/engine/journal/memory-replay.ts +157 -0
- package/engine/journal/plan-replay.ts +139 -0
- package/engine/journal/pull-request-entries.ts +41 -0
- package/engine/journal/replay.ts +157 -2144
- package/engine/journal/reply-replay.ts +144 -0
- package/engine/journal/repo-wait-entries.ts +53 -0
- package/engine/journal/run-entries.ts +172 -0
- package/engine/journal/run-state.ts +264 -0
- package/engine/journal/shared-failure-replay.ts +133 -0
- package/engine/journal/stuck-entries.ts +193 -0
- package/engine/journal/ticket-progress.ts +392 -0
- package/engine/journal/ticket-replay.ts +411 -0
- package/engine/journal/ticket-result-replay.ts +364 -0
- package/engine/journal/ticket-retry-replay.ts +142 -0
- package/engine/journal/worktree-entries.ts +122 -0
- package/engine/models/model-score.ts +512 -0
- package/engine/shell/run-command.ts +187 -18
- package/engine/testing/agent-turn-fixtures.ts +287 -0
- package/engine/testing/already-done-fixtures.ts +97 -0
- package/engine/testing/build-fixtures.ts +68 -973
- package/engine/testing/checkouts-fixtures.ts +48 -0
- package/engine/testing/final-review-fixtures.ts +62 -1
- package/engine/testing/final-review-steps.ts +143 -0
- package/engine/testing/limit-fixtures.ts +85 -0
- package/engine/testing/live-file-fixtures.ts +57 -0
- package/engine/testing/practice-repo.ts +10 -4
- package/engine/testing/practice-run.ts +1 -1
- package/engine/testing/reply-fixtures.ts +88 -0
- package/engine/testing/run-budget-fixtures.ts +165 -0
- package/engine/testing/run-fixtures.ts +219 -0
- package/engine/testing/sdk-play.ts +177 -0
- package/engine/testing/setup-repo.ts +194 -0
- package/engine/testing/step-record-fixtures.ts +55 -0
- package/engine/testing/ticket-step-fixtures.ts +272 -0
- package/engine/testing/wait-scenarios.ts +186 -0
- package/engine/tracker/gh-retry.ts +217 -0
- package/engine/tracker/github-tracker.ts +310 -90
- package/engine/tracker/in-memory-tracker.ts +8 -4
- package/engine/tracker/tracker.ts +131 -6
- package/package.json +2 -1
- package/skills/luca-retro/SKILL.md +74 -0
- package/skills/luca-retro/scripts/retro-summary.ts +1356 -0
- package/skills/luca-unstick/SKILL.md +153 -0
- package/skills/luca-unstick/scripts/stuck-summary.ts +1063 -0
- package/engine/jev/jev-client.ts +0 -173
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The owner's replies and the engine's stuck reports in replay: a reply
|
|
3
|
+
* taken for the run, the final review, or a ticket; a report for the stuck
|
|
4
|
+
* run, the final review, or a ticket; and a ticket's `retry`.
|
|
5
|
+
*/
|
|
6
|
+
import omit from 'lodash/omit'
|
|
7
|
+
|
|
8
|
+
import type { JournalRecord } from './journal-record'
|
|
9
|
+
import { engineCommentsAfter, type RunState } from './run-state'
|
|
10
|
+
import { applyTicketRecord } from './ticket-replay'
|
|
11
|
+
|
|
12
|
+
import { runBudgetOf } from '../limits/run-budget'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* An owner's reply: `stop` ends the run, a bare `retry` or `ship` is the
|
|
16
|
+
* stuck run's or the final review's, and the rest go to its ticket.
|
|
17
|
+
*/
|
|
18
|
+
export const replyReceivedAfter = ({
|
|
19
|
+
state,
|
|
20
|
+
next,
|
|
21
|
+
record,
|
|
22
|
+
}: {
|
|
23
|
+
/** The state before the record. */
|
|
24
|
+
state: RunState
|
|
25
|
+
/** The state with the record's seq and crash counts. */
|
|
26
|
+
next: RunState
|
|
27
|
+
record: Extract<JournalRecord, { kind: 'reply_received' }>
|
|
28
|
+
}): RunState => {
|
|
29
|
+
const handled = {
|
|
30
|
+
...next,
|
|
31
|
+
handled_comments: [
|
|
32
|
+
...state.handled_comments,
|
|
33
|
+
record.content.comment_id,
|
|
34
|
+
],
|
|
35
|
+
}
|
|
36
|
+
const { word, comment_id, ticket } = record.content
|
|
37
|
+
if (word === 'stop') return { ...handled, stop: { comment_id } }
|
|
38
|
+
// A bare `retry` while the run is stuck on its budget adds its top-up
|
|
39
|
+
// (one whole budget for a retry journaled before top-ups, #543), and
|
|
40
|
+
// the run carries on; stuck on its PR, the PR is tried again; stuck on
|
|
41
|
+
// its repo wait, it waits 24 hours more.
|
|
42
|
+
const { stuck } = state.run_budget
|
|
43
|
+
if (ticket === null && word === 'retry' && stuck !== null) {
|
|
44
|
+
const top_up =
|
|
45
|
+
stuck.reason === 'run_budget'
|
|
46
|
+
? (record.content.top_up ??
|
|
47
|
+
runBudgetOf({ config: state.config }))
|
|
48
|
+
: 0
|
|
49
|
+
return {
|
|
50
|
+
...handled,
|
|
51
|
+
repo_wait:
|
|
52
|
+
stuck.reason === 'repo_busy'
|
|
53
|
+
? { status: 'waiting', since: record.time }
|
|
54
|
+
: state.repo_wait,
|
|
55
|
+
run_budget: {
|
|
56
|
+
stuck: null,
|
|
57
|
+
report: null,
|
|
58
|
+
top_ups: state.run_budget.top_ups + top_up,
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (ticket === null && (word === 'retry' || word === 'ship')) {
|
|
63
|
+
return { ...handled, final_reply: { word, comment_id } }
|
|
64
|
+
}
|
|
65
|
+
return applyTicketRecord({ state: handled, record })
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** A stuck report the engine posted, for the run, the final review, or a ticket. */
|
|
69
|
+
export const stuckReportedAfter = ({
|
|
70
|
+
state,
|
|
71
|
+
next,
|
|
72
|
+
record,
|
|
73
|
+
}: {
|
|
74
|
+
state: RunState
|
|
75
|
+
next: RunState
|
|
76
|
+
record: Extract<JournalRecord, { kind: 'stuck_reported' }>
|
|
77
|
+
}): RunState => {
|
|
78
|
+
const reported = {
|
|
79
|
+
...next,
|
|
80
|
+
engine_comments: engineCommentsAfter({
|
|
81
|
+
state,
|
|
82
|
+
comment_id: record.content.comment_id,
|
|
83
|
+
}),
|
|
84
|
+
}
|
|
85
|
+
// A report with no ticket is the stuck run's, while it is not
|
|
86
|
+
// told yet, else the final review's.
|
|
87
|
+
const { run_budget } = state
|
|
88
|
+
if (
|
|
89
|
+
record.ticket === null &&
|
|
90
|
+
run_budget.stuck !== null &&
|
|
91
|
+
run_budget.report === null
|
|
92
|
+
) {
|
|
93
|
+
return {
|
|
94
|
+
...reported,
|
|
95
|
+
run_budget: {
|
|
96
|
+
...run_budget,
|
|
97
|
+
report: { comment_id: record.content.comment_id },
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return record.ticket === null
|
|
102
|
+
? {
|
|
103
|
+
...reported,
|
|
104
|
+
final_stuck_report: {
|
|
105
|
+
comment_id: record.content.comment_id,
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
: applyTicketRecord({ state: reported, record })
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** A ticket's `retry`, with the run-wide parts it resets. */
|
|
112
|
+
export const ticketRetriedAfter = ({
|
|
113
|
+
state,
|
|
114
|
+
next,
|
|
115
|
+
record,
|
|
116
|
+
}: {
|
|
117
|
+
state: RunState
|
|
118
|
+
next: RunState
|
|
119
|
+
record: Extract<JournalRecord, { kind: 'ticket_retried' }>
|
|
120
|
+
}): RunState => {
|
|
121
|
+
const { answer_id, mode } = record.content
|
|
122
|
+
const install = state.run_branch_install?.check
|
|
123
|
+
// A run branch whose install failed is installed again on a retry.
|
|
124
|
+
const run_branch_install =
|
|
125
|
+
mode === 'refused' || install === undefined || install?.ok !== false
|
|
126
|
+
? state.run_branch_install
|
|
127
|
+
: null
|
|
128
|
+
return applyTicketRecord({
|
|
129
|
+
state: {
|
|
130
|
+
...next,
|
|
131
|
+
// A retry gives the ticket fresh crash counts too.
|
|
132
|
+
crashes:
|
|
133
|
+
record.ticket === null
|
|
134
|
+
? next.crashes
|
|
135
|
+
: omit(next.crashes, String(record.ticket)),
|
|
136
|
+
run_branch_install,
|
|
137
|
+
engine_comments: engineCommentsAfter({
|
|
138
|
+
state,
|
|
139
|
+
comment_id: answer_id,
|
|
140
|
+
}),
|
|
141
|
+
},
|
|
142
|
+
record,
|
|
143
|
+
})
|
|
144
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { ENTRY_FIELDS } from './entry-fields'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The journal entries of the repo wait (#615): a run started while an
|
|
7
|
+
* earlier run on the same repo is going waits for it, before intake.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The run waits for the earlier runs on its repo that are going, named by
|
|
12
|
+
* run id and spec (`null` for a demo). The spec issue was told once.
|
|
13
|
+
*/
|
|
14
|
+
export const RepoWaitStartedEntrySchema = z.object({
|
|
15
|
+
...ENTRY_FIELDS,
|
|
16
|
+
kind: z.literal('repo_wait_started'),
|
|
17
|
+
content: z.object({
|
|
18
|
+
runs: z.array(
|
|
19
|
+
z.object({
|
|
20
|
+
run_id: z.string().min(1),
|
|
21
|
+
spec: z.number().int().positive().nullable(),
|
|
22
|
+
})
|
|
23
|
+
),
|
|
24
|
+
}),
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
/** No earlier run on the repo is going anymore: the run goes on to intake. */
|
|
28
|
+
export const RepoWaitEndedEntrySchema = z.object({
|
|
29
|
+
...ENTRY_FIELDS,
|
|
30
|
+
kind: z.literal('repo_wait_ended'),
|
|
31
|
+
content: z.object({}),
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The repo wait couldn't check whether the earlier runs are going, since
|
|
36
|
+
* `ps` failed (#624): `error` says how. Journaled once per wait, which goes
|
|
37
|
+
* on, counting every unfinished run as going.
|
|
38
|
+
*/
|
|
39
|
+
export const RepoWaitPsFailedEntrySchema = z.object({
|
|
40
|
+
...ENTRY_FIELDS,
|
|
41
|
+
kind: z.literal('repo_wait_ps_failed'),
|
|
42
|
+
content: z.object({ error: z.string() }),
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The run was started with `luca-run --alongside`, so it never waits for
|
|
47
|
+
* another run on its repo. Journaled right after `run_started`.
|
|
48
|
+
*/
|
|
49
|
+
export const RepoWaitSkippedEntrySchema = z.object({
|
|
50
|
+
...ENTRY_FIELDS,
|
|
51
|
+
kind: z.literal('repo_wait_skipped'),
|
|
52
|
+
content: z.object({}),
|
|
53
|
+
})
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { ENTRY_FIELDS } from './entry-fields'
|
|
4
|
+
|
|
5
|
+
import { AgentRoleSchema } from '../agents/role-results'
|
|
6
|
+
import { ConfigChangeSchema } from '../config/config-reload'
|
|
7
|
+
import { EngineConfigSchema } from '../config/engine-config'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The journal entries of the run's own life: its start, resumes and config
|
|
11
|
+
* reloads, a stop, and the scheduler's step records.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export const RunStartedEntrySchema = z.object({
|
|
15
|
+
...ENTRY_FIELDS,
|
|
16
|
+
kind: z.literal('run_started'),
|
|
17
|
+
content: z.object({
|
|
18
|
+
spec_number: z.number().int().positive(),
|
|
19
|
+
config: EngineConfigSchema,
|
|
20
|
+
/** The branch the run branch starts from and its PR merges into. */
|
|
21
|
+
base_branch: z.string().min(1).default('main'),
|
|
22
|
+
/**
|
|
23
|
+
* Memory for this run (#370): on, with the project's vault (`null`
|
|
24
|
+
* searches only `default`), or `null` for off. Off leaves the run
|
|
25
|
+
* exactly as it was before memory.
|
|
26
|
+
*/
|
|
27
|
+
memory: z
|
|
28
|
+
.object({ project_vault: z.string().min(1).nullable() })
|
|
29
|
+
.nullable()
|
|
30
|
+
.default(null),
|
|
31
|
+
/**
|
|
32
|
+
* The repo the run is on, as an absolute path, so `luca-run --resume`
|
|
33
|
+
* can find it. `null` in older journals.
|
|
34
|
+
*/
|
|
35
|
+
repo: z.string().min(1).nullable().default(null),
|
|
36
|
+
/**
|
|
37
|
+
* Luca's version the run started on (#460). `null` in older
|
|
38
|
+
* journals.
|
|
39
|
+
*/
|
|
40
|
+
luca_version: z.string().min(1).nullable().default(null),
|
|
41
|
+
}),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The engine started again on the run's journal (#460), on Luca's version
|
|
46
|
+
* `luca_version`, which may differ from the one in `run_started`. Journaled
|
|
47
|
+
* once per resume, before the engine's first step. Nothing reads it but
|
|
48
|
+
* the board.
|
|
49
|
+
*/
|
|
50
|
+
export const EngineResumedEntrySchema = z.object({
|
|
51
|
+
...ENTRY_FIELDS,
|
|
52
|
+
kind: z.literal('engine_resumed'),
|
|
53
|
+
content: z.object({ luca_version: z.string().min(1) }),
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A resume read the repo's `.luca/config.json` again (#516), and the
|
|
58
|
+
* build fields it reloads (`RELOADED_FIELDS`) changed: each one, old to
|
|
59
|
+
* new. Journaled right after the resume's `engine_resumed`, only when
|
|
60
|
+
* something changed. Replay puts the new values on the run's config.
|
|
61
|
+
*/
|
|
62
|
+
export const ConfigReloadedEntrySchema = z.object({
|
|
63
|
+
...ENTRY_FIELDS,
|
|
64
|
+
kind: z.literal('config_reloaded'),
|
|
65
|
+
content: z.object({ changes: z.array(ConfigChangeSchema).min(1) }),
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* A resume could not take the repo's config (#516): it is missing, not
|
|
70
|
+
* JSON, not a valid config, or one intake would refuse. The run keeps the
|
|
71
|
+
* config it had and goes on. `reason` says what is wrong.
|
|
72
|
+
*/
|
|
73
|
+
export const ConfigReloadRefusedEntrySchema = z.object({
|
|
74
|
+
...ENTRY_FIELDS,
|
|
75
|
+
kind: z.literal('config_reload_refused'),
|
|
76
|
+
content: z.object({ reason: z.string().min(1) }),
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The run stopped because going on was unsafe: the wrong credentials or
|
|
81
|
+
* plan, the wrong model, or a foreign MCP server. A later `runEngine` on the
|
|
82
|
+
* same journal picks the step up again.
|
|
83
|
+
*
|
|
84
|
+
* A `billing` stop (overage, or a billing error) sticks: the run never goes
|
|
85
|
+
* on, however often the engine is started again on its journal.
|
|
86
|
+
*/
|
|
87
|
+
export const RunStoppedEntrySchema = z.object({
|
|
88
|
+
...ENTRY_FIELDS,
|
|
89
|
+
kind: z.literal('run_stopped'),
|
|
90
|
+
content: z.object({
|
|
91
|
+
reason: z.string(),
|
|
92
|
+
role: AgentRoleSchema.nullable().default(null),
|
|
93
|
+
billing: z.boolean().default(false),
|
|
94
|
+
/**
|
|
95
|
+
* The same step was cut off by a crash `MAX_CRASHES` times in a row
|
|
96
|
+
* on a run-level key: like a billing stop, it sticks.
|
|
97
|
+
*/
|
|
98
|
+
crashed: z.boolean().default(false),
|
|
99
|
+
}),
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The scheduler is about to carry out one step: an action it started, other
|
|
104
|
+
* than a wait. `key` is the scheduler's key for it (a ticket's number,
|
|
105
|
+
* `final`, `lens:<lens>`, `replies`, or `run`), and `step` its action type,
|
|
106
|
+
* plus `:<role>` for an agent's turn. `first_seq` is the `step_started` seq
|
|
107
|
+
* of this step's first try when a crash cut off an earlier try of it, else
|
|
108
|
+
* `null`. `ticket` is the action's ticket, and `role` the agent's role.
|
|
109
|
+
*/
|
|
110
|
+
export const StepStartedEntrySchema = z.object({
|
|
111
|
+
...ENTRY_FIELDS,
|
|
112
|
+
kind: z.literal('step_started'),
|
|
113
|
+
content: z.object({
|
|
114
|
+
key: z.string().min(1),
|
|
115
|
+
step: z.string().min(1),
|
|
116
|
+
first_seq: z.number().int().min(1).nullable().default(null),
|
|
117
|
+
}),
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The step under `key` settled: its own records are in the journal, so it
|
|
122
|
+
* is a checkpoint. Not written when the step threw.
|
|
123
|
+
*/
|
|
124
|
+
export const StepEndedEntrySchema = z.object({
|
|
125
|
+
...ENTRY_FIELDS,
|
|
126
|
+
kind: z.literal('step_ended'),
|
|
127
|
+
content: z.object({
|
|
128
|
+
key: z.string().min(1),
|
|
129
|
+
step: z.string().min(1),
|
|
130
|
+
}),
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A ticket began to wait on purpose between steps (#559): `baseline` for
|
|
135
|
+
* another ticket's shared baseline tests, `join` for the join queue,
|
|
136
|
+
* `start` for the start queue, each on `on_ticket`. Journaled once when the
|
|
137
|
+
* wait starts, since `since`; the ticket's next `step_started` ends it.
|
|
138
|
+
* Only the board reads it.
|
|
139
|
+
*/
|
|
140
|
+
export const TicketWaitingEntrySchema = z.object({
|
|
141
|
+
...ENTRY_FIELDS,
|
|
142
|
+
kind: z.literal('ticket_waiting'),
|
|
143
|
+
content: z.object({
|
|
144
|
+
for: z.enum(['baseline', 'join', 'start']),
|
|
145
|
+
on_ticket: z.number().int().positive().nullable(),
|
|
146
|
+
since: z.iso.datetime(),
|
|
147
|
+
}),
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
/** One step a crash cut off: its `step_started` had no `step_ended`. */
|
|
151
|
+
export const InterruptedStepSchema = z.object({
|
|
152
|
+
key: z.string().min(1),
|
|
153
|
+
step: z.string().min(1),
|
|
154
|
+
ticket: z.number().int().positive().nullable(),
|
|
155
|
+
role: z.string().nullable(),
|
|
156
|
+
/** The seq of the cut-off step's `step_started`. */
|
|
157
|
+
started_seq: z.number().int().min(1),
|
|
158
|
+
/** That record's `first_seq`: the step's first try, if it was a redo. */
|
|
159
|
+
first_seq: z.number().int().min(1).nullable(),
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
export type InterruptedStep = z.infer<typeof InterruptedStepSchema>
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* A restarted engine found steps a crash cut off, journaled once before its
|
|
166
|
+
* first step. Each is taken again, an agent's turn in a fresh session.
|
|
167
|
+
*/
|
|
168
|
+
export const RunResumedEntrySchema = z.object({
|
|
169
|
+
...ENTRY_FIELDS,
|
|
170
|
+
kind: z.literal('run_resumed'),
|
|
171
|
+
content: z.object({ interrupted: z.array(InterruptedStepSchema) }),
|
|
172
|
+
})
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shape of a run's state as replay rebuilds it, with its run-wide parts
|
|
3
|
+
* (snapshot, comments, PR, notes, budget), its empty value, and the small
|
|
4
|
+
* run-wide updates: the snapshot's phase, run notes, and engine comments.
|
|
5
|
+
*/
|
|
6
|
+
import { EMPTY_FINAL_REVIEW, type FinalReviewState } from './final-review-state'
|
|
7
|
+
import type { JournalRecord, RunStuckReason } from './journal-record'
|
|
8
|
+
import { EMPTY_MEMORY, type MemoryState } from './memory-replay'
|
|
9
|
+
import type { PlanState } from './plan-replay'
|
|
10
|
+
import type { CrashCounts } from './step-records'
|
|
11
|
+
import type {
|
|
12
|
+
ReplayedGates,
|
|
13
|
+
ReplayedInstall,
|
|
14
|
+
ReplayedWorktree,
|
|
15
|
+
TicketProgress,
|
|
16
|
+
} from './ticket-progress'
|
|
17
|
+
|
|
18
|
+
import type { AgentRole } from '../agents/role-results'
|
|
19
|
+
import type { EngineConfig } from '../config/engine-config'
|
|
20
|
+
import type { TestCaseRef } from '../gates/gate-schemas'
|
|
21
|
+
import type {
|
|
22
|
+
IntakeProblem,
|
|
23
|
+
IntakeRead,
|
|
24
|
+
LeftOutTicket,
|
|
25
|
+
SpecSnapshot,
|
|
26
|
+
TicketSnapshot,
|
|
27
|
+
} from '../intake/intake-schemas'
|
|
28
|
+
|
|
29
|
+
/** Where a run stands, as far as intake goes. */
|
|
30
|
+
export type RunPhase =
|
|
31
|
+
| 'new'
|
|
32
|
+
| 'started'
|
|
33
|
+
| 'intake_read'
|
|
34
|
+
| 'refused'
|
|
35
|
+
| 'nothing_to_do'
|
|
36
|
+
/** The spec snapshot is written but some ticket snapshots are not. */
|
|
37
|
+
| 'snapshotting'
|
|
38
|
+
| 'intake_passed'
|
|
39
|
+
|
|
40
|
+
/** The snapshot as replayed from `spec_snapshot` and `ticket_snapshot`. */
|
|
41
|
+
export type ReplayedSnapshot = {
|
|
42
|
+
spec: SpecSnapshot
|
|
43
|
+
ticket_order: number[]
|
|
44
|
+
closed_tickets: number[]
|
|
45
|
+
/** The latest snapshot of each ticket, keyed by ticket number. */
|
|
46
|
+
tickets: Record<number, TicketSnapshot>
|
|
47
|
+
/** The open tickets intake left out for a person, and why (#499). */
|
|
48
|
+
left_out: LeftOutTicket[]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** A comment the engine read on the spec issue. */
|
|
52
|
+
export type ReplayedComment = {
|
|
53
|
+
comment_id: number
|
|
54
|
+
author: string
|
|
55
|
+
body: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The run's pull request, once opened. */
|
|
59
|
+
export type ReplayedPullRequest = { number: number; url: string }
|
|
60
|
+
|
|
61
|
+
/** One run note, with the agent that wrote it. */
|
|
62
|
+
export type ReplayedRunNote = { ticket: number; role: AgentRole; note: string }
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The run budget (#435): whether the run is stuck on it (or on its PR,
|
|
66
|
+
* #508) and told, and how many tokens the owner's `retry` replies added.
|
|
67
|
+
*/
|
|
68
|
+
export type RunBudgetState = {
|
|
69
|
+
/** The run is stuck, until the owner's `retry`. */
|
|
70
|
+
stuck: { reason: RunStuckReason; detail: string } | null
|
|
71
|
+
/** The spec issue's comment that told the owner the run is stuck. */
|
|
72
|
+
report: { comment_id: number } | null
|
|
73
|
+
/**
|
|
74
|
+
* Tokens added by `retry` (#543): the run may use its budget plus these.
|
|
75
|
+
* A retry journaled with no top-up added one whole budget.
|
|
76
|
+
*/
|
|
77
|
+
top_ups: number
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The repo wait (#615), before intake: not begun (`none`), waiting for an
|
|
82
|
+
* earlier run on the repo, over, or skipped (`luca-run --alongside`).
|
|
83
|
+
*/
|
|
84
|
+
export type RepoWaitState = {
|
|
85
|
+
status: 'none' | 'waiting' | 'ended' | 'skipped'
|
|
86
|
+
/**
|
|
87
|
+
* When the wait began, or the owner's `retry` of a run stuck on it
|
|
88
|
+
* (`repo_busy`): its 24 hours count from here.
|
|
89
|
+
*/
|
|
90
|
+
since: string | null
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** An old test that failed in a ticket's check, at its record's time (#544). */
|
|
94
|
+
export type OldTestFailure = TestCaseRef & { ticket: number; time: string }
|
|
95
|
+
|
|
96
|
+
/** A run's state, rebuilt only from its journal. There is no status file. */
|
|
97
|
+
export type RunState = {
|
|
98
|
+
phase: RunPhase
|
|
99
|
+
spec_number: number | null
|
|
100
|
+
config: EngineConfig | null
|
|
101
|
+
base_branch: string | null
|
|
102
|
+
intake: IntakeRead | null
|
|
103
|
+
problems: IntakeProblem[] | null
|
|
104
|
+
snapshot: ReplayedSnapshot | null
|
|
105
|
+
run_branch: ReplayedWorktree | null
|
|
106
|
+
/** The install in the run branch's checkout, once it ran. */
|
|
107
|
+
run_branch_install: ReplayedInstall | null
|
|
108
|
+
tickets: Record<number, TicketProgress>
|
|
109
|
+
/**
|
|
110
|
+
* The repo had a changesets config when the run branch was made, so a
|
|
111
|
+
* changeset is written before the PR (#461).
|
|
112
|
+
*/
|
|
113
|
+
changesets: boolean
|
|
114
|
+
/** The run's changeset, once written and pushed. */
|
|
115
|
+
changeset: { path: string | null; sha: string } | null
|
|
116
|
+
pull_request: ReplayedPullRequest | null
|
|
117
|
+
plan: PlanState
|
|
118
|
+
/**
|
|
119
|
+
* The seq of each ticket's latest usage record (a retried ticket that
|
|
120
|
+
* finishes again gets another), and whether the run's is recorded.
|
|
121
|
+
*/
|
|
122
|
+
usage_recorded: { tickets: Record<number, number>; run: boolean }
|
|
123
|
+
/** The worktrees the engine removed at the end of the run. */
|
|
124
|
+
removed_worktrees: string[]
|
|
125
|
+
/**
|
|
126
|
+
* Every session journaled as closed (`agent_session_closed`), or found
|
|
127
|
+
* gone by a follow-up (#521). None is ever a follow-up target again.
|
|
128
|
+
*/
|
|
129
|
+
closed_sessions: string[]
|
|
130
|
+
/**
|
|
131
|
+
* Every run note from every finished agent in the run, oldest first
|
|
132
|
+
* (journal order), word for word.
|
|
133
|
+
*/
|
|
134
|
+
run_notes: ReplayedRunNote[]
|
|
135
|
+
/** The latest gates on the run branch: after a join, or a final review fix. */
|
|
136
|
+
run_branch_gates: ReplayedGates | null
|
|
137
|
+
/**
|
|
138
|
+
* Every untracked path a prepare run made in any of the run's checkouts
|
|
139
|
+
* (`prepare_made`), in journal order. Never an agent's work: the engine
|
|
140
|
+
* leaves them out of commits, the leftover scan, and role rules.
|
|
141
|
+
*/
|
|
142
|
+
prepare_made: string[]
|
|
143
|
+
/**
|
|
144
|
+
* Every old test (one that passed at its ticket's baseline) that failed
|
|
145
|
+
* in a ticket's red check, gates or join gates, oldest first (#544).
|
|
146
|
+
*/
|
|
147
|
+
old_test_failures: OldTestFailure[]
|
|
148
|
+
final_review: FinalReviewState
|
|
149
|
+
/** Comments read on the spec issue while waiting for replies, oldest first. */
|
|
150
|
+
comments: ReplayedComment[]
|
|
151
|
+
/** Comments already taken as a reply, or sent back. */
|
|
152
|
+
handled_comments: number[]
|
|
153
|
+
/** Comments the engine itself posted on the spec issue. */
|
|
154
|
+
engine_comments: number[]
|
|
155
|
+
/** The owner replied `stop`: nothing new starts, and the run ends without a PR. */
|
|
156
|
+
stop: { comment_id: number } | null
|
|
157
|
+
/** The spec issue's comment that told the owner the final review is stuck. */
|
|
158
|
+
final_stuck_report: { comment_id: number } | null
|
|
159
|
+
/** The owner's reply to the stuck final review, until the engine acts on it. */
|
|
160
|
+
final_reply: { word: 'retry' | 'ship'; comment_id: number } | null
|
|
161
|
+
/** The run's budget of tokens: stuck on it, and the budgets added (#435). */
|
|
162
|
+
run_budget: RunBudgetState
|
|
163
|
+
/** The wait for earlier runs on the same repo (#615). */
|
|
164
|
+
repo_wait: RepoWaitState
|
|
165
|
+
/** Memory's recalls, the learner, and the saves (#370). */
|
|
166
|
+
memory: MemoryState
|
|
167
|
+
/**
|
|
168
|
+
* Crashes in a row per scheduler key (`run_resumed`), until a step under
|
|
169
|
+
* the key ends. A ticket's `retry`, or the final review's, clears its own.
|
|
170
|
+
*/
|
|
171
|
+
crashes: CrashCounts
|
|
172
|
+
/** Set once a stop for crashes is journaled. It sticks. */
|
|
173
|
+
crash_stopped: { reason: string } | null
|
|
174
|
+
last_seq: number
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export const EMPTY_STATE: RunState = {
|
|
178
|
+
phase: 'new',
|
|
179
|
+
spec_number: null,
|
|
180
|
+
config: null,
|
|
181
|
+
base_branch: null,
|
|
182
|
+
intake: null,
|
|
183
|
+
problems: null,
|
|
184
|
+
snapshot: null,
|
|
185
|
+
run_branch: null,
|
|
186
|
+
run_branch_install: null,
|
|
187
|
+
tickets: {},
|
|
188
|
+
changesets: false,
|
|
189
|
+
changeset: null,
|
|
190
|
+
pull_request: null,
|
|
191
|
+
plan: {
|
|
192
|
+
hit: null,
|
|
193
|
+
wait: null,
|
|
194
|
+
resets_announced: [],
|
|
195
|
+
billing: null,
|
|
196
|
+
billing_stopped: null,
|
|
197
|
+
usage_wait: null,
|
|
198
|
+
waited_until: null,
|
|
199
|
+
},
|
|
200
|
+
usage_recorded: { tickets: {}, run: false },
|
|
201
|
+
removed_worktrees: [],
|
|
202
|
+
closed_sessions: [],
|
|
203
|
+
run_notes: [],
|
|
204
|
+
run_branch_gates: null,
|
|
205
|
+
prepare_made: [],
|
|
206
|
+
old_test_failures: [],
|
|
207
|
+
final_review: EMPTY_FINAL_REVIEW,
|
|
208
|
+
comments: [],
|
|
209
|
+
handled_comments: [],
|
|
210
|
+
engine_comments: [],
|
|
211
|
+
stop: null,
|
|
212
|
+
final_stuck_report: null,
|
|
213
|
+
final_reply: null,
|
|
214
|
+
run_budget: { stuck: null, report: null, top_ups: 0 },
|
|
215
|
+
repo_wait: { status: 'none', since: null },
|
|
216
|
+
memory: EMPTY_MEMORY,
|
|
217
|
+
crashes: {},
|
|
218
|
+
crash_stopped: null,
|
|
219
|
+
last_seq: 0,
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export const snapshotPhase = ({
|
|
223
|
+
snapshot,
|
|
224
|
+
}: {
|
|
225
|
+
snapshot: ReplayedSnapshot
|
|
226
|
+
}): RunPhase =>
|
|
227
|
+
snapshot.ticket_order.every((number) => number in snapshot.tickets)
|
|
228
|
+
? 'intake_passed'
|
|
229
|
+
: 'snapshotting'
|
|
230
|
+
|
|
231
|
+
/** The run's notes after an agent finished: its own go at the end. */
|
|
232
|
+
export const notesAfter = ({
|
|
233
|
+
state,
|
|
234
|
+
record,
|
|
235
|
+
}: {
|
|
236
|
+
state: RunState
|
|
237
|
+
record: Extract<JournalRecord, { kind: 'agent_finished' }>
|
|
238
|
+
}): ReplayedRunNote[] => {
|
|
239
|
+
const { ticket, content } = record
|
|
240
|
+
// Reviewers (the ticket reviewer and the lenses) leave no run notes.
|
|
241
|
+
if (ticket === null || !('run_notes' in content.result)) {
|
|
242
|
+
return state.run_notes
|
|
243
|
+
}
|
|
244
|
+
return [
|
|
245
|
+
...state.run_notes,
|
|
246
|
+
...content.result.run_notes.map((note) => ({
|
|
247
|
+
ticket,
|
|
248
|
+
role: content.role,
|
|
249
|
+
note,
|
|
250
|
+
})),
|
|
251
|
+
]
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** The spec comments the engine posted, plus this one if it posted one. */
|
|
255
|
+
export const engineCommentsAfter = ({
|
|
256
|
+
state,
|
|
257
|
+
comment_id,
|
|
258
|
+
}: {
|
|
259
|
+
state: RunState
|
|
260
|
+
comment_id: number | null
|
|
261
|
+
}): number[] =>
|
|
262
|
+
comment_id === null
|
|
263
|
+
? state.engine_comments
|
|
264
|
+
: [...state.engine_comments, comment_id]
|