Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
6429463
chore(release): open dev at 2.76.0 before releasing 2.75.0 (#6351)
github-actions[bot] Oct 1, 2026
0328373
perf(responses): reuse measured entry strings for the state snapshot …
lidge-jun Oct 1, 2026
a6114b6
feat(codex): pick the model for each LazyCodex agent role (carry #626…
lidge-jun Oct 1, 2026
da13a02
feat(codex): auto-assign LazyCodex role models by sizing each role (c…
lidge-jun Oct 1, 2026
de8afe2
feat(subagents): suggest a delegation model by sizing the work (carry…
lidge-jun Oct 1, 2026
6c91540
docs(devlog): close the omo (Codex / LazyCodex) carry unit (#6390)
lidge-jun Oct 1, 2026
b7f106e
fix(claude): log a stalled or over-cap passthrough stream as a 502 in…
sh940701 Oct 1, 2026
7b2deb8
fix(anthropic): clamp budget thinking to the model's real output maxi…
vadymhimself Oct 1, 2026
22c890c
fix(anthropic): enforce model routes for vision and search helpers (#…
luvs01 Oct 1, 2026
7429513
fix(gemini): bound type-array schema normalization and preserve point…
luvs01 Oct 1, 2026
459b4ec
fix(antigravity): enforce one sibling rotation across authentication …
luvs01 Oct 1, 2026
5939b09
fix(kiro): retry rebuilt requests at the rebuilt destination (#6374)
luvs01 Oct 1, 2026
3ed275f
fix(kiro): release leases granted across request cancellation (#6377)
luvs01 Oct 1, 2026
de4b2e2
fix(xai): authorize the Fast wire model across API endpoints (#6373)
luvs01 Oct 1, 2026
6e51011
fix(config): require owner-only no-follow registry publication (#6375)
luvs01 Oct 1, 2026
72e6543
fix(codex): reject unpaired surrogates in discovered model metadata (…
luvs01 Oct 1, 2026
c94fcf5
fix(chat): recognize Eliza qwen3-8-27b checkpoint ids in the leading-…
arikon Oct 1, 2026
faf946e
fix(command-code): preserve canonical path case in project confinemen…
luvs01 Oct 1, 2026
50b3dd4
fix(gui): keep native login confirmation readable and contained (#6388)
pengusto Oct 1, 2026
7f6b5b7
fix(config): surface why macOS proxy "auto" refuses (exception shapes…
JinHanAI Oct 1, 2026
95f21f4
test(codex): match the canonical role path in the role-route write-fa…
lidge-jun Oct 1, 2026
404ca8b
fix(claude): relay native Anthropic rate-limit headers (#6356)
Ingwannu Oct 1, 2026
a207452
fix(responses): record first-output timing for tool-only streams (car…
lidge-jun Oct 1, 2026
a9d5a80
fix(codex): verify service manager identity before census delegation …
lidge-jun Oct 1, 2026
1c92271
feat(zed): experimental Zed Hosted AI provider, use at your own risk …
lidge-jun Oct 1, 2026
6256cb4
fix(kiro): rebind continuation ownership after refusal failover (#6376)
luvs01 Oct 1, 2026
bd3d303
fix(combos): a pool-held 429 must not park the combo target past the …
vadymhimself Oct 1, 2026
5444d34
fix(responses): display hosted image results in local Codex clients (…
lidge-jun Oct 1, 2026
4448e98
fix(spend): name the refused ledger file and condition, warn on synce…
lidge-jun Oct 1, 2026
58a26f0
fix(router): preserve policy authorization across fallback redirects …
lidge-jun Oct 1, 2026
665e2bc
test(config): canonicalize the owner-registry ACL test root (macOS) (…
lidge-jun Oct 1, 2026
fcbfb16
feat(chatgpt): experimental macOS app-server quota-gate shim (split f…
lidge-jun Oct 1, 2026
0202cc6
fix(codex): exclude macOS Electron helpers from client diagnostics (c…
lidge-jun Oct 1, 2026
09cd45d
fix(update): check and pin the npm cache root before staging (#6288) …
lidge-jun Oct 1, 2026
8a3a776
fix(service): tolerate locale dates in Windows service wrappers (carr…
lidge-jun Oct 1, 2026
58726ae
feat(transport): carry opt-in Antigravity TLS profile onto provider e…
lidge-jun Oct 1, 2026
06cc381
feat(combos): JEV decision methods — TypeSafe, System One server, or …
lidge-jun Oct 1, 2026
ff1ce7e
fix(chatgpt): close the #6361 review follow-ups (#6412)
lidge-jun Oct 1, 2026
5ea6375
fix(chatgpt): build the bundled app-server path with posix.join on ev…
lidge-jun Oct 1, 2026
328ce95
fix(spend): classify synced state paths with POSIX rules on every hos…
lidge-jun Oct 1, 2026
f86ad0a
feat(codex): window-aware main-account hard-lock thresholds and outsi…
lidge-jun Oct 1, 2026
89db85f
fix(service): bound every Windows manager command the guarded stop de…
devin-ai-integration[bot] Oct 1, 2026
137164e
Extend Windows takeover startup budget (#6400)
devin-ai-integration[bot] Oct 1, 2026
17d6e84
fix(update): release the Bun updater lease around service-manager sta…
devin-ai-integration[bot] Oct 1, 2026
584b525
feat(claude): list opencodex models in the Claude Code CLI first-part…
lidge-jun Oct 2, 2026
cfde167
fix(service): scope Windows scheduler probes to the root task and re-…
devin-ai-integration[bot] Oct 2, 2026
0f2ec7a
fix(update): release the restart lease before the service refresh (#5…
devin-ai-integration[bot] Oct 2, 2026
6d84e44
fix(cli): stabilize guarded-stop re-verification and report the faili…
devin-ai-integration[bot] Oct 2, 2026
8b23fe3
fix(claude): rebuild a CLI picker snapshot whose rows no longer decod…
lidge-jun Oct 2, 2026
3d77e3d
fix(claude): start the intercept pair on demand instead of asking for…
lidge-jun Oct 2, 2026
03ed9a3
feat(gui): top-level Claude page with Account, Code, Desktop and Sett…
lidge-jun Oct 2, 2026
933bd03
fix(gui): conditions-based Claude account-pool and OAuth warning copy…
lidge-jun Oct 2, 2026
0f6026d
fix(anthropic): bind native Claude metadata and client identity to th…
lidge-jun Oct 2, 2026
af35814
fix(cli): succeed ensure for validated connected clients (#6427)
Ingwannu Oct 2, 2026
a300b57
fix(anthropic): classify 429s and admit by per-model weekly quota in …
lidge-jun Oct 2, 2026
4707580
fix(streaming): decode CR, LF and CRLF server-sent events across chun…
lidge-jun Oct 2, 2026
fc0f24a
fix(cli): carry oocheol's CLI validation and diagnostics fixes (#6429…
lidge-jun Oct 2, 2026
10428d0
feat(codex): switch accounts at 100% by default and make spending Cha…
lidge-jun Oct 2, 2026
21aed9f
fix(service): wait out the npm Bun placeholder instead of executing i…
LilMGenius Oct 2, 2026
e0af52c
feat(providers): add OpenGateway (Sionic AI) preset with live discove…
lidge-jun Oct 2, 2026
6af28b5
Merge preview into 2.76.0-preview.20261003 promotion
lidge-jun Oct 2, 2026
e3a7212
chore(release): 2.76.0-preview.20261003
lidge-jun Oct 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,17 @@ network failures, or invalid decisions fail open to the first currently eligible
cancellation still cancels the request. Automated tests use a mocked TypeSafe endpoint and do not
validate a live JEV account.

A JEV Combo can instead ask a self-hosted decision model, such as Ollama's keyless `tev1`: add a
`jev-decision` provider whose `baseUrl` is the full `/v1/systemone` endpoint and set the Combo's
`decisionProvider` to it. TypeSafe credentials are never sent there. Details:
[System One-compatible server](https://opencodex.me/guides/combos/#system-one-compatible-server).

## Providers & adapters

<!-- sponsors:main-first-mention -->
OpenAI (ChatGPT login or API key), Anthropic, Google Gemini, xAI, Kimi, Azure OpenAI, Ollama
(local + Cloud), Cursor (experimental), and every OpenAI-compatible endpoint — plus DeepSeek,
Groq, OpenRouter, Together, Fireworks, Cerebras, Mistral, Hugging Face, NVIDIA NIM, MiniMax,
Groq, OpenRouter, OpenGateway, Together, Fireworks, Cerebras, Mistral, Hugging Face, NVIDIA NIM, MiniMax,
Qwen Cloud, Qoder Global and CN (official PAT + CLI), SiliconFlow, and more. Full list: `ocx init` or the
[provider docs](https://opencodex.me/guides/providers/).

Expand Down
13 changes: 12 additions & 1 deletion bin/ocx.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { checkRegistryPackageIntegrity } from "../src/update/registry-integrity.
import { hasPendingTeardownIn } from "../src/config/pending-teardown-names.mjs";
import {
npmCachePreflightFailureMessage,
resolveNpmCachePath,
runNpmCachePreflight,
} from "../src/update/npm-cache-preflight.mjs";
import { handoffWindowsTrayForUpdate, planWindowsTrayUpdate } from "../src/update/tray-update-plan.mjs";
Expand Down Expand Up @@ -271,12 +272,21 @@ function runPackageManagerSelfUpdate(manager) {
console.log(`Verified ${PKG}@${latest} integrity metadata ${integrity.integrity.slice(0, 24)}…`);
}

// The cache root is resolved once, with the environment staging uses, then checked and pinned:
// the stage installs with exactly the root this pre-flight inspected (#6288).
let npmCachePath;
if (manager === "npm") {
const cachePreflight = runNpmCachePreflight();
const npmCache = resolveNpmCachePath({ env: unprivilegedOwnershipMutationEnvironment(process.env) });
// Windows skipped this gate before #6288: an unresolvable npm cache path keeps that behavior
// there (no check, no pin) and only a confirmed broken root aborts the update.
const cachePreflight = npmCache.ok
? runNpmCachePreflight({ cachePath: npmCache.path })
: process.platform === "win32" ? { ok: true, reason: "windows_skip" } : npmCache;
if (!cachePreflight.ok) {
console.error(`opencodex: ${npmCachePreflightFailureMessage(cachePreflight.reason)}. Aborting before stopping the proxy.`);
process.exit(1);
}
npmCachePath = npmCache.path;
}

// Remember whether a background service manages the proxy BEFORE stopping — `ocx stop`
Expand Down Expand Up @@ -737,6 +747,7 @@ function runPackageManagerSelfUpdate(manager) {
pkgName: PKG,
targetVersion: latest || undefined,
tag,
cachePath: npmCachePath,
runNpm: (args) => {
const invocation = npmInvocation(args);
if (!invocation) return { status: 1 };
Expand Down
2 changes: 1 addition & 1 deletion desktop/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "opencodex-desktop"
version = "2.75.0-preview.20261001"
version = "2.76.0-preview.20261003"
description = "OpenCodex desktop shell"
authors = ["OpenCodex contributors"]
license = "MIT"
Expand Down
3 changes: 3 additions & 0 deletions desktop/src-tauri/src/provider_icons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const ALIASES: &[(&str, &str)] = &[
("opencode-go", "opencode.svg"),
("opencode-zen", "opencode.svg"),
("openrouter", "openrouter-color.svg"),
("opengateway", "opengateway.svg"),
("opper", "opper.svg"),
("qianfan", "qianfan-color.svg"),
("qoder", "qoder.svg"),
Expand Down Expand Up @@ -128,6 +129,7 @@ fn paint(file: &str) -> &'static str {
| "novita.svg"
| "ollama-color.svg"
| "opencode.svg"
| "opengateway.svg"
| "opper.svg"
| "packycode.svg"
| "siliconflow.svg"
Expand Down Expand Up @@ -189,6 +191,7 @@ fn svg(file: &str) -> Option<&'static str> {
"openai.svg" => svg!("openai.svg"),
"opencode.svg" => svg!("opencode.svg"),
"openrouter-color.svg" => svg!("openrouter-color.svg"),
"opengateway.svg" => svg!("opengateway.svg"),
"opper.svg" => svg!("opper.svg"),
"orcarouter.svg" => svg!("orcarouter.svg"),
"packycode.svg" => svg!("packycode.svg"),
Expand Down
33 changes: 30 additions & 3 deletions desktop/src-tauri/src/startup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,10 +526,14 @@ impl Startup {
/// Consume the decision and publish the extended ceiling in the same critical section, so
/// the guard's next expiry check sees either a pending/answered prompt or the new deadline,
/// never the gap between them.
fn resolve_consent(&self, deadline: Instant) {
fn resolve_consent(&self, mut deadline: Instant, approved: bool) -> Instant {
if approved && cfg!(target_os = "windows") {
deadline += Duration::from_secs(60);
}
let mut live = self.live();
live.deadline = deadline;
live.consent = ConsentState::Idle;
deadline
}

fn set_deadline(&self, deadline: Instant) {
Expand Down Expand Up @@ -933,7 +937,7 @@ async fn run(app: &AppHandle, started: Instant) {
deadline += asked.elapsed();
// The extension and the clear are one critical section: the guard sees
// either a prompt still pending or the moved ceiling, never the gap.
startup.resolve_consent(deadline);
deadline = startup.resolve_consent(deadline, approved);
if !approved {
attach_as_guest(
app,
Expand Down Expand Up @@ -2482,13 +2486,36 @@ mod tests {
Expiry::Blocked
));
// Once the run publishes the moved ceiling the guard waits on it instead of firing.
startup.resolve_consent(tokio::time::Instant::now() + Duration::from_secs(60));
startup.resolve_consent(tokio::time::Instant::now() + Duration::from_secs(60), false);
assert!(matches!(
startup.expire_run(tokio::time::Instant::now(), 1, "expired".to_owned()),
Expiry::Waiting(_)
));
}

#[test]
fn approved_windows_takeover_has_one_bounded_extended_deadline() {
let startup = Startup::new();
startup.generation.store(1, Ordering::SeqCst);
let deadline = Instant::now() - Duration::from_secs(5);
assert_eq!(startup.resolve_consent(deadline, false), deadline);
let extended = startup.resolve_consent(deadline, true);
if cfg!(target_os = "windows") {
assert_eq!(extended - deadline, Duration::from_secs(60));
assert!(matches!(
startup.expire_run(deadline - DEADLINE, 1, "expired".to_owned()),
Expiry::Waiting(_)
));
} else {
assert_eq!(extended, deadline);
}
startup.resolve_consent(Instant::now() - Duration::from_secs(95), true);
assert!(matches!(
startup.expire_run(deadline - DEADLINE, 1, "expired".to_owned()),
Expiry::Fired(_)
));
}

#[test]
fn a_terminal_run_posts_no_prompt() {
// The other half of the race: the failure already landed, so the ask path must not
Expand Down
2 changes: 1 addition & 1 deletion desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "OpenCodex",
"version": "2.75.0-preview.20261001",
"version": "2.76.0-preview.20261003",
"identifier": "com.opencodex.desktop",
"build": {
"frontendDist": "../ui",
Expand Down
62 changes: 62 additions & 0 deletions devlog/_fin/261001_omo_lazycodex_carry/000_plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# 261001 omo (Codex / LazyCodex) carry series

LilMGenius opened three stacked PRs that let opencodex manage the model of each Codex agent role installed by LazyCodex (#6262), size roles and auto-assign models (#6269), and suggest a delegation model on the Subagents page (#6274). They could not land as fork PRs: the readiness gate needs the author's local-validation attestation, fork CI never ran its test shards, and `hygiene` flagged an unsponsored management-API surface. This unit lands the same work as three maintainer carry PRs in dependency order, each crediting the author, each merged only after its exact head passes hosted CI.

## Loop spec

- **Loop archetype:** satisfy-spec (verifier defines done: exact-head required CI green, then squash merge).
- **Trigger:** maintainer request (2026-10-01) to research omo and merge LilMGenius's work via cxc-loop.
- **Goal:** #6262, #6269 and #6274 content on `dev`, originals closed with credit.
- **Non-goals:** no behavior changes beyond the contributor heads; no Pi omo or OpenCode omo changes; no #6348 or other JEV work; no release or promotion. **No local test suites or typecheck** (maintainer instruction); hosted CI is the only execution evidence.
- **Verifier:** `gh pr checks <carry PR> --required` on the exact head SHA (reads every required job of that head, including test shards, typecheck, structure, privacy, file-size ratchet, hygiene, enforce-target). Local: `git diff --check` and `git merge-tree --write-tree origin/dev HEAD` (textual union only).
- **Stop condition:** all three carries merged and originals closed, or a blocker that needs maintainer direction.
- **Memory artifact:** this unit (000–030 docs) and the session goalplan `lilmgenius-omo-codex-lazycodex-role-model-series`.
- **Expected terminal outcomes:** DONE (three merges); BLOCKED (CI failure needing design change, union conflict that changes behavior); NEEDS_HUMAN (security-review objection).
- **Escalation condition:** a required job fails for a reason that is not a mechanical carry fix; a behavior decision beyond the contributor heads; a security-review objection. Shared gate 4 compatibility repairs (including a byte-for-byte ratchet move) are pre-authorized and do not escalate.
- **Resource bounds:** none set by the user beyond the host goal.

## Research

- **omo variants** (maintainer review 2026-09-30 01:47 on #6262): Pi omo (senpi, `~/.omo/agent`, existing omo tab), OpenCode omo (oh-my-opencode, untouched), Codex omo (LazyCodex). The series is now scoped to LazyCodex; Pi omo has no diff against `dev`.
- **LazyCodex detection verified against LazyCodex source** (`~/developer/codex/161_lazycodex`): the installer writes `lazycodex-install.json` into the plugin root (`plugins/omo/scripts/install-flow.mjs:4` `INSTALL_SNAPSHOT_FILE`, `plugins/omo/dist/cli/index.js:99259`); the plugin is installed with `codex plugin add omo@sisyphuslabs` (README). `src/clients/lazycodex.ts` requires `plugins."omo@sisyphuslabs".enabled = true` and a receipt under `plugins/cache/sisyphuslabs/omo/<ver>/`, matching the Codex plugin cache layout.
- **Open review threads** re-checked at heads 6262 `ada7ec14b1`, 6269 `6c97ca9a4f`, 6274 `b180fcec0a` (architect D2–D4): unreadable `omo.jsonc` (handled by `readOmoRoleModels` → `unreadable`), escaped quoted keys (decoded, undecodable refused), multiline closing quotes (scanner consumes them), mirror retry (`retryMirror`), DelegationSuggest live region (mounted polite region). All fixed with regressions; threads are resolved on landing with a pointer.
- **Topology:** strictly stacked 6262 ⊂ 6269 ⊂ 6274, merge-base `961a4b569` (26 behind `dev` at `0328373fb8`); `git merge-tree` of 6274 vs `dev` is clean. Layer sizes: L1 18 commits / 39 files, L2 19 / 43, L3 12 / 38. All 49 commits authored by `LilMGenius <smsmeee@naver.com>`.
- **Ratchet:** no touched file is in `tests/fixtures/file-size-baseline.json` caps; i18n catalogs are exempt. Uncapped files fail at 2,000 lines; `src/server/management/agent-settings-routes.ts` reaches 1,941 at 6274 (watch in wp3).

## Work-phase map (dependency order)

| WP | Doc | Content | Depends |
|---|---|---|---|
| wp0 | this unit | docs-only roadmap | — |
| wp1 | 010 | carry `961a4b569..6262`, PR, CI, merge | wp0 |
| wp2 | 020 | carry `6262..6269` onto merged dev, PR, CI, merge | wp1 |
| wp3 | 030 | carry `6269..6274` onto merged dev, PR, CI, merge, close originals | wp2 |

## Decisions (architect Godel `01a0f664-d0ea-7000-894a-50e8a319b548`)

- D1 sequential layer cherry-pick onto landed dev — **accepted**: each PR diff is its own layer; author identity stays on every commit; squash body adds `Co-authored-by: LilMGenius <smsmeee@naver.com>`.
- D2/D3/D4 findings already fixed — **accepted**; no extra code; resolve threads with pointers on landing.
- D5 union gates (ratchet 2,000-line ceiling, test-layout maps, i18n parity, structure ownership, route registry) — **accepted**; enforced by hosted CI, watched by hand at carry time.
- D6 preserve recent dev changes in shared files — **accepted**; conflicts resolved by keeping both sides, never wholesale contributor tree.
- D7 merge-dev-into-contributor-head alternative — **rejected**: post-squash parent overlap makes later layers re-carry earlier commits.
- D8 #6274 scope is general Codex delegation, not LazyCodex-only — **accepted as intended**: the author states it configures Codex delegation defaults; the maintainer asked to merge the whole series.
- Reflection: see 001_reflection.md.

## Security review note

## Gates shared by every carry (r2, after architect reflection)

1. **Pinned inputs.** Replay immutable full-SHA ranges only: wp1 `961a4b569512bd568106c4ea67a21a346e002779..ada7ec14b1b089f461e43e208d54750591fd26f9`, wp2 `ada7ec14b1b089f461e43e208d54750591fd26f9..6c97ca9a4fdec6c59901fa115be341d9cc590a15`, wp3 `6c97ca9a4fdec6c59901fa115be341d9cc590a15..b180fcec0a4c3ff63b9f230acc79e5f029bb6cea`. Before replay assert `git rev-parse refs/omo/<n>` still equals the upper SHA; a moved contributor head stops the carry for re-plan.
2. **Fresh base.** `git fetch origin dev` immediately before branching; wp2/wp3 assert `git merge-base --is-ancestor <previous squash SHA> origin/dev`.
3. **Conflict reconciliation.** Keep both sides semantically: one entry per key in i18n catalogs, layout maps and route registry; no duplicated registrations; never take the contributor file wholesale.
4. **Compatibility repairs are allowed** when hosted CI fails for a mechanical union reason (test-layout registration, ratchet 2,000-line ceiling via a byte-for-byte move into a sibling module, i18n key parity, structure ownership). Such a repair is a separate commit named "fix(carry): …", listed in the PR body, and does not change behavior. Anything else escalates.
5. **CI receipt.** Record in the PR body/comment and in this unit: head SHA, base SHA, `gh pr checks <n> --required` output with every required job `pass`, and a coverage assertion that the expected jobs actually ran and succeeded at that head — every `test` shard, `typecheck`, structure, privacy scan, file-size ratchet, `hygiene`, `enforce-target`, and GUI lint/tests when `gui/` changed; a job that is absent, skipped or cancelled fails this gate. Also record the CI run id and attempt for the `pull_request` event at that head. Immediately before merge, re-read the head SHA and required checks; merge with `gh pr merge <n> --squash --match-head-commit <sha>`.
6. **Publication.** PR template fully filled; GUI screenshots linked from the contributor's existing pr-assets (no image committed to the branch); squash body ends with `Co-authored-by: LilMGenius <smsmeee@naver.com>`; maintainer-integration record (MAINTAINERS.md "maintainer integration": actor lidge-jun admin, exact-head CI evidence) posted as a PR comment.
7. **Security review.** Before merge, an independent read-only security reviewer (fresh subagent, not the architect) reviews the exact carry head for its surfaces — management-API route admission and sibling guard, file writes under `$CODEX_HOME/agents` and `~/.omo/omo.jsonc` (path validation, atomicity, no secret logging), and the loopback self chat-completion (admission header, response bounds). Its verdict (PASS / FINDINGS) is bound to the head SHA and recorded in the PR comment and in this unit. FINDINGS block merge until fixed or explicitly dispositioned; an unresolved objection is NEEDS_HUMAN. Owner authorization (2026-10-01) covers the merge decision, not the review.
8. **D8 evidence.** #6274 author comment 2026-09-30T07:35: "Delegation suggest configures Codex delegation defaults, so it stays unscoped from the omo variants"; the maintainer's 2026-10-01 instruction covers the whole series.
9. **Maintainer-objection gate.** The originals carry two `CHANGES_REQUESTED` reviews by lidge-jun (2026-09-30 01:44 stack split, withdrawn by the 01:47 review; 01:47 omo-variant scoping). The author addressed the variant scoping in `e9ea34661`, `7c81640d0`, `b91537a75`, `d7a4f91a7` (#6262) and the matching #6269/#6274 commits. When each carry PR opens, dismiss both reviews on its original with a message citing those commits and the carry PR; immediately before each merge run `scripts/ci/assert-mergeable-review.sh --maintainer-integration <carry PR>` and require exit 0. Any other maintainer objection is NEEDS_HUMAN.
10. **Base binding.** `pull_request` CI tests the merge of head and base at trigger time. Immediately before merge: `git fetch origin dev`; if `origin/dev` moved past the base recorded in the CI receipt, merge `origin/dev` into the carry branch (no force push), push, and repeat gates 5, 7 and 9 on the new head; for gate 7 the security reviewer inspects the incoming dev delta and re-attests the new head (a short "no security impact" verdict bound to that SHA suffices). Merge only when the receipt base equals current `origin/dev`.

## Security review note (surfaces)

Surfaces: management API routes (`/api/codex-agent-roles`, auto-assign, `/api/injection-model/suggest`), file writes under `$CODEX_HOME/agents` and `~/.omo/omo.jsonc`, and a loopback self chat-completion (`src/lib/local-chat-completion.ts`). No credential storage or OAuth change. Sibling instances refuse writes. Each carry PR states this and requests the MAINTAINERS.md security review explicitly.
Loading
Loading