omnilane 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,368 @@
1
+ <div align="center">
2
+
3
+ # omnilane
4
+
5
+ ### One routing table, every harness.
6
+
7
+ *Your main loop stops guessing which model to use.*<br/>
8
+ Every subtask goes to the model that is actually best at it — across<br/>
9
+ **Claude Code · Codex · Grok Build · Antigravity**, on the subscriptions you already pay for.
10
+
11
+ <img src="docs/hero.png" alt="omnilane routes each subtask to the best model across Claude Code, Codex, Grok and Antigravity" width="820"/>
12
+
13
+ [![ci](https://github.com/Seraphim0916/omnilane/actions/workflows/ci.yml/badge.svg)](https://github.com/Seraphim0916/omnilane/actions/workflows/ci.yml)
14
+ [![license](https://img.shields.io/github/license/Seraphim0916/omnilane)](LICENSE)
15
+ [![version](https://img.shields.io/github/v/tag/Seraphim0916/omnilane?label=version)](https://github.com/Seraphim0916/omnilane/tags)
16
+
17
+ **English** · [繁體中文](README.zh-TW.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) · [한국어](README.ko.md)
18
+
19
+ </div>
20
+
21
+ ---
22
+
23
+ ## What's new in v0.7.0
24
+
25
+ - **Preview any dispatch first** — `--dry-run` prints the fully resolved plan
26
+ (vendor, model, mode, timeouts, side-effect decision) with no provider call
27
+ and no job state.
28
+ - **Automate with versioned JSON** — one `--json` envelope for `--list`,
29
+ `--explain`, `--validate`, and `jobs list|status|result|stats`, plus
30
+ read-only `jobs wait`, `jobs audit`, and an offline `omnilane release-audit`
31
+ gate with a deterministic manifest.
32
+ - **Drive local jobs end to end** — `jobs tail` peeks at live output,
33
+ `jobs retry` re-dispatches a completed job fail-closed,
34
+ `prune --older-than` ages out old jobs, and `--help` covers every command.
35
+ - **Install and complete safely** — `install.sh --check`/`--dry-run` report
36
+ drift without writing, `omnilane completion bash|zsh` ships safe tab
37
+ completion, and five macOS stock Bash 3.2 crashes are fixed.
38
+
39
+ ## What's new in v0.6.0
40
+
41
+ - **Explain and validate routes offline** — inspect every fallback candidate
42
+ with `--explain`, or lint the complete effective table with `--validate`,
43
+ without invoking a provider or creating job state.
44
+ - **Inspect local health and outcomes** — bounded `jobs.sh stats` aggregates and
45
+ `omnilane doctor --json` make local automation observable without exposing
46
+ task or result bodies.
47
+ - **Compare runs in Live Board** — pin one loaded job as a memory-only reference
48
+ and compare its model path and public result with the current selection.
49
+ - **Keep lock recovery quiet** — transient owner-file read races no longer leak
50
+ misleading missing-file diagnostics.
51
+
52
+ ## What's new in v0.5.1
53
+
54
+ - **Use Codex work outside Git** — ordinary directories remain supported;
55
+ Omnilane never requires or runs `git init`.
56
+ - **Stop non-Git hangs cleanly** — the resolved per-call watchdog becomes an
57
+ automatic process-group fuse when no whole-job timeout was configured, while
58
+ explicit timeout precedence and exit semantics remain intact.
59
+ - **Trust the displayed version** — `VERSION` now drives `omnilane --version`
60
+ and both plugin manifests, with CI checking the changelog and all five READMEs.
61
+
62
+ ## ⚡ 60-second start
63
+
64
+ ```bash
65
+ git clone https://github.com/Seraphim0916/omnilane && cd omnilane
66
+ ./install.sh # finds your CLIs, links the skill, speaks your language
67
+ omnilane route hardest-coding "fix the flaky auth token refresh"
68
+ omnilane ui start # optional: watch jobs live in your browser
69
+ ```
70
+
71
+ ## 🧭 How it works
72
+
73
+ omnilane lets the main loop of **any** agentic CLI classify subtasks into
74
+ lanes and dispatch each lane to the best vendor's CLI — headlessly, using
75
+ your existing subscription logins:
76
+
77
+ ```mermaid
78
+ flowchart LR
79
+ M["main loop<br/><i>any CLI you drive</i>"] --> T{{"routing.yaml<br/>one shared table"}}
80
+ T -->|hardest-coding| C1["Codex — GPT-5.6 Sol"]
81
+ T -->|bulk-mechanical| C2["Codex — GPT-5.6 Terra"]
82
+ T -->|taste-final| C3["Claude — Opus 4.8"]
83
+ T -->|long-context| C4["Gemini — 3.1 Pro"]
84
+ T -->|live-search| C5["Grok — 4.5"]
85
+ T -->|"arbitrate (opt-in)"| C6["vote — 1-4 model panel"]
86
+ ```
87
+
88
+ - **`routing.yaml`** — lane → vendor + model + effort. One file, read by every
89
+ harness.
90
+ - **Fallback chains** — a lane can list candidates
91
+ (`codex … | claude … | off`); dispatch picks the first vendor CLI you actually
92
+ have, so the default table works even with a single subscription.
93
+ - **`scripts/dispatch.sh [--vendor V] <lane> "<task>"`** — resolves the lane
94
+ and shells out to the vendor's CLI headlessly. `--vendor` selects one named
95
+ vendor without fallback.
96
+ - **`skills/omnilane/SKILL.md`** — a single skill every harness can load:
97
+ identify your own model, self-execute your lane, dispatch the rest.
98
+
99
+ <div align="center">
100
+
101
+ | | | |
102
+ |:---:|:---:|:---:|
103
+ | 🧭 **One table**<br/>four harnesses share it | 🪂 **Fallback chains**<br/>degrades to the CLIs you have | 🗳️ **Opinion panel**<br/>multi-model vote for big calls |
104
+ | 🔒 **Safety rails**<br/>locks · watchdogs · no nesting | 🌏 **Five languages**<br/>the installer speaks your locale | ↩️ **Reversible**<br/>`--uninstall` undoes everything |
105
+
106
+ </div>
107
+
108
+ ## 🛤️ Lanes (defaults — run `scripts/dispatch.sh --list` for your effective table)
109
+
110
+ | Lane | First choice | Backup | When |
111
+ |---|---|---|---|
112
+ | 🔥 hardest-coding | GPT-5.6 Sol (xhigh) | Claude Opus 4.8 (high) | Hardest implementation, deep root-cause debug, correctness-critical edits |
113
+ | 🏗️ bulk-mechanical | GPT-5.6 Terra (max) | Claude Sonnet 5 (high) | Refactors, migrations, tests, review sweeps — mechanical endurance |
114
+ | 🧹 triage | GPT-5.6 Luna (medium) | Gemini 3.5 Flash (Low) | High-volume scans, first-pass filtering |
115
+ | ⚖️ hard-judgment | GPT-5.6 Sol (max) | Claude Opus 4.8 (high) | Architecture arbitration, deep reasoning, second opinions |
116
+ | ✒️ taste-final | Claude Opus 4.8 (high) | GPT-5.6 Sol (max) | User-facing prose, prompt/doc polish, style arbitration |
117
+ | 💬 consult | Explicit named vendor/model | — (no fallback) | Direct natural-language consultation; always keep `--vendor` |
118
+ | 🎨 ui-draft | GPT-5.6 Sol (xhigh) | Claude Opus 4.8 (high) | UI drafts only WITH a design system / reference images |
119
+ | 📚 long-context | Gemini 3.1 Pro (High) | Claude Opus 4.8 (high) | 1M-token synthesis — analysis only, never agentic loops |
120
+ | ⚡ fast-agentic | Gemini 3.5 Flash (High) | GPT-5.6 Luna (high) | Fast multi-step agentic loops, multimodal checks |
121
+ | 📡 live-search | Grok 4.5 | — (off) | Realtime X/web search and social context |
122
+ | 🚰 coding-overflow | Grok 4.5 | — (off) | Codex-quota relief valve for mid-tier coding |
123
+ | 🗳️ arbitrate | off (opt-in vote panel) | — | Built-in opinion panel for big calls — disabled by default; enable it in `routing.local.yaml`, one call per voter per round |
124
+
125
+ The **backup** is the next candidate in the lane's `routing.yaml` chain — what
126
+ dispatch falls back to when the first-choice vendor CLI is not installed. Every
127
+ lane is such a chain; when nothing in it is installed the lane degrades to `off`.
128
+
129
+ > **Where is Claude Fable 5?** Deliberately not in the defaults: the top
130
+ > Claude tier is usually the *main loop itself*, not a dispatched worker, and
131
+ > it prices above Opus. It is offered in the configurator's model menu —
132
+ > route to it if you disagree (e.g. `taste-final: claude claude-fable-5 high`
133
+ > in `routing.local.yaml`).
134
+
135
+ ### Natural-language consultation
136
+
137
+ With the `omnilane` skill or `/route`, you can ask normally:
138
+ **“Ask Opus to challenge this architecture.”** The Agent Skill interprets the
139
+ request; this is not a free-form shell parser in `dispatch.sh`.
140
+
141
+ - A capability-only question recommends the first available model for the
142
+ matching lane and makes no model call.
143
+ - A generic vendor name uses that vendor's configured candidate in `consult`.
144
+ - A canonical alias such as Opus pins its exact model family from the skill
145
+ table. If an explicit target is absent or unavailable, the command fails
146
+ clearly instead of falling back to another vendor or family.
147
+
148
+ <details>
149
+ <summary><b>👉 Which lanes do you run yourself? Pick your main model</b></summary>
150
+
151
+ <br/>
152
+
153
+ The table above is vendor-neutral — the *best* model for a lane doesn't change
154
+ with who is driving. What changes is which lanes you **self-execute** (you
155
+ already are that model, so no second call) versus **dispatch**. Your harness's
156
+ `omnilane` skill applies the right row automatically; this is the human view.
157
+
158
+ - **Claude Code · Fable 5** — self-execute: hard-judgment, taste-final, the hardest correctness-critical fixes. Dispatch mechanical coding volume → Codex, long-context → Gemini, live-search → Grok.
159
+ - **Claude Code · Opus 4.8** — self-execute: taste-final. Dispatch hard-judgment to Codex Sol (it out-scores Opus on raw intelligence), all coding to the Codex lanes, long-context → Gemini, live-search → Grok.
160
+ - **Codex · Sol** — self-execute: hardest-coding, hard-judgment, ui-draft. Dispatch taste-final → Claude, long-context → Gemini, live-search → Grok, bulk → Codex Terra.
161
+ - **Codex · Terra** — self-execute: bulk-mechanical. Escalate the genuinely hardest pieces to Sol; dispatch taste → Claude, long-context → Gemini, live-search → Grok.
162
+ - **Grok Build · Grok 4.5** — self-execute: live-search, coding-overflow (mid-tier coding). Dispatch everything hard to Codex/Claude/Gemini — and verify every API signature and cited fact first.
163
+ - **Antigravity · Gemini** — self-execute: long-context (3.1 Pro) and fast-agentic (Flash). Dispatch coding/judgment/taste to Codex/Claude; live-search → Grok. Never take agentic tool-loop chains on 3.1 Pro.
164
+
165
+ </details>
166
+
167
+ ## 🖥️ Live Board
168
+
169
+ Every dispatch — foreground or `--background` — is a job on disk. The Live
170
+ Board is an optional, read-only local workbench over that job store: what each
171
+ model was asked, what it answered, how it was routed, and whether it is still
172
+ running.
173
+
174
+ <div align="center">
175
+
176
+ <img src="docs/live-board.png" alt="Omnilane Live Board on desktop — job list on the left, task, public result and model path for the selected job on the right" width="820"/>
177
+
178
+ <img src="docs/live-board-mobile.png" alt="Omnilane Live Board on mobile — searchable job list with status filters" width="280"/>
179
+
180
+ </div>
181
+
182
+ ```bash
183
+ omnilane ui start # start or reuse the server and print its authenticated URL
184
+ omnilane ui status # inspect the local server
185
+ omnilane ui url # print the current authenticated URL
186
+ omnilane ui stop # stop it cleanly
187
+ ```
188
+
189
+ The desktop view keeps the job list and detail pane independently scrollable;
190
+ mobile uses a list/detail flow with Back and Esc navigation. Server-sent events
191
+ stream updates without replacing focused rows, and a short disconnect keeps the
192
+ last snapshot while reconnecting. Pin any loaded task as a reference, then
193
+ select another task to compare both model paths and public results side by side.
194
+ The reference is memory-only and disappears when the page closes. The board
195
+ binds only to `127.0.0.1`, uses a random token, and is read-only. It shows
196
+ `task.txt` and the public `out.txt`, but never raw worker or vendor logs.
197
+
198
+ Core routing does not need Python; only this UI requires Python 3.9 or newer.
199
+
200
+ ## 📦 Install
201
+
202
+ Requirements: the vendor CLIs you want to route to, logged in (`codex`,
203
+ `claude`, `grok`, `agy`) and on `PATH` — install only the ones you have; the
204
+ rest of the table degrades automatically.
205
+
206
+ Quickest: `./install.sh` — symlinks the skill for the CLIs it finds, prints
207
+ the plugin commands for the rest, shows your effective routing, and offers the
208
+ interactive lane configurator (`--uninstall` reverses it). The installer
209
+ speaks English, 繁體中文, 简体中文, 日本語 and 한국어 (auto-detected from
210
+ your locale; force with `OMNILANE_LANG=zh-TW` etc.). It also offers an
211
+ optional per-CLI **routing reminder**: a marked, reversible block appended to
212
+ each CLI's instruction file (`~/.claude/CLAUDE.md`, `~/.codex/AGENTS.md`,
213
+ `~/.grok/Agents.md`, `~/.gemini/GEMINI.md` — paths may vary across CLI
214
+ versions) so the main loop remembers to consult the table; non-interactive
215
+ installs can pass `OMNILANE_HOOKS=all|none|claude,codex`. Manual wiring:
216
+
217
+ Use `./install.sh --check` for a read-only drift report. Add `--dry-run` to an
218
+ install or `--uninstall` to preview every checkout-owned file action.
219
+ Rollback the installer-owned links and marked reminders with
220
+ `./install.sh --uninstall`.
221
+
222
+ - **Claude Code**: install as a plugin (ships the skill + `/route`,
223
+ `/route-jobs` commands), or drop `skills/omnilane` into `~/.claude/skills/`.
224
+ - **Codex**: drop/symlink `skills/omnilane` into `~/.codex/skills/`.
225
+ - **Grok Build**: `grok plugin install <this repo> --trust`
226
+ - **Antigravity**: `agy plugin install <this repo>` (check first with
227
+ `agy plugin validate <this repo>`)
228
+
229
+ ## ⚙️ Configure
230
+
231
+ Three layers, all optional:
232
+
233
+ 1. **Interactive menu** — `scripts/configure.sh` lists configurable lanes, lets you
234
+ pick vendor → model → effort per lane from suggestions (or free text for
235
+ future models), and writes the result to `~/.omnilane/routing.local.yaml`.
236
+ It intentionally skips the multi-vendor `consult` lane; edit that one by
237
+ hand if needed. `install.sh` offers to run the menu at the end of a normal install.
238
+ 2. **`~/.omnilane/routing.local.yaml`** — hand-edited overrides, same format
239
+ as `routing.yaml`; local lines win. See `routing.local.yaml.example`.
240
+ 3. **`~/.omnilane/local.sh`** — per-machine binaries, proxies, auth wrappers;
241
+ sourced by every runner, never committed. See `local.sh.example`.
242
+
243
+ Check the result any time:
244
+
245
+ ```
246
+ scripts/dispatch.sh --list # effective table, fallback resolution annotated
247
+ ```
248
+
249
+ ## 📖 Command reference
250
+
251
+ ```
252
+ omnilane list | route … | jobs … | configure # global wrapper, works anywhere
253
+ # (install.sh links it into ~/.local/bin)
254
+ eval "$(omnilane completion bash)" # enable Bash completion for this shell
255
+ source <(omnilane completion zsh) # enable Zsh completion for this shell
256
+ omnilane release-audit [--target VERSION] [--json] # offline, read-only release gate
257
+ omnilane ui start # start/reuse the local Live UI; print its URL
258
+ omnilane ui status # report whether the Live UI is running
259
+ omnilane ui url # print the current authenticated local URL
260
+ omnilane ui stop # stop the Live UI
261
+ omnilane doctor [--json] # read-only routing and runtime health report
262
+ dispatch.sh [--background] [--dry-run] [--mode advise|work] [--workdir DIR]
263
+ [--vendor V] [--model M] [--effort E] [--timeout SEC] [--job-timeout SEC]
264
+ LANE "TASK" # "-" reads task from stdin
265
+ dispatch.sh [--json] --list [--json]
266
+ dispatch.sh [--json] --explain LANE [--json] # offline candidate-by-candidate decision trace
267
+ dispatch.sh [--json] --validate [--json] # lint effective routing; no provider calls
268
+ jobs.sh [--json] {list | status ID | result ID} # JSON result reports metadata, never bodies
269
+ jobs.sh wait ID [--timeout N] # job exit; 124 timeout; 125 dead worker
270
+ jobs.sh [--json] stats [--last N] # local success and routing aggregates
271
+ jobs.sh audit [--last N] [--json] # read-only job integrity/privacy check
272
+ jobs.sh prune [--keep N] [--apply] # preview by default; completed jobs only
273
+ configure.sh # interactive lane menu
274
+ ```
275
+
276
+ **Big decisions can get a panel, not a person.** The `arbitrate` lane ships
277
+ **disabled** — a panel costs one call per voter per round, so it is opt-in.
278
+ Enable it with `arbitrate: vote codex,claude,grok -` in `routing.local.yaml`,
279
+ or through the configurator, which lets you pick any 1-4 voters from
280
+ codex/claude/grok/gemini. The same question then goes to every voter, the
281
+ opinions come back side by side, and the calling model chairs the verdict.
282
+ Set the effort field to `2` for a debate round — every voter sees the whole
283
+ panel and rebuts only the disagreements. Power users can swap in their own
284
+ gate via the `exec` vendor:
285
+ `arbitrate: exec /path/to/script -` — the script receives
286
+ `MODE WORKDIR EFFORT PROMPT_FILE OUTPUT_FILE` and writes its verdict to
287
+ `OUTPUT_FILE` (see `scripts/runners/run-exec.sh`).
288
+
289
+ Exit codes: `2` bad usage (including an invalid vendor or a requested vendor
290
+ absent from the lane), `3` lane disabled (off), `4` no vendor CLI available in
291
+ the chain or the requested vendor is configured but its CLI is unavailable,
292
+ `5` too few successful Round 1
293
+ voters, `6` no Round 2 rebuttal succeeded, `86` nested dispatch refused, `87`
294
+ lock timeout, `124` whole-job timeout expired; otherwise the worker's own exit
295
+ code passes through.
296
+
297
+ ## 🎭 Modes
298
+
299
+ - **advise** (default) — read-only worker. Codex runs in a read-only sandbox;
300
+ Claude gets only Read/Glob/Grep; Grok runs in plan mode. Use for reviews,
301
+ questions, second opinions.
302
+ - **work** — the worker may edit files, only inside the `--workdir` you name.
303
+ Codex gets a workspace-write sandbox; Claude auto-accepts edits; Gemini runs
304
+ in accept-edits mode.
305
+
306
+ ## 🔒 Safety rails
307
+
308
+ - **No nested dispatch** — workers cannot fan out again (`OMNILANE_DEPTH`
309
+ guard, exit 86): no runaway agent-calls-agent quota chains.
310
+ - **Serialized codex** — same-target-directory codex dispatches queue behind a
311
+ lock keyed on the normalized workdir; stale locks from crashed jobs are
312
+ detected by owner PID and stolen safely.
313
+ - **Watchdog** — every worker runs under `timeout`/`gtimeout`, or a perl-alarm
314
+ fallback when neither exists (stock macOS), so a hung CLI cannot block
315
+ forever. The cap applies to **each CLI invocation**, highest priority first:
316
+ `--timeout SECONDS` beats a per-lane `OMNILANE_TIMEOUT_<LANE>` (the lane
317
+ upper-cased with `-`→`_`, e.g. `OMNILANE_TIMEOUT_HARD_JUDGMENT`) beats the
318
+ global `OMNILANE_TIMEOUT`, default 600s. It is a per-call hang-guard, not a
319
+ whole-job budget: a retrying vendor (grok) or the `vote` panel (voters ×
320
+ rounds) makes several calls, so total wall-clock can be a multiple of this
321
+ value.
322
+ - **Whole-job fuse** — optional `--job-timeout SECONDS` caps lock wait plus all
323
+ retries, voters, and rounds under one process-group supervisor. Priority is
324
+ flag > `OMNILANE_JOB_TIMEOUT_<LANE>` > `OMNILANE_JOB_TIMEOUT` > disabled,
325
+ with one automatic exception: Codex `work` outside a Git worktree uses the
326
+ resolved per-call watchdog as its whole-job fuse when none was configured,
327
+ capped at the supervisor's 999999999-second maximum. This automatic guard
328
+ needs the bundled Perl supervisor; if unavailable, dispatch warns and keeps
329
+ non-Git work running through the existing per-call watchdog path, which emits
330
+ its own warning if no watchdog tool exists.
331
+ Expiry cleans the supervised process group and returns 124. For a deep audit
332
+ of a fubon-autotrade-sized repository, start around 2–4 hours (7200–14400s)
333
+ with a 30-minute per-call watchdog; these are recommendations, not defaults.
334
+ - **Background lifecycle** — `--background` workers run in their own process
335
+ group and survive the caller's exit; killed workers record an exit code, and
336
+ `jobs.sh status` reports `dead` instead of `running` forever.
337
+ - **Payload caps** — oversized task text is truncated head+tail before it can
338
+ blow a worker's context.
339
+
340
+ ## 📊 Defaults and provenance
341
+
342
+ Default lane assignments follow Artificial Analysis coding/intelligence data
343
+ (2026-07 snapshot, cross-checked against AA site records and vendor pricing
344
+ pages) plus published head-to-head reviews; they are opinions, not laws — the
345
+ configurator and `routing.local.yaml` exist so you can disagree.
346
+
347
+ ## ⚠️ Known limitations
348
+
349
+ - **Antigravity tool calls in print mode are unstable** in current CLI builds
350
+ (tool calls may be denied or rejected with invalid-argument errors). The
351
+ long-context lane is designed for content-you-paste-in synthesis, which is
352
+ unaffected; for repo *inspection* prefer the claude/codex candidates.
353
+ - **Grok has no reasoning-effort knob**; the effort field is accepted for
354
+ interface parity and ignored.
355
+ - **Non-Git Codex work is supported.** Some Codex CLI builds may stall outside
356
+ a Git worktree, so the automatic fuse above bounds that case and cleans the
357
+ supervised process group. Omnilane neither initializes nor requires a repository.
358
+
359
+ ## 🌱 Status
360
+
361
+ v0.5.1 keeps Codex `work` usable outside Git while bounding stalls with
362
+ process-group cleanup, and synchronizes every public version surface. It builds
363
+ on v0.5.0's installer, lifecycle, job-store, deadline, diagnostics, and release
364
+ CI hardening. Grok/Antigravity command-shell behavior may still vary across CLI
365
+ versions. Issues and PRs welcome.
366
+
367
+ Project policies: [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md) ·
368
+ [Changelog](CHANGELOG.md)