- 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 test suite to verify git configuration overrides for auth tokens.
- Validated that repo-local git configurations cannot override security-critical settings such as proxy, sslVerify, and credential helpers.
- Confirmed that smart-HTTP path-specific overrides are correctly applied to prevent proxy-based MITM attacks.
- Ensured system CA locations remain untouched to prevent disruption of TLS verification.
- 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.
- Normalized agent `setSystemPrompt` to wrap string inputs into one-item arrays.
- Updated session creation to accept string `systemPrompt` values and normalize callback or direct results to string arrays.
- Adjusted extension result handling and test fixtures to accept string `systemPrompt` and missing `assistant_message` fields without crashing.
- Wrapped queue shutdown and cancel test assertions in `try`/`finally` blocks.
- Cancelled and awaited worker and in-flight tasks in finalizers to prevent lingering background tasks.
- Handled expected `CancelledError` exceptions during task cleanup with `suppress`.
- 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.
- Added a new @oh-my-pi/snapcompact package and redirected compaction call sites to it.
- Added provider-aware snapcompact shape resolution for model-specific mixed-frame behavior.
- Added optional image detail support by extending ImageContent and passing hints through OpenAI providers.
- Added native snapcompact render options, including 5x8/8x8 font loading and palette/geometry controls.
- 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
`SandboxManager.ensure_workspace` calls `fetch_base_ref` (then
`worktree add origin/<ref>`) and `fetch_pr_head` (then
`worktree add --detach FETCH_HEAD`). Both used to issue a plain
`git fetch origin <ref>`. On a `--filter=blob:none` pool the fetch
inherits `remote.origin.partialclonefilter` from the pool config and
brings the commit + tree but no blobs. The next `worktree add` runs
in a non-token subprocess, hits a missing blob, and tries a lazy
promisor fetch — which under `ProxyGitTransport` deployments has no
PAT in the orchestrator container and dies with
fatal: could not read Username for 'https://github.com'
fatal: could not fetch <sha> from promisor remote
`git_ops.fetch_ref` and `fetch_pr_head` now pass `--refetch
--no-filter` so the fetch (which already runs through the token-bearing
transport) eagerly materializes every blob reachable from the requested
ref. `--refetch` is required: without it git short-circuits on "we
already have this commit" and the lazy-fetch path stays primed.
`fetch_prune` (the periodic pool refresh) is untouched, so the
partial-clone disk savings are preserved on the steady-state path.
`remote.origin.partialclonefilter` is left intact in the pool config.
Fixes#1818
- Added `is_implementation_authorizer` check requiring OWNER or allowlisted maintainer to authorize implementation work.
- Blocked `gh_push_branch` and `gh_open_pr` for unclassified/enhancement/proposal issues without explicit directive authorization.
- Auto-allowed bug and documentation issues without requiring a directive.
- Propagated `authorizes_impl` flag through events, server, tasks, and worker bindings.
- Added `review_pr` task that checks out PR head in a detached worktree, classifies rank/type/area, and posts a batched GitHub review as `event=COMMENT`.
- Added four new host tools: `fetch_pr`, `classify_pr`, `pr_review_comment`, and `submit_pr_review`; review tools self-gate on `review_mode`, push/open-PR tools refuse when `review_mode` is set.
- Added sqlite staging table `pr_review_comments` with `stage_review_comment`, `list_staged_review_comments`, and `clear_staged_review_comments` DAOs.
- Routed `pull_request.opened/reopened/ready_for_review` to `review_pr` and extended `pull_request.closed` cleanup to any tracked PR regardless of author.
- Upgraded workspace catalog dependencies to newer versions in both package manifests.
- Regenerated bun.lock to align transitive versions, including Vite and ecosystem tooling updates.
- Updated ACP startup tests and transport handling to fail fast on unsupported server transport types.
Fire Pass support:
- New provider with login command 'omp /login firepass'
- Hand-seeded kimi-k2.6-turbo model with Fire Pass router wire id
- pi-ai CLI --help lists firepass
AI provider fixes surfaced during the Fire Pass review:
- service_tier whitelist restored for openai/openai-codex only (was leaking to
Fireworks, Firepass, OpenRouter, Azure OpenAI Responses)
- Anthropic tool schema normalizer collapses {} -> true for additionalProperties
- anthropic.prepareParams fires onPayload after drop helpers so callers see the
real wire body
- isServiceTier type guard narrowed to ResolvedServiceTier
- transformMessages stops dropping orphan tool_result when all pending tool
calls have already resolved
- zodToWireSchema preserves null for non-scalar nullable() inner schemas
- isEmptyObject / isJsonObjectEmpty use Object.keys().length === 0 instead of
prototype-walking for...in
- Telemetry records resolved service_tier (priority) instead of scoped
placeholder (openai-only/claude-only)
- Robomp dirty-state reminder no longer asserts a formatter-failure premise