Skip to content

perf(hooks): add subscription-based event filtering to reduce hot-path dispatch overhead#1

Open
coleleavitt wants to merge 2 commits intodevfrom
refactor/hook-event-filtering
Open

perf(hooks): add subscription-based event filtering to reduce hot-path dispatch overhead#1
coleleavitt wants to merge 2 commits intodevfrom
refactor/hook-event-filtering

Conversation

@coleleavitt
Copy link
Owner

@coleleavitt coleleavitt commented Feb 27, 2026

Summary

  • Add HOOK_SUBSCRIPTIONS mapping: each of 21 hooks declares which event types it cares about
  • During LLM streaming (message.part.delta events at ~100/sec), 19 of 21 hooks are now skipped entirely
  • Only 3 critical hooks (claudeCodeHooks, stopContinuationGuard, writeExistingFileGuard) are awaited; 18 others fire-and-forget with .catch(log) error handling
  • Reduces async hook dispatch from ~2,100/sec to ~200/sec during streaming

Problem

The event dispatcher in event.ts dispatches every event (including high-frequency message.part.delta tokens) to all 21 hooks sequentially with await. At ~100 delta events/sec, this means ~2,100 async hook invocations per second. Most hooks don't care about delta events at all.

Combined with:

  1. opencode's reconcile() O(n) deep-diffing per token (separate PR)
  2. Bun's bmalloc SYSCALL spin loop on madvise EAGAIN (WebKit PR)

This creates enough GC pressure to trigger the bmalloc hang, freezing the TUI.

Changes

src/plugin/event.ts

New constants:

  • SESSION_LIFECYCLE: event types for session-level hooks
  • MESSAGE_EVENTS: event types for message-level hooks (no deltas)
  • HOOK_SUBSCRIPTIONS: maps each hook name → subscribed event types or "*" (all)
  • AWAITED_HOOKS: Set of 3 hooks that must be awaited

New dispatcher (dispatchToHooks):

  • Iterates hook entries, checks event type against subscriptions
  • Awaited hooks: await Promise.resolve(invoke(input))
  • Fire-and-forget hooks: Promise.resolve(invoke(input)).catch(err => log(...))

Hook subscription mapping:

Hook Subscribes To
claudeCodeHooks * (all events)
interactiveBashSession * (all events)
sessionNotification Session lifecycle
unstableAgentBabysitter Session lifecycle
runtimeFallback Session lifecycle
contextWindowMonitor Messages + session.status
writeExistingFileGuard Messages
todoContinuationEnforcer Messages
directoryAgentsInjector session.created + message.updated
... (18 more) See source

Part of a 3-layer fix

  1. Bun/WebKit (bmalloc SYSCALL EAGAIN spin loop): oven-sh/WebKit#169
  2. opencode (reconcile→path-syntax): Separate PR on coleleavitt/opencode
  3. oh-my-opencode (this PR): subscription-based hook dispatcher

Verification

  • TypeScript typecheck: ✅ (bun x tsc --noEmit — clean, no errors)

Summary by cubic

Adds subscription-based event filtering so only relevant hooks run per event, and completes lifecycle/cleanup subscriptions. This cuts hot-path dispatch during LLM token streaming (message.part.delta) from ~2,100 to ~200 async calls/sec and reduces GC pressure and UI stalls.

  • Refactors

    • Added HOOK_SUBSCRIPTIONS and event groups (SESSION_LIFECYCLE now includes session.compacted; MESSAGE_EVENTS); unlisted hooks default to "*".
    • Precomputed hookEntries and updated dispatchToHooks to filter by subscription; awaits 3 critical hooks, others fire-and-forget with error logging.
    • On message.part.delta, 19 of 21 hooks are skipped to avoid unnecessary work.
  • Bug Fixes

    • Added missing session.deleted and session.compacted subscriptions to cleanup/reset hooks.
    • Wrapped fire-and-forget invocations in Promise.resolve().then(...) to catch sync throws.

Written for commit cae1645. Summary will update on new commits.

Summary by CodeRabbit

  • Refactor
    • Overhauled internal event dispatching to a data-driven subscription model with centralized event-type filtering.
    • Introduces conditional awaiting for hooks to preserve important synchronous behavior while non-awaited hooks run resiliently with error logging.
    • Maintains backward compatibility and makes no changes to the public API.

@kusari-inspector
Copy link

⚠️ Workspace Mapping Required

Hello! We noticed that your GitHub organization is not yet mapped to a Kusari workspace. Kusari Inspector now requires installations to be associated with a Kusari workspace.

⚠️ NOTE: Only the admin who installed the Kusari GitHub App can complete these steps. If the admin is unable to complete these steps, please contact support@kusari.dev

To complete the setup:

  1. Visit https://console.us.kusari.cloud/auth/github and log in via github
  2. If you have only one workspace, it will be automatically selected for you
  3. Once the mapping is complete, return here and create a new comment with: @kusari-inspector re-run

This will trigger the analysis to run again.

For more information, or if you need help, visit https://github.com/kusaridev/community/discussions

@devloai
Copy link

devloai bot commented Feb 27, 2026

Unable to trigger custom agent "Code Reviewer". You have run out of credits 😔
Please upgrade your plan or buy additional credits from the subscription page.

@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

📝 Walkthrough

Walkthrough

The event dispatch in src/plugin/event.ts was refactored to a data-driven dispatcher: HOOK_SUBSCRIPTIONS maps hooks to event types, AWAITED_HOOKS marks hooks to await, and a dynamic loop (hookEntries) invokes matching hooks, awaiting or logging errors according to configuration while preserving existing awaited-hook behavior.

Changes

Cohort / File(s) Summary
Event Dispatch Refactor
src/plugin/event.ts
Replaced fixed sequence of awaited hook calls with a data-driven dispatch using HOOK_SUBSCRIPTIONS and AWAITED_HOOKS. Introduced hookEntries iteration to filter by event type (supports "*" default), conditionally await configured hooks, and catch/log errors for non-awaited hooks. Preserves specific awaited hooks (e.g., claudeCodeHooks, stopContinuationGuard, writeExistingFileGuard).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through hooks, rewired the flow,

Subscriptions in rows, awaits in a row,
Events now find doors they truly adore,
I log the small bumps and await what's hardcore,
A rabbit-approved dispatch — bounce and go! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding subscription-based event filtering to optimize hook dispatch during high-frequency events like message.part.delta.
Description check ✅ Passed The description comprehensively covers the problem, solution, hook subscription mapping, and verification status, aligning well with the provided template structure.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/hook-event-filtering

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Feb 27, 2026

All contributors have signed the CLA. Thank you! ✅
Posted by the CLA Assistant Lite bot.

@qodo-free-for-open-source-projects

Review Summary by Qodo

Performance optimization, Gemini model support, and comprehensive code refactoring

✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
  **Performance optimization and comprehensive refactoring:**
• Implement subscription-based hook event filtering in event.ts to reduce hot-path dispatch
  overhead during LLM streaming (~2,100/sec → ~200/sec)
• Add HOOK_SUBSCRIPTIONS mapping declaring which event types each of 21 hooks cares about
• Introduce AWAITED_HOOKS set (3 critical hooks) that must be awaited; 18 others fire-and-forget
  with error handling
• Refactor dispatchToHooks to conditionally await or fire-and-forget based on hook criticality
  **Model support and agent enhancements:**
• Add Gemini model routing to Atlas and Hephaestus agents with optimized system prompts
• Create Gemini-optimized prompts for Prometheus, Atlas, and ultrawork mode keyword detector
• Update Gemini model references from gemini-3-pro to gemini-3.1-pro across test suites and
  migrations
• Export Gemini Sisyphus Junior prompt builder
  **Code organization and maintainability:**
• Extract utility functions from background-agent manager into dedicated modules
  (error-classifier, fallback-retry-handler, process-cleanup, session-idle-event-handler,
  task-poller, duration-formatter, compaction-aware-message-resolver)
• Modularize edit operations with extracted utility functions (edit-deduplication,
  edit-ordering, edit-operation-primitives)
• Refactor edit operations API: unified op field replaces type; operation names standardized
  (insert_beforeprepend, insert_afterappend, set_linereplace)
  **Testing improvements:**
• Add 25-case comprehensive edit_file stress test suite with edge cases and whitespace handling
• Add 21-operation edit_file test suite with validation and colored output
• Add multi-model benchmark test runner for cross-model validation
• Refactor and simplify test suites: think-mode hooks (452 → 155 lines), background update checker,
  directory injectors, edit operations
• Add new error classifier utility test suite with comprehensive edge case coverage
• Update all test cases to reflect new API schemas and model naming conventions
  **Configuration and tooling:**
• Add optional threads property to GlobOptions for ripgrep thread count limiting
• Add pendingNotifications map to queue notifications when parent session is aborted
• Add isModelFallbackEnabled flag to guard model fallback logic
• Add deleteSessionTools cleanup call in session deletion handler
Diagram
flowchart LR
  A["Event Dispatcher<br/>2100 ops/sec"] -->|"Subscription Filter"| B["Hook Subscriptions<br/>19 skipped"]
  B -->|"Awaited"| C["3 Critical Hooks<br/>claudeCodeHooks<br/>stopContinuationGuard<br/>writeExistingFileGuard"]
  B -->|"Fire-and-Forget"| D["18 Other Hooks<br/>with error handling"]
  C -->|"Result"| E["Optimized Dispatch<br/>200 ops/sec"]
  D -->|"Result"| E
  F["Gemini Models"] -->|"Route"| G["Atlas Agent"]
  F -->|"Route"| H["Prometheus Agent"]
  F -->|"Route"| I["Ultrawork Mode"]
  J["Edit Operations"] -->|"Modularize"| K["Deduplication<br/>Ordering<br/>Primitives"]
  K -->|"Unified API"| L["op field<br/>prepend/append/replace"]
Loading

Grey Divider

File Changes

1. benchmarks/test-edge-cases.ts 🧪 Tests +1121/-0

Add 25-case comprehensive edit_file stress test suite

• New comprehensive test suite with 25 edge cases for edit_file operations
• Tests cover basic operations (single-line, range replace, delete), creative cases (batch edits,
 expansions, special characters), and whitespace handling
• Each test case includes file setup, LLM prompt, and validation logic to verify correct file state
• Supports CLI argument passthrough for model selection and provider configuration

benchmarks/test-edge-cases.ts


2. benchmarks/test-edit-ops.ts 🧪 Tests +808/-0

Add 21-operation edit_file test suite with validation

• New test suite with 21 operation types for edit_file functionality
• Covers 5 basic operations (replace, append, prepend, range replace, delete), 10 creative cases,
 and 6 whitespace edge cases
• Each test spawns headless mode with unique demo file and validates final file state
• Includes colored output, error reporting, and summary statistics

benchmarks/test-edit-ops.ts


3. src/plugin/event.ts ✨ Enhancement +288/-238

Implement subscription-based hook event filtering for performance

• Add subscription-based event filtering: HOOK_SUBSCRIPTIONS maps each hook to event types it
 cares about
• Introduce AWAITED_HOOKS set (3 critical hooks: claudeCodeHooks, stopContinuationGuard,
 writeExistingFileGuard) that must be awaited; others fire-and-forget with error handling
• Refactor dispatchToHooks to iterate hook entries, check event type against subscriptions, and
 conditionally await or fire-and-forget
• Add deleteSessionTools cleanup call in session deletion handler
• Add isModelFallbackEnabled flag to guard model fallback logic; fix formatting and import
 ordering

src/plugin/event.ts


View more (122)
4. src/agents/atlas/agent.ts ✨ Enhancement +11/-11

Add Gemini model routing to Atlas agent

• Add Gemini model routing: import isGeminiModel and new getGeminiAtlasPrompt function
• Extend AtlasPromptSource type to include "gemini" option
• Update getAtlasPromptSource to detect Gemini models and return "gemini"
• Update getAtlasPrompt switch statement to handle Gemini case
• Change MODE from "primary" to "all" for broader agent availability

src/agents/atlas/agent.ts


5. src/plugin-handlers/config-handler.test.ts 🧪 Tests +1/-7

Update Gemini model version in test

• Update test expectation: change expected Gemini model from "google/gemini-3-pro" to
 "google/gemini-3.1-pro"

src/plugin-handlers/config-handler.test.ts


6. src/agents/hephaestus.ts ✨ Enhancement +1/-1

Update Hephaestus agent mode to all

• Change MODE constant from "primary" to "all" to expand agent availability

src/agents/hephaestus.ts


7. src/tools/glob/types.ts ✨ Enhancement +1/-0

Add threads option to glob configuration

• Add optional threads property to GlobOptions interface to limit rg (ripgrep) thread count

src/tools/glob/types.ts


8. src/features/background-agent/manager.ts Refactoring +105/-499

Extract utility functions into dedicated modules for maintainability

• Extracted large utility functions into separate modules (error-classifier,
 fallback-retry-handler, process-cleanup, session-idle-event-handler, task-poller,
 duration-formatter, compaction-aware-message-resolver)
• Added pendingNotifications map to queue notifications when parent session is aborted
• Refactored tryFallbackRetry to delegate to extracted handler module
• Refactored pruneStaleTasksAndNotifications and checkAndInterruptStaleTasks to use extracted
 task-poller functions
• Simplified process cleanup registration by delegating to extracted registerManagerForCleanup and
 unregisterManagerForCleanup

src/features/background-agent/manager.ts


9. src/shared/model-resolver.test.ts 🧪 Tests +65/-65

Update Gemini model references to 3.1-pro version

• Updated all test cases to use google/gemini-3.1-pro instead of google/gemini-3-pro
• Ensures test data reflects current model naming conventions with dot notation

src/shared/model-resolver.test.ts


10. src/hooks/think-mode/index.test.ts 🧪 Tests +112/-409

Simplify think-mode hook tests with focused test cases

• Simplified test suite from 452 lines to 155 lines by removing extensive provider-specific tests
• Replaced ThinkModeInput type with simpler ThinkModeHookInput and ThinkModeHookOutput types
• Consolidated tests to focus on core functionality: high variant switching, dotted model ID
 handling, and edge cases
• Removed detailed tests for GitHub Copilot provider integration, backwards compatibility, and
 agent-level thinking configuration

src/hooks/think-mode/index.test.ts


11. src/hooks/think-mode/switcher.test.ts 🧪 Tests +8/-405

Remove thinking config tests, keep variant normalization tests

• Removed 128 lines of tests for getThinkingConfig function and THINKING_CONFIGS structure
• Removed provider-specific integration tests (GitHub Copilot, direct providers, Z.AI GLM)
• Kept tests for getHighVariant and isAlreadyHighVariant with model ID normalization
• Updated Gemini model references from gemini-3-pro to gemini-3.1-pro

src/hooks/think-mode/switcher.test.ts


12. src/tools/hashline-edit/edit-operations.test.ts 🧪 Tests +225/-65

Refactor edit operations to unified op-based API

• Refactored edit operation tests to use new unified op field instead of type field
• Changed operation names: insert_beforeprepend, insert_afterappend, set_linereplace
• Added tests for applyAppend and applyPrepend primitives
• Added tests for overlapping range detection and non-overlapping range handling
• Added test for anchor canonicalization deduplication with whitespace variants
• Removed tests for insert_between operation

src/tools/hashline-edit/edit-operations.test.ts


13. src/tools/hashline-edit/edit-operations.ts Refactoring +35/-211

Modularize edit operations with extracted utility functions

• Extracted utility functions into separate modules: edit-deduplication, edit-ordering,
 edit-operation-primitives
• Refactored applyHashlineEditsWithReport to use new modular functions
• Simplified edit sorting with EDIT_PRECEDENCE map for consistent operation ordering
• Added detectOverlappingRanges validation for range-based edits
• Changed from type field to op field in edit operations

src/tools/hashline-edit/edit-operations.ts


14. src/shared/migration/agent-category.ts ⚙️ Configuration changes +1/-1

Update Gemini model reference in category migration map

• Updated model mapping from google/gemini-3-pro to google/gemini-3.1-pro
• Reflects current Google Gemini model naming convention

src/shared/migration/agent-category.ts


15. src/agents/prometheus/gemini.ts ✨ Enhancement +328/-0

Gemini-optimized Prometheus strategic planning system prompt

• New Gemini-optimized system prompt for Prometheus (strategic planning agent)
• Enforces mandatory exploration phases before asking user questions
• Implements thinking checkpoints between phase transitions
• Includes decision-complete work plan generation with Metis consultation
• Provides high-accuracy review loop via Momus for plan verification

src/agents/prometheus/gemini.ts


16. src/agents/atlas/gemini.ts ✨ Enhancement +372/-0

Gemini-optimized Atlas orchestration system prompt

• New Gemini-optimized system prompt for Atlas (orchestration agent)
• Enforces tool-call mandates and delegation-first approach
• Implements 4-phase critical QA verification protocol for subagent work
• Includes notepad protocol for cumulative intelligence across stateless subagents
• Provides comprehensive verification rules to catch subagent failures

src/agents/atlas/gemini.ts


17. src/hooks/auto-update-checker/hook/background-update-check.test.ts 🧪 Tests +150/-119

Refactored background update checker tests with improved structure

• Refactored test structure with improved type safety using PluginInput type
• Added helper functions createPluginEntry() and createTruncator() for test setup
• Reorganized test cases into logical describe blocks by scenario (no plugin entry, no version,
 fetch fails, etc.)
• Improved test assertions with explicit given/when/then comments and clearer expectations
• Removed references to updatePinnedVersion mock (function no longer exists)

src/hooks/auto-update-checker/hook/background-update-check.test.ts


18. src/tools/hashline-edit/tools.test.ts 🧪 Tests +225/-23

Updated hashline edit tool tests for new API schema

• Updated test cases to match new hashline edit API: op field replaces type, pos/end replace
 line/start_line/end_line
• Added new test cases for file creation, BOM/CRLF preservation, and edge cases
• Added tests for canonicalizeFileText() function to verify line ending detection
• Added validation tests for invalid input combinations (delete with edits, delete with rename)
• Improved test clarity with explicit given/when/then structure

src/tools/hashline-edit/tools.test.ts


19. src/hooks/keyword-detector/ultrawork/gemini.ts ✨ Enhancement +265/-0

Gemini-optimized ultrawork mode system prompt

• New Gemini-optimized ultrawork mode system prompt
• Enforces mandatory intent classification before any action (research vs implementation vs
 investigation)
• Implements absolute certainty protocol with exploration and specialist consultation
• Includes tool-call mandate and delegation rules for non-trivial tasks
• Provides anti-optimism checkpoints and zero-tolerance failure rules

src/hooks/keyword-detector/ultrawork/gemini.ts


20. src/hooks/directory-readme-injector/injector.test.ts 🧪 Tests +170/-119

Refactored directory README injector tests with real file operations

• Refactored test setup to use real file system operations instead of mocks
• Simplified mock module setup with in-memory storage map for session caching
• Reorganized tests into logical scenarios: parent directory injection, root-level inclusion,
 multiple READMEs, caching, truncation
• Added helper functions createPluginContext() and createTruncator() for cleaner test setup
• Improved test clarity with explicit given/when/then comments

src/hooks/directory-readme-injector/injector.test.ts


21. src/hooks/directory-agents-injector/injector.test.ts 🧪 Tests +157/-114

Refactored directory agents injector tests with real file operations

• Refactored test setup to use real file system operations instead of mocks
• Simplified mock module setup with in-memory storage map for session caching
• Reorganized tests into logical scenarios: parent directory injection, root-level skipping,
 multiple AGENTS.md, caching, truncation
• Added helper functions and constants for cleaner test setup
• Improved test clarity with explicit given/when/then comments

src/hooks/directory-agents-injector/injector.test.ts


22. src/features/background-agent/error-classifier.test.ts 🧪 Tests +351/-0

New error classifier utility test suite

• New comprehensive test suite for error classification utility functions
• Tests cover isRecord(), isAbortedSessionError(), getErrorText(), extractErrorName(),
 extractErrorMessage(), and getSessionErrorMessage()
• Organized into describe blocks by function with sub-groups for different input categories
• Covers edge cases: null/undefined, primitives, Error instances, nested error structures, circular
 references
• Validates error message extraction from various object shapes and fallback behaviors

src/features/background-agent/error-classifier.test.ts


23. benchmarks/test-multi-model.ts 🧪 Tests +280/-0

Multi-model edit file benchmark test runner

• New benchmark script for testing edit_file operations across multiple AI models
• Spawns test runner for each model with configurable per-model timeout (default 15 minutes)
• Parses test output to extract pass/fail results and generates summary table
• Supports CLI argument --timeout to override default timeout
• Provides colored console output with per-model and overall statistics

benchmarks/test-multi-model.ts


24. src/agents/sisyphus-junior/index.ts ✨ Enhancement +1/-0

Export Gemini Sisyphus Junior prompt builder

• Added export for new buildGeminiSisyphusJuniorPrompt function
• Maintains existing exports for default and GPT variants

src/agents/sisyphus-junior/index.ts


25. .github/workflows/publish-platform.yml Additional files +63/-10

...

.github/workflows/publish-platform.yml


26. .github/workflows/publish.yml Additional files +1/-1

...

.github/workflows/publish.yml


27. .issue-comment-2064.md Additional files +61/-0

...

.issue-comment-2064.md


28. AGENTS.md Additional files +6/-6

...

AGENTS.md


29. README.ja.md Additional files +3/-3

...

README.ja.md


30. README.ko.md Additional files +3/-3

...

README.ko.md


31. README.md Additional files +3/-3

...

README.md


32. README.zh-cn.md Additional files +3/-3

...

README.zh-cn.md


33. assets/oh-my-opencode.schema.json Additional files +180/-13

...

assets/oh-my-opencode.schema.json


34. benchmarks/headless.ts Additional files +193/-0

...

benchmarks/headless.ts


35. benchmarks/package.json Additional files +19/-0

...

benchmarks/package.json


36. bin/oh-my-opencode.js Additional files +96/-34

...

bin/oh-my-opencode.js


37. bin/platform.d.ts Additional files +14/-0

...

bin/platform.d.ts


38. bin/platform.js Additional files +44/-0

...

bin/platform.js


39. bin/platform.test.ts Additional files +56/-1

...

bin/platform.test.ts


40. package.json Additional files +13/-8

...

package.json


41. packages/darwin-arm64/package.json Additional files +1/-1

...

packages/darwin-arm64/package.json


42. packages/darwin-x64-baseline/package.json Additional files +1/-1

...

packages/darwin-x64-baseline/package.json


43. packages/darwin-x64/package.json Additional files +1/-1

...

packages/darwin-x64/package.json


44. packages/linux-arm64-musl/package.json Additional files +1/-1

...

packages/linux-arm64-musl/package.json


45. packages/linux-arm64/package.json Additional files +1/-1

...

packages/linux-arm64/package.json


46. packages/linux-x64-baseline/package.json Additional files +1/-1

...

packages/linux-x64-baseline/package.json


47. packages/linux-x64-musl-baseline/package.json Additional files +1/-1

...

packages/linux-x64-musl-baseline/package.json


48. packages/linux-x64-musl/package.json Additional files +1/-1

...

packages/linux-x64-musl/package.json


49. packages/linux-x64/package.json Additional files +1/-1

...

packages/linux-x64/package.json


50. packages/windows-x64-baseline/package.json Additional files +1/-1

...

packages/windows-x64-baseline/package.json


51. packages/windows-x64/package.json Additional files +1/-1

...

packages/windows-x64/package.json


52. postinstall.mjs Additional files +23/-7

...

postinstall.mjs


53. signatures/cla.json Additional files +104/-0

...

signatures/cla.json


54. src/AGENTS.md Additional files +5/-5

...

src/AGENTS.md


55. src/agents/AGENTS.md Additional files +1/-1

...

src/agents/AGENTS.md


56. src/agents/atlas/index.ts Additional files +1/-13

...

src/agents/atlas/index.ts


57. src/agents/env-context.test.ts Additional files +41/-0

...

src/agents/env-context.test.ts


58. src/agents/env-context.ts Additional files +1/-18

...

src/agents/env-context.ts


59. src/agents/index.ts Additional files +0/-24

...

src/agents/index.ts


60. src/agents/prometheus/index.ts Additional files +0/-10

...

src/agents/prometheus/index.ts


61. src/agents/prometheus/system-prompt.ts Additional files +9/-2

...

src/agents/prometheus/system-prompt.ts


62. src/agents/sisyphus-gemini-overlays.ts Additional files +117/-0

...

src/agents/sisyphus-gemini-overlays.ts


63. src/agents/sisyphus-junior/agent.ts Additional files +10/-3

...

src/agents/sisyphus-junior/agent.ts


64. src/agents/sisyphus-junior/gemini.ts Additional files +191/-0

...

src/agents/sisyphus-junior/gemini.ts


65. src/agents/sisyphus.ts Additional files +25/-11

...

src/agents/sisyphus.ts


66. src/agents/tool-restrictions.test.ts Additional files +15/-0

...

src/agents/tool-restrictions.test.ts


67. src/agents/types.test.ts Additional files +61/-9

...

src/agents/types.test.ts


68. src/agents/types.ts Additional files +12/-4

...

src/agents/types.ts


69. src/agents/utils.test.ts Additional files +6/-4

...

src/agents/utils.test.ts


70. src/cli/AGENTS.md Additional files +1/-1

...

src/cli/AGENTS.md


71. src/cli/config-manager.test.ts Additional files +2/-2

...

src/cli/config-manager.test.ts


72. src/cli/config-manager/AGENTS.md Additional files +1/-1

...

src/cli/config-manager/AGENTS.md


73. src/cli/config-manager/antigravity-provider-configuration.ts Additional files +3/-3

...

src/cli/config-manager/antigravity-provider-configuration.ts


74. src/cli/config-manager/bun-install.ts Additional files +2/-1

...

src/cli/config-manager/bun-install.ts


75. src/cli/config-manager/opencode-binary.ts Additional files +2/-1

...

src/cli/config-manager/opencode-binary.ts


76. src/cli/config-manager/write-omo-config.test.ts Additional files +80/-0

...

src/cli/config-manager/write-omo-config.test.ts


77. src/cli/config-manager/write-omo-config.ts Additional files +1/-1

...

src/cli/config-manager/write-omo-config.ts


78. src/cli/doctor/checks/dependencies.ts Additional files +2/-2

...

src/cli/doctor/checks/dependencies.ts


79. src/cli/doctor/checks/model-resolution.test.ts Additional files +1/-1

...

src/cli/doctor/checks/model-resolution.test.ts


80. src/cli/doctor/checks/system-binary.ts Additional files +2/-1

...

src/cli/doctor/checks/system-binary.ts


81. src/cli/doctor/checks/tools-gh.ts Additional files +4/-2

...

src/cli/doctor/checks/tools-gh.ts


82. src/cli/doctor/formatter.test.ts Additional files +91/-47

...

src/cli/doctor/formatter.test.ts


83. src/cli/model-fallback-requirements.ts Additional files +16/-16

...

src/cli/model-fallback-requirements.ts


84. src/cli/model-fallback.test.ts Additional files +3/-4

...

src/cli/model-fallback.test.ts


85. src/cli/provider-model-id-transform.test.ts Additional files +20/-20

...

src/cli/provider-model-id-transform.test.ts


86. src/cli/run/AGENTS.md Additional files +1/-1

...

src/cli/run/AGENTS.md


87. src/cli/run/event-handlers.test.ts Additional files +3/-4

...

src/cli/run/event-handlers.test.ts


88. src/cli/run/event-state.ts Additional files +3/-0

...

src/cli/run/event-state.ts


89. src/cli/run/event-stream-processor.ts Additional files +3/-0

...

src/cli/run/event-stream-processor.ts


90. src/cli/run/integration.test.ts Additional files +15/-8

...

src/cli/run/integration.test.ts


91. src/cli/run/on-complete-hook.test.ts Additional files +15/-11

...

src/cli/run/on-complete-hook.test.ts


92. src/cli/run/on-complete-hook.ts Additional files +2/-1

...

src/cli/run/on-complete-hook.ts


93. src/cli/run/opencode-binary-resolver.ts Additional files +2/-1

...

src/cli/run/opencode-binary-resolver.ts


94. src/cli/run/poll-for-completion.ts Additional files +85/-1

...

src/cli/run/poll-for-completion.ts


95. src/cli/run/session-resolver.ts Additional files +1/-1

...

src/cli/run/session-resolver.ts


96. src/config/AGENTS.md Additional files +1/-1

...

src/config/AGENTS.md


97. src/config/index.ts Additional files +0/-13

...

src/config/index.ts


98. src/config/schema/agent-overrides.ts Additional files +9/-1

...

src/config/schema/agent-overrides.ts


99. src/config/schema/categories.ts Additional files +1/-0

...

src/config/schema/categories.ts


100. src/config/schema/oh-my-opencode-config.ts Additional files +3/-1

...

src/config/schema/oh-my-opencode-config.ts


101. src/features/AGENTS.md Additional files +1/-1

...

src/features/AGENTS.md


102. src/features/background-agent/AGENTS.md Additional files +1/-1

...

src/features/background-agent/AGENTS.md


103. src/features/background-agent/background-task-completer.ts Additional files +0/-40

...

src/features/background-agent/background-task-completer.ts


104. src/features/background-agent/compaction-aware-message-resolver.test.ts Additional files +190/-0

...

src/features/background-agent/compaction-aware-message-resolver.test.ts


105. src/features/background-agent/compaction-aware-message-resolver.ts Additional files +57/-0

...

src/features/background-agent/compaction-aware-message-resolver.ts


106. src/features/background-agent/concurrency.test.ts Additional files +2/-2

...

src/features/background-agent/concurrency.test.ts


107. src/features/background-agent/error-classifier.ts Additional files +62/-0

...

src/features/background-agent/error-classifier.ts


108. src/features/background-agent/fallback-retry-handler.test.ts Additional files +270/-0

...

src/features/background-agent/fallback-retry-handler.test.ts


109. src/features/background-agent/fallback-retry-handler.ts Additional files +126/-0

...

src/features/background-agent/fallback-retry-handler.ts


110. src/features/background-agent/format-duration.ts Additional files +0/-14

...

src/features/background-agent/format-duration.ts


111. src/features/background-agent/index.ts Additional files +0/-3

...

src/features/background-agent/index.ts


112. src/features/background-agent/manager.test.ts Additional files +92/-0

...

src/features/background-agent/manager.test.ts


113. src/features/background-agent/message-dir.ts Additional files +0/-1

...

src/features/background-agent/message-dir.ts


114. src/features/background-agent/notification-builder.ts Additional files +0/-41

...

src/features/background-agent/notification-builder.ts


115. src/features/background-agent/parent-session-context-resolver.ts Additional files +0/-81

...

src/features/background-agent/parent-session-context-resolver.ts


116. src/features/background-agent/parent-session-notifier.test.ts Additional files +0/-39

...

src/features/background-agent/parent-session-notifier.test.ts


117. src/features/background-agent/parent-session-notifier.ts Additional files +0/-103

...

src/features/background-agent/parent-session-notifier.ts


118. src/features/background-agent/process-cleanup.test.ts Additional files +162/-0

...

src/features/background-agent/process-cleanup.test.ts


119. src/features/background-agent/process-cleanup.ts Additional files +81/-0

...

src/features/background-agent/process-cleanup.ts


120. src/features/background-agent/result-handler-context.ts Additional files +0/-9

...

src/features/background-agent/result-handler-context.ts


121. src/features/background-agent/result-handler.ts Additional files +0/-7

...

src/features/background-agent/result-handler.ts


122. src/features/background-agent/session-idle-event-handler.test.ts Additional files +340/-0

...

src/features/background-agent/session-idle-event-handler.test.ts


123. src/features/background-agent/session-output-validator.ts Additional files +0/-89

...

src/features/background-agent/session-output-validator.ts


124. src/features/background-agent/session-task-cleanup.ts Additional files +0/-46

...

src/features/background-agent/session-task-cleanup.ts


125. Additional files not shown Additional files +0/-0

...

Additional files not shown


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link

qodo-free-for-open-source-projects bot commented Feb 27, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (4) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Given/when/then uses comments 📘 Rule violation ✓ Correctness
Description
The new normalize-edits.test.ts uses //#given/#when/#then comments instead of the required
nested describe blocks. This violates the required test structure convention.
Code

src/tools/hashline-edit/normalize-edits.test.ts[R4-19]

+describe("normalizeHashlineEdits", () => {
+  it("maps replace with pos to replace", () => {
+    //#given
+    const input: RawHashlineEdit[] = [{ op: "replace", pos: "2#VK", lines: "updated" }]
+
+    //#when
+    const result = normalizeHashlineEdits(input)
+
+    //#then
+    expect(result).toEqual([{ op: "replace", pos: "2#VK", lines: "updated" }])
+  })
+
+  it("maps replace with pos and end to replace", () => {
+    //#given
+    const input: RawHashlineEdit[] = [{ op: "replace", pos: "2#VK", end: "4#MB", lines: ["a", "b"] }]
+
Evidence
PR Compliance ID 7 requires nested describe blocks with #given/#when/#then prefixes; using
comment markers is not the required structure. The added test file uses //#given, //#when, and
//#then comments inside it(...) blocks.

AGENTS.md
src/tools/hashline-edit/normalize-edits.test.ts[4-19]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Tests are using `//#given/#when/#then` comment markers instead of nested `describe` blocks with `#given/#when/#then` prefixes.

## Issue Context
The test style requirement is explicit about using nested `describe` blocks for given/when/then organization.

## Fix Focus Areas
- src/tools/hashline-edit/normalize-edits.test.ts[4-61]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. as any in new test 📘 Rule violation ✓ Correctness
Description
The new fallback-retry-handler.test.ts introduces as any casts, which suppress type safety. This
violates the prohibition on type/lint suppression mechanisms in modified code.
Code

src/features/background-agent/fallback-retry-handler.test.ts[R54-66]

+function createMockClient() {
+  return {
+    session: {
+      abort: mock(async () => ({})),
+    },
+  } as any
+}
+
+function createDefaultArgs(taskOverrides: Partial<BackgroundTask> = {}) {
+  const processKeyFn = mock(() => {})
+  const queuesByKey = new Map<string, Array<{ task: BackgroundTask; input: any }>>()
+  const idleDeferralTimers = new Map<string, ReturnType<typeof setTimeout>>()
+  const concurrencyManager = createMockConcurrencyManager()
Evidence
PR Compliance ID 14 explicitly forbids introducing as any. The newly added test file uses `} as
any and also casts shouldRetryError to any` for mocking.

AGENTS.md
src/features/background-agent/fallback-retry-handler.test.ts[54-66]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New tests introduce `as any` casts, which suppress type safety and are explicitly disallowed.

## Issue Context
These casts are used to shape mock objects and to access mock methods on imported functions.

## Fix Focus Areas
- src/features/background-agent/fallback-retry-handler.test.ts[54-66]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. .issue-comment-2064.md naming 📘 Rule violation ✓ Correctness
Description
A new file .issue-comment-2064.md was added with a leading dot, which is not kebab-case. This
violates the kebab-case-only requirement for new file names.
Code

.issue-comment-2064.md[R1-3]

+[sisyphus-bot] 
+
+## Confirmed Bug
Evidence
PR Compliance ID 11 requires newly added files to be kebab-case. The PR adds
.issue-comment-2064.md, whose leading . makes it non-kebab-case under the stated rule.

AGENTS.md
.issue-comment-2064.md[1-3]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A newly added file name uses a leading dot and is not kebab-case.

## Issue Context
Compliance requires kebab-case for all newly added or renamed files/directories.

## Fix Focus Areas
- .issue-comment-2064.md[1-61]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. Broken hook subscriptions 🐞 Bug ✓ Correctness
Description
HOOK_SUBSCRIPTIONS is used to skip hook invocations, but multiple hooks are subscribed to
too-narrow event sets that omit event types their own handlers explicitly depend on. This will
prevent core behaviors (todo continuation, auto-compact recovery, atlas continuation,
runtime/background fallback, notifications) and some cleanups from ever running.
Code

src/plugin/event.ts[R140-168]

+  const SESSION_LIFECYCLE = ["session.idle", "session.created", "session.deleted", "session.status", "session.error", "session.updated"];
+  const MESSAGE_EVENTS = ["message.updated", "message.part.updated"];
+  const HOOK_SUBSCRIPTIONS: Record<string, string[] | "*"> = {
+    // ALL events including deltas (transcript tracking, streaming output monitoring)
+    claudeCodeHooks: "*",
+    interactiveBashSession: "*",
+    // Session lifecycle only
+    sessionNotification: SESSION_LIFECYCLE,
+    unstableAgentBabysitter: SESSION_LIFECYCLE,
+    runtimeFallback: SESSION_LIFECYCLE,
+    agentUsageReminder: SESSION_LIFECYCLE,
+    categorySkillReminder: SESSION_LIFECYCLE,
+    ralphLoop: SESSION_LIFECYCLE,
+    stopContinuationGuard: SESSION_LIFECYCLE,
+    backgroundNotificationHook: SESSION_LIFECYCLE,
+    autoUpdateChecker: SESSION_LIFECYCLE,
+    // Message events (no deltas)
+    contextWindowMonitor: [...MESSAGE_EVENTS, "session.status"],
+    anthropicContextWindowLimitRecovery: MESSAGE_EVENTS,
+    compactionTodoPreserver: MESSAGE_EVENTS,
+    writeExistingFileGuard: MESSAGE_EVENTS,
+    todoContinuationEnforcer: MESSAGE_EVENTS,
+    atlasHook: MESSAGE_EVENTS,
+    // Chat-level events
+    directoryAgentsInjector: ["session.created", "message.updated"],
+    directoryReadmeInjector: ["session.created", "message.updated"],
+    rulesInjector: ["session.created", "message.updated"],
+    thinkMode: ["session.created", "message.updated"],
+  };
Evidence
dispatchToHooks enforces HOOK_SUBSCRIPTIONS by skipping any hook whose subscription list doesn’t
include input.event.type. However, several hooks’ implementations branch on event types that are
not included in their configured subscriptions (and SESSION_LIFECYCLE itself omits important
lifecycle event types like session.compacted and session.stop). Therefore those branches become
unreachable at runtime.

src/plugin/event.ts[137-209]
src/hooks/todo-continuation-enforcer/handler.ts[32-75]
src/hooks/anthropic-context-window-limit-recovery/recovery-hook.ts[39-140]
src/hooks/atlas/event-handler.ts[26-43]
src/hooks/atlas/event-handler.ts[178-204]
src/hooks/runtime-fallback/hook.ts[53-61]
src/hooks/runtime-fallback/event-handler.ts[190-195]
src/hooks/session-notification.ts[136-185]
src/hooks/background-notification/hook.ts[26-30]
src/features/background-agent/manager.ts[693-755]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`src/plugin/event.ts` now filters hook invocations via `HOOK_SUBSCRIPTIONS`, but many hooks are subscribed to event sets that omit event types their own handlers explicitly process (e.g. `session.idle`, `session.error`, `session.compacted`, `session.stop`, `tool.execute.*`). This makes key hook logic unreachable and breaks functionality/cleanup.

## Issue Context
The dispatcher enforces the subscription list (`if (subs !== &quot;*&quot; &amp;&amp; !subs.includes(eventType)) continue;`). Several hook implementations contain branches for events that are not in their configured subscription arrays.

## Fix Focus Areas
- src/plugin/event.ts[140-168]
- src/plugin/event.ts[199-208]
- src/hooks/todo-continuation-enforcer/handler.ts[32-68]
- src/hooks/anthropic-context-window-limit-recovery/recovery-hook.ts[39-140]
- src/hooks/atlas/event-handler.ts[26-43]
- src/hooks/atlas/event-handler.ts[178-204]
- src/hooks/runtime-fallback/event-handler.ts[190-195]
- src/hooks/session-notification.ts[136-185]
- src/features/background-agent/manager.ts[693-755]

## Suggested direction
1. Expand `SESSION_LIFECYCLE` to include at least `session.compacted` and `session.stop` (and any other session.* events used by hooks).
2. Fix individual subscriptions, e.g.:
  - `todoContinuationEnforcer`: include `session.idle`, `session.error`, `session.deleted`, and tool events it watches.
  - `anthropicContextWindowLimitRecovery`: include `session.error`, `session.idle`, `session.deleted`.
  - `atlasHook`: include `session.idle`, `session.error`, `session.deleted`, `session.compacted`, and `tool.execute.*`.
  - `runtimeFallback`: include `message.updated` and `session.stop`.
  - `sessionNotification`: include `message.updated` and `tool.execute.*`.
  - `backgroundNotificationHook`: likely `&quot;*&quot;` (it routes all events to `BackgroundManager`).
3. Alternatively (often simpler/safer): only special-case filtering for `message.part.delta` by maintaining a small allowlist of hooks for that single high-frequency event, and let all hooks receive other event types as before.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

5. Hook error log lacks context 📘 Rule violation ⛨ Security
Description
The new fire-and-forget hook dispatch logs raw err without including the triggering event.type
or session identifiers, making production debugging harder. Logging the raw error object can also
leak sensitive data depending on what upstream errors contain.
Code

src/plugin/event.ts[R200-207]

+    const eventType = input.event.type;
+    for (const [name, invoke, subs] of hookEntries) {
+      if (subs !== "*" && !subs.includes(eventType)) continue;
+      if (AWAITED_HOOKS.has(name)) {
+        await Promise.resolve(invoke(input));
+      } else {
+        Promise.resolve(invoke(input)).catch((err) => log("[hook] error:", { hook: name, error: err }));
+      }
Evidence
PR Compliance ID 3 requires actionable error context, and PR Compliance ID 5 requires avoiding
sensitive data in logs. The new dispatcher catches errors and logs { hook: name, error: err }
without event/session context and without sanitizing the error object.

Rule 3: Generic: Robust Error Handling and Edge Case Management
Rule 5: Generic: Secure Logging Practices
src/plugin/event.ts[200-207]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The fire-and-forget hook dispatch logs a raw `err` object with limited context, which can reduce debuggability and may risk leaking sensitive data via logs.

## Issue Context
Per compliance requirements, error logs should be actionable (include what failed and why) and should not include sensitive data.

## Fix Focus Areas
- src/plugin/event.ts[200-207]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Sync throw bypasses catch 🐞 Bug ⛯ Reliability
Description
Fire-and-forget hooks use Promise.resolve(invoke(input)).catch(...), but a synchronous exception
thrown inside invoke(input) happens before the Promise is created and will bubble up, defeating
the intended isolation of non-awaited hooks. This can reintroduce hot-path failures from
“non-critical” hooks.
Code

src/plugin/event.ts[R200-207]

+    const eventType = input.event.type;
+    for (const [name, invoke, subs] of hookEntries) {
+      if (subs !== "*" && !subs.includes(eventType)) continue;
+      if (AWAITED_HOOKS.has(name)) {
+        await Promise.resolve(invoke(input));
+      } else {
+        Promise.resolve(invoke(input)).catch((err) => log("[hook] error:", { hook: name, error: err }));
+      }
Evidence
The dispatcher calls invoke(input) directly and only attaches .catch to the Promise returned by
Promise.resolve(...). Since hook creation is protected but hook invocation is not, any synchronous
throw from a non-awaited hook will not be logged-and-swallowed as intended and can still abort event
handling.

src/plugin/event.ts[199-208]
src/shared/safe-create-hook.ts[7-23]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Promise.resolve(invoke(input)).catch(...)` does not catch synchronous exceptions thrown by `invoke(input)` because the function call occurs before `Promise.resolve` wraps the result. This defeats the goal of isolating non-awaited hooks.

## Issue Context
Non-awaited hooks are intended to be fire-and-forget with error logging, but sync throws will still propagate.

## Fix Focus Areas
- src/plugin/event.ts[199-208]

## Suggested fix
Change the fire-and-forget invocation to defer execution into the Promise chain, e.g.:
- `void Promise.resolve().then(() =&gt; invoke(input)).catch(err =&gt; log(...))`

Optionally apply the same pattern to awaited hooks if you want consistent behavior around sync throws (or explicitly `try/catch` around `invoke(input)` to log and continue for non-awaited hooks).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the performance and robustness of the system by introducing a subscription-based event dispatching mechanism for hooks, which drastically reduces overhead during high-frequency operations. It also addresses critical configuration management issues, improves platform binary compatibility, and expands agent capabilities with optimized support for Gemini models. Additionally, several agent-specific behaviors and user interaction flows have been refined, including better handling of background tasks, Git worktrees, and user notifications.

Highlights

  • Performance Optimization: Implemented subscription-based event filtering for hooks, drastically reducing async hook dispatch overhead during LLM streaming. This means 19 of 21 hooks are now skipped entirely during high-frequency message.part.delta events, cutting dispatches from ~2,100/sec to ~200/sec.
  • Config Merge Logic Fix: Corrected a bug in the config writing logic (deepMergeRecord) that previously overwrote user-defined model settings during oh-my-opencode install. User configurations are now properly preserved.
  • Platform Binary Loading Improvements: Enhanced the platform binary loading mechanism to support AVX2 and baseline binaries, including a fallback strategy for improved compatibility and robustness across different CPU architectures.
  • Agent Model Support for Gemini: Updated Atlas and Prometheus agents with Gemini-optimized prompts and routing, ensuring better performance and adherence to Gemini's specific behavioral characteristics.
  • Sisyphus Gemini Overlays: Introduced Gemini-specific prompt overlays for Sisyphus agents to enforce tool usage, delegation, and verification more aggressively, countering Gemini's tendency to skip these steps.
  • Hashline Tool Enhancements: Improved the Hashline Read Enhancer to support new OpenCode read tool output formats (e.g., pipe-delimited lines) and provide a simpler success message for write operations. The hashline format itself was updated from : to |.
  • Background Agent Manager Improvements: Implemented a watchdog for idle background sessions and refined error handling with a new fallback retry mechanism, enhancing the reliability and resilience of background tasks.
  • Start Work Command Worktree Support: Added support for specifying Git worktrees with the /start-work command, allowing users to direct Sisyphus to operate within a specific worktree directory.
  • Think Mode Hook Refinement: The Think Mode hook was simplified to directly use the variant property for model configuration, removing complex thinking config injections and improving compatibility.
  • Session Notification for Input-Needed Events: The session-notification hook now triggers notifications when the agent asks a question or requires permission, improving user awareness for interactive prompts.
  • Hephaestus Non-GPT Model Opt-Out: The no-hephaestus-non-gpt hook now includes an allow_non_gpt_model option, enabling users to opt-out of the default restriction and use non-GPT models with Hephaestus if desired.
  • Todo Continuation Enforcer Updates: The todo-continuation-enforcer now correctly ignores blocked or deleted todos and pending questions, preventing unnecessary continuation prompts.
  • Write Existing File Guard Refinements: The write-existing-file-guard hook was updated to allow writes to files outside the session directory and simplify the check for .sisyphus paths, providing more flexible file management.
Changelog
  • .issue-comment-2064.md
    • Added a new issue comment detailing a bug in the config merge logic.
  • AGENTS.md
    • Updated the total count of lifecycle hooks from 44 to 46.
    • Updated the generation date.
  • README.ja.md
    • Changed the hashline format from : to | in code examples.
  • README.ko.md
    • Changed the hashline format from : to | in code examples.
  • README.md
    • Changed the hashline format from : to | in code examples.
  • README.zh-cn.md
    • Changed the hashline format from : to | in code examples.
  • assets/oh-my-opencode.schema.json
    • Relaxed the enum constraint for disabled_agents to allow any string.
    • Added model_fallback as an optional boolean property.
    • Added compaction object with optional model and variant properties to agent overrides.
    • Added max_prompt_tokens as an optional integer property to category configuration.
    • Added allow_non_gpt_model as an optional boolean property to Hephaestus agent overrides.
  • benchmarks/bun.lock
    • Added new dependencies for benchmarking tools.
  • benchmarks/headless.ts
    • Added a new headless script for running benchmarks of the hashline edit tool.
  • benchmarks/package.json
    • Added a new package.json for hashline edit tool benchmarks.
  • benchmarks/test-edge-cases.ts
    • Added a new test file for edge cases of the hashline edit tool.
  • benchmarks/test-edit-ops.ts
    • Added a new test file for basic operations of the hashline edit tool.
  • benchmarks/test-multi-model.ts
    • Added a new test file for multi-model benchmarks of the hashline edit tool.
  • bin/oh-my-opencode.js
    • Modified binary loading to support AVX2 and baseline binaries with fallback.
    • Added supportsAvx2 function to detect AVX2 support.
    • Added getSignalExitCode function to map signal names to exit codes.
  • bin/platform.d.ts
    • Added declaration for getPlatformPackageCandidates.
  • bin/platform.js
    • Added getPlatformPackageCandidates function to provide primary and baseline package options.
    • Added getBaselinePlatformPackage function to determine baseline package names.
  • bin/platform.test.ts
    • Added tests for getPlatformPackageCandidates covering different platforms and baseline preferences.
  • bun.lock
    • Updated package versions.
    • Added diff dependency.
  • package.json
    • Updated package version to 3.9.0.
    • Added diff as a dependency.
    • Added new optional dependencies for baseline platform binaries (darwin-x64-baseline, linux-x64-baseline, linux-x64-musl-baseline, windows-x64-baseline).
  • packages/darwin-arm64/package.json
    • Updated package version to 3.9.0.
  • packages/darwin-x64-baseline/package.json
    • Updated package version to 3.9.0.
  • packages/darwin-x64/package.json
    • Updated package version to 3.9.0.
  • packages/linux-arm64-musl/package.json
    • Updated package version to 3.9.0.
  • packages/linux-arm64/package.json
    • Updated package version to 3.9.0.
  • packages/linux-x64-baseline/package.json
    • Updated package version to 3.9.0.
  • packages/linux-x64-musl-baseline/package.json
    • Updated package version to 3.9.0.
  • packages/linux-x64-musl/package.json
    • Updated package version to 3.9.0.
  • packages/linux-x64/package.json
    • Updated package version to 3.9.0.
  • packages/windows-x64-baseline/package.json
    • Updated package version to 3.9.0.
  • packages/windows-x64/package.json
    • Updated package version to 3.9.0.
  • postinstall.mjs
    • Modified postinstall script to check for platform package candidates, including baseline versions.
  • signatures/cla.json
    • Added new CLA signatures.
  • src/AGENTS.md
    • Updated hook count from 35 to 37 in createCoreHooks.
    • Updated generation date.
  • src/agents/AGENTS.md
    • Updated generation date.
  • src/agents/atlas/agent.ts
    • Updated Atlas agent to support Gemini models.
    • Changed agent mode from primary to all.
    • Removed createAgentToolRestrictions call.
  • src/agents/atlas/gemini.ts
    • Added a new Gemini-optimized system prompt for the Atlas agent.
  • src/agents/atlas/index.ts
    • Simplified exports, removing direct exports of prompt sections and source detection functions.
  • src/agents/env-context.test.ts
    • Added tests for createEnvContext to ensure only timezone and locale are included.
  • src/agents/env-context.ts
    • Removed Current date and Current time from the environment context to avoid duplication with OpenCode's system.ts.
  • src/agents/hephaestus.ts
    • Changed Hephaestus agent mode from primary to all.
  • src/agents/index.ts
    • Simplified exports, removing direct exports of individual agent creation functions and prompt sections.
  • src/agents/prometheus/gemini.ts
    • Added a new Gemini-optimized system prompt for the Prometheus agent.
  • src/agents/prometheus/index.ts
    • Simplified exports, removing direct exports of prompt sections and source detection functions.
  • src/agents/prometheus/system-prompt.ts
    • Updated Prometheus system prompt to support Gemini models.
  • src/agents/sisyphus-gemini-overlays.ts
    • Added new functions (buildGeminiToolMandate, buildGeminiDelegationOverride, buildGeminiVerificationOverride, buildGeminiIntentGateEnforcement) to provide Gemini-specific prompt overlays for Sisyphus agents.
  • src/agents/sisyphus-junior/agent.ts
    • Updated Sisyphus-Junior agent to support Gemini models.
  • src/agents/sisyphus-junior/gemini.ts
    • Added a new Gemini-optimized system prompt for the Sisyphus-Junior agent.
  • src/agents/sisyphus-junior/index.ts
    • Exported buildGeminiSisyphusJuniorPrompt.
  • src/agents/sisyphus.ts
    • Changed Sisyphus agent mode from primary to all.
    • Applied Gemini-specific prompt overlays to the Sisyphus agent when using a Gemini model.
  • src/agents/tool-restrictions.test.ts
    • Added a test for Atlas agent's tool permissions.
  • src/agents/types.test.ts
    • Updated isGptModel tests to exclude o-series models by name.
    • Added new tests for isGeminiModel covering various providers and model names.
  • src/agents/types.ts
    • Modified isGptModel to check for 'gpt' in the model name.
    • Added isGeminiModel function to detect Gemini models across different providers.
  • src/agents/utils.test.ts
    • Updated Hephaestus agent creation logic in tests.
    • Updated Gemini model ID in buildAgent test snapshot.
  • src/cli/AGENTS.md
    • Updated generation date.
  • src/cli/snapshots/model-fallback.test.ts.snap
    • Updated Gemini model IDs from gemini-3-pro-preview to gemini-3.1-pro-preview in various agent and category configurations.
  • src/cli/config-manager.test.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in Antigravity provider configuration tests.
  • src/cli/config-manager/AGENTS.md
    • Updated generation date.
  • src/cli/config-manager/antigravity-provider-configuration.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro.
  • src/cli/config-manager/bun-install.ts
    • Imported and used spawnWithWindowsHide for Bun.spawn calls.
  • src/cli/config-manager/opencode-binary.ts
    • Imported and used spawnWithWindowsHide for Bun.spawn calls.
  • src/cli/config-manager/write-omo-config.test.ts
    • Added a new test to ensure writeOmoConfig preserves existing user values during config merge.
  • src/cli/config-manager/write-omo-config.ts
    • Reversed the order of arguments in deepMergeRecord to prioritize existing user configuration over new defaults.
  • src/cli/doctor/checks/dependencies.ts
    • Imported and used spawnWithWindowsHide for binary existence and version checks.
  • src/cli/doctor/checks/model-resolution.test.ts
    • Updated Gemini model ID from gemini-3-pro to gemini-3.1-pro in model resolution tests.
  • src/cli/doctor/checks/system-binary.ts
    • Imported and used spawnWithWindowsHide for OpenCode binary version checks.
  • src/cli/doctor/checks/tools-gh.ts
    • Imported and used spawnWithWindowsHide for gh commands.
  • src/cli/doctor/formatter.test.ts
    • Updated formatter tests to use stripAnsi and verify output for different modes and issues.
    • Removed mock.restore() and module mocking, opting for fresh imports.
  • src/cli/model-fallback-requirements.ts
    • Updated Hephaestus requiresProvider to exclude github-copilot.
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in various agent and category fallback chains.
  • src/cli/model-fallback.test.ts
    • Updated Hephaestus creation logic to reflect gpt-5.3-codex unavailability on github-copilot.
    • Updated Gemini model IDs from gemini-3-pro-preview to gemini-3.1-pro-preview in snapshots.
  • src/cli/provider-model-id-transform.test.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in transformation tests.
  • src/cli/run/AGENTS.md
    • Updated generation date.
  • src/cli/run/event-handlers.test.ts
    • Fixed Date.now mock to return a consistent value.
    • Initialized state.messageStartedAtById to ensure correct duration calculation.
  • src/cli/run/event-state.ts
    • Added lastEventTimestamp to EventState for watchdog detection.
  • src/cli/run/event-stream-processor.ts
    • Updated state.lastEventTimestamp with the current time for every processed event.
  • src/cli/run/integration.test.ts
    • Imported spawnWithWindowsHide and used it for Bun.spawn mocks.
    • Fixed expect().rejects.toThrow to be expect(result).rejects.toThrow.
  • src/cli/run/on-complete-hook.test.ts
    • Imported spawnWithWindowsHide and used it for Bun.spawn mocks.
  • src/cli/run/on-complete-hook.ts
    • Imported and used spawnWithWindowsHide for Bun.spawn calls.
  • src/cli/run/opencode-binary-resolver.ts
    • Imported and used spawnWithWindowsHide for Bun.spawn calls.
  • src/cli/run/poll-for-completion.ts
    • Added eventWatchdogMs and secondaryMeaningfulWorkTimeoutMs options.
    • Implemented a watchdog mechanism to verify session status via API if no events are received for a period.
    • Added a secondary timeout to check for active work if no meaningful events are received.
  • src/cli/run/session-resolver.ts
    • Changed type assertion for session creation body from any to Record<string, unknown>.
  • src/config/AGENTS.md
    • Updated generation date.
  • src/config/index.ts
    • Simplified exports, removing individual schema exports.
  • src/config/schema/agent-overrides.ts
    • Added compaction object with optional model and variant properties to AgentOverrideConfigSchema.
    • Added allow_non_gpt_model as an optional boolean property to hephaestus agent override.
  • src/config/schema/categories.ts
    • Added max_prompt_tokens as an optional integer property to CategoryConfigSchema.
  • src/config/schema/oh-my-opencode-config.ts
    • Relaxed the type of disabled_agents to z.array(z.string()).
    • Added model_fallback as an optional boolean property.
  • src/features/AGENTS.md
    • Updated generation date.
  • src/features/background-agent/AGENTS.md
    • Updated generation date.
  • src/features/background-agent/background-task-completer.ts
    • Removed the file (logic moved to manager.ts).
  • src/features/background-agent/compaction-aware-message-resolver.test.ts
    • Added new tests for isCompactionAgent and findNearestMessageExcludingCompaction.
  • src/features/background-agent/compaction-aware-message-resolver.ts
    • Added isCompactionAgent and findNearestMessageExcludingCompaction functions to filter out compaction agent messages.
  • src/features/background-agent/concurrency.test.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in concurrency manager tests.
  • src/features/background-agent/error-classifier.test.ts
    • Added new tests for isRecord, isAbortedSessionError, getErrorText, extractErrorName, extractErrorMessage, and getSessionErrorMessage.
  • src/features/background-agent/error-classifier.ts
    • Added isRecord, extractErrorName, extractErrorMessage, and getSessionErrorMessage functions for robust error classification.
  • src/features/background-agent/fallback-retry-handler.test.ts
    • Added new tests for tryFallbackRetry covering various retry scenarios.
  • src/features/background-agent/fallback-retry-handler.ts
    • Added tryFallbackRetry function to handle model fallbacks and retries for background tasks.
  • src/features/background-agent/format-duration.ts
    • Removed the file (logic moved to shared/duration-formatter.ts).
  • src/features/background-agent/index.ts
    • Simplified exports, removing TaskHistory, ConcurrencyManager, and TaskStateManager.
  • src/features/background-agent/manager.test.ts
    • Added getPendingNotifications helper function.
    • Added test to queue notification when promptAsync aborts while parent is idle.
    • Added test for injectPendingNotificationsIntoChatMessage to prepend queued notifications.
    • Added test to clean pending notifications for deleted sessions.
  • src/features/background-agent/manager.ts
    • Added pendingNotifications map to store notifications for parent sessions.
    • Added queuePendingNotification and injectPendingNotificationsIntoChatMessage methods.
    • Updated error handling to use new error-classifier functions.
    • Updated tryFallbackRetry to use the new fallback-retry-handler module.
    • Updated pruneStaleTasksAndNotifications and checkAndInterruptStaleTasks to use new modules.
    • Removed formatDuration, isAbortedSessionError, getErrorText, extractErrorName, extractErrorMessage, isRecord, getSessionErrorMessage methods (now imported from error-classifier and duration-formatter).
  • src/features/background-agent/message-dir.ts
    • Removed the file (logic moved to manager.ts).
  • src/features/background-agent/notification-builder.ts
    • Removed the file (logic moved to manager.ts).
  • src/features/background-agent/parent-session-context-resolver.ts
    • Removed the file (logic moved to manager.ts).
  • src/features/background-agent/parent-session-notifier.test.ts
    • Removed the file (tests moved).
  • src/features/background-agent/parent-session-notifier.ts
    • Removed the file (logic moved to manager.ts).
  • src/features/background-agent/process-cleanup.test.ts
    • Added new tests for registerManagerForCleanup and unregisterManagerForCleanup.
  • src/features/background-agent/process-cleanup.ts
    • Added registerManagerForCleanup and unregisterManagerForCleanup functions to handle process cleanup for background managers.
  • src/features/background-agent/result-handler-context.ts
    • Removed the file.
  • src/features/background-agent/result-handler.ts
    • Removed the file.
  • src/features/background-agent/session-idle-event-handler.test.ts
    • Added new tests for handleSessionIdleBackgroundEvent covering deferral, completion, and various edge cases.
  • src/features/background-agent/session-idle-event-handler.ts
    • Added handleSessionIdleBackgroundEvent function to manage session idle events for background tasks.
  • src/features/background-agent/session-output-validator.ts
    • Removed the file (logic moved to manager.ts).
  • src/features/background-agent/session-task-cleanup.ts
    • Removed the file (logic moved to manager.ts).
  • src/features/background-agent/session-todo-checker.ts
    • Removed the file (logic moved to manager.ts).
  • src/features/background-agent/spawner.ts
    • Changed type assertion for session creation body from any to Record<string, unknown>.
  • src/features/background-agent/spawner/background-session-creator.ts
    • Removed the file.
  • src/features/background-agent/spawner/concurrency-key-from-launch-input.ts
    • Removed the file.
  • src/features/background-agent/spawner/spawner-context.ts
    • Removed the file.
  • src/features/background-agent/spawner/tmux-callback-invoker.ts
    • Removed the file.
  • src/features/boulder-state/storage.test.ts
    • Added tests for correctly counting space-indented, tab-indented, and mixed checkboxes in plan progress.
  • src/features/boulder-state/storage.ts
    • Updated regex for checkbox matching to include leading whitespace (^\s*[-*]\s*\[).
    • Added worktreePath parameter to createBoulderState and included it in the returned BoulderState.
  • src/features/boulder-state/types.ts
    • Added worktree_path as an optional string property to BoulderState.
  • src/features/builtin-commands/templates/start-work.ts
    • Added ARGUMENTS section to describe --worktree flag.
    • Added Worktree Setup section with instructions for managing Git worktrees.
    • Updated output format examples to include Worktree information.
  • src/features/claude-tasks/AGENTS.md
    • Updated generation date.
  • src/features/claude-tasks/index.ts
    • Removed the file.
  • src/features/mcp-oauth/AGENTS.md
    • Updated generation date.
  • src/features/mcp-oauth/index.ts
    • Removed the file.
  • src/features/opencode-skill-loader/AGENTS.md
    • Updated generation date.
  • src/features/task-toast-manager/manager.test.ts
    • Updated Gemini model ID from gemini-3-pro to gemini-3.1-pro in tests.
  • src/features/task-toast-manager/manager.ts
    • Added ClientWithTui type for better type safety when accessing client.tui.
  • src/features/tmux-subagent/AGENTS.md
    • Updated generation date.
  • src/hooks/AGENTS.md
    • Updated hook count from 44 to 46.
    • Updated generation date.
    • Updated hook tiers to reflect new counts and added modelFallback, noSisyphusGpt, noHephaestusNonGpt, runtimeFallback to Session Hooks.
    • Moved jsonErrorRecovery from Session Hooks to Tool Guard Hooks.
  • src/hooks/anthropic-context-window-limit-recovery/executor.ts
    • Updated executeCompact to accept pluginConfig and removed experimental parameter.
  • src/hooks/anthropic-context-window-limit-recovery/recovery-hook.ts
    • Updated createAnthropicContextWindowLimitRecoveryHook to accept pluginConfig.
  • src/hooks/anthropic-context-window-limit-recovery/state.ts
    • Added firstAttemptTime to RetryState.
  • src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.test.ts
    • Added new tests for runSummarizeRetryStrategy covering total timeout and delay capping.
  • src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.ts
    • Added SUMMARIZE_RETRY_TOTAL_TIMEOUT_MS constant.
    • Implemented total timeout logic for summarize retries.
    • Used resolveCompactionModel to determine the model for compaction.
  • src/hooks/anthropic-context-window-limit-recovery/types.ts
    • Added firstAttemptTime to RetryState.
  • src/hooks/atlas/AGENTS.md
    • Updated generation date.
  • src/hooks/atlas/boulder-continuation-injector.ts
    • Added worktreePath parameter to injectBoulderContinuation.
    • Included worktreePath in the continuation prompt if available.
    • Added sessionState.lastFailureAt = Date.now() when prompt injection fails.
  • src/hooks/atlas/event-handler.ts
    • Added FAILURE_BACKOFF_MS constant for prompt failure backoff.
    • Implemented a backoff mechanism for prompt failures to prevent continuous retries.
    • Refined agent matching logic to allow Sisyphus for Atlas boulders.
    • Reset promptFailureCount and lastFailureAt after successful continuation.
  • src/hooks/atlas/index.test.ts
    • Updated Atlas hook tests for agent matching logic.
    • Added tests for prompt failure backoff mechanism.
  • src/hooks/atlas/system-reminder-templates.ts
    • Added VERIFICATION_REMINDER_GEMINI template with aggressive verification mandates for Gemini models.
  • src/hooks/atlas/types.ts
    • Added lastFailureAt as an optional number property to SessionState.
  • src/hooks/auto-update-checker/hook.test.ts
    • Updated tests for createAutoUpdateCheckerHook to cover CLI run mode, subagent sessions, and local dev versions.
    • Refactored test setup to use fresh imports and clear mocks before each test.
  • src/hooks/auto-update-checker/hook/background-update-check.test.ts
    • Updated tests for runBackgroundUpdateCheck to cover various scenarios including no plugin entry, no version, fetch failures, auto-update disabled, pinned versions, and install failures.
  • src/hooks/background-notification/hook.ts
    • Added a chat.message handler to inject pending notifications into the chat output.
  • src/hooks/claude-code-hooks/AGENTS.md
    • Updated generation date.
  • src/hooks/directory-agents-injector/injector.test.ts
    • Updated tests for processFilePathForAgentsInjection to cover multiple AGENTS.md files, caching, truncation, and empty file paths.
  • src/hooks/directory-readme-injector/injector.test.ts
    • Updated tests for processFilePathForReadmeInjection to cover multiple README.md files, caching, truncation, and empty file paths.
  • src/hooks/hashline-edit-diff-enhancer/index.test.ts
    • Removed the file.
  • src/hooks/hashline-edit-diff-enhancer/index.ts
    • Removed the file.
  • src/hooks/hashline-read-enhancer/hook.ts
    • Updated transformLine to use | instead of : for hashline format.
    • Added support for FILE_OPEN_TAG and PIPE_READ_LINE_PATTERN to handle new OpenCode read tool output formats.
    • Modified appendWriteHashlineOutput to provide a simpler success message for write operations instead of full hashlined content.
  • src/hooks/hashline-read-enhancer/index.test.ts
    • Added tests for new hashline format (|), inline content tags, truncated lines, and simplified write success messages.
  • src/hooks/interactive-bash-session/interactive-bash-session-tracker.ts
    • Imported and used spawnWithWindowsHide for tmux kill-session.
  • src/hooks/interactive-bash-session/state-manager.ts
    • Imported and used spawnWithWindowsHide for tmux kill-session.
  • src/hooks/keyword-detector/AGENTS.md
    • Updated generation date.
  • src/hooks/keyword-detector/ultrawork/gemini.ts
    • Added a new Gemini-optimized ultrawork message with explicit intent gates and verification mandates.
  • src/hooks/keyword-detector/ultrawork/index.ts
    • Updated getUltraworkMessage to support Gemini models.
  • src/hooks/keyword-detector/ultrawork/source-detector.ts
    • Exported isGeminiModel and added gemini to UltraworkSource type.
    • Added logic to getUltraworkSource to prioritize Gemini models.
  • src/hooks/no-hephaestus-non-gpt/hook.ts
    • Added NoHephaestusNonGptHookOptions to allow configuring allowNonGptModel.
    • Modified showToast to accept a variant parameter.
    • Updated createNoHephaestusNonGptHook to use allowNonGptModel for conditional agent switching.
  • src/hooks/no-hephaestus-non-gpt/index.test.ts
    • Added tests for allowNonGptModel option, ensuring warning toast is shown but agent is not switched when enabled.
  • src/hooks/preemptive-compaction.test.ts
    • Added setupImmediateTimeouts helper function.
    • Added a test to ensure in-progress lock is cleared when summarize times out.
  • src/hooks/preemptive-compaction.ts
    • Added pluginConfig parameter to createPreemptiveCompactionHook.
    • Imported resolveCompactionModel and used it to determine the model for compaction.
    • Added withTimeout utility and applied it to ctx.client.session.summarize calls.
  • src/hooks/ralph-loop/AGENTS.md
    • Updated generation date.
  • src/hooks/ralph-loop/completion-promise-detector.test.ts
    • Added new tests for detectCompletionInSessionMessages to cover sinceMessageIndex and multiple assistant messages.
  • src/hooks/ralph-loop/completion-promise-detector.ts
    • Added sinceMessageIndex option to detectCompletionInSessionMessages to limit message scanning.
    • Modified message scanning logic to iterate from the end of scopedMessages.
  • src/hooks/ralph-loop/index.test.ts
    • Added default_strategy: "continue" to RalphLoopConfig.
    • Updated messagesCalls expectation in tests.
    • Added tests for skipping concurrent idle events and detecting completion with many assistant messages.
  • src/hooks/ralph-loop/iteration-continuation.ts
    • Moved options.loopState.setSessionID(newSessionID) call after selectSessionInTui.
  • src/hooks/ralph-loop/loop-state-controller.ts
    • Added message_count_at_start to RalphLoopState and setMessageCountAtStart function.
  • src/hooks/ralph-loop/ralph-loop-event-handler.ts
    • Added inFlightSessions set to prevent concurrent processing of session.idle events for the same session.
  • src/hooks/ralph-loop/ralph-loop-hook.ts
    • Added messageCountAtStart to RalphLoopHook options.
    • Added getMessageCountFromResponse function.
    • Updated startLoop to capture messageCountAtStart if not provided.
  • src/hooks/ralph-loop/reset-strategy-race-condition.test.ts
    • Added a new test file to verify race condition handling in Ralph Loop's reset strategy.
  • src/hooks/ralph-loop/storage.ts
    • Added message_count_at_start to RalphLoopState storage and YAML serialization.
  • src/hooks/ralph-loop/types.ts
    • Added message_count_at_start as an optional number property to RalphLoopState.
  • src/hooks/rules-injector/AGENTS.md
    • Updated generation date.
  • src/hooks/runtime-fallback/index.test.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in tests.
  • src/hooks/session-notification-input-needed.test.ts
    • Added new tests for session notification on question and permission events.
  • src/hooks/session-notification.test.ts
    • Updated session notification tests to use new session-notification-sender mocks.
  • src/hooks/session-notification.ts
    • Added questionMessage and permissionMessage to SessionNotificationConfig.
    • Added enforceMainSessionFilter to config.
    • Implemented logic to trigger notifications for question tool calls and permission events.
  • src/hooks/session-recovery/AGENTS.md
    • Updated generation date.
  • src/hooks/session-recovery/recover-empty-content-message.ts
    • Removed the file.
  • src/hooks/session-recovery/recover-tool-result-missing.ts
    • Changed type assertion for client.session.promptAsync to ClientWithPromptAsync.
  • src/hooks/shared/compaction-model-resolver.ts
    • Added resolveCompactionModel function to determine the model for compaction based on agent configuration.
  • src/hooks/start-work/index.test.ts
    • Added tests for worktree support in the start-work hook, covering valid/invalid paths, storage, and resume scenarios.
  • src/hooks/start-work/index.ts
    • Exported detectWorktreePath and parseUserRequest.
  • src/hooks/start-work/parse-user-request.test.ts
    • Added new tests for parseUserRequest covering various combinations of plan names, worktree flags, and ultrawork keywords.
  • src/hooks/start-work/parse-user-request.ts
    • Added parseUserRequest function to extract plan name and explicit worktree path from user prompts.
  • src/hooks/start-work/start-work-hook.ts
    • Imported statSync from node:fs.
    • Removed KEYWORD_PATTERN and extractUserRequestPlanName (now using parseUserRequest).
    • Added resolveWorktreeContext to handle worktree path resolution and context block generation.
    • Updated boulder state creation to include worktreePath.
    • Modified logic to inject worktree setup instructions or display the resolved worktree path.
  • src/hooks/start-work/worktree-detector.test.ts
    • Added new tests for detectWorktreePath covering valid/invalid Git directories.
  • src/hooks/start-work/worktree-detector.ts
    • Added detectWorktreePath function to identify the root of a Git worktree.
  • src/hooks/stop-continuation-guard/hook.ts
    • Added backgroundManager option to createStopContinuationGuardHook.
    • Implemented logic to cancel running/pending background tasks when continuation is stopped.
  • src/hooks/stop-continuation-guard/index.test.ts
    • Added tests for canceling background tasks when continuation is stopped.
  • src/hooks/think-mode/hook.ts
    • Changed hook type from chat.params to chat.message.
    • Simplified logic to directly set output.message.variant to 'high' and update output.message.model.
    • Removed isDisabledThinkingConfig and getThinkingConfig as they are no longer needed.
  • src/hooks/think-mode/index.test.ts
    • Updated Think Mode hook tests to reflect the change from chat.params to chat.message and the new variant usage.
  • src/hooks/think-mode/switcher.test.ts
    • Removed getThinkingConfig and THINKING_CONFIGS related tests.
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in getHighVariant and isAlreadyHighVariant tests.
  • src/hooks/think-mode/switcher.ts
    • Removed resolveProvider, THINKING_CONFIGS, and THINKING_CAPABLE_MODELS.
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in HIGH_VARIANT_MAP.
  • src/hooks/think-mode/types.ts
    • Simplified ThinkModeState by replacing thinkingConfigInjected with variantSet.
    • Removed ThinkModeInput and MessageWithModel interfaces as they are no longer directly used in the hook signature.
  • src/hooks/thinking-block-validator/hook.ts
    • Changed type assertion for thinking and sessionID properties to unknown as ThinkingPart and unknown as MessageInfoExtended respectively.
  • src/hooks/todo-continuation-enforcer/AGENTS.md
    • Updated generation date.
  • src/hooks/todo-continuation-enforcer/constants.ts
    • Reduced CONTINUATION_COOLDOWN_MS from 30,000ms to 5,000ms.
  • src/hooks/todo-continuation-enforcer/idle-event.ts
    • Added hasUnansweredQuestion check to skip continuation if a pending question exists.
  • src/hooks/todo-continuation-enforcer/pending-question-detection.test.ts
    • Added new tests for hasUnansweredQuestion covering various message scenarios.
  • src/hooks/todo-continuation-enforcer/pending-question-detection.ts
    • Added hasUnansweredQuestion function to detect if the last assistant message contains a question tool call.
  • src/hooks/todo-continuation-enforcer/todo-continuation-enforcer.test.ts
    • Added a test to ensure continuation is not injected when remaining todos are blocked or deleted.
    • Removed a test case for canceling all countdowns for a second session.
  • src/hooks/todo-continuation-enforcer/todo.ts
    • Updated getIncompleteCount to also exclude todos with blocked and deleted statuses.
  • src/hooks/write-existing-file-guard/hook.ts
    • Removed sep import.
    • Updated BLOCK_MESSAGE to a more general message.
    • Removed OUTSIDE_SESSION_MESSAGE constant.
    • Modified isSisyphusPath check to use includes("/.sisyphus/") instead of startsWith.
    • Removed blocking logic for writes outside the session directory, allowing them to proceed.
  • src/hooks/write-existing-file-guard/index.test.ts
    • Updated BLOCK_MESSAGE and removed OUTSIDE_SESSION_MESSAGE.
    • Modified test case for writing outside session directory to expect success instead of blocking.
  • src/mcp/AGENTS.md
    • Updated generation date.
  • src/plugin-config.test.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in config merge tests.
  • src/plugin-handlers/AGENTS.md
    • Updated generation date.
  • src/plugin-handlers/agent-config-handler.ts
    • Added filterDisabledAgents function.
    • Applied filterDisabledAgents to userAgents, projectAgents, and pluginAgents during agent merging.
  • src/plugin-handlers/agent-key-remapper.test.ts
    • Updated tests for remapAgentKeysToDisplayNames to ensure original agent keys are preserved alongside display names.
  • src/plugin-handlers/agent-key-remapper.ts
    • Modified remapAgentKeysToDisplayNames to preserve original agent keys in the remapped object.
  • src/plugin-handlers/config-handler-formatter.test.ts
    • Added new tests for createConfigHandler to ensure formatter configuration is passed through correctly.
  • src/plugin-handlers/config-handler.test.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in config handler tests.
    • Removed AGENTS_WITHOUT_TODO_DENY and updated todo deny logic for Prometheus and Sisyphus-Junior.
  • src/plugin-handlers/config-handler.ts
    • Preserved config.formatter property by reassigning it after other config applications.
  • src/plugin-handlers/tool-config-handler.test.ts
    • Added new tests for applyToolConfig to verify global and per-agent denial of todowrite and todoread when task_system is enabled.
  • src/plugin-handlers/tool-config-handler.ts
    • Added denyTodoTools to agent permissions for todowrite and todoread when task_system is enabled.
  • src/plugin/AGENTS.md
    • Updated hook count from 44 to 46.
    • Updated generation date.
    • Updated hook tiers to reflect new counts.
  • src/plugin/chat-message.test.ts
    • Added a test to ensure queued background notifications are injected through the chat.message hook.
  • src/plugin/chat-message.ts
    • Added backgroundNotificationHook and thinkMode to the list of hooks processed by createChatMessageHandler.
  • src/plugin/event.model-fallback.test.ts
    • Updated model fallback tests to use createModelFallbackHook and ensure modelFallback is provided.
    • Added a test to verify model fallback is not triggered when the hook is disabled by default.
  • src/plugin/event.ts
    • Refactored event dispatching to use HOOK_SUBSCRIPTIONS for filtering events per hook.
    • Introduced AWAITED_HOOKS to specify hooks that must be awaited.
    • Changed isRuntimeFallbackEnabled to also check isModelFallbackEnabled.
    • Removed isRuntimeFallbackEnabled check from message.updated and session.status model fallback logic.
    • Added deleteSessionTools to session deletion cleanup.
  • src/plugin/hooks/create-continuation-hooks.ts
    • Passed backgroundManager to createStopContinuationGuardHook.
  • src/plugin/hooks/create-session-hooks.ts
    • Passed pluginConfig to createPreemptiveCompactionHook and createAnthropicContextWindowLimitRecoveryHook.
    • Added allowNonGptModel from pluginConfig.agents.hephaestus to createNoHephaestusNonGptHook.
  • src/plugin/tool-execute-before-session-notification.test.ts
    • Added a new test file to verify session notification for question tools.
  • src/plugin/tool-execute-before.test.ts
    • Added tests to ensure session notification hook is triggered for question tools and not for other tools.
  • src/plugin/tool-execute-before.ts
    • Added logic to trigger the sessionNotification hook for question tool executions.
  • src/plugin/ultrawork-db-model-override.ts
    • Removed unnecessary check for result.changes before applying variant/thinking updates.
  • src/plugin/ultrawork-model-override.test.ts
    • Added a test to ensure keyword-detector variant is overridden with configured ultrawork variant.
    • Removed output.message["thinking"] expectation from tests.
  • src/plugin/ultrawork-model-override.ts
    • Updated logic to apply variant and thinking overrides directly from override.variant.
  • src/shared/AGENTS.md
    • Updated generation date.
  • src/shared/command-executor/execute-hook-command.ts
    • Added timeoutMs option to ExecuteHookOptions with a default of 30 seconds.
    • Implemented timeout mechanism with SIGTERM and SIGKILL for hook commands.
    • Added detached option to spawn for non-Windows platforms to kill process groups.
  • src/shared/migration.test.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in migration tests.
  • src/shared/migration/agent-category.ts
    • Updated Gemini model ID from gemini-3-pro to gemini-3.1-pro in MODEL_TO_CATEGORY_MAP.
  • src/shared/model-availability.test.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in various tests.
  • src/shared/model-availability.ts
    • Changed type assertion for modelItem.id from any to direct access.
  • src/shared/model-requirements.test.ts
    • Updated Hephaestus requiresProvider to include venice.
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in category model requirements tests.
    • Added tests to ensure gpt-5.3-codex entries do not include github-copilot as a provider.
  • src/shared/model-requirements.ts
    • Updated Hephaestus requiresProvider to include venice.
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in various fallback chains and requiresModel properties.
  • src/shared/model-variant-helpers.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in MODEL_VARIANT_MAP.
  • src/shared/opencode-config-dir-types.ts
    • Added model_fallback as an optional boolean property to OhMyOpenCodeConfig.
  • src/shared/opencode-config-schema.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in default agent and category configurations.
  • src/shared/opencode-sdk-types.ts
    • Added variant as an optional string property to Model.
    • Added thinking as an optional object property to ExtraBody.
  • src/shared/provider-model-id-transform.ts
    • Updated Gemini model IDs from gemini-3-pro to gemini-3.1-pro in transformation logic.
  • src/shared/session-tools-store.ts
    • Added deleteSessionTools function to clear tools for a given session ID.
  • src/shared/spawn-with-windows-hide.ts
    • Added spawnWithWindowsHide utility function to spawn child processes with windowsHide option.
  • src/shared/tmux.ts
    • Imported and used spawnWithWindowsHide for Bun.spawn calls.
  • src/tools/AGENTS.md
    • Updated generation date.
  • src/tools/hashline-edit/AGENTS.md
    • Updated generation date.
  • src/tools/hashline-edit/edit-operations.test.ts
    • Updated tests for applyHashlineEditsWithReport to handle empty lines correctly.
  • src/tools/hashline-edit/edit-operations.ts
    • Fixed applyHashlineEditsWithReport to correctly handle empty lines in lines array for replace operations.
  • src/tools/hashline-edit/hash-computation.test.ts
    • Updated tests for formatHashLines to reflect the new hashline format (|).
  • src/tools/hashline-edit/hash-computation.ts
    • Changed the hashline format from : to |.
  • src/tools/hashline-edit/index.ts
    • Exported formatHashLines, normalizeHashlineEdits, applyHashlineEditsWithReport, canonicalizeFileText, and restoreFileText.
  • src/tools/hashline-edit/normalize-edits.test.ts
    • Updated tests for normalizeHashlineEdits to handle empty lines correctly.
  • src/tools/hashline-edit/normalize-edits.ts
    • Fixed normalizeHashlineEdits to correctly handle empty lines in lines array for replace operations.
  • src/tools/hashline-edit/tool.ts
    • Updated editFileTool to use | for hashline format in input schema description.
  • src/tools/lsp/AGENTS.md
    • Updated generation date.
  • src/tools/lsp/lsp-client.ts
    • Imported and used spawnWithWindowsHide for Bun.spawn calls.
  • src/tools/lsp/lsp-manager.ts
    • Imported and used spawnWithWindowsHide for Bun.spawn calls.
  • src/tools/read/AGENTS.md
    • Updated generation date.
  • src/tools/read/read-file.test.ts
    • Updated tests for readFileTool to reflect the new hashline format (|).
  • src/tools/read/read-file.ts
    • Updated readFileTool to use | for hashline format in output description.
  • src/tools/task/AGENTS.md
    • Updated generation date.
  • src/tools/task/task-tool.test.ts
    • Added tests for max_prompt_tokens in the task tool.
  • src/tools/task/task-tool.ts
    • Added max_prompt_tokens as an optional number property to the task tool input schema.
  • src/tools/write/AGENTS.md
    • Updated generation date.
  • src/tools/write/write-file.test.ts
    • Updated tests for writeFileTool to reflect the new hashline format (|).
  • src/tools/write/write-file.ts
    • Updated writeFileTool to use | for hashline format in input schema description.
Ignored Files
  • Ignored by pattern: .github/workflows/** (2)
    • .github/workflows/publish-platform.yml
    • .github/workflows/publish.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

12 issues found across 314 files

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/features/background-agent/fallback-retry-handler.ts">

<violation number="1" location="src/features/background-agent/fallback-retry-handler.ts:106">
P3: Dead code: `task.agent` fallback is unreachable since `task.model` was unconditionally assigned a few lines above. The ternary is always true. Consider simplifying to just the template literal.</violation>
</file>

<file name="src/cli/config-manager/write-omo-config.ts">

<violation number="1" location="src/cli/config-manager/write-omo-config.ts:46">
P1: Swapped argument order reverses merge priority: existing on-disk config now silently overrides freshly generated install selections. Previously `newConfig` (user's new choices) took precedence over `existing` (on-disk); now `existing` always wins on conflicting keys. If a user re-runs `install` to change settings, their new selections won't take effect for any key already present in the config file.

If the intent is to preserve user customizations while adding new keys, consider a more explicit strategy (e.g., only merge keys that don't exist yet), and document this behavior. If the intent is for new selections to win, restore the original argument order.</violation>
</file>

<file name=".issue-comment-2064.md">

<violation number="1" location=".issue-comment-2064.md:11">
P2: This issue comment contains factually incorrect information. It claims `write-omo-config.ts` line 46 uses `deepMergeRecord(existing, newConfig)`, but the actual source already uses `deepMergeRecord(newConfig, existing)` — the exact order this document recommends as the "fix". The described bug does not exist in the current codebase. This document should either be corrected or removed to avoid misleading developers.</violation>
</file>

<file name="src/cli/run/poll-for-completion.ts">

<violation number="1" location="src/cli/run/poll-for-completion.ts:134">
P1: Missing error handling for API calls in the secondary timeout block. If `session.children()` or `session.todo()` throws, the entire polling loop crashes. Other API calls in this file (e.g., `getMainSessionStatus`) use try/catch — this block should too.</violation>

<violation number="2" location="src/cli/run/poll-for-completion.ts:145">
P2: `hasActiveChildren` counts all children regardless of status, unlike `hasActiveTodos` which filters by status. A session with only idle/completed children will falsely trigger `hasReceivedMeaningfulWork = true`. Consider checking child session statuses (as done in `completion.ts`'s `areAllDescendantsIdle`).</violation>
</file>

<file name="src/features/background-agent/compaction-aware-message-resolver.ts">

<violation number="1" location="src/features/background-agent/compaction-aware-message-resolver.ts:16">
P1: Bug: `hasPartialAgentOrModel` can still match compaction agent messages. When a message has `agent: "compaction"` but valid model fields, `hasModel` is `true` and the OR returns `true`, allowing a compaction message to leak through the fallback pass. The function should reject compaction agents outright before checking partial fields.</violation>
</file>

<file name="src/cli/config-manager/antigravity-provider-configuration.ts">

<violation number="1" location="src/cli/config-manager/antigravity-provider-configuration.ts:19">
P2: Stale documentation: `docs/guide/installation.md` still references the old `antigravity-gemini-3-pro` model name in 3 places. These should be updated to `antigravity-gemini-3.1-pro` to match this rename.</violation>

<violation number="2" location="src/cli/config-manager/antigravity-provider-configuration.ts:19">
P2: Display name not updated to match model version bump: key says `3.1` but `name` still says `Gemini 3 Pro`. Should be `"Gemini 3.1 Pro (Antigravity)"`.</violation>
</file>

<file name=".github/workflows/publish-platform.yml">

<violation number="1" location=".github/workflows/publish-platform.yml:203">
P1: Using `if: always() && !cancelled()` on the publish job means it runs even when core platform builds fail. Combined with `continue-on-error: true` on the download step, a failure in any critical platform (e.g., `darwin-arm64`, `linux-x64`) will be silently swallowed — the workflow can succeed while that platform's binary is missing from npm. Consider either: (a) separating baseline builds into a separate job with `continue-on-error` so core builds remain required, or (b) adding a validation step that checks `needs.build.result == 'success'` for non-baseline platforms before publishing.</violation>
</file>

<file name="src/features/background-agent/process-cleanup.ts">

<violation number="1" location="src/features/background-agent/process-cleanup.ts:35">
P1: `cleanupAll()` can be called multiple times (signal→exit, beforeExit→exit, or rapid Ctrl+C), causing `shutdown()` to run repeatedly on each manager. Add a re-entrancy guard to ensure cleanup executes only once.</violation>
</file>

<file name="src/features/background-agent/error-classifier.ts">

<violation number="1" location="src/features/background-agent/error-classifier.ts:1">
P2: Duplicate of `src/shared/record-type-guard.ts`. Several modules already import the shared `isRecord`—reuse it here instead of adding another copy.</violation>
</file>

<file name="benchmarks/headless.ts">

<violation number="1" location="benchmarks/headless.ts:32">
P1: Missing closing `}` for the `for await` loop. The `}` on this line closes the `switch`, but there is no subsequent `}` to close the `for await (const part of stream.fullStream)` loop. As a result, `await stream.response`, `messages.push(...)`, the `finishReason` check, and the `break` statement all execute **inside** the for-await loop rather than after it. This causes: (1) `stream.response` blocks on the first part so remaining parts never go through the switch, (2) the `break` exits the for-await loop, not the step loop, so the agent loop keeps running when it should stop.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

}

const merged = deepMergeRecord(existing, newConfig)
const merged = deepMergeRecord(newConfig, existing)
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Swapped argument order reverses merge priority: existing on-disk config now silently overrides freshly generated install selections. Previously newConfig (user's new choices) took precedence over existing (on-disk); now existing always wins on conflicting keys. If a user re-runs install to change settings, their new selections won't take effect for any key already present in the config file.

If the intent is to preserve user customizations while adding new keys, consider a more explicit strategy (e.g., only merge keys that don't exist yet), and document this behavior. If the intent is for new selections to win, restore the original argument order.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/cli/config-manager/write-omo-config.ts, line 46:

<comment>Swapped argument order reverses merge priority: existing on-disk config now silently overrides freshly generated install selections. Previously `newConfig` (user's new choices) took precedence over `existing` (on-disk); now `existing` always wins on conflicting keys. If a user re-runs `install` to change settings, their new selections won't take effect for any key already present in the config file.

If the intent is to preserve user customizations while adding new keys, consider a more explicit strategy (e.g., only merge keys that don't exist yet), and document this behavior. If the intent is for new selections to win, restore the original argument order.</comment>

<file context>
@@ -43,7 +43,7 @@ export function writeOmoConfig(installConfig: InstallConfig): ConfigMergeResult
         }
 
-        const merged = deepMergeRecord(existing, newConfig)
+        const merged = deepMergeRecord(newConfig, existing)
         writeFileSync(omoConfigPath, JSON.stringify(merged, null, 2) + "\n")
       } catch (parseErr) {
</file context>
Fix with Cubic

) {
secondaryTimeoutChecked = true
// Check if session actually has pending work (children, todos, etc.)
const childrenRes = await ctx.client.session.children({
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Missing error handling for API calls in the secondary timeout block. If session.children() or session.todo() throws, the entire polling loop crashes. Other API calls in this file (e.g., getMainSessionStatus) use try/catch — this block should too.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/cli/run/poll-for-completion.ts, line 134:

<comment>Missing error handling for API calls in the secondary timeout block. If `session.children()` or `session.todo()` throws, the entire polling loop crashes. Other API calls in this file (e.g., `getMainSessionStatus`) use try/catch — this block should too.</comment>

<file context>
@@ -81,6 +121,50 @@ export async function pollForCompletion(
+      ) {
+        secondaryTimeoutChecked = true
+        // Check if session actually has pending work (children, todos, etc.)
+        const childrenRes = await ctx.client.session.children({
+          path: { id: ctx.sessionID },
+          query: { directory: ctx.directory },
</file context>
Fix with Cubic

!!message.model?.modelID
}

function hasPartialAgentOrModel(message: StoredMessage): boolean {
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Bug: hasPartialAgentOrModel can still match compaction agent messages. When a message has agent: "compaction" but valid model fields, hasModel is true and the OR returns true, allowing a compaction message to leak through the fallback pass. The function should reject compaction agents outright before checking partial fields.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/background-agent/compaction-aware-message-resolver.ts, line 16:

<comment>Bug: `hasPartialAgentOrModel` can still match compaction agent messages. When a message has `agent: "compaction"` but valid model fields, `hasModel` is `true` and the OR returns `true`, allowing a compaction message to leak through the fallback pass. The function should reject compaction agents outright before checking partial fields.</comment>

<file context>
@@ -0,0 +1,57 @@
+    !!message.model?.modelID
+}
+
+function hasPartialAgentOrModel(message: StoredMessage): boolean {
+  const hasAgent = !!message.agent && !isCompactionAgent(message.agent)
+  const hasModel = !!message.model?.providerID && !!message.model?.modelID
</file context>
Fix with Cubic

# =============================================================================
publish:
needs: build
if: always() && !cancelled()
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Using if: always() && !cancelled() on the publish job means it runs even when core platform builds fail. Combined with continue-on-error: true on the download step, a failure in any critical platform (e.g., darwin-arm64, linux-x64) will be silently swallowed — the workflow can succeed while that platform's binary is missing from npm. Consider either: (a) separating baseline builds into a separate job with continue-on-error so core builds remain required, or (b) adding a validation step that checks needs.build.result == 'success' for non-baseline platforms before publishing.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/publish-platform.yml, line 203:

<comment>Using `if: always() && !cancelled()` on the publish job means it runs even when core platform builds fail. Combined with `continue-on-error: true` on the download step, a failure in any critical platform (e.g., `darwin-arm64`, `linux-x64`) will be silently swallowed — the workflow can succeed while that platform's binary is missing from npm. Consider either: (a) separating baseline builds into a separate job with `continue-on-error` so core builds remain required, or (b) adding a validation step that checks `needs.build.result == 'success'` for non-baseline platforms before publishing.</comment>

<file context>
@@ -150,12 +200,13 @@ jobs:
   # =============================================================================
   publish:
     needs: build
+    if: always() && !cancelled()
     runs-on: ubuntu-latest
     strategy:
</file context>
Fix with Cubic

if (cleanupRegistered) return
cleanupRegistered = true

const cleanupAll = () => {
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: cleanupAll() can be called multiple times (signal→exit, beforeExit→exit, or rapid Ctrl+C), causing shutdown() to run repeatedly on each manager. Add a re-entrancy guard to ensure cleanup executes only once.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/background-agent/process-cleanup.ts, line 35:

<comment>`cleanupAll()` can be called multiple times (signal→exit, beforeExit→exit, or rapid Ctrl+C), causing `shutdown()` to run repeatedly on each manager. Add a re-entrancy guard to ensure cleanup executes only once.</comment>

<file context>
@@ -0,0 +1,81 @@
+  if (cleanupRegistered) return
+  cleanupRegistered = true
+
+  const cleanupAll = () => {
+    for (const m of cleanupManagers) {
+      try {
</file context>
Fix with Cubic

})
const todos = normalizeSDKResponse(todosRes, [] as unknown[])

const hasActiveChildren =
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: hasActiveChildren counts all children regardless of status, unlike hasActiveTodos which filters by status. A session with only idle/completed children will falsely trigger hasReceivedMeaningfulWork = true. Consider checking child session statuses (as done in completion.ts's areAllDescendantsIdle).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/cli/run/poll-for-completion.ts, line 145:

<comment>`hasActiveChildren` counts all children regardless of status, unlike `hasActiveTodos` which filters by status. A session with only idle/completed children will falsely trigger `hasReceivedMeaningfulWork = true`. Consider checking child session statuses (as done in `completion.ts`'s `areAllDescendantsIdle`).</comment>

<file context>
@@ -81,6 +121,50 @@ export async function pollForCompletion(
+        })
+        const todos = normalizeSDKResponse(todosRes, [] as unknown[])
+
+        const hasActiveChildren =
+          Array.isArray(children) && children.length > 0
+        const hasActiveTodos =
</file context>
Fix with Cubic

/**
* Antigravity Provider Configuration
*
* IMPORTANT: Model names MUST use `antigravity-` prefix for stability.
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Stale documentation: docs/guide/installation.md still references the old antigravity-gemini-3-pro model name in 3 places. These should be updated to antigravity-gemini-3.1-pro to match this rename.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/cli/config-manager/antigravity-provider-configuration.ts, line 19:

<comment>Stale documentation: `docs/guide/installation.md` still references the old `antigravity-gemini-3-pro` model name in 3 places. These should be updated to `antigravity-gemini-3.1-pro` to match this rename.</comment>

<file context>
@@ -16,7 +16,7 @@ export const ANTIGRAVITY_PROVIDER_CONFIG = {
     name: "Google",
     models: {
-      "antigravity-gemini-3-pro": {
+      "antigravity-gemini-3.1-pro": {
         name: "Gemini 3 Pro (Antigravity)",
         limit: { context: 1048576, output: 65535 },
</file context>
Fix with Cubic

name: "Google",
models: {
"antigravity-gemini-3-pro": {
"antigravity-gemini-3.1-pro": {
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Display name not updated to match model version bump: key says 3.1 but name still says Gemini 3 Pro. Should be "Gemini 3.1 Pro (Antigravity)".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/cli/config-manager/antigravity-provider-configuration.ts, line 19:

<comment>Display name not updated to match model version bump: key says `3.1` but `name` still says `Gemini 3 Pro`. Should be `"Gemini 3.1 Pro (Antigravity)"`.</comment>

<file context>
@@ -16,7 +16,7 @@ export const ANTIGRAVITY_PROVIDER_CONFIG = {
     name: "Google",
     models: {
-      "antigravity-gemini-3-pro": {
+      "antigravity-gemini-3.1-pro": {
         name: "Gemini 3 Pro (Antigravity)",
         limit: { context: 1048576, output: 65535 },
</file context>
Fix with Cubic

@@ -1,3 +1,7 @@
export function isRecord(value: unknown): value is Record<string, unknown> {
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Duplicate of src/shared/record-type-guard.ts. Several modules already import the shared isRecord—reuse it here instead of adding another copy.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/background-agent/error-classifier.ts, line 1:

<comment>Duplicate of `src/shared/record-type-guard.ts`. Several modules already import the shared `isRecord`—reuse it here instead of adding another copy.</comment>

<file context>
@@ -1,3 +1,7 @@
+export function isRecord(value: unknown): value is Record<string, unknown> {
+  return typeof value === "object" && value !== null
+}
</file context>
Fix with Cubic

task.queuedAt = new Date()
task.error = undefined

const key = task.model ? `${task.model.providerID}/${task.model.modelID}` : task.agent
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Dead code: task.agent fallback is unreachable since task.model was unconditionally assigned a few lines above. The ternary is always true. Consider simplifying to just the template literal.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/background-agent/fallback-retry-handler.ts, line 106:

<comment>Dead code: `task.agent` fallback is unreachable since `task.model` was unconditionally assigned a few lines above. The ternary is always true. Consider simplifying to just the template literal.</comment>

<file context>
@@ -0,0 +1,126 @@
+  task.queuedAt = new Date()
+  task.error = undefined
+
+  const key = task.model ? `${task.model.providerID}/${task.model.modelID}` : task.agent
+  const queue = queuesByKey.get(key) ?? []
+  const retryInput: LaunchInput = {
</file context>
Fix with Cubic

Comment on lines +4 to +19
describe("normalizeHashlineEdits", () => {
it("maps replace with pos to replace", () => {
//#given
const input: RawHashlineEdit[] = [{ op: "replace", pos: "2#VK", lines: "updated" }]

//#when
const result = normalizeHashlineEdits(input)

//#then
expect(result).toEqual([{ op: "replace", pos: "2#VK", lines: "updated" }])
})

it("maps replace with pos and end to replace", () => {
//#given
const input: RawHashlineEdit[] = [{ op: "replace", pos: "2#VK", end: "4#MB", lines: ["a", "b"] }]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Given/when/then uses comments 📘 Rule violation ✓ Correctness

The new normalize-edits.test.ts uses //#given/#when/#then comments instead of the required
nested describe blocks. This violates the required test structure convention.
Agent Prompt
## Issue description
Tests are using `//#given/#when/#then` comment markers instead of nested `describe` blocks with `#given/#when/#then` prefixes.

## Issue Context
The test style requirement is explicit about using nested `describe` blocks for given/when/then organization.

## Fix Focus Areas
- src/tools/hashline-edit/normalize-edits.test.ts[4-61]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +54 to +66
function createMockClient() {
return {
session: {
abort: mock(async () => ({})),
},
} as any
}

function createDefaultArgs(taskOverrides: Partial<BackgroundTask> = {}) {
const processKeyFn = mock(() => {})
const queuesByKey = new Map<string, Array<{ task: BackgroundTask; input: any }>>()
const idleDeferralTimers = new Map<string, ReturnType<typeof setTimeout>>()
const concurrencyManager = createMockConcurrencyManager()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. as any in new test 📘 Rule violation ✓ Correctness

The new fallback-retry-handler.test.ts introduces as any casts, which suppress type safety. This
violates the prohibition on type/lint suppression mechanisms in modified code.
Agent Prompt
## Issue description
New tests introduce `as any` casts, which suppress type safety and are explicitly disallowed.

## Issue Context
These casts are used to shape mock objects and to access mock methods on imported functions.

## Fix Focus Areas
- src/features/background-agent/fallback-retry-handler.test.ts[54-66]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +1 to +3
[sisyphus-bot]

## Confirmed Bug

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. .issue-comment-2064.md naming 📘 Rule violation ✓ Correctness

A new file .issue-comment-2064.md was added with a leading dot, which is not kebab-case. This
violates the kebab-case-only requirement for new file names.
Agent Prompt
## Issue description
A newly added file name uses a leading dot and is not kebab-case.

## Issue Context
Compliance requires kebab-case for all newly added or renamed files/directories.

## Fix Focus Areas
- .issue-comment-2064.md[1-61]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +140 to +168
const SESSION_LIFECYCLE = ["session.idle", "session.created", "session.deleted", "session.status", "session.error", "session.updated"];
const MESSAGE_EVENTS = ["message.updated", "message.part.updated"];
const HOOK_SUBSCRIPTIONS: Record<string, string[] | "*"> = {
// ALL events including deltas (transcript tracking, streaming output monitoring)
claudeCodeHooks: "*",
interactiveBashSession: "*",
// Session lifecycle only
sessionNotification: SESSION_LIFECYCLE,
unstableAgentBabysitter: SESSION_LIFECYCLE,
runtimeFallback: SESSION_LIFECYCLE,
agentUsageReminder: SESSION_LIFECYCLE,
categorySkillReminder: SESSION_LIFECYCLE,
ralphLoop: SESSION_LIFECYCLE,
stopContinuationGuard: SESSION_LIFECYCLE,
backgroundNotificationHook: SESSION_LIFECYCLE,
autoUpdateChecker: SESSION_LIFECYCLE,
// Message events (no deltas)
contextWindowMonitor: [...MESSAGE_EVENTS, "session.status"],
anthropicContextWindowLimitRecovery: MESSAGE_EVENTS,
compactionTodoPreserver: MESSAGE_EVENTS,
writeExistingFileGuard: MESSAGE_EVENTS,
todoContinuationEnforcer: MESSAGE_EVENTS,
atlasHook: MESSAGE_EVENTS,
// Chat-level events
directoryAgentsInjector: ["session.created", "message.updated"],
directoryReadmeInjector: ["session.created", "message.updated"],
rulesInjector: ["session.created", "message.updated"],
thinkMode: ["session.created", "message.updated"],
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Broken hook subscriptions 🐞 Bug ✓ Correctness

HOOK_SUBSCRIPTIONS is used to skip hook invocations, but multiple hooks are subscribed to
too-narrow event sets that omit event types their own handlers explicitly depend on. This will
prevent core behaviors (todo continuation, auto-compact recovery, atlas continuation,
runtime/background fallback, notifications) and some cleanups from ever running.
Agent Prompt
## Issue description
`src/plugin/event.ts` now filters hook invocations via `HOOK_SUBSCRIPTIONS`, but many hooks are subscribed to event sets that omit event types their own handlers explicitly process (e.g. `session.idle`, `session.error`, `session.compacted`, `session.stop`, `tool.execute.*`). This makes key hook logic unreachable and breaks functionality/cleanup.

## Issue Context
The dispatcher enforces the subscription list (`if (subs !== "*" && !subs.includes(eventType)) continue;`). Several hook implementations contain branches for events that are not in their configured subscription arrays.

## Fix Focus Areas
- src/plugin/event.ts[140-168]
- src/plugin/event.ts[199-208]
- src/hooks/todo-continuation-enforcer/handler.ts[32-68]
- src/hooks/anthropic-context-window-limit-recovery/recovery-hook.ts[39-140]
- src/hooks/atlas/event-handler.ts[26-43]
- src/hooks/atlas/event-handler.ts[178-204]
- src/hooks/runtime-fallback/event-handler.ts[190-195]
- src/hooks/session-notification.ts[136-185]
- src/features/background-agent/manager.ts[693-755]

## Suggested direction
1. Expand `SESSION_LIFECYCLE` to include at least `session.compacted` and `session.stop` (and any other session.* events used by hooks).
2. Fix individual subscriptions, e.g.:
   - `todoContinuationEnforcer`: include `session.idle`, `session.error`, `session.deleted`, and tool events it watches.
   - `anthropicContextWindowLimitRecovery`: include `session.error`, `session.idle`, `session.deleted`.
   - `atlasHook`: include `session.idle`, `session.error`, `session.deleted`, `session.compacted`, and `tool.execute.*`.
   - `runtimeFallback`: include `message.updated` and `session.stop`.
   - `sessionNotification`: include `message.updated` and `tool.execute.*`.
   - `backgroundNotificationHook`: likely `"*"` (it routes all events to `BackgroundManager`).
3. Alternatively (often simpler/safer): only special-case filtering for `message.part.delta` by maintaining a small allowlist of hooks for that single high-frequency event, and let all hooks receive other event types as before.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a wide range of improvements, with the primary goal of optimizing performance through a new event dispatching mechanism. While the core dispatcher code was not in the provided diffs, the other changes are substantial and enhance the project's robustness, feature set, and maintainability.

Key changes include:

  • A critical bug fix in the configuration merging logic to correctly respect user overrides.
  • Significant robustness improvements, such as adding an AVX2 fallback for native binaries and implementing watchdog timers and backoff mechanisms for long-running processes.
  • New features, most notably support for Gemini models with tailored prompts and integration for git worktrees.
  • Numerous refactorings that improve code structure, such as centralizing error classification and event handling logic.

My review identified one medium-severity issue regarding a schema change that weakens configuration validation. Overall, this is a high-quality contribution with many valuable enhancements.

default_run_agent: z.string().optional(),
disabled_mcps: z.array(AnyMcpNameSchema).optional(),
disabled_agents: z.array(BuiltinAgentNameSchema).optional(),
disabled_agents: z.array(z.string()).optional(),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Changing disabled_agents from z.array(BuiltinAgentNameSchema) to z.array(z.string()) weakens configuration validation. This means typos in agent names will no longer be caught by the schema, potentially leading to agents not being disabled as expected. If the list of agents is now dynamic, it would be helpful to add a .describe() to the schema explaining this and pointing to where users can find the list of valid agent names. If the list is still static, restoring the stricter schema (BuiltinAgentNameSchema) would be preferable for user config safety.

…h dispatch overhead

Replace sequential all-hooks dispatch with subscription-based filtering.
Each hook declares which event types it cares about via HOOK_SUBSCRIPTIONS.
Critical hooks (claudeCodeHooks, stopContinuationGuard, writeExistingFileGuard)
remain awaited; 18 other hooks fire-and-forget with error logging.

During LLM streaming (~100 message.part.delta events/sec), 19 of 21 hooks
are now skipped entirely, reducing async dispatch from ~2100/sec to ~200/sec.
@coleleavitt coleleavitt force-pushed the refactor/hook-event-filtering branch from 3d851eb to 39eabd8 Compare February 27, 2026 01:53
@kusari-inspector
Copy link

⚠️ Workspace Mapping Required

Hello! We noticed that your GitHub organization is not yet mapped to a Kusari workspace. Kusari Inspector now requires installations to be associated with a Kusari workspace.

⚠️ NOTE: Only the admin who installed the Kusari GitHub App can complete these steps. If the admin is unable to complete these steps, please contact support@kusari.dev

To complete the setup:

  1. Visit https://console.us.kusari.cloud/auth/github and log in via github
  2. If you have only one workspace, it will be automatically selected for you
  3. Once the mapping is complete, return here and create a new comment with: @kusari-inspector re-run

This will trigger the analysis to run again.

For more information, or if you need help, visit https://github.com/kusaridev/community/discussions

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/plugin/event.ts (1)

175-197: Avoid silent wildcard fallback for unmapped hooks.

Using HOOK_SUBSCRIPTIONS[name] ?? "*" hides missed mappings and can silently regress dispatch filtering. Consider surfacing missing entries (e.g., startup warning or assertion) so new hooks are explicitly classified.

♻️ Suggested hardening
-  ] as [string, HookInvoker][]).map(([name, fn]) => [name, fn, HOOK_SUBSCRIPTIONS[name] ?? "*"] as [string, HookInvoker, string[] | "*"]);
+  ] as [string, HookInvoker][]).map(([name, fn]) => {
+    const subs = HOOK_SUBSCRIPTIONS[name];
+    if (!subs) {
+      log("[event] missing HOOK_SUBSCRIPTIONS entry; defaulting to '*'", { hook: name });
+    }
+    return [name, fn, subs ?? "*"] as [string, HookInvoker, string[] | "*"];
+  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugin/event.ts` around lines 175 - 197, The current hookEntries builder
silently falls back to "*" via HOOK_SUBSCRIPTIONS[name] ?? "*" which hides
missing mappings; update the map that constructs hookEntries to explicitly
detect when HOOK_SUBSCRIPTIONS[name] is undefined and surface it (e.g., call a
startup assertion or emit a clear processLogger.warn/error mentioning the hook
name) instead of defaulting to "*", and then use an explicit default like an
empty array or fail-fast in development; change the expression
HOOK_SUBSCRIPTIONS[name] ?? "*" to an inline check (e.g., const subs =
HOOK_SUBSCRIPTIONS[name]; if (!subs) { processLogger.warn(`Missing
HOOK_SUBSCRIPTIONS entry for ${name}`); /* or throw new Error(...) */ } ) and
return subs or [] accordingly so new hooks cannot regress dispatch filtering
silently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/plugin/event.ts`:
- Around line 205-207: The current fire-and-forget path calls invoke(input)
directly so a synchronous throw escapes the .catch; change the wrapping to start
the chain with Promise.resolve().then(() => invoke(input)).catch(err =>
log("[hook] error:", { hook: name, error: err })), so both sync and async errors
from invoke are caught; update the else block that references invoke, log, name,
and input accordingly (do not await the promise).

---

Nitpick comments:
In `@src/plugin/event.ts`:
- Around line 175-197: The current hookEntries builder silently falls back to
"*" via HOOK_SUBSCRIPTIONS[name] ?? "*" which hides missing mappings; update the
map that constructs hookEntries to explicitly detect when
HOOK_SUBSCRIPTIONS[name] is undefined and surface it (e.g., call a startup
assertion or emit a clear processLogger.warn/error mentioning the hook name)
instead of defaulting to "*", and then use an explicit default like an empty
array or fail-fast in development; change the expression
HOOK_SUBSCRIPTIONS[name] ?? "*" to an inline check (e.g., const subs =
HOOK_SUBSCRIPTIONS[name]; if (!subs) { processLogger.warn(`Missing
HOOK_SUBSCRIPTIONS entry for ${name}`); /* or throw new Error(...) */ } ) and
return subs or [] accordingly so new hooks cannot regress dispatch filtering
silently.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f3cbc24 and 39eabd8.

📒 Files selected for processing (1)
  • src/plugin/event.ts

…cription map

- Add session.compacted to SESSION_LIFECYCLE (it's a lifecycle event)
- Add session.deleted to hooks that do cleanup: contextWindowMonitor,
  compactionTodoPreserver, writeExistingFileGuard, todoContinuationEnforcer,
  directoryReadmeInjector, thinkMode
- Add session.compacted to hooks that reset state on compaction:
  compactionTodoPreserver, atlasHook, directoryAgentsInjector,
  directoryReadmeInjector, rulesInjector
- Fix sync throw escaping fire-and-forget catch by wrapping invoke in
  Promise.resolve().then() instead of Promise.resolve(invoke())
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/plugin/event.ts (1)

199-208: Sync-throw handling is now correct; consider adding void prefix.

The fix using Promise.resolve().then(() => invoke(input)) properly catches synchronous throws since invoke is called inside the .then() callback. However, the fire-and-forget promise at line 206 lacks an explicit void prefix, which some linters flag as an unhandled promise.

✨ Optional: Add void prefix for explicit intent
       } else {
-        Promise.resolve().then(() => invoke(input)).catch((err) => log("[hook] error:", { hook: name, error: err }));
+        void Promise.resolve().then(() => invoke(input)).catch((err) => log("[hook] error:", { hook: name, error: err }));
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugin/event.ts` around lines 199 - 208, In dispatchToHooks, for the
fire-and-forget branch (when a hook name is not in AWAITED_HOOKS) prefix the
Promise.resolve().then(() => invoke(input)).catch(...) call with void to mark
the returned promise as intentionally unawaited; locate the loop over
hookEntries and the non-awaited branch that currently calls invoke(input) inside
Promise.resolve().then and change it to use a void prefix while preserving the
.catch handler so synchronous throws are still caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/plugin/event.ts`:
- Around line 199-208: In dispatchToHooks, for the fire-and-forget branch (when
a hook name is not in AWAITED_HOOKS) prefix the Promise.resolve().then(() =>
invoke(input)).catch(...) call with void to mark the returned promise as
intentionally unawaited; locate the loop over hookEntries and the non-awaited
branch that currently calls invoke(input) inside Promise.resolve().then and
change it to use a void prefix while preserving the .catch handler so
synchronous throws are still caught.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39eabd8 and cae1645.

📒 Files selected for processing (1)
  • src/plugin/event.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant