fix(atlas): pause after final verification wave for explicit user approval

This commit is contained in:
YeonGyu-Kim
2026-03-13 12:43:33 +09:00
parent fd71c89b95
commit 04b0c6f33c
9 changed files with 416 additions and 60 deletions
+8 -52
View File
@@ -1,11 +1,9 @@
import type { PluginInput } from "@opencode-ai/plugin"
import { appendSessionId, getPlanProgress, readBoulderState } from "../../features/boulder-state"
import type { BoulderState, PlanProgress } from "../../features/boulder-state"
import { subagentSessions } from "../../features/claude-code-session-state"
import { getPlanProgress, readBoulderState } from "../../features/boulder-state"
import { log } from "../../shared/logger"
import { isSessionInBoulderLineage } from "./boulder-session-lineage"
import { injectBoulderContinuation } from "./boulder-continuation-injector"
import { HOOK_NAME } from "./hook-name"
import { resolveActiveBoulderSession } from "./resolve-active-boulder-session"
import type { AtlasHookOptions, SessionState } from "./types"
const CONTINUATION_COOLDOWN_MS = 5000
@@ -19,54 +17,6 @@ function hasRunningBackgroundTasks(sessionID: string, options?: AtlasHookOptions
: false
}
async function resolveActiveBoulderSession(input: {
client: PluginInput["client"]
directory: string
sessionID: string
}): Promise<{
boulderState: BoulderState
progress: PlanProgress
appendedSession: boolean
} | null> {
const boulderState = readBoulderState(input.directory)
if (!boulderState) {
return null
}
const progress = getPlanProgress(boulderState.active_plan)
if (progress.isComplete) {
return { boulderState, progress, appendedSession: false }
}
if (boulderState.session_ids.includes(input.sessionID)) {
return { boulderState, progress, appendedSession: false }
}
if (!subagentSessions.has(input.sessionID)) {
return null
}
const belongsToActiveBoulder = await isSessionInBoulderLineage({
client: input.client,
sessionID: input.sessionID,
boulderSessionIDs: boulderState.session_ids,
})
if (!belongsToActiveBoulder) {
return null
}
const updatedBoulderState = appendSessionId(input.directory, input.sessionID)
if (!updatedBoulderState?.session_ids.includes(input.sessionID)) {
return null
}
return {
boulderState: updatedBoulderState,
progress,
appendedSession: true,
}
}
async function injectContinuation(input: {
ctx: PluginInput
sessionID: string
@@ -113,6 +63,7 @@ function scheduleRetry(input: {
sessionState.pendingRetryTimer = undefined
if (sessionState.promptFailureCount >= 2) return
if (sessionState.waitingForFinalWaveApproval) return
const currentBoulder = readBoulderState(ctx.directory)
if (!currentBoulder) return
@@ -173,6 +124,11 @@ export async function handleAtlasSessionIdle(input: {
const sessionState = getState(sessionID)
const now = Date.now()
if (sessionState.waitingForFinalWaveApproval) {
log(`[${HOOK_NAME}] Skipped: waiting for explicit final-wave approval`, { sessionID })
return
}
if (sessionState.lastEventWasAbortError) {
sessionState.lastEventWasAbortError = false
log(`[${HOOK_NAME}] Skipped: abort error immediately before idle`, { sessionID })