diff --git a/docs-ai/055-agent-profile-runtimes/000-plan.md b/docs-ai/055-agent-profile-runtimes/000-plan.md index 6e2bb4f2..d5749bd0 100644 --- a/docs-ai/055-agent-profile-runtimes/000-plan.md +++ b/docs-ai/055-agent-profile-runtimes/000-plan.md @@ -150,10 +150,13 @@ and final PR, then commit in reviewable layers and submit a non-draft PR to ## Amendments -- The launch catalog is keyed by `AgentProfileRuntime`, not only - `DetectedAgent`. Pi and Oh My Pi deliberately share the `.pi` detection - family, but require distinct executables, icons, option contracts, and - availability checks. +- Updated 2026-08-01: Correct execution-policy semantics and separate Pi from + Oh My Pi throughout detection and session identity — see + [002-execution-policy-and-pi-omp-separation.md](002-execution-policy-and-pi-omp-separation.md). +- The launch catalog remains keyed by `AgentProfileRuntime`, with a one-to-one + mapping to canonical detection identity. Pi and Oh My Pi now have distinct + executables, icons, option contracts, availability checks, heuristics, and + session stores. - A relocated Profile home now records its native session/config root separately from the provisioned root. Gemini nests state under `.gemini`, while Cline uses an explicit `data/tasks` subtree; assuming both paths are diff --git a/docs-ai/055-agent-profile-runtimes/001-action.md b/docs-ai/055-agent-profile-runtimes/001-action.md index df4aac79..b230ff46 100644 --- a/docs-ai/055-agent-profile-runtimes/001-action.md +++ b/docs-ai/055-agent-profile-runtimes/001-action.md @@ -12,12 +12,12 @@ Agent Profiles now support every launch runtime represented by Prowl's current agent catalog: Claude Code, Codex, Gemini CLI, Cursor Agent, Cline, OpenCode, GitHub Copilot, Kimi Code, Factory Droid, Amp, Qoder CLI, Qwen Code, Grok -Build, Pi, and Oh My Pi. This is fifteen launch runtimes over fourteen -`DetectedAgent` families because Pi and Oh My Pi intentionally share process -detection while remaining different Profile targets. +Build, Pi, and Oh My Pi. This is fifteen launch runtimes over fifteen +`DetectedAgent` families: Pi and Oh My Pi are now independent process, +heuristic, display, and session identities. The implementation does not pretend that every CLI has the same contract. -Model, reasoning effort, unrestricted execution, and Dedicated Home controls +Model, reasoning effort, execution mode, and Dedicated Home controls are rendered only when the selected launch adapter can satisfy their Prowl semantics. The full positive/negative matrix and the source checks used to exclude false positives are recorded in the linked research document. @@ -29,12 +29,15 @@ exclude false positives are recorded in the linked research document. - Split Profile launch from side-effect-free session resume. All fifteen runtimes have launch adapters, while only Claude Code and Codex remain in the proven resume registry. -- Keyed launch metadata by `AgentProfileRuntime` so Pi and Oh My Pi preserve - their executable, icon, availability probe, and option differences while - still mapping to the `.pi` detection family. +- Kept launch metadata keyed by `AgentProfileRuntime`, with a one-to-one + canonical detection mapping so Pi and Oh My Pi remain independent. - Added explicit field capabilities and per-runtime invocation rendering for interactive, seeded-interactive, and headless intents. Unsupported intents, notably Amp's seeded interactive mode, fail as typed adapter errors. +- Replaced the one-sided unrestricted capability with adapter-declared + execution-mode choices. Cline, Grok, and Oh My Pi render explicit guarded + and least-restricted invocations; Droid, Amp, and Pi hide the field because + their interactive CLIs cannot express both Prowl modes. - Kept user Extra Arguments last-wins for ordinary options, but append managed home arguments after them so a bound Profile cannot be redirected away from the provisioned directory. @@ -50,6 +53,8 @@ exclude false positives are recorded in the linked research document. - Added rooted session layouts and pid-artifact lookup where those runtimes store native identity beneath the relocated root. Surface launch metadata now carries `sessionConfigRoot` independently from `dedicatedHome`. +- Added OMP's native `~/.omp/agent/sessions` marker and home-relative directory + encoding independently from Pi's `~/.pi/agent/sessions` layout. - Deliberately omitted Dedicated Home for Cursor, OpenCode, Kimi, Droid, Amp, and Grok after documentation/source inspection showed that available overrides relocate only part of their mutable state. @@ -57,7 +62,8 @@ exclude false positives are recorded in the linked research document. ### Profile and workflow UX - Expanded persisted runtime tokens without changing existing Claude/Codex - encodings. OMP keeps its own icon even though live detection reports Pi. + encodings. OMP now reports its own `.omp` detection identity and keeps its + icon without launch-metadata recovery. - Made the Agent Profile editor conditional: unsupported model, reasoning, execution, and home controls are absent rather than present-but-ignored. Switching to a runtime without full home relocation clears the binding. @@ -74,11 +80,23 @@ exclude false positives are recorded in the linked research document. - Installed the previously missing Qwen Code 0.21.2 through its official Homebrew distribution. It launched and was detected, but no paid provider credential was added, so authenticated task execution is marked Best Effort. -- Launched every runtime in a disposable Prowl tab and confirmed the expected - detection family. Cline was corrected to `cline --tui`; bare `cline` opens - its Kanban UI and is not an agent-terminal launch. +- Launched every runtime in a disposable Prowl tab and confirmed interactive + startup. Cline was corrected to `cline --tui`; bare `cline` opens its Kanban + UI and is not an agent-terminal launch. - Performed source-level false-positive checks for partial home relocation and - OMP's `PI_CODING_AGENT_DIR` behavior before finalizing the unsupported rows. + OMP's approval, session, and `PI_CODING_AGENT_DIR` behavior before finalizing + the unsupported rows. +- Rechecked permission semantics against current help and official sources. + Pi's default is intentionally unprompted; Cline and OMP expose inverse + guarded flags; Grok requires independent permission and sandbox flags; Droid + exposes a third-state autonomy scale; Amp's guarded behavior is settings-only. +- Re-ran guarded launches through `prowl`: Cline visibly disabled auto-approve, + Grok accepted `--permission-mode default`, and OMP accepted + `--approval-mode always-ask` and printed its native `omp --resume ` path. + The installed baseline also reproduced the erroneous OMP-as-Pi identity. A + simultaneous Debug instance could not mount Ghostty surfaces, so the fixed + `.omp` payload is verified by production-path tests rather than claimed as a + post-change live observation. - Opened the latest Debug app through the native Settings UI and confirmed the Add Profile menu exposes all fifteen launch runtimes without creating or editing user Profiles. @@ -91,12 +109,12 @@ exclude false positives are recorded in the linked research document. availability probes, and Handoff admission. - The first focused TDD run failed at the expected missing runtime/capability assertions before implementation. -- `make test` passed with **2164 tests and zero failures**. The five emitted +- `make test` passed with **2167 tests and zero failures**. The five emitted dependency-scan warnings are pre-existing package declaration warnings. - `make check` passed. - `make build-app` passed with zero warnings and zero errors. -- CLI sources and contracts were not changed, so the CLI-specific build, - smoke, and socket integration gates were not required. +- `make build-cli` and `make test-cli-smoke` passed. +- `make test-cli-integration` passed all **64 tests**. ## Known limitations and follow-up seams @@ -118,5 +136,7 @@ exclude false positives are recorded in the linked research document. session layouts, and regression coverage. - `c1b7ff0c` — runtime research, shipped matrix, agent manual, and this durable design/action record. +- `cfb6ce75` — explicit guarded/least-restricted execution mappings and the + independent Pi/OMP detection, heuristic, session, and CLI identities. - [PR #643](https://github.com/onevcat/Prowl/pull/643) targets `onevcat/Prowl:main` as a non-draft pull request. diff --git a/docs-ai/055-agent-profile-runtimes/002-execution-policy-and-pi-omp-separation.md b/docs-ai/055-agent-profile-runtimes/002-execution-policy-and-pi-omp-separation.md new file mode 100644 index 00000000..534dbe2d --- /dev/null +++ b/docs-ai/055-agent-profile-runtimes/002-execution-policy-and-pi-omp-separation.md @@ -0,0 +1,96 @@ +# 055.002 — Execution Policy Semantics and Pi/OMP Separation + +| | | +| --- | --- | +| **Status** | Implemented | +| **Date** | 2026-08-01 | +| **Primary PR** | [#643](https://github.com/onevcat/Prowl/pull/643) | +| **Related** | [Plan](000-plan.md), [runtime research](research-agent-profile-runtimes.md), `docs/components/agent-profiles.md`, `docs/components/agent-detection.md`, `docs/components/handoff.md` | + +## Context + +The first adapter expansion treated a missing launch-wide bypass flag as proof +that an execution-mode picker should be hidden. That test was incomplete for +runtimes whose default is already auto-approved, or whose guarded mode requires +an explicit inverse flag. It also retained the historical assumption that Pi +and Oh My Pi are one detected agent even though their executables, permission +models, UI, default homes, session directories, and resume behavior have +diverged. + +Both assumptions create product bugs. A Profile labelled Standard may launch a +default-unrestricted CLI, and an OMP pane may be attributed to Pi's session +store. Future handoff and cross-agent workflows would then inherit the wrong +runtime identity and capability set. + +## Verified execution-policy findings + +| Runtime | Runtime default | Guarded launch | Least-restricted launch | Profile decision | +| --- | --- | --- | --- | --- | +| Cline CLI | Auto-approve enabled | `--auto-approve false` | `--auto-approve true` | Show picker; render both modes explicitly | +| Factory Droid | Tiered autonomy; headless default is read-only | Bare / autonomy levels | Full bypass exists only on `droid exec` | Hide picker for interactive Profiles | +| Amp | No approval prompts unless settings enable its permission plugin | Settings/plugin only | Bare default | Hide picker; preserve runtime configuration | +| Grok Build | Ask permissions; sandbox is independently off by default | `--permission-mode default` | `--permission-mode bypassPermissions --sandbox off` | Show picker; render both permission and sandbox intent | +| Pi | No built-in permission prompts or sandbox | Extensions/tool filtering only | Bare default | Hide picker; preserve runtime configuration | +| Oh My Pi | `tools.approvalMode: yolo` | `--approval-mode always-ask` | `--approval-mode yolo` | Show picker; render both modes explicitly | + +Runtime and managed policies remain authoritative. For example, OMP per-tool +`prompt`/`deny` rules and Grok deny rules or hooks still apply after a Profile +requests the least-restricted mode. Prowl must describe the launch request, not +promise that external policy can be bypassed. + +## Change + +1. Replace the one-sided `supportsUnrestrictedExecution` capability with an + execution-mode selection capability. Adapters that expose the control must + render both `.standard` and `.unrestricted` honestly; runtimes that cannot + represent both hide the control. +2. Add inverse guarded-mode rendering for Cline and OMP, and add Grok's verified + permission-plus-sandbox mapping. Keep Droid, Amp, and Pi on runtime-default + behavior with no Profile permission selector. +3. Preserve the existing runtime-change normalization boundary. Switching + runtimes clears model, reasoning, extra argv, environment overrides, and + execution mode; tests will specifically cover transitions from a supported + permission control to an unsupported one. +4. Add `DetectedAgent.omp` and make `AgentProfileRuntime` map one-to-one to Pi + and OMP. Remove executable-name and icon fallbacks that only existed to + recover OMP identity after it had collapsed into Pi. +5. Give OMP its own process aliases, screen-state entry point, default session + marker (`~/.omp/agent/sessions`), home-relative session-directory encoder, + rooted account-bound session layout, display identity, handoff token, and + tests. Pi retains only Pi's own process, home, session layout, and UI rules. +6. Split the research matrix's ambiguous `Safe Prowl resume` column into native + resume/fork support and handoff-safe source-briefing admission. Native + `--resume` may append to the source session; Prowl admission additionally + requires verified source immutability, output capture, confidence gates, + timeout behavior, and failure fallback. + +## Outcome and validation + +- Focused tests first failed for the missing Cline/Grok/OMP execution mappings + and independent OMP identity, then passed after implementation. The affected + suite covered 201 tests; a dedicated OMP home-relative session-root test was + added after the first green pass. +- Runtime switching now resets an existing Unrestricted selection before a + runtime without execution-mode choices is displayed. Persisted stale state is + also normalized by the launch plan. +- Classifier, session-path, rooted-session, screen-state, Active Agents, CLI + payload, runtime catalog, and editor tests cover `DetectedAgent.omp` as an + independent family. +- `make test` passed 2167 tests; `make check`, `make build-app`, `make build-cli`, + `make test-cli-smoke`, and 64 CLI integration tests all passed. +- Live Prowl panes proved that Cline's guarded launch disables auto-approve, + Grok accepts its guarded permission mode, OMP accepts `always-ask`, and OMP + exposes native `--resume`. The installed baseline simultaneously reproduced + the OMP-as-Pi bug. A second Debug instance could not mount Ghostty surfaces + while the production app remained active, so the fixed `.omp` result is + covered end-to-end by production-path tests rather than recorded as a false + live positive. + +## Refs + +- [Pi coding-agent README](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/README.md) +- [Cline CLI reference](https://docs.cline.bot/cli/cli-reference) +- [Droid CLI reference](https://docs.factory.ai/reference/cli-reference) +- [Amp Owner's Manual](https://ampcode.com/manual) +- [Grok permissions](https://docs.x.ai/build/features/permissions) and [sandbox](https://docs.x.ai/build/features/sandbox) +- [Oh My Pi approval mode](https://github.com/can1357/oh-my-pi/blob/main/docs/approval-mode.md) and [session operations](https://github.com/can1357/oh-my-pi/blob/main/docs/session-operations-export-share-fork-resume.md) diff --git a/docs-ai/055-agent-profile-runtimes/research-agent-profile-runtimes.md b/docs-ai/055-agent-profile-runtimes/research-agent-profile-runtimes.md index 9a672bb6..8533f972 100644 --- a/docs-ai/055-agent-profile-runtimes/research-agent-profile-runtimes.md +++ b/docs-ai/055-agent-profile-runtimes/research-agent-profile-runtimes.md @@ -26,24 +26,23 @@ Evidence labels: ## Prowl catalog -`DetectedAgent` has fourteen families. Agent Profiles expose fifteen launch -runtimes because `pi`, `omp`, and `oh-my-pi` are intentionally classified as -the same Pi family while Pi and Oh My Pi remain different executables and -Profile option contracts. +`DetectedAgent` and Agent Profiles now expose the same fifteen runtime +families. `pi` identifies Pi; `omp` and `oh-my-pi` identify Oh My Pi. The two +runtimes are independent even though OMP originated as a Pi fork. -| Detection token | Launch runtime | Installed version | Live Prowl result | +| Detection token | Launch runtime | Installed version | Prowl validation | | --- | --- | --- | --- | | `pi` | Pi / `pi` | 0.82.0 | Detected as `pi` | -| `pi` | Oh My Pi / `omp` | 17.2.1 | Detected as `pi`, OMP icon token preserved by launch Profile | +| `omp` | Oh My Pi / `omp` | 17.2.1 | Live guarded launch reproduced the installed baseline's incorrect `pi` collapse; independent `.omp` output is covered by the shipped production-path tests | | `claude` | Claude Code / `claude` | 2.1.220 | Detected as `claude` | | `codex` | Codex / `codex` | 0.146.0 | Detected as `codex` | | `gemini` | Gemini CLI / `gemini` | 0.46.0 | Detected as `gemini`; workspace trust screen shown | | `cursor-agent` | Cursor Agent / `cursor-agent` | 2026.05.09-0afadcc | Detected as `cursor-agent` | -| `cline` | Cline CLI / `cline --tui` | 2.18.0 | Detected as `cline`; bare `cline` was rejected as the Profile entry because it opens Kanban | +| `cline` | Cline CLI / `cline --tui` | 3.0.48 | Detected as `cline`; bare `cline` was rejected as the Profile entry because it opens Kanban | | `opencode` | OpenCode / `opencode` | 1.17.18 | Detected as `opencode` | | `copilot` | GitHub Copilot CLI / `copilot` | 1.0.70 | Detected as `copilot`; workspace trust screen shown | | `kimi` | Kimi Code CLI / `kimi` | 1.41.0 | Detected as `kimi`; update notice shown | -| `droid` | Factory Droid / `droid` | 0.170.0 | Detected as `droid` | +| `droid` | Factory Droid / `droid` | 0.186.0 | Detected as `droid` | | `amp` | Amp / `amp` | 0.0.1783746383-g8a60c7 | Detected as `amp` | | `qodercli` | Qoder CLI / `qodercli` | 1.0.48 | Detected as `qodercli`; existing login accepted | | `qwen` | Qwen Code / `qwen` | 0.21.2 | Installed during research; detected as `qwen`; provider setup required | @@ -54,29 +53,39 @@ returned to the original development pane. No missing credential prevented interactive startup or Prowl detection. Qwen had no configured provider, so authenticated task execution remains **Best effort** rather than Live proof. +The execution-policy follow-up was also exercised live: Cline rendered +`Auto-approve all disabled` under `--auto-approve false`; Grok accepted +`--permission-mode default`; and OMP accepted `--approval-mode always-ask`. +The installed pre-PR app reported that OMP pane as `pi`, reproducing the split's +product bug, and OMP printed a concrete `omp --resume ` command on exit. +The newly built Debug app could not host a second terminal runtime beside the +running production app (`runtimeSurfaces=0`), so post-split `.omp` output is +validated by classifier, session resolver, Active Agents, and CLI payload tests +rather than mislabeled as a same-process live check. + ## Shipped capability matrix -Legend: ✅ exposed by Agent Profiles; — deliberately hidden because the CLI -contract cannot satisfy Prowl's field semantics; ⚠️ CLI has related behavior, -but it is not admitted to that Prowl workflow. - -| Runtime | Interactive / prompt / headless | Model | Reasoning | Unrestricted | Dedicated home | Safe Prowl resume | Profile | -| --- | --- | --- | --- | --- | --- | --- | --- | --- | -| Claude Code | ✅ / ✅ / `-p` | ✅ | `--effort` | `--dangerously-skip-permissions` | `CLAUDE_CONFIG_DIR` | ✅ forked print resume | ✅ | -| Codex | ✅ / ✅ / `exec` | ✅ | `model_reasoning_effort` | bypass approvals and sandbox | `CODEX_HOME` | ✅ ephemeral exec resume | ✅ | -| Gemini CLI | ✅ / `--prompt-interactive` / `--prompt` | ✅ | — | YOLO plus sandbox disabled | `GEMINI_CLI_HOME`; sessions under `.gemini` | ⚠️ resume exists, safe fork not admitted | ✅ | -| Cursor Agent | ✅ / positional / `--print` | ✅ | — | YOLO plus sandbox disabled | **— no verified full-state relocation** | ⚠️ resume exists, safe fork not admitted | ✅ | -| Cline CLI | `--tui` / `--tui ` / positional | ✅ | `--thinking` | — | `--config`, `--data-dir`, and `--hooks-dir` | ⚠️ task resume exists, safe fork not admitted | ✅ | -| OpenCode | ✅ / `--prompt` / `run` | ✅ | `--variant` | `--auto` | **— config-dir only; auth and sessions remain in XDG data** | ⚠️ fork flag exists, protocol not admitted | ✅ | -| GitHub Copilot | ✅ / `--interactive` / `--prompt` | ✅ | `--reasoning-effort` | `--allow-all` | `COPILOT_HOME` | ⚠️ resume exists, safe fork not admitted | ✅ | -| Kimi Code | ✅ / `--prompt` / `--print --prompt` | ✅ | — (boolean thinking is not an effort scale) | `--yolo` | **— alternate config/share paths do not relocate every data class** | ⚠️ resume/fork exists, protocol not admitted | ✅ | -| Factory Droid | ✅ / positional / `exec` | **— interactive CLI has no model option** | — | — (`--auto` is an autonomy level) | **— settings overlay only** | ⚠️ fork exists, protocol not admitted | ✅ | -| Amp | ✅ / **— seeded interactive prompt unavailable** / `--execute` | **— `--mode` is not a model selector** | `--effort` | — | **— settings/log paths do not relocate auth and threads** | ⚠️ continue exists, safe fork not admitted | ✅ bare launch | -| Qoder CLI | ✅ / `--prompt-interactive` / `--print` | ✅ | `--reasoning-effort` | skip permissions | `--config-dir` | ⚠️ fork-session exists, protocol not admitted | ✅ | -| Qwen Code | ✅ / `--prompt-interactive` / `--prompt` | ✅ | `--reasoning-effort` | YOLO plus sandbox disabled | `QWEN_HOME` | ⚠️ resume exists, safe fork not admitted | ✅ Best effort | -| Grok Build | ✅ / positional / `--single` | ✅ | `--reasoning-effort` | **— auto-approval does not prove sandbox removal** | **— no verified full-state relocation** | ⚠️ fork-session exists, protocol not admitted | ✅ | -| Pi | ✅ / positional / `--print` | ✅ | `--thinking` | — (no launch-wide bypass contract) | `PI_CODING_AGENT_DIR` | ⚠️ fork exists, protocol not admitted | ✅ | -| Oh My Pi | ✅ / positional / `--print` | ✅ | `--thinking` | `--approval-mode yolo` | `PI_CODING_AGENT_DIR` | ⚠️ resume exists, safe fork not admitted | ✅ | +Legend: ✅ exposed or admitted by Prowl; — deliberately hidden because the CLI +contract cannot satisfy Prowl's field semantics; ⚠️ native behavior exists but +is not admitted to the stricter Prowl workflow. + +| Runtime | Interactive / prompt / headless | Model | Reasoning | Execution mode selection | Dedicated home | Native resume / fork | Handoff-safe source briefing | Profile | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| Claude Code | ✅ / ✅ / `-p` | ✅ | `--effort` | bare / `--dangerously-skip-permissions` | `CLAUDE_CONFIG_DIR` | ✅ / ✅ | ✅ forked print resume | ✅ | +| Codex | ✅ / ✅ / `exec` | ✅ | `model_reasoning_effort` | guarded / bypass approvals and sandbox | `CODEX_HOME` | ✅ / ephemeral | ✅ ephemeral exec resume | ✅ | +| Gemini CLI | ✅ / `--prompt-interactive` / `--prompt` | ✅ | — | bare / YOLO plus sandbox disabled | `GEMINI_CLI_HOME`; sessions under `.gemini` | ✅ / — | ⚠️ not admitted | ✅ | +| Cursor Agent | ✅ / positional / `--print` | ✅ | — | bare / YOLO plus sandbox disabled | **— no verified full-state relocation** | ✅ / — | ⚠️ not admitted | ✅ | +| Cline CLI | `--tui` / `--tui ` / positional | ✅ | `--thinking` | `--auto-approve false` / `true` | `--config`, `--data-dir`, and `--hooks-dir` | ✅ task / — | ⚠️ not admitted | ✅ | +| OpenCode | ✅ / `--prompt` / `run` | ✅ | `--variant` | bare / `--auto` | **— config-dir only; auth and sessions remain in XDG data** | ✅ / ✅ | ⚠️ not admitted | ✅ | +| GitHub Copilot | ✅ / `--interactive` / `--prompt` | ✅ | `--reasoning-effort` | bare / `--allow-all` | `COPILOT_HOME` | ✅ / — | ⚠️ not admitted | ✅ | +| Kimi Code | ✅ / `--prompt` / `--print --prompt` | ✅ | — (boolean thinking is not an effort scale) | bare / `--yolo` | **— alternate paths do not relocate every data class** | ✅ / ✅ | ⚠️ not admitted | ✅ | +| Factory Droid | ✅ / positional / `exec` | **— interactive CLI has no model option** | — | **— tiered interactive autonomy; full bypass is headless-only** | **— settings overlay only** | ✅ / ✅ | ⚠️ not admitted | ✅ | +| Amp | ✅ / **— seeded interactive prompt unavailable** / `--execute` | **— `--mode` is not a model selector** | `--effort` | **— default has no approval prompts; guarded mode is settings-only** | **— settings/log paths do not relocate auth and threads** | ✅ continue / — | ⚠️ not admitted | ✅ bare launch | +| Qoder CLI | ✅ / `--prompt-interactive` / `--print` | ✅ | `--reasoning-effort` | bare / skip permissions | `--config-dir` | ✅ / ✅ | ⚠️ not admitted | ✅ | +| Qwen Code | ✅ / `--prompt-interactive` / `--prompt` | ✅ | `--reasoning-effort` | bare / YOLO plus sandbox disabled | `QWEN_HOME` | ✅ / — | ⚠️ not admitted | ✅ Best effort | +| Grok Build | ✅ / positional / `--single` | ✅ | `--reasoning-effort` | `default` / `bypassPermissions` plus sandbox off | **— no verified full-state relocation** | ✅ / ✅ | ⚠️ not admitted | ✅ | +| Pi | ✅ / positional / `--print` | ✅ | `--thinking` | **— default has no approval prompts or sandbox; no guarded CLI mode** | `PI_CODING_AGENT_DIR` | ✅ / ✅ | ⚠️ not admitted | ✅ | +| Oh My Pi | ✅ / positional / `--print` | ✅ | `--thinking` | `always-ask` / `yolo` | `PI_CODING_AGENT_DIR` | ✅ / ✅ | ⚠️ not admitted | ✅ | ### Explicit unsupported results after false-positive checks @@ -97,17 +106,41 @@ but it is not admitted to that Prowl workflow. Amp's `--mode` selects a bundled agent mode rather than a model identifier. - **Reasoning effort is unavailable for Gemini, Cursor, Kimi, and Droid.** A boolean thinking switch is not rendered through Prowl's scalar effort field. -- **Unrestricted mode is hidden for Cline, Droid, Amp, Grok, and Pi.** Their - closest flags do not prove the exact Prowl promise of both no permission - prompts and no sandboxing. Experts can still use Extra Arguments, and the UI - will say the effective mode follows those arguments instead of making a - false Standard/Unrestricted claim. -- **Only Claude Code and Codex remain admitted to side-effect-free Prowl - resume.** Other CLIs may resume or fork sessions, but output capture, +- **Execution mode is hidden only for Droid, Amp, and Pi.** Droid's interactive + `--auto low|medium|high` values are a third, tiered autonomy model, while its + full bypass is available only on headless `droid exec`. Amp and Pi default to + no approval prompts, but neither exposes a launch flag for the inverse, + approval-required Standard mode. Cline, Grok, and Oh My Pi do expose both + sides, so Prowl renders their guarded flag for Standard and their + least-restricted flag(s) for Unrestricted. +- **Only Claude Code and Codex remain admitted to handoff-safe source + briefing.** Other CLIs may resume or fork sessions, but output capture, source-session immutability, confidence gates, and timeout/error behavior have not yet been proven as one protocol. Generic Profile registration no longer implies resume support. +### Permission-semantics evidence + +- [Pi's coding-agent README](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/README.md) + explicitly rejects permission popups and recommends a container or extension + for confirmation flows. `pi --approve` means project resource trust, not tool + approval; `--tools`, `--exclude-tools`, and `--no-tools` filter capabilities + but do not create Prowl's Standard mode. +- [Cline's CLI reference](https://docs.cline.bot/cli/cli-reference) documents + `--auto-approve `, allowing Prowl to render both values explicitly. +- [Droid's CLI reference](https://docs.factory.ai/reference/cli-reference) + documents tiered `--auto` for the interactive root and limits + `--skip-permissions-unsafe` to `droid exec`. +- [Amp's manual](https://ampcode.com/manual) and + [permission announcement](https://ampcode.com/news/neo) place guarded-file + behavior in settings/plugins, not a per-launch inverse flag. +- [Grok's permission](https://docs.x.ai/build/features/permissions) and + [sandbox](https://docs.x.ai/build/features/sandbox) documentation show that + the two axes are independent, so Unrestricted must set both. +- [Oh My Pi's approval-mode documentation](https://github.com/can1357/oh-my-pi/blob/main/docs/approval-mode.md) + defines `always-ask`, `write`, and `yolo`. Prowl maps the first and last while + leaving the middle tier to Extra Arguments. + ## Account isolation evidence | Runtime | Evidence and session-root consequence | @@ -115,7 +148,7 @@ but it is not admitted to that Prowl workflow. | Claude Code | Existing live support; `CLAUDE_CONFIG_DIR` points directly at the managed root. | | Codex | Existing live support; `CODEX_HOME` points directly at the managed root. | | Gemini CLI | [Official configuration](https://geminicli.com/docs/reference/configuration/) documents `GEMINI_CLI_HOME` as a user-home base; Gemini creates `.gemini` beneath it, so Prowl records `/.gemini` for session resolution. | -| Cline CLI | Local 2.18 help documents separate config, data, and hooks directories. A temporary `CLINE_DATA_DIR` run created state under that directory; Prowl supplies all three CLI paths and resolves sessions under `/data/tasks`. | +| Cline CLI | Local 3.0.48 help documents separate config, data, and hooks directories. A temporary `CLINE_DATA_DIR` run created state under that directory; Prowl supplies all three CLI paths and resolves sessions under `/data/tasks`. | | GitHub Copilot | Local `copilot help environment` and the [official CLI reference](https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-command-reference) identify `COPILOT_HOME`; session-state and pid logs are rooted directly below it. | | Qoder CLI | Local 1.0.48 help describes `--config-dir` as a custom user-level config root; local session layout remains `projects//.jsonl` below it. | | Qwen Code | [Official settings documentation](https://qwenlm.github.io/qwen-code-docs/en/users/configuration/settings/) documents `QWEN_HOME` for credentials, settings, memory, skills, and global state. Prowl resolves projects and pid sidecars directly below that root. | @@ -131,10 +164,12 @@ also the native session root. Both assumptions fail in the expanded catalog. The implementation now uses: -- a launch adapter keyed by `AgentProfileRuntime`, preserving Pi/OMP executable - identity while mapping both to the Pi detection family; +- a launch adapter keyed by `AgentProfileRuntime`, with a one-to-one mapping to + the canonical detected runtime, including independent Pi and OMP families; - independent profile-field capabilities, so the editor renders only options the adapter can implement honestly; +- an adapter-declared execution-mode set, so a runtime may render both guarded + and least-restricted modes with asymmetric flags, or hide the field entirely; - an optional `AgentProfileHomeRelocation` that supports environment variables, one or more managed path arguments, and a distinct session root; - a separate resume-adapter lookup, leaving `canResume` true only for proven diff --git a/docs/components/active-agents.md b/docs/components/active-agents.md index de91c8f4..8aa5f2d4 100644 --- a/docs/components/active-agents.md +++ b/docs/components/active-agents.md @@ -24,9 +24,9 @@ Command Palette → "Toggle Active Agents Panel". pane title or branch (secondary) ``` -- **Icon** — the detected command/agent icon (for example `omp` keeps the OMP - icon even though it reports as the Pi agent; unknown wrappers fall back to the - agent icon, then a sparkle). +- **Icon** — the detected command/agent icon. Aliases such as `oh-my-pi` use + their canonical runtime icon; unknown wrappers fall back to the agent icon, + then a sparkle. - **Title** — detected command/agent name + repository (repo color-coded); command aliases such as `omp` are shown directly. Panes Prowl launched from an [agent profile](agent-profiles.md) show the profile's display name diff --git a/docs/components/agent-detection.md b/docs/components/agent-detection.md index a9a65cb2..fcb7a1b2 100644 --- a/docs/components/agent-detection.md +++ b/docs/components/agent-detection.md @@ -21,10 +21,11 @@ Kimi, Droid, Amp, Pi (`pi`), Oh My Pi (`omp`, `oh-my-pi`), Qoder CLI (`qodercli` Qwen Code (`qwen`), and Grok Build (`grok`). Detection covers common wrappers (node, python, bun, bash, etc.) so agents launched indirectly are -still found. Oh My Pi reuses Pi-derived screen heuristics but uses its own command -icon where Prowl shows detected command icons, including terminal tabs. Grok Build -also ships an `agent` symlink; Prowl only treats that name as Grok when the path -points at a `~/.grok/` install (so Cursor's own `agent` entrypoint stays Cursor). +still found. Pi and Oh My Pi are independent detected agents. Pi uses only its +own minimal working/idle cues; Oh My Pi owns its richer spinner and interactive +Ask-prompt heuristics, plus its own session layout and icon. Grok Build also +ships an `agent` symlink; Prowl only treats that name as Grok when the path points +at a `~/.grok/` install (so Cursor's own `agent` entrypoint stays Cursor). ## How detection works (two stages) diff --git a/docs/components/agent-profiles.md b/docs/components/agent-profiles.md index fc0ed56d..58549945 100644 --- a/docs/components/agent-profiles.md +++ b/docs/components/agent-profiles.md @@ -65,9 +65,9 @@ restores the runtime's brand icon. Live panes and Active Agents retain the icon of the process Prowl actually detects. Changing a profile's **Agent** resets its Model, Reasoning Effort, Extra -Arguments, and confirmed Unrestricted mode to the new runtime defaults. Those -values are runtime-specific; add new values after choosing the destination -agent. +Arguments, and execution mode to the new runtime defaults. Unsupported fields +disappear instead of carrying stale state across runtimes; add new values only +after choosing the destination agent. **Recommended** resolves in three tiers: the repo's **Default Agent Profile** (Repo Settings) → the last profile explicitly launched in this repo → the @@ -131,7 +131,7 @@ shell-interpreted). A bound Profile's managed-home arguments follow Extra Arguments so an accidental duplicate cannot redirect credentials outside the UUID home; otherwise your flags remain last-wins. The editor stays honest about what it can prove: recognized bypass flags (`--yolo`, -`--dangerously-skip-permissions`, …) show the red unrestricted warning even +`--dangerously-skip-permissions`, …) show the red least-restricted warning even when the picker says Standard; any other extra argument (including `--sandbox`/`--ask-for-approval`/`-c` overrides) shows a neutral "effective execution mode follows your extra arguments" note instead of claiming @@ -145,26 +145,40 @@ effort, execution mode, placement). ## Runtime capability matrix All listed runtimes support a bare interactive Agent Profile launch. Pi and Oh -My Pi share Prowl's Pi detection family but remain separate Profile choices so -the correct executable, icon, and arguments are preserved. +My Pi are independent runtime and detection families: each keeps its own +executable, icon, screen heuristics, home, and session identity. -| Runtime | Model | Reasoning | Unrestricted | Dedicated Home | +| Runtime | Model | Reasoning | Execution mode | Dedicated Home | | --- | --- | --- | --- | --- | -| Claude Code | Yes | Yes | Yes | `CLAUDE_CONFIG_DIR` | -| Codex | Yes | Yes | Yes | `CODEX_HOME` | -| Gemini CLI | Yes | No | Yes | `GEMINI_CLI_HOME` | -| Cursor Agent | Yes | No | Yes | No verified full-state relocation | -| Cline CLI | Yes | Yes | No | Managed config, data, and hooks paths | -| OpenCode | Yes | Yes | Yes | No; config override does not move auth/session data | -| GitHub Copilot | Yes | Yes | Yes | `COPILOT_HOME` | -| Kimi Code | Yes | No | Yes | No verified full-state relocation | -| Factory Droid | No | No | No | No verified full-state relocation | -| Amp | No | Yes | No | No verified full-state relocation | -| Qoder CLI | Yes | Yes | Yes | `--config-dir` | -| Qwen Code | Yes | Yes | Yes | `QWEN_HOME` | -| Grok Build | Yes | Yes | No | No verified full-state relocation | -| Pi | Yes | Yes | No | `PI_CODING_AGENT_DIR` | -| Oh My Pi | Yes | Yes | Yes | `PI_CODING_AGENT_DIR` | +| Claude Code | Yes | Yes | Standard / Unrestricted | `CLAUDE_CONFIG_DIR` | +| Codex | Yes | Yes | Standard / Unrestricted | `CODEX_HOME` | +| Gemini CLI | Yes | No | Standard / Unrestricted | `GEMINI_CLI_HOME` | +| Cursor Agent | Yes | No | Standard / Unrestricted | No verified full-state relocation | +| Cline CLI | Yes | Yes | Standard / Unrestricted | Managed config, data, and hooks paths | +| OpenCode | Yes | Yes | Standard / Unrestricted | No; config override does not move auth/session data | +| GitHub Copilot | Yes | Yes | Standard / Unrestricted | `COPILOT_HOME` | +| Kimi Code | Yes | No | Standard / Unrestricted | No verified full-state relocation | +| Factory Droid | No | No | Runtime default only | No verified full-state relocation | +| Amp | No | Yes | Runtime default only | No verified full-state relocation | +| Qoder CLI | Yes | Yes | Standard / Unrestricted | `--config-dir` | +| Qwen Code | Yes | Yes | Standard / Unrestricted | `QWEN_HOME` | +| Grok Build | Yes | Yes | Standard / Unrestricted | No verified full-state relocation | +| Pi | Yes | Yes | Runtime default only | `PI_CODING_AGENT_DIR` | +| Oh My Pi | Yes | Yes | Standard / Unrestricted | `PI_CODING_AGENT_DIR` | + +The execution-mode picker appears only when Prowl can render both choices +honestly. Cline maps Standard to `--auto-approve false` and Unrestricted to +`--auto-approve true`; Grok maps them to `--permission-mode default` and +`--permission-mode bypassPermissions --sandbox off`; Oh My Pi maps them to +`--approval-mode always-ask` and `--approval-mode yolo`. Managed policies, +hooks, and per-tool deny or prompt rules remain authoritative. + +Factory Droid, Amp, and Pi deliberately have no picker. Droid exposes tiered +interactive autonomy and reserves its full bypass for headless `droid exec`. +Amp and Pi normally run without approval prompts, but neither offers a +launch-scoped pair of CLI flags that lets Prowl force both a guarded Standard +mode and the default least-restricted mode. Their own configuration remains in +control; Extra Arguments stay available for expert overrides. Amp has one additional limitation: it supports bare interactive Profile launch and `--execute` headless launch, but has no argv form that seeds a prompt and diff --git a/docs/components/cli.md b/docs/components/cli.md index beac4ff4..53ac0727 100644 --- a/docs/components/cli.md +++ b/docs/components/cli.md @@ -118,8 +118,8 @@ prowl agents --json ``` Each agent contains: - `id`: the pane/surface UUID, suitable for `--pane`. -- `type`, `name`: normalized detector type and displayed command name. Aliases - such as `omp` are preserved in `name`. +- `type`, `name`: normalized detector type and displayed command name. Pi uses + `pi`; Oh My Pi uses `omp`, with `oh-my-pi` preserved as a display alias. - `status`, `raw_state`: detected agent state. `status` is one of `blocked`, `working`, `done`, `idle`; `raw_state` is the lower-level detector state. - `last_changed_at`: ISO-8601 timestamp for the most recent state change. @@ -288,7 +288,7 @@ blocking it. verified Claude Code and Codex adapters for the destination launch only; model identifiers remain with their original agent family. Interactive launch is verified for `claude` and `codex`; `--no-launch` still archives + - saves and accepts the full detected-agent list: `pi`, `claude`, `codex`, + saves and accepts the full detected-agent list: `pi`, `omp`, `claude`, `codex`, `gemini`, `cursor-agent`, `cline`, `opencode`, `copilot`, `kimi`, `droid`, `amp`, `qodercli`, `qwen`, `grok`. - **`save`** — a deferred-handoff checkpoint: installs a fresh briefing diff --git a/docs/components/handoff.md b/docs/components/handoff.md index 47d15cb5..932170c2 100644 --- a/docs/components/handoff.md +++ b/docs/components/handoff.md @@ -131,7 +131,7 @@ prowl handoff save [target] [--brief -|--no-brief] [--note "…"] - **`to `** runs the full transition and launches the receiver in a background tab. Interactive launch is verified for `claude` and `codex`; `--no-launch` still archives + saves and accepts every detected-agent - token (`pi`, `claude`, `codex`, `gemini`, `cursor-agent`, `cline`, + token (`pi`, `omp`, `claude`, `codex`, `gemini`, `cursor-agent`, `cline`, `opencode`, `copilot`, `kimi`, `droid`, `amp`, `qodercli`, `qwen`, `grok`). - **`save`** is the deferred-handoff checkpoint: install a fresh briefing and regenerate context, with no destination and no launch. Use it when you stop @@ -198,6 +198,13 @@ Because the request is plain language, **any detected agent can be a source** — the pane-injection path is not limited to claude/codex; only the fork fallback is. +Native CLI resume and Prowl's Fork Briefing are different contracts. A native +`--resume` may reopen and append to the source session; Oh My Pi supports that +operation. Fork Briefing additionally requires an exact/high-confidence +session identity, an immutable source, deterministic headless output and exit, +and bounded failure handling. Until those properties are proven together for +a runtime, native resume support does not admit it to this fallback. + ## Safety - Handoff never commits, pushes, or runs destructive git — saving only