fix(todo-continuation-enforcer): require boulder session for continuation

The todo-continuation-enforcer was firing boulder continuation in ALL main
sessions with incomplete todos, regardless of whether /start-work was ever
executed. This caused unwanted BOULDER CONTINUATION directives in sessions
that never invoked /start-work.

Changes:
- Add readBoulderState check in idle-event.ts to verify session is registered
  in boulder.json's session_ids array
- Change filter condition from main session check to boulder session check
- Add 4 new test cases for boulder session gate behavior
- Update all existing 41 tests to set up boulder state appropriately

Now boulder continuation only fires when:
1. Session is in boulder.json's session_ids (/start-work was executed), OR
2. Session is a background task session (subagent)

TDD cycle:
- RED: 2 new tests failed as expected (no boulder check in implementation)
- GREEN: Implementation added, all 41 tests pass
- REFACTOR: Full test suite 2513 pass, typecheck & build clean
This commit is contained in:
YeonGyu-Kim
2026-02-10 15:39:55 +09:00
parent 6917312170
commit c9364f7b6b
2 changed files with 164 additions and 40 deletions
@@ -1,7 +1,8 @@
import type { PluginInput } from "@opencode-ai/plugin"
import type { BackgroundManager } from "../../features/background-agent"
import { getMainSessionID, subagentSessions } from "../../features/claude-code-session-state"
import { readBoulderState } from "../../features/boulder-state"
import { subagentSessions } from "../../features/claude-code-session-state"
import type { ToolPermission } from "../../features/hook-message-injector"
import { log } from "../../shared/logger"
@@ -35,12 +36,12 @@ export async function handleSessionIdle(args: {
log(`[${HOOK_NAME}] session.idle`, { sessionID })
const mainSessionID = getMainSessionID()
const isMainSession = sessionID === mainSessionID
const isBackgroundTaskSession = subagentSessions.has(sessionID)
const boulderState = readBoulderState(ctx.directory)
const isBoulderSession = boulderState?.session_ids.includes(sessionID) ?? false
if (mainSessionID && !isMainSession && !isBackgroundTaskSession) {
log(`[${HOOK_NAME}] Skipped: not main or background task session`, { sessionID })
if (!isBackgroundTaskSession && !isBoulderSession) {
log(`[${HOOK_NAME}] Skipped: not boulder or background task session`, { sessionID })
return
}