121 Commits

Author SHA1 Message Date
YeonGyu-Kim
5b34a98e0a feat(background-agent): use "interrupt" status for promptAsync errors
Change promptAsync catch blocks to set status = "interrupt" instead of "error".

This distinguishes prompt errors from stale timeouts (cancelled) and TTL expirations (error).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-09 18:25:54 +09:00
YeonGyu-Kim
a37259326a feat(background-agent): add "interrupt" to BackgroundTaskStatus type
Add interrupt as a terminal status for background tasks that fail due to promptAsync errors (e.g., prompt exceed, agent not found).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-09 18:25:34 +09:00
YeonGyu-Kim
0e49214ee7 fix(background-agent): rename getCompletedTasks to getNonRunningTasks for semantic accuracy 2026-02-09 11:45:20 +09:00
YeonGyu-Kim
7fdba56d8f fix(background-agent): align getCompletedTasks filter with state manager semantics 2026-02-09 11:36:29 +09:00
YeonGyu-Kim
247940bf02 fix: address Cubic background-agent issues — task status filter, array response handling, error mapping, concurrency key, duration fallback, output validation 2026-02-09 11:19:39 +09:00
YeonGyu-Kim
d6fbe7bd8d fix: address Cubic CLI and agent issues — URL encode, JSONC leading comments, config clone, untracked files, parse error handling, cache path, message-dir dedup 2026-02-09 11:17:51 +09:00
YeonGyu-Kim
ce37924fd8 Merge remote-tracking branch 'origin/dev' into refactor/modular-code-enforcement
# Conflicts:
#	src/features/background-agent/manager.ts
#	src/features/background-agent/spawner.ts
#	src/features/tmux-subagent/manager.ts
#	src/shared/model-availability.test.ts
#	src/shared/model-availability.ts
#	src/shared/model-resolution-pipeline.ts
#	src/tools/delegate-task/executor.ts
2026-02-08 21:43:57 +09:00
YeonGyu-Kim
46a30cd7ec Merge remote-tracking branch 'origin/dev' into refactor/modular-code-enforcement
# Conflicts:
#	src/agents/utils.ts
#	src/config/schema.ts
#	src/features/background-agent/spawner/background-session-creator.ts
#	src/features/background-agent/spawner/parent-directory-resolver.ts
#	src/features/background-agent/spawner/tmux-callback-invoker.ts
#	src/features/tmux-subagent/manager.ts
#	src/hooks/interactive-bash-session/index.ts
#	src/hooks/task-continuation-enforcer.test.ts
#	src/index.ts
#	src/plugin-handlers/config-handler.test.ts
#	src/tools/background-task/tools.ts
#	src/tools/call-omo-agent/tools.ts
#	src/tools/delegate-task/executor.ts
2026-02-08 19:05:41 +09:00
YeonGyu-Kim
1324fee30f feat(cli/run, background-agent): manage session permissions for CLI and background tasks
- Deny question prompts in CLI run mode since there's no TUI to answer them
- Inherit parent session permission rules in background task sessions
- Force deny questions while preserving other parent permission settings
- Add test coverage for permission inheritance behavior

🤖 Generated with assistance of OhMyOpenCode
2026-02-08 18:41:26 +09:00
YeonGyu-Kim
d5f0e75b7d fix: restore permission config in background session creation
Add permission: [{ permission: 'question', action: 'deny', pattern: '*' }]
to client.session.create() call to prevent background sessions from
asking questions that go unanswered, causing hangs.
2026-02-08 18:39:36 +09:00
YeonGyu-Kim
42dbc8f39c Fix Issue #1428: Deny bash permission for Prometheus agent
- Change PROMETHEUS_PERMISSION bash from 'allow' to 'deny' to prevent unrestricted bash execution
- Prometheus is a read-only planner and should not execute bash commands
- The prometheus-md-only hook provides additional blocking as backup
2026-02-08 17:37:44 +09:00
YeonGyu-Kim
f3f6ba47fe merge: integrate origin/dev into modular-enforcement branch
Resolves all merge conflicts, preserving our split module structure
while integrating all dev changes:
- Custom agent summaries support (parseRegisteredAgentSummaries)
- Background notification queue (enqueueNotificationForParent)
- Atlas shared git-worktree module (collectGitDiffStats, formatFileChanges)
- Ralph-loop withTimeout + DEFAULT_API_TIMEOUT=5000
- Session recovery assistant_prefill_unsupported error type
- Atlas agentOverrides forwarding
- Config handler plan model demotion (buildPlanDemoteConfig)
- Delegate-task agentOverrides, promptSyncWithModelSuggestionRetry, variant
- LSP init timeout + stale init detection
- isPlanFamily function + task-continuation-enforcer hook
- Handoff command
2026-02-08 17:34:47 +09:00
YeonGyu-Kim
e3bd43ff64 refactor(background-agent): split manager.ts into focused modules
Extract 30+ single-responsibility modules from manager.ts (1556 LOC):
- task lifecycle: task-starter, task-completer, task-canceller, task-resumer
- task queries: task-queries, task-poller, task-queue-processor
- notifications: notification-builder, notification-tracker, parent-session-notifier
- session handling: session-validator, session-output-validator, session-todo-checker
- spawner: spawner/ directory with focused spawn modules
- utilities: duration-formatter, error-classifier, message-storage-locator
- result handling: result-handler-context, background-task-completer
- shutdown: background-manager-shutdown, process-signal
2026-02-08 16:20:52 +09:00
YeonGyu-Kim
f1fcc26aaa fix(background-agent): serialize parent notifications (#1582) 2026-02-08 13:05:06 +09:00
Peïo Thibault
414cecd7df test: add promptAsync mocks to all test files for promptAsync migration 2026-02-07 14:41:46 +01:00
Peïo Thibault
5f21ddf473 fix(background-agent): switch session.prompt to promptAsync 2026-02-07 13:42:20 +01:00
YeonGyu-Kim
9040383da7 fix: cascade cancel descendant tasks when parent session is deleted (#114)
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-07 19:10:49 +09:00
YeonGyu-Kim
a691a3ac0a refactor: migrate delegate_task to task tool with metadata fixes
- Rename delegate_task tool to task across codebase (100 files)
- Update model references: claude-opus-4-6 → 4-5, gpt-5.3-codex → 5.2-codex
- Add tool-metadata-store to restore metadata overwritten by fromPlugin()
- Add session ID polling for BackgroundManager task sessions
- Await async ctx.metadata() calls in tool executors
- Add ses_ prefix guard to getMessageDir for performance
- Harden BackgroundManager with idle deferral and error handling
- Fix duplicate task key in sisyphus-junior test object literals
- Fix unawaited showOutputToUser in ast_grep_replace
- Fix background=true → run_in_background=true in ultrawork prompt
- Fix duplicate task/task references in docs and comments
2026-02-06 21:35:30 +09:00
YeonGyu-Kim
1f64920453 chore: update claude-opus-4-5 references to claude-opus-4-6 (excludes antigravity models) 2026-02-06 15:09:07 +09:00
YeonGyu-Kim
48cb2033e2 fix(background-agent): gracefully handle aborted parent session in notifyParentSession
When the main session is aborted while background tasks are running,
notifyParentSession() would attempt to call session.messages() and
session.prompt() on the aborted parent session, causing exceptions
that could crash the TUI.

- Add isAbortedSessionError() helper to detect abort-related errors
- Add abort check in session.messages() catch block with early return
- Add abort check in session.prompt() catch block with early return
- Add test case covering aborted parent session scenario

Fixes TUI crash when aborting main session with running background tasks.
2026-02-05 11:31:54 +09:00
YeonGyu-Kim
1e383f44d9 fix(background-agent): abort session on model suggestion retry failure
When promptWithModelSuggestionRetry() fails, the session was not being aborted, causing the polling loop to wait forever for an idle state. Added session.abort() calls in startTask() and resume() catch blocks.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-04 13:36:45 +09:00
YeonGyu-Kim
49c933961e fix(background-cancel): skip notification when user explicitly cancels tasks
- Add skipNotification option to cancelTask method
- Apply skipNotification to background_cancel tool
- Prevents unwanted notifications when user cancels via tool
2026-02-03 16:56:40 +09:00
YeonGyu-Kim
e36dde6e64
refactor(background-agent): optimize lifecycle and simplify tools (#1411)
* refactor(background-agent): optimize cache timer lifecycle and result handling

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(background-task): simplify tool implementation and expand test coverage

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(background-task): fix BackgroundCancel tool parameter handling

Correct parameter names and types in BackgroundCancel tool to match actual usage patterns. Add comprehensive test coverage for parameter validation.

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-03 12:11:45 +09:00
YeonGyu-Kim
159fccddcf refactor(background-agent): optimize cache timer lifecycle and result handling
Improve cache timer management in background agent manager and update result handler to properly handle cache state transitions
2026-02-02 21:07:20 +09:00
YeonGyu-Kim
25dcd2a3f2 fix(background-agent): prevent concurrency slot leaks on task startup failures
Unify slot ownership: processKey() owns the slot until task.concurrencyKey is set.
Previously, startTask() released the slot on errors (session.create catch,
createResult.error), but processKey() catch block didn't release, causing slot
leaks when errors occurred between acquire() and task.concurrencyKey assignment.

Changes:
- Remove all pre-transfer release() calls in startTask()
- Add conditional release in processKey() catch: only if task.concurrencyKey not set
- Add validation for createResult.data?.id to catch malformed API responses

This fixes 'Task failed to start within timeout' errors caused by exhausted
concurrency slots that were never released.
2026-02-01 21:24:52 +09:00
YeonGyu-Kim
6bcc3c33f0 refactor(background-agent): show category in task completion notification
Add agent category info to the task completion notification for better
visibility of what category was used for the task.
2026-02-01 19:45:09 +09:00
YeonGyu-Kim
6080bc8caf refactor(delegate-task): improve session title format and add task_metadata block
- Change session title from 'Task: {desc}' to '{desc} (@{agent} subagent)'
- Move session_id to structured <task_metadata> block for better parsing
- Add category tracking to BackgroundTask type and LaunchInput
- Add tests for new title format and metadata block
2026-02-01 19:44:22 +09:00
YeonGyu-Kim
09e738c989 refactor(background-agent): optimize task timing and constants management
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-01 19:01:30 +09:00
justsisyphus
7f9fcc708f fix(tests): properly stub notifyParentSession and fix timer-based tests
- Add stubNotifyParentSession implementation to stub manager's notifyParentSession method
- Add stubNotifyParentSession calls to checkAndInterruptStaleTasks tests
- Add messages mock to client mocks for completeness
- Fix timer-based tests by using real timers (fakeTimers.restore) with wait()
- Increase timeout for tests that need real time delays
2026-02-01 18:33:06 +09:00
justsisyphus
a5b2ae2895 feat(background-agent): add isUnstableAgent flag for unstable model detection 2026-02-01 17:06:39 +09:00
justsisyphus
3e9a0ef9aa fix(background-agent): abort session on task completion to prevent zombie attach processes 2026-02-01 17:05:38 +09:00
YeonGyu-Kim
f146aeff0f
refactor: major codebase cleanup - BDD comments, file splitting, bug fixes (#1350)
* style(tests): normalize BDD comments from '// #given' to '// given'

- Replace 4,668 Python-style BDD comments across 107 test files
- Patterns changed: // #given -> // given, // #when -> // when, // #then -> // then
- Also handles no-space variants: //#given -> // given

* fix(rules-injector): prefer output.metadata.filePath over output.title

- Extract file path resolution to dedicated output-path.ts module
- Prefer metadata.filePath which contains actual file path
- Fall back to output.title only when metadata unavailable
- Fixes issue where rules weren't injected when tool output title was a label

* feat(slashcommand): add optional user_message parameter

- Add user_message optional parameter for command arguments
- Model can now call: command='publish' user_message='patch'
- Improves error messages with clearer format guidance
- Helps LLMs understand correct parameter usage

* feat(hooks): restore compaction-context-injector hook

- Restore hook deleted in cbbc7bd0 for session compaction context
- Injects 7 mandatory sections: User Requests, Final Goal, Work Completed,
  Remaining Tasks, Active Working Context, MUST NOT Do, Agent Verification State
- Re-register in hooks/index.ts and main plugin entry

* refactor(background-agent): split manager.ts into focused modules

- Extract constants.ts for TTL values and internal types (52 lines)
- Extract state.ts for TaskStateManager class (204 lines)
- Extract spawner.ts for task creation logic (244 lines)
- Extract result-handler.ts for completion handling (265 lines)
- Reduce manager.ts from 1377 to 755 lines (45% reduction)
- Maintain backward compatible exports

* refactor(agents): split prometheus-prompt.ts into subdirectory

- Move 1196-line prometheus-prompt.ts to prometheus/ subdirectory
- Organize prompt sections into separate files for maintainability
- Update agents/index.ts exports

* refactor(delegate-task): split tools.ts into focused modules

- Extract categories.ts for category definitions and routing
- Extract executor.ts for task execution logic
- Extract helpers.ts for utility functions
- Extract prompt-builder.ts for prompt construction
- Reduce tools.ts complexity with cleaner separation of concerns

* refactor(builtin-skills): split skills.ts into individual skill files

- Move each skill to dedicated file in skills/ subdirectory
- Create barrel export for backward compatibility
- Improve maintainability with focused skill modules

* chore: update import paths and lockfile

- Update prometheus import path after refactor
- Update bun.lock

* fix(tests): complete BDD comment normalization

- Fix remaining #when/#then patterns missed by initial sed
- Affected: state.test.ts, events.test.ts

---------

Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
2026-02-01 16:47:50 +09:00
Sisyphus
bb181ee572
fix(background-agent): track and cancel completion timers to prevent memory leaks (#1058)
Track setTimeout timers in notifyParentSession using a completionTimers Map.
Clear all timers on shutdown() and when tasks are deleted via session.deleted.
This prevents the BackgroundManager instance from being held in memory by
uncancelled timer callbacks.

Fixes #1043

Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
2026-01-31 16:26:01 +09:00
Nguyen Khac Trung Kien
b03e463bde
fix: prevent zombie processes with proper process lifecycle management (#1306)
* fix: prevent zombie processes with proper process lifecycle management

- Await proc.exited for fire-and-forget spawns in tmux-utils.ts
- Remove competing process.exit() calls from LSP client and skill-mcp-manager
  signal handlers to let background-agent manager coordinate final exit
- Await process exit after kill() in interactive-bash timeout handler
- Await process exit after kill() in LSP client stop() method

These changes ensure spawned processes are properly reaped and prevent
orphan/zombie processes when running with tmux integration.

* fix: address Copilot review comments on process cleanup

- LSP cleanup: use async/sync split with Promise.allSettled for proper subprocess cleanup
- LSP stop(): make idempotent by nulling proc before await to prevent race conditions
- Interactive-bash timeout: use .then()/.catch() pattern instead of async callback to avoid unhandled rejections
- Skill-mcp-manager: use void+catch pattern for fire-and-forget signal handlers

* fix: address remaining Copilot review comments

- interactive-bash: reject timeout immediately, fire-and-forget zombie cleanup
- skill-mcp-manager: update comments to accurately describe signal handling strategy

* fix: address additional Copilot review comments

- LSP stop(): add 5s timeout to prevent indefinite hang on stuck processes
- tmux-utils: log warnings when pane title setting fails (both spawn/replace)
- BackgroundManager: delay process.exit() to next tick via setImmediate to allow other signal handlers to complete cleanup

* fix: address code review findings

- Increase exit delay from setImmediate to 100ms setTimeout to allow async cleanup
- Use asyncCleanup for SIGBREAK on Windows for consistency with SIGINT/SIGTERM
- Add try/catch around stderr read in spawnTmuxPane for consistency with replaceTmuxPane

* fix: address latest Copilot review comments

- LSP stop(): properly clear timeout when proc.exited wins the race
- BackgroundManager: use process.exitCode before delayed exit for cleaner shutdown
- spawnTmuxPane: remove redundant log import, reuse existing one

* fix: address latest Copilot review comments

- LSP stop(): escalate to SIGKILL on timeout, add logging
- tmux spawnTmuxPane/replaceTmuxPane: drain stderr immediately to avoid backpressure

* fix: address latest Copilot review comments

- Add .catch() to asyncCleanup() signal handlers to prevent unhandled rejections
- Await proc.exited after SIGKILL with 1s timeout to confirm termination

* fix: increase exit delay to 6s to accommodate LSP cleanup

LSP cleanup can take up to 5s (timeout) + 1s (SIGKILL wait), so the exit
delay must be at least 6s to ensure child processes are properly reaped.
2026-01-31 16:01:19 +09:00
YeonGyu-Kim
8c2625cfb0
🏆 test: optimize test suite with FakeTimers and race condition fixes (#1284)
* fix: exclude prompt/permission from plan agent config

plan agent should only inherit model settings from prometheus,
not the prompt or permission. This ensures plan agent uses
OpenCode's default behavior while only overriding the model.

* test(todo-continuation-enforcer): use FakeTimers for 15x faster tests

- Add custom FakeTimers implementation (~100 lines)
- Replace all real setTimeout waits with fakeTimers.advanceBy()
- Test time: 104.6s → 7.01s

* test(callback-server): fix race conditions with Promise.all and Bun.fetch

- Use Bun.fetch.bind(Bun) to avoid globalThis.fetch mock interference
- Use Promise.all pattern for concurrent fetch/waitForCallback
- Add Bun.sleep(10) in afterEach for port release

* test(concurrency): replace placeholder assertions with getCount checks

Replace 6 meaningless expect(true).toBe(true) assertions with
actual getCount() verifications for test quality improvement

* refactor(config-handler): simplify planDemoteConfig creation

Remove unnecessary IIFE and destructuring, use direct spread instead

* test(executor): use FakeTimeouts for faster tests

- Add custom FakeTimeouts implementation
- Replace setTimeout waits with fakeTimeouts.advanceBy()
- Test time reduced from ~26s to ~6.8s

* test: fix gemini model mock for artistry unstable mode

* test: fix model list mock payload shape

* test: mock provider models for artistry category

---------

Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
2026-01-30 22:10:52 +09:00
justsisyphus
ad95880198 fix(start-work): restore atlas agent and proper model fallback chain
- Restore agent: 'atlas' in start-work command (removed by PR #1201)
- Fix model-resolver to properly iterate through fallback chain providers
- Remove broken parent model inheritance that bypassed fallback logic
- Add model-suggestion-retry for runtime API failures (cherry-pick 800846c1)

Fixes #1200
2026-01-30 12:52:46 +09:00
YeonGyu-Kim
b4973954e3
fix(background-agent): prevent zombie processes by aborting sessions on shutdown (#1240) (#1243)
- BackgroundManager.shutdown() now aborts all running child sessions via
  client.session.abort() before clearing state, preventing orphaned
  opencode processes when parent exits
- Add onShutdown callback to BackgroundManager constructor, used to
  trigger TmuxSessionManager.cleanup() on process exit signals
- Interactive bash session hook now aborts tracked subagent opencode
  sessions when killing tmux sessions (defense-in-depth)
- Add 4 tests verifying shutdown abort behavior and callback invocation

Closes #1240
2026-01-29 18:29:47 +09:00
justsisyphus
baf6358736 fix(background-agent): pass variant as top-level field in prompt body 2026-01-27 16:49:03 +09:00
justsisyphus
de439edc22 feat(subagent): block question tool at both SDK and hook level
- Add permission: [{ permission: 'question', action: 'deny' }] to session.create()
  in background-agent and delegate-task for SDK-level blocking
- Add subagent-question-blocker hook as backup layer to intercept question tool
  calls in tool.execute.before event
- Ensures subagents cannot ask questions to users and must work autonomously
2026-01-27 13:07:09 +09:00
justsisyphus
26b1c67964 fix(background-agent): disable question tool for background tasks 2026-01-26 18:25:06 +09:00
justsisyphus
68aa913499
refactor(tmux-subagent): state-first architecture with decision engine (#1125)
* refactor(tmux-subagent): add state-first architecture with decision engine

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(tmux): add pane spawn callbacks for background and sync sessions

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

---------

Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-01-26 12:02:37 +09:00
YeonGyu-Kim
aead4aebd2
Add tmux pane management for background agent sessions (#1094)
* feat(config): add TmuxConfigSchema for tmux subagent pane management

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(shared): add tmux module structure

* feat(shared/tmux): implement tmux pane utilities

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(tmux-subagent): add TmuxSessionManager tests (TDD RED)

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(tmux-subagent): implement TmuxSessionManager

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(integration): wire TmuxSessionManager with 500ms delay

- Task 5: Add 500ms delay in BackgroundManager after session creation
- Task 6: Wire TmuxSessionManager event handlers (session.created/deleted)
- Both changes integrate tmux pane management into plugin lifecycle

Co-authored-by: Sisyphus <ultrawork@oh-my-opencode>

---------

Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Co-authored-by: Sisyphus <ultrawork@oh-my-opencode>
2026-01-25 15:34:10 +09:00
justsisyphus
bf3f8e5005 fix(background-agent): prevent premature task completion when agent still running
- Add session.status re-check in stability detection before completing
- Reset stablePolls if session is not idle (agent still working)
- Fix statusText to show CANCELLED instead of COMPLETED for non-completed tasks
2026-01-19 14:58:13 +09:00
justsisyphus
c6fb0c701b fix(types): add null checks for optional sessionID and startedAt fields 2026-01-19 10:35:47 +09:00
justsisyphus
ebaab5aa60 test(background-agent): add non-blocking queue tests 2026-01-19 10:27:50 +09:00
justsisyphus
92942a562f feat(ui): show pending/queued status in toast and background_output 2026-01-19 10:22:34 +09:00
justsisyphus
9710e10aca fix(background-agent): use queuedAt for pending task TTL 2026-01-19 10:19:48 +09:00
justsisyphus
d6723a7d11 feat(background-agent): support cancelling pending tasks 2026-01-19 10:18:10 +09:00
justsisyphus
933c0c99c5 fix(background-agent): track pending tasks in pendingByParent 2026-01-19 10:16:02 +09:00
justsisyphus
54f448583c feat(background-agent): implement per-key queue processor 2026-01-19 10:16:02 +09:00