When a user cancels a generation (ESC x2), all three idle hooks could
enter a permanently broken state:
1. **todo-continuation-enforcer**: consecutiveFailures accumulated from
abort-caused promptAsync failures, eventually hitting MAX_CONSECUTIVE_FAILURES
and permanently stopping continuation injection.
2. **unstable-agent-babysitter**: no abort awareness at all — would keep
firing reminders after user cancelled the session.
3. **runtime-fallback**: retry dedupe keys and pending fallback state
persisted across cancellation, blocking legitimate error recovery.
Fix:
- Add shared `isAbortError()` utility for consistent abort detection
- Reset consecutiveFailures and clear stale state on AbortError in all hooks
- Track `lastCancelledAt` in todo-continuation-enforcer for abort window
- Add abort-awareness to unstable-agent-babysitter (skip if recently cancelled)
- Clear runtime-fallback retry state on abort errors
Tests: 61 pass, 0 fail across all 3 affected hook test suites.
Closes#2984
The non-interactive-env hook hardcoded shellType as 'unix', causing
'export' syntax to be used on Windows PowerShell where it doesn't work.
This caused sub-agent infinite loops on Windows as git commands would
fail with 'export: The term export is not recognized' and retry forever.
Fix: use the existing detectShellType() function which correctly detects
PowerShell (via PSModulePath), csh, cmd (win32 fallback), and unix shells.
Updated tests to verify platform-aware shell syntax selection.
Closes#3000
Add TLS requirement for HTTP hook destinations:
- Warn when plain http:// URLs are used
- Reject remote http:// in production mode
- Allow http://localhost and http://127.0.0.1 for dev
Prevents secret exfiltration over unencrypted channels.
Adds a defensive tool-pair-validator hook that runs as the final step in
the messages transform pipeline. When compaction or context-window recovery
removes user messages containing tool_result blocks without removing the
preceding assistant message with tool_use blocks, this validator detects
the mismatch and either:
1. Injects missing tool_result parts into the next user message, or
2. Creates a synthetic user message with placeholder tool_results
This prevents Anthropic API errors like 'tool_use ids found without
tool_result blocks immediately after'.
Fixes#3014
Reduce repeated session.idle work by reusing hook config loads across a short TTL and by retrying parent session lookup instead of permanently caching transient failures.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Static slash-command discovery runs before agent registration, so /start-work regressed to Sisyphus even though config-time wiring still needed Atlas-aware fallback. Split builtin command resolution so discovery stays Atlas-first while command config remains availability-aware.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Use the plugin session directory instead of process.cwd() when resolving project slash commands. This restores project and opencode-project slashcommand behavior when the runtime cwd differs from the actual session workspace.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Keep native /start-work resolvable on Sisyphus, but switch the work session back to Atlas when Atlas is registered. Stamp the outgoing agent with Atlas's actual list-display key so config→start-work execution resolves correctly and still falls back to Sisyphus when Atlas is unavailable.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
/start-work should leave plan mode even when Atlas is unavailable. This prevents Prometheus from being persisted into boulder state and keeping resumed work sessions in md-only mode.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
When claude_code integration is disabled in oh-my-opencode.json, the
rules-injector now skips loading rules from ~/.claude/rules/ to prevent
Claude Code-specific instructions from leaking into non-Claude agents
(e.g., GPT-5.4 Sisyphus), which causes agent hallucination.
Also adds ~/.sisyphus/rules/ and ~/.opencode/rules/ as OpenCode-native
user rule directories that are always searched regardless of config.
Fixes#2920
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- background_output: snapshot read cursor before consuming, restore on
/undo message removal so re-reads return data (fixes#2915)
- MCP loader: preserve oauth field in transformMcpServer, add scope/
projectPath filtering so local-scoped MCPs only load in matching
directories (fixes#2917)
- runtime-fallback: add 'reached your usage limit' to retryable error
patterns so quota exhaustion triggers model fallback (fixes#2918)
Verified: bun test (4606 pass / 0 fail), tsc --noEmit clean