Skip to content

Commit 45fc578

Browse files
Refactor loop infrastructure and TUI refresh helpers across core modules
1 parent 2b7e9e3 commit 45fc578

23 files changed

Lines changed: 581 additions & 454 deletions

‎src/cli/commands/cancel.ts‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ export async function run(argv: CancelArgs): Promise<void> {
6969

7070
if (argv.name) {
7171
const { match, candidates } = findPartialMatch(argv.name, loops, (l) => [
72-
l.state.worktreeName,
72+
l.state.loopName,
7373
l.state.worktreeBranch,
7474
])
7575

7676
if (!match && candidates.length > 0) {
7777
console.error(`Multiple loops match '${argv.name}':`)
7878
for (const c of candidates) {
79-
console.error(` - ${c.state.worktreeName}`)
79+
console.error(` - ${c.state.loopName}`)
8080
}
8181
console.error('')
8282
process.exit(1)
@@ -87,7 +87,7 @@ export async function run(argv: CancelArgs): Promise<void> {
8787
console.error('')
8888
console.error('Active loops:')
8989
for (const l of loops) {
90-
console.error(` - ${l.state.worktreeName}`)
90+
console.error(` - ${l.state.loopName}`)
9191
}
9292
console.error('')
9393
process.exit(1)
@@ -102,7 +102,7 @@ export async function run(argv: CancelArgs): Promise<void> {
102102
console.log('Multiple active loops. Please specify which one to cancel:')
103103
console.log('')
104104
for (const l of loops) {
105-
console.log(` - ${l.state.worktreeName}`)
105+
console.log(` - ${l.state.loopName}`)
106106
}
107107
console.log('')
108108
console.log("Run 'oc-forge loop cancel <name>' to cancel a specific loop.")
@@ -120,7 +120,7 @@ export async function run(argv: CancelArgs): Promise<void> {
120120

121121
console.log('')
122122
console.log(`Loop to Cancel:`)
123-
console.log(` Worktree: ${state.worktreeName}`)
123+
console.log(` Loop: ${state.loopName}`)
124124
console.log(` Session: ${state.sessionId}`)
125125
console.log(` Iteration: ${state.iteration}/${state.maxIterations}`)
126126
console.log(` Phase: ${state.phase}`)
@@ -129,7 +129,7 @@ export async function run(argv: CancelArgs): Promise<void> {
129129
}
130130
console.log('')
131131

132-
const shouldProceed = argv.force || await confirm(`Cancel loop '${state.worktreeName}'`)
132+
const shouldProceed = argv.force || await confirm(`Cancel loop '${state.loopName}'`)
133133

134134
if (!shouldProceed) {
135135
console.log('Cancelled.')
@@ -149,7 +149,7 @@ export async function run(argv: CancelArgs): Promise<void> {
149149
loopToCancel.row.key,
150150
)
151151

152-
console.log(`Cancelled loop: ${state.worktreeName}`)
152+
console.log(`Cancelled loop: ${state.loopName}`)
153153

154154
if (argv.cleanup && state.worktreeDir && state.worktree) {
155155
if (existsSync(state.worktreeDir)) {

‎src/cli/commands/restart.ts‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,14 @@ export async function run(argv: RestartArgs): Promise<void> {
8181

8282
if (argv.name) {
8383
const { match, candidates } = findPartialMatch(argv.name, loops, (l) => [
84-
l.state.worktreeName,
84+
l.state.loopName,
8585
l.state.worktreeBranch,
8686
])
8787

8888
if (!match && candidates.length > 0) {
8989
console.error(`Multiple loops match '${argv.name}':`)
9090
for (const c of candidates) {
91-
console.error(` - ${c.state.worktreeName}`)
91+
console.error(` - ${c.state.loopName}`)
9292
}
9393
console.error('')
9494
process.exit(1)
@@ -99,7 +99,7 @@ export async function run(argv: RestartArgs): Promise<void> {
9999
console.error('')
100100
console.error('Available loops:')
101101
for (const l of loops) {
102-
console.error(` - ${l.state.worktreeName}`)
102+
console.error(` - ${l.state.loopName}`)
103103
}
104104
console.error('')
105105
process.exit(1)
@@ -121,7 +121,7 @@ export async function run(argv: RestartArgs): Promise<void> {
121121
console.log('Multiple restartable loops. Please specify which one to restart:')
122122
console.log('')
123123
for (const l of restartableLoops) {
124-
console.log(` - ${l.state.worktreeName}`)
124+
console.log(` - ${l.state.loopName}`)
125125
}
126126
console.log('')
127127
console.log("Run 'oc-forge loop restart <name>' to restart a specific loop.")
@@ -139,14 +139,14 @@ export async function run(argv: RestartArgs): Promise<void> {
139139

140140
if (state.terminationReason === 'completed') {
141141
console.log('')
142-
console.log(`Loop "${state.worktreeName}" completed successfully and cannot be restarted.`)
142+
console.log(`Loop "${state.loopName}" completed successfully and cannot be restarted.`)
143143
console.log('')
144144
process.exit(1)
145145
}
146146

147147
if (!state.worktreeDir) {
148148
console.log('')
149-
console.log(`Cannot restart "${state.worktreeName}": worktree directory is missing.`)
149+
console.log(`Cannot restart "${state.loopName}": worktree directory is missing.`)
150150
console.log('')
151151
process.exit(1)
152152
}
@@ -155,7 +155,7 @@ export async function run(argv: RestartArgs): Promise<void> {
155155
const { existsSync } = await import('fs')
156156
if (!existsSync(state.worktreeDir)) {
157157
console.log('')
158-
console.log(`Cannot restart "${state.worktreeName}": worktree directory no longer exists at ${state.worktreeDir}.`)
158+
console.log(`Cannot restart "${state.loopName}": worktree directory no longer exists at ${state.worktreeDir}.`)
159159
console.log('')
160160
process.exit(1)
161161
}
@@ -164,13 +164,13 @@ export async function run(argv: RestartArgs): Promise<void> {
164164
if (state.active && !argv.force) {
165165
console.log('')
166166
console.log(`Loop to Force Restart:`)
167-
console.log(` Worktree: ${state.worktreeName}`)
167+
console.log(` Loop: ${state.loopName}`)
168168
console.log(` Session: ${state.sessionId}`)
169169
console.log(` Iteration: ${state.iteration}/${state.maxIterations}`)
170170
console.log(` Phase: ${state.phase}`)
171171
console.log('')
172172

173-
const shouldProceed = await confirm(`Force restart active loop '${state.worktreeName}'`)
173+
const shouldProceed = await confirm(`Force restart active loop '${state.loopName}'`)
174174

175175
if (!shouldProceed) {
176176
console.log('Cancelled.')
@@ -193,7 +193,7 @@ export async function run(argv: RestartArgs): Promise<void> {
193193
}
194194

195195
const createResult = await client.session.create({
196-
title: state.worktreeName,
196+
title: state.loopName,
197197
directory,
198198
permission: LOOP_PERMISSION_RULESET,
199199
})
@@ -209,7 +209,7 @@ export async function run(argv: RestartArgs): Promise<void> {
209209
db.prepare('INSERT OR REPLACE INTO project_kv (project_id, key, data, expires_at, updated_at) VALUES (?, ?, ?, ?, ?)').run(
210210
row.project_id,
211211
sessionKey,
212-
JSON.stringify(state.worktreeName),
212+
JSON.stringify(state.loopName),
213213
now + 30 * 24 * 60 * 60 * 1000,
214214
now,
215215
)
@@ -250,7 +250,7 @@ export async function run(argv: RestartArgs): Promise<void> {
250250
}
251251

252252
console.log('')
253-
console.log(`Restarted loop "${state.worktreeName}"`)
253+
console.log(`Restarted loop "${state.loopName}"`)
254254
console.log('')
255255
console.log(`New session: ${newSessionId}`)
256256
console.log(`Continuing from iteration: ${state.iteration}`)
@@ -271,7 +271,7 @@ Usage:
271271
oc-forge loop restart [name] [options]
272272
273273
Arguments:
274-
name Worktree name to restart (optional if only one active)
274+
name Loop name to restart (optional if only one active)
275275
276276
Options:
277277
--force Force restart an active loop without confirmation

‎src/cli/commands/status.ts‎

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { findPartialMatch, filterByPartial } from '../../utils/partial-match'
77

88
interface LoopInfo {
99
sessionId: string
10-
worktreeName: string
10+
loopName: string
1111
worktreeBranch?: string
1212
iteration: number
1313
maxIterations: number
@@ -81,9 +81,9 @@ export async function run(argv: StatusArgs): Promise<void> {
8181
console.error(`Failed to parse loop state for key ${row.key}:`, err)
8282
}
8383
}
84-
const filtered = filterByPartial(argv.listWorktreesFilter, states, (s) => [s.worktreeName, s.worktreeBranch])
84+
const filtered = filterByPartial(argv.listWorktreesFilter, states, (s) => [s.loopName, s.worktreeBranch])
8585
for (const state of filtered) {
86-
console.log(state.worktreeName)
86+
console.log(state.loopName)
8787
}
8888
db.close()
8989
return
@@ -116,10 +116,10 @@ export async function run(argv: StatusArgs): Promise<void> {
116116
for (const row of rows) {
117117
try {
118118
const state = JSON.parse(row.data) as LoopState
119-
if (state.active && state.sessionId && state.worktreeName && state.iteration != null && state.maxIterations != null && state.phase && state.startedAt) {
119+
if (state.active && state.sessionId && state.loopName && state.iteration != null && state.maxIterations != null && state.phase && state.startedAt) {
120120
activeLoops.push({
121121
sessionId: state.sessionId,
122-
worktreeName: state.worktreeName,
122+
loopName: state.loopName,
123123
worktreeBranch: state.worktreeBranch,
124124
iteration: state.iteration,
125125
maxIterations: state.maxIterations,
@@ -133,66 +133,66 @@ export async function run(argv: StatusArgs): Promise<void> {
133133
} catch {}
134134
}
135135

136-
const worktreeName = argv.name
136+
const loopName = argv.name
137137

138-
if (worktreeName) {
138+
if (loopName) {
139139
type LoopUnion = { type: 'active'; loop: LoopInfo } | { type: 'recent'; loop: typeof recentLoops[number] }
140140
const allLoops: LoopUnion[] = [
141141
...activeLoops.map((l) => ({ type: 'active' as const, loop: l })),
142142
...recentLoops.map((l) => ({ type: 'recent' as const, loop: l })),
143143
]
144144

145-
const { match, candidates } = findPartialMatch(worktreeName, allLoops, (l) => [
146-
l.type === 'active' ? l.loop.worktreeName : l.loop.state.worktreeName,
145+
const { match, candidates } = findPartialMatch(loopName, allLoops, (l) => [
146+
l.type === 'active' ? l.loop.loopName : l.loop.state.loopName,
147147
l.type === 'active' ? l.loop.worktreeBranch : l.loop.state.worktreeBranch,
148148
])
149149

150150
if (!match && candidates.length > 0) {
151-
console.error(`Multiple loops match '${worktreeName}':`)
151+
console.error(`Multiple loops match '${loopName}':`)
152152
for (const c of candidates) {
153-
const name = c.type === 'active' ? c.loop.worktreeName : c.loop.state.worktreeName
153+
const name = c.type === 'active' ? c.loop.loopName : c.loop.state.loopName
154154
console.error(` - ${name}`)
155155
}
156156
console.error('')
157157
process.exit(1)
158158
}
159159

160160
if (!match && candidates.length === 0) {
161-
console.error(`Loop not found: ${worktreeName}`)
161+
console.error(`Loop not found: ${loopName}`)
162162
console.error('')
163163
if (activeLoops.length > 0) {
164164
console.error('Active loops:')
165165
for (const l of activeLoops) {
166-
console.error(` - ${l.worktreeName}`)
166+
console.error(` - ${l.loopName}`)
167167
}
168168
}
169169
if (recentLoops.length > 0) {
170170
console.error('Recently completed:')
171171
for (const l of recentLoops) {
172-
console.error(` - ${l.state.worktreeName}`)
172+
console.error(` - ${l.state.loopName}`)
173173
}
174174
}
175175
console.error('')
176176
process.exit(1)
177177
}
178178

179179
const matchedLoop = match!
180-
const resolvedWorktreeName = matchedLoop.type === 'active'
181-
? matchedLoop.loop.worktreeName
182-
: matchedLoop.loop.state.worktreeName
180+
const resolvedLoopName = matchedLoop.type === 'active'
181+
? matchedLoop.loop.loopName
182+
: matchedLoop.loop.state.loopName
183183

184184
if (matchedLoop.type === 'active') {
185185
const row = rows.find((r) => {
186186
try {
187187
const state = JSON.parse(r.data) as LoopState
188-
return state.worktreeName === resolvedWorktreeName
188+
return state.loopName === resolvedLoopName
189189
} catch {
190190
return false
191191
}
192192
})
193193

194194
if (!row) {
195-
console.error(`Failed to retrieve state for: ${worktreeName}`)
195+
console.error(`Failed to retrieve state for: ${loopName}`)
196196
process.exit(1)
197197
}
198198

@@ -204,9 +204,9 @@ export async function run(argv: StatusArgs): Promise<void> {
204204
const seconds = Math.floor((duration % (1000 * 60)) / 1000)
205205

206206
console.log('')
207-
console.log(`Loop: ${state.worktreeName}`)
207+
console.log(`Loop: ${state.loopName}`)
208208
console.log(` Session ID: ${state.sessionId}`)
209-
console.log(` Worktree: ${state.worktreeName}`)
209+
console.log(` Loop Name: ${state.loopName}`)
210210
if (state.worktreeBranch) {
211211
console.log(` Branch: ${state.worktreeBranch}`)
212212
}
@@ -250,9 +250,9 @@ export async function run(argv: StatusArgs): Promise<void> {
250250
const seconds = Math.floor((duration % (1000 * 60)) / 1000)
251251

252252
console.log('')
253-
console.log(`Loop (Completed): ${state.worktreeName}`)
253+
console.log(`Loop (Completed): ${state.loopName}`)
254254
console.log(` Session ID: ${state.sessionId}`)
255-
console.log(` Worktree: ${state.worktreeName}`)
255+
console.log(` Loop Name: ${state.loopName}`)
256256
if (state.worktreeBranch) {
257257
console.log(` Branch: ${state.worktreeBranch}`)
258258
}
@@ -294,7 +294,7 @@ export async function run(argv: StatusArgs): Promise<void> {
294294
const iterStr = `${loop.iteration}/${loop.maxIterations}`
295295
const audit = loop.audit ? 'Yes' : 'No'
296296

297-
console.log(` ${loop.worktreeName}`)
297+
console.log(` ${loop.loopName}`)
298298
console.log(` Phase: ${loop.phase} Iteration: ${iterStr} Duration: ${durationStr} Audit: ${audit}`)
299299
console.log('')
300300
}
@@ -313,7 +313,7 @@ export async function run(argv: StatusArgs): Promise<void> {
313313
const reason = loop.state.terminationReason ?? 'unknown'
314314
const completed = new Date(loop.state.completedAt!).toLocaleString()
315315

316-
console.log(` ${loop.state.worktreeName}`)
316+
console.log(` ${loop.state.loopName}`)
317317
console.log(` Iterations: ${loop.state.iteration} Reason: ${reason} Completed: ${completed}`)
318318
console.log('')
319319
}

0 commit comments

Comments
 (0)