diff --git a/skills/ocx/references/01_management_surface.md b/skills/ocx/references/01_management_surface.md index 5682c76ac71..c8cf409f332 100644 --- a/skills/ocx/references/01_management_surface.md +++ b/skills/ocx/references/01_management_surface.md @@ -834,14 +834,14 @@ Restart the Codex desktop app and app-servers. | Flag | Value | Meaning | |---|---|---| -| `--yes` | boolean | Required: fully quits and relaunches the operator's Codex desktop app and restarts its app-servers. | +| `--yes` | boolean | Required: fully quits and relaunches the operator's Codex desktop app, which may discard unsaved composer drafts, model-picker selections, and pending approval prompts; also restarts its app-servers. | | `--json` | boolean | Emit the restart result as JSON. | JSON mode: `payload`. - `sync --restart-codex` is not a substitute: it restarts only as a side effect after a catalog or cache write, so it cannot restart a healthy install on request. - Restarts the Codex desktop app as well as the app-servers, through the same module the CLI uses. When the proxy itself runs inside the Codex app it refuses instead, because restarting the app would kill the request. -- --yes is mandatory because this interrupts a running editor session, which must never happen because an agent guessed a subcommand. +- --yes is mandatory because this interrupts a running editor session and may discard unsaved composer drafts, model-picker selections, and pending approval prompts; it must never happen because an agent guessed a subcommand. ### `ocx integration native` diff --git a/src/cli/capabilities.ts b/src/cli/capabilities.ts index cb117bcba05..bb153d987c2 100644 --- a/src/cli/capabilities.ts +++ b/src/cli/capabilities.ts @@ -784,7 +784,7 @@ export const CAPABILITIES: readonly Capability[] = [ summary: "Restart the Codex desktop app and app-servers.", routes: [{ method: "POST", path: "/api/system/codex-restart" }], flags: [ - { name: "--yes", value: "boolean", summary: "Required: fully quits and relaunches the operator's Codex desktop app and restarts its app-servers." }, + { name: "--yes", value: "boolean", summary: "Required: fully quits and relaunches the operator's Codex desktop app, which may discard unsaved composer drafts, model-picker selections, and pending approval prompts; also restarts its app-servers." }, { name: "--json", value: "boolean", summary: "Emit the restart result as JSON." }, ], mutates: true, @@ -792,7 +792,7 @@ export const CAPABILITIES: readonly Capability[] = [ details: [ "`sync --restart-codex` is not a substitute: it restarts only as a side effect after a catalog or cache write, so it cannot restart a healthy install on request.", "Restarts the Codex desktop app as well as the app-servers, through the same module the CLI uses. When the proxy itself runs inside the Codex app it refuses instead, because restarting the app would kill the request.", - "--yes is mandatory because this interrupts a running editor session, which must never happen because an agent guessed a subcommand.", + "--yes is mandatory because this interrupts a running editor session and may discard unsaved composer drafts, model-picker selections, and pending approval prompts; it must never happen because an agent guessed a subcommand.", ], }, { diff --git a/src/cli/system-command.ts b/src/cli/system-command.ts index 4e08fcbc49c..acde4e7e9d0 100644 --- a/src/cli/system-command.ts +++ b/src/cli/system-command.ts @@ -202,13 +202,20 @@ export async function handleSystemCommand(argv: string[], deps: RuntimeApiDeps = printData(await runtimeRequest("/api/system/codex-app-server", {}, deps), wantsJson); } else if (sub === "codex-restart") { // --yes required: this fully quits and relaunches the user's Codex desktop app as well as - // restarting app-servers; an agent guessing a subcommand must not interrupt that session. + // restarting app-servers, which can discard unsaved drafts, selections, and approval prompts. const args = [...rest]; const wantsJson = takeFlag(args, "--json"); const yes = takeFlag(args, "--yes"); - if (!yes) throw new CliUsageError("system codex-restart requires --yes: this fully quits and relaunches the Codex desktop app and restarts its app-servers", USAGE); + if (!yes) throw new CliUsageError( + "system codex-restart requires --yes: this fully quits and relaunches the Codex desktop app, so unsaved composer drafts, model-picker selections, and pending approval prompts may be lost; it also restarts the app-servers", + USAGE, + ); rejectArgs(args, USAGE); - printData(await runtimeRequest("/api/system/codex-restart", { method: "POST" }, deps), wantsJson, ["Codex desktop app and app-server restart requested."]); + printData( + await runtimeRequest("/api/system/codex-restart", { method: "POST" }, deps), + wantsJson, + ["Codex desktop app and app-server restart requested. Unsaved composer drafts, model-picker selections, and pending approval prompts may be lost."], + ); } else if (sub === "update") await update(rest, deps); else throw new CliUsageError(`unknown system command ${sub}`, USAGE); }); diff --git a/structure/runtime.md b/structure/runtime.md index 26f5b2a43f8..994c1de6974 100644 --- a/structure/runtime.md +++ b/structure/runtime.md @@ -65,7 +65,7 @@ Catalog-derived reasoning-level diagnostics are escaped only at the human-output ## CLI Codex restart scope -`ocx system codex-restart` requests a full Codex desktop-app restart and app-server restarts through the management endpoint. `src/cli/capabilities.ts` names that scope in its summary and `--yes` description; `src/cli/system-command.ts` explains the desktop interruption when confirmation is missing and sends no restart request. Human output says the restart was requested, while `--json` preserves the complete server result, including skipped or refused desktop outcomes. +`ocx system codex-restart` requests a full Codex desktop-app restart and app-server restarts through the management endpoint. `src/cli/capabilities.ts` names that scope and warns that unsaved composer drafts, model-picker selections, and pending approval prompts may be discarded. `src/cli/system-command.ts` repeats that concrete state-loss warning both when confirmation is missing and after a confirmed human-readable request; the unconfirmed path sends no restart request. `--json` preserves the complete server result, including skipped or refused desktop outcomes. After a CLI catalog/cache write, advisory restart guidance compares each running Codex app-server's start time with the written catalog mtime. It reports only processes proven stale; a fresh or diff --git a/tests/cli/cli-headless-parity.test.ts b/tests/cli/cli-headless-parity.test.ts index 27e9f657ff8..acafc98dc78 100644 --- a/tests/cli/cli-headless-parity.test.ts +++ b/tests/cli/cli-headless-parity.test.ts @@ -30,6 +30,9 @@ describe("ocx system codex-restart confirmation", () => { const warning = errors.mock.calls.flat().join(" "); expect(warning).toContain("requires --yes"); expect(warning).toContain("fully quits and relaunches the Codex desktop app"); + expect(warning).toContain("unsaved composer drafts"); + expect(warning).toContain("model-picker selections"); + expect(warning).toContain("pending approval prompts"); } finally { errors.mockRestore(); } }); @@ -48,6 +51,9 @@ describe("ocx system codex-restart confirmation", () => { else { expect(text).toContain("Codex desktop app"); expect(text).toContain("restart requested."); + expect(text).toContain("Unsaved composer drafts"); + expect(text).toContain("model-picker selections"); + expect(text).toContain("pending approval prompts"); expect(text).not.toContain("restarted"); } } finally { output.mockRestore(); }