OMO 5.0.0-beta.16 — Formula-Sized init-deep, One ULW Keyword Table, and a Steadier Senpi 2026.8.22
The center of gravity: init-deep stops flooding your main session and runs as a formula-sized DAG map-reduce, every ULW keyword now routes through one exception-free skill-pointer table so composite invocations load everything they name, and the bundled Senpi 2026.8.22 engine stops Cursor streams from dying under heartbeats, keeps shutdown from throwing on pending permission prompts, and lets Ruby and Julia kernels boot under load without timing out.
🗺️ init-deep becomes a formula-sized DAG map-reduce (#7123)
Large repos no longer blow the orchestrator's context exactly when hierarchical AGENTS.md coverage matters most. The old flow collected every explore result into the main session; the new one replaces discovery and generation with a DAG map-reduce whose shape is computed by one formula in an eval cell, not vibes:
- Quick scanner nodes extract per-chunk facts into bounded file reports. Chunks are 400 KB of source, roughly 100k tokens against a ~150k usable quick window, so
N_quick = ceil(S / CHUNK), bin-packed by directory. - Unspecified-high writer nodes own disjoint subtrees and write the
AGENTS.mdfiles from about 12 reports each:N_high = ceil(N_quick / 12). - A root writer consumes only per-subtree digests, and a verify node gates every produced file before the run can claim success.
- The always-reduce rule makes context protection structural rather than aspirational: the main session reads only the verify verdict, never chunk reports or raw node output.
Small repos (N_quick < 4) keep an inline path, and repos that would exceed task.dag.max_nodes_per_run chain one run per top-level directory instead of overflowing. The scoring matrix, templates, file-writing rule, and the Phase 5 snapshot/mode contract that the init-deep-advisor reads are all preserved unchanged. The rewrite even nets out 512 characters smaller.
🎯 Composite ULW invocations load every skill they name (#7120)
"mass ulw loop" used to arm ultrawork and point at mass-ulw, then quietly drop the ulw-loop skill the phrase names. "mass ulw research" had the same gap. A new component detects ulw loop / ulw-loop / ulwloop and the research equivalents in any case and injects one hidden skill pointer per matched skill, so a composite invocation loads ultrawork, mass-ulw, and the named skill together in a single turn.
Suppressions mirror mass-ulw per skill: extension-source inputs, a raw /skill: command for the same skill, and an already-expanded skill block never inject. Queued prompts carry the pointers appended inside the one message, so the group survives senpi's one-at-a-time queue drain intact. A new e2e (ulw-skill-pointers-e2e.mjs) drives the built plugin through a sandboxed live senpi run per prompt and asserts each pointer rides as a hidden custom_message in the session JSONL, that plain "mass ulw" stays pointer-free, and that the real agent dir is untouched.
🧮 One exception-free ULW keyword table (#7122)
The mass-ulw and ulw-skill-pointers components were the same mechanism written twice, and their ulw(?!-) lookaheads silently swallowed overlapping mentions: "mass ulw-loop" fired neither mass-ulw nor ultrawork. Both are now replaced by a single skill-pointers component holding one uniform target table (mass-ulw with its aliases, ulw-plan, ulw-loop, ulw-research) with no cross-keyword exceptions. Overlapping keywords all fire, and each matched skill gets its own hidden pointer. The ultrawork trigger likewise drops the (?!-) guard, so any ulw mention arms it.
What changes at your keyboard:
- Typing "mass ulw-loop" now loads ultrawork + mass-ulw + ulw-loop together instead of nothing.
- "ulw plan" loads ultrawork + ulw-plan, via the new
omo-ulw-plan:skill-pointercustom type. - Existing custom types (
omo-mass-ulw:skill-pointer,omo-ulw-loop/-research:skill-pointer) stay stable. - Flag consolidation:
omo-senpi-mass-ulw-disabledandomo-senpi-ulw-skill-pointers-disabledare replaced by a singleomo-senpi-skill-pointers-disabled. Move your flag if you had one set.
Only structural dedup remains: extension-source inputs, raw /skill: commands for the same skill, expanded skill blocks, and the <ultrawork-mode> tag-pair guard. The e2e was rebuilt as skill-pointers-e2e.mjs, proving the overlap case ("mass ulw-loop" carries the directive plus both pointers), the new plan pointer, and that plain "mass ulw" stays loop- and research-free; mass-ulw-prompts-e2e.mjs is unchanged and still passes.
📐 mass-ULW planning sizes waves by work grain (#7121)
The old "target 5-8 nodes per wave" cap is gone. Wave sizing is now grain-based: one node per genuinely independent chunk, with coverage-beats-cost scoped to quick map and research waves, and an explicit fan-in contract for waves wider than about 10 nodes, where aggregator and verification nodes read bounded per-node file reports instead of raw output. The capacity numbers are reframed as config defaults (task.dag.max_nodes_per_run / max_runs_per_session) with queue-time framing rather than "hard caps / slot budget" wording. Mass harvests get a sharding rule of their own: nodes aren't units of work, so N_nodes = ceil(total_items / items_per_node), with roughly 50 to 200 items per quick node bounded by the <=5k-token report contract, and chained runs plus per-run aggregators once one run's cap is exceeded.
📚 Docs stamped against dev HEAD
A sweep refreshed stale claims across the AGENTS.md files: the root stamp moved to 2026-08-22, the tools (15 dirs) and features (25 modules) counts were corrected, the CI Bun pin now reads 1.4.0 with the lagging devcontainer 1.3.12 pin called out, the Windows CI sharding claim matches the workflow table (2 shards), and the omo-senpi component list was corrected from fifteen to the eighteen actually registered (native-badge, onboarding, and init-deep-advisor were missing), with agent-home noted as a non-component resolver.
⚙️ Bundled Senpi 2026.8.22 — the engine wave
The host pin moves to 2026.8.22. What you feel:
- Cursor streams survive heartbeats and checkpoints. The provider now matches the official Cursor CLI's stream recovery: its 30s health deadline is refreshed on every inbound frame, and pre-
turnEndedstalls or transport deaths are silently retried with bounded backoff, resuming from the latest conversation checkpoint with the originally pinned model. Long-running local tools and longxhighthinking turns previously died withCursor stream ended before turnEnded: inbound stream stalledand immediately rotated the fallback chain. - Clean shutdown with prompts pending. The
permission-systembuiltin extension no longer turns a rejection duringsession_shutdowninto an unhandled promise rejection /uncaughtExceptionwhen permission prompts are still pending. - Ruby and Julia kernels boot safely under load. Eval cells now wait for the subprocess
readysignal before execution timeouts arm, so interpreter startup under load can no longer time out a state-setting cell and silently restart the kernel before the next cell runs.
Full engine changelog: senpi v2026.8.22.
🧹 Roundup
- Dependency pins: the omo package now depends on senpi 2026.8.22, and
bun-typesmoved 1.3.14 to 1.4.0 in the Codex plugin shared manifest, finishing the Bun 1.4 graduation started in beta.13. - Bundle freshness: the committed omo-senpi extension bundles were regenerated on Linux after each ULW component change, so the CI freshness gate and your installed extension agree byte-for-byte.
Install / upgrade:
bun i -g oh-my-opencode@beta
bun i -g oh-my-openagent@beta
bun i -g lazycodex-ai@beta
npm i -g omo-ai@beta