Files
oh-my-opencode/src/hooks/todo-continuation-enforcer/AGENTS.md
T
YeonGyu-Kim 1e7a7600a2 docs(agents-md): regenerate hierarchical AGENTS.md knowledge base for v4.1.1
Refresh all AGENTS.md files to reflect codebase state at 5ffbe0e24 (was cd31d2a1a, 197 commits behind).

Key drift corrections across 45 modified + 1 new file:

Root AGENTS.md:
- TS file counts: 1967 -> 2034 in src/ (1337 source + 697 test)
- LOC: 278k -> 292k
- Barrel index.ts: 120 -> 122
- Hook tier composition: 52/59 -> 54/61 (base/with team-mode)
- Tool Guard hooks: 14 -> 16 (add fsync-skip-warning, bash-file-read-guard)
- Add boulder feature, agent-ordering schema, .agents/ directory, v4.1.1 release tag
- Add generated/ directory entry

src/AGENTS.md:
- Subsystem inventory: agents 96->102, hooks 570->581, tools 306->314,
  features 389->400, shared 258->278, cli 150->158, plugin 55->56
- LOC totals refreshed for every subsystem
- Schema files: 32 -> 30

src/hooks/AGENTS.md:
- Tier 2 (Tool Guard): 14 -> 16 hooks, add fsyncSkipWarning row
- Total: 52 base / 59 team-mode -> 54 base / 61 team-mode
- zauc-mocks count: 7 -> 5

src/features/AGENTS.md:
- background-agent: 47 -> 57 files, mention archive fallback
- opencode-skill-loader: 33 -> 30
- tmux-subagent: 34 -> 32

src/plugin/AGENTS.md:
- Tool Guard composer count: 14 -> 16
- Aggregator total: 43 -> 45

src/cli/AGENTS.md:
- Add new boulder subcommand (BoulderState inspector)
- Command count: 6 -> 7

NEW: src/features/boulder-state/AGENTS.md
- Document the new Boulder work tracking feature
- Schema v2 with BoulderState/BoulderWorkState/TaskSessionState
- Lifecycle, storage, integration points with atlas/ralph-loop hooks

All other AGENTS.md files: Generated date 2026-05-08 -> 2026-05-14.
2026-05-14 12:57:46 +09:00

2.6 KiB

src/hooks/todo-continuation-enforcer/ — Boulder Continuation Mechanism

Generated: 2026-05-14

OVERVIEW

14 files (~2061 LOC). The "boulder" — Continuation Tier hook that forces Sisyphus to keep rolling when incomplete todos remain. Fires on session.idle, injects continuation prompt after 2s countdown toast.

HOW IT WORKS

session.idle
  → Is main session (not prometheus/compaction)? (DEFAULT_SKIP_AGENTS)
  → No abort detected recently? (ABORT_WINDOW_MS = 3s)
  → Todos still incomplete? (todo.ts)
  → No background tasks running?
  → Cooldown passed? (CONTINUATION_COOLDOWN_MS = 30s)
  → Failure count < max? (MAX_CONSECUTIVE_FAILURES = 5)
  → Start 2s countdown toast → inject CONTINUATION_PROMPT

KEY FILES

File Purpose
handler.ts createTodoContinuationHandler() — event router, delegates to idle/non-idle handlers
idle-event.ts handleSessionIdle() — main decision gate for session.idle
non-idle-events.ts handleNonIdleEvent() — handles session.error (abort detection)
session-state.ts SessionStateStore — per-session failure/abort/cooldown state
todo.ts Check todo completion status via session store
countdown.ts 2s countdown toast before injection
abort-detection.ts Detect MessageAbortedError / AbortError
continuation-injection.ts Build + inject CONTINUATION_PROMPT into session
message-directory.ts Temp dir for message injection exchange
constants.ts Timing constants, CONTINUATION_PROMPT, skip agents
types.ts SessionState, handler argument types

CONSTANTS

DEFAULT_SKIP_AGENTS = ["prometheus", "compaction", "plan"]
CONTINUATION_COOLDOWN_MS = 30_000     // 30s between injections
MAX_CONSECUTIVE_FAILURES = 5          // Then 5min pause (exponential backoff)
FAILURE_RESET_WINDOW_MS = 5 * 60_000  // 5min window for failure reset
COUNTDOWN_SECONDS = 2
ABORT_WINDOW_MS = 3000                // Grace after abort signal

STATE PER SESSION

interface SessionState {
  failureCount: number       // Consecutive failures
  lastFailureAt?: number     // Timestamp
  abortDetectedAt?: number   // Reset after ABORT_WINDOW_MS
  cooldownUntil?: number     // Next injection allowed after
  countdownTimer?: Timer     // Active countdown reference
}

RELATIONSHIP TO ATLAS

todoContinuationEnforcer handles main Sisyphus sessions only. atlasHook handles boulder/ralph/subagent sessions with a different decision gate. Both fire on session.idle but check session type first.