@spacek33z/autoauto 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +197 -0
  2. package/package.json +51 -0
  3. package/src/App.tsx +224 -0
  4. package/src/cli.ts +772 -0
  5. package/src/components/AgentPanel.tsx +254 -0
  6. package/src/components/Chat.test.tsx +71 -0
  7. package/src/components/Chat.tsx +308 -0
  8. package/src/components/CycleField.tsx +23 -0
  9. package/src/components/ModelPicker.tsx +97 -0
  10. package/src/components/PostUpdatePrompt.tsx +46 -0
  11. package/src/components/ResultsTable.tsx +172 -0
  12. package/src/components/RunCompletePrompt.tsx +90 -0
  13. package/src/components/RunSettingsOverlay.tsx +49 -0
  14. package/src/components/RunsTable.tsx +219 -0
  15. package/src/components/StatsHeader.tsx +100 -0
  16. package/src/daemon.ts +264 -0
  17. package/src/index.tsx +8 -0
  18. package/src/lib/agent/agent-provider.test.ts +133 -0
  19. package/src/lib/agent/claude-provider.ts +277 -0
  20. package/src/lib/agent/codex-provider.ts +413 -0
  21. package/src/lib/agent/default-providers.ts +10 -0
  22. package/src/lib/agent/index.ts +32 -0
  23. package/src/lib/agent/mock-provider.ts +61 -0
  24. package/src/lib/agent/opencode-provider.ts +424 -0
  25. package/src/lib/agent/types.ts +73 -0
  26. package/src/lib/auth.ts +11 -0
  27. package/src/lib/config.ts +152 -0
  28. package/src/lib/daemon-callbacks.ts +59 -0
  29. package/src/lib/daemon-client.ts +16 -0
  30. package/src/lib/daemon-lifecycle.ts +368 -0
  31. package/src/lib/daemon-spawn.ts +122 -0
  32. package/src/lib/daemon-status.ts +189 -0
  33. package/src/lib/daemon-watcher.ts +192 -0
  34. package/src/lib/experiment-loop.ts +679 -0
  35. package/src/lib/experiment.ts +356 -0
  36. package/src/lib/finalize.test.ts +143 -0
  37. package/src/lib/finalize.ts +511 -0
  38. package/src/lib/format.test.ts +32 -0
  39. package/src/lib/format.ts +44 -0
  40. package/src/lib/git.ts +176 -0
  41. package/src/lib/ideas-backlog.test.ts +54 -0
  42. package/src/lib/ideas-backlog.ts +109 -0
  43. package/src/lib/measure.ts +472 -0
  44. package/src/lib/model-options.ts +24 -0
  45. package/src/lib/programs.ts +247 -0
  46. package/src/lib/push-stream.ts +48 -0
  47. package/src/lib/run-context.ts +112 -0
  48. package/src/lib/run-setup.ts +34 -0
  49. package/src/lib/run.ts +383 -0
  50. package/src/lib/syntax-theme.ts +39 -0
  51. package/src/lib/system-prompts/experiment.ts +77 -0
  52. package/src/lib/system-prompts/finalize.ts +90 -0
  53. package/src/lib/system-prompts/index.ts +7 -0
  54. package/src/lib/system-prompts/setup.ts +516 -0
  55. package/src/lib/system-prompts/update.ts +188 -0
  56. package/src/lib/tool-events.ts +99 -0
  57. package/src/lib/validate-measurement.ts +326 -0
  58. package/src/lib/worktree.ts +40 -0
  59. package/src/screens/AuthErrorScreen.tsx +31 -0
  60. package/src/screens/ExecutionScreen.tsx +851 -0
  61. package/src/screens/FirstSetupScreen.tsx +168 -0
  62. package/src/screens/HomeScreen.tsx +406 -0
  63. package/src/screens/PreRunScreen.tsx +206 -0
  64. package/src/screens/SettingsScreen.tsx +189 -0
  65. package/src/screens/SetupScreen.tsx +226 -0
  66. package/src/tui.tsx +17 -0
  67. package/tsconfig.json +17 -0
package/README.md ADDED
@@ -0,0 +1,197 @@
1
+ # AutoAuto
2
+
3
+ A TUI tool that makes the [autoresearch](https://github.com/karpathy/autoresearch) pattern easy to set up and run on any codebase. Define a metric, let an AI agent iteratively optimize your code, keep improvements, discard failures, loop overnight.
4
+
5
+ While autoresearch originated in ML training, AutoAuto applies it to everything: software performance, test stability, prompt optimization, search ranking, marketing copy — anything where you have code and a measurable metric. No training loops, datasets, or GPUs required.
6
+
7
+ Don't understand autoresearch or don't know what to apply it on? No problem! This tool will scan your codebase, guide you step by step to create it.
8
+
9
+ This tool takes care of everything:
10
+
11
+ * Finding autoresearch opportunities in your codebase
12
+ * Defining metrics, creating a scripts
13
+ * Defining the best settings
14
+ * Running the experiments (supports Claude, Codex and OpenCode)
15
+ * Using best practices
16
+
17
+ ## What it does
18
+
19
+ AutoAuto wraps the full autoresearch workflow — from defining what to optimize, to running hundreds of autonomous experiments, to packaging the results — into a terminal UI that handles all the tricky parts for you.
20
+
21
+ ```
22
+ ┌─ Setup ────────────────────────────────────────────────────────────┐
23
+ │ An AI agent inspects your repo, helps you define what to optimize, │
24
+ │ generates a measurement script, and validates it's stable. │
25
+ └────────────────────────────────────────────────────────────────────┘
26
+
27
+ ┌─ Execute ──────────────────────────────────────────────────────────┐
28
+ │ Autonomous loop in a background daemon: │
29
+ │ 1. Spawn a fresh agent with context from previous experiments │
30
+ │ 2. Agent makes one change and commits │
31
+ │ 3. Measure (median of N runs) │
32
+ │ 4. Keep if improved beyond noise threshold, discard otherwise │
33
+ │ 5. Repeat │
34
+ │ Runs in a git worktree — your main checkout stays clean. │
35
+ │ Survives terminal close. │
36
+ └────────────────────────────────────────────────────────────────────┘
37
+
38
+ ┌─ Finalize ─────────────────────────────────────────────────────────┐
39
+ │ Review the accumulated diff, group changes into independent │
40
+ │ branches, and produce a summary. │
41
+ └────────────────────────────────────────────────────────────────────┘
42
+ ```
43
+
44
+ ## Why use this instead of a script
45
+
46
+ Autoresearch looks simple — "just loop an agent and measure" — but real implementations fail in predictable ways. AutoAuto encodes lessons from 30+ real-world implementations so you don't have to learn the hard way:
47
+
48
+ - **Metric gaming** — Agents optimize the measurement instead of the real goal (random seed manipulation, stripping untested features, benchmark-specific hacks). AutoAuto locks measurement files, enforces scope constraints, and supports quality gates.
49
+ - **Variance** — A "3% improvement" means nothing if your measurement has 5% noise. AutoAuto validates measurement stability during setup, runs median-of-N measurements, and uses a noise threshold to filter false improvements.
50
+ - **Agent drift** — Without constraints, agents rewrite your architecture or add dependencies you never wanted. AutoAuto's `program.md` defines exactly what's in scope and off-limits.
51
+ - **Narrative momentum** — Long-running agents convince themselves their approach is working and resist changing direction. AutoAuto spawns a fresh agent per experiment with no memory except a structured context packet.
52
+ - **Recovery** — One bad experiment shouldn't corrupt the run. AutoAuto uses `git reset --hard` for clean rollback after every failure, re-baselines to detect environment drift, and auto-stops after prolonged stagnation.
53
+
54
+ ## Quick start
55
+
56
+ ### Prerequisites
57
+
58
+ - [Bun](https://bun.sh) runtime
59
+ - One of the supported AI providers:
60
+ - **Claude** — [Claude CLI](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated, or `ANTHROPIC_API_KEY` set
61
+ - **Codex** — [Codex CLI](https://github.com/openai/codex) installed
62
+ - **OpenCode** — [OpenCode](https://opencode.ai) installed
63
+
64
+ ### Install and run
65
+
66
+ TODO: add easier way to install
67
+
68
+ ```bash
69
+ git clone https://github.com/SpaceK33z/autoauto.git
70
+ cd autoauto
71
+ bun install
72
+ bun dev
73
+ ```
74
+
75
+ Or install globally:
76
+
77
+ ```bash
78
+ bun link
79
+ autoauto
80
+ ```
81
+
82
+ ### Headless CLI
83
+
84
+ AutoAuto also has a headless CLI for coding agents, CI or just generally scripting:
85
+
86
+ ```bash
87
+ autoauto list # List programs
88
+ autoauto runs <program> # List runs for a program
89
+ autoauto run <program> # Start a run
90
+ autoauto run <program> --max 50 # Run with max experiments
91
+ autoauto stop <program> # Stop after current experiment
92
+ autoauto attach <program> # Attach TUI to a running daemon
93
+ ```
94
+
95
+ ## How it works
96
+
97
+ ### 1. Setup — define what to optimize
98
+
99
+ The Setup Agent inspects your repo and walks you through an interactive chat to configure an optimization **program**:
100
+
101
+ - **Goal** — What are you optimizing? (e.g., "reduce homepage LCP", "fix flaky test suite", "improve prompt pass rate")
102
+ - **Measurement script** — A `measure.sh` that outputs a JSON object with your metric. AutoAuto validates it runs cleanly and measures variance across multiple runs.
103
+ - **Scope constraints** — Which files the agent can touch, what's off-limits, and rules it must follow.
104
+ - **Quality gates** — Secondary metrics that must stay within bounds (e.g., "CLS must remain below 0.1" while optimizing LCP).
105
+
106
+ The result is a reusable program stored in `.autoauto/programs/<name>/` — you can run it repeatedly.
107
+
108
+ ### 2. Execute — the autonomous loop
109
+
110
+ Hit run and AutoAuto:
111
+
112
+ 1. Creates a git worktree (your main checkout stays untouched)
113
+ 2. Spawns a background daemon that survives terminal close
114
+ 3. Establishes a baseline measurement
115
+ 4. Loops: spawn agent → one change → commit → measure → keep or discard → repeat
116
+
117
+ Each experiment agent gets a **context packet** — not the full chat history, but a structured summary: current baseline, recent results, git log of kept changes, diffs from recently discarded attempts, and an ideas backlog of what's been tried. This prevents repeating failed approaches while keeping context small.
118
+
119
+ The live TUI dashboard shows:
120
+
121
+ - **Stats header** — experiment count, keeps/discards, baseline vs best with improvement %, cost, and a sparkline
122
+ - **Results table** — color-coded experiment outcomes (green = kept, red = discarded)
123
+ - **Agent panel** — live streaming output from the current experiment
124
+
125
+ ### 3. Finalize — package the results
126
+
127
+ After the loop completes (or you stop it), a Finalize Agent reviews the accumulated diff and groups changes into independent branches for clean review and merge. Falls back to a single squash commit if changes are too intertwined.
128
+
129
+ ## Key safeguards
130
+
131
+ | Safeguard | What it prevents |
132
+ |-----------|-----------------|
133
+ | **Locked evaluator** — `measure.sh` + `config.json` are `chmod 444` during runs | Agent modifying the measurement to fake improvements |
134
+ | **Scope constraints** — `program.md` defines allowed files and off-limits areas | Agent drifting into unrelated code or risky changes |
135
+ | **Quality gates** — secondary metrics with hard thresholds | Agent improving one metric by degrading another |
136
+ | **Noise threshold** — improvements must exceed measured variance | False positives from measurement noise |
137
+ | **Median-of-N** — repeated measurements with median aggregation | Outlier measurements causing bad decisions |
138
+ | **One agent per experiment** — fresh context each iteration | Narrative momentum and compounding errors |
139
+ | **Git worktree isolation** — experiments run in a separate checkout | Corrupting your working directory |
140
+ | **Lock violation detection** — discards any experiment that touches `.autoauto/` | Agent tampering with its own config |
141
+ | **Re-baselining** — fresh baseline after keeps and after consecutive discards | Environment drift causing phantom improvements |
142
+ | **Stagnation detection** — auto-stops after 10 consecutive non-improving experiments | Burning money when the agent is stuck |
143
+ | **Simplicity criterion** — auto-keeps within-noise changes that reduce LOC | Rewarding code simplification even without metric gain |
144
+
145
+ ## Data model
146
+
147
+ ```
148
+ .autoauto/ # All state, gitignored automatically
149
+ config.json # Project config (models, provider)
150
+ programs/
151
+ homepage-lcp/
152
+ program.md # Agent instructions + scope constraints
153
+ measure.sh # Measurement script
154
+ config.json # Metric, direction, noise, quality gates
155
+ build.sh # Optional build step before measurement
156
+ runs/
157
+ 20260407-143022/
158
+ state.json # Run state checkpoint
159
+ results.tsv # Append-only experiment outcomes
160
+ ideas.md # Ideas backlog (optional)
161
+ stream-001.log # Per-experiment agent output
162
+ ...
163
+ worktrees/
164
+ 20260407-143022/ # Git worktree for active run
165
+ ```
166
+
167
+ ## Configuration
168
+
169
+ AutoAuto supports two model slots:
170
+
171
+ - **Execution model** — powers the experiment agents (default: Sonnet)
172
+ - **Support model** — powers setup, update, and finalize agents (default: Sonnet)
173
+
174
+ Both are configurable per-provider with effort level (low/medium/high). Override per-run from the pre-run config screen.
175
+
176
+ Supported providers: **Claude** (Agent SDK), **Codex** (CLI), **OpenCode**.
177
+
178
+ ## Stack
179
+
180
+ - **Runtime:** [Bun](https://bun.sh)
181
+ - **Language:** TypeScript (strict mode)
182
+ - **TUI:** [OpenTUI](https://opentui.com) (React reconciler for the terminal)
183
+ - **Agent:** [Claude Agent SDK](https://github.com/anthropics/claude-agent-sdk-typescript), with pluggable provider support
184
+
185
+ ## Documentation
186
+
187
+ | Doc | Contents |
188
+ |-----|----------|
189
+ | [Architecture](docs/architecture.md) | System architecture, data model, daemon design |
190
+ | [Orchestration Patterns](docs/orchestration-patterns.md) | Loop design, context packets, stopping criteria |
191
+ | [Measurement Patterns](docs/measurement-patterns.md) | Metric design, scoring approaches, variance handling |
192
+ | [Failure Patterns](docs/failure-patterns.md) | Documented failure modes and safeguards from real implementations |
193
+ | [Autoresearch Ideas](docs/autoresearch-ideas.md) | Non-ML use cases across performance, prompts, marketing, and more |
194
+
195
+ ## License
196
+
197
+ MIT
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@spacek33z/autoauto",
3
+ "version": "0.0.1",
4
+ "description": "TUI tool for autoresearch — autonomous experiment loops on any codebase",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/SpaceK33z/autoauto.git"
10
+ },
11
+ "author": "Kees Kluskens",
12
+ "homepage": "https://github.com/SpaceK33z/autoauto",
13
+ "engines": {
14
+ "bun": ">=1.0.0"
15
+ },
16
+ "keywords": [
17
+ "autoresearch",
18
+ "tui",
19
+ "ai",
20
+ "automation",
21
+ "experiments",
22
+ "claude",
23
+ "codex"
24
+ ],
25
+ "files": [
26
+ "src/",
27
+ "tsconfig.json"
28
+ ],
29
+ "scripts": {
30
+ "dev": "bun run src/index.tsx",
31
+ "build": "bun build --compile src/index.tsx --outfile dist/autoauto",
32
+ "lint": "oxlint",
33
+ "typecheck": "bun tsc --noEmit"
34
+ },
35
+ "bin": {
36
+ "autoauto": "./src/index.tsx"
37
+ },
38
+ "dependencies": {
39
+ "@anthropic-ai/claude-agent-sdk": "^0.2.92",
40
+ "@openai/codex-sdk": "^0.118.0",
41
+ "@opencode-ai/sdk": "^1.3.17",
42
+ "@opentui/core": "^0.1.97",
43
+ "@opentui/react": "^0.1.97"
44
+ },
45
+ "devDependencies": {
46
+ "@types/bun": "^1.3.11",
47
+ "@types/react": "^19.2.14",
48
+ "oxlint": "^1.58.0",
49
+ "typescript": "^5.7.0"
50
+ }
51
+ }
package/src/App.tsx ADDED
@@ -0,0 +1,224 @@
1
+ import { useState, useEffect } from "react"
2
+ import {
3
+ useKeyboard,
4
+ useRenderer,
5
+ useTerminalDimensions,
6
+ } from "@opentui/react"
7
+ import { HomeScreen } from "./screens/HomeScreen.tsx"
8
+ import { SetupScreen } from "./screens/SetupScreen.tsx"
9
+ import { SettingsScreen } from "./screens/SettingsScreen.tsx"
10
+ import { ExecutionScreen } from "./screens/ExecutionScreen.tsx"
11
+ import { PreRunScreen, type PreRunOverrides } from "./screens/PreRunScreen.tsx"
12
+ import { FirstSetupScreen } from "./screens/FirstSetupScreen.tsx"
13
+ import { PostUpdatePrompt } from "./components/PostUpdatePrompt.tsx"
14
+ import { ensureAutoAutoDir, getProjectRoot, type Screen } from "./lib/programs.ts"
15
+ import { loadProjectConfig, configExists, DEFAULT_CONFIG, type ProjectConfig } from "./lib/config.ts"
16
+ import { isRunActive } from "./lib/run.ts"
17
+
18
+ const cwd = process.cwd()
19
+
20
+ export function App() {
21
+ const renderer = useRenderer()
22
+ const { width, height } = useTerminalDimensions()
23
+ const [screen, setScreen] = useState<Screen | null>(null)
24
+ const [selectedProgram, setSelectedProgram] = useState<string | null>(null)
25
+ const [projectRoot, setProjectRoot] = useState(cwd)
26
+ const [projectConfig, setProjectConfig] = useState<ProjectConfig>(DEFAULT_CONFIG)
27
+ const [preRunOverrides, setPreRunOverrides] = useState<PreRunOverrides | null>(null)
28
+ const [attachRunId, setAttachRunId] = useState<string | null>(null)
29
+ const [attachReadOnly, setAttachReadOnly] = useState(false)
30
+ const [autoFinalize, setAutoFinalize] = useState(false)
31
+ const [updateProgramSlug, setUpdateProgramSlug] = useState<string | null>(null)
32
+ const [showPostUpdatePrompt, setShowPostUpdatePrompt] = useState(false)
33
+
34
+ useEffect(() => {
35
+ getProjectRoot(cwd).then(setProjectRoot).catch(() => {})
36
+ ensureAutoAutoDir(cwd).catch(() => {})
37
+ configExists(cwd).then((exists) => {
38
+ setScreen(exists ? "home" : "first-setup")
39
+ })
40
+ }, [])
41
+
42
+ // Load project config + reload when returning to home
43
+ useEffect(() => {
44
+ if (screen === "home") {
45
+ loadProjectConfig(cwd).then(setProjectConfig)
46
+ }
47
+ }, [screen])
48
+
49
+ useKeyboard((key) => {
50
+ if (key.name === "escape") {
51
+ if (screen === "home") {
52
+ renderer.destroy()
53
+ }
54
+ // execution screen handles its own Escape
55
+ }
56
+ })
57
+
58
+ if (!screen) {
59
+ return (
60
+ <box flexDirection="column" width={width} height={height}>
61
+ <box flexGrow={1} justifyContent="center" alignItems="center">
62
+ <text fg="#888888">Loading...</text>
63
+ </box>
64
+ </box>
65
+ )
66
+ }
67
+
68
+ const footerText =
69
+ screen === "home"
70
+ ? " n: new | e: edit | d: delete | f: finalize | s: settings | Tab: switch | Enter: run | Esc: quit"
71
+ : screen === "execution"
72
+ ? " Escape: detach (daemon continues) | Tab: switch panel | s: settings | q: stop | Ctrl+C: abort"
73
+ : screen === "settings"
74
+ ? " ↑↓: navigate | ←→: change/open | Enter: open model picker | Escape: back"
75
+ : screen === "first-setup"
76
+ ? " ↑↓: navigate | ←→: cycle | Enter: select/continue"
77
+ : " Escape: back"
78
+
79
+ return (
80
+ <box flexDirection="column" width={width} height={height}>
81
+ {screen !== "execution" && screen !== "pre-run" && (
82
+ <box
83
+ height={3}
84
+ border
85
+ borderStyle="rounded"
86
+ justifyContent="center"
87
+ alignItems="center"
88
+ >
89
+ <text>
90
+ <strong>AutoAuto</strong>
91
+ </text>
92
+ </box>
93
+ )}
94
+
95
+ <box flexDirection="column" flexGrow={1} flexShrink={1}>
96
+ {screen === "first-setup" && (
97
+ <FirstSetupScreen
98
+ cwd={cwd}
99
+ navigate={setScreen}
100
+ onConfigChange={setProjectConfig}
101
+ />
102
+ )}
103
+ {screen === "home" && (
104
+ <HomeScreen
105
+ cwd={cwd}
106
+ navigate={setScreen}
107
+ onSelectProgram={(slug) => {
108
+ setSelectedProgram(slug)
109
+ setAttachRunId(null)
110
+ setAttachReadOnly(false)
111
+ setScreen("pre-run")
112
+ }}
113
+ onSelectRun={(run) => {
114
+ if (!run.state) return
115
+ setSelectedProgram(run.state.program_slug)
116
+ setPreRunOverrides(null)
117
+ setAttachRunId(run.run_id)
118
+ setAutoFinalize(false)
119
+ setAttachReadOnly(!isRunActive(run))
120
+ setScreen("execution")
121
+ }}
122
+ onFinalizeRun={(run) => {
123
+ if (!run.state) return
124
+ setSelectedProgram(run.state.program_slug)
125
+ setPreRunOverrides(null)
126
+ setAttachRunId(run.run_id)
127
+ setAutoFinalize(true)
128
+ setAttachReadOnly(false)
129
+ setScreen("execution")
130
+ }}
131
+ onUpdateProgram={(slug) => {
132
+ setUpdateProgramSlug(slug)
133
+ setSelectedProgram(slug)
134
+ setScreen("setup")
135
+ }}
136
+ />
137
+ )}
138
+ {screen === "setup" && !showPostUpdatePrompt && (
139
+ <SetupScreen
140
+ cwd={projectRoot}
141
+ navigate={(s) => {
142
+ if (updateProgramSlug && s === "home") {
143
+ // Leaving update mode — show post-update prompt
144
+ setShowPostUpdatePrompt(true)
145
+ } else {
146
+ setUpdateProgramSlug(null)
147
+ setScreen(s)
148
+ }
149
+ }}
150
+ modelConfig={projectConfig.supportModel}
151
+ programSlug={updateProgramSlug ?? undefined}
152
+ />
153
+ )}
154
+ {screen === "setup" && showPostUpdatePrompt && selectedProgram && (
155
+ <PostUpdatePrompt
156
+ programSlug={selectedProgram}
157
+ onStartRun={() => {
158
+ setShowPostUpdatePrompt(false)
159
+ setUpdateProgramSlug(null)
160
+ setScreen("pre-run")
161
+ }}
162
+ onGoHome={() => {
163
+ setShowPostUpdatePrompt(false)
164
+ setUpdateProgramSlug(null)
165
+ setScreen("home")
166
+ }}
167
+ />
168
+ )}
169
+ {screen === "settings" && (
170
+ <SettingsScreen
171
+ cwd={cwd}
172
+ navigate={setScreen}
173
+ config={projectConfig}
174
+ onConfigChange={setProjectConfig}
175
+ />
176
+ )}
177
+ {screen === "pre-run" && selectedProgram && (
178
+ <PreRunScreen
179
+ cwd={projectRoot}
180
+ programSlug={selectedProgram}
181
+ defaultModelConfig={projectConfig.executionModel}
182
+ navigate={setScreen}
183
+ onStart={(overrides) => {
184
+ setPreRunOverrides(overrides)
185
+ setAttachRunId(null)
186
+ setAttachReadOnly(false)
187
+ setScreen("execution")
188
+ }}
189
+ />
190
+ )}
191
+ {screen === "execution" && selectedProgram && (preRunOverrides || attachRunId) && (
192
+ <ExecutionScreen
193
+ cwd={projectRoot}
194
+ programSlug={selectedProgram}
195
+ modelConfig={preRunOverrides?.modelConfig ?? projectConfig.executionModel}
196
+ supportModelConfig={projectConfig.supportModel}
197
+ ideasBacklogEnabled={projectConfig.ideasBacklogEnabled}
198
+ navigate={(s) => { setPreRunOverrides(null); setAttachRunId(null); setAttachReadOnly(false); setAutoFinalize(false); setScreen(s) }}
199
+ maxExperiments={preRunOverrides?.maxExperiments ?? 0}
200
+ useWorktree={preRunOverrides?.useWorktree ?? true}
201
+ attachRunId={attachRunId ?? undefined}
202
+ readOnly={attachReadOnly}
203
+ autoFinalize={autoFinalize}
204
+ onUpdateProgram={(slug) => {
205
+ setPreRunOverrides(null)
206
+ setAttachRunId(null)
207
+ setAttachReadOnly(false)
208
+ setAutoFinalize(false)
209
+ setUpdateProgramSlug(slug)
210
+ setSelectedProgram(slug)
211
+ setScreen("setup")
212
+ }}
213
+ />
214
+ )}
215
+ </box>
216
+
217
+ {screen !== "pre-run" && (
218
+ <box height={1} flexShrink={0} paddingX={1}>
219
+ <text fg="#888888">{footerText}</text>
220
+ </box>
221
+ )}
222
+ </box>
223
+ )
224
+ }