omnilane 0.42.9 → 0.44.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.ko.md CHANGED
@@ -47,36 +47,133 @@ Gemini CLI** 같은——를 쓰고 계시죠. 각각은 하나의 모델 계열
47
47
 
48
48
  ## ⚡ 60초 시작
49
49
 
50
- **가장 빠른 방법——npm 으로 설치:**
50
+ 터미널 앞에 앉은 사람이라면 지금 바로 디스패치할 수 있습니다.
51
+
52
+ **1. 설치.**
51
53
 
52
54
  ```bash
53
- npm i -g omnilane # CLI 설치
54
- export OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1 # 호출자는 모델이 아닌 사람 운영자
55
- omnilane route hardest-coding "간헐적으로 실패하는 auth 토큰 갱신 테스트 수정"
56
- omnilane doctor # 사용 가능한 AI CLI / 키 확인
57
- omnilane ui start # 선택: 브라우저에서 잡을 실시간 확인
55
+ npm i -g omnilane
58
56
  ```
59
57
 
60
- **또는 리포지토리 clone**(라우팅 테이블과 커스터마이즈용 스킬을 얻음):
58
+ 또는 저장소를 클론합니다. 사용자 정의할 수 있는 라우팅 테이블과 스킬도 함께 얻습니다.
61
59
 
62
60
  ```bash
63
61
  git clone https://github.com/Seraphim0916/omnilane && cd omnilane
64
- ./install.sh # CLI 감지, 스킬 연결, 당신의 언어로 대화
65
- export OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1 # 호출자는 모델이 아닌 사람 운영자
66
- omnilane route hardest-coding "간헐적으로 실패하는 auth 토큰 갱신 테스트 수정"
62
+ ./install.sh # finds your CLIs, links the skill, speaks your language
63
+ ```
64
+
65
+ **2. 무엇이 있는지 확인.** `doctor` 는 omnilane 이 닿을 수 있는 모델 CLI 와 API 키를 나열해 실제로 무엇이 실행될지 알려 줍니다. 아무것도 바꾸지 않습니다.
66
+
67
+ ```bash
68
+ omnilane doctor
69
+ omnilane list # the routing table this machine resolves
70
+ ```
71
+
72
+ **3. 자신이 운영자임을 밝히고 디스패치.**
73
+
74
+ ```bash
75
+ export OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1
76
+ omnilane route hardest-coding "fix the flaky auth token refresh"
77
+ omnilane ui start # optional: watch jobs live in your browser
78
+ ```
79
+
80
+ > **왜 export 가 필요한가?** omnilane 은 디스패치할 때마다 "요청하는 쪽의 능력 점수"와 대조하므로, 누가 요청하는지 밝혀야 합니다. 사람은 `OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1`(또는 호출마다 `--operator-asserted-human`)로 한 번만 밝히면 됩니다. 모델은 스스로 이렇게 선언할 수 없습니다. 모델의 신원은 그것을 실행한 CLI 에서 읽습니다. 둘 다 없으면 작업이 만들어지기 전에 `missing-caller-context` 로 거부됩니다.
81
+
82
+ 사람이 쓰기에는 여기까지면 충분합니다. 다음 절은 더 유용한 구성, 즉 AI 어시스턴트가 스스로 디스패치하게 하는 방법입니다.
83
+
84
+ ## 🤖 AI 어시스턴트가 omnilane 을 운전하게 하기
85
+
86
+ 어시스턴트(Claude Code, Codex, Grok Build, Antigravity)는 스킬 파일을 읽고 레인을 고르는 법과 디스패치하는 법을 배웁니다. 머신마다 한 번, 네 단계입니다.
87
+
88
+ ### 1단계: 어시스턴트에게 스킬 주기
89
+
90
+ `./install.sh` 는 찾은 모든 CLI 에 링크를 만듭니다. 수동으로 할 때:
91
+
92
+ | 어시스턴트 | 방법 |
93
+ |---|---|
94
+ | Claude Code | `claude plugin marketplace add <이 저장소>` 다음 `claude plugin install omnilane@omnilane`(`/route`, `/route-jobs`, 완료 인박스 포함). 또는 `skills/omnilane` 을 `~/.claude/skills/` 에 링크 |
95
+ | Codex | `skills/omnilane` 을 `~/.codex/skills/` 에 링크 |
96
+ | Grok Build | `grok plugin install <이 저장소> --trust` |
97
+ | Antigravity | `agy plugin install <이 저장소>`(먼저 `agy plugin validate <이 저장소>` 로 확인) |
98
+
99
+ ### 2단계: "각 CLI 가 지정한 모델을 정말로 선택한다"는 것을 한 번 증명하기
100
+
101
+ 모델이 호출자일 때는 이 머신이 **증명한** 대상으로만 디스패치할 수 있습니다. 예를 들어 `codex -m gpt-5.6-sol` 이 정말로 Sol 을 실행한다는 것입니다. 이 증명은 로컬 파일이며 **트랜스포트 오버레이(transport overlay)** 라고 부릅니다. 패키지에는 들어 있지 않습니다. 이것이 없으면 모든 레인이 모델 호출자를 `runtime-mapping-unverified` 로 거부하고, `omnilane doctor` 는 `no overlay configured` 라고 경고합니다.
102
+
103
+ 일반 데스크톱 터미널에서 만드세요. (ssh 로그인 세션은 CLI 가 로그인에 쓰는 키체인을 읽지 못해 모두 로그인되지 않았다고 보고합니다.)
104
+
105
+ ```bash
106
+ cd "$(npm root -g)/omnilane" # or your clone
107
+ ROOT=~/.omnilane/transport-evidence/first-sweep
108
+ python3 scripts/lib/probe_sweep.py --root "$ROOT" # one tiny prompt per selector, about 55 calls
109
+ python3 scripts/lib/build_overlay.py --root "$ROOT"
110
+ cp "$ROOT/transport-contracts.local.json" ~/.omnilane/transport-contracts.local.json
111
+ echo 'export OMNILANE_AA_TRANSPORT_OVERLAY="$HOME/.omnilane/transport-contracts.local.json"' >> ~/.omnilane/local.sh
112
+ omnilane doctor | grep transport-overlay # PASS, with a count per vendor
113
+ ```
114
+
115
+ 로그인하지 않은 벤더는 `unprobeable` 로 보고되고 미검증 상태로 남을 뿐입니다. 나머지는 동작합니다.
116
+
117
+ ### 3단계: 증명을 손대지 않고 최신으로 유지하기
118
+
119
+ 오버레이는 각 CLI 실행 파일을 해시로 고정합니다. 그리고 **CLI 는 스스로 업데이트됩니다**. 일주일에 한 번인 경우도 흔합니다. 업데이트 뒤에는 오버레이가 다시 서명될 때까지 그 벤더의 레인이 거부됩니다. `omnilane resign` 이 이 일을 전부 합니다. 바뀐 것을 찾고, 그 벤더만 다시 프로브하고, 결과를 확인하고, 교체하고, 실제 디스패치 한 건으로 확인하고, 실패하면 이전 파일로 되돌립니다.
120
+
121
+ 아무것이나 다시 서명하지는 않습니다. 바뀐 CLI 가 **무인으로** 재서명되는 것은 기록된 것과 같은 코드 서명 팀을 가지고 같은 종류의 설치 위치에 있을 때뿐입니다. 그래서 어떤 서명자를 받아들일지 한 번 알려 줍니다.
122
+
123
+ ```bash
124
+ omnilane resign --record-signers # once, right after Step 2
125
+ ```
126
+
127
+ 업데이트 때마다 벤더 CLI 를 직접 패치하고 adhoc 으로 다시 서명한다면, 그것도 벤더별로 한 번 알려 줍니다. 이후 같은 설치 디렉터리 안의 adhoc 업데이트도 무인으로 재서명됩니다.
128
+
129
+ ```bash
130
+ omnilane resign --trust-adhoc claude # 직접 claude 를 adhoc 서명하는 경우에만
131
+ ```
132
+
133
+ 그다음 매일 실행되게 합니다. 스케줄러는 무엇이든 좋지만 반드시 **데스크톱 로그인 세션 안에서** 실행되어야 합니다(CLI 에 키체인이 필요합니다). macOS 에서는 LaunchAgent 를 쓸 수 있습니다.
134
+
135
+ ```bash
136
+ cat > ~/Library/LaunchAgents/dev.omnilane.resign.plist <<'EOF'
137
+ <?xml version="1.0" encoding="UTF-8"?>
138
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
139
+ <plist version="1.0"><dict>
140
+ <key>Label</key><string>dev.omnilane.resign</string>
141
+ <key>ProgramArguments</key><array><string>/bin/zsh</string><string>-lc</string><string>omnilane resign</string></array>
142
+ <key>StartCalendarInterval</key><dict><key>Hour</key><integer>9</integer><key>Minute</key><integer>0</integer></dict>
143
+ <key>StandardOutPath</key><string>/tmp/omnilane-resign.log</string>
144
+ <key>StandardErrorPath</key><string>/tmp/omnilane-resign.log</string>
145
+ </dict></plist>
146
+ EOF
147
+ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/dev.omnilane.resign.plist
67
148
  ```
68
149
 
69
- > **그 export 는 왜 필요한가요?** omnilane 은 호출자 자신의 능력 점수로 모든 디스패치를
70
- > 게이트하므로, 디스패치는 «누가 요청하는지»를 반드시 밝혀야 합니다. 터미널 앞의 사람은
71
- > `OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1` 을 한 번 설정하거나 호출마다
72
- > `--operator-asserted-human` 을 붙입니다. omnilane 을 구동하는 모델은 **스스로 이를 주장할
73
- > 수 없습니다**. 모델의 신원은 그것을 실행한 CLI 의 모델·effort 플래그에서 자동으로 읽히므로,
74
- > 일반 세션은 아무것도 전달할 필요가 없습니다. `omnilane whoami` 는 그 신원을
75
- > `--caller-context FILE` 로 출력합니다. 주장도 읽을 수 있는 신원도 없으면 잡 생성 전에
76
- > `missing-caller-context` 로 거부됩니다.
150
+ 이번 릴리스는 데스크톱 터미널에서의 `omnilane resign` 을 실제로 검증했습니다. Codex 의 실제 자체 업데이트에 대한 무인 재서명도 포함합니다. 위의 LaunchAgent 는 예시이며 그 자체는 검증하지 않았습니다. `launchctl kickstart gui/$(id -u)/dev.omnilane.resign` 으로 여러분의 머신에서 확인하세요.
151
+
152
+ `omnilane resign` 의 종료 코드:
77
153
 
78
- > 처음이신가요? 먼저 `omnilane doctor` 를 실행하세요. omnilane 이 지금 어떤 모델 CLI 와
79
- > API 키에 접근할 수 있는지 알려 주어, 실제로 무엇이 실행될지 파악할 수 있습니다.
154
+ | 종료 코드 | 의미 | 할 일 |
155
+ |---|---|---|
156
+ | 0 | 바뀐 것이 없거나, 바뀐 것이 모두 재서명됨 | 없음 |
157
+ | 10 | `--check` 전용: 무언가 바뀜 | `omnilane resign` 실행 |
158
+ | 20 | 어떤 벤더에 사람이 필요함: 서명자가 새롭거나 기록이 없음, 실행 파일이 서명되지 않았거나 로컬에서 수정됨, 설치 디렉터리가 바뀜, 또는 지난번 통과한 프로브를 이번에 공급자가 거부함 | 메시지를 읽는다. "나중에 다시 시도" 또는 확인 후 실행할 `omnilane resign --vendor V --approve V` 가 그대로 출력된다 |
159
+ | 30 | 재서명한 오버레이가 실제 디스패치에 실패해 이전 것으로 복원됨 | 망가진 것은 없다. 로그를 읽는다 |
160
+ | 2 | 오버레이가 설정되지 않음 | 2단계를 한다 |
161
+
162
+ 알아 둘 제한이 두 가지 있습니다. 서명자 확인은 macOS 코드 서명을 사용하므로, Linux 에서는 CLI 가 바뀔 때마다 종료 코드 20 에서 멈추고 `--approve` 를 요구합니다. 또한 정식 서명이 없는 바이너리(예: 로컬에서 패치한 CLI)는 항상 승인을 기다리며 멈춥니다. 그것을 벤더와 이어 주는 것이 아무것도 없기 때문이며, 그것이 바로 이 확인의 목적입니다.
163
+
164
+ ### 4단계: 어시스턴트 안에서 시험하기
165
+
166
+ 어시스턴트에게 `omnilane whoami` 를 실행하게 하세요. 자신이 어떤 모델과 어떤 effort 로 실행 중인지, 그리고 점수를 답해야 합니다. 이어서 작은 일을 위임하게 합니다. "omnilane 으로 triage 레인에게 이 저장소의 TODO 주석 수를 세게 해 줘".
167
+
168
+ 거부되면 어느 확인에서 실패했는지, 무엇을 해야 하는지가 거부 메시지에 있습니다.
169
+
170
+ | `failed_gate` | 쉽게 말하면 | 고치는 법 |
171
+ |---|---|---|
172
+ | `caller-identity` | 어떤 모델이 요청하는지 omnilane 이 알 수 없음 | `omnilane whoami` 를 그 도구 호출의 **유일한 명령**으로 실행하게 한다. 특히 Codex 는 `; echo $?`, `&&`, 파이프 뒤에서는 읽을 수 없다 |
173
+ | `target-transport` | 이 머신이 그 대상을 증명하지 않았거나, 그 뒤 CLI 가 업데이트됨 | `omnilane resign`(3단계) |
174
+ | `downward-ceiling` | 대상 모델의 점수가 요청하는 모델보다 높음. 모델은 옆이나 아래로만 위임할 수 있음 | 거부 메시지의 `eligible_lanes` 중 하나를 고르거나, 더 높은 effort 로 어시스턴트를 시작한다 |
175
+
176
+ 기존 스레드를 깨우는 Codex 자동화는 effort 를 기록하지 않습니다. omnilane 은 그 호출자를 거부하는 대신 해당 모델의 최저 점수로 제한합니다. 저렴한 레인은 계속 동작하고, 비싼 레인은 어떤 effort 면 닿는지 알려 줍니다.
80
177
 
81
178
  ## 🧭 동작 방식
82
179
 
@@ -173,6 +270,34 @@ flowchart LR
173
270
 
174
271
  </details>
175
272
 
273
+ ## 어시스턴트 자신의 서브에이전트 사용하기
274
+
275
+ omnilane 은 기본적으로 벤더의 명령줄 도구에 일을 넘깁니다. 일을 해야 할 모델이 어시스턴트 **자신의 벤더** 것일 때 다른 CLI 를 거치는 것은 돌아가는 길입니다. 로그인이 하나 더, 프로세스가 하나 더, 그 CLI 가 업데이트되면 망가질 곳이 하나 더 생깁니다. 대부분의 어시스턴트는 스스로 서브에이전트를 시작할 수 있고, omnilane 은 그에 맞춰 일을 계획할 수 있습니다. 방법은 두 가지입니다.
276
+
277
+ **어시스턴트와 정확히 같은 것을 실행하는 워커(`--inherit`).** 어시스턴트는 *모델도 effort 도 지정하지 않고* 서브에이전트를 시작하므로 워커는 호출자의 복제입니다. 복제가 원본보다 강할 수는 없고, omnilane 의 점수 확인이 막으려는 것은 그것뿐입니다. 그래서 이 경로에는 벤더 CLI 도 트랜스포트 오버레이도 필요 없고, 호출자의 effort 를 알 수 없거나 오버레이가 오래되었을 때도 동작합니다.
278
+
279
+ ```sh
280
+ omnilane native-context --workdir /absolute/repo --inherits-caller-runtime # prints a capability file
281
+ omnilane route --inherit --native-context /path/printed/above --workdir /absolute/repo triage "Count the TODO comments"
282
+ # -> a PENDING handoff (JSON). The assistant now starts its own sub-agent with no
283
+ # model argument, checks the result, and records it:
284
+ omnilane jobs --json complete-native JOB_ID /absolute/completion.json
285
+ omnilane jobs --json status JOB_ID
286
+ ```
287
+
288
+ 정직한 부분: 핸드오프에는 `satisfies_lane_target: false` 가 표시됩니다. 여기서 레인은 일의 종류를 나타내는 라벨일 뿐입니다. 이렇게 얻은 결과는 "어시스턴트 자신의 서브에이전트"가 만든 것이지 결코 "hardest-coding 모델"이 만든 것이 아닙니다. 호출자보다 강한 모델이 필요한 레인은 여전히 거부됩니다. `--inherits-caller-runtime` 은 "내 서브에이전트 도구는 이렇게 동작한다"는 어시스턴트 자신의 진술이며 omnilane 은 이를 관찰할 수 없습니다. 어시스턴트별로 알려진 사항:
289
+
290
+ | 어시스턴트 | 모델 인자 없는 서브에이전트 |
291
+ |---|---|
292
+ | Claude Code | 메인 대화의 모델을 사용하고 effort 는 세션 것을 이어받는다고 공식 문서에 명시(에이전트 정의가 지정하는 경우 제외). 내장 general-purpose 에이전트이고 `CLAUDE_CODE_SUBAGENT_MODEL` 이 설정되지 않았을 때 성립. 이번 릴리스에서 끝까지 실행함 |
293
+ | Codex | 모델도 effort 도 없는 `collaboration.spawn_agent`. 이번 릴리스에서 끝까지 실행함 |
294
+ | Grok Build | 부모의 모델을 상속한다고 문서에 명시(번들된 `general-purpose` 는 `model: inherit`). effort 는 문서에 없음. 이번 릴리스에서 실행하지 않음 |
295
+ | Antigravity | `agy` 1.2.7 에서 서브에이전트 도구를 찾지 못함. 사용 불가 |
296
+
297
+ **어시스턴트의 도구가 선택할 수 있는 특정 모델.** 도구가 실제로 받아들이는 것을 capability 파일에 적고(`omnilane native-context` 의 출력에서 시작해 정확한 모델과 effort 쌍마다 행을 추가) 일반 `omnilane route` 에 `--native-context FILE` 을 넘깁니다. omnilane 은 어떤 행이 정확히 일치할 때만 서브에이전트를 사용합니다. 모델, effort, 모드, workdir, 도구, 격리 방식, 수명 주기 모두입니다. 같은 벤더가 같은 모델은 아니며, 설치된 CLI 로부터 추측하지도 않습니다. `--executor native` 는 폴백하지 않고 실패하고, `--executor cli` 는 외부 CLI 를 강제합니다. 파일이 없다는 이유만으로 같은 벤더의 대상이 CLI 를 거친 경우, 디스패치가 이제 그 사실을 알려 줍니다.
298
+
299
+ 어느 쪽이든 서브에이전트는 어시스턴트의 도구와 파일 시스템을 공유합니다. 운영체제 수준의 샌드박스는 없으며 `advise`/`work` 는 의도이지 강제가 아닙니다. 백그라운드, 상주, 이름 있는 스레드, 다중 라운드, 투표, `sysops` 작업은 CLI 경로에 남습니다. 프로토콜 처리에는 Python 3.9 이상이 필요합니다. 스키마, 완료 파일, 에이전트 재사용과 취소: [docs/native-executor.md](docs/native-executor.md).
300
+
176
301
  ## 🖥️ Live Board
177
302
 
178
303
  모든 디스패치는——포그라운드든 `--background` 든——디스크에 잡으로 기록됩니다.
@@ -562,6 +687,30 @@ doctor가 파일과 벤더를 지목하며, 재서명 절차는 디스패치 스
562
687
 
563
688
  ## 📜 릴리스 기록
564
689
 
690
+ ## v0.44.0 새 기능
691
+
692
+ - **직접 패치한 CLI 도 무인으로 재서명됩니다.** 업데이트 때마다 벤더 CLI 를 패치하고 adhoc 으로 다시 서명하는 로컬 단계가 있다면, 지금까지는 서명자 검사가 그런 업데이트를 모두 `--approve` 대기로 막았습니다. 벤더별로 한 번 `omnilane resign --trust-adhoc VENDOR` 를 실행하면 같은 설치 디렉터리 안의 adhoc 업데이트는 같은 서명자의 업데이트처럼 매일의 `omnilane resign` 으로 자동 재서명됩니다. 서명되지 않은 실행 파일, 다른 디렉터리의 adhoc, 다른 벤더는 여전히 멈추고 확인을 기다립니다. 신뢰는 오버레이에 기록되고 이후 어떤 벤더의 재서명에서도 유지되며, 모델이 실행하지 않는 운영자 작업입니다. 네 벤더 모두 지원.
693
+ - **로그인 만료는 "나중에 다시" 가 아니라 "먼저 로그인" 으로 안내합니다.** `Failed to authenticate`, `OAuth session expired`, `Invalid API key`, `Unauthorized`, `401` 은 해당 벤더를 프로브 불가로 표시하고, 보류 메시지는 먼저 로그인하라고 안내합니다.
694
+ - 업그레이드: `npm i -g omnilane@0.44.0`. 0.42.x 에서 올라오는 경우 `omnilane resign --record-signers` 도 한 번 실행하세요(0.43.0 설명 참조).
695
+
696
+ ## v0.43.1 새 기능
697
+
698
+ 0.43.0 대신 이 버전을 설치하세요. 0.43.0 에서는 `build_overlay.py` 와 `probe.py` 가 Python 3.9 에서 임포트에 실패해, 해당 버전에서 첫 설치의 오버레이 생성과 `omnilane resign` 이 동작하지 않았습니다. 그 밖의 변경은 없으며 아래 0.43.0 설명이 모두 그대로 적용됩니다. 업그레이드: `npm i -g omnilane@0.43.1` 다음 한 번만 `omnilane resign --record-signers`.
699
+
700
+ ## v0.43.0 새 기능
701
+
702
+ 열흘 동안 0.42.x 는 모든 모델 호출자를 네 번 거부했습니다. 매번 omnilane 이 통제하지 못하는 사실 때문이었습니다. 이름이 바뀐 런처, 재서명 없이 변경된 runner 스크립트, 같은 주에 스스로 업데이트된 네 개의 벤더 CLI, effort 를 기록하지 않는 Codex 자동화. 모두 "아무것도 디스패치할 수 없음"이 되었습니다. 이번 릴리스는 각각을 더 좁고 설명 가능한 결과로 바꾸고, 가장 흔한 경우는 스스로 고칩니다.
703
+
704
+ - **벤더 CLI 가 업데이트되었나요? `omnilane resign`.** 바뀐 것을 찾고, 그 벤더만 다시 프로브하고, 결과를 확인하고, 교체하고, 실제 디스패치 한 건으로 확인하고, 실패하면 이전 오버레이로 되돌립니다. 새 실행 파일이 같은 코드 서명 팀을 가지고 같은 위치에 있을 때만 **무인으로** 재서명하며, 그 외에는 실행할 `--approve` 명령을 출력하고 멈춥니다. `omnilane resign --record-signers` 를 한 번 실행하고 `omnilane resign` 을 매일 예약하면 CLI 업데이트는 더 이상 여러분의 일이 아닙니다. Codex 의 실제 자체 업데이트(0.155.0 → 0.155.1)로 검증함: 승인 없음, 매핑 전부 유지, 종료 코드 0.
705
+ - **거부가 모델에게 다음 행동을 알려 줍니다.** 거부된 모든 디스패치는 `failed_gate`, `reason`, `next_command`, `required_caller_effort`, 그리고 `eligible_lanes`(그 호출자가 지금 *닿을 수 있는* 레인)를 담습니다.
706
+ - **effort 기록이 없으면 거부 대신 범위를 좁힙니다.** Codex 하트비트 자동화는 모든 레인에서 거부되는 대신 해당 모델의 최저 점수로 제한됩니다. 저렴한 레인은 계속 동작하고, 비싼 레인은 필요한 effort 를 알려 줍니다.
707
+ - **어시스턴트 자신의 서브에이전트.** `omnilane native-context` 가 예전에는 손으로 써야 했던 capability 파일을 만들어 줍니다. `omnilane route --inherit` 는 호출자의 복제인 워커를 계획합니다. 외부 CLI 없음, 오버레이 없음, 호출자를 식별할 수 없을 때도 동작하며, 그 레인의 대상 모델이 *아님*을 정직하게 표시합니다. Claude Code 와 Codex 데스크톱에서 끝까지 실행했습니다.
708
+ - **Codex: 도구 호출 한 번에 omnilane 명령 하나.** `omnilane whoami; echo $?` 는 식별할 수 없고, `omnilane whoami` 단독은 식별됩니다. 거부 메시지가 이제 그렇게 안내합니다.
709
+ - **doctor 가 자리를 옮긴 CLI 를 찾아냅니다**(새 버전이 이전 파일 옆에 설치되는 경우). 오버레이가 전혀 없으면 절차와 함께 경고합니다.
710
+ - **스킬과 튜토리얼을 다시 작성.** 스킬은 이제 모델이 순서대로 따르는 다섯 단계 절차이며, 이 README 는 어시스턴트가 omnilane 을 운전하게 하기까지를 차례로 안내합니다.
711
+ - **제한.** 무인 재서명은 macOS 코드 서명에 의존합니다. Linux, 그리고 서명되지 않았거나 로컬에서 수정된 CLI 에서는 업데이트마다 `--approve` 를 요구합니다. `--inherit` 는 Grok Build 안에서 실행해 보지 않았고, Antigravity 는 서브에이전트 도구를 제공하지 않습니다. 자세한 내용은 [CHANGELOG](CHANGELOG.md).
712
+ - **업그레이드.** `npm i -g omnilane@0.43.0` 다음 한 번만: `omnilane resign --record-signers`.
713
+
565
714
  ## v0.42.9 새 기능
566
715
 
567
716
  - **런처를 거치는 Codex 데스크톱.** ChatGPT.app이 codex-profile-switch를 통해 app-server를
package/README.md CHANGED
@@ -44,42 +44,170 @@ CLI or seven — dispatch picks the first candidate you actually have, and a lan
44
44
  with nothing available simply turns off. The default table works on a single
45
45
  subscription.
46
46
 
47
- **[⬇ Jump to the 60-second start](#-60-second-start)** · **[❓ Read the FAQ](#-faq)**
47
+ **[⬇ 60-second start](#-60-second-start)** · **[🤖 Let your AI assistant drive it](#-let-your-ai-assistant-drive-omnilane)** · **[❓ FAQ](#-faq)**
48
48
 
49
49
  ## ⚡ 60-second start
50
50
 
51
- **The quick way — install from npm:**
51
+ You, a person at a terminal, can dispatch right away.
52
+
53
+ **1. Install.**
52
54
 
53
55
  ```bash
54
- npm i -g omnilane # install the CLI
55
- export OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1 # you are the operator, not a model
56
- omnilane route hardest-coding "fix the flaky auth token refresh"
57
- omnilane doctor # see which AI CLIs / keys you have
58
- omnilane ui start # optional: watch jobs live in your browser
56
+ npm i -g omnilane
59
57
  ```
60
58
 
61
- **Or clone the repo** (gets you the routing table and skill to customise):
59
+ Or clone it, which also gives you the routing table and the skill to customise:
62
60
 
63
61
  ```bash
64
62
  git clone https://github.com/Seraphim0916/omnilane && cd omnilane
65
63
  ./install.sh # finds your CLIs, links the skill, speaks your language
66
- export OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1 # you are the operator, not a model
64
+ ```
65
+
66
+ **2. See what you have.** `doctor` lists which model CLIs and API keys omnilane
67
+ can reach, so you know what will actually run. It changes nothing.
68
+
69
+ ```bash
70
+ omnilane doctor
71
+ omnilane list # the routing table this machine resolves
72
+ ```
73
+
74
+ **3. Say you are the operator, then dispatch.**
75
+
76
+ ```bash
77
+ export OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1
67
78
  omnilane route hardest-coding "fix the flaky auth token refresh"
79
+ omnilane ui start # optional: watch jobs live in your browser
80
+ ```
81
+
82
+ > **Why the export?** omnilane checks every delegation against the capability
83
+ > score of whoever is asking, so a dispatch has to say who that is. A human says
84
+ > it once with `OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1` (or `--operator-asserted-human`
85
+ > per call). A model cannot say it for itself: its identity is read from the CLI
86
+ > that launched it. With neither, the dispatch is refused with
87
+ > `missing-caller-context` before any job exists.
88
+
89
+ That is all a human needs. The rest of this section is for the more useful
90
+ setup: your AI assistant dispatching on its own.
91
+
92
+ ## 🤖 Let your AI assistant drive omnilane
93
+
94
+ The assistant (Claude Code, Codex, Grok Build or Antigravity) reads a skill file
95
+ that tells it how to pick a lane and dispatch. Four steps, once per machine.
96
+
97
+ ### Step 1 — Give the assistant the skill
98
+
99
+ `./install.sh` links it for every CLI it finds. By hand:
100
+
101
+ | Assistant | How |
102
+ |---|---|
103
+ | Claude Code | `claude plugin marketplace add <this repo>` then `claude plugin install omnilane@omnilane` (also gives `/route`, `/route-jobs` and the completion inbox), or link `skills/omnilane` into `~/.claude/skills/` |
104
+ | Codex | link `skills/omnilane` into `~/.codex/skills/` |
105
+ | Grok Build | `grok plugin install <this repo> --trust` |
106
+ | Antigravity | `agy plugin install <this repo>` (check first with `agy plugin validate <this repo>`) |
107
+
108
+ ### Step 2 — Prove, once, that each CLI selects the model it is asked for
109
+
110
+ A model caller is only allowed to dispatch to a target this machine has *proven*:
111
+ that `codex -m gpt-5.6-sol` really runs Sol, and so on. The proof is a local file,
112
+ the **transport overlay**. Nothing ships with one. Without it every lane refuses
113
+ a model caller with `runtime-mapping-unverified`, and `omnilane doctor` warns
114
+ `no overlay configured`.
115
+
116
+ Build it from a normal desktop terminal. (An ssh login cannot read the keychain
117
+ the CLIs log in with, so it would report them all as not logged in.)
118
+
119
+ ```bash
120
+ cd "$(npm root -g)/omnilane" # or your clone
121
+ ROOT=~/.omnilane/transport-evidence/first-sweep
122
+ python3 scripts/lib/probe_sweep.py --root "$ROOT" # one tiny prompt per selector, about 55 calls
123
+ python3 scripts/lib/build_overlay.py --root "$ROOT"
124
+ cp "$ROOT/transport-contracts.local.json" ~/.omnilane/transport-contracts.local.json
125
+ echo 'export OMNILANE_AA_TRANSPORT_OVERLAY="$HOME/.omnilane/transport-contracts.local.json"' >> ~/.omnilane/local.sh
126
+ omnilane doctor | grep transport-overlay # PASS, with a count per vendor
127
+ ```
128
+
129
+ A vendor you are not logged in to is reported `unprobeable` and simply stays
130
+ unverified; the others work.
131
+
132
+ ### Step 3 — Keep the proof current without doing it by hand
133
+
134
+ The overlay pins each CLI executable by hash, and **the CLIs update themselves**,
135
+ often weekly. After an update that vendor's lanes are refused until the overlay
136
+ is re-signed. `omnilane resign` does the whole job: finds what changed, re-probes
137
+ only that vendor, checks the result, swaps it in, sends one real dispatch to
138
+ confirm, and restores the old file if that fails.
139
+
140
+ It will not re-sign just anything. A changed CLI is re-signed **unattended** only
141
+ when it carries the same code-signing team as the one on record and sits in the
142
+ same install location. So tell it once which signers you accept:
143
+
144
+ ```bash
145
+ omnilane resign --record-signers # once, right after Step 2
146
+ ```
147
+
148
+ If you patch a vendor CLI yourself after every update and re-sign it adhoc,
149
+ tell omnilane that too, once per vendor; an adhoc update in the same install
150
+ directory is then re-signed unattended as well:
151
+
152
+ ```bash
153
+ omnilane resign --trust-adhoc claude # only if you re-sign claude adhoc yourself
154
+ ```
155
+
156
+ Then let it run every day. Any scheduler works as long as it runs **inside your
157
+ desktop login session** (the CLIs need the keychain). On macOS, a LaunchAgent:
158
+
159
+ ```bash
160
+ cat > ~/Library/LaunchAgents/dev.omnilane.resign.plist <<'EOF'
161
+ <?xml version="1.0" encoding="UTF-8"?>
162
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
163
+ <plist version="1.0"><dict>
164
+ <key>Label</key><string>dev.omnilane.resign</string>
165
+ <key>ProgramArguments</key><array><string>/bin/zsh</string><string>-lc</string><string>omnilane resign</string></array>
166
+ <key>StartCalendarInterval</key><dict><key>Hour</key><integer>9</integer><key>Minute</key><integer>0</integer></dict>
167
+ <key>StandardOutPath</key><string>/tmp/omnilane-resign.log</string>
168
+ <key>StandardErrorPath</key><string>/tmp/omnilane-resign.log</string>
169
+ </dict></plist>
170
+ EOF
171
+ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/dev.omnilane.resign.plist
68
172
  ```
69
173
 
70
- > **Why that export?** Omnilane gates every delegation against the caller's own
71
- > capability score, so a dispatch has to say who is asking. A human at a terminal
72
- > asserts that once with `OMNILANE_AA_OPERATOR_ASSERTED_HUMAN=1`, or per call with
73
- > `--operator-asserted-human`. A model driving omnilane cannot assert it for
74
- > itself. Its identity is read from the nearest launching CLI: explicit model and
75
- > effort flags, or for Codex app-server/no-model launches, a bound current-turn
76
- > rollout (never app-server startup defaults). An ordinary session passes nothing,
77
- > and `omnilane whoami` prints that identity as a `--caller-context FILE`. With
78
- > neither an assertion nor a readable identity, the dispatch is refused with
79
- > `missing-caller-context` before any job is created.
174
+ This release verified `omnilane resign` from a desktop terminal session, including
175
+ a real unattended re-sign of a Codex self-update; the LaunchAgent wrapper above is
176
+ an example and was not itself exercised. Check it on your machine with
177
+ `launchctl kickstart gui/$(id -u)/dev.omnilane.resign`.
80
178
 
81
- > New to this? Run `omnilane doctor` first — it tells you which model CLIs and
82
- > API keys omnilane can already reach, so you know what will actually run.
179
+ What `omnilane resign` exits with:
180
+
181
+ | Exit | Meaning | You do |
182
+ |---|---|---|
183
+ | 0 | nothing had changed, or everything that changed was re-signed | nothing |
184
+ | 10 | `--check` only: something changed | run `omnilane resign` |
185
+ | 20 | a vendor needs you: new or missing signer, unsigned or locally patched binary, new install directory, or the provider refused probes that passed last time | read the message. It prints either "retry later" or the exact `omnilane resign --vendor V --approve V` to run after you have looked |
186
+ | 30 | the re-signed overlay failed its real dispatch and the previous one was restored | nothing is broken; read the log |
187
+ | 2 | no overlay is configured | do Step 2 |
188
+
189
+ Two limits to know. Signer checks use macOS code signatures, so on Linux every
190
+ changed CLI stops at exit 20 for your `--approve`. And a binary with no real
191
+ signature (a locally patched CLI, for example) always stops for approval: nothing
192
+ ties it to its vendor, which is the point of the check.
193
+
194
+ ### Step 4 — Try it from inside the assistant
195
+
196
+ Ask your assistant to run `omnilane whoami`. It should answer with the model and
197
+ effort it is running as, and a score. Then ask it to delegate something small:
198
+ "use omnilane to have the triage lane count the TODO comments in this repo".
199
+
200
+ If it is refused, the refusal says which check failed and what to do:
201
+
202
+ | `failed_gate` | In plain words | Fix |
203
+ |---|---|---|
204
+ | `caller-identity` | omnilane could not tell which model is asking | have it run `omnilane whoami` **as the only command** in that tool call. Codex in particular is unreadable behind `; echo $?`, `&&` or a pipe |
205
+ | `target-transport` | this machine has not proven that target, or a CLI updated since | `omnilane resign` (Step 3) |
206
+ | `downward-ceiling` | the target model scores higher than the model asking; a model may only delegate sideways or down | pick one of the `eligible_lanes` the refusal lists, or start the assistant at a higher effort |
207
+
208
+ A Codex automation that wakes an existing thread records no effort. omnilane
209
+ then holds that caller to its model's lowest score instead of refusing it: cheap
210
+ lanes keep working, expensive ones say which effort would reach them.
83
211
 
84
212
  ## 🧭 How it works
85
213
 
@@ -160,52 +288,59 @@ request; this is not a free-form shell parser in `dispatch.sh`.
160
288
  table. If an explicit target is absent or unavailable, the command fails
161
289
  clearly instead of falling back to another vendor or family.
162
290
 
163
- ## Native-first delegation, terminal-compatible
291
+ ## Using the assistant's own sub-agents
164
292
 
165
- Model routing and execution are separate. `--executor auto` (default) selects
166
- a caller-owned native tool only from explicit structured capabilities. Without
167
- that context a standalone terminal uses legacy CLI. `--executor cli` forces
168
- the old behavior; `--executor native` rejects missing/incompatible capability.
169
- Same vendor is not same model; explicit model/vendor/effort are preserved.
170
- On native rejection, auto reports a CLI reason and keeps the exact resolved
171
- target rather than substituting another vendor/model.
293
+ By default omnilane hands work to a vendor's command-line tool. When the model
294
+ that should do the work belongs to the assistant's **own** vendor, going out
295
+ through a second CLI is a detour: another login, another process, another thing
296
+ that breaks when that CLI updates. Most assistants can start a sub-agent
297
+ themselves, and omnilane can plan the work for that instead. Two ways.
172
298
 
173
- ```sh
174
- # Standalone terminal: CLI dry run, no jobs or provider calls.
175
- omnilane route --executor auto --dry-run hardest-coding "Review this change"
299
+ **A worker that runs exactly what the assistant runs (`--inherit`).** The
300
+ assistant starts its sub-agent *without choosing a model or an effort*, so the
301
+ worker is a copy of the caller. A copy cannot be stronger than the original,
302
+ which is the only thing omnilane's score check is there to prevent, so this path
303
+ needs no vendor CLI and no transport overlay, and it keeps working when the
304
+ caller's effort is unknown or an overlay has gone stale.
176
305
 
177
- # Host supplies honest shared/inherited capability JSON; inspect the linked schema.
178
- omnilane route --executor native --native-context /absolute/capability.json --workdir /absolute/repo hardest-coding "Review this change"
179
- # The host now spawns its native agent tool, waits and writes actual evidence.
306
+ ```sh
307
+ omnilane native-context --workdir /absolute/repo --inherits-caller-runtime # prints a capability file
308
+ omnilane route --inherit --native-context /path/printed/above --workdir /absolute/repo triage "Count the TODO comments"
309
+ # -> a PENDING handoff (JSON). The assistant now starts its own sub-agent with no
310
+ # model argument, checks the result, and records it:
180
311
  omnilane jobs --json complete-native JOB_ID /absolute/completion.json
181
312
  omnilane jobs --json status JOB_ID
182
- omnilane jobs --json result JOB_ID
183
- omnilane jobs --json list --status pending
184
313
  ```
185
314
 
186
- Native route emits **pending handoff JSON**, not a shell-native invocation or
187
- completed job. Codex `collaboration.spawn_agent` has no sandbox/tool/workdir
188
- restriction parameters and inherits parent tools/filesystem. Its honest request
189
- and matching capability row explicitly use `shared-inherited` with empty tool
190
- arrays; `advise`/`work` and workdir are task intent, not an OS boundary. Hard
191
- isolation remains same-model CLI in auto and rejects forced native.
192
-
193
- The caller spawns the real agent with the exact resolved model/effort, then
194
- ingests the actual agent ID, runtime model/effort/vendor/harness/backend,
195
- outcome, public result, and evidence. An explicit model override uses
196
- `fork_turns: "none"` or bounded positive history, never `fork_turns: "all"`.
197
- Unknown caller current model may be omitted when the route explicitly selects
198
- an exact model declared by the matching capability row. Duplicate completion is
199
- rejected. Native cancellation never signals PIDs; the caller separately stops
200
- any spawned agent.
201
-
202
- Background/durable/live/named CLI sessions, sysops, unsupported isolation,
203
- vote/arbitration and multi-round paths remain CLI-only. Native integration is
204
- limited to list/status/result/cancel/completion, not CLI wait/retry/mailbox or
205
- goal-loop. Protocol handling needs Python 3.9+; legacy terminal CLI remains
206
- compatible. Tests are fixtures, not live native acceptance. The parent alone
207
- syncs the host AGENTS managed block after review.
208
- See [schemas, complete examples and limitations](docs/native-executor.md).
315
+ The honest part: the handoff is marked `satisfies_lane_target: false`. The lane
316
+ is only a label for the kind of work. A result produced this way was made by
317
+ "the assistant's own sub-agent", never by "the hardest-coding model", and a lane
318
+ that needs a stronger model than the caller is still refused.
319
+ `--inherits-caller-runtime` is the assistant's own statement that its sub-agent
320
+ tool behaves this way; omnilane cannot observe it. What is known per assistant:
321
+
322
+ | Assistant | Sub-agent without a model argument |
323
+ |---|---|
324
+ | Claude Code | documented to use the main conversation's model, and the session's effort unless the agent definition sets one. True for the built-in general-purpose agent with `CLAUDE_CODE_SUBAGENT_MODEL` unset. Run end to end in this release |
325
+ | Codex | `collaboration.spawn_agent` with no model and no effort. Run end to end in this release |
326
+ | Grok Build | documented to inherit the parent's model (the bundled `general-purpose` agent is `model: inherit`); effort not documented. Not run in this release |
327
+ | Antigravity | no sub-agent tool found in `agy` 1.2.7. Not available |
328
+
329
+ **A specific model the assistant's tool can select.** Describe what the tool
330
+ really accepts in a capability file (start from `omnilane native-context`, add a
331
+ row per exact model and effort) and pass `--native-context FILE` to an ordinary
332
+ `omnilane route`. omnilane uses the sub-agent only when a row matches exactly:
333
+ model, effort, mode, workdir, tools, isolation and lifecycle. Same vendor is not
334
+ same model, and nothing is guessed from the CLIs you have installed.
335
+ `--executor native` fails instead of falling back; `--executor cli` forces the
336
+ external CLI. When a same-vendor target goes out through the CLI only because no
337
+ file was given, dispatch now says so.
338
+
339
+ Either way the sub-agent shares the assistant's tools and filesystem: there is no
340
+ operating-system sandbox, and `advise`/`work` are intent, not enforcement.
341
+ Background, live, named-thread, multi-round, vote and `sysops` work stays on the
342
+ CLI path. Protocol handling needs Python 3.9+. Schemas, the completion file,
343
+ agent reuse and cancellation: [docs/native-executor.md](docs/native-executor.md).
209
344
 
210
345
  <details>
211
346
  <summary><b>Model-role guidance (delegation still required)</b></summary>
@@ -637,6 +772,9 @@ When that fails, run `omnilane whoami` — it either prints a
637
772
  `--effort`, a model alias, no scored row). A model must not assert the human
638
773
  exemption for itself.
639
774
 
775
+ Every refusal is one JSON line on stderr. Read `failed_gate`, `reason` and
776
+ `next_command` first; `eligible_lanes` lists what you can still dispatch.
777
+
640
778
  `runtime-mapping-unverified` — your identity is fine, but the *target* has no
641
779
  proven host-local request selector. Either it was never probed, or its probe
642
780
  failed; `omnilane doctor` reports the count of such configurations and the
@@ -650,7 +788,13 @@ and runner-script hash, and Codex and Claude evidence paths embed version
650
788
  directories, so an upgrade removes the file rather than changing its digest.
651
789
  Tagged evidence degrades only its own vendor; untagged evidence, such as the
652
790
  probe manifest, still closes the whole gate. Doctor names the file and the
653
- vendor; the dispatch skill carries the re-signing runbook.
791
+ vendor; `omnilane resign` re-probes and re-signs it, and the dispatch skill
792
+ carries the runbook behind that command.
793
+
794
+ `target-above-effective-ceiling` — nothing is broken. The target scores above the
795
+ caller. `required_caller_effort` names the effort the calling session would need;
796
+ a caller marked `caller_degraded` was launched by a harness that recorded no
797
+ effort (a Codex heartbeat automation does this) and is held to its model's floor.
654
798
 
655
799
  </details>
656
800
 
@@ -706,6 +850,71 @@ working notes, including per-benchmark caveats, live in
706
850
 
707
851
  ## 📜 Release history
708
852
 
853
+ ## What's new in v0.44.0
854
+
855
+ - **A CLI you patch yourself is re-signed unattended too.** If a local step
856
+ re-signs a vendor CLI adhoc after every update (a post-update patch, for
857
+ instance), the signer check used to hold every such update for `--approve`.
858
+ Run `omnilane resign --trust-adhoc VENDOR` once per vendor and an adhoc update
859
+ in the same install directory now goes through the daily `omnilane resign`
860
+ like a same-signer one. An unsigned executable, an adhoc one in another
861
+ directory, and every other vendor still stop for you. The trust is recorded
862
+ on the overlay, survives later re-signs of any vendor, and is an operator
863
+ action a model never runs. Works for all four vendors.
864
+ - **An expired login says "log in", not "retry later".** `Failed to
865
+ authenticate`, `OAuth session expired`, `Invalid API key`, `Unauthorized` and
866
+ `401` now mark the vendor unprobeable, and the held-vendor message tells you
867
+ to log in first.
868
+ - Upgrade: `npm i -g omnilane@0.44.0`. If you are coming from 0.42.x, run
869
+ `omnilane resign --record-signers` once as well (see the 0.43.0 notes).
870
+
871
+ ## What's new in v0.43.1
872
+
873
+ Install this rather than 0.43.0. In 0.43.0, `build_overlay.py` and `probe.py`
874
+ failed to import on Python 3.9, which broke the first-install overlay build and
875
+ `omnilane resign` on that version. Nothing else changed; everything in the 0.43.0
876
+ notes below applies. Upgrade: `npm i -g omnilane@0.43.1`, then once:
877
+ `omnilane resign --record-signers`.
878
+
879
+ ## What's new in v0.43.0
880
+
881
+ In ten days 0.42.x refused every model caller four times, each time over a fact
882
+ omnilane does not control: a renamed launcher, a runner script changed without a
883
+ re-sign, four vendor CLIs updating themselves in one week, and a Codex automation
884
+ that records no effort. Each became "nothing can be dispatched". This release
885
+ turns each into a narrower, explained outcome, and repairs the common one itself.
886
+
887
+ - **Vendor CLI updated? `omnilane resign`.** It finds what changed, re-probes only
888
+ that vendor, checks the result, swaps it in, confirms with one real dispatch,
889
+ and restores the old overlay if that fails. It re-signs **unattended** only when
890
+ the new executable carries the same code-signing team and sits in the same
891
+ place; anything else stops with the exact `--approve` command for you. Run
892
+ `omnilane resign --record-signers` once, schedule `omnilane resign` daily, and
893
+ updates stop being your problem. Verified on a real Codex self-update
894
+ (0.155.0 → 0.155.1): no approval, every mapping kept, exit 0.
895
+ - **A refusal tells the model what to do.** Every refused dispatch now carries
896
+ `failed_gate`, `reason`, `next_command`, `required_caller_effort`, and
897
+ `eligible_lanes` — the lanes that caller *can* reach right now.
898
+ - **No recorded effort narrows instead of refusing.** A Codex heartbeat
899
+ automation is held to its model's lowest score rather than being refused on
900
+ every lane. Cheap lanes keep working; expensive ones say which effort is needed.
901
+ - **The assistant's own sub-agents.** `omnilane native-context` writes the
902
+ capability file that used to be hand-made, and `omnilane route --inherit` plans
903
+ a worker that is a copy of the caller: no external CLI, no overlay, works even
904
+ when the caller cannot be identified, and is honestly marked as *not* the
905
+ lane's target model. Run end to end in Claude Code and Codex desktop.
906
+ - **Codex: one omnilane command per tool call.** `omnilane whoami; echo $?`
907
+ cannot be identified, `omnilane whoami` alone can. The refusal now says so.
908
+ - **Doctor sees a CLI that moved** beside its old file, and warns, with the
909
+ steps, when no overlay exists at all.
910
+ - **Rewritten skill and tutorial.** The skill is now a five-step procedure a
911
+ model follows; this README walks through letting an assistant drive omnilane.
912
+ - **Limits.** Unattended re-signing relies on macOS code signatures; on Linux, and
913
+ for any unsigned or locally patched CLI, every update asks for `--approve`.
914
+ `--inherit` has not been run inside Grok Build, and Antigravity exposes no
915
+ sub-agent tool. Full detail: [CHANGELOG](CHANGELOG.md).
916
+ - **Upgrade.** `npm i -g omnilane@0.43.0`, then once: `omnilane resign --record-signers`.
917
+
709
918
  ## What's new in v0.42.9
710
919
 
711
920
  - **Codex desktop behind a launcher.** When ChatGPT.app starts its app-server