@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
package/engine/cli/run-modes.ts
CHANGED
|
@@ -1,157 +1,54 @@
|
|
|
1
|
-
import { existsSync, readdirSync } from 'node:fs'
|
|
2
|
-
import { mkdtemp, rm } from 'node:fs/promises'
|
|
3
|
-
import { tmpdir } from 'node:os'
|
|
4
|
-
import { join } from 'node:path'
|
|
5
|
-
|
|
6
1
|
import isEmpty from 'lodash/isEmpty'
|
|
7
|
-
import { z } from 'zod'
|
|
8
2
|
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
3
|
+
import { configReloadText } from './config-reload-text'
|
|
4
|
+
import {
|
|
5
|
+
openDecisionModel,
|
|
6
|
+
type DecisionModelSetup,
|
|
7
|
+
} from './decision-model-setup'
|
|
8
|
+
import { readRunStart } from './read-run'
|
|
9
|
+
import { driveRun, errorText, type RunEnd, type RunLauncher } from './run-end'
|
|
10
|
+
|
|
11
11
|
import type { BoardSync } from '../board/board-sync'
|
|
12
12
|
import { loadEngineConfig } from '../config/engine-config'
|
|
13
13
|
import { lucaVersion } from '../config/luca-version'
|
|
14
|
-
import { decide, type EngineAction } from '../core/decide'
|
|
15
14
|
import {
|
|
15
|
+
recordConfigReload,
|
|
16
16
|
recordResume,
|
|
17
17
|
runEngine,
|
|
18
18
|
startRun,
|
|
19
|
-
STOP_ACTIONS,
|
|
20
19
|
} from '../core/execute'
|
|
20
|
+
import type { GoingRunsReader } from '../core/execute-repo-wait'
|
|
21
|
+
import { runLiveFilePath } from '../core/live-file'
|
|
21
22
|
import { createGitAdapter } from '../git/git-adapter'
|
|
22
|
-
import {
|
|
23
|
-
import type { JevShadow } from '../jev/jev-shadow'
|
|
24
|
-
import { createJournal, runJournalPath, type Journal } from '../journal/journal'
|
|
25
|
-
import type { JournalRecord } from '../journal/journal-record'
|
|
23
|
+
import { createJournal, runJournalPath } from '../journal/journal'
|
|
26
24
|
import type { UsageLineDeps } from '../limits/usage-line'
|
|
27
25
|
import type { MemoryDeps } from '../memory/memory-client'
|
|
28
|
-
import {
|
|
29
|
-
DEMO_TURNS,
|
|
30
|
-
demoMuninn,
|
|
31
|
-
demoTracker,
|
|
32
|
-
makePracticeRepo,
|
|
33
|
-
PRACTICE_SPEC_NUMBER,
|
|
34
|
-
} from '../testing/practice-run'
|
|
35
|
-
import type { InMemoryPullRequest } from '../tracker/in-memory-tracker'
|
|
36
26
|
import type { Tracker } from '../tracker/tracker'
|
|
37
27
|
|
|
38
|
-
|
|
39
|
-
export type
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const errorText = (error: unknown): string =>
|
|
51
|
-
error instanceof Error ? error.message : String(error)
|
|
52
|
-
|
|
53
|
-
/** What a run's last action means for the person watching it. */
|
|
54
|
-
const endOf = ({ action }: { action: EngineAction }): RunEnd => {
|
|
55
|
-
if (action.type === 'invalid_journal') {
|
|
56
|
-
return {
|
|
57
|
-
ok: false,
|
|
58
|
-
message: `The journal is not a run: ${action.reason}`,
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (action.type !== 'done') {
|
|
62
|
-
return {
|
|
63
|
-
ok: false,
|
|
64
|
-
message: `The engine stopped before ${action.type}.`,
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
switch (action.outcome) {
|
|
68
|
-
case 'pr_opened':
|
|
69
|
-
return {
|
|
70
|
-
ok: true,
|
|
71
|
-
message: `PR opened: ${action.pull_request.url}`,
|
|
72
|
-
}
|
|
73
|
-
case 'nothing_to_do':
|
|
74
|
-
return {
|
|
75
|
-
ok: true,
|
|
76
|
-
message: 'Nothing to do: every ticket of the spec is closed.',
|
|
77
|
-
}
|
|
78
|
-
case 'refused':
|
|
79
|
-
return {
|
|
80
|
-
ok: false,
|
|
81
|
-
message:
|
|
82
|
-
'Intake refused the run; the spec and tickets have comments saying what is missing.',
|
|
83
|
-
}
|
|
84
|
-
case 'stopped_by_user':
|
|
85
|
-
return {
|
|
86
|
-
ok: false,
|
|
87
|
-
message:
|
|
88
|
-
"Stopped by your `stop` reply: no PR. The run branch and the unfinished tickets' worktrees are kept.",
|
|
89
|
-
}
|
|
90
|
-
case 'all_skipped':
|
|
91
|
-
return {
|
|
92
|
-
ok: true,
|
|
93
|
-
message:
|
|
94
|
-
'Every ticket was skipped, so there is no PR. The skipped tickets stay open.',
|
|
95
|
-
}
|
|
96
|
-
case 'stopped':
|
|
97
|
-
return {
|
|
98
|
-
ok: false,
|
|
99
|
-
message: `Run stopped for billing: ${action.reason}. It will not go on; start a new run once per-token billing is off.`,
|
|
100
|
-
}
|
|
101
|
-
case 'crashed':
|
|
102
|
-
return {
|
|
103
|
-
ok: false,
|
|
104
|
-
message: `Run stopped for good after crashes: ${action.reason} It will not go on; read the engine's log for why it crashed, then start a new run.`,
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Runs the engine to its end and turns what happened into a `RunEnd`, then
|
|
111
|
-
* closes the launcher's open sessions and tells the board. A crash is caught
|
|
112
|
-
* and reported, never thrown.
|
|
113
|
-
*/
|
|
114
|
-
const driveRun = async ({
|
|
115
|
-
journal,
|
|
116
|
-
run,
|
|
117
|
-
launcher,
|
|
118
|
-
memory,
|
|
119
|
-
board,
|
|
120
|
-
log,
|
|
121
|
-
}: {
|
|
122
|
-
journal: Journal
|
|
123
|
-
run: () => Promise<EngineAction>
|
|
124
|
-
launcher: RunLauncher
|
|
125
|
-
/** Closed at the end too. */
|
|
126
|
-
memory?: MemoryDeps
|
|
127
|
-
board: BoardSync | null
|
|
128
|
-
log: (line: string) => void
|
|
129
|
-
}): Promise<RunEnd> => {
|
|
130
|
-
let end: RunEnd
|
|
131
|
-
try {
|
|
132
|
-
end = endOf({ action: await run() })
|
|
133
|
-
} catch (error) {
|
|
134
|
-
const message = errorText(error)
|
|
135
|
-
// A launcher stop is journaled as run_stopped, then thrown.
|
|
136
|
-
end = message.startsWith('Run stopped:')
|
|
137
|
-
? { ok: false, message }
|
|
138
|
-
: { ok: false, message: `The engine crashed: ${message}` }
|
|
139
|
-
} finally {
|
|
140
|
-
await launcher.closeAll?.()
|
|
141
|
-
await memory?.client.close().catch(() => undefined)
|
|
142
|
-
}
|
|
143
|
-
log(`[luca-run] ${end.ok ? 'finished' : 'stopped'}: ${end.message}`)
|
|
144
|
-
await board?.end({ records: journal.read(), ...end })
|
|
145
|
-
return end
|
|
146
|
-
}
|
|
28
|
+
export { configReloadText } from './config-reload-text'
|
|
29
|
+
export type { DecisionModelSetup } from './decision-model-setup'
|
|
30
|
+
export { readRunStart, type RunStart } from './read-run'
|
|
31
|
+
export { DEMO_TURN_DELAY_MS, runDemo } from './run-demo'
|
|
32
|
+
export { resumeCommand, type RunEnd, type RunLauncher } from './run-end'
|
|
33
|
+
export {
|
|
34
|
+
restartableRuns,
|
|
35
|
+
RestartableRunSchema,
|
|
36
|
+
unfinishedRuns,
|
|
37
|
+
UnfinishedOutputSchema,
|
|
38
|
+
type RestartableRun,
|
|
39
|
+
} from './unfinished-runs'
|
|
147
40
|
|
|
148
41
|
/**
|
|
149
42
|
* A real run of `spec_number` on `repo`: loads the repo's engine config,
|
|
150
|
-
* opens (or resumes) the run's journal at `<runs_dir>/<run_id
|
|
151
|
-
*
|
|
152
|
-
*
|
|
43
|
+
* opens (or resumes) the run's journal at `<runs_dir>/<run_id>` (its live
|
|
44
|
+
* file, `live.json`, goes beside it), and runs the
|
|
45
|
+
* engine with the board kept in step, the agents from `launcher`, and the
|
|
46
|
+
* decision model in shadow mode if given (`decision_model`; with no
|
|
47
|
+
* credentials it is off for the run, see `openDecisionModel`). With `memory`, a new run turns memory on (#370),
|
|
153
48
|
* with the engine config's `muninn.vault` as the project vault (none:
|
|
154
|
-
* `default` only); a resumed run keeps what its journal says.
|
|
49
|
+
* `default` only); a resumed run keeps what its journal says. A new run
|
|
50
|
+
* stops on a bad config; a resume takes the config's build fields again
|
|
51
|
+
* and keeps its own on a bad one (`recordConfigReload`, #516). Never throws;
|
|
155
52
|
* the launcher's sessions and the memory client are closed and the board
|
|
156
53
|
* always gets the run's end.
|
|
157
54
|
*
|
|
@@ -159,7 +56,8 @@ const driveRun = async ({
|
|
|
159
56
|
* const end = await runSpec({
|
|
160
57
|
* spec_number: 374, repo: '/code/app', run_id, base_branch: null,
|
|
161
58
|
* runs_dir: defaultRunsDir(), tracker: createGitHubTracker({ repo: 'acme/app' }),
|
|
162
|
-
* launcher: createClaudeLauncher({}),
|
|
59
|
+
* launcher: createClaudeLauncher({}),
|
|
60
|
+
* decision_model: { credentials: await loadDecisionModelCredentials({ env: process.env, home: homedir() }) },
|
|
163
61
|
* board, log: console.log,
|
|
164
62
|
* })
|
|
165
63
|
*/
|
|
@@ -171,9 +69,11 @@ export const runSpec = async ({
|
|
|
171
69
|
runs_dir,
|
|
172
70
|
tracker,
|
|
173
71
|
launcher,
|
|
174
|
-
|
|
72
|
+
decision_model,
|
|
175
73
|
memory,
|
|
176
74
|
usage,
|
|
75
|
+
going_runs,
|
|
76
|
+
alongside,
|
|
177
77
|
board,
|
|
178
78
|
log,
|
|
179
79
|
luca_version = lucaVersion(),
|
|
@@ -186,12 +86,16 @@ export const runSpec = async ({
|
|
|
186
86
|
runs_dir: string
|
|
187
87
|
tracker: Tracker
|
|
188
88
|
launcher: RunLauncher
|
|
189
|
-
/**
|
|
190
|
-
|
|
89
|
+
/** The decision model's setup (#534). Leave it out to run without one. */
|
|
90
|
+
decision_model?: DecisionModelSetup
|
|
191
91
|
/** MuninnDB (#370). Leave it out to run without memory. */
|
|
192
92
|
memory?: MemoryDeps
|
|
193
93
|
/** The usage line (#434). Leave it out to run without one. */
|
|
194
94
|
usage?: UsageLineDeps
|
|
95
|
+
/** The going runs, for the repo wait (#615). Leave it out for no wait. */
|
|
96
|
+
going_runs?: GoingRunsReader
|
|
97
|
+
/** A new run skips the repo wait (`--alongside`). */
|
|
98
|
+
alongside?: boolean
|
|
195
99
|
board: BoardSync | null
|
|
196
100
|
log: (line: string) => void
|
|
197
101
|
/** Luca's version, recorded on start and resume. Defaults to the engine's own. */
|
|
@@ -203,7 +107,9 @@ export const runSpec = async ({
|
|
|
203
107
|
log(`[luca-run] spec #${spec_number} in ${repo}, run ${run_id}`)
|
|
204
108
|
log(`[luca-run] journal: ${journal.file}`)
|
|
205
109
|
const loaded = await loadEngineConfig({ repo_root: repo })
|
|
206
|
-
|
|
110
|
+
const fresh = isEmpty(journal.read())
|
|
111
|
+
// A new run needs a good config; a resume keeps its own (#516).
|
|
112
|
+
if (fresh && !loaded.ok) {
|
|
207
113
|
log(`[luca-run] stopped: ${loaded.error}`)
|
|
208
114
|
await launcher.closeAll?.()
|
|
209
115
|
await memory?.client.close().catch(() => undefined)
|
|
@@ -211,7 +117,7 @@ export const runSpec = async ({
|
|
|
211
117
|
await board?.end({ records: journal.read(), ...end })
|
|
212
118
|
return end
|
|
213
119
|
}
|
|
214
|
-
if (
|
|
120
|
+
if (fresh && loaded.ok) {
|
|
215
121
|
startRun({
|
|
216
122
|
journal,
|
|
217
123
|
spec_number,
|
|
@@ -222,14 +128,19 @@ export const runSpec = async ({
|
|
|
222
128
|
? undefined
|
|
223
129
|
: { project_vault: loaded.config.muninn?.vault ?? null },
|
|
224
130
|
repo,
|
|
131
|
+
alongside,
|
|
225
132
|
luca_version,
|
|
226
133
|
})
|
|
227
134
|
} else {
|
|
228
135
|
log('[luca-run] resuming the run from its journal')
|
|
229
136
|
recordResume({ journal, luca_version })
|
|
137
|
+
const reload = recordConfigReload({ journal, loaded })
|
|
138
|
+
if (reload !== null) log(`[luca-run] ${configReloadText({ reload })}`)
|
|
230
139
|
}
|
|
140
|
+
const jev = openDecisionModel({ setup: decision_model, journal, log })
|
|
231
141
|
return driveRun({
|
|
232
142
|
journal,
|
|
143
|
+
run_id,
|
|
233
144
|
launcher,
|
|
234
145
|
memory,
|
|
235
146
|
board,
|
|
@@ -243,185 +154,13 @@ export const runSpec = async ({
|
|
|
243
154
|
jev,
|
|
244
155
|
memory,
|
|
245
156
|
usage,
|
|
157
|
+
going_runs,
|
|
246
158
|
board: board ?? undefined,
|
|
159
|
+
live_file: runLiveFilePath({ runs_dir, run_id }),
|
|
247
160
|
}),
|
|
248
161
|
})
|
|
249
162
|
}
|
|
250
163
|
|
|
251
|
-
/** What a run's `run_started` says: its spec, base branch, and repo. */
|
|
252
|
-
export type RunStart = {
|
|
253
|
-
spec_number: number
|
|
254
|
-
base_branch: string
|
|
255
|
-
/** `null` in journals from before the repo was kept. */
|
|
256
|
-
repo: string | null
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* The records of run `run_id`, or why there are none to go on from: no
|
|
261
|
-
* journal, an empty one, or one that cannot be read. Never makes the run's
|
|
262
|
-
* folder.
|
|
263
|
-
*/
|
|
264
|
-
const readRun = ({
|
|
265
|
-
runs_dir,
|
|
266
|
-
run_id,
|
|
267
|
-
}: {
|
|
268
|
-
runs_dir: string
|
|
269
|
-
run_id: string
|
|
270
|
-
}): { ok: true; records: JournalRecord[] } | { ok: false; error: string } => {
|
|
271
|
-
const file = runJournalPath({ runs_dir, run_id })
|
|
272
|
-
if (!existsSync(file)) {
|
|
273
|
-
return { ok: false, error: `No run ${run_id}: there is no ${file}.` }
|
|
274
|
-
}
|
|
275
|
-
try {
|
|
276
|
-
const records = createJournal({ file }).read()
|
|
277
|
-
return records.length === 0
|
|
278
|
-
? {
|
|
279
|
-
ok: false,
|
|
280
|
-
error: `Run ${run_id} has an empty journal (${file}), so there is nothing to go on from; start a new run with --spec.`,
|
|
281
|
-
}
|
|
282
|
-
: { ok: true, records }
|
|
283
|
-
} catch (error) {
|
|
284
|
-
return { ok: false, error: errorText(error) }
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Reads run `run_id`'s `run_started`: the spec, base branch, and repo a
|
|
290
|
-
* resume goes on with. An error when the run has no journal, an empty one,
|
|
291
|
-
* or one that does not start with `run_started`.
|
|
292
|
-
*
|
|
293
|
-
* @example
|
|
294
|
-
* const start = readRunStart({ runs_dir: defaultRunsDir(), run_id })
|
|
295
|
-
* if (start.ok) console.log(start.start.spec_number)
|
|
296
|
-
*/
|
|
297
|
-
export const readRunStart = ({
|
|
298
|
-
runs_dir,
|
|
299
|
-
run_id,
|
|
300
|
-
}: {
|
|
301
|
-
runs_dir: string
|
|
302
|
-
run_id: string
|
|
303
|
-
}): { ok: true; start: RunStart } | { ok: false; error: string } => {
|
|
304
|
-
const read = readRun({ runs_dir, run_id })
|
|
305
|
-
if (!read.ok) return read
|
|
306
|
-
const [first] = read.records
|
|
307
|
-
if (first?.kind !== 'run_started') {
|
|
308
|
-
return {
|
|
309
|
-
ok: false,
|
|
310
|
-
error: `Run ${run_id}'s journal does not start with run_started, so it is not a run.`,
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
const { spec_number, base_branch, repo } = first.content
|
|
314
|
-
return { ok: true, start: { spec_number, base_branch, repo } }
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* The ids of the runs in `runs_dir` that are not over: runs whose journal's
|
|
319
|
-
* next action (by the decision step) is not a stop (`done` or
|
|
320
|
-
* `invalid_journal`), such as a run that crashed, was killed, or waits for a
|
|
321
|
-
* reply. Folders with no journal, an empty one, or one that cannot be read
|
|
322
|
-
* are left out. Sorted, so oldest first for made-up run ids. Paseo can
|
|
323
|
-
* `resumeRun` each one when it starts (#375).
|
|
324
|
-
*
|
|
325
|
-
* @example
|
|
326
|
-
* for (const run_id of unfinishedRuns({ runs_dir: defaultRunsDir() })) console.log(run_id)
|
|
327
|
-
*/
|
|
328
|
-
export const unfinishedRuns = ({
|
|
329
|
-
runs_dir,
|
|
330
|
-
}: {
|
|
331
|
-
runs_dir: string
|
|
332
|
-
}): string[] => {
|
|
333
|
-
if (!existsSync(runs_dir)) return []
|
|
334
|
-
return readdirSync(runs_dir, { withFileTypes: true })
|
|
335
|
-
.filter((entry) => entry.isDirectory())
|
|
336
|
-
.map(({ name }) => name)
|
|
337
|
-
.filter((run_id) => {
|
|
338
|
-
const read = readRun({ runs_dir, run_id })
|
|
339
|
-
return (
|
|
340
|
-
read.ok &&
|
|
341
|
-
!STOP_ACTIONS.has(decide({ records: read.records }).type)
|
|
342
|
-
)
|
|
343
|
-
})
|
|
344
|
-
.toSorted()
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* One unfinished run, as `luca-run --unfinished` prints it for the board
|
|
349
|
-
* plugin (#375): whether Paseo may restart it with `--resume`, and why.
|
|
350
|
-
*
|
|
351
|
-
* - `resumable`: the engine was cut off (a crash, a kill); `restart` is true.
|
|
352
|
-
* - `launcher_stopped`: its last record is a launcher stop (the wrong login,
|
|
353
|
-
* plan, or model). A restart would stop the same way, so `restart` is
|
|
354
|
-
* false; `message` is the stop's reason.
|
|
355
|
-
* - `billing_stopped`: it stopped for billing, which sticks; `restart` is
|
|
356
|
-
* false and `message` is the stop's reason.
|
|
357
|
-
*/
|
|
358
|
-
export const RestartableRunSchema = z.object({
|
|
359
|
-
run_id: z.string(),
|
|
360
|
-
restart: z.boolean(),
|
|
361
|
-
reason: z.enum(['resumable', 'launcher_stopped', 'billing_stopped']),
|
|
362
|
-
message: z.string().nullable(),
|
|
363
|
-
})
|
|
364
|
-
|
|
365
|
-
export type RestartableRun = z.infer<typeof RestartableRunSchema>
|
|
366
|
-
|
|
367
|
-
/** What `luca-run --unfinished` prints: one JSON object, snake_case keys. */
|
|
368
|
-
export const UnfinishedOutputSchema = z.object({
|
|
369
|
-
runs: z.array(RestartableRunSchema),
|
|
370
|
-
})
|
|
371
|
-
|
|
372
|
-
/** Whether Paseo may restart one unfinished run, from its records. */
|
|
373
|
-
const restartOf = ({
|
|
374
|
-
run_id,
|
|
375
|
-
records,
|
|
376
|
-
}: {
|
|
377
|
-
run_id: string
|
|
378
|
-
records: JournalRecord[]
|
|
379
|
-
}): RestartableRun => {
|
|
380
|
-
// A billing stop sticks, wherever it is in the journal.
|
|
381
|
-
const billing = records.find(
|
|
382
|
-
(record) => record.kind === 'run_stopped' && record.content.billing
|
|
383
|
-
)
|
|
384
|
-
if (billing?.kind === 'run_stopped') {
|
|
385
|
-
return {
|
|
386
|
-
run_id,
|
|
387
|
-
restart: false,
|
|
388
|
-
reason: 'billing_stopped',
|
|
389
|
-
message: billing.content.reason,
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
const last = records.at(-1)
|
|
393
|
-
if (last?.kind === 'run_stopped' && !last.content.crashed) {
|
|
394
|
-
return {
|
|
395
|
-
run_id,
|
|
396
|
-
restart: false,
|
|
397
|
-
reason: 'launcher_stopped',
|
|
398
|
-
message: last.content.reason,
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
return { run_id, restart: true, reason: 'resumable', message: null }
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* The unfinished runs in `runs_dir` (`unfinishedRuns`), each with whether
|
|
406
|
-
* Paseo may restart it with `--resume` (#375). A run whose last record is a
|
|
407
|
-
* launcher stop is not restarted, since it would stop the same way; a run
|
|
408
|
-
* with a billing stop anywhere in its journal never is. Everything else was
|
|
409
|
-
* cut off and can go on from its journal.
|
|
410
|
-
*
|
|
411
|
-
* @example
|
|
412
|
-
* const runs = restartableRuns({ runs_dir: defaultRunsDir() })
|
|
413
|
-
* // [{ run_id: 'luca-20260923-141500-ab12', restart: true, reason: 'resumable', message: null }]
|
|
414
|
-
*/
|
|
415
|
-
export const restartableRuns = ({
|
|
416
|
-
runs_dir,
|
|
417
|
-
}: {
|
|
418
|
-
runs_dir: string
|
|
419
|
-
}): RestartableRun[] =>
|
|
420
|
-
unfinishedRuns({ runs_dir }).flatMap((run_id) => {
|
|
421
|
-
const read = readRun({ runs_dir, run_id })
|
|
422
|
-
return read.ok ? [restartOf({ run_id, records: read.records })] : []
|
|
423
|
-
})
|
|
424
|
-
|
|
425
164
|
/**
|
|
426
165
|
* Goes on with run `run_id` from its journal, as `luca-run --resume` does:
|
|
427
166
|
* the spec and base branch come from its `run_started`, and the repo from
|
|
@@ -446,9 +185,10 @@ export const resumeRun = async ({
|
|
|
446
185
|
repo,
|
|
447
186
|
tracker,
|
|
448
187
|
launcher,
|
|
449
|
-
|
|
188
|
+
decision_model,
|
|
450
189
|
memory,
|
|
451
190
|
usage,
|
|
191
|
+
going_runs,
|
|
452
192
|
board,
|
|
453
193
|
log,
|
|
454
194
|
luca_version,
|
|
@@ -459,8 +199,8 @@ export const resumeRun = async ({
|
|
|
459
199
|
repo: string | null
|
|
460
200
|
tracker: ({ repo }: { repo: string }) => Tracker | Promise<Tracker>
|
|
461
201
|
launcher: RunLauncher
|
|
462
|
-
/**
|
|
463
|
-
|
|
202
|
+
/** The decision model's setup (#534). Leave it out to go on without one. */
|
|
203
|
+
decision_model?: DecisionModelSetup
|
|
464
204
|
/**
|
|
465
205
|
* MuninnDB (#370), used when the run's `run_started` turned memory on.
|
|
466
206
|
* Leave it out to go on without memory.
|
|
@@ -468,6 +208,8 @@ export const resumeRun = async ({
|
|
|
468
208
|
memory?: MemoryDeps
|
|
469
209
|
/** The usage line (#434). Leave it out to go on without one. */
|
|
470
210
|
usage?: UsageLineDeps
|
|
211
|
+
/** The going runs, so a repo wait cut off goes on (#615). */
|
|
212
|
+
going_runs?: GoingRunsReader
|
|
471
213
|
board: BoardSync | null
|
|
472
214
|
log: (line: string) => void
|
|
473
215
|
/** Luca's version, recorded on the resume. Defaults to the engine's own. */
|
|
@@ -499,131 +241,12 @@ export const resumeRun = async ({
|
|
|
499
241
|
runs_dir,
|
|
500
242
|
tracker: made,
|
|
501
243
|
launcher,
|
|
502
|
-
|
|
244
|
+
decision_model,
|
|
503
245
|
memory,
|
|
504
246
|
usage,
|
|
247
|
+
going_runs,
|
|
505
248
|
board,
|
|
506
249
|
log,
|
|
507
250
|
luca_version,
|
|
508
251
|
})
|
|
509
252
|
}
|
|
510
|
-
|
|
511
|
-
/** Wraps a launcher so each agent turn takes at least `delay_ms`. */
|
|
512
|
-
const slowLauncher = ({
|
|
513
|
-
launcher,
|
|
514
|
-
delay_ms,
|
|
515
|
-
log,
|
|
516
|
-
}: {
|
|
517
|
-
launcher: AgentLauncher
|
|
518
|
-
delay_ms: number
|
|
519
|
-
log: (line: string) => void
|
|
520
|
-
}): AgentLauncher => ({
|
|
521
|
-
launch: async (args) => {
|
|
522
|
-
log(`[luca-run] ${args.role} on #${args.ticket}`)
|
|
523
|
-
await Bun.sleep(delay_ms)
|
|
524
|
-
return launcher.launch(args)
|
|
525
|
-
},
|
|
526
|
-
followUp: async (args) => {
|
|
527
|
-
log(`[luca-run] ${args.role} on #${args.ticket} (follow-up)`)
|
|
528
|
-
await Bun.sleep(delay_ms)
|
|
529
|
-
return launcher.followUp(args)
|
|
530
|
-
},
|
|
531
|
-
closeSession: (args) => launcher.closeSession(args),
|
|
532
|
-
})
|
|
533
|
-
|
|
534
|
-
/**
|
|
535
|
-
* The demo's Jev: the real client with no key, so every ask is journaled as
|
|
536
|
-
* `jev_failed` (`missing_key`) and nothing is sent, as in a real run without
|
|
537
|
-
* `TYPESAFE_API_KEY`.
|
|
538
|
-
*/
|
|
539
|
-
const OFFLINE_JEV: JevShadow = { client: createTypeSafeJev({ api_key: '' }) }
|
|
540
|
-
|
|
541
|
-
/**
|
|
542
|
-
* A practice run, safe to try the board with: a throwaway repo with a local
|
|
543
|
-
* bare origin in a temp folder, the practice spec with two tickets (#12
|
|
544
|
-
* blocked by #11) in an in-memory tracker, and scripted agents that take
|
|
545
|
-
* `turn_delay_ms` per turn. No GitHub, no models, no network: Jev is asked in
|
|
546
|
-
* shadow mode with no key, and memory (#370) is a fake MuninnDB seeded with
|
|
547
|
-
* a few memories, so the board shows searches, the learner, and a save
|
|
548
|
-
* with nothing leaving the machine. The temp folder (which also holds the run's
|
|
549
|
-
* journal) is removed at the end.
|
|
550
|
-
*
|
|
551
|
-
* @returns The run's end, the PRs the in-memory tracker opened, and the
|
|
552
|
-
* (removed) temp folder.
|
|
553
|
-
*
|
|
554
|
-
* @example
|
|
555
|
-
* const { ok, pull_requests } = await runDemo({ run_id, board: null, log: console.log, turn_delay_ms: DEMO_TURN_DELAY_MS })
|
|
556
|
-
*/
|
|
557
|
-
export const runDemo = async ({
|
|
558
|
-
run_id,
|
|
559
|
-
board,
|
|
560
|
-
log,
|
|
561
|
-
turn_delay_ms,
|
|
562
|
-
}: {
|
|
563
|
-
run_id: string
|
|
564
|
-
board: BoardSync | null
|
|
565
|
-
log: (line: string) => void
|
|
566
|
-
turn_delay_ms: number
|
|
567
|
-
}): Promise<
|
|
568
|
-
RunEnd & { pull_requests: InMemoryPullRequest[]; root: string }
|
|
569
|
-
> => {
|
|
570
|
-
const root = await mkdtemp(join(tmpdir(), 'luca-demo-'))
|
|
571
|
-
try {
|
|
572
|
-
const { repo, origin } = await makePracticeRepo({ root })
|
|
573
|
-
const journal = createJournal({
|
|
574
|
-
file: runJournalPath({ runs_dir: join(root, 'runs'), run_id }),
|
|
575
|
-
})
|
|
576
|
-
log(`[luca-run] demo run ${run_id} in ${root}`)
|
|
577
|
-
log(`[luca-run] repo: ${repo}`)
|
|
578
|
-
log(`[luca-run] origin: ${origin}`)
|
|
579
|
-
log(`[luca-run] journal: ${journal.file}`)
|
|
580
|
-
const loaded = await loadEngineConfig({ repo_root: repo })
|
|
581
|
-
if (!loaded.ok) throw new Error(loaded.error)
|
|
582
|
-
const tracker = demoTracker()
|
|
583
|
-
startRun({
|
|
584
|
-
journal,
|
|
585
|
-
spec_number: PRACTICE_SPEC_NUMBER,
|
|
586
|
-
config: loaded.config,
|
|
587
|
-
base_branch: 'main',
|
|
588
|
-
memory: { project_vault: null },
|
|
589
|
-
repo,
|
|
590
|
-
})
|
|
591
|
-
const memory = { client: demoMuninn() }
|
|
592
|
-
const launcher = slowLauncher({
|
|
593
|
-
launcher: createScriptedLauncher({
|
|
594
|
-
turns: DEMO_TURNS,
|
|
595
|
-
}),
|
|
596
|
-
delay_ms: turn_delay_ms,
|
|
597
|
-
log,
|
|
598
|
-
})
|
|
599
|
-
const end = await driveRun({
|
|
600
|
-
journal,
|
|
601
|
-
launcher,
|
|
602
|
-
memory,
|
|
603
|
-
board,
|
|
604
|
-
log,
|
|
605
|
-
run: () =>
|
|
606
|
-
runEngine({
|
|
607
|
-
journal,
|
|
608
|
-
tracker,
|
|
609
|
-
git: createGitAdapter({ repo_root: repo }),
|
|
610
|
-
launcher,
|
|
611
|
-
jev: OFFLINE_JEV,
|
|
612
|
-
memory,
|
|
613
|
-
board: board ?? undefined,
|
|
614
|
-
}),
|
|
615
|
-
})
|
|
616
|
-
return { ...end, pull_requests: tracker.pullRequests(), root }
|
|
617
|
-
} catch (error) {
|
|
618
|
-
const end = {
|
|
619
|
-
ok: false,
|
|
620
|
-
message: `The demo crashed: ${errorText(error)}`,
|
|
621
|
-
}
|
|
622
|
-
log(`[luca-run] stopped: ${end.message}`)
|
|
623
|
-
await board?.end(end)
|
|
624
|
-
return { ...end, pull_requests: [], root }
|
|
625
|
-
} finally {
|
|
626
|
-
await rm(root, { recursive: true, force: true })
|
|
627
|
-
log(`[luca-run] removed ${root}`)
|
|
628
|
-
}
|
|
629
|
-
}
|
package/engine/cli/setup.ts
CHANGED
|
@@ -25,10 +25,9 @@ import {
|
|
|
25
25
|
import { safeMemory, type MemoryClient } from '../memory/memory-client'
|
|
26
26
|
import { runCommand } from '../shell/run-command'
|
|
27
27
|
import {
|
|
28
|
-
|
|
29
|
-
READY_LABEL,
|
|
30
|
-
REFACTOR_LABEL,
|
|
28
|
+
RELEASE_LABEL_DEFINITIONS,
|
|
31
29
|
RELEASE_LABELS,
|
|
30
|
+
RUN_LABELS,
|
|
32
31
|
type Tracker,
|
|
33
32
|
} from '../tracker/tracker'
|
|
34
33
|
|
|
@@ -86,56 +85,14 @@ export type SetupEnd = {
|
|
|
86
85
|
doctor: DoctorCheck[]
|
|
87
86
|
}
|
|
88
87
|
|
|
89
|
-
/** The labels a run needs, with what they're for. */
|
|
90
|
-
const LABELS = [
|
|
91
|
-
{
|
|
92
|
-
name: READY_LABEL,
|
|
93
|
-
color: '0e8a16',
|
|
94
|
-
description: 'Ready for a Luca run',
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
name: REFACTOR_LABEL,
|
|
98
|
-
color: '5319e7',
|
|
99
|
-
description: 'Changes shape, not behavior: no new tests',
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
name: NEEDS_INFO_LABEL,
|
|
103
|
-
color: 'd93f0b',
|
|
104
|
-
description: 'Luca needs more detail before it can build this',
|
|
105
|
-
},
|
|
106
|
-
]
|
|
107
|
-
|
|
108
|
-
/** The version-bump labels a repo with changesets gets, one per bump. */
|
|
109
|
-
const RELEASE_LABEL_INFO: Record<
|
|
110
|
-
(typeof RELEASE_LABELS)[number],
|
|
111
|
-
{ color: string; description: string }
|
|
112
|
-
> = {
|
|
113
|
-
'release:patch': {
|
|
114
|
-
color: 'c2e0c6',
|
|
115
|
-
description: "A patch bump for this spec's changeset (the default)",
|
|
116
|
-
},
|
|
117
|
-
'release:minor': {
|
|
118
|
-
color: 'fbca04',
|
|
119
|
-
description: "A minor bump for this spec's changeset",
|
|
120
|
-
},
|
|
121
|
-
'release:major': {
|
|
122
|
-
color: 'b60205',
|
|
123
|
-
description: "A major bump for this spec's changeset",
|
|
124
|
-
},
|
|
125
|
-
'release:none': {
|
|
126
|
-
color: 'ededed',
|
|
127
|
-
description: 'No version bump: an empty changeset',
|
|
128
|
-
},
|
|
129
|
-
}
|
|
130
|
-
|
|
131
88
|
/** Where a repo that uses changesets keeps their config. */
|
|
132
89
|
const CHANGESET_CONFIG_FILE = join('.changeset', 'config.json')
|
|
133
90
|
|
|
134
91
|
/** The labels `repo` needs: the run's, plus the release ones with changesets. */
|
|
135
92
|
const labelsFor = async ({ repo }: { repo: string }) => [
|
|
136
|
-
...
|
|
93
|
+
...RUN_LABELS,
|
|
137
94
|
...((await Bun.file(join(repo, CHANGESET_CONFIG_FILE)).exists())
|
|
138
|
-
? RELEASE_LABELS.map((name) =>
|
|
95
|
+
? RELEASE_LABELS.map((name) => RELEASE_LABEL_DEFINITIONS[name])
|
|
139
96
|
: []),
|
|
140
97
|
]
|
|
141
98
|
|
|
@@ -601,7 +558,7 @@ const list = (lines: string[]): string =>
|
|
|
601
558
|
|
|
602
559
|
/**
|
|
603
560
|
* Gets `repo` ready for Luca. It creates the missing `ready-for-agent`,
|
|
604
|
-
* `refactor`, and `needs-info` labels, and in a repo with
|
|
561
|
+
* `ready-for-human`, `refactor`, and `needs-info` labels, and in a repo with
|
|
605
562
|
* `.changeset/config.json` the `release:*` ones too; writes a starting
|
|
606
563
|
* `.luca/config.json` from `package.json` when there is none (see
|
|
607
564
|
* `guessChecks`), with the repo's GitHub name as its `muninn.vault`, rewrites an old-Luca config into the new shape keeping
|