- Add blocked todo status and optional blocker attribute to todo items.
- Update RPC client and worker serialization logic to support todo blockers.
- Add test coverage for parsing session state with blocked todos.
The finalized-issue boilerplate promises "reopen and I'll triage again from
scratch," but github_events.route() dropped issues.reopened to the ignored
skip branch (only opened/closed handled), while pull_request.reopened was
already routed. A user following the instruction got silence.
Route issues.reopened like issues.opened (submitter-attributable triage_issue,
same per-user rate budget) and dispatch it in queue._dispatch(). triage_issue
now tears down a stale finalized workspace (merged/closed/abandoned) before
re-provisioning, mirroring the maintainer directive-reopen teardown so the
re-triage branches afresh from default instead of a merged/deleted branch.
Fixes#5891
- Add automatic retries for transient 5xx status codes on idempotent request methods.
- Ensure non-idempotent methods like POST fail immediately without retry.
- Aligned the blocked-todo reconciliation test with the debounced
subagent-lifecycle observer on main (fake timers + 100ms advance).
- Carries in-progress robomp queue/sandbox/config scaffolding from the
shared worktree (.env.example, config.py, queue.py, sandbox.py).
Ran deferred-submission promotion on an independent timer in addition to the empty-queue path, so a sustained ordinary queue can no longer starve a rate-limited submitter after their rolling window frees. Added ROBOMP_DEFERRED_PROMOTION_SCAN_SECONDS to tune or disable the sweep.
Fixes#5882
Stored a bounded per-login overflow backlog and promoted deferred events oldest-first as rolling-window capacity became available. Surfaced the deferred state through the dashboard contract and documented admission behavior.
Fixes#5882
- Added `ROBOMP_ISSUE_INDEX_SYNC_SECONDS` configuration and lifecycle-managed issue indexing through startup/shutdown hooks.
- Added issue/PR index tables with FTS5 triggers plus upsert and keyword/filter search helpers for indexed records.
- Added GitHub backend/proxy support for `IssueIndexEntry` and issue-index page retrieval, including webhook ingestion and periodic watermark-driven sync.
- Updated `gh_search_issues` to prefer local index queries when synchronized and added `search_commits` host tool with query modes and validation.
- Added `search_issues` support to the GitHub backend and client, including `state_reason` and `is_pull_request` in issue summaries.
- Added the `gh_search_issues` host tool with repo-prefixed query handling, non-empty/restricted `repo:` validation, default and bounded `limit` values, and inbound issue filtering.
- Added proxy integration for issue search with a new `/gh/v1/search_issues` endpoint and matching proxy-client method/response parsing.
- Updated triage prompts to perform pre-`classify_issue` duplicate and already-fixed checks via search, and added tests for search query formatting, validation, and state-aware match rendering.
- Updated the system prompt to require additional bug-gate checks, including repo-owned-defect and premise-verification before labeling a report as `bug`.
- Added non-bug routing guidance for upstream-caused failures, environment/user errors, duplicate audit batches, and out-of-scope or already-possible scenarios.
- Adjusted host-tool and issue kick-off prompt instructions to call out upstream vs this-repo cause checks and expanded wontfix rationale wording.
- Added `wontfix` to primary classification handling by updating host-tool classification metadata and issue taxonomy prompts.
- Updated kickoff/follow-up/system prompt guidance to treat intentional-design reports as `wontfix`, with maintainer-intent signals stopping work and ending in a single explanatory comment.
- Added tests to verify `classify_issue` persists a `wontfix` classification and returns a no-PR, comment-only next step.
- Added entrypoint setup for `/srv/agent-home/.omp/run` to enforce `omp` group ownership, group-write access, and setgid permissions so any sandbox slot can create or enter daemon state directories.
- Updated worker startup to skip generic home normalization on `.omp/run` and added a root-only run-dir preparation pass that reasserts `omp` ownership and writable, setgid permissions before launching subprocesses.
- Introduced `Max` as a first-class reasoning effort tier across all packages, including AI providers, coding agent configurations, and RPC protocols.
- Refactored model effort ladders to use wire-exact mappings and removed legacy effort aliasing (e.g., `max-to-xhigh` mapping).
- Updated model registry and provider configurations to support `Max` tier routing, color themes, and UI icon associations.
- Expanded test suites to provide end-to-end coverage for the new reasoning tier, including updated compatibility and fallback scenarios.
- Make commit message repair mandatory once broken escapes are detected.
- Implement a failure handler that halts execution and provides manual correction instructions when git operations fail during the rewrite process.
- Ensure that partial states are avoided by refusing the push instead of allowing it with uncorrected messages.
- Updated `_run_pre_publish_bun_fix` to amend `bun run fix` output into HEAD instead of creating standalone `style:` commits.
- Added `_repair_commit_message_escapes` to detect and rewrite commit messages containing shell-literal `\n` sequences into real newlines.
- Enforced safety checks during `bun run fix` to ensure HEAD is mutable and locally authored before amending.
- Improved documentation in prompts and README regarding commit message formatting and formatter workflow changes.
A diff-scoped review of the event-loop-hang fixes surfaced gaps in the new
timeout/error-handling code and its tests. All at/above the medium floor,
each mutation-verified.
- remove_workspace: prune on any nonzero `git worktree remove` (not just a
present checkout) and RAISE on a failed prune, so a killed remove that
leaves a dangling pool registration is cleared or retried instead of
recording success over stale metadata. Gate git ops on the pool being a
real clone (ensure_clone mkdir's the dir before cloning, so a failed first
clone leaves a non-git dir where `git worktree prune` would error), and
only speculatively prune a missing checkout when ws_root still exists.
- _worktree_add: new helper wrapping the three worktree-add sites; on a
failed add (incl. the new 124 timeout) it removes the partial checkout and
prunes the pool before re-raising, so the event retry starts clean. Raises
a failed prune chained from the add error.
- _reset_origin_url: a timed-out (124) `git remote get-url origin` probe is
indeterminate; raise before fetch instead of silently skipping the rewrite,
so a legacy credentialed origin cannot persist and be reused.
- tests: assert the subprocess timeout is passed in the _safe_run/_run
timeout fakes; add a real-`git worktree prune` integration test; make the
cancel-drain test deterministic (loop-turn pump, no wall-clock sleep) and
cover the repeated-cancel branch; add regressions for the prune-failure,
checkout-gone-on-entry, non-git-pool, and repeat-close cleanup paths.
Op: correct
Restores: spec:pool-cleanup-clears-or-retries-dangling-registration
Restores: spec:indeterminate-git-probes-raise-not-silently-proceed
`remove_workspace` guarded its rmtree+prune fallback on `repo_dir.exists()`.
But a `git worktree remove` that is killed (incl. a 124 timeout) mid-operation
can delete the checkout *before* it clears the pool's worktree registration.
In that window `repo_dir` is already gone, so the exists() guard skipped the
prune and left dangling metadata — the next `git worktree add` for the same
path then failed with "missing but already registered worktree".
Guard the fallback on the remove command's return code instead; prune runs on
any nonzero exit regardless of whether the checkout was already deleted. Added
a regression test for the remove-deleted-checkout-then-died case, which the
existing test (checkout survives) never covered.
Op: correct
Restores: spec:failed-worktree-remove-must-prune-dangling-pool-metadata
- log the worker thread's exception when a workspace op raises during
caller cancellation, so a persistently failing setup surfaces instead
of being buried behind CancelledError.
- raise on a timed-out (124) git symbolic-ref probe in the repo-exists
path, matching the rev-parse probes, instead of silently accepting the
caller-supplied branch.
- assert the subprocess timeout is passed in the two _chown_workspace
test fakes so a refactor cannot silently drop the bound.
Op: correct
Restores: spec:indeterminate-git-probes-raise-not-silently-proceed
Workspace setup/teardown (git clone/fetch, worktree add/remove, chown)
ran synchronously on the asyncio dispatcher loop, so one stalled
subprocess froze the entire process.
- Offload every ensure_workspace/remove_workspace call to a worker thread
via a new _run_workspace_op helper that drains the thread to completion
on cancellation, so a cancelled event cannot reap/release a slot the
setup thread still owns.
- Serialize same-repo setup with a per-repo threading.RLock while letting
distinct repos run concurrently.
- Bound the direct git/chown subprocesses with a 120s timeout
(returncode 124); treat a timed-out branch probe as an error rather
than "branch absent" to avoid silently rebasing a follow-up onto the
default branch and losing the PR's commits.
- When a timed-out worktree remove leaves the checkout behind, rmtree it
and run `git worktree prune` so the pool's dangling registration cannot
trip a later worktree add for the same path.
Adds regression tests for event-loop liveness, cancellation-safe offload,
per-repo lock serialization, subprocess timeout mapping, the branch-probe
timeout guard, and worktree-prune after a failed remove.
Op: correct
Restores: spec:dispatcher-event-loop-never-blocks-on-workspace-io
- Added exponential backoff retry mechanisms to `GitHubClient` and `GitHubProxyClient` request methods.
- Included handlers for `httpx.ConnectError` and `httpx.TimeoutException` to improve resilience against transient network failures.
- Constrained git configuration for smart-HTTP requests by explicitly overriding proxy, sslVerify, and credential helpers across all relevant path suffixes.
- Prevented potential credential capture by disabling repo-configured credential helpers that could otherwise execute malicious commands during authentication challenges.
- Hardened git operations against attacker-injected proxies by exhaustively blanking configuration keys for all identifiable git request endpoints.
- Excluded sslCAInfo/sslCAPath from overrides to prevent premature TLS negotiation failure while maintaining security via mandatory proxy neutralization.
- Added `_require_fetch_ref` validator to enforce strict alphanumeric character sets and disallow special git characters (e.g., `:`, `--`, `..`, `*`).
- Integrated validation into `git_fetch_ref_endpoint` to block malicious refspec inputs before git execution.
- Added test cases in `test_proxy_server.py` to verify rejection of attempted shell and refspec injections.
- Added a check to reject remote URLs that begin with a hyphen to prevent command-line option injection.
- Updated the test suite to verify that option-shaped URLs are correctly blocked.
- Extracted `_pat_safe_remote` and rejected HTTP(S) origins with embedded credentials or mismatched host/repo.
- Guarded `clone` via `_assert_clone_url_safe` on the caller-supplied `clone_url` (pool has no `origin` yet).
- Asserted origin safety before `fetch`, `fetch_ref`, and `fetch_pr_head` inject the PAT header.
- Appended POSIX `--` separator in `omp_local` so prompts starting with `-` aren't parsed as flags.
- Added proxy tests covering attacker-origin fetch rejection and unsafe `clone_url` refusal.
Co-authored-by: can1357 <me@can.ac>
- Updated the mention extraction regex to prevent partial matching when a suffix follows the `[bot]` identifier.
- Added a regression test to ensure that invalid extended suffixes are correctly rejected.
- Implement `has_authorized_impl_event` in the database to retrieve historical authorization state.
- Update `_enforce_impl_authorization` to permit actions if prior events on the issue provided implementation authorization.
- Normalize maintainer logins by stripping `[bot]` suffixes and allow match-regex to ignore them.
- Implemented case-insensitive normalization for bot logins to handle mention handles and `[bot]` suffixes consistently.
- Added support for `ROBOMP_MAINTAINER_LOGINS` to allow authorized non-owner users to execute implementations.
- Refined authorization logic to distinguish between personal repository owners and organizational accounts.
- Updated documentation and added comprehensive tests to verify authorization handling across tasks, workers, and directive processing.
- Updated configuration to strip the '@' prefix from bot login names.
- Granted personal repository owners authorization to trigger implementations regardless of their GitHub author association.
- Included authorizes_impl field when attaching threads to directives.
- Added a test case to ensure the author authorization flag is preserved during directive hydration.
- Added `ensure_workspace_dependencies` to automate `bun install` for new worktrees where dependencies are missing.
- Configured the installer to use `--frozen-lockfile` and `--ignore-scripts` to preserve security and lockfile integrity.
- Integrated the bootstrap step into the worker startup process to ensure workspace packages are resolvable.
- Introduced a vouching mechanism to manage PR authorization via a tracked user list and discussion-based management workflows.
- Added automated PR gatekeeping workflows to close contributions from unvouched users and require specific labels for review.
- Refactored PR event handling to support label-based review deferral and enforce authorization checks for labelers.
- Added comprehensive test coverage for vouch-gate logic, including label activation and unauthorized access scenarios.
- Added event retry settings with parsed delay schedules and jittered delay computation.
- Extended event persistence to persist an `available_at` timestamp, honor it during dequeuing, and clear it when re-queuing.
- Updated worker failure handling to queue bounded retries with backoff and transition to failed only when the retry budget is exhausted.
- Updated `RpcClient` to spawn `omp` in a new session, cache its process group, and terminate descendants on stop.
- Fixed `stop()` to signal the cached process group with SIGTERM then SIGKILL so leaked grandchildren are terminated.
- Moved status-query reads in `create_app` to `asyncio.to_thread`, preventing FastAPI event-loop stalls.
- Added regression coverage for stopping a spawned grandchild process in the client tests.
- In _run_rpc_blocking, added a check for an assistant_message stopReason after timeout handling.
- When stopReason is "error", the worker now reads errorMessage (or a default message) and raises a RuntimeError.
system_append.md and system_append_pr_review.md hardcoded the literal
'robomp' as the bot persona, so the agent self-mentioned an account
that does not exist when deployments configure ROBOMP_BOT_LOGIN to a
different login. Affected users saw the agent ask for @robomp mentions
that GitHub never resolved to the actual bot.
Thread the configured login through persona.system_append and
persona.system_append_pr_review as a bot_login keyword, render it
via the existing {{bot_login}} placeholder, and pass
settings.bot_login at the worker callsite. Regression test asserts the
templated login lands in both prompts and the legacy literal is gone.
Fixes#1932
Prevented the durable queue from claiming a queued event while another event with the same issue key is still running, so duplicate worker instances cannot resume the same RpcClient session concurrently.
Added regression coverage for blocked same-issue events and for skipping blocked queue heads without stalling unrelated issues.
Fixes#1840