@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
|
@@ -1,978 +1,73 @@
|
|
|
1
|
-
import { SPEC_OWNER } from './intake-fixtures'
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
AgentRole,
|
|
5
|
-
Finding,
|
|
6
|
-
FindingResponse,
|
|
7
|
-
FindingRuling,
|
|
8
|
-
} from '../agents/role-results'
|
|
9
|
-
import type { EngineConfig } from '../config/engine-config'
|
|
10
|
-
import type { TestRun } from '../gates/gate-schemas'
|
|
11
|
-
import type { TicketSnapshot } from '../intake/intake-schemas'
|
|
12
|
-
import type {
|
|
13
|
-
CommitStage,
|
|
14
|
-
JournalEntry,
|
|
15
|
-
StuckReason,
|
|
16
|
-
} from '../journal/journal-record'
|
|
17
|
-
|
|
18
1
|
/**
|
|
19
2
|
* Journal entry builders for the build steps, so decision-step tests can
|
|
20
3
|
* write a journal that stops anywhere along a ticket's spine.
|
|
4
|
+
*
|
|
5
|
+
* The builders live in modules by job, and this module re-exports all of
|
|
6
|
+
* them, so a test imports every one from here.
|
|
21
7
|
*/
|
|
22
8
|
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
(ticket): JournalEntry => ({
|
|
89
|
-
kind: 'ticket_snapshot',
|
|
90
|
-
ticket: ticket.number,
|
|
91
|
-
role: null,
|
|
92
|
-
content: ticket,
|
|
93
|
-
})
|
|
94
|
-
),
|
|
95
|
-
]
|
|
96
|
-
|
|
97
|
-
export const RUN_BRANCH = 'luca/spec-10-run'
|
|
98
|
-
|
|
99
|
-
/** Where fixtures put each ticket's worktree, and the run branch's. */
|
|
100
|
-
export const ticketPath = (ticket: number): string =>
|
|
101
|
-
`/runs/run/tickets/${ticket}`
|
|
102
|
-
|
|
103
|
-
export const RUN_BRANCH_PATH = '/runs/run/run-branch'
|
|
104
|
-
|
|
105
|
-
export const runBranchCreated = (): JournalEntry => ({
|
|
106
|
-
kind: 'run_branch_created',
|
|
107
|
-
ticket: null,
|
|
108
|
-
role: null,
|
|
109
|
-
content: {
|
|
110
|
-
branch: RUN_BRANCH,
|
|
111
|
-
path: RUN_BRANCH_PATH,
|
|
112
|
-
base_sha: 'b0',
|
|
113
|
-
},
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
export const ticketWorktreeCreated = ({
|
|
117
|
-
ticket,
|
|
118
|
-
}: {
|
|
119
|
-
ticket: number
|
|
120
|
-
}): JournalEntry => ({
|
|
121
|
-
kind: 'ticket_worktree_created',
|
|
122
|
-
ticket,
|
|
123
|
-
role: null,
|
|
124
|
-
content: {
|
|
125
|
-
branch: `${RUN_BRANCH}--ticket-${ticket}`,
|
|
126
|
-
path: ticketPath(ticket),
|
|
127
|
-
base_sha: 'b0',
|
|
128
|
-
},
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* The engine's install in a new worktree: the run branch's checkout
|
|
133
|
-
* (`ticket` unset) or a ticket's worktree. Passing unless `ok` is false.
|
|
134
|
-
*/
|
|
135
|
-
export const dependenciesInstalled = ({
|
|
136
|
-
ticket,
|
|
137
|
-
ok,
|
|
138
|
-
}: {
|
|
139
|
-
ticket?: number
|
|
140
|
-
ok?: boolean
|
|
141
|
-
}): JournalEntry => ({
|
|
142
|
-
kind: 'dependencies_installed',
|
|
143
|
-
ticket: ticket ?? null,
|
|
144
|
-
role: null,
|
|
145
|
-
content: {
|
|
146
|
-
target: ticket === undefined ? 'run_branch' : 'ticket',
|
|
147
|
-
check: {
|
|
148
|
-
name: 'install',
|
|
149
|
-
command: 'bun install --frozen-lockfile',
|
|
150
|
-
ok: ok ?? true,
|
|
151
|
-
exit_code: ok === false ? 1 : 0,
|
|
152
|
-
output:
|
|
153
|
-
ok === false
|
|
154
|
-
? 'error: lockfile had changes, but lockfile is frozen'
|
|
155
|
-
: '',
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* The entries with a passing install after each new worktree that has none,
|
|
162
|
-
* so tests about later steps need not list the installs.
|
|
163
|
-
*/
|
|
164
|
-
export const withInstalls = ({
|
|
165
|
-
entries,
|
|
166
|
-
}: {
|
|
167
|
-
entries: JournalEntry[]
|
|
168
|
-
}): JournalEntry[] =>
|
|
169
|
-
entries.flatMap((entry, index) => {
|
|
170
|
-
const made =
|
|
171
|
-
entry.kind === 'run_branch_created' ||
|
|
172
|
-
entry.kind === 'ticket_worktree_created'
|
|
173
|
-
if (!made || entries[index + 1]?.kind === 'dependencies_installed') {
|
|
174
|
-
return [entry]
|
|
175
|
-
}
|
|
176
|
-
return [
|
|
177
|
-
entry,
|
|
178
|
-
dependenciesInstalled({ ticket: entry.ticket ?? undefined }),
|
|
179
|
-
]
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
/** A test run with no test files, as a fresh repo has. */
|
|
183
|
-
export const emptyTestRun = (): TestRun => ({
|
|
184
|
-
command: 'bun test',
|
|
185
|
-
ok: true,
|
|
186
|
-
exit_code: 1,
|
|
187
|
-
no_test_files: true,
|
|
188
|
-
cases: [],
|
|
189
|
-
files_without_results: [],
|
|
190
|
-
output: '0 test files matching',
|
|
191
|
-
})
|
|
192
|
-
|
|
193
|
-
export const baselineTests = ({
|
|
194
|
-
ticket,
|
|
195
|
-
}: {
|
|
196
|
-
ticket: number
|
|
197
|
-
}): JournalEntry => ({
|
|
198
|
-
kind: 'baseline_tests',
|
|
199
|
-
ticket,
|
|
200
|
-
role: null,
|
|
201
|
-
content: emptyTestRun(),
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
/** The session id fixtures give each role's turns unless told otherwise. */
|
|
205
|
-
export const SESSIONS = {
|
|
206
|
-
'test-writer': 'tw-1',
|
|
207
|
-
implementer: 'impl-1',
|
|
208
|
-
'ticket-reviewer': 'rev-1',
|
|
209
|
-
'architecture-lens': 'architecture-1',
|
|
210
|
-
'simplification-lens': 'simplification-1',
|
|
211
|
-
'security-lens': 'security-1',
|
|
212
|
-
'integration-lens': 'integration-1',
|
|
213
|
-
'rules-lens': 'rules-1',
|
|
214
|
-
learner: 'learner-1',
|
|
215
|
-
} as const satisfies Record<AgentRole, string>
|
|
216
|
-
|
|
217
|
-
/** An agent turn started: a fresh launch, or a follow-up to `follow_up_of`. */
|
|
218
|
-
export const agentStarted = ({
|
|
219
|
-
ticket,
|
|
220
|
-
role,
|
|
221
|
-
prompt,
|
|
222
|
-
follow_up_of,
|
|
223
|
-
}: {
|
|
224
|
-
/** `null` for the final review. */
|
|
225
|
-
ticket: number | null
|
|
226
|
-
role: AgentRole
|
|
227
|
-
prompt?: string
|
|
228
|
-
follow_up_of?: string
|
|
229
|
-
}): JournalEntry => ({
|
|
230
|
-
kind: 'agent_started',
|
|
231
|
-
ticket,
|
|
232
|
-
role,
|
|
233
|
-
content: {
|
|
234
|
-
role,
|
|
235
|
-
prompt: prompt ?? 'p',
|
|
236
|
-
follow_up_of: follow_up_of ?? null,
|
|
237
|
-
},
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
export const testsWritten = ({
|
|
241
|
-
ticket,
|
|
242
|
-
session_id,
|
|
243
|
-
assumptions,
|
|
244
|
-
finding_responses,
|
|
245
|
-
run_notes,
|
|
246
|
-
}: {
|
|
247
|
-
/** `null` for the final review. */
|
|
248
|
-
ticket: number | null
|
|
249
|
-
/** Defaults to `SESSIONS['test-writer']`. */
|
|
250
|
-
session_id?: string
|
|
251
|
-
/** Defaults to one assumption. */
|
|
252
|
-
assumptions?: string[]
|
|
253
|
-
/** A review fixer's answer to each finding it got. */
|
|
254
|
-
finding_responses?: FindingResponse[]
|
|
255
|
-
/** Defaults to none. */
|
|
256
|
-
run_notes?: string[]
|
|
257
|
-
}): JournalEntry => ({
|
|
258
|
-
kind: 'agent_finished',
|
|
259
|
-
ticket,
|
|
260
|
-
role: 'test-writer',
|
|
261
|
-
content: {
|
|
262
|
-
role: 'test-writer',
|
|
263
|
-
session_id: session_id ?? SESSIONS['test-writer'],
|
|
264
|
-
result: {
|
|
265
|
-
outcome: 'tests_written',
|
|
266
|
-
criteria: [
|
|
267
|
-
{
|
|
268
|
-
criterion_id: 'AC1',
|
|
269
|
-
tests: [
|
|
270
|
-
{
|
|
271
|
-
file: 'src/sum.test.ts',
|
|
272
|
-
name: 'sum adds two numbers',
|
|
273
|
-
},
|
|
274
|
-
],
|
|
275
|
-
},
|
|
276
|
-
],
|
|
277
|
-
summary: 'One test for AC1.',
|
|
278
|
-
assumptions: assumptions ?? ['Numbers are integers.'],
|
|
279
|
-
run_notes: run_notes ?? [],
|
|
280
|
-
finding_responses: finding_responses ?? [],
|
|
281
|
-
},
|
|
282
|
-
},
|
|
283
|
-
})
|
|
284
|
-
|
|
285
|
-
/** A test-writer that found nothing new to test. */
|
|
286
|
-
export const nothingNewToTest = ({
|
|
287
|
-
ticket,
|
|
288
|
-
}: {
|
|
289
|
-
ticket: number
|
|
290
|
-
}): JournalEntry => ({
|
|
291
|
-
kind: 'agent_finished',
|
|
292
|
-
ticket,
|
|
293
|
-
role: 'test-writer',
|
|
294
|
-
content: {
|
|
295
|
-
role: 'test-writer',
|
|
296
|
-
session_id: SESSIONS['test-writer'],
|
|
297
|
-
result: { outcome: 'nothing_new_to_test' },
|
|
298
|
-
},
|
|
299
|
-
})
|
|
300
|
-
|
|
301
|
-
/** The commit fixtures say did an already-done ticket's work. */
|
|
302
|
-
export const DONE_SHA = '3559c25f5a1b2c3d4e5f60718293a4b5c6d7e8f9'
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* A test-writer that found the ticket's work already on the base branch:
|
|
306
|
-
* done by `DONE_SHA` unless told otherwise, with one existing test for AC1.
|
|
307
|
-
*/
|
|
308
|
-
export const alreadyDone = ({
|
|
309
|
-
ticket,
|
|
310
|
-
shas,
|
|
311
|
-
}: {
|
|
312
|
-
ticket: number
|
|
313
|
-
/** Defaults to `[DONE_SHA]`. */
|
|
314
|
-
shas?: string[]
|
|
315
|
-
}): JournalEntry => ({
|
|
316
|
-
kind: 'agent_finished',
|
|
317
|
-
ticket,
|
|
318
|
-
role: 'test-writer',
|
|
319
|
-
content: {
|
|
320
|
-
role: 'test-writer',
|
|
321
|
-
session_id: SESSIONS['test-writer'],
|
|
322
|
-
result: {
|
|
323
|
-
outcome: 'already_done',
|
|
324
|
-
done_by: (shas ?? [DONE_SHA]).map((sha) => ({
|
|
325
|
-
sha,
|
|
326
|
-
title: 'feat: add sum',
|
|
327
|
-
})),
|
|
328
|
-
criteria: [
|
|
329
|
-
{
|
|
330
|
-
criterion_id: 'AC1',
|
|
331
|
-
tests: [
|
|
332
|
-
{
|
|
333
|
-
file: 'src/sum.test.ts',
|
|
334
|
-
name: 'sum adds two numbers',
|
|
335
|
-
},
|
|
336
|
-
],
|
|
337
|
-
},
|
|
338
|
-
],
|
|
339
|
-
summary: 'The sum is already on main, with its test.',
|
|
340
|
-
},
|
|
341
|
-
},
|
|
342
|
-
})
|
|
343
|
-
|
|
344
|
-
/** The engine noted that a ticket's work is already done, on the spec issue. */
|
|
345
|
-
export const ticketAlreadyDone = ({
|
|
346
|
-
ticket,
|
|
347
|
-
shas,
|
|
348
|
-
}: {
|
|
349
|
-
ticket: number
|
|
350
|
-
/** Defaults to `[DONE_SHA]`. */
|
|
351
|
-
shas?: string[]
|
|
352
|
-
}): JournalEntry => ({
|
|
353
|
-
kind: 'ticket_already_done',
|
|
354
|
-
ticket,
|
|
355
|
-
role: null,
|
|
356
|
-
content: { shas: shas ?? [DONE_SHA], comment_id: 300 + ticket },
|
|
357
|
-
})
|
|
358
|
-
|
|
359
|
-
/** The engine closed an already-done ticket, with a comment on it. */
|
|
360
|
-
export const ticketClosed = ({ ticket }: { ticket: number }): JournalEntry => ({
|
|
361
|
-
kind: 'ticket_closed',
|
|
362
|
-
ticket,
|
|
363
|
-
role: null,
|
|
364
|
-
content: { comment_id: 400 + ticket },
|
|
365
|
-
})
|
|
366
|
-
|
|
367
|
-
export const redCheck = ({
|
|
368
|
-
ticket,
|
|
369
|
-
ok,
|
|
370
|
-
}: {
|
|
371
|
-
ticket: number
|
|
372
|
-
ok: boolean
|
|
373
|
-
}): JournalEntry => ({
|
|
374
|
-
kind: 'red_check',
|
|
375
|
-
ticket,
|
|
376
|
-
role: null,
|
|
377
|
-
content: {
|
|
378
|
-
ok,
|
|
379
|
-
problems: ok ? [] : ['"sum adds two numbers" passes already'],
|
|
380
|
-
notes: [],
|
|
381
|
-
tests: {
|
|
382
|
-
...emptyTestRun(),
|
|
383
|
-
output: ok ? '1 fail' : '(pass) sum adds two numbers',
|
|
384
|
-
},
|
|
385
|
-
},
|
|
386
|
-
})
|
|
387
|
-
|
|
388
|
-
export const leftoverScan = ({
|
|
389
|
-
ticket,
|
|
390
|
-
stage,
|
|
391
|
-
hits,
|
|
392
|
-
}: {
|
|
393
|
-
/** `null` for the final review. */
|
|
394
|
-
ticket: number | null
|
|
395
|
-
stage: CommitStage
|
|
396
|
-
hits?: { path: string; reason: string }[]
|
|
397
|
-
}): JournalEntry => ({
|
|
398
|
-
kind: 'leftover_scan',
|
|
399
|
-
ticket,
|
|
400
|
-
role: null,
|
|
401
|
-
content: { stage, hits: hits ?? [] },
|
|
402
|
-
})
|
|
403
|
-
|
|
404
|
-
export const commitMade = ({
|
|
405
|
-
ticket,
|
|
406
|
-
stage,
|
|
407
|
-
sha,
|
|
408
|
-
files,
|
|
409
|
-
}: {
|
|
410
|
-
/** `null` for the final review. */
|
|
411
|
-
ticket: number | null
|
|
412
|
-
stage: CommitStage
|
|
413
|
-
/** Defaults to `<stage>-sha`. */
|
|
414
|
-
sha?: string
|
|
415
|
-
files?: string[]
|
|
416
|
-
}): JournalEntry => ({
|
|
417
|
-
kind: 'commit_made',
|
|
418
|
-
ticket,
|
|
419
|
-
role: null,
|
|
420
|
-
content: {
|
|
421
|
-
stage,
|
|
422
|
-
sha: sha ?? `${stage}-sha`,
|
|
423
|
-
message: stage,
|
|
424
|
-
files: files ?? [],
|
|
425
|
-
},
|
|
426
|
-
})
|
|
427
|
-
|
|
428
|
-
export const implemented = ({
|
|
429
|
-
ticket,
|
|
430
|
-
outcome,
|
|
431
|
-
session_id,
|
|
432
|
-
reason,
|
|
433
|
-
assumptions,
|
|
434
|
-
finding_responses,
|
|
435
|
-
run_notes,
|
|
436
|
-
}: {
|
|
437
|
-
/** `null` for the final review. */
|
|
438
|
-
ticket: number | null
|
|
439
|
-
outcome?: 'done' | 'bad_test'
|
|
440
|
-
/** Defaults to `SESSIONS.implementer`. */
|
|
441
|
-
session_id?: string
|
|
442
|
-
/** The bad test's reason. Defaults to "Wrong sum." */
|
|
443
|
-
reason?: string
|
|
444
|
-
assumptions?: string[]
|
|
445
|
-
finding_responses?: FindingResponse[]
|
|
446
|
-
/** Defaults to none. */
|
|
447
|
-
run_notes?: string[]
|
|
448
|
-
}): JournalEntry => ({
|
|
449
|
-
kind: 'agent_finished',
|
|
450
|
-
ticket,
|
|
451
|
-
role: 'implementer',
|
|
452
|
-
content: {
|
|
453
|
-
role: 'implementer',
|
|
454
|
-
session_id: session_id ?? SESSIONS.implementer,
|
|
455
|
-
result: {
|
|
456
|
-
outcome: outcome ?? 'done',
|
|
457
|
-
bad_test:
|
|
458
|
-
outcome === 'bad_test'
|
|
459
|
-
? {
|
|
460
|
-
file: 'src/sum.test.ts',
|
|
461
|
-
name: 'sum adds two numbers',
|
|
462
|
-
reason: reason ?? 'Wrong sum.',
|
|
463
|
-
}
|
|
464
|
-
: null,
|
|
465
|
-
summary: 'Added sum.',
|
|
466
|
-
assumptions: assumptions ?? [],
|
|
467
|
-
run_notes: run_notes ?? [],
|
|
468
|
-
finding_responses: finding_responses ?? [],
|
|
469
|
-
},
|
|
470
|
-
},
|
|
471
|
-
})
|
|
472
|
-
|
|
473
|
-
export const gatesRun = ({
|
|
474
|
-
ticket,
|
|
475
|
-
target,
|
|
476
|
-
ok,
|
|
477
|
-
}: {
|
|
478
|
-
/** `null` for the final review. */
|
|
479
|
-
ticket: number | null
|
|
480
|
-
target: 'ticket' | 'run_branch'
|
|
481
|
-
ok: boolean
|
|
482
|
-
}): JournalEntry => ({
|
|
483
|
-
kind: 'gates_run',
|
|
484
|
-
ticket,
|
|
485
|
-
role: null,
|
|
486
|
-
content: {
|
|
487
|
-
target,
|
|
488
|
-
ok,
|
|
489
|
-
checks: [
|
|
490
|
-
{
|
|
491
|
-
name: 'test',
|
|
492
|
-
command: 'bun test',
|
|
493
|
-
ok,
|
|
494
|
-
exit_code: ok ? 0 : 1,
|
|
495
|
-
output: ok ? '' : '1 fail',
|
|
496
|
-
},
|
|
497
|
-
],
|
|
498
|
-
},
|
|
499
|
-
})
|
|
500
|
-
|
|
501
|
-
/** One reviewer finding; a code should-fix in `src/sum.ts` unless told otherwise. */
|
|
502
|
-
export const finding = ({
|
|
503
|
-
id,
|
|
504
|
-
severity,
|
|
505
|
-
kind,
|
|
506
|
-
title,
|
|
507
|
-
file,
|
|
508
|
-
}: {
|
|
509
|
-
id: string
|
|
510
|
-
severity?: 'blocker' | 'should_fix' | 'nit'
|
|
511
|
-
kind?: 'code' | 'test'
|
|
512
|
-
title?: string
|
|
513
|
-
file?: string | null
|
|
514
|
-
}): Finding => ({
|
|
515
|
-
id,
|
|
516
|
-
severity: severity ?? 'should_fix',
|
|
517
|
-
kind: kind ?? 'code',
|
|
518
|
-
file: file === undefined ? 'src/sum.ts' : file,
|
|
519
|
-
title: title ?? `Finding ${id}`,
|
|
520
|
-
detail: `Detail of ${id}.`,
|
|
521
|
-
})
|
|
522
|
-
|
|
523
|
-
/**
|
|
524
|
-
* A ticket reviewer's result. The verdict follows the findings: changes are
|
|
525
|
-
* requested when any is a blocker or should-fix.
|
|
526
|
-
*/
|
|
527
|
-
export const reviewed = ({
|
|
528
|
-
ticket,
|
|
529
|
-
findings,
|
|
530
|
-
rulings,
|
|
531
|
-
session_id,
|
|
532
|
-
}: {
|
|
533
|
-
ticket: number
|
|
534
|
-
findings?: Finding[]
|
|
535
|
-
rulings?: FindingRuling[]
|
|
536
|
-
/** Defaults to `SESSIONS['ticket-reviewer']`. */
|
|
537
|
-
session_id?: string
|
|
538
|
-
}): JournalEntry => {
|
|
539
|
-
const list = findings ?? []
|
|
540
|
-
const blocking = list.some(({ severity }) => severity !== 'nit')
|
|
541
|
-
return {
|
|
542
|
-
kind: 'agent_finished',
|
|
543
|
-
ticket,
|
|
544
|
-
role: 'ticket-reviewer',
|
|
545
|
-
content: {
|
|
546
|
-
role: 'ticket-reviewer',
|
|
547
|
-
session_id: session_id ?? SESSIONS['ticket-reviewer'],
|
|
548
|
-
result: {
|
|
549
|
-
verdict: blocking ? 'changes_requested' : 'approve',
|
|
550
|
-
findings: list,
|
|
551
|
-
rulings: rulings ?? [],
|
|
552
|
-
summary: 'Looks right.',
|
|
553
|
-
assumptions: [],
|
|
554
|
-
},
|
|
555
|
-
},
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
/** An agent turn failed, in the session its role's fixtures use unless told otherwise. */
|
|
560
|
-
export const agentFailed = ({
|
|
561
|
-
ticket,
|
|
562
|
-
role,
|
|
563
|
-
failure,
|
|
564
|
-
error,
|
|
565
|
-
session_id,
|
|
566
|
-
}: {
|
|
567
|
-
/** `null` for the final review. */
|
|
568
|
-
ticket: number | null
|
|
569
|
-
role: AgentRole
|
|
570
|
-
failure: 'agent' | 'result' | 'guard' | 'engine'
|
|
571
|
-
/** Defaults to "It broke." */
|
|
572
|
-
error?: string
|
|
573
|
-
/** Defaults to `SESSIONS[role]`; `null` for a turn with no session. */
|
|
574
|
-
session_id?: string | null
|
|
575
|
-
}): JournalEntry => ({
|
|
576
|
-
kind: 'agent_failed',
|
|
577
|
-
ticket,
|
|
578
|
-
role,
|
|
579
|
-
content: {
|
|
580
|
-
role,
|
|
581
|
-
failure,
|
|
582
|
-
error: error ?? 'It broke.',
|
|
583
|
-
session_id: session_id === undefined ? SESSIONS[role] : session_id,
|
|
584
|
-
},
|
|
585
|
-
})
|
|
586
|
-
|
|
587
|
-
/** The engine threw away a ticket worktree's uncommitted changes. */
|
|
588
|
-
export const worktreeReset = ({
|
|
589
|
-
ticket,
|
|
590
|
-
}: {
|
|
591
|
-
ticket: number
|
|
592
|
-
}): JournalEntry => ({
|
|
593
|
-
kind: 'worktree_reset',
|
|
594
|
-
ticket,
|
|
595
|
-
role: null,
|
|
596
|
-
content: { sha: 'red-sha' },
|
|
597
|
-
})
|
|
598
|
-
|
|
599
|
-
export const joined = ({ ticket }: { ticket: number }): JournalEntry => ({
|
|
600
|
-
kind: 'ticket_joined',
|
|
601
|
-
ticket,
|
|
602
|
-
role: null,
|
|
603
|
-
content: { ok: true, shas: ['r1', 'g1'] },
|
|
604
|
-
})
|
|
605
|
-
|
|
606
|
-
/** A join whose cherry-pick clashed with the run branch (git aborted it). */
|
|
607
|
-
export const joinClashed = ({
|
|
608
|
-
ticket,
|
|
609
|
-
error,
|
|
610
|
-
}: {
|
|
611
|
-
ticket: number
|
|
612
|
-
/** Defaults to a conflict in `src/index.ts`. */
|
|
613
|
-
error?: string
|
|
614
|
-
}): JournalEntry => ({
|
|
615
|
-
kind: 'ticket_joined',
|
|
616
|
-
ticket,
|
|
617
|
-
role: null,
|
|
618
|
-
content: { ok: false, error: error ?? 'CONFLICT (content): src/index.ts' },
|
|
619
|
-
})
|
|
620
|
-
|
|
621
|
-
/** The engine put a ticket's change back on top of the run branch. */
|
|
622
|
-
export const ticketRebased = ({
|
|
623
|
-
ticket,
|
|
624
|
-
cause,
|
|
625
|
-
tests,
|
|
626
|
-
code,
|
|
627
|
-
undone,
|
|
628
|
-
}: {
|
|
629
|
-
ticket: number
|
|
630
|
-
cause: 'clash' | 'join_gates'
|
|
631
|
-
/** The test files that clashed. Defaults to none. */
|
|
632
|
-
tests?: string[]
|
|
633
|
-
/** The code files that clashed. Defaults to none. */
|
|
634
|
-
code?: string[]
|
|
635
|
-
/** The run branch commits undone first. Defaults to none. */
|
|
636
|
-
undone?: string[]
|
|
637
|
-
}): JournalEntry => ({
|
|
638
|
-
kind: 'ticket_rebased',
|
|
639
|
-
ticket,
|
|
640
|
-
role: null,
|
|
641
|
-
content: {
|
|
642
|
-
cause,
|
|
643
|
-
base_sha: 'onto-sha',
|
|
644
|
-
tests: tests ?? [],
|
|
645
|
-
code: code ?? [],
|
|
646
|
-
undone: undone ?? [],
|
|
647
|
-
},
|
|
648
|
-
})
|
|
649
|
-
|
|
650
|
-
/** The engine removed these worktrees at the end of the run. */
|
|
651
|
-
export const worktreesRemoved = ({
|
|
652
|
-
paths,
|
|
653
|
-
}: {
|
|
654
|
-
paths: string[]
|
|
655
|
-
}): JournalEntry => ({
|
|
656
|
-
kind: 'worktrees_removed',
|
|
657
|
-
ticket: null,
|
|
658
|
-
role: null,
|
|
659
|
-
content: { paths },
|
|
660
|
-
})
|
|
661
|
-
|
|
662
|
-
/** The run's one PR, #99, opened from the run branch. */
|
|
663
|
-
export const pullRequestOpened = (): JournalEntry => ({
|
|
664
|
-
kind: 'pull_request_opened',
|
|
665
|
-
ticket: null,
|
|
666
|
-
role: null,
|
|
667
|
-
content: {
|
|
668
|
-
number: 99,
|
|
669
|
-
url: 'https://github.com/acme/app/pull/99',
|
|
670
|
-
head: RUN_BRANCH,
|
|
671
|
-
base: 'main',
|
|
672
|
-
title: 'Practice spec (#10)',
|
|
673
|
-
body: '',
|
|
674
|
-
},
|
|
675
|
-
})
|
|
676
|
-
|
|
677
|
-
export const ticketStuck = ({
|
|
678
|
-
ticket,
|
|
679
|
-
reason,
|
|
680
|
-
detail,
|
|
681
|
-
}: {
|
|
682
|
-
ticket: number
|
|
683
|
-
reason: StuckReason
|
|
684
|
-
/** Defaults to "why". */
|
|
685
|
-
detail?: string
|
|
686
|
-
}): JournalEntry => ({
|
|
687
|
-
kind: 'ticket_stuck',
|
|
688
|
-
ticket,
|
|
689
|
-
role: null,
|
|
690
|
-
content: { reason, detail: detail ?? 'why' },
|
|
691
|
-
})
|
|
692
|
-
|
|
693
|
-
export const pushed = ({
|
|
694
|
-
ticket,
|
|
695
|
-
sha,
|
|
696
|
-
}: {
|
|
697
|
-
/** `null` for the final review's push. */
|
|
698
|
-
ticket: number | null
|
|
699
|
-
/** Defaults to `g1`. */
|
|
700
|
-
sha?: string
|
|
701
|
-
}): JournalEntry => ({
|
|
702
|
-
kind: 'run_branch_pushed',
|
|
703
|
-
ticket,
|
|
704
|
-
role: null,
|
|
705
|
-
content: { branch: RUN_BRANCH, sha: sha ?? 'g1' },
|
|
706
|
-
})
|
|
707
|
-
|
|
708
|
-
/** Every step of one ticket, from its worktree to the push, all passing. */
|
|
709
|
-
export const ticketBuilt = ({ ticket }: { ticket: number }): JournalEntry[] => [
|
|
710
|
-
ticketWorktreeCreated({ ticket }),
|
|
711
|
-
baselineTests({ ticket }),
|
|
712
|
-
testsWritten({ ticket }),
|
|
713
|
-
redCheck({ ticket, ok: true }),
|
|
714
|
-
leftoverScan({ ticket, stage: 'red' }),
|
|
715
|
-
commitMade({ ticket, stage: 'red' }),
|
|
716
|
-
implemented({ ticket }),
|
|
717
|
-
gatesRun({ ticket, target: 'ticket', ok: true }),
|
|
718
|
-
leftoverScan({ ticket, stage: 'green' }),
|
|
719
|
-
commitMade({ ticket, stage: 'green' }),
|
|
720
|
-
reviewed({ ticket }),
|
|
721
|
-
joined({ ticket }),
|
|
722
|
-
gatesRun({ ticket, target: 'run_branch', ok: true }),
|
|
723
|
-
pushed({ ticket }),
|
|
724
|
-
]
|
|
725
|
-
|
|
726
|
-
/** Seconds since the epoch for an ISO time, as `resetsAt` gives it. */
|
|
727
|
-
export const epochSeconds = (iso: string): number =>
|
|
728
|
-
Math.floor(Date.parse(iso) / 1000)
|
|
729
|
-
|
|
730
|
-
/**
|
|
731
|
-
* One `rate_limit_event`'s info as the SDK sends it, with the windows'
|
|
732
|
-
* utilization under `unifiedWindows` as real readings have it.
|
|
733
|
-
*/
|
|
734
|
-
export const rateLimitReading = ({
|
|
735
|
-
status,
|
|
736
|
-
rate_limit_type,
|
|
737
|
-
resets_at,
|
|
738
|
-
is_using_overage,
|
|
739
|
-
windows,
|
|
740
|
-
}: {
|
|
741
|
-
status: 'allowed' | 'allowed_warning' | 'rejected'
|
|
742
|
-
/** Defaults to `five_hour`. */
|
|
743
|
-
rate_limit_type?: string
|
|
744
|
-
/** An ISO time; leave it out for a reading with no `resetsAt`. */
|
|
745
|
-
resets_at?: string
|
|
746
|
-
is_using_overage?: boolean
|
|
747
|
-
/** Utilization (0 to 1) per window, such as `{ five_hour: 0.2 }`. */
|
|
748
|
-
windows?: Record<string, number>
|
|
749
|
-
}): Record<string, unknown> => ({
|
|
750
|
-
status,
|
|
751
|
-
rateLimitType: rate_limit_type ?? 'five_hour',
|
|
752
|
-
...(resets_at === undefined ? {} : { resetsAt: epochSeconds(resets_at) }),
|
|
753
|
-
overageStatus: 'rejected',
|
|
754
|
-
overageDisabledReason: 'org_level_disabled',
|
|
755
|
-
isUsingOverage: is_using_overage ?? false,
|
|
756
|
-
unifiedWindows: Object.fromEntries(
|
|
757
|
-
Object.entries(windows ?? {}).map(([name, utilization]) => [
|
|
758
|
-
name,
|
|
759
|
-
{ utilization },
|
|
760
|
-
])
|
|
761
|
-
),
|
|
762
|
-
})
|
|
763
|
-
|
|
764
|
-
/** The launcher's summary of one agent turn, with these readings and tokens. */
|
|
765
|
-
export const agentSession = ({
|
|
766
|
-
ticket,
|
|
767
|
-
role,
|
|
768
|
-
rate_limit_events,
|
|
769
|
-
billing_error,
|
|
770
|
-
output_tokens,
|
|
771
|
-
}: {
|
|
772
|
-
/** `null` for the final review. */
|
|
773
|
-
ticket: number | null
|
|
774
|
-
role: AgentRole
|
|
775
|
-
rate_limit_events?: Record<string, unknown>[]
|
|
776
|
-
billing_error?: boolean
|
|
777
|
-
/** Defaults to 100; input tokens are always 10. */
|
|
778
|
-
output_tokens?: number
|
|
779
|
-
}): JournalEntry => ({
|
|
780
|
-
kind: 'agent_session',
|
|
781
|
-
ticket,
|
|
782
|
-
role,
|
|
783
|
-
content: {
|
|
784
|
-
role,
|
|
785
|
-
session: {
|
|
786
|
-
session_id: SESSIONS[role],
|
|
787
|
-
usage: {
|
|
788
|
-
input_tokens: 10,
|
|
789
|
-
output_tokens: output_tokens ?? 100,
|
|
790
|
-
cache_read_input_tokens: 0,
|
|
791
|
-
cache_creation_input_tokens: 0,
|
|
792
|
-
},
|
|
793
|
-
rate_limit_events: rate_limit_events ?? [],
|
|
794
|
-
billing_error: billing_error ?? false,
|
|
795
|
-
},
|
|
796
|
-
},
|
|
797
|
-
})
|
|
798
|
-
|
|
799
|
-
/** A limit wait started, hit by #11's test-writer unless told otherwise. */
|
|
800
|
-
export const limitWaitStarted = ({
|
|
801
|
-
until,
|
|
802
|
-
resets_at,
|
|
803
|
-
rate_limit_type,
|
|
804
|
-
}: {
|
|
805
|
-
until: string
|
|
806
|
-
resets_at: string | null
|
|
807
|
-
/** Defaults to `five_hour`. */
|
|
808
|
-
rate_limit_type?: string
|
|
809
|
-
}): JournalEntry => ({
|
|
810
|
-
kind: 'limit_wait_started',
|
|
811
|
-
ticket: null,
|
|
812
|
-
role: null,
|
|
813
|
-
content: {
|
|
814
|
-
until,
|
|
815
|
-
resets_at,
|
|
816
|
-
rate_limit_type: rate_limit_type ?? 'five_hour',
|
|
817
|
-
hit_ticket: 11,
|
|
818
|
-
hit_role: 'test-writer',
|
|
819
|
-
},
|
|
820
|
-
})
|
|
821
|
-
|
|
822
|
-
export const limitWaitEnded = ({ until }: { until: string }): JournalEntry => ({
|
|
823
|
-
kind: 'limit_wait_ended',
|
|
824
|
-
ticket: null,
|
|
825
|
-
role: null,
|
|
826
|
-
content: { until },
|
|
827
|
-
})
|
|
828
|
-
|
|
829
|
-
/** The run stopped for good on a sign of per-token billing. */
|
|
830
|
-
export const billingStopped = ({
|
|
831
|
-
reason,
|
|
832
|
-
}: {
|
|
833
|
-
reason: string
|
|
834
|
-
}): JournalEntry => ({
|
|
835
|
-
kind: 'run_stopped',
|
|
836
|
-
ticket: null,
|
|
837
|
-
role: null,
|
|
838
|
-
content: { reason, role: null, billing: true },
|
|
839
|
-
})
|
|
840
|
-
|
|
841
|
-
/** One ticket's steps up to and including its approving review. */
|
|
842
|
-
export const ticketApproved = ({
|
|
843
|
-
ticket,
|
|
844
|
-
}: {
|
|
845
|
-
ticket: number
|
|
846
|
-
}): JournalEntry[] => ticketBuilt({ ticket }).slice(0, 11)
|
|
847
|
-
|
|
848
|
-
/** The engine told the spec issue that a ticket is stuck, in comment `comment_id`. */
|
|
849
|
-
export const stuckReported = ({
|
|
850
|
-
ticket,
|
|
851
|
-
comment_id,
|
|
852
|
-
}: {
|
|
853
|
-
ticket: number
|
|
854
|
-
/** Defaults to 100 + the ticket number. */
|
|
855
|
-
comment_id?: number
|
|
856
|
-
}): JournalEntry => ({
|
|
857
|
-
kind: 'stuck_reported',
|
|
858
|
-
ticket,
|
|
859
|
-
role: null,
|
|
860
|
-
content: { comment_id: comment_id ?? 100 + ticket, body: 'stuck' },
|
|
861
|
-
})
|
|
862
|
-
|
|
863
|
-
/** A comment the engine read on the spec issue. */
|
|
864
|
-
export const commentRead = ({
|
|
865
|
-
comment_id,
|
|
866
|
-
body,
|
|
867
|
-
author,
|
|
868
|
-
}: {
|
|
869
|
-
comment_id: number
|
|
870
|
-
body: string
|
|
871
|
-
/** Defaults to the spec's owner. */
|
|
872
|
-
author?: string
|
|
873
|
-
}): JournalEntry => ({
|
|
874
|
-
kind: 'comment_read',
|
|
875
|
-
ticket: null,
|
|
876
|
-
role: null,
|
|
877
|
-
content: { comment_id, author: author ?? SPEC_OWNER, body },
|
|
878
|
-
})
|
|
879
|
-
|
|
880
|
-
/** The engine took a reply word from the spec's owner. */
|
|
881
|
-
export const replyReceived = ({
|
|
882
|
-
word,
|
|
883
|
-
ticket,
|
|
884
|
-
comment_id,
|
|
885
|
-
}: {
|
|
886
|
-
word: 'retry' | 'skip' | 'stop' | 'ship'
|
|
887
|
-
ticket: number | null
|
|
888
|
-
comment_id: number
|
|
889
|
-
}): JournalEntry => ({
|
|
890
|
-
kind: 'reply_received',
|
|
891
|
-
ticket,
|
|
892
|
-
role: null,
|
|
893
|
-
content: { word, ticket, comment_id, author: SPEC_OWNER },
|
|
894
|
-
})
|
|
895
|
-
|
|
896
|
-
/** A retried ticket: resumed, started over, or refused. */
|
|
897
|
-
export const ticketRetried = ({
|
|
898
|
-
ticket,
|
|
899
|
-
mode,
|
|
900
|
-
}: {
|
|
901
|
-
ticket: number
|
|
902
|
-
mode: 'resume' | 'restart' | 'refused'
|
|
903
|
-
}): JournalEntry => ({
|
|
904
|
-
kind: 'ticket_retried',
|
|
905
|
-
ticket,
|
|
906
|
-
role: null,
|
|
907
|
-
content: {
|
|
908
|
-
mode,
|
|
909
|
-
base_sha: mode === 'restart' ? 'tip-sha' : null,
|
|
910
|
-
problems: mode === 'refused' ? ['no criteria'] : [],
|
|
911
|
-
answer_id: null,
|
|
912
|
-
},
|
|
913
|
-
})
|
|
914
|
-
|
|
915
|
-
/** A ticket left out of the run. */
|
|
916
|
-
export const ticketSkipped = ({
|
|
917
|
-
ticket,
|
|
918
|
-
because,
|
|
919
|
-
}: {
|
|
920
|
-
ticket: number
|
|
921
|
-
because?: number
|
|
922
|
-
}): JournalEntry => ({
|
|
923
|
-
kind: 'ticket_skipped',
|
|
924
|
-
ticket,
|
|
925
|
-
role: null,
|
|
926
|
-
content: { because: because ?? null },
|
|
927
|
-
})
|
|
928
|
-
|
|
929
|
-
export { SPEC_OWNER }
|
|
930
|
-
|
|
931
|
-
/**
|
|
932
|
-
* The scheduler started a step: `step` is its action type, plus `:<role>`
|
|
933
|
-
* for an agent's turn. `key` defaults to the ticket's number, or `run`.
|
|
934
|
-
*/
|
|
935
|
-
export const stepStarted = ({
|
|
936
|
-
ticket,
|
|
937
|
-
step,
|
|
938
|
-
key,
|
|
939
|
-
role,
|
|
940
|
-
first_seq,
|
|
941
|
-
}: {
|
|
942
|
-
ticket: number | null
|
|
943
|
-
step: string
|
|
944
|
-
key?: string
|
|
945
|
-
role?: AgentRole
|
|
946
|
-
/** The step's first try, on a redo. Defaults to `null`. */
|
|
947
|
-
first_seq?: number
|
|
948
|
-
}): JournalEntry => ({
|
|
949
|
-
kind: 'step_started',
|
|
950
|
-
ticket,
|
|
951
|
-
role: role ?? null,
|
|
952
|
-
content: {
|
|
953
|
-
key: key ?? (ticket === null ? 'run' : String(ticket)),
|
|
954
|
-
step,
|
|
955
|
-
first_seq: first_seq ?? null,
|
|
956
|
-
},
|
|
957
|
-
})
|
|
958
|
-
|
|
959
|
-
/** The scheduler saw a step settle. `key` as in `stepStarted`. */
|
|
960
|
-
export const stepEnded = ({
|
|
961
|
-
ticket,
|
|
962
|
-
step,
|
|
963
|
-
key,
|
|
964
|
-
role,
|
|
965
|
-
}: {
|
|
966
|
-
ticket: number | null
|
|
967
|
-
step: string
|
|
968
|
-
key?: string
|
|
969
|
-
role?: AgentRole
|
|
970
|
-
}): JournalEntry => ({
|
|
971
|
-
kind: 'step_ended',
|
|
972
|
-
ticket,
|
|
973
|
-
role: role ?? null,
|
|
974
|
-
content: {
|
|
975
|
-
key: key ?? (ticket === null ? 'run' : String(ticket)),
|
|
976
|
-
step,
|
|
977
|
-
},
|
|
978
|
-
})
|
|
9
|
+
export {
|
|
10
|
+
agentFailed,
|
|
11
|
+
agentSession,
|
|
12
|
+
agentStarted,
|
|
13
|
+
finding,
|
|
14
|
+
implemented,
|
|
15
|
+
nothingNewToTest,
|
|
16
|
+
reviewed,
|
|
17
|
+
SESSIONS,
|
|
18
|
+
testsWritten,
|
|
19
|
+
} from './agent-turn-fixtures'
|
|
20
|
+
export {
|
|
21
|
+
alreadyDone,
|
|
22
|
+
alreadyDoneChecked,
|
|
23
|
+
DONE_SHA,
|
|
24
|
+
ticketAlreadyDone,
|
|
25
|
+
ticketClosed,
|
|
26
|
+
} from './already-done-fixtures'
|
|
27
|
+
export { SPEC_OWNER } from './intake-fixtures'
|
|
28
|
+
export {
|
|
29
|
+
billingStopped,
|
|
30
|
+
epochSeconds,
|
|
31
|
+
limitWaitEnded,
|
|
32
|
+
limitWaitStarted,
|
|
33
|
+
rateLimitReading,
|
|
34
|
+
} from './limit-fixtures'
|
|
35
|
+
export {
|
|
36
|
+
commentRead,
|
|
37
|
+
replyReceived,
|
|
38
|
+
stuckReported,
|
|
39
|
+
ticketRetried,
|
|
40
|
+
ticketSkipped,
|
|
41
|
+
} from './reply-fixtures'
|
|
42
|
+
export {
|
|
43
|
+
baselineTests,
|
|
44
|
+
BUILD_CONFIG,
|
|
45
|
+
dependenciesInstalled,
|
|
46
|
+
emptyTestRun,
|
|
47
|
+
intakePassed,
|
|
48
|
+
practiceTicket,
|
|
49
|
+
pullRequestOpened,
|
|
50
|
+
RUN_BRANCH,
|
|
51
|
+
RUN_BRANCH_PATH,
|
|
52
|
+
runBranchCreated,
|
|
53
|
+
ticketPath,
|
|
54
|
+
ticketWorktreeCreated,
|
|
55
|
+
withInstalls,
|
|
56
|
+
worktreesRemoved,
|
|
57
|
+
} from './run-fixtures'
|
|
58
|
+
export { stepEnded, stepStarted } from './step-record-fixtures'
|
|
59
|
+
export {
|
|
60
|
+
commitMade,
|
|
61
|
+
gatesRun,
|
|
62
|
+
joinClashed,
|
|
63
|
+
joined,
|
|
64
|
+
leftoverScan,
|
|
65
|
+
pushed,
|
|
66
|
+
redCheck,
|
|
67
|
+
testsSentBack,
|
|
68
|
+
ticketApproved,
|
|
69
|
+
ticketBuilt,
|
|
70
|
+
ticketRebased,
|
|
71
|
+
ticketStuck,
|
|
72
|
+
worktreeReset,
|
|
73
|
+
} from './ticket-step-fixtures'
|