diff --git a/docs/settings.md b/docs/settings.md index d604d75fa..e3ef950de 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -88,7 +88,7 @@ built-in defaults <- global config <- project config <- CLI overlays <- From highest to lowest: -1. **Runtime overrides** — dedicated CLI flags and feature env vars applied in memory for the current process: `--model`, `--smol`, `--slow`, `--plan`, `--approval-mode`, `--auto-approve`/`--yolo`, `--hide-thinking`, `--no-pty`, `--api-key`, and protocol-mode defaults. Never persisted. +1. **Runtime overrides** — dedicated CLI flags and feature env vars applied in memory for the current process: `--model`, `--smol`, `--slow`, `--plan`, `--approval-mode`, `--auto-approve`/`--yolo`, `--hide-thinking`, `--advisor`, `--no-pty`, `--api-key`, and protocol-mode defaults. Never persisted. 2. **CLI config overlays** — each `--config `; later overlay files override earlier ones. 3. **Project settings** — `/.omp/settings.json` then `/.omp/config.yml` (and contributions from other discovery providers at project level). 4. **Global settings** — `~/.omp/agent/config.yml`. @@ -312,7 +312,7 @@ See [Models](./models.md) for the `models.yml` schema and custom-provider defini ### Advisor -The advisor is a second model that reviews each completed turn and can inject advice into the primary session. Assign a model with `modelRoles.advisor`, then enable it with `advisor.enabled` or `/advisor on`. There is no `--advisor` flag. +The advisor is a second model that reviews each completed turn and can inject advice into the primary session. Assign a model with `modelRoles.advisor`, then enable it with `advisor.enabled`, `/advisor on`, or by launching with the `--advisor` flag. See [Advisor and WATCHDOG.md](./advisor-watchdog.md) for runtime behavior, `WATCHDOG.md` discovery, and bounded catch-up semantics. diff --git a/packages/coding-agent/src/cli/args.ts b/packages/coding-agent/src/cli/args.ts index fe0ca8b71..4557959d0 100644 --- a/packages/coding-agent/src/cli/args.ts +++ b/packages/coding-agent/src/cli/args.ts @@ -33,6 +33,7 @@ export interface Args { appendSystemPrompt?: string; thinking?: Effort; hideThinking?: boolean; + advisor?: boolean; continue?: boolean; resume?: string | true; help?: boolean; @@ -194,6 +195,8 @@ export function parseArgs(inputArgs: string[], extensionFlags?: Map = new Set([ "--no-lsp", "--no-pty", "--hide-thinking", + "--advisor", "--print", "--no-extensions", "--no-skills", diff --git a/packages/coding-agent/src/commands/launch.ts b/packages/coding-agent/src/commands/launch.ts index b18c4efc8..a2c40d8a1 100644 --- a/packages/coding-agent/src/commands/launch.ts +++ b/packages/coding-agent/src/commands/launch.ts @@ -106,6 +106,9 @@ export default class Index extends Command { "hide-thinking": Flags.boolean({ description: "Hide thinking blocks in TUI output (display only, does not disable model thinking)", }), + advisor: Flags.boolean({ + description: "Enable the advisor runtime (passively reviews each turn and injects notes)", + }), hook: Flags.string({ description: "Load a hook/extension file (can be used multiple times)", multiple: true, diff --git a/packages/coding-agent/src/main.ts b/packages/coding-agent/src/main.ts index b730a9b46..4cf6faf6e 100644 --- a/packages/coding-agent/src/main.ts +++ b/packages/coding-agent/src/main.ts @@ -1041,6 +1041,10 @@ export async function runRootCommand( if (parsedArgs.hideThinking) { settingsInstance.override("hideThinkingBlock", true); } + // Apply --advisor CLI flag (ephemeral, not persisted) + if (parsedArgs.advisor) { + settingsInstance.override("advisor.enabled", true); + } await logger.time( "initTheme:final", diff --git a/packages/coding-agent/test/cli-advisor-flag.test.ts b/packages/coding-agent/test/cli-advisor-flag.test.ts new file mode 100644 index 000000000..8e516fd96 --- /dev/null +++ b/packages/coding-agent/test/cli-advisor-flag.test.ts @@ -0,0 +1,38 @@ +import { describe, expect, it } from "bun:test"; +import { parseArgs } from "@oh-my-pi/pi-coding-agent/cli/args"; + +describe("parseArgs — --advisor flag", () => { + it("parses --advisor as a boolean flag", () => { + const result = parseArgs(["--advisor"]); + expect(result.advisor).toBe(true); + }); + + it("defaults advisor to undefined when flag is not provided", () => { + const result = parseArgs([]); + expect(result.advisor).toBeUndefined(); + }); + + it("parses --advisor with other flags", () => { + const result = parseArgs(["--advisor", "--model", "opus", "hello"]); + expect(result.advisor).toBe(true); + expect(result.model).toBe("opus"); + expect(result.messages).toContain("hello"); + }); + + it("parses --advisor in any position", () => { + const result1 = parseArgs(["--advisor", "prompt"]); + const result2 = parseArgs(["prompt", "--advisor"]); + const result3 = parseArgs(["--model", "opus", "--advisor", "prompt"]); + + expect(result1.advisor).toBe(true); + expect(result2.advisor).toBe(true); + expect(result3.advisor).toBe(true); + }); + + it("does not consume a value after --advisor", () => { + const result = parseArgs(["--advisor", "--model", "opus"]); + expect(result.advisor).toBe(true); + expect(result.model).toBe("opus"); + expect(result.messages).toEqual([]); + }); +});