Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions devlog/_plan/260906_c_lane/000_plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# C-lane integration coordination

Scope: carry public PRs #3638, #3536, #3631, #3576, #3658 with original-author attribution and user-authorized stacked PR integration into dev. No local tests, typechecks or builds.

The user explicitly requires security working plans and reviews to stay in gitignored scratch. Full numbered diff-level roadmap and evidence live in `.tmp/c-lane/` of the bound d778 checkout; this neutral index is the PABCD plan-unit anchor. This storage override follows AGENTS.md and does not weaken any implementation or verification criterion.

Order: roadmap → service scheduler → account persistence → OAuth configuration → Antigravity refresh/replay → quota diagnostics → final stack integration. OAuth refresh consumes the configuration layer; other layers retain the user-requested stack order. Each layer is independently reviewed and tested on a remote host before cycle close. Hosted full CI runs at each PR head and gates final bottom-up merges.

Original PR and fully solved linked issues close immediately after the matching change is proven on dev. Partial diagnostic work does not close a broader unresolved report. Release branches and live account settings are out of scope.
6 changes: 6 additions & 0 deletions docs-site/src/content/docs/fr/reference/cli/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ Invalide le cache local du sélecteur de modèles de Codex afin qu’il soit rec

Exécute opencodex comme service d’arrière-plan géré à l’ouverture de session — **launchd** sous macOS, **unité utilisateur systemd** sous Linux et **Task Scheduler** sous Windows — qui démarre automatiquement à la connexion et redémarre après un plantage. Les services définissent `OCX_SERVICE=1` afin qu’un redémarrage ne réécrive pas inutilement la configuration Codex.

Les installations via le Planificateur de tâches Windows utilisent une priorité de processus normale (`Priority=4`).
L’ancienne priorité d’arrière-plan (`7`, également la valeur par défaut si le paramètre est omis) peut retarder les réponses
aux contrôles de santé en cas de contention CPU : la zone de notification affiche alors Offline même si le processus fonctionne.
Après la mise à jour, exécutez `ocx service repair` pour migrer cette priorité enregistrée et redémarrer le service.
Une confirmation UAC peut être nécessaire. Une priorité déjà normale ou haute ne déclenche pas, à elle seule, de réenregistrement.

| Sous-commande | Action |
| --- | --- |
| aucune | Installe et démarre le service s’il est absent ; sinon, actualise et redémarre le service existant. Une définition Task Scheduler Windows saine est réutilisée ; une définition obsolète peut être réenregistrée et nécessiter une élévation. |
Expand Down
6 changes: 6 additions & 0 deletions docs-site/src/content/docs/ja/reference/cli/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ Codex のローカル モデル ピッカー キャッシュを無効にし、

opencodex を、ログイン時に自動起動し、クラッシュ時に自動再起動するログイン管理バックグラウンド サービス (macOS **launchd**、Linux **systemd ユーザー ユニット**、Windows **タスク スケジューラ**) として実行します。サービスは `OCX_SERVICE=1` を設定して実行されるため、再起動によって Codex 設定が変更されることはありません。

Windows タスク スケジューラでインストールするサービスは、通常のプロセス優先度(`Priority=4`)を使用します。
以前のバックグラウンド優先度(`7`。省略時もスケジューラの既定値は `7`)では、CPU の競合により
ヘルスチェックへの応答が遅れ、プロセスが動作中でもトレイに Offline と表示されることがあります。
アップグレード後に `ocx service repair` を実行すると、この登録済み優先度を移行してサービスを再起動します。
移行時に UAC の承認が必要になる場合があります。すでに通常または高優先度の場合、優先度だけを理由に再登録しません。

|サブコマンド |アクション |
| --- | --- |
|なし |未インストールなら作成して開始し、既存なら更新して再起動します。正常な Windows タスク スケジューラ定義は再利用しますが、古い定義は再登録され、昇格が必要になる場合があります。 |
Expand Down
6 changes: 6 additions & 0 deletions docs-site/src/content/docs/ko/reference/cli/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,12 @@ Codex의 로컬 모델 선택기 캐시를 무효화하여, 활성 opencodex 카
유닛, Windows **Task Scheduler**). 로그인 시 자동 시작하고 충돌 시 자동 재시작합니다. 서비스 실행은
`OCX_SERVICE=1`을 설정하므로 재시작해도 Codex 설정이 흔들리지 않습니다.

Windows 작업 스케줄러로 설치하는 서비스는 보통 프로세스 우선순위(`Priority=4`)를 사용합니다.
이전의 백그라운드 우선순위(`7`, 생략 시에도 스케줄러 기본값은 `7`)에서는 CPU 경합으로 상태 확인 응답이
늦어져 프로세스가 살아 있어도 트레이에 Offline이 표시될 수 있습니다. 업그레이드 후 `ocx service repair`를
실행하면 등록된 해당 우선순위를 변경하고 서비스를 재시작합니다. 이 과정에서 UAC 승인이 필요할 수 있습니다.
이미 보통 또는 높음 우선순위인 경우 우선순위만을 이유로 다시 등록하지 않습니다.

| 하위 명령 | 동작 |
| --- | --- |
| 없음 | 서비스가 없으면 설치하고 시작하며, 이미 있으면 새로 고쳐 재시작합니다. 정상인 Windows 작업 스케줄러 정의는 재사용하지만, 오래된 정의는 다시 등록되어 관리자 권한 승인이 필요할 수 있습니다. |
Expand Down
6 changes: 6 additions & 0 deletions docs-site/src/content/docs/reference/cli/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,12 @@ Run opencodex as a login-managed background service (macOS **launchd**, Linux **
Windows **Task Scheduler**) that auto-starts on login and auto-restarts on crash. Service runs set
`OCX_SERVICE=1` so a restart does not churn the Codex config.

Windows Task Scheduler installs use normal process priority (`Priority=4`). The older background
priority (`7`, also the scheduler default when omitted) can delay the proxy's health responses under
CPU contention, making the tray report Offline even while the process is alive. After upgrading,
run `ocx service repair` to migrate that registered priority and restart the service. This migration
may request UAC approval; a priority already set to normal or high does not itself trigger replacement.

The Windows wrapper verifies its baked Bun runtime and CLI entry before every start attempt. If an
interrupted package update removed either file, it logs one `installation is incomplete` message and
stops instead of retrying the same missing executable every five seconds. Reinstall opencodex, then
Expand Down
6 changes: 6 additions & 0 deletions docs-site/src/content/docs/ru/reference/cli/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,12 @@ unit**, Windows **Task Scheduler**), которая автоматически
перезапускается при crash. Запуски службы выставляют `OCX_SERVICE=1`, чтобы restart не дёргал
конфиг Codex.

При установке через Windows Task Scheduler используется обычный приоритет процесса (`Priority=4`).
Прежний фоновый приоритет (`7`, также значение планировщика по умолчанию при отсутствии параметра)
при конкуренции за CPU может задерживать ответы проверки состояния: трей показывает Offline, хотя процесс работает.
После обновления выполните `ocx service repair`, чтобы изменить этот зарегистрированный приоритет и перезапустить службу.
Может потребоваться подтверждение UAC. Если уже задан обычный или высокий приоритет, сам приоритет не вызывает перерегистрацию.

| Подкоманда | Действие |
| --- | --- |
| none | Установить и запустить службу, если её нет; иначе обновить и перезапустить существующую службу. Исправная конфигурация Windows Task Scheduler используется повторно; устаревшая может быть перерегистрирована и потребовать повышения прав. |
Expand Down
6 changes: 6 additions & 0 deletions docs-site/src/content/docs/tr/reference/cli/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,12 @@ kullanıcı birimi**, Windows **Görev Zamanlayıcı**) olarak çalıştırın.
çalıştırmaları `OCX_SERVICE=1` ayarlar, böylece bir yeniden başlatma Codex
yapılandırmasını dalgalandırmaz.

Windows Görev Zamanlayıcı kurulumları normal işlem önceliğini (`Priority=4`) kullanır. Eski arka plan
önceliği (`7`; değer belirtilmediğinde de zamanlayıcının varsayılanı `7` olur), CPU çekişmesi sırasında
sağlık denetimi yanıtlarını geciktirebilir ve işlem çalışırken bile sistem tepsisinde Offline görünmesine neden olabilir.
Güncellemeden sonra kayıtlı bu önceliği değiştirmek ve servisi yeniden başlatmak için `ocx service repair` komutunu çalıştırın.
UAC onayı gerekebilir. Zaten normal veya yüksek öncelik ayarlanmışsa yalnızca öncelik nedeniyle yeniden kayıt yapılmaz.

| Alt komut | Eylem |
| --- | --- |
| none | Servis yoksa kurup başlatın; varsa yenileyip yeniden başlatın. Sağlıklı bir Windows Task Scheduler tanımı yeniden kullanılır; eski bir tanım yeniden kaydedilebilir ve yükseltme gerektirebilir. |
Expand Down
4 changes: 4 additions & 0 deletions docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ ocx status --json

将 opencodex 作为登录管理的后台服务运行(macOS **launchd**、Linux **systemd user unit**、Windows **Task Scheduler**),在登录时自动启动,在崩溃时自动重启。服务运行会设置 `OCX_SERVICE=1`,因此重启时不会反复改动 Codex 配置。

Windows 任务计划程序安装使用普通进程优先级(`Priority=4`)。旧的后台优先级(`7`,省略时调度器也默认使用 `7`)
可能在 CPU 竞争时延迟健康检查响应,导致进程仍存活时托盘显示 Offline。升级后运行 `ocx service repair`,
即可迁移该注册优先级并重启服务;过程中可能需要批准 UAC 提示。已设为普通或高优先级时,不会仅因优先级而重新注册。

| 子命令 | 操作 |
| --- | --- |
| none | 服务不存在时安装并启动;已存在时刷新并重启。正常的 Windows 任务计划程序定义会复用;过时定义可能会重新注册并需要提升权限。 |
Expand Down
4 changes: 4 additions & 0 deletions docs-site/src/content/docs/zh-tw/reference/cli/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ ocx status --json

將 opencodex 作為登入管理的背景服務執行(macOS **launchd**、Linux **systemd user unit**、Windows **Task Scheduler**),在登入時自動啟動並在崩潰時自動重啟。服務執行時設定 `OCX_SERVICE=1`,使重啟不會折騰 Codex 設定。

Windows 工作排程器安裝使用一般處理程序優先順序(`Priority=4`)。舊的背景優先順序(`7`,省略時排程器也預設使用 `7`)
可能在 CPU 競爭時延遲健康檢查回應,導致處理程序仍在執行時系統匣顯示 Offline。升級後執行 `ocx service repair`,
即可遷移該註冊優先順序並重新啟動服務;過程中可能需要核准 UAC 提示。已設為一般或高優先順序時,不會僅因優先順序而重新註冊。

| 子指令 | 動作 |
| --- | --- |
| 無 | 服務不存在時安裝並啟動;已存在時重新整理並重啟。正常的 Windows 工作排程器定義會沿用;過時的定義可能會重新註冊並需要提高權限。 |
Expand Down
8 changes: 6 additions & 2 deletions src/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1926,7 +1926,7 @@ export function buildWindowsTaskXml(
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
<Priority>4</Priority>
<RestartOnFailure>
<Interval>PT1M</Interval>
<Count>3</Count>
Expand Down Expand Up @@ -2972,6 +2972,10 @@ export async function repairService(deps: RepairServiceDeps = {}): Promise<void>
const identityUpgradeNeeded = registrationHealthy
&& preferredSid !== undefined
&& !windowsTaskHasSessionRecoveryTriggers(triggers, preferredSid);
// Omitted Priority also defaults to 7; background priority can starve health probes under CPU load.
const priorityUpgradeNeeded = registrationHealthy && taskXmlOptionalValueEquals(
taskXmlSection(taskXmlWithoutCommentsAndCdata(registeredXml), "Settings"), "Priority", "7",
);
const refreshableLegacy = windowsTaskRegistrationRefreshableLegacy(
registeredXml,
deps.schedulerWscript,
Expand All @@ -2998,7 +3002,7 @@ export async function repairService(deps: RepairServiceDeps = {}): Promise<void>
// Re-register only when the registered XML is actually stale, so the ordinary repair
// stays free of `schtasks /create` and its UAC prompt.
let startExpectedXml = registeredXml;
if (!registrationHealthy || identityUpgradeNeeded) {
if (!registrationHealthy || identityUpgradeNeeded || priorityUpgradeNeeded) {
// The task was stopped above, so a failed replacement must not exit here: `/create /f`
// can be rejected, elevation can be cancelled, and staging or verification can fail.
// Any of those would leave a previously runnable proxy stopped and the user worse off
Expand Down
32 changes: 32 additions & 0 deletions tests/service/service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ describe("Windows service task", () => {
expect(xml).toContain("<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>");
expect(xml).toContain("<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>");
expect(xml).toContain("<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>");
expect(xml).toContain("<Priority>4</Priority>");
expect(xml).toContain("<RestartOnFailure>");
expect(xml).toContain("<Interval>PT1M</Interval>");
expect(xml).toContain("<Count>3</Count>");
Expand Down Expand Up @@ -2601,6 +2602,37 @@ describe("service repair", () => {
expect(calls).toEqual(["env", "auth", "stop", "assets", "reregister", "start", "state"]);
});

test.each(["7", "omitted", "4", "1"])("repair migrates only the background scheduler priority (%s)", async priority => {
const calls: string[] = [];
const previousXml = buildWindowsTaskXml().replace(/<Priority>\d<\/Priority>/,
priority === "omitted" ? "" : `<Priority>${priority}</Priority>`);
const shouldUpgrade = priority === "7" || priority === "omitted";
let attemptNonce = "";
await repairService({
platform: "win32",
diagnose: () => baseDiag,
assertEnv: () => {},
assertAuth: () => {},
resolveExpectedUserId: () => TEST_WINDOWS_TASK_SID,
stopScheduler: () => { calls.push("stop"); },
writeSchedulerAssets: () => { calls.push("assets"); },
readSchedulerXml: () => attemptNonce
? buildWindowsTaskXml(undefined, undefined, attemptNonce)
: previousXml,
reregisterScheduler: async (nonce, registeredXml) => {
expect(registeredXml).toBe(previousXml);
expect(buildWindowsTaskXmlDocument()).toContain("<Priority>4</Priority>");
calls.push("reregister");
attemptNonce = nonce;
},
startScheduler: () => { calls.push("start"); },
writeSchedulerState: () => { calls.push("state"); },
});
expect(calls).toEqual(shouldUpgrade
? ["stop", "assets", "reregister", "start", "state"]
: ["stop", "assets", "start", "state"]);
});

test("repair migrates an exact legacy account name to the preferred SID", async () => {
const calls: string[] = [];
const sid = "S-1-5-21-111-222-333-1001";
Expand Down
Loading