omnilane 0.12.0 → 0.14.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/CHANGELOG.md CHANGED
@@ -6,6 +6,71 @@ semantic version tags.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.14.0] - 2026-08-10
10
+
11
+ ### Added
12
+
13
+ - Optional `omnilane doctor --probe V` and read-only MCP `provider_probe` perform
14
+ one bounded advise-mode live capability check only when explicitly requested;
15
+ reports include routing/timing metadata but never the provider response body.
16
+ - Live Board retained-history search and state filters now drive a local
17
+ **Export visible** JSON download that excludes tokens, task/result bodies,
18
+ workdirs, and logs.
19
+ - `omnilane benchmark` provides a versioned fixed-workload quality/timing report,
20
+ transparent user-supplied per-call cost estimates, default no-call dry-run,
21
+ and an explicit `--run` provider-call gate.
22
+ - CI runs `omnilane doctor --strict --json` against an isolated, offline fixture
23
+ as a post-install acceptance contract.
24
+
25
+ - `omnilane jobs recommend` and the read-only MCP `jobs_recommend` tool derive
26
+ per-lane vendor suggestions from bounded completed-job metadata. A configurable
27
+ minimum sample gate prevents one-off successes from outranking established
28
+ evidence; neither surface reads task/result bodies or changes routing.
29
+ - `omnilane doctor --strict` keeps warning diagnostics intact but exits nonzero
30
+ when any warning is present, so local automation and CI can enforce a complete
31
+ runtime setup. JSON output now includes the applied `strict` policy and makes
32
+ `ok` reflect it.
33
+
34
+ ### Fixed
35
+
36
+ - `doctor` now validates macOS `stat -f` output before falling back to GNU
37
+ `stat -c`, so owner-only job-store permissions are classified consistently on
38
+ Linux CI instead of becoming a false strict-mode warning.
39
+
40
+ ## [0.13.0] - 2026-08-03
41
+
42
+ ### Changed
43
+
44
+ - `long-context` now orders on AA-LCR, Artificial Analysis's long-context
45
+ reasoning benchmark, which scores exactly this lane's work: extracting and
46
+ synthesising across long-form documents. Gemini 3.1 Pro leads both fallbacks
47
+ there, so first place is now positively justified rather than merely
48
+ unrevisited. The two fallbacks swapped — GPT-5.6 Sol at `high` precedes
49
+ Claude Opus 5 at `high`.
50
+ - Corrected the advice this lane used to give. It sent multi-hop synthesis to
51
+ the Claude candidate on the strength of second-hand figures for a prior model
52
+ generation; on first-party current-generation data Claude is the weakest of
53
+ the three shipped candidates, not the strongest. The claim is gone from
54
+ `routing.yaml` and from all five lane tables.
55
+
56
+ ### Added
57
+
58
+ - `release-audit --require-tag` now reports whether recently pushed tags have a
59
+ matching GitHub release. v0.11.0 shipped a tag with no release and nothing
60
+ noticed for a week. The check warns rather than fails, skips silently when
61
+ `gh` is absent, unauthenticated or offline so the audit still works in CI,
62
+ excludes the target being released (whose release does not exist yet at audit
63
+ time), and looks only at the few most recent tags — a check that stays yellow
64
+ forever is one everyone learns to ignore.
65
+
66
+ ### Notes
67
+
68
+ - AA-LCR runs on documents of 10k-100k tokens, so it settles synthesis quality
69
+ across long documents and settles nothing at a full 1M. GPT-5.6 Luna tops
70
+ that table at a fraction of the cost and was deliberately *not* promoted:
71
+ this lane's headline case is the 1M sweep, which the benchmark does not
72
+ reach. See `docs/model-capabilities-2026-07.md`.
73
+
9
74
  ## [0.12.0] - 2026-08-03
10
75
 
11
76
  ### Changed
@@ -529,7 +594,10 @@ work to the wrong model, and records the evidence behind the shipped defaults.
529
594
  - Initial shared routing table, cross-vendor dispatcher, runners, installer,
530
595
  and baseline lint fixes.
531
596
 
532
- [Unreleased]: https://github.com/Seraphim0916/omnilane/compare/v0.12.0...HEAD
597
+ [Unreleased]: https://github.com/Seraphim0916/omnilane/compare/v0.14.0...HEAD
598
+
599
+ [0.14.0]: https://github.com/Seraphim0916/omnilane/compare/v0.13.0...v0.14.0
600
+ [0.13.0]: https://github.com/Seraphim0916/omnilane/compare/v0.12.0...v0.13.0
533
601
  [0.12.0]: https://github.com/Seraphim0916/omnilane/compare/v0.11.0...v0.12.0
534
602
  [0.11.0]: https://github.com/Seraphim0916/omnilane/compare/v0.10.4...v0.11.0
535
603
  [0.10.4]: https://github.com/Seraphim0916/omnilane/compare/v0.10.3...v0.10.4
package/README.ja.md CHANGED
@@ -119,7 +119,7 @@ flowchart LR
119
119
  | ✒️ taste-final | Claude Opus 5 (high) | GPT-5.6 Sol (max) | 対外文章、prompt/ドキュメント推敲、スタイル最終審 |
120
120
  | 💬 consult | 明示指定したベンダー/モデル | —(フォールバックなし) | 自然言語で直接相談。`--vendor` を必ず維持 |
121
121
  | 🎨 ui-draft | GPT-5.6 Sol (xhigh) | Claude Opus 5 (high) | デザインシステム/参考画像がある場合の UI ドラフト |
122
- | 📚 long-context | Gemini 3.1 Pro (High) | Claude Opus 5 (high) | 100 万トークン級の走査と検索。複数箇所をまたぐ統合には Claude 候補を、高速反復ループは Flash を優先 |
122
+ | 📚 long-context | Gemini 3.1 Pro (High) | GPT-5.6 Sol (high) | 100 万トークン級の走査・検索と、長文をまたぐ統合。高速反復ループは Flash を優先 |
123
123
  | ⚡ fast-agentic | GPT-5.6 Luna (max) | Gemini 3.6 Flash (High) | 高速なマルチステップ agentic ループ、マルチモーダル確認 |
124
124
  | 📡 live-search | Grok 4.5 | —(off) | リアルタイム X/ウェブ検索とソーシャル文脈 |
125
125
  | 🚰 coding-overflow | Grok 4.5 | Kimi K3 → Qwen3 Coder Plus → OpenCode | Codex クォータ逼迫時の中級コーディング逃し弁 |
@@ -516,6 +516,31 @@ scripts/dispatch.sh --dry-run hardest-coding "…" # 解決済みプラン、
516
516
 
517
517
  ## 📜 リリース履歴
518
518
 
519
+ ## v0.14.0 の新機能
520
+
521
+ - **根拠に基づくルーティング提案**:`jobs recommend` と MCP `jobs_recommend` は公開ジョブメタデータだけを読み、ルーティングを自動変更しません。
522
+ - **任意の実動プローブ**:`doctor --probe V` と MCP `provider_probe` は明示された場合だけプロバイダーを呼び出し、応答本文を報告しません。
523
+ - **Live Board の履歴検索・絞り込み・エクスポート**:直近 50 件を対象に、表示中の公開メタデータだけを出力します。
524
+ - **固定品質/コストベンチマーク**:`omnilane benchmark` は既定で dry-run、実呼び出しには `--run` が必要です。
525
+ - **厳格なインストール検証**:CI で隔離された `doctor --strict --json` を実行し、macOS/GNU `stat` の権限判定差も修正しました。
526
+
527
+ ## v0.13.0 の新機能
528
+
529
+ - **`long-context` を AA-LCR で順序付け** — Artificial Analysis の長文脈推論
530
+ ベンチマークで、まさにこのレーンの仕事を測るものです。Gemini 3.1 Pro が両方の
531
+ フォールバックを上回るため、その一番手は「未見直し」から「根拠あり」に変わりました。
532
+ - **このレーンの旧来の助言は逆で、削除しました。** 従来は多段の統合を Claude 候補へ
533
+ 回すよう促していましたが、根拠は前世代モデルの二次情報でした。一次情報の現行世代
534
+ データでは Claude が三候補中もっとも弱く、フォールバックを入れ替えて GPT-5.6 Sol
535
+ (high) が Claude Opus 5 (high) の前に来ます。
536
+ - **`release-audit --require-tag` が GitHub リリースのないタグを指摘します。** 失敗
537
+ ではなく警告で、`gh` が無い場合やオフラインではスキップするため CI でも動作し、
538
+ 直近のタグのみを見ます。
539
+ - **範囲の注記:** AA-LCR は 10k〜100k トークンの文書で実施されるため、長文の統合品質
540
+ は決まりますが 1M での挙動は何も決まりません。GPT-5.6 Luna は同表の首位でしかも
541
+ はるかに安価ですが、**意図的に昇格させていません** — このレーンの本命は 1M の走査で、
542
+ ベンチマークがそこまで届かないからです。
543
+
519
544
  ## v0.12.0 の新機能
520
545
 
521
546
  - **`hardest-coding` の Sol を `max` から `xhigh` へ** — AA の努力度別 Coding Index
package/README.ko.md CHANGED
@@ -117,7 +117,7 @@ flowchart LR
117
117
  | ✒️ taste-final | Claude Opus 5 (high) | GPT-5.6 Sol (max) | 대외 문장, prompt/문서 다듬기, 스타일 최종심 |
118
118
  | 💬 consult | 명시적으로 지정한 벤더/모델 | —(폴백 없음) | 자연어 직접 상담. `--vendor` 를 반드시 유지 |
119
119
  | 🎨 ui-draft | GPT-5.6 Sol (xhigh) | Claude Opus 5 (high) | 디자인 시스템/참고 이미지가 있을 때의 UI 초안 |
120
- | 📚 long-context | Gemini 3.1 Pro (High) | Claude Opus 5 (high) | 100만 토큰급 훑기와 검색. 여러 곳을 잇는 다중 홉 통합은 Claude 후보를, 빠른 반복 루프는 Flash 우선 |
120
+ | 📚 long-context | Gemini 3.1 Pro (High) | GPT-5.6 Sol (high) | 100만 토큰급 훑기·검색과 문서를 잇는 통합. 빠른 반복 루프는 Flash 우선 |
121
121
  | ⚡ fast-agentic | GPT-5.6 Luna (max) | Gemini 3.6 Flash (High) | 빠른 멀티스텝 agentic 루프, 멀티모달 확인 |
122
122
  | 📡 live-search | Grok 4.5 | —(off) | 실시간 X/웹 검색과 소셜 맥락 |
123
123
  | 🚰 coding-overflow | Grok 4.5 | Kimi K3 → Qwen3 Coder Plus → OpenCode | Codex 쿼터 소진 시 중급 코딩 안전 밸브 |
@@ -499,6 +499,31 @@ scripts/dispatch.sh --dry-run hardest-coding "…" # 완전히 해석된 계
499
499
 
500
500
  ## 📜 릴리스 기록
501
501
 
502
+ ## v0.14.0 새 기능
503
+
504
+ - **근거 기반 라우팅 제안**: `jobs recommend`와 MCP `jobs_recommend`는 공개 작업 메타데이터만 읽고 라우팅을 자동 변경하지 않습니다.
505
+ - **선택형 실제 기능 탐지**: `doctor --probe V`와 MCP `provider_probe`는 명시적으로 요청할 때만 공급자를 호출하며 응답 본문을 보고하지 않습니다.
506
+ - **Live Board 기록 검색·필터·내보내기**: 최근 50개 작업을 검색하고 현재 표시된 공개 메타데이터만 내보냅니다.
507
+ - **고정 품질/비용 벤치마크**: `omnilane benchmark`는 기본적으로 dry-run이며 실제 호출에는 `--run`이 필요합니다.
508
+ - **엄격한 설치 검증**: CI에서 격리된 `doctor --strict --json`을 실행하고 macOS/GNU `stat` 권한 판정 차이도 수정했습니다.
509
+
510
+ ## v0.13.0 새 기능
511
+
512
+ - **`long-context` 를 AA-LCR 기준으로 정렬** — Artificial Analysis 의 장문맥 추론
513
+ 벤치마크로, 바로 이 레인의 일을 측정합니다. Gemini 3.1 Pro 가 두 폴백을 모두
514
+ 앞서므로 1순위가 "미검토" 에서 "근거 있음" 으로 바뀌었습니다.
515
+ - **이 레인의 기존 조언은 반대였고 제거했습니다.** 예전에는 다중 홉 통합을 Claude
516
+ 후보로 보내라고 했지만 근거는 이전 세대 모델의 2차 자료였습니다. 1차 현세대
517
+ 데이터에서는 Claude 가 세 후보 중 가장 약해, 폴백을 바꿔 GPT-5.6 Sol (high) 가
518
+ Claude Opus 5 (high) 앞에 옵니다.
519
+ - **`release-audit --require-tag` 가 GitHub 릴리스 없는 태그를 표시합니다.** 실패가
520
+ 아니라 경고이며, `gh` 가 없거나 오프라인이면 건너뛰어 CI 에서도 동작하고, 최근
521
+ 태그만 봅니다.
522
+ - **범위 참고:** AA-LCR 은 10k~100k 토큰 문서로 수행되므로 긴 문서 통합 품질은
523
+ 가려지지만 1M 에서의 동작은 전혀 가려지지 않습니다. GPT-5.6 Luna 가 이 표의
524
+ 1위이고 훨씬 저렴하지만 **의도적으로 승격하지 않았습니다** — 이 레인의 본령은
525
+ 벤치마크가 닿지 않는 1M 훑기이기 때문입니다.
526
+
502
527
  ## v0.12.0 새 기능
503
528
 
504
529
  - **`hardest-coding`의 Sol을 `max`에서 `xhigh`로** — AA의 노력 수준별 Coding Index
package/README.md CHANGED
@@ -122,7 +122,7 @@ actually resolves.
122
122
  | ✒️ taste-final | Claude Opus 5 (high) | GPT-5.6 Sol (max) | User-facing prose, prompt/doc polish, style arbitration |
123
123
  | 💬 consult | Explicit named vendor/model | — (no fallback) | Direct natural-language consultation; always keep `--vendor` |
124
124
  | 🎨 ui-draft | GPT-5.6 Sol (xhigh) | Claude Opus 5 (high) | UI drafts only WITH a design system / reference images |
125
- | 📚 long-context | Gemini 3.1 Pro (High) | Claude Opus 5 (high) | 1M-token sweeps and retrieval; for multi-hop synthesis prefer the Claude candidate, and Flash for fast repeated loops |
125
+ | 📚 long-context | Gemini 3.1 Pro (High) | GPT-5.6 Sol (high) | 1M-token sweeps, retrieval, and synthesis across long documents; Flash for fast repeated loops |
126
126
  | ⚡ fast-agentic | GPT-5.6 Luna (max) | Gemini 3.6 Flash (High) | Fast multi-step agentic loops, multimodal checks |
127
127
  | 📡 live-search | Grok 4.5 | — (off) | Realtime X/web search and social context |
128
128
  | 🚰 coding-overflow | Grok 4.5 | Kimi K3 → Qwen3 Coder Plus → OpenCode | Codex-quota relief valve for mid-tier coding |
@@ -195,6 +195,10 @@ The reference is memory-only and disappears when the page closes. The board
195
195
  binds only to `127.0.0.1`, uses a random token, and is read-only. It shows
196
196
  `task.txt` and the public `out.txt`, but never raw worker or vendor logs.
197
197
 
198
+ Search and state filters apply to the latest 50 retained jobs. **Export visible**
199
+ downloads only the currently visible public metadata as local JSON; it excludes
200
+ tokens, task text, result bodies, workdirs, and raw logs.
201
+
198
202
  The board reads in English, Japanese, Korean, Traditional Chinese and Simplified
199
203
  Chinese. It follows the browser language on first load; the switcher in the
200
204
  header overrides that and the choice is remembered locally.
@@ -255,7 +259,8 @@ adding a routing reminder. Configure the host to launch the installed CLI:
255
259
 
256
260
  The server exposes `route` plus read-only introspection: `list_lanes`,
257
261
  `explain`, `validate`, `dry_run`, `jobs_list`, `jobs_status`, `jobs_result`,
258
- `jobs_stats`, `jobs_audit`, and `doctor`. `route` defaults to read-only `advise` mode. Calls that select `work` must also
262
+ `jobs_stats`, `jobs_recommend`, `jobs_audit`, `doctor`, and the explicitly opt-in
263
+ `provider_probe`. `route` defaults to read-only `advise` mode. Calls that select `work` must also
259
264
  provide an explicit `workdir`.
260
265
 
261
266
  Node.js is the only runtime requirement (no npm packages). If you prefer
@@ -299,7 +304,8 @@ omnilane ui start # start/reuse the local Live UI;
299
304
  omnilane ui status # report whether the Live UI is running
300
305
  omnilane ui url # print the current authenticated local URL
301
306
  omnilane ui stop # stop the Live UI
302
- omnilane doctor [--json] # read-only routing and runtime health report
307
+ omnilane doctor [--json] [--strict] [--probe V] [--probe-timeout SEC] # live probe is opt-in
308
+ omnilane benchmark [--json] [--run] [--vendor V] [--cost-per-call V=USD] # dry-run by default
303
309
  dispatch.sh [--background] [--dry-run] [--mode advise|work|sysops] [--workdir DIR]
304
310
  [--vendor V] [--model M] [--effort E] [--timeout SEC] [--job-timeout SEC]
305
311
  LANE "TASK" # "-" reads task from stdin
@@ -312,12 +318,24 @@ jobs.sh wait ID [--timeout N] # job exit; 124 timeout; 125 d
312
318
  jobs.sh cancel ID # stop a running job: group SIGTERM, then SIGKILL
313
319
  jobs.sh rm ID # delete one finished/dead job (refuses a running job)
314
320
  jobs.sh [--json] stats [--last N] [--lane L] [--vendor V] # local success and routing aggregates
321
+ jobs.sh [--json] recommend [--last N] [--lane L] [--min-samples N] # evidence-gated vendor suggestion
315
322
  jobs.sh audit [--last N] [--json] # read-only job integrity/privacy check
316
323
  jobs.sh prune [--keep N] [--apply] # preview by default; completed jobs only
317
324
  configure.sh # interactive lane menu
318
325
  configure.sh set|get|unset|list|diff LANE [SPEC] # script/inspect routing.local.yaml, no tty
319
326
  ```
320
327
 
328
+ `jobs recommend` reads only validated public metadata and exit codes. It ranks
329
+ eligible vendors by success rate, sample count, then name; the default minimum
330
+ is three completed jobs. It never reads task/result bodies or changes routing.
331
+
332
+ `doctor --probe V` makes one bounded advise-mode provider call and returns only
333
+ availability, selected model, timing, and response byte count—not the response
334
+ body. Without `--probe`, doctor remains offline. `benchmark` uses the fixed TSV
335
+ suite in `benchmarks/workloads.tsv`; its default dry-run resolves every route
336
+ without provider calls. `--run` is the explicit call gate, and cost totals are
337
+ estimates based only on values supplied with `--cost-per-call`.
338
+
321
339
  **Big decisions can get a panel, not a person.** The `arbitrate` lane ships
322
340
  **disabled** — a panel costs one call per voter per round, so it is opt-in.
323
341
  Enable it with `arbitrate: vote codex,claude,grok -` in `routing.local.yaml`,
@@ -547,6 +565,43 @@ working notes, including per-benchmark caveats, live in
547
565
 
548
566
  ## 📜 Release history
549
567
 
568
+ ## What's new in v0.14.0
569
+
570
+ - **Evidence-based routing recommendations** — `jobs recommend` and MCP
571
+ `jobs_recommend` rank vendors from completed public job metadata, enforce a
572
+ minimum sample gate, and never change routing automatically.
573
+ - **Opt-in live capability probes** — `doctor --probe V` and MCP
574
+ `provider_probe` distinguish an installed CLI from a working provider call.
575
+ Default doctor remains offline; probe reports never include response bodies.
576
+ - **Search, filter, and export Live Board history** — search and state filters
577
+ cover the latest 50 jobs, while **Export visible** downloads only filtered
578
+ public metadata.
579
+ - **Repeatable quality/cost benchmark** — `omnilane benchmark` ships a fixed
580
+ workload suite, defaults to provider-free dry-run, and requires `--run` for
581
+ actual calls. Cost estimates use only explicit `--cost-per-call` values.
582
+ - **Strict installation acceptance** — CI runs isolated
583
+ `omnilane doctor --strict --json`, catching incomplete runtime wiring without
584
+ contacting providers.
585
+
586
+ ## What's new in v0.13.0
587
+
588
+ - **`long-context` is ordered on AA-LCR** — Artificial Analysis's long-context
589
+ reasoning benchmark, which scores exactly this lane's work. Gemini 3.1 Pro
590
+ leads both fallbacks there, so its first place is now positively justified
591
+ rather than merely unrevisited.
592
+ - **The lane's old advice was backwards and is gone.** It used to send
593
+ multi-hop synthesis to the Claude candidate on second-hand figures for a
594
+ prior model generation; on first-party current-generation data Claude is the
595
+ weakest of the three shipped candidates. The fallbacks swapped, so GPT-5.6
596
+ Sol (high) now precedes Claude Opus 5 (high).
597
+ - **`release-audit --require-tag` flags tags with no GitHub release.** It warns
598
+ rather than fails, skips when `gh` is absent or offline so the audit still
599
+ runs in CI, and looks only at recent tags.
600
+ - **Scope note:** AA-LCR runs on 10k-100k-token documents, so it settles
601
+ synthesis across long documents and nothing at a full 1M. GPT-5.6 Luna tops
602
+ that table far more cheaply and was deliberately *not* promoted, because this
603
+ lane exists for the 1M sweep the benchmark does not reach.
604
+
550
605
  ## What's new in v0.12.0
551
606
 
552
607
  - **`hardest-coding` drops Sol from `max` to `xhigh`** — on AA's per-effort
package/README.zh-CN.md CHANGED
@@ -110,7 +110,7 @@ flowchart LR
110
110
  | ✒️ taste-final | Claude Opus 5 (high) | GPT-5.6 Sol (max) | 对外文字、prompt 与文档打磨、风格终审 |
111
111
  | 💬 consult | 明确指定的厂商/模型 | —(不降级) | 自然语言直接咨询;必须保留 `--vendor` |
112
112
  | 🎨 ui-draft | GPT-5.6 Sol (xhigh) | Claude Opus 5 (high) | 有设计规范/参考图时的 UI 出稿;开放式视觉品味交给 taste-final |
113
- | 📚 long-context | Gemini 3.1 Pro (High) | Claude Opus 5 (high) | 百万 token 扫读与检索;要跨段落多跳整合请改用 Claude 候选,高速重复循环仍优先 Flash |
113
+ | 📚 long-context | Gemini 3.1 Pro (High) | GPT-5.6 Sol (high) | 百万 token 扫读、检索与长文跨段整合;高速重复循环仍优先 Flash |
114
114
  | ⚡ fast-agentic | GPT-5.6 Luna (max) | Gemini 3.6 Flash (High) | 快速多步骤 agentic 循环、多模态检查 |
115
115
  | 📡 live-search | Grok 4.5 | —(off) | 实时 X/网络搜索与社群脉络 |
116
116
  | 🚰 coding-overflow | Grok 4.5 | Kimi K3 → Qwen3 Coder Plus → OpenCode | Codex 额度吃紧时的中量级编码溢流道;事实性声明须另行查证 |
@@ -473,6 +473,28 @@ vendor 一律当成 `work`,而且它只能逐次明确指定,永远不是 lane
473
473
 
474
474
  ## 📜 版本历程
475
475
 
476
+ ## v0.14.0 新功能
477
+
478
+ - **基于证据的路由建议**:`jobs recommend` 与 MCP `jobs_recommend` 只读取公开作业元数据,并且不会自动修改路由。
479
+ - **可选的真实能力探测**:`doctor --probe V` 与 MCP `provider_probe` 仅在明确请求时调用供应商,报告不包含回答正文。
480
+ - **Live Board 历史搜索、筛选与导出**:支持最近 50 条作业,并且只导出当前可见的公开元数据。
481
+ - **固定质量/成本基准**:`omnilane benchmark` 默认只做 dry-run,`--run` 才实际调用供应商。
482
+ - **严格安装验收**:CI 在隔离环境执行 `doctor --strict --json`,并修正 macOS/GNU `stat` 权限检测差异。
483
+
484
+ ## v0.13.0 新功能
485
+
486
+ - **`long-context` 改用 AA-LCR 排序**——那是 Artificial Analysis 的长脉络推理基准,
487
+ 量的正是这条通道的工作。Gemini 3.1 Pro 在该榜领先两个备援,因此它的第一顺位
488
+ 从「未复审」升格为「有据」。
489
+ - **这条通道原本的建议是反的,已移除。** 它原先要人把多跳整合改派给 Claude 候选,
490
+ 依据是上一代模型的二手数字;以第一手当代数据看,Claude 反而是三个候选里最弱的。
491
+ 备援因此换位,GPT-5.6 Sol (high) 排在 Claude Opus 5 (high) 前面。
492
+ - **`release-audit --require-tag` 会标出没有 GitHub release 的 tag。** 只警告不中断,
493
+ `gh` 缺席或离线时自动跳过(CI 仍可跑),且只看最近几个 tag。
494
+ - **范围注记:** AA-LCR 测的是 10k–100k token 的文件,所以它能定「长文整合谁强」,
495
+ 定不了 1M 的行为。GPT-5.6 Luna 在该榜居首且便宜得多,**刻意不升**——这条通道的
496
+ 招牌工作是 1M 扫读,而该基准涵盖不到。
497
+
476
498
  ## v0.12.0 新功能
477
499
 
478
500
  - **`hardest-coding` 的 Sol 从 `max` 降到 `xhigh`**——在 AA 分档位的 Coding Index
package/README.zh-TW.md CHANGED
@@ -110,7 +110,7 @@ flowchart LR
110
110
  | ✒️ taste-final | Claude Opus 5 (high) | GPT-5.6 Sol (max) | 對外文字、prompt 與文件打磨、風格終審 |
111
111
  | 💬 consult | 明確點名的廠商/模型 | —(不降級) | 自然語言直接諮詢;必須保留 `--vendor` |
112
112
  | 🎨 ui-draft | GPT-5.6 Sol (xhigh) | Claude Opus 5 (high) | 有設計規範/參考圖時的 UI 出稿;開放式視覺品味交給 taste-final |
113
- | 📚 long-context | Gemini 3.1 Pro (High) | Claude Opus 5 (high) | 百萬 token 掃讀與檢索;要跨段落多跳整合請改用 Claude 候選,高速重複迴圈仍優先 Flash |
113
+ | 📚 long-context | Gemini 3.1 Pro (High) | GPT-5.6 Sol (high) | 百萬 token 掃讀、檢索與長文跨段整合;高速重複迴圈仍優先 Flash |
114
114
  | ⚡ fast-agentic | GPT-5.6 Luna (max) | Gemini 3.6 Flash (High) | 快速多步驟 agentic 迴圈、多模態檢查 |
115
115
  | 📡 live-search | Grok 4.5 | —(off) | 即時 X/網路搜尋與社群脈絡 |
116
116
  | 🚰 coding-overflow | Grok 4.5 | Kimi K3 → Qwen3 Coder Plus → OpenCode | Codex 額度吃緊時的中量級編碼溢流道;事實性宣稱須另行查證 |
@@ -178,6 +178,9 @@ omnilane ui stop # 正常停止
178
178
  `127.0.0.1`、用隨機 token 保護、全程唯讀。畫面只顯示 `task.txt` 與公開的
179
179
  `out.txt`,不顯示工作端或廠商原始 log。
180
180
 
181
+ 搜尋與狀態篩選會套用到最近保留的 50 筆工作歷史。按「匯出目前結果」只會把畫面上
182
+ 目前可見的公開中繼資料下載成 JSON;不含 token、任務本文、結果本文、工作目錄與原始 log。
183
+
181
184
  畫面提供英文、日文、韓文、繁體中文與簡體中文。首次載入依瀏覽器語言決定,可用標題列
182
185
  的切換器覆寫,選擇會記在本機。
183
186
 
@@ -228,7 +231,7 @@ omnilane ui stop # 正常停止
228
231
  }
229
232
  ```
230
233
 
231
- Server 提供 `route`,以及一組唯讀查詢工具:`list_lanes`、`explain`、`validate`、`dry_run`、`jobs_list`、`jobs_status`、`jobs_result`、`jobs_stats`、`jobs_audit`、`doctor`。
234
+ Server 提供 `route`,以及一組唯讀查詢工具:`list_lanes`、`explain`、`validate`、`dry_run`、`jobs_list`、`jobs_status`、`jobs_result`、`jobs_stats`、`jobs_recommend`、`jobs_audit`、`doctor`,以及必須明確選用的 `provider_probe`。
232
235
  `route` 預設唯讀 `advise` 模式;選 `work` 的呼叫必須同時提供明確的
233
236
  `workdir`。
234
237
 
@@ -266,7 +269,8 @@ omnilane ui start # 啟動或沿用本機 Live UI,
266
269
  omnilane ui status # 查看 Live UI 是否運作中
267
270
  omnilane ui url # 印出目前通過驗證的本機網址
268
271
  omnilane ui stop # 停止 Live UI
269
- omnilane doctor [--json] # 唯讀檢查路由與本機執行環境
272
+ omnilane doctor [--json] [--strict] [--probe V] [--probe-timeout SEC] # 實際探測必須明確選用
273
+ omnilane benchmark [--json] [--run] [--vendor V] [--cost-per-call V=USD] # 預設只乾跑
270
274
  dispatch.sh [--background] [--dry-run] [--mode advise|work|sysops] [--workdir 目錄]
271
275
  [--vendor V] [--model M] [--effort E] [--timeout SEC] [--job-timeout SEC]
272
276
  通道 "任務" # "-" 表示從 stdin 讀任務
@@ -279,6 +283,7 @@ jobs.sh wait 工作ID [--timeout N] # 工作結束碼;124 逾
279
283
  jobs.sh cancel 工作ID # 停止執行中的工作:整組 SIGTERM,再 SIGKILL
280
284
  jobs.sh rm 工作ID # 刪除單一已完成/已死工作(執行中會被拒絕)
281
285
  jobs.sh [--json] stats [--last N] [--lane L] [--vendor V] # 本機成功率與路由彙整
286
+ jobs.sh [--json] recommend [--last N] [--lane L] [--min-samples N] # 有證據門檻的廠商建議
282
287
  jobs.sh audit [--last N] [--json] # 唯讀檢查工作完整性與隱私
283
288
  jobs.sh prune [--keep N] [--apply] # 預設只預覽;只清理已完成工作
284
289
  omnilane mcp # MCP stdio server(需 Node.js)
@@ -287,6 +292,15 @@ configure.sh # 互動通道選單
287
292
  configure.sh set|get|unset|list|diff LANE [SPEC] # 非互動編輯/檢視 routing.local.yaml
288
293
  ```
289
294
 
295
+ `jobs recommend` 只讀取通過驗證的公開中繼資料與退出碼。候選達到最低樣本數後,
296
+ 依成功率、樣本數、廠商名稱排序;預設至少三筆已完成工作。它不讀任務/結果本文,
297
+ 也不修改路由。
298
+
299
+ `doctor --probe V` 只會做一次有逾時上限的 advise 模式供應商呼叫,回傳可用性、
300
+ 選到的模型、耗時與回應位元組數,不回傳回答本文;未帶 `--probe` 時仍完全離線。
301
+ `benchmark` 使用 `benchmarks/workloads.tsv` 的固定題組,預設只解析路由、不呼叫供應商;
302
+ `--run` 才是實際呼叫閘門,成本總額也只依 `--cost-per-call` 明確提供的估值計算。
303
+
290
304
  **重大決定可以開評審團,不是問一個人。**`arbitrate` 通道**預設關閉**——
291
305
  評審團每評審每輪燒一次額度,所以做成選配。要用就在 `routing.local.yaml`
292
306
  寫 `arbitrate: vote codex,claude,grok -`,或跑設定選單,從
@@ -483,6 +497,33 @@ vendor 一律當成 `work`,而且它只能逐次明確指定,永遠不是 lane
483
497
 
484
498
  ## 📜 版本歷程
485
499
 
500
+ ## v0.14.0 新功能
501
+
502
+ - **依證據產生路由建議**:`jobs recommend` 與 MCP `jobs_recommend` 只用已完成工作的
503
+ 公開中繼資料排序供應商,設有最低樣本門檻,也不會自動修改路由。
504
+ - **選配實際能力探測**:`doctor --probe V` 與 MCP `provider_probe` 可分辨「CLI 已安裝」
505
+ 和「供應商呼叫真的可用」。doctor 預設仍離線,探測報告不含回答本文。
506
+ - **Live Board 歷史搜尋、篩選與匯出**:搜尋與狀態篩選涵蓋最近 50 筆工作;
507
+ 「匯出目前結果」只下載篩選後的公開中繼資料。
508
+ - **可重現的品質/成本基準**:`omnilane benchmark` 內建固定題組,預設不呼叫供應商;
509
+ `--run` 才會實際執行,成本也只依明確提供的 `--cost-per-call` 估值計算。
510
+ - **嚴格安裝驗收**:CI 以隔離環境執行 `omnilane doctor --strict --json`,
511
+ 不接觸供應商也能抓出 runtime 接線不完整。
512
+
513
+ ## v0.13.0 新功能
514
+
515
+ - **`long-context` 改用 AA-LCR 排序**——那是 Artificial Analysis 的長脈絡推理基準,
516
+ 量的正是這條通道的工作。Gemini 3.1 Pro 在該榜領先兩個備援,因此它的第一順位
517
+ 從「未複審」升格為「有據」。
518
+ - **這條通道原本的建議是反的,已移除。** 它原先要人把多跳整合改派給 Claude 候選,
519
+ 依據是上一代模型的二手數字;以第一手當代數據看,Claude 反而是三個候選裡最弱的。
520
+ 備援因此換位,GPT-5.6 Sol (high) 排在 Claude Opus 5 (high) 前面。
521
+ - **`release-audit --require-tag` 會標出沒有 GitHub release 的 tag。** 只警告不中斷,
522
+ `gh` 缺席或離線時自動跳過(CI 仍可跑),且只看最近幾個 tag。
523
+ - **範圍註記:** AA-LCR 測的是 10k–100k token 的文件,所以它能定「長文整合誰強」,
524
+ 定不了 1M 的行為。GPT-5.6 Luna 在該榜居首且便宜得多,**刻意不升**——這條通道的
525
+ 招牌工作是 1M 掃讀,而該基準涵蓋不到。
526
+
486
527
  ## v0.12.0 新功能
487
528
 
488
529
  - **`hardest-coding` 的 Sol 從 `max` 降到 `xhigh`**——在 AA 分檔位的 Coding Index
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.12.0
1
+ 0.14.0
@@ -0,0 +1,4 @@
1
+ # id<TAB>preferred_lane<TAB>weight<TAB>Python regex<TAB>prompt
2
+ exact_alpha consult 1 ^ALPHA\s*$ Return exactly ALPHA and nothing else.
3
+ arithmetic consult 2 ^42\s*$ Return only the integer result of 17 + 25.
4
+ json_contract hard-judgment 2 ^\{"status":"pass","count":3\}\s*$ Return exactly this compact JSON object with the stated key order: {"status":"pass","count":3}
package/bin/omnilane CHANGED
@@ -52,6 +52,13 @@ case "$cmd" in
52
52
  ;;
53
53
  release-audit) exec bash "$REPO/scripts/release-audit.sh" "$@" ;;
54
54
  doctor) exec bash "$REPO/scripts/doctor.sh" "$@" ;;
55
+ benchmark)
56
+ command -v python3 >/dev/null 2>&1 || {
57
+ echo "omnilane: benchmark requires Python 3.9 or newer" >&2
58
+ exit 1
59
+ }
60
+ exec python3 "$REPO/scripts/benchmark.py" "$@"
61
+ ;;
55
62
  ui)
56
63
  command -v python3 >/dev/null 2>&1 || {
57
64
  echo "omnilane: ui requires Python 3.9 or newer" >&2
@@ -68,11 +75,12 @@ omnilane — one routing table, every harness
68
75
  omnilane list effective routing table
69
76
  omnilane route [--vendor V] [flags] LANE "TASK"
70
77
  dispatch or consult a model
71
- omnilane jobs [--json] COMMAND [ARGS] list, status, result, stats, wait, or audit
78
+ omnilane jobs [--json] COMMAND [ARGS] list, status, result, stats, recommend, wait, or audit
72
79
  omnilane mcp start the MCP stdio server
73
80
  omnilane completion bash|zsh|fish print a shell completion script
74
81
  omnilane release-audit [flags] offline, read-only release gate
75
- omnilane doctor [--json] read-only local health report
82
+ omnilane doctor [--json] [--strict] [--probe V] local health / opt-in live probe
83
+ omnilane benchmark [--json] [--run] [--vendor V] fixed quality/cost comparison
76
84
  omnilane ui start|status|url|stop
77
85
  omnilane configure interactive lane menu
78
86
  EOF
package/bin/omnilane-mcp CHANGED
@@ -10,6 +10,8 @@ const ROOT = path.resolve(__dirname, '..');
10
10
  const DISPATCH_SCRIPT = path.join(ROOT, 'scripts', 'dispatch.sh');
11
11
  const JOBS_SCRIPT = path.join(ROOT, 'scripts', 'jobs.sh');
12
12
  const DOCTOR_SCRIPT = path.join(ROOT, 'scripts', 'doctor.sh');
13
+ const PROVIDER_PROBE_SCRIPT = process.env.OMNILANE_PROVIDER_PROBE_SCRIPT ||
14
+ path.join(ROOT, 'scripts', 'provider-probe.sh');
13
15
  const LATEST_PROTOCOL_VERSION = '2025-11-25';
14
16
  const SUPPORTED_PROTOCOL_VERSIONS = new Set([
15
17
  '2025-11-25',
@@ -285,6 +287,37 @@ const tools = [
285
287
  openWorldHint: false,
286
288
  },
287
289
  },
290
+ {
291
+ name: 'provider_probe',
292
+ description: 'Explicitly invoke one configured provider with a bounded fixed prompt to verify live inference. Incurs one provider call; never returns the provider response.',
293
+ inputSchema: {
294
+ type: 'object',
295
+ required: ['vendor'],
296
+ properties: {
297
+ vendor: {
298
+ type: 'string',
299
+ enum: ['codex', 'claude', 'grok', 'gemini', 'kimi', 'qwen', 'opencode', 'openrouter', 'deepseek', 'zai', 'mistral', 'groq', 'cerebras'],
300
+ },
301
+ timeout: {
302
+ type: 'integer',
303
+ minimum: 1,
304
+ maximum: 300,
305
+ default: 30,
306
+ },
307
+ json: {
308
+ type: 'boolean',
309
+ default: true,
310
+ },
311
+ },
312
+ additionalProperties: false,
313
+ },
314
+ annotations: {
315
+ readOnlyHint: true,
316
+ destructiveHint: false,
317
+ idempotentHint: false,
318
+ openWorldHint: true,
319
+ },
320
+ },
288
321
  {
289
322
  name: 'jobs_stats',
290
323
  description: 'Aggregate local background-job outcomes and lane/vendor distribution from bounded public metadata. Never reads task or result bodies.',
@@ -311,6 +344,45 @@ const tools = [
311
344
  openWorldHint: false,
312
345
  },
313
346
  },
347
+ {
348
+ name: 'jobs_recommend',
349
+ description: 'Recommend a vendor per lane from bounded local completed-job outcomes. Read-only, evidence-gated, and never reads task or result bodies.',
350
+ inputSchema: {
351
+ type: 'object',
352
+ properties: {
353
+ last: {
354
+ type: 'integer',
355
+ minimum: 1,
356
+ maximum: 10000,
357
+ description: 'Limit analysis to the most recent N jobs.',
358
+ },
359
+ lane: {
360
+ type: 'string',
361
+ pattern: '^[a-z][a-z0-9-]*$',
362
+ description: 'Optionally analyze one lane.',
363
+ },
364
+ min_samples: {
365
+ type: 'integer',
366
+ minimum: 1,
367
+ maximum: 1000,
368
+ default: 3,
369
+ description: 'Completed samples required before a vendor is eligible for recommendation.',
370
+ },
371
+ json: {
372
+ type: 'boolean',
373
+ default: false,
374
+ description: 'Return the versioned JSON envelope instead of the human report.',
375
+ },
376
+ },
377
+ additionalProperties: false,
378
+ },
379
+ annotations: {
380
+ readOnlyHint: true,
381
+ destructiveHint: false,
382
+ idempotentHint: true,
383
+ openWorldHint: false,
384
+ },
385
+ },
314
386
  {
315
387
  name: 'jobs_audit',
316
388
  description: 'Bounded read-only integrity and privacy scan of the local job store. Reports findings without printing task or result content.',
@@ -435,6 +507,24 @@ function validateJsonOnlyArguments(args) {
435
507
  return null;
436
508
  }
437
509
 
510
+ function validateProviderProbeArguments(args) {
511
+ const error = validationError(args, ['vendor', 'timeout', 'json']);
512
+ if (error) return error;
513
+ const vendors = new Set([
514
+ 'codex', 'claude', 'grok', 'gemini', 'kimi', 'qwen', 'opencode',
515
+ 'openrouter', 'deepseek', 'zai', 'mistral', 'groq', 'cerebras',
516
+ ]);
517
+ if (typeof args.vendor !== 'string' || !vendors.has(args.vendor)) {
518
+ return 'vendor must name one probe-capable provider';
519
+ }
520
+ if (OWN(args, 'timeout') &&
521
+ (!Number.isInteger(args.timeout) || args.timeout < 1 || args.timeout > 300)) {
522
+ return 'timeout must be an integer from 1 to 300';
523
+ }
524
+ if (OWN(args, 'json') && typeof args.json !== 'boolean') return 'json must be a boolean';
525
+ return null;
526
+ }
527
+
438
528
  function validateJobsQueryArguments(args) {
439
529
  const error = validationError(args, ['last', 'json']);
440
530
  if (error) return error;
@@ -445,6 +535,23 @@ function validateJobsQueryArguments(args) {
445
535
  return null;
446
536
  }
447
537
 
538
+ function validateJobsRecommendArguments(args) {
539
+ const error = validationError(args, ['last', 'lane', 'min_samples', 'json']);
540
+ if (error) return error;
541
+ if (OWN(args, 'last') && (!Number.isInteger(args.last) || args.last < 1 || args.last > 10000)) {
542
+ return 'last must be an integer from 1 to 10000';
543
+ }
544
+ if (OWN(args, 'lane') && (typeof args.lane !== 'string' || !LANE_PATTERN.test(args.lane))) {
545
+ return 'lane must match ^[a-z][a-z0-9-]*$';
546
+ }
547
+ if (OWN(args, 'min_samples') &&
548
+ (!Number.isInteger(args.min_samples) || args.min_samples < 1 || args.min_samples > 1000)) {
549
+ return 'min_samples must be an integer from 1 to 1000';
550
+ }
551
+ if (OWN(args, 'json') && typeof args.json !== 'boolean') return 'json must be a boolean';
552
+ return null;
553
+ }
554
+
448
555
  function validateExplainArguments(args) {
449
556
  const error = validationError(args, ['lane', 'json']);
450
557
  if (error) return error;
@@ -645,6 +752,14 @@ async function callTool(name, args) {
645
752
  const argv = args.json === true ? ['--json'] : [];
646
753
  return runToolScript('doctor', DOCTOR_SCRIPT, argv);
647
754
  }
755
+ if (name === 'provider_probe') {
756
+ const error = validateProviderProbeArguments(args);
757
+ if (error) return toolError(error);
758
+ const argv = ['--vendor', args.vendor];
759
+ if (OWN(args, 'timeout')) argv.push('--timeout', String(args.timeout));
760
+ if (args.json !== false) argv.push('--json');
761
+ return runToolScript('provider_probe', PROVIDER_PROBE_SCRIPT, argv);
762
+ }
648
763
  if (name === 'jobs_stats' || name === 'jobs_audit') {
649
764
  const error = validateJobsQueryArguments(args);
650
765
  if (error) return toolError(error);
@@ -654,6 +769,17 @@ async function callTool(name, args) {
654
769
  if (OWN(args, 'last')) argv.push('--last', String(args.last));
655
770
  return runToolScript(name, JOBS_SCRIPT, argv);
656
771
  }
772
+ if (name === 'jobs_recommend') {
773
+ const error = validateJobsRecommendArguments(args);
774
+ if (error) return toolError(error);
775
+ const argv = [];
776
+ if (args.json === true) argv.push('--json');
777
+ argv.push('recommend');
778
+ if (OWN(args, 'last')) argv.push('--last', String(args.last));
779
+ if (OWN(args, 'lane')) argv.push('--lane', args.lane);
780
+ if (OWN(args, 'min_samples')) argv.push('--min-samples', String(args.min_samples));
781
+ return runToolScript(name, JOBS_SCRIPT, argv);
782
+ }
657
783
  throw new RpcError(-32602, `Unknown tool: ${name}`);
658
784
  }
659
785