omnilane 0.41.1 → 0.42.2
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/.claude-plugin/marketplace.json +4 -4
- package/.claude-plugin/plugin.json +2 -2
- package/CHANGELOG.md +38 -1
- package/README.ja.md +27 -2
- package/README.ko.md +27 -2
- package/README.md +89 -16
- package/README.zh-CN.md +27 -2
- package/README.zh-TW.md +69 -11
- package/VERSION +1 -1
- package/config/aa-model-policy.json +3046 -0
- package/docs/completion-wakeup.md +126 -0
- package/docs/native-executor.md +264 -0
- package/docs/release-notes-0.42.2.md +31 -0
- package/hooks/routing-instruction.md +101 -40
- package/package.json +6 -2
- package/plugin.json +2 -2
- package/routing.yaml +7 -7
- package/scripts/completion-wakeup.py +390 -0
- package/scripts/dispatch.sh +240 -18
- package/scripts/jobs.sh +58 -15
- package/scripts/lib/aa_policy.py +482 -0
- package/scripts/lib/aa_retry.py +77 -0
- package/scripts/lib/common.sh +59 -0
- package/scripts/lib/job-worker.sh +2 -0
- package/scripts/lib/native.py +507 -0
- package/scripts/runners/run-grok.sh +16 -2
- package/scripts/runners/run-vote.sh +3 -0
- package/skills/omnilane/SKILL.md +120 -31
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# 完成續驗橋接(Codex heartbeat)
|
|
2
|
+
|
|
3
|
+
協定版本:2026-09-07。
|
|
4
|
+
|
|
5
|
+
`scripts/completion-wakeup.py` 是獨立命令列工具:
|
|
6
|
+
追蹤明確登錄的 CLI 工作、發出一次有效領取權、記錄主控送達與驗收。
|
|
7
|
+
它不呼叫模型、不建立排程、不讀工作輸出,也不保證 app 已喚醒。
|
|
8
|
+
真正喚醒由主控透過 `mcp__codex_app__automation_update` 註冊的 heartbeat 負責。
|
|
9
|
+
這是排程輪詢,不是即時推播;本機離線、排程延遲與 app 狀態都會影響送達。
|
|
10
|
+
|
|
11
|
+
## 登錄與身分
|
|
12
|
+
|
|
13
|
+
每個 host/thread 只有一份 registry,同 run 可追加工作並重用 automation ID。
|
|
14
|
+
主控傳入的 thread ID 必須來自 app 的實際任務,不能把 omnilane 自身 thread 名稱代入。
|
|
15
|
+
只有一個 active run;不同 run 會拒絕。既有 run 已 closed 時,新 run 的 prepare 會先把完整舊紀錄
|
|
16
|
+
存入私有 history,再建立 pending 的新紀錄;舊 automation ID、租約、事件與 adoption 不沿用。
|
|
17
|
+
舊 run 的 poll/ack 會拒絕,不會領取新 run 的事件。原本 active/pending 的 run 從不默默被取代。
|
|
18
|
+
同一 host/thread 歷史曾使用的 run_id 永不重用,以免舊 heartbeat 命令在後續同名輪次復活。
|
|
19
|
+
歷史的 accepted receipt 留在原紀錄,不沿用為新 run 的驗收證據;請為每輪指定全新的 run_id。
|
|
20
|
+
這是工作流程契約,不是防止同使用者程序偽造參數的安全隔離。
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
PY=python3
|
|
24
|
+
SCRIPT=/absolute/repo/scripts/completion-wakeup.py
|
|
25
|
+
BIND=(--thread-id CONTROLLER_THREAD --host-id local --run-id RUN_ID)
|
|
26
|
+
$PY "$SCRIPT" prepare "${BIND[@]}" \
|
|
27
|
+
--workdir /absolute/repo --job JOB_ID --ttl-seconds 3600
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
工作必須已存在於 `~/.omnilane/jobs/JOB_ID`,且 `meta.json` 身分與工作目錄相符。
|
|
31
|
+
若 metadata 的 foreman_session 非空,表示另有原主控身分,單靠 allowlist 不足以收錄。
|
|
32
|
+
該欄位來自 Claude 程序綁定,並非 Codex thread ID;程式不硬比兩者。
|
|
33
|
+
必須取得操作者明示採用後,把確認整理為 scoped adoption receipt,prepare 加 `--adoption-evidence`。
|
|
34
|
+
未提供會回 `adoption_required:JOB_ID:IDENTITY_SHA256`,只透露工作指紋,不輸出原 session 值。
|
|
35
|
+
空 foreman_session 仍可由主控的明確 allowlist 直接登錄。
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"source": "operator_adoption",
|
|
40
|
+
"operator_confirmed": true,
|
|
41
|
+
"controller_thread_id": "CONTROLLER_THREAD",
|
|
42
|
+
"controller_host_id": "local",
|
|
43
|
+
"run_id": "RUN_ID",
|
|
44
|
+
"job_identity_sha256": {"JOB_ID": "IDENTITY_SHA256"}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
此 receipt 必須反映已取得的明示確認,不是讓工作者自己填 true 自我授權。
|
|
49
|
+
程式驗其 run/thread/host/job/fingerprint 並保存 receipt 雜湊;這是可稽核聲明,不是 OS 身分認證。
|
|
50
|
+
新 run 不沿用舊 run 的 adoption;metadata 身分改動後舊 adoption 也失效。
|
|
51
|
+
可用 `--home /absolute/private/path` 指定測試儲存;所有命令都要使用同一 home/binding。
|
|
52
|
+
prepare 回傳工具名稱、tool_args(heartbeat/create 或 update、prompt、targetThreadId、status),
|
|
53
|
+
以及 schedule_request。主控將工具接受的排程格式補入 rrule,保留既有通知偏好後呼叫工具。
|
|
54
|
+
沒有直接寫 automation 設定檔,也沒有把 pending 當 active。
|
|
55
|
+
|
|
56
|
+
工具成功後,由主控將實際結果整理成最小 JSON receipt(不要包含憑證或私人訊息):
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"source": "automation_update",
|
|
61
|
+
"automation_id": "AUTOMATION_ID",
|
|
62
|
+
"controller_thread_id": "CONTROLLER_THREAD",
|
|
63
|
+
"controller_host_id": "local",
|
|
64
|
+
"status": "ACTIVE",
|
|
65
|
+
"effective_interval_seconds": 60
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
$PY "$SCRIPT" record-registration "${BIND[@]}" \
|
|
71
|
+
--automation-id AUTOMATION_ID --evidence /absolute/registration-receipt.json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
支持綁入已存在的 automation。receipt 是主控對工具結果的具名聲明,腳本驗格式/綁定/雜湊,
|
|
75
|
+
不自行查 app;輸出明示 caller-attested,不宣稱獨立確認排程。註冊不等於 delivered。
|
|
76
|
+
|
|
77
|
+
## 排程回合接續驗收
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
$PY "$SCRIPT" poll "${BIND[@]}"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
僅 registered、未過期的工作會得到 events。pending/closed 不領取,expired 要求停用。
|
|
84
|
+
每事件含 event_key、job_id、exit_code、claim_token、lease_until。
|
|
85
|
+
空 events 不表示已完成:可能仍執行中或已有領取租約;以 needs_disable 與 errors 判斷。
|
|
86
|
+
poll 預設租約 900 秒,可用 `--lease-seconds` 調整至最多一天;有效租約期間第二次 poll 不重複領取。
|
|
87
|
+
租約過期可以重播且換 token,舊 token 失效。工作內容從未作為可執行通知提示。
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
$PY "$SCRIPT" ack-delivered "${BIND[@]}" --event-key EVENT_KEY --claim-token CLAIM_TOKEN
|
|
91
|
+
# 主控現在讀相關產物、執行原任務驗證,再留下精簡證據檔。
|
|
92
|
+
$PY "$SCRIPT" ack-accepted "${BIND[@]}" --event-key EVENT_KEY --claim-token CLAIM_TOKEN \
|
|
93
|
+
--result PASS --evidence /absolute/verification-evidence.md
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
result 支援 PASS/FAIL/PARTIAL/BLOCKED;非零工作退出碼也可送達並驗收為 FAIL。
|
|
97
|
+
accepted 表示主控已作驗收判定,**不是固定等同 PASS**。沒有 delivered 就拒絕 accepted。
|
|
98
|
+
同一租約內相同 acknowledgement 可重試;驗收結果或證據衝突被拒絕。
|
|
99
|
+
binding 或終態退出碼在 poll 後改動,ack 也會拒絕。
|
|
100
|
+
|
|
101
|
+
## 停用
|
|
102
|
+
|
|
103
|
+
所有登錄工作均已作驗收判定時,poll 回 needs_disable=true。
|
|
104
|
+
主控先以 automation_update 停用現有 heartbeat,工具確認後寫同樣綁定、status=PAUSED 的 receipt:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
$PY "$SCRIPT" closed "${BIND[@]}" --automation-id AUTOMATION_ID \
|
|
108
|
+
--evidence /absolute/paused-receipt.json
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
未驗收完的使用者停止用 `--close-reason stopped`;真正到期用 `--close-reason expired`。
|
|
112
|
+
預設 completed 會檢查所有工作已判定。closed 命令本身不會停用 app 排程。
|
|
113
|
+
使用者先前的停止/重開機要求與新一輪授權仍由主控處理,不自動延長期限。
|
|
114
|
+
|
|
115
|
+
## 資料與限制
|
|
116
|
+
|
|
117
|
+
- 僅讀 CLI 的 `meta.json` 以及 `exit`;不讀 inbox tail、out.txt、events、task、native.json、Codex 私人對話。
|
|
118
|
+
- 凍結 metadata 的 lane/vendor/model/mode/workdir/foreman_session/started;忽略其他可變欄位,不因 finished 更新誤拒。
|
|
119
|
+
- native 工作明確拒絕,使用原生完成通道;後續可接獨立公共終態 receipt,不應掃描 private native state。
|
|
120
|
+
- 儲存於 `~/.omnilane/wakeups`,目錄 0700、檔案 0600,拒絕 symlink、非檔案、不同擁有者及超大紀錄。
|
|
121
|
+
- 核心鎖使用 flock,程序結束自動釋放;registry 以同目錄暫存檔及原子替換發布。
|
|
122
|
+
- 至少一次交付與冪等驗收,不宣稱 exactly-once;租約期間不得啟動第二份驗收。
|
|
123
|
+
- 一個 controller registry 最多 100 個工作;metadata 綁定錯誤會出 errors,不默默接受替代工作。
|
|
124
|
+
- 待真實排程回合在同主控任務送達、產物驗收、停止確認後,才可聲稱端到端 PASS。
|
|
125
|
+
|
|
126
|
+
驗證命令(從 repo 根目錄執行):`python3 -m unittest discover -s tests -p test_completion_wakeup.py`。
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# Native executor protocol (v1)
|
|
2
|
+
|
|
3
|
+
`native` means a **caller-owned agent tool**, not a shell executable. Omnilane
|
|
4
|
+
resolves a lane, checks explicitly supplied capabilities, and emits a pending
|
|
5
|
+
handoff. The host executes the declared new/reuse strategy and ingests its actual result separately.
|
|
6
|
+
Creating a handoff is not task success. Native delegation still counts as
|
|
7
|
+
delegation when commander and worker use the same exact model.
|
|
8
|
+
|
|
9
|
+
## Selection and terminal compatibility
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
# Standalone terminal: no native capability context, legacy CLI selection.
|
|
13
|
+
omnilane route --dry-run hardest-coding "Review the change"
|
|
14
|
+
omnilane route --executor cli --dry-run hardest-coding "Review the change"
|
|
15
|
+
|
|
16
|
+
# Host-generated capability file: native when ALL requirements match.
|
|
17
|
+
omnilane route --executor auto --native-context /absolute/capability.json \
|
|
18
|
+
--workdir /absolute/repo --dry-run hardest-coding "Review the change"
|
|
19
|
+
|
|
20
|
+
# Fail closed instead of falling back. JSON on stdout; no provider is called.
|
|
21
|
+
omnilane route --executor native --native-context /absolute/capability.json \
|
|
22
|
+
--workdir /absolute/repo hardest-coding "Review the change"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Native-aware selection fixes the first configured lane candidate (or the
|
|
26
|
+
explicit `--vendor` row) **before** checking native or CLI availability.
|
|
27
|
+
`--model` and `--effort` override that row without renaming either value. No
|
|
28
|
+
model aliases/family inference or vendor substitution are performed. A native
|
|
29
|
+
rejection in `auto` may use only that same resolved target's CLI; if it is
|
|
30
|
+
missing, exit 4 rather than walk another vendor's fallback chain. Without a
|
|
31
|
+
context, `auto` and forced `cli` preserve the historical available-CLI chain.
|
|
32
|
+
`--executor cli` ignores the native context. CLI plans and metadata include
|
|
33
|
+
`executor=cli` and a reason; native plans are JSON.
|
|
34
|
+
|
|
35
|
+
`--executor native` returns exit 2 for missing/incompatible capability context.
|
|
36
|
+
Malformed contexts are errors even in `auto`, not invitations to call a CLI.
|
|
37
|
+
Native protocol support requires Python 3.9+ on the local host; the unchanged
|
|
38
|
+
terminal path does not acquire that dependency. `--list` / `--explain` retain
|
|
39
|
+
their legacy CLI-availability meaning and do not advertise native readiness.
|
|
40
|
+
|
|
41
|
+
## Capability context
|
|
42
|
+
|
|
43
|
+
The caller constructs this object from the **currently exposed tool contract**
|
|
44
|
+
and its known runtime, not credentials, installed binaries, environment sniffing,
|
|
45
|
+
or model family guesses. These example model/harness values are slots, not a
|
|
46
|
+
catalog. Paths must be existing absolute directories (canonicalized for exact
|
|
47
|
+
comparison; a parent directory does not grant child workdirs).
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"schema_version": 1,
|
|
52
|
+
"harness": "HARNESS_FROM_RUNTIME",
|
|
53
|
+
"vendor": "codex",
|
|
54
|
+
"current_model": "MODEL_FROM_RUNTIME",
|
|
55
|
+
"requirements": {
|
|
56
|
+
"tools": [],
|
|
57
|
+
"isolation": "shared-inherited",
|
|
58
|
+
"lifecycle": "single-shot"
|
|
59
|
+
},
|
|
60
|
+
"capabilities": [{
|
|
61
|
+
"model": "EXACT_SUPPORTED_MODEL",
|
|
62
|
+
"efforts": ["EXACT_SUPPORTED_EFFORT"],
|
|
63
|
+
"modes": ["advise"],
|
|
64
|
+
"workdirs": ["/absolute/repo"],
|
|
65
|
+
"tools": [],
|
|
66
|
+
"isolations": ["shared-inherited"],
|
|
67
|
+
"lifecycles": ["single-shot"]
|
|
68
|
+
}]
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Every field shown except `current_model` is required. Capability rows describe
|
|
73
|
+
joint constraints; permission from separate rows is never combined. All arrays
|
|
74
|
+
except `tools` must be nonempty. `current_model` is only needed when the routed
|
|
75
|
+
model is absent or `-`; when the route explicitly selects an exact supported
|
|
76
|
+
model, the caller may omit an unknown current model. The effort string is
|
|
77
|
+
matched exactly; an absent effort or `-` is unknown, so native rejects it until
|
|
78
|
+
the caller supplies a known explicit `--effort`. Model names are never
|
|
79
|
+
hardcoded in the engine.
|
|
80
|
+
|
|
81
|
+
Codex `collaboration.spawn_agent` exposes no sandbox, tool allowlist, or
|
|
82
|
+
workdir restriction parameter and inherits the parent's tool/filesystem access.
|
|
83
|
+
Its honest native capability uses `shared-inherited` in both the request and the
|
|
84
|
+
same matching capability row. `tools: []` means no tool restriction is
|
|
85
|
+
requested or advertised. `advise` and `work` remain task intent; the matched
|
|
86
|
+
workdir is task context, not an OS boundary. Requests for hard `read-only`,
|
|
87
|
+
`workspace-write`, or any other unsupported isolation never become shared
|
|
88
|
+
native jobs: `auto` stays on the same resolved model through CLI, while forced
|
|
89
|
+
native fails closed.
|
|
90
|
+
|
|
91
|
+
Native supports only a caller-supervised single task. `--background`, explicit
|
|
92
|
+
`--live` / `--single-shot`, `--thread`, `sysops`, explicit/environment whole-job
|
|
93
|
+
or idle watchdogs, vote/multi-round and `exec` arbitration paths stay CLI or
|
|
94
|
+
reject forced native. The handoff's `timeout` is a caller-enforced deadline,
|
|
95
|
+
not a shell watchdog. Native has no durable worker, FIFO, implicit follow-up,
|
|
96
|
+
CLI lock, scheduling, or inherited named session. Supplying a context does not
|
|
97
|
+
change `routing.yaml`, `routing.local.yaml`, or host configuration.
|
|
98
|
+
|
|
99
|
+
## Handoff, completion and cancellation
|
|
100
|
+
|
|
101
|
+
Native route stdout is one JSON object: `schema_version`, `executor`,
|
|
102
|
+
`executor_reason`, `vendor`, `model`, `effort`, `harness`, `lane`, `task`,
|
|
103
|
+
`mode`, `workdir`, `requirements`, `timeout`, `worker_contract`, `job_id`,
|
|
104
|
+
`task_id`, `agent_id`, `state`, `provider_invoked`, `job_state_created`.
|
|
105
|
+
Normal routing returns `state=pending`, equal task/job IDs and null agent ID.
|
|
106
|
+
Dry run returns `state=planned`, null IDs and creates neither job store nor job.
|
|
107
|
+
Dry run does not read task stdin. It never spawns or calls a provider.
|
|
108
|
+
|
|
109
|
+
`worker_contract` records `no_nested_dispatch`, the matched
|
|
110
|
+
`shared-inherited` isolation, that mode is task intent, and that the caller owns
|
|
111
|
+
deadline enforcement. It does not claim tool or filesystem restriction.
|
|
112
|
+
|
|
113
|
+
The host invokes its real agent tool with the resolved model and effort, then
|
|
114
|
+
passes the workdir, mode, task, and deadline as task intent rather than claimed
|
|
115
|
+
tool or filesystem enforcement. With an explicit model override, Codex must use
|
|
116
|
+
`fork_turns: "none"` (or a bounded positive history count), never
|
|
117
|
+
`fork_turns: "all"`:
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
collaboration.spawn_agent({
|
|
121
|
+
task_name: "native_shared_smoke",
|
|
122
|
+
fork_turns: "none",
|
|
123
|
+
model: handoff.model,
|
|
124
|
+
reasoning_effort: handoff.effort,
|
|
125
|
+
message: "Shared/inherited access. Do not delegate. Intended workdir: " +
|
|
126
|
+
handoff.workdir + ". Deadline: " + handoff.timeout +
|
|
127
|
+
" seconds. Task: " + handoff.task
|
|
128
|
+
})
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The call does not establish a filesystem boundary. The parent keeps the actual
|
|
132
|
+
agent ID, waits for the real outcome, independently verifies the public result,
|
|
133
|
+
and only then writes **public, sanitized** completion input:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"schema_version": 1,
|
|
138
|
+
"job_id": "JOB_ID_FROM_HANDOFF",
|
|
139
|
+
"agent_id": "ACTUAL_AGENT_ID",
|
|
140
|
+
"runtime": {
|
|
141
|
+
"vendor": "codex",
|
|
142
|
+
"model": "ACTUAL_EXACT_MODEL",
|
|
143
|
+
"effort": "ACTUAL_EFFORT",
|
|
144
|
+
"harness": "ACTUAL_HARNESS",
|
|
145
|
+
"backend": "ACTUAL_AGENT_TOOL_BACKEND"
|
|
146
|
+
},
|
|
147
|
+
"outcome": "success",
|
|
148
|
+
"result": "Public result summary, not raw logs",
|
|
149
|
+
"evidence": ["Public command/result or artifact reference"]
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
omnilane jobs --json status JOB_ID
|
|
155
|
+
omnilane jobs --json complete-native JOB_ID /absolute/completion.json
|
|
156
|
+
omnilane jobs --json result JOB_ID
|
|
157
|
+
omnilane jobs --json list --status pending
|
|
158
|
+
omnilane jobs --json cancel JOB_ID
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The reusable `jobs complete-native` interface checks the actual runtime's
|
|
162
|
+
vendor/model/effort/harness against the resolved request, requires agent ID,
|
|
163
|
+
backend, outcome (`success` or `failure`), result and nonempty evidence, and
|
|
164
|
+
rejects malformed/extra fields, symlinks, oversized inputs and duplicate JSON
|
|
165
|
+
keys. Missing/invalid/duplicate completions leave state unchanged. Completion
|
|
166
|
+
and cancellation share a per-job lock and an atomic state replacement.
|
|
167
|
+
|
|
168
|
+
`pending -> completed` exposes `state=done`, `native_state=completed`, exit 0
|
|
169
|
+
for success or 1 for failure. Ingestion itself returns 0 for a valid failure
|
|
170
|
+
record; `jobs result` returns the recorded exit code. `pending -> cancelled`
|
|
171
|
+
records exit 143 and permanently rejects later completion. Neither transition
|
|
172
|
+
signals a PID. If an agent was already spawned, **the caller must cancel it
|
|
173
|
+
using that agent tool separately**; cancelling the record cannot stop it.
|
|
174
|
+
|
|
175
|
+
Data lives under `$OMNILANE_HOME/jobs/ID/`: `task.txt`, `meta.json`,
|
|
176
|
+
`native.json` and `native.lock`. Creation writes all four 0600 files inside a
|
|
177
|
+
0700 hidden same-filesystem staging directory, then atomically renames it to the
|
|
178
|
+
final ID under a private publication lock. Listing only accepts final ID names,
|
|
179
|
+
so it never observes construction or an interrupted hidden stage. Normal
|
|
180
|
+
failures clean only the creator's own stage; collisions leave the existing
|
|
181
|
+
final directory untouched. The context itself and raw provider logs are not
|
|
182
|
+
stored. Completion is a
|
|
183
|
+
caller attestation, not independent backend authentication or proof that the
|
|
184
|
+
model honored the task; the parent still verifies evidence. Do not submit
|
|
185
|
+
tokens, cookies, credential/session/cache values or raw logs in any public field.
|
|
186
|
+
|
|
187
|
+
Only `list`, `status`, `result`, `cancel`, `complete-native` integrate native
|
|
188
|
+
jobs. Native `send`, `watch`, `close`, `wait`, `retry`, `tail`, and `rm` reject;
|
|
189
|
+
inspect status while the host owns execution. Native records do not have CLI
|
|
190
|
+
exit markers and are not included in completed-CLI stats/recommend/prune.
|
|
191
|
+
Do not use CLI-only UI/audit/goal-loop summaries as native acceptance evidence.
|
|
192
|
+
|
|
193
|
+
## Explicit existing-agent reuse(明示重用)
|
|
194
|
+
|
|
195
|
+
協定版本:2026-09-07。
|
|
196
|
+
Default `agent_strategy` is `new`; exhausted creation capacity never silently becomes reuse.
|
|
197
|
+
Explicit `reuse` keeps the existing context and uses caller-owned `collaboration.followup_task`,
|
|
198
|
+
not `collaboration.spawn_agent`. This remains one supervised task, not an automatic loop.
|
|
199
|
+
|
|
200
|
+
Reuse extends the v1 capability object (values must be caller-observed, not inferred):
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
{
|
|
204
|
+
"schema_version": 1,
|
|
205
|
+
"harness": "codex",
|
|
206
|
+
"vendor": "codex",
|
|
207
|
+
"current_model": "gpt-6-astra",
|
|
208
|
+
"current_effort": "medium",
|
|
209
|
+
"agent_strategy": "reuse",
|
|
210
|
+
"preserve_existing_context": true,
|
|
211
|
+
"new_agent_capacity": "exhausted",
|
|
212
|
+
"existing_agent": {
|
|
213
|
+
"agent_id": "/root/EXISTING_AGENT",
|
|
214
|
+
"vendor": "codex",
|
|
215
|
+
"model": "gpt-6-astra",
|
|
216
|
+
"effort": "medium",
|
|
217
|
+
"harness": "codex",
|
|
218
|
+
"state": "idle",
|
|
219
|
+
"observed_by": "caller",
|
|
220
|
+
"evidence": ["Caller-observed creation configuration and current idle state"]
|
|
221
|
+
},
|
|
222
|
+
"requirements": {"tools": [], "isolation": "shared-inherited", "lifecycle": "single-shot"},
|
|
223
|
+
"capabilities": [{
|
|
224
|
+
"model": "gpt-6-astra", "efforts": ["medium"], "modes": ["advise"],
|
|
225
|
+
"workdirs": ["/absolute/repo"], "tools": [],
|
|
226
|
+
"isolations": ["shared-inherited"], "lifecycles": ["single-shot"],
|
|
227
|
+
"agent_strategy": "reuse", "existing_agent_id": "/root/EXISTING_AGENT"
|
|
228
|
+
}]
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Reuse requires routed vendor/model/effort/harness and existing runtime to match exactly.
|
|
233
|
+
`current_model` and `current_effort` must match too; capability rows/agent IDs are never combined.
|
|
234
|
+
The idle declaration is caller evidence, not provider authentication or a reservation. Recheck idle
|
|
235
|
+
immediately before followup; the tool may still fail. Model self-description is not creation evidence.
|
|
236
|
+
Retained context may contain old instructions, so supply the new task boundary and existing AA child contract.
|
|
237
|
+
|
|
238
|
+
Missing evidence is malformed context. Busy/unknown state, missing preservation, identity/strategy mismatch,
|
|
239
|
+
hard isolation or unsupported lifecycle yield no reuse handoff. Forced native rejects; auto may choose
|
|
240
|
+
only the original exact target's CLI for a well-formed but incompatible context.
|
|
241
|
+
`new_agent_capacity` accepts available/exhausted/unknown; exhausted rejects new native selection.
|
|
242
|
+
Unknown retains the old pending-handoff behavior, never asserts that an agent successfully started.
|
|
243
|
+
|
|
244
|
+
Plans/status/results preserve `agent_strategy`, `existing_agent_id`, `preserve_existing_context`.
|
|
245
|
+
Pending reuse `agent_id` identifies the existing target, not proof followup ran.
|
|
246
|
+
`worker_contract.backend` is `collaboration.followup_task`; `reuse_observation` records the caller's evidence.
|
|
247
|
+
|
|
248
|
+
```javascript
|
|
249
|
+
collaboration.followup_task({
|
|
250
|
+
target: handoff.existing_agent_id,
|
|
251
|
+
message: "Keep existing context. Shared/inherited access; do not delegate. " +
|
|
252
|
+
"Apply the handoff's AA child context and task boundary. " + handoff.task
|
|
253
|
+
})
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
After real response and independent verification, ingest the normal completion object with
|
|
257
|
+
`agent_strategy: "reuse"`, exact existing `agent_id`, and runtime backend `collaboration.followup_task`.
|
|
258
|
+
Different strategy/ID/backend is rejected without completing the job; duplicate completion is rejected.
|
|
259
|
+
New completions may omit strategy or supply `new`, but must not claim the followup backend.
|
|
260
|
+
Both strategies retain AA preflight, approved original registry bytes, child context, atomic publication,
|
|
261
|
+
and per-job completion/cancellation locking. Reuse adds no automatic creation, permission upgrade or service.
|
|
262
|
+
|
|
263
|
+
Offline coverage: `TMPDIR="$PWD/.native-test-artifacts/tmp" python3
|
|
264
|
+
tests/test_native_executor.py`. Those fixtures are not a live native smoke.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Omnilane 0.42.2
|
|
2
|
+
|
|
3
|
+
This patch repairs the Grok single-shot reasoning-effort transport. It does not raise caller scores or remove the exact-AA downward-delegation gate.
|
|
4
|
+
|
|
5
|
+
## Changes
|
|
6
|
+
|
|
7
|
+
- Explicit Grok effort is forwarded as `--reasoning-effort VALUE`. The supported selector spellings are `low`, `medium`, `high`, and `xhigh`; invalid values fail before provider startup.
|
|
8
|
+
- Grok 4.6 entries in the default routing table explicitly select `high`.
|
|
9
|
+
- A scored Grok target requires a verified `cli_reasoning_effort` mapping and the exact `--reasoning-effort` flag. The existing host-local transport overlay validates host, snapshot, exact identity, evidence hashes, vendor, flag, and effort.
|
|
10
|
+
- Explicit effort on the live ACP path is rejected rather than discarded. This release does not add Grok work-mode network isolation on macOS.
|
|
11
|
+
|
|
12
|
+
## Verification boundary
|
|
13
|
+
|
|
14
|
+
The frozen AA registry and its approved SHA remain unchanged. Transport evidence belongs to the local host; the package does not ship a blanket assertion that every Grok model/effort combination is verified.
|
|
15
|
+
|
|
16
|
+
`request-selector-contract` proves how Omnilane selects the model and effort. It does not independently authenticate the upstream model's internal identity: `upstream_identity_verified` remains false. A successful reply alone is not an identity attestation.
|
|
17
|
+
|
|
18
|
+
For an existing local overlay, use `selector_type: cli_reasoning_effort`, `cli_flag: --reasoning-effort`, and matching model/effort identity only after checking the installed CLI and runner. Retain absolute evidence paths and SHA-256 hashes. Changed evidence requires re-verification; do not merely relabel an old mapping as verified. Select it with `--transport-overlay /absolute/overlay.json` or `OMNILANE_AA_TRANSPORT_OVERLAY`.
|
|
19
|
+
|
|
20
|
+
## Upgrade
|
|
21
|
+
|
|
22
|
+
After npm publication:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm i -g omnilane@0.42.2
|
|
26
|
+
omnilane --version
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Repo-symlink installations use the updated checkout. Do not rerun `install.sh` just to update the version. Local routing overrides take precedence; review any Grok entries still using `-`.
|
|
30
|
+
|
|
31
|
+
GitHub release, npm publication, local provider smoke, and Linux CI are separate verification surfaces. Release evidence must identify each result rather than equating one with the others.
|
|
@@ -1,42 +1,103 @@
|
|
|
1
1
|
<!-- omnilane-routing:start -->
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
2
|
+
<!-- source: codex-s / MacStudio; repo omnilane; approved AA v4.2 snapshot 2026-09-07 -->
|
|
3
|
+
## omnilane — model routing and executor selection
|
|
4
|
+
|
|
5
|
+
Delegate tasks by default, including when the resolved model is the commander's
|
|
6
|
+
exact model. Native agents count as delegation; a model match is not permission
|
|
7
|
+
to self-execute. Consult `omnilane list` and classify the lane, then resolve
|
|
8
|
+
vendor/model/effort separately from executor choice:
|
|
9
|
+
|
|
10
|
+
omnilane route [--executor auto|native|cli] [--native-context FILE] [--vendor V] [--mode work] [--workdir DIR] <lane> "<task>"
|
|
11
|
+
|
|
12
|
+
Terminal `auto` without capability context preserves legacy CLI. Build native
|
|
13
|
+
capabilities only from the active agent-tool contract. Codex
|
|
14
|
+
`collaboration.spawn_agent` has no sandbox/tool/workdir restriction parameters
|
|
15
|
+
and inherits the parent's tools/filesystem. Its request and matching capability
|
|
16
|
+
row must explicitly use `shared-inherited` with empty tool arrays;
|
|
17
|
+
`advise`/`work` and workdir remain task intent, not OS isolation. Hard isolation
|
|
18
|
+
stays same-model CLI in auto and rejects forced native. Supply the active
|
|
19
|
+
harness/vendor, exact supported model/effort, optional known current model,
|
|
20
|
+
mode/workdir, isolation, and lifecycle. Same vendor is not the same model.
|
|
21
|
+
Unknown capabilities do not match. Do not infer capability from credentials,
|
|
22
|
+
installed binaries, or model families. Explicit vendor/model/effort must survive
|
|
23
|
+
fallback unchanged.
|
|
24
|
+
|
|
25
|
+
Native is a host-callable tool, not a shell executable. A native route emits a
|
|
26
|
+
machine-readable PENDING handoff JSON with task/job ID and resolved requirements.
|
|
27
|
+
The caller executes the declared native strategy, passes intent plus a
|
|
28
|
+
no-nested-delegation instruction, waits for the actual result, and records it with:
|
|
29
|
+
|
|
30
|
+
omnilane jobs --json complete-native JOB_ID /absolute/completion.json
|
|
31
|
+
omnilane jobs --json status JOB_ID
|
|
32
|
+
omnilane jobs --json result JOB_ID
|
|
33
|
+
|
|
34
|
+
Completion includes actual agent ID, runtime vendor/model/effort/harness/backend,
|
|
35
|
+
outcome, public result and evidence. A handoff alone is not success. Duplicate or
|
|
36
|
+
invalid completion is rejected. Native cancellation records cancellation without
|
|
37
|
+
signaling PIDs; the caller must separately stop an already-spawned agent.
|
|
38
|
+
|
|
39
|
+
When the caller supplies an explicit model override, use `fork_turns: "none"` or
|
|
40
|
+
a bounded positive history count; never combine it with `fork_turns: "all"`.
|
|
41
|
+
Unknown caller current model may be omitted only when an exact requested model is
|
|
42
|
+
explicitly selected and declared in the matching capability row.
|
|
43
|
+
|
|
44
|
+
Forced CLI preserves external execution; forced native rejects missing or
|
|
45
|
+
incompatible capability. Auto emits an explicit CLI reason, never a different
|
|
46
|
+
vendor/model on native fallback. Background/durable/live/named CLI sessions,
|
|
47
|
+
sysops, unsupported isolation and vote/arbitration/multi-round paths remain CLI.
|
|
48
|
+
|
|
49
|
+
The commander owns planning, decomposition, task briefs, routing/handoff/result
|
|
50
|
+
orchestration, acceptance, operator replies, git commit/push and governance edits.
|
|
51
|
+
Workers execute assigned tasks and never delegate again (shell depth guard:
|
|
52
|
+
exit 86; native callers must enforce the same rule). Read-only work defaults to
|
|
53
|
+
advise. Implementation uses explicit `--mode work --workdir DIR --timeout 3600`
|
|
54
|
+
or longer; native timeouts are caller-enforced. External long jobs can use
|
|
55
|
+
`--background`, CLI `jobs wait`, live send/close and CLI goal-loop as before.
|
|
56
|
+
|
|
57
|
+
If a vendor/model is explicitly named, retain `--vendor` and apply the
|
|
58
|
+
omnilane skill's consultation rules. The repository skill and
|
|
59
|
+
`docs/native-executor.md` define schemas, examples and limits. Only the parent
|
|
60
|
+
backs up and syncs the host's managed AGENTS block after review.
|
|
61
|
+
Exact-AA downward policy applies before every native/CLI candidate, fallback, retry,
|
|
62
|
+
and vote constituent. Supply an exact model `--caller-context FILE`; unknown identity
|
|
63
|
+
fails closed, and target score must be <= min(caller score, inherited ceiling).
|
|
64
|
+
Explicit targets do not override the gate. Use `--transport-overlay FILE` only for
|
|
65
|
+
host-local hashed request-selector evidence, never as a score or identity upgrade.
|
|
66
|
+
Pass the job-owned child caller context to native workers; CLI propagates it itself.
|
|
67
|
+
Retries intersect the current caller with the original authorizer ceiling, retain
|
|
68
|
+
the target config, and revalidate integrity. Missing current caller fails closed;
|
|
69
|
+
a model retry does not inherit a previous human exemption.
|
|
70
|
+
Human exemption is an explicit cooperative operator assertion, never inferred for a
|
|
71
|
+
model. Preserve OMNILANE_DEPTH. Failed work returns to the operator rather than an
|
|
72
|
+
unapproved upward route. Observe terminal result and acceptance before ending a
|
|
73
|
+
controller task; a background job/PENDING handoff is not success, and wakeup delivery
|
|
74
|
+
requires its own evidence.
|
|
75
|
+
|
|
76
|
+
For Codex background CLI jobs, actively bind completion to this controller before
|
|
77
|
+
ending the turn: use the repository's `scripts/completion-wakeup.py prepare` with
|
|
78
|
+
the actual app thread ID, local host ID, a unique run ID and exact job allowlist.
|
|
79
|
+
Use its handoff with the app `automation_update` heartbeat tool; update an existing
|
|
80
|
+
controller monitor instead of duplicating it. Record the successful tool receipt
|
|
81
|
+
with `record-registration`. Never write scheduler files directly or label an
|
|
82
|
+
unregistered handoff as active. Current caller metadata must come from this
|
|
83
|
+
controller's verified runtime, not another task's context or a default model.
|
|
84
|
+
|
|
85
|
+
On the scheduled callback, `poll`; stay quiet when nothing changed. For a terminal
|
|
86
|
+
event, record `ack-delivered`, inspect the public result and required verification,
|
|
87
|
+
then `ack-accepted` with PASS/FAIL/PARTIAL evidence. Exit zero is not acceptance.
|
|
88
|
+
After all tracked events are handled, pause the actual automation with the app
|
|
89
|
+
tool and record `closed` using its receipt. New runs get fresh, never-reused IDs.
|
|
90
|
+
See `docs/completion-wakeup.md` for binding, leases, replay and expiry rules.
|
|
91
|
+
Heartbeat is scheduled polling, not instant push. A next-prompt inbox is not wakeup.
|
|
92
|
+
Without a supported callback tool, keep the controller active using `jobs wait`
|
|
93
|
+
and continue acceptance on return; do not end with an unobserved background job.
|
|
94
|
+
Native completion uses the host's agent callback and the same actual-result gate.
|
|
95
|
+
|
|
96
|
+
Native reuse is explicit, never a silent substitute for new-agent creation. It
|
|
97
|
+
requires a proven exact existing agent, caller-observed idle state and preserved
|
|
98
|
+
context consent in the capability. Recheck idle before `collaboration.followup_task`;
|
|
99
|
+
the completion must match strategy, agent and backend. Unknown identity or busy
|
|
100
|
+
agents do not qualify. See `docs/native-executor.md`; a thread quota failure is
|
|
101
|
+
not a successful run, and a cancelled pending job stays cancelled.
|
|
102
|
+
|
|
42
103
|
<!-- omnilane-routing:end -->
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnilane",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "One routing table, every harness — classify subtasks into lanes and
|
|
3
|
+
"version": "0.42.2",
|
|
4
|
+
"description": "One routing table, every harness — classify subtasks into lanes and delegate each lane through a compatible caller-owned native agent or vendor CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"omnilane": "bin/omnilane"
|
|
7
7
|
},
|
|
@@ -24,8 +24,12 @@
|
|
|
24
24
|
"README.ja.md",
|
|
25
25
|
"README.ko.md",
|
|
26
26
|
"SECURITY.md",
|
|
27
|
+
"config/aa-model-policy.json",
|
|
27
28
|
"docs/aa-model-coverage-2026-09-05.json",
|
|
28
29
|
"docs/model-capabilities-2026-09.md",
|
|
30
|
+
"docs/native-executor.md",
|
|
31
|
+
"docs/completion-wakeup.md",
|
|
32
|
+
"docs/release-notes-0.42.2.md",
|
|
29
33
|
"hooks/",
|
|
30
34
|
"skills/",
|
|
31
35
|
".claude-plugin/",
|
package/plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://antigravity.google/schemas/v1/plugin.json",
|
|
3
3
|
"name": "omnilane",
|
|
4
|
-
|
|
5
|
-
"description": "One routing table, every harness: classify subtasks into lanes and
|
|
4
|
+
"version": "0.42.2",
|
|
5
|
+
"description": "One routing table, every harness: classify subtasks into lanes and delegate through compatible caller-owned native agents or vendor CLIs with exact-AA downward policy and supervised jobs."
|
|
6
6
|
}
|
package/routing.yaml
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# vendor = codex | claude | grok | gemini | kimi | qwen | opencode | openrouter
|
|
4
4
|
# openrouter is direct-API (needs only OPENROUTER_API_KEY + curl) and advise/consult
|
|
5
5
|
# only — it cannot edit files, so it is not in the default work-capable chains.
|
|
6
|
-
# effort = codex reasoning effort / claude --effort / agy thinking suffix /
|
|
6
|
+
# effort = codex reasoning effort / claude --effort / agy thinking suffix / grok --reasoning-effort
|
|
7
7
|
# Fallback chain: the first candidate whose vendor CLI is installed wins, so the
|
|
8
8
|
# same table degrades gracefully when you only subscribe to one or two vendors.
|
|
9
9
|
# Override any line in ~/.omnilane/routing.local.yaml (same format; local wins).
|
|
@@ -20,17 +20,17 @@
|
|
|
20
20
|
# standard short-context API tier — on subscription CLIs treat $ as relative ranking.
|
|
21
21
|
# Your own job outcomes (~/.omnilane/jobs/) outrank these priors; edit lanes to match.
|
|
22
22
|
|
|
23
|
-
hardest-coding: claude claude-fable-5-1 max | codex gpt-6-astra xhigh | grok grok-4.6
|
|
23
|
+
hardest-coding: claude claude-fable-5-1 max | codex gpt-6-astra xhigh | grok grok-4.6 high | gemini gemini-3.8-flash-high - # correctness-first coding: Fable max leads the same-condition comparison; Astra xhigh is the default Codex quality/cost tradeoff; explicit --effort max remains available; Grok and Flash keep cross-vendor depth
|
|
24
24
|
bulk-mechanical: codex gpt-5.6-sol high | gemini gemini-3.8-flash-high - | claude claude-sonnet-5 high # endurance and migration work stays on proven Sol high; Flash 3.8 refreshes the fast middle fallback; Sonnet preserves cross-vendor depth
|
|
25
25
|
triage: codex gpt-5.6-luna high | gemini gemini-3.8-flash-low - | claude claude-haiku-4-5 - # first-pass filtering favors the low-cost Luna row; Flash low and Haiku remain cheap cross-vendor fallbacks
|
|
26
|
-
hard-judgment: claude claude-fable-5-1 xhigh | codex gpt-6-astra xhigh | grok grok-4.6
|
|
27
|
-
taste-final: claude claude-fable-5-1 xhigh | codex gpt-6-astra xhigh | grok grok-4.6
|
|
28
|
-
consult: codex gpt-6-astra xhigh | claude claude-fable-5-1 xhigh | grok grok-4.6
|
|
26
|
+
hard-judgment: claude claude-fable-5-1 xhigh | codex gpt-6-astra xhigh | grok grok-4.6 high # strongest same-condition judgment row first, then an independently verified Codex family and Grok; this lane is not a controller selector
|
|
27
|
+
taste-final: claude claude-fable-5-1 xhigh | codex gpt-6-astra xhigh | grok grok-4.6 high | gemini gemini-3.8-flash-high - # final prose and style still require human taste review; general quality evidence orders the candidates without claiming an aesthetic benchmark
|
|
28
|
+
consult: codex gpt-6-astra xhigh | claude claude-fable-5-1 xhigh | grok grok-4.6 high | gemini gemini-3.8-flash-medium - # direct named-model consultation chain; keep --vendor to pin the requested family and prevent fallback
|
|
29
29
|
ui-draft: codex gpt-5.6-sol high | claude claude-fable-5-1 xhigh | gemini gemini-3.8-flash-high - # UI drafts require a design system or references; measured coding/agent evidence supports the order but does not prove visual taste
|
|
30
30
|
long-context: gemini gemini-3.8-flash-medium - | codex gpt-5.6-terra max | claude claude-opus-5 medium # Flash medium leads long-document synthesis; Terra and Opus stay because context capacity alone does not prove task quality
|
|
31
31
|
fast-agentic: gemini gemini-3.8-flash-low - | codex gpt-5.6-luna high | claude claude-haiku-4-5 - # low-latency tool loops favor Flash low; Luna and Haiku retain cross-vendor fallback depth
|
|
32
|
-
live-search: grok grok-4.6
|
|
33
|
-
coding-overflow: grok grok-4.6
|
|
32
|
+
live-search: grok grok-4.6 high | gemini gemini-3.8-flash-high - | claude claude-sonnet-5 high | off # Grok remains the native X/web choice; Flash and Sonnet provide generic web-search fallback, not equivalent social context
|
|
33
|
+
coding-overflow: grok grok-4.6 high | gemini gemini-3.8-flash-high - | kimi kimi-k3 - | qwen qwen3-coder-plus - | opencode - - | off # explicit quota-relief lane; keep all existing non-Codex fallbacks and do not infer unverified Qwen aliases from another harness
|
|
34
34
|
arbitrate: off - - # opinion panel remains opt-in because each voter and round consumes quota
|
|
35
35
|
# Enable: `arbitrate: vote codex,claude,grok -` (any 1-4 of codex/claude/grok/gemini)
|
|
36
36
|
# Debate round (each voter rebuts the others): set the effort field to 2.
|