diff --git a/devlog/_plan/260906_c_lane/000_plan.md b/devlog/_plan/260906_c_lane/000_plan.md new file mode 100644 index 0000000000..8f7385965e --- /dev/null +++ b/devlog/_plan/260906_c_lane/000_plan.md @@ -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. diff --git a/docs-site/src/content/docs/fr/reference/cli/lifecycle.md b/docs-site/src/content/docs/fr/reference/cli/lifecycle.md index ac152db316..59652bbaef 100644 --- a/docs-site/src/content/docs/fr/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/fr/reference/cli/lifecycle.md @@ -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. | diff --git a/docs-site/src/content/docs/ja/reference/cli/lifecycle.md b/docs-site/src/content/docs/ja/reference/cli/lifecycle.md index d6e9425b52..b187ff7fd3 100644 --- a/docs-site/src/content/docs/ja/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/ja/reference/cli/lifecycle.md @@ -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 タスク スケジューラ定義は再利用しますが、古い定義は再登録され、昇格が必要になる場合があります。 | diff --git a/docs-site/src/content/docs/ko/reference/cli/lifecycle.md b/docs-site/src/content/docs/ko/reference/cli/lifecycle.md index 081c791bbb..4847614674 100644 --- a/docs-site/src/content/docs/ko/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/ko/reference/cli/lifecycle.md @@ -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 작업 스케줄러 정의는 재사용하지만, 오래된 정의는 다시 등록되어 관리자 권한 승인이 필요할 수 있습니다. | diff --git a/docs-site/src/content/docs/reference/cli/lifecycle.md b/docs-site/src/content/docs/reference/cli/lifecycle.md index 0e91777061..e75a2b6241 100644 --- a/docs-site/src/content/docs/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/reference/cli/lifecycle.md @@ -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 diff --git a/docs-site/src/content/docs/ru/reference/cli/lifecycle.md b/docs-site/src/content/docs/ru/reference/cli/lifecycle.md index 30b4e627a3..1ace7cc10f 100644 --- a/docs-site/src/content/docs/ru/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/ru/reference/cli/lifecycle.md @@ -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 используется повторно; устаревшая может быть перерегистрирована и потребовать повышения прав. | diff --git a/docs-site/src/content/docs/tr/reference/cli/lifecycle.md b/docs-site/src/content/docs/tr/reference/cli/lifecycle.md index e26f4c8662..6a7a565139 100644 --- a/docs-site/src/content/docs/tr/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/tr/reference/cli/lifecycle.md @@ -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. | diff --git a/docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md b/docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md index dfae403438..f0c6ee5a59 100644 --- a/docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/zh-cn/reference/cli/lifecycle.md @@ -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 任务计划程序定义会复用;过时定义可能会重新注册并需要提升权限。 | diff --git a/docs-site/src/content/docs/zh-tw/reference/cli/lifecycle.md b/docs-site/src/content/docs/zh-tw/reference/cli/lifecycle.md index bb377466fd..71d575e774 100644 --- a/docs-site/src/content/docs/zh-tw/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/zh-tw/reference/cli/lifecycle.md @@ -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 工作排程器定義會沿用;過時的定義可能會重新註冊並需要提高權限。 | diff --git a/src/service.ts b/src/service.ts index b37e88c3db..fa8770ec55 100644 --- a/src/service.ts +++ b/src/service.ts @@ -1926,7 +1926,7 @@ export function buildWindowsTaskXml( true false PT0S - 7 + 4 PT1M 3 @@ -2972,6 +2972,10 @@ export async function repairService(deps: RepairServiceDeps = {}): Promise 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, @@ -2998,7 +3002,7 @@ export async function repairService(deps: RepairServiceDeps = {}): Promise // 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 diff --git a/tests/service/service.test.ts b/tests/service/service.test.ts index e36a2785b6..2eadf7f4fc 100644 --- a/tests/service/service.test.ts +++ b/tests/service/service.test.ts @@ -491,6 +491,7 @@ describe("Windows service task", () => { expect(xml).toContain("false"); expect(xml).toContain("false"); expect(xml).toContain("PT0S"); + expect(xml).toContain("4"); expect(xml).toContain(""); expect(xml).toContain("PT1M"); expect(xml).toContain("3"); @@ -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(/\d<\/Priority>/, + priority === "omitted" ? "" : `${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("4"); + 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";