From 93d7102311f25e590dcd45cb33de849a603d2492 Mon Sep 17 00:00:00 2001 From: JUN Date: Sun, 4 Oct 2026 00:23:43 +0900 Subject: [PATCH 001/113] docs(cli): plan GUI workflow parity stack --- .../_plan/261003_cli_gui_parity/000_plan.md | 58 +++++ .../261003_cli_gui_parity/002_terminal_ux.md | 29 +++ .../003_verification_strategy.md | 30 +++ .../004_settings_coverage.md | 135 +++++++++++ .../005_operations_coverage.md | 158 +++++++++++++ .../006_target_contracts.md | 219 ++++++++++++++++++ .../007_architecture_decisions.md | 42 ++++ .../008_task_ledger.json | 185 +++++++++++++++ .../261003_cli_gui_parity/009_roadmap_lock.md | 9 + .../010_discovery_foundation.md | 45 ++++ .../020_existing_workflow_discovery.md | 33 +++ .../030_provider_management.md | 44 ++++ .../040_models_routing.md | 38 +++ .../050_accounts_runtime_settings.md | 48 ++++ .../060_integrations_maintenance.md | 47 ++++ .../070_observation_api_tools.md | 60 +++++ .../080_acceptance_publication.md | 35 +++ 17 files changed, 1215 insertions(+) create mode 100644 devlog/_plan/261003_cli_gui_parity/000_plan.md create mode 100644 devlog/_plan/261003_cli_gui_parity/002_terminal_ux.md create mode 100644 devlog/_plan/261003_cli_gui_parity/003_verification_strategy.md create mode 100644 devlog/_plan/261003_cli_gui_parity/004_settings_coverage.md create mode 100644 devlog/_plan/261003_cli_gui_parity/005_operations_coverage.md create mode 100644 devlog/_plan/261003_cli_gui_parity/006_target_contracts.md create mode 100644 devlog/_plan/261003_cli_gui_parity/007_architecture_decisions.md create mode 100644 devlog/_plan/261003_cli_gui_parity/008_task_ledger.json create mode 100644 devlog/_plan/261003_cli_gui_parity/009_roadmap_lock.md create mode 100644 devlog/_plan/261003_cli_gui_parity/010_discovery_foundation.md create mode 100644 devlog/_plan/261003_cli_gui_parity/020_existing_workflow_discovery.md create mode 100644 devlog/_plan/261003_cli_gui_parity/030_provider_management.md create mode 100644 devlog/_plan/261003_cli_gui_parity/040_models_routing.md create mode 100644 devlog/_plan/261003_cli_gui_parity/050_accounts_runtime_settings.md create mode 100644 devlog/_plan/261003_cli_gui_parity/060_integrations_maintenance.md create mode 100644 devlog/_plan/261003_cli_gui_parity/070_observation_api_tools.md create mode 100644 devlog/_plan/261003_cli_gui_parity/080_acceptance_publication.md diff --git a/devlog/_plan/261003_cli_gui_parity/000_plan.md b/devlog/_plan/261003_cli_gui_parity/000_plan.md new file mode 100644 index 00000000000..4ca64462b75 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/000_plan.md @@ -0,0 +1,58 @@ +# Make dashboard workflows usable from the terminal + +OpenCodex already implements many dashboard operations in its CLI, but discovery omits working commands and several workflows expose only some GUI fields. This unit completes the eligible task gaps, makes existing commands discoverable, and gives the shipped ocx skill verified task recipes. Operators keep the same management validation and consent boundaries, with explicit local/live target selection where those effects differ. + +Reader: maintainers reviewing the six-layer manual PR stack; they need the scope, exact command contracts and proof for each layer. + +## Loop contract + +- Archetype: satisfy a fixed, source-audited task inventory, followed by residual accounting. +- Trigger: user requested near-GUI CLI parity, improved shipped skill, inherited-model subagents, repeated PABCD and a published stack. +- Goal: every eligible GUI task has a named command/sequence, useful help, safe output, documented target and behavioral evidence; genuine exclusions and duplicate views remain explicit. +- Non-goals: GUI redesign, provider routing redesign, new auth authority, raw API/config escape hatches, live-user operation, native GitHub stacks, merging, release or deployment. +- Verifier: numbered phase acceptance tests plus the baseline/QA strategy in 003_verification_strategy.md; a docs checker observes these exact plan files and task ownership before B. +- Stop: six open, reviewable PRs with successful current-head hosted CI; all task ledger rows closed as verified, alias or justified exclusion, with no unexplained UNKNOWN. +- Durable artifacts: this unit, 008_task_ledger.json and ignored command/QA receipts under this session. +- Outcomes: DONE requires implementation, synchronized skill/docs, independent reviews and CI. Real unsupported prerequisites/authority are reported under host blocked rules; workload or compaction is not completion. +- Escalation: main resolves source/architecture conflicts; ask the user only for genuinely new authority. Failed delegates follow the bounded retry/retirement owner; do not swap models silently. +- Resources: no user token/cost/time cap. Tool scope is repository editing, isolated local fixtures and GitHub PR/CI for this repository. No real accounts, credentials, running services, paid upstream calls or destructive user files are QA targets. + +## Baseline and source owners + +Baseline dev is 9f89b7265b754eb681215ad327fc9459af37b9e1. The initial inventories contain 176 task-entry rows, with two additional embedded dashboard setting groups subsequently found (memory models and compaction routing). Duplicate entry points are retained as aliases rather than silently dropped. Source-coverage labels in 004/005 are not passing runtime evidence. Executable 010..080 decisions supersede earlier source-join syntax proposals; the private audit record retains their history. + +The tree remains Bun TypeScript: src/cli owns domain handlers and pure help/capability data; existing server management modules own validation/live mutation; tests/cli plus domain server tests own proof; skills/ocx and docs-site own operating guidance; structure owns current contracts. Existing structure/manifest.json maps src/cli to runtime/config/integration/Desktop/release docs. Only affected owners are updated. + +## Dependency-ordered work phases and PR layers + +| Phase | Executable document | Dependency | Output / PR layer | +| --- | --- | --- | --- | +| wp0 | This roadmap, inventories and UX contract | none | Docs-only audit; locks the remaining designs before source edits | +| wp1 | 010_discovery_foundation.md | wp0 | Pure metadata and generated-document capacity; layer 1 | +| wp2 | 020_existing_workflow_discovery.md | wp1 | Accurate existing task discovery and skill routing; finish layer 1 | +| wp3 | 030_provider_management.md | wp2 | Bounded input and exact provider live workflows; layer 2 | +| wp4 | 040_models_routing.md | wp3 | Models, picker order, combos and routing profile edits; layer 3 | +| wp5 | 050_accounts_runtime_settings.md | wp4 | Account policies, explicit auth options, agent/settings/v2 parity; layer 4 | +| wp6 | 060_integrations_maintenance.md | wp5 | Live Desktop profile, integration recovery, storage and Hub reads; layer 5 | +| wp7 | 070_observation_api_tools.md | wp6 | Timeline/log fidelity, scoped usage and chosen-key/audio tools; layer 6 | +| wp8 | 080_acceptance_publication.md | wp7 | Residual task proof, final skill/docs and all exact-head PR receipts; finish layer 6 | + +Every work phase runs a full P→A→B→C→D cycle. wp0 is code-free. Later P revalidates its existing decade doc and quotes the previous D conclusion; changes to decisions return to the same architect before A. Branch names: codex/cli-parity-foundation → codex/cli-parity-providers → codex/cli-parity-models → codex/cli-parity-accounts → codex/cli-parity-integrations → codex/cli-parity-observation. The bottom targets dev; each child targets its open parent. No native stack registration or merge is authorized. + +## Coverage and decisions + +- 002_terminal_ux.md defines terminal behavior and progressive disclosure. +- 003_verification_strategy.md records real baseline checks and verification scope. +- 004_settings_coverage.md and 005_operations_coverage.md preserve field-level source joins. +- 007_architecture_decisions.md records proposal dispositions, additive field chain and target boundaries. +- 008_task_ledger.json assigns every row to a phase; historical labels are retained while current status/evidence advance. + +Source comparison established that local provider/custom-model/v2/logout effects differ from live management receipts. --live is therefore explicit and never inferred from proxy availability or --json. Existing local behavior remains available. Browser-session identity actions stay outside automated parity; data-plane API testing is included with the same data-plane admission authority. + +## Alternatives rejected + +A generic API request command would expose routes without usable task contracts. Generic config writes would bypass existing live validation and completion receipts. A new command framework would duplicate the existing Capability/domain-handler architecture. Declaring routes that local commands never fetch would make coverage appear complete while remaining false. None is used. + +## Phase records + +wp0 roadmap was locked after independent audits passed. Inventory corrections already folded: existing v2 verbs are real local implementations, not absent agent verbs; model preset custom is disabled in the GUI; Lab local commands must not acquire fictitious HTTP coverage; memory-model and compaction-routing controls need explicit rows. Whole-plan architect reflection is ALIGNED at a095a4e514d6d8e5a37dbf05a66b2c9156ebaeeb28a8e0fb878bc76f931c27b1; the serializer and data-plane contract amendments were audited independently and passed. See 009_roadmap_lock.md. diff --git a/devlog/_plan/261003_cli_gui_parity/002_terminal_ux.md b/devlog/_plan/261003_cli_gui_parity/002_terminal_ux.md new file mode 100644 index 00000000000..20ed64696fe --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/002_terminal_ux.md @@ -0,0 +1,29 @@ +# Terminal UX contract + +This is a repeated-use management tool for people and automation. The design preserves the compact root help and contextual family navigation delivered by the CLI help stack; it extends task coverage without turning the terminal into an endpoint debugger. + +Design variance: 2/10. Motion: 1/10 (no decorative animation). Density: D8 for the full reference, progressive disclosure for first use. Monospace, plain text and predictable line ordering carry meaning; color or symbols never determine correctness. Raster concepts do not help this utility surface and are intentionally omitted. + +## Task language + +- Extend existing nouns before adding new roots. Prefer list/show/status, set/update, enable/disable, apply/reset and their established domain equivalents. +- A family with no action offers a safe overview/help or an existing read-only default. It must never silently choose a write. +- Help is available without a live proxy and never runs a management action. Examples use registered grammar and placeholders, with a next read/verify command after a mutation. +- Short human output answers what changed, what remains unapplied and the next action. JSON preserves safe API DTO fidelity on stdout; diagnostics stay on stderr and failures keep documented exit codes. +- Empty lists distinguish no configuration, no matching rows and unavailable evidence. Do not render unavailable as zero or an empty successful inventory. +- Unknown/missing/duplicate arguments must fail before network writes. Boolean and numeric syntax reuse established parsers; structured inputs receive bounded, explicit JSON file/stdin forms only when the task's data shape needs them. +- IDs and names are encoded at path/query boundaries. No arbitrary method/URL command is counted as GUI parity. + +## Writes and recovery + +Existing management routes remain the source of validation, persistence, ownership and live application. A saved configuration is not proof that the client/runtime applied it; preserve refusal, partial application and restart-needed fields in output. + +Destructive operations retain explicit confirmation or preview as appropriate to the existing command family and server contract. Read, preview, apply and verify are distinguishable operations. No hidden retry of non-idempotent writes. New commands do not expand account identity, browser consent or secret-returning authority. + +No-running-proxy output names the recovery command. Invalid input names the argument and expected syntax without leaking its value when secret-bearing. Server errors preserve meaningful reason/hint fields and failure exit codes. Tests activate server refusal, not-found/conflict, malformed arguments and non-confirmed mutation paths. + +## Discoverability and skills + +The capability registry, help resolver, generated management reference and human recipes describe the same supported commands. Existing undeclared commands must be mapped before declaring a gap. Skill recipes start with readiness/version checks when operating a real proxy, then task-specific commands and verification. Human-only exclusions stay explicit and do not gain an API workaround. + +Each inventory row records GUI task, existing API contract, existing CLI route, implementation/discovery gap, final command and verification, or a reasoned exclusion. Coverage is measured against user tasks, not endpoint count or lines added. diff --git a/devlog/_plan/261003_cli_gui_parity/003_verification_strategy.md b/devlog/_plan/261003_cli_gui_parity/003_verification_strategy.md new file mode 100644 index 00000000000..a863a13ebb7 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/003_verification_strategy.md @@ -0,0 +1,30 @@ +# Verification strategy and observed baseline + +Baseline: `9f89b7265b754eb681215ad327fc9459af37b9e1`, the completed CLI-help stack on dev. This unit starts on `codex/cli-parity-foundation` in the existing managed worktree. + +Before implementation, the following ran successfully: + +| Command | Result | What it observes | +| --- | --- | --- | +| `bun run typecheck` | exit 0 | The repository TypeScript graph, including src/cli. | +| `bun run structure:check` | exit 0 | Structure manifest, declared source ownership, existing paths and invariant bindings; not prose correctness. | +| `bun run skill:surface:check` | exit 0 | Generated skill reference compared with src/cli/capabilities.ts. | +| `bun test tests/cli/cli-capabilities.test.ts tests/cli/cli-capabilities-arguments.test.ts tests/server/management-route-registry.test.ts tests/ci-workflows/skill-ocx.test.ts` | 62 pass, 0 fail, 1180 assertions | Capability parsing, leaf-module import boundary, management declaration reconciliation and shipped-skill command/consent boundaries. | + +Raw evidence is in the ignored `.tmp/cli-parity/baseline-*.log` files. The source-map command is unavailable in the installed plugin (it requires a codexclaw development checkout); bounded file inventories and exact source anchors replace it. + +## Per-unit proof + +Each implementation phase owns focused regression files with exact expected HTTP method/path/body, safe structured output, error/exit mapping and no-request assertions for rejected inputs. Tests use isolated homes and injected RuntimeApiDeps or a disposable loopback fixture; they do not mutate the operator's running proxy, credentials, client applications or accounts. + +Acceptance includes real CLI subprocess invocations with separated stdout/stderr, recorded exit codes and plain/pipe output. Help/version paths must remain offline and write-free. For mutations, run an equivalent isolated management-route contract scenario where appropriate; mocking a request records transport shape but does not by itself prove server acceptance. Input files/stdin, cancellation and confirmation paths receive explicit reachable scenarios. Each QA-owned temporary server/process has a teardown receipt. + +Existing global gates remain intact. New test files enter both test-layout maps. Source changes update their owning structure docs; public behavior updates CLI docs and the operating skill. Generated output is regenerated from its actual registry owner and checked for drift. Prose/UX semantics receive independent human-style review, not a test that only looks for a phrase. + +## Broad verification and publication + +Focused tests and type/static/document gates run locally. Full-suite and platform coverage use the current-head hosted PR CI for every layer; the repository's full suite has tens of thousands of tests and concurrent worktrees make repeated local full/changed runs disproportionate. This is the resource-scoped verification plan, not permission to ignore failing focused tests. Record exact commands and the coverage left to CI in each PR. + +The preceding CLI-help task recorded four local full-suite failures, all reproduced on its untouched baseline (three restart-lease failures and a pre-request directory snapshot EISDIR). Those records are history, not current-unit passing evidence. If this unit encounters a failure, inspect it and attribute or repair it with fresh source/command evidence. No skip, threshold relaxation, retry-as-fix or unrelated suite substitution is allowed. + +Each PR must retain its own current-head CI run, event, attempt, expected executed jobs, checkouts actually tested and open-review dispositions. Canceled/skipped/missing jobs are not passing tests. The stack remains open for review at completion; merge/release is not part of this request. diff --git a/devlog/_plan/261003_cli_gui_parity/004_settings_coverage.md b/devlog/_plan/261003_cli_gui_parity/004_settings_coverage.md new file mode 100644 index 00000000000..cf5d39fb783 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/004_settings_coverage.md @@ -0,0 +1,135 @@ +# Settings GUI-to-CLI field/workflow gap join + +Source-only completed join, 2026-10-03. One row for every one of the 67 tasks in the settings GUI/API inventory; IDs are prefixed `set-`. Joined the CLI source inventory to targeted provider/models/account/agent/combo/route/protocol/Lab handlers. No whole-CLI rescan, runtime/test/proxy/credential access, or source edits. Only this second-pass artifact is written. Exact source anchors establish implementation shape, not runtime success. + +Status meanings: + +- **COMPLETE**: named implementation covers the GUI fields/actions; no new operation identified. Runtime validation remains unrun. +- **DISCOVERY_ONLY**: GUI operation is implemented, but full leaf grammar is absent/incomplete in indexed capabilities/help; retain existing writer and improve discovery. This does not demand one capability entry per visual action. +- **IMPLEMENTATION_GAP**: at least one reachable field/action or material workflow behavior differs; existing supported variants are retained explicitly in the row. +- **EXCLUDED**: session-only consent or presentation boundary; no admin-token bypass should be proposed. +- **UNKNOWN**: field coverage exists but local/live convergence equivalence needs isolated proof. A generic config writer or HTTP passthrough is not parity. + +Commands are shown without repeated `ocx` prefixes for readability. Recommended syntax is a remediation proposal for the parent, not a claim that those flags already exist. `--json` is preserved where implemented; secrets use existing stdin contracts. Source scopes include the directly referenced handler helpers only. + +## Corrections and important joins + +1. Model preset `custom` is a disabled GUI state, not a selectable action (`gui/src/pages/Models.tsx:1550`). Existing preset/all CLI is sufficient; do not implement a custom flag solely because the server accepts the field. +2. Picker order and featured roster share `/api/subagent-models` but are distinct bodies. Existing `agent subagents set` does not implement picker ordering. +3. `--effort-mode` on combo sets `defaultEffortMode` (fallback/force), not GUI `reasoningEffortMode` (strict/adaptive). A similar name is not field parity. +4. Anthropic account threshold exists with `--account`; the same parser requires an account and does not expose the GUI pool-wide threshold/quota-window/enabled controls. Codex per-account threshold is also missing while pool-wide threshold exists. +5. Registry deferred claims for Lab public actions are stale per the CLI inventory. CompatibilityMatrix is read-only and the local Lab reads already exist; do not plan an HTTP-only rewrite. +6. GUI model-display-name mutation is absent from both dedicated CLI and current route declaration. Custom-model edit is not a substitute. Pricing reset, discovered metadata reset and context-cap variants are already implemented. +7. **Parent correction applied:** multi-agent mode/thread/keep-native/hint operations exist under the independent `ocx v2` root (`src/cli/dispatch.ts:539`, `src/cli/v2.ts:109`). M13/S04 are not missing writers; they are UNKNOWN for local/live equivalence with confirmed JSON/discovery/advisory differences. No duplicate `agent mode` taxonomy is proposed. +8. A11 reachability is now confirmed: picker and hard lock mount in `gui/src/pages/codex-set-multiauth.tsx:218` and `:221`. Client-settings ownership still needs sibling deduplication. + +## Complete task matrix + +| Task | Status | Existing command(s) | Exact missing variant / supported boundary | Recommended syntax / remediation | Source anchors (CLI and GUI/API) | +|---|---|---|---|---|---| +| set-P01 — Inspect configured providers, presets, authentication availability | DISCOVERY_ONLY | provider list/show/presets; inspect config; account list/current; status --json | Provider/catalog/authentication views exist across commands; static provider list is not the live config view. No separate raw OAuth-provider route command is needed if preset/auth inventory is preserved. | Index existing workflows and distinguish local provider list from inspect config; retain redaction. | src/cli/provider.ts:80; src/cli/provider-runtime.ts:235; src/cli/inspect.ts:209; src/cli/account.ts:44; gui/src/pages/use-providers-fetch.ts:34; src/server/management/provider-routes.ts:933 | +| set-P02 — Add a preset/custom provider; enable canonical OpenAI account provider | IMPLEMENTATION_GAP | provider add P [--adapter A --base-url U --api-key ... --default-model M --allow-private-network --force --set-default --sync]; provider edit openai --enabled on | Add parser has no responsesPath/authMode fields; account-mode is a later command. Local add returns needsSync; --json returns before --sync executes. Live validated POST parity and canonical enable are separate concerns. | Extend add with --responses-path PATH and --auth-mode key\|forward\|oauth; use server POST on explicitly live path, preserving existing offline mode. Make --json --sync report actual convergence instead of silently bypassing it. | src/cli/provider.ts:142; src/cli/provider.ts:156; src/cli/provider.ts:212; src/cli/provider.ts:279; src/cli/provider-runtime.ts:73; gui/src/components/AddProviderModal.tsx:203; src/server/management/provider-routes.ts:1161 | +| set-P03 — Edit provider transport, discovery, default model, note, network permission | IMPLEMENTATION_GAP | provider edit/update P --adapter A --base-url U --default-model M\|- --auth-mode MODE\|- --note TEXT\|- --api-key-transport MODE\|- --enabled on\|off --live-models on\|off --allow-private-network on\|off | GUI fields covered except Cursor upstreamHttpVersion. Empty note/default clearing exists; headers and context-tier CLI extras do not cover HTTP-version override. | Add --upstream-http-version http1.1\|- to provider edit; '-' sends null, omission leaves field unchanged; preserve server validation. | src/cli/provider-runtime.ts:59; src/cli/provider-runtime.ts:112; src/cli/provider-runtime.ts:312; gui/src/components/provider-workspace/ProviderSettings.tsx:233; src/server/management/provider-routes.ts:1412 | +| set-P04 — Configure and inspect request pacing | IMPLEMENTATION_GAP | inspect pacing --name P --json | Read exists; provider edit has no requestPacing writer, no provider/model RPM, delay or concurrency fields, no enabled/reset controls. | Add provider pacing P [--enabled on\|off] [--rpm N] [--min-interval-ms N] [--max-concurrent N] [--model M] [--clear] --json; a domain-specific --file rules.json can carry atomic full rules, not arbitrary API paths. Preserve untouched provider/model fields. | src/cli/inspect.ts:214; src/cli/provider-runtime.ts:65; src/cli/provider-runtime.ts:140; gui/src/components/provider-workspace/ProviderSettings.tsx:178; src/server/management/provider-routes.ts:917 | +| set-P05 — Enable/disable, choose default, remove provider | IMPLEMENTATION_GAP | provider edit P --enabled on\|off; provider set-default P; provider remove P | Enable is live PATCH. Set-default/remove are local paths; remove refuses current default while GUI reassigns an enabled replacement; local removal dependency check only examines targets. Thus CRUD names do not establish same live workflow. | Keep names, add/use live mutation path for set-default and remove with exact server receipt/dependency refusals. Explicit offline behavior must remain labeled. Do not emulate default deletion as two non-atomic requests. | src/cli/provider-runtime.ts:133; src/cli/provider.ts:345; src/cli/provider.ts:355; src/cli/provider.ts:459; gui/src/pages/use-providers-crud.ts:67; src/server/management/provider-routes.ts:1459 | +| set-P06 — Change OpenAI account mode | DISCOVERY_ONLY | provider account-mode pool\|direct --json | Standalone PATCH is covered, including server-side rebind/cache effects. Leaf lacks dedicated capability metadata per CLI inventory. | Document/index existing command; no new writer. | src/cli/provider-runtime.ts:252; gui/src/components/provider-workspace/ProviderSettings.tsx:289; src/server/management/provider-routes.ts:1421 | +| set-P07 — Atomically edit provider JSON | IMPLEMENTATION_GAP | config import exists but is not provider-editor CAS parity | No dedicated baseline/next provider DTO workflow; local full config import lacks server stale-baseline check, target scope and persisted receipt. | provider snapshot --json; provider apply --baseline FILE --file FILE --json. Snapshot emits {defaultProvider,providers}; apply sends exactly {baseline,next}, rejects stale 409 without auto-refresh/rebase; bounded files or stdin variant. No generic passthrough. | src/cli/provider-runtime.ts:312; src/server/management/provider-routes.ts:1055; gui/src/hooks/useJsonConfigEditor.ts:16; gui/src/hooks/useJsonConfigEditor.ts:55; src/server/management/provider-routes.ts:1055 | +| set-P08 — Check provider connectivity | DISCOVERY_ONLY | provider test P --json | Existing named probe distinguishes applicable:false. No missing GUI action. | Index command and retain not-applicable/configuration-only versus live connectivity distinctions. | src/cli/provider-runtime.ts:148; gui/src/components/provider-workspace/ProviderOverview.tsx:109; src/server/management/provider-routes.ts:1619 | +| set-P09 — Inspect provider quota/capacity/usage | COMPLETE | provider quota [--refresh] --json; account list P --quota [--refresh] --json; usage --range 30d --surface codex\|all --json | Operational quota and scoped usage reads exist. Generic telemetry ownership belongs to sibling; do not add a duplicate provider usage transport. | Reuse existing commands. Keep passive quota unavailable and partial usage signals. | src/cli/provider-runtime.ts:178; src/cli/account-api.ts:370; src/cli/observe.ts:164; gui/src/components/provider-workspace/ProviderWorkspaceShell.tsx:182; src/server/management/provider-routes.ts:904 | +| set-P10 — OAuth login, add another account, reauthenticate, submit callback, cancel, logout | IMPLEMENTATION_GAP | account login P [--reauth --id I] [--no-wait]; account reauth/code/cancel; login P (local); logout P --json (local) | Core flow exists, but account login always sends addAccount:true for non-reauth; no explicit openBrowser override. Initial local-import login and runtime logout equivalence remain UNKNOWN. Meta Muse consent cannot be bypassed. | Add account login --open-browser on\|off and --add-account on\|off with omission preserving server preference; add account logout P --json for exact runtime logout if live-equivalence fixture fails. Keep local login behavior documented separately and preserve provider consent gate. | src/cli/account-auth.ts:139; src/cli/account-auth.ts:260; src/cli/dispatch.ts:374; src/cli/dispatch.ts:425; gui/src/pages/use-providers-oauth.ts:119; src/server/management/oauth-account-routes.ts:236 | +| set-P11 — Kiro native device login | COMPLETE | account login kiro --method builder-id\|google\|github [--no-wait] --json; account cancel kiro --flow F --json | Native device method, flow polling and cancellation exist; add-only constraints match GUI. | Retain implementation; expose flags consistently in higher-level account help where omitted. | src/cli/account-auth.ts:150; src/cli/account-auth.ts:174; src/cli/account-auth.ts:327; gui/src/components/use-kiro-device-login.ts:46; src/server/management/oauth-account-routes.ts:250 | +| set-P12 — Manage OAuth account roster | DISCOVERY_ONLY | account list/current/use P I; account alias P I TEXT\|-; account pause/resume P I; account remove P I --yes; all support --json | Roster lifecycle and clear alias are covered through provider-aware endpoints. Alias and several lifecycle leaves are under-indexed. | Index existing grammar; no new endpoint. Preserve provider capability refusals and exact id/alias resolution. | src/cli/account.ts:44; src/cli/account-extended.ts:438; src/cli/account-extended.ts:803; src/cli/account-extended.ts:1064; gui/src/hooks/useProviderAccountPools.ts:210; src/server/management/oauth-account-routes.ts:398 | +| set-P13 — Import Antigravity accounts | DISCOVERY_ONLY | account import google-antigravity --format cockpit-tools --file F\|--stdin --json | Bounded import exists with redacted per-record receipt and nonzero for failed/unsupported records; no missing GUI action. | Index existing command and safe input forms. | src/cli/account-extended.ts:541; src/cli/account-extended.ts:595; src/cli/account-extended.ts:616; gui/src/components/provider-workspace/ProviderAuthPanel.tsx:358; src/server/management/oauth-account-routes.ts:835 | +| set-P14 — Manage API-key pool | DISCOVERY_ONLY | account list/use P I; account add-key P [--label L] (stdin); account alias P I TEXT\|-; account remove P I --yes --json | Key pool lifecycle is implemented. Secret stdin and null/blank alias semantics already exist. | Index full family; do not add key text to argv examples or create duplicate key pool commands. | src/cli/account-api.ts:419; src/cli/account-extended.ts:507; src/cli/account-extended.ts:1064; gui/src/hooks/useProviderAccountPools.ts:279; src/server/management/oauth-account-routes.ts:929 | +| set-P15 — Set account-pool strategy and thresholds | IMPLEMENTATION_GAP | account strategy P STRATEGY; account sticky P N; account auto-switch P on\|off\|threshold N\|status; account routes anthropic ... | Strategy/sticky cover common fields. No pool enabled writer or quotaWindow writer. Anthropic auto-switch delegates to account-only parser and requires --account, so GUI pool-level Anthropic threshold is missing. Generic/Codex thresholds exist. | Add account pool P [--enabled on\|off] [--threshold N] [--quota-window five-hour\|weekly\|max-utilization] --json, using unified pool/settings DTO supported fields. Can expose strategy/sticky in same command but retain existing aliases. Never map pool enable to threshold 0 or per-account override. | src/cli/account-extended.ts:355; src/cli/account-extended.ts:941; src/cli/account-extended.ts:974; src/cli/account-anthropic-threshold.ts:14; gui/src/pool-settings.ts:74; src/server/management/oauth-account-routes.ts:559 | +| set-P16 — Set per-Anthropic-account auto-switch override | COMPLETE | account auto-switch anthropic status\|on\|off\|inherit\|threshold N --account I --json | Per-account nullable override and inherited/effective threshold are implemented; inherit sends null. | Keep command; do not confuse P15 pool policy with this scoped override. | src/cli/account-anthropic-threshold.ts:4; gui/src/hooks/useProviderAccountPools.ts:443; src/server/management/oauth-account-routes.ts:507 | +| set-P17 — Control xAI Responses opt-in and model Fast variants | IMPLEMENTATION_GAP | provider edit xai --xai-chat on\|off --json | xaiResponsesOptIn is implemented via inverse --xai-chat (!value). No fastEnabled field/flag for provider Fast model variant rows. | Add provider edit P --fast on\|off mapping fastEnabled; document --xai-chat off means Responses opt-in true, without reversing existing flag meaning. | src/cli/provider-runtime.ts:76; src/cli/provider-runtime.ts:108; gui/src/components/provider-workspace/ProviderAuthPanel.tsx:75; src/server/management/provider-routes.ts:1412 | +| set-P18 — Inspect/redeem Grok reset coupons | COMPLETE | account grok-reset-coupons [I] [--consume --yes --token-id T --operation-id UUID] --json | Read, token selection, consent flag and stable operation-id retry exist. | No new writer. Preserve explicit user spend intent and exact operation UUID on retry. | src/cli/account-auth.ts:374; gui/src/hooks/useGrokResetCoupons.ts:133; src/server/management/grok-coupon-routes.ts:63 | +| set-P19 — Inspect/redeem Anthropic reset grants | IMPLEMENTATION_GAP | No Anthropic grant read command in account-auth dispatcher; Grok/Codex reset commands target different contracts | Read missing; consume is EXCLUDED because server requires gui-session. Do not extend reset-credit consume to Claude. | Add account anthropic-reset-grants [I] --json for GET only, with optional current-account semantics matching server. Explain session-only consume rather than attempting session minting. | src/cli/account-auth.ts:414; src/server/management/anthropic-reset-grant-routes.ts:109; src/server/management/anthropic-reset-grant-routes.ts:131; gui/src/hooks/useAnthropicResetGrants.ts:168; src/server/management/anthropic-reset-grant-routes.ts:131 | +| set-P20 — Choose whether OAuth launches browser on proxy host | IMPLEMENTATION_GAP | account login currently omits openBrowser; GUI local preference feeds request field | No one-shot browser-launch override; device flag changes authentication protocol and is not equivalent. | Add account login P --open-browser on\|off; omit field when flag absent. No new persistent settings write required for GUI-local preference. | src/cli/account-auth.ts:139; src/cli/account-auth.ts:198; src/cli/account-auth.ts:260; gui/src/components/open-browser-pref-toggle.tsx:19 | +| set-A01 — Inspect/refresh account readiness, quotas and active selection | COMPLETE | account list openai --quota [--refresh] --json; account current openai --json; account refresh openai --json | Read, quota refresh and POST validation refresh already exist. Login's old recovery prose pointing to GUI does not mean refresh command is absent. | Reuse command; update recovery guidance as discovery work only if in authorized scope. | src/cli/account-extended.ts:326; src/cli/account-extended.ts:347; src/cli/account-api.ts:281; gui/src/hooks/useCodexAccountPool.ts:317; src/codex/auth-api/routes.ts:35 | +| set-A02 — Add/re-authenticate pool account with browser or device flow | IMPLEMENTATION_GAP | account login openai --id I --reauth --device --no-wait --json; account code/cancel openai --flow F | Start/poll/manual code/cancel complete; openBrowser one-shot preference absent as P20. No need for a second Codex login command. | Extend existing login flag as P20, keep id and flowId distinct, preserve device flag and user verification. | src/cli/account-auth.ts:139; src/cli/account-auth.ts:197; src/cli/account-auth.ts:294; src/cli/account-auth.ts:327; gui/src/components/use-add-codex-account-oauth.ts:95; src/codex/auth-api/routes.ts:493 | +| set-A03 — Reauthenticate native main in place | COMPLETE | account main reauth --device [--no-wait] --json; account main reauth status\|cancel --flow F --json | Dedicated native-main no-body start, exact-flow polling/cancel implemented. | Keep native-main identity separate from account login openai. Sibling can own docs without duplicating operation. | src/cli/account-main.ts:192; gui/src/components/use-main-device-reauth.ts:99; src/codex/main-device-reauth-api.ts:49 | +| set-A04 — Select active account, rename, remove | DISCOVERY_ONLY | account current/use/clear openai; account alias openai I TEXT\|-; account remove openai I --yes --json | Selection, explicit auto clear, rename/reset alias and removal exist. Main versus auto has documented identity precedence. | Index leaves. Use account clear to always clear pin when a real id is named auto. | src/cli/account.ts:44; src/cli/account.ts:364; src/cli/account-extended.ts:438; src/cli/account-extended.ts:1064; gui/src/hooks/useCodexAccountPool.ts:486; src/codex/auth-api/routes.ts:52 | +| set-A05 — Pause/resume, pause exhausted accounts, set priority | COMPLETE | account pause/resume openai I; account pause-exhausted openai; account priority openai I N\|first\|earlier\|normal\|later\|last\|reset --json | Pause/resume/exhausted and priority null-reset are present. | No new commands; keep main restrictions and server-authoritative priority receipt. | src/cli/account-extended.ts:714; src/cli/account-extended.ts:803; src/cli/account-extended.ts:875; gui/src/hooks/useCodexAccountPool.ts:535; src/codex/auth-api/routes.ts:90 | +| set-A06 — Set per-account auto-switch threshold | IMPLEMENTATION_GAP | account auto-switch openai on\|off\|threshold N\|status is pool-wide only | Codex per-account id plus threshold:null override has no parser path; --account is parsed only by Anthropic handler. | Extend account auto-switch openai ... --account I, add inherit => {id,threshold:null}; pool action with no --account remains {threshold}. Resolve main and aliases explicitly. | src/cli/account-extended.ts:355; src/cli/account-extended.ts:394; src/cli/account-anthropic-threshold.ts:4; gui/src/hooks/useCodexAccountPool.ts:623; src/codex/auth-api/routes.ts:310 | +| set-A07 — Permit paid credits after quota exhaustion | IMPLEMENTATION_GAP | Only generic config fallback; no account-auth/extended credits policy handler | Both individual {id,creditsAfterLimit} and aggregate {all} variants are missing. | account credits openai I on\|off --json; account credits openai --all on\|off --json. Mutually exclusive selector/all; GET/read from account roster, PUT exact credits endpoint. Require explicit cost-spend opt-in intent; never infer from show-credits preference. | src/cli/account.ts:44; src/cli/account-auth.ts:414; src/codex/auth-api/routes.ts:122; gui/src/hooks/useCodexAccountPool.ts:662; src/codex/auth-api/routes.ts:122 | +| set-A08 — Inspect/redeem Codex reset credits | DISCOVERY_ONLY | account reset-credits I\|main [--consume --yes --operation-id UUID] --json | Read and redeem exist, with stronger optional retry identity than current GUI. Root account usage omits operation-id though leaf handler supports it. | Index leaf grammar and stable retry id; no missing operation. | src/cli/account-auth.ts:345; src/cli/account.ts:69; gui/src/components/CodexAccountPool.tsx:441; src/codex/auth-api/routes.ts:454 | +| set-A09 — Configure quota-window activation and credit display | IMPLEMENTATION_GAP | system settings --json reads settings; account refresh handles immediate refresh only | No codexQuotaAutoRefresh per-id/per-window writer and no showCodexCredits switch. Immediate refresh is not quota-window activation; show credits is not credits-after-limit. | account quota-activation openai I --window fiveHour\|weekly on\|off --json, exact {codexQuotaAutoRefresh:{id,window,enabled}}; system settings --show-codex-credits on\|off for presentation preference. Sibling/main decide ownership. | src/cli/system-command.ts:124; src/cli/account-extended.ts:326; gui/src/components/CodexAccountPool.tsx:374; src/server/management/config-routes.ts:564 | +| set-A10 — Native-main profile inventory, register, switch/recover | DISCOVERY_ONLY | account main list\|doctor\|register LABEL\|switch I --yes\|recover [--rollback --yes] --json | Native-profile workflows implemented, including staging add beyond GUI. CLI recover without rollback intentionally uses {rollback:false}; GUI's confirmedStopped true does not imply missing safe recovery action. | Index existing family; shared lifecycle owner should verify no-op recovery versus rollback fixture, not add a second writer. | src/cli/account-main.ts:269; src/cli/account-main.ts:280; src/cli/account-main.ts:359; src/cli/account-main.ts:376; gui/src/components/CodexAccountPool.tsx:564; src/codex/native-profile-api.ts:137 | +| set-A11 — Account-picker setting and main hard lock | IMPLEMENTATION_GAP | system settings --json reads values | No codexAccountPickerEnabled or codexMainAccountHardLock writer in dedicated settings handler. | Extend system settings --account-picker on\|off --main-account-hard-lock on\|off, exact settings fields and server receipt. Confirmed GUI mount at codex-set-multiauth:218/221; sibling-owned overlap, not unresolved reachability. | src/cli/system-command.ts:124; gui/src/pages/codex-set-multiauth.tsx:218; gui/src/components/CodexAccountPickerSetting.tsx:27; src/server/management/config-routes.ts:512 | +| set-A12 — Read prompt layer stack and effective prompt text | COMPLETE | inspect codex-prompt --json; inspect codex-prompt --text (mutually exclusive) | Stack and bounded effective-text read are implemented. | No new command; unavailable text remains unavailable, not empty successful content. | src/cli/inspect.ts:32; src/cli/inspect.ts:216; gui/src/pages/codex-set-prompt.tsx:147; src/server/management/codex-prompt-routes.ts:308 | +| set-A13 — Toggle/edit/order custom prompt layers and base variants | EXCLUDED | inspect codex-prompt is read-only | Prompt toggles, ordered custom layers, base select/edit/delete require GUI-session principal; no admin CLI write parity should be added. | Retain documented exclusion; user-directed GUI operation only unless parent separately redesigns product consent contract. | src/server/management/codex-prompt-routes.ts:299; src/server/management/route-registry.ts:198; gui/src/pages/codex-set-prompt.tsx:163; src/server/management/codex-prompt-routes.ts:332 | +| set-A14 — Adopt existing prompt configuration or repair prompt drift | EXCLUDED | inspect codex-prompt can expose drift | Adopt/repair preview and commit share session-only gate; no auto-repair from read. | Retain exclusion; do not create token-based adoption/repair command. | src/server/management/codex-prompt-routes.ts:299; src/server/management/codex-prompt-routes.ts:413; src/server/management/route-registry.ts:196; gui/src/pages/codex-set-prompt.tsx:304; src/server/management/codex-prompt-routes.ts:413 | +| set-A15 — Enable default-mode request-user-input | COMPLETE | agent request-user-input [on\|off] --json | Read and boolean write cover GUI; confirmed mounted in CodexSet. | No new command; sibling deduplicates advanced settings. | src/cli/inspect.ts:126; src/cli/agent.ts:432; gui/src/components/DefaultModeRequestUserInputSetting.tsx:7; src/server/management/agent-settings-routes.ts:509 | +| set-A16 — Toggle Ultra Fast tier | IMPLEMENTATION_GAP | system settings --json reads ultraFastTier | No --ultra-fast-tier mutation flag; provider fastEnabled and catalog fastRows are different settings. | Add system settings --ultra-fast-tier on\|off --json => {ultraFastTier}; preserve server default deletion semantics. | src/cli/system-command.ts:124; src/server/management/config-routes.ts:654; gui/src/components/UltraFastTierSetting.tsx:36; src/server/management/config-routes.ts:516 | +| set-M01 — Inspect catalog, exposed selection, context limits and provider metadata | DISCOVERY_ONLY | models live --provider P --json; models selected P; models context status; models preset show; models new-policy; alias list; inspect config/catalog | All catalog read families exist; plain models is explicitly static and cannot replace models live. | Index relevant leaves and communicate static versus live; no new catch-all catalog command required. | src/cli/models-runtime.ts:73; src/cli/models-runtime.ts:387; src/cli/models-runtime.ts:435; src/cli/models.ts:381; gui/src/pages/Models.tsx:395; src/server/management/model-routes.ts:213 | +| set-M02 — Show/hide selected models or all models of one provider | DISCOVERY_ONLY | models enable\|disable P/M [--native] --json; models provider P on\|off --json | Single-model and provider-all identity-aware writes exist. GUI has no separately required arbitrary multi-selection batch command beyond these workflows. | Index existing verbs; preserve native bit and provider membership, not raw disabled-list overwrite. | src/cli/models-runtime.ts:354; src/cli/models-runtime.ts:369; gui/src/model-visibility.ts:87; src/server/management/model-routes.ts:621 | +| set-M03 — Choose curated/provider model preset and default policy for newly discovered models | DISCOVERY_ONLY | models preset show [--provider P]; models preset apply P [--all]; models new-policy on\|off [--provider P]; models new-arrivals --json | GUI offers preset/all, both implemented. custom is a disabled state activated by model edits, not a missing GUI destination. Policy global/provider on/off covered. | No custom-preset flag required for GUI parity; index existing commands. Any server-only mode custom flag is optional API expansion. | src/cli/models-runtime.ts:435; src/cli/models-runtime.ts:474; gui/src/pages/Models.tsx:1529; gui/src/pages/Models.tsx:1550; gui/src/pages/Models.tsx:1170; src/server/management/model-routes.ts:233 | +| set-M04 — Edit provider/model aliases and default alias policy | DISCOVERY_ONLY | alias list; alias set P\|P/M ALIAS; alias rm P\|P/M; alias defaults on\|off [--provider P] --json | Provider/model aliases, explicit remove and global/provider defaults covered. | Index full family; do not conflate model alias with display label. | src/cli/alias.ts:16; gui/src/pages/models-alias-editing.ts:30; src/server/management/model-routes.ts:295 | +| set-M05 — Edit/reset model display label and cost override | IMPLEMENTATION_GAP | models price P/M; models set-price P/M --input N --output N [--cache-read N --cache-write N] or --auto; custom models edit --display-name only | Pricing including null reset complete. Discovered model display-name set/null clear absent; server route is also undeclared in registry. | Add models display-name P/M --set TEXT\|--clear --json; exact modelId/displayName body; preserve persistence receipt when HTTP reports catalog convergence failure. Do not repurpose custom model id endpoint. | src/cli/models-runtime.ts:106; src/cli/models-runtime.ts:202; src/cli/models-runtime.ts:566; src/server/management/model-routes.ts:447; gui/src/components/ModelPriceDialog.tsx:7; src/server/management/model-routes.ts:386 | +| set-M06 — Create/edit/delete custom model definitions | UNKNOWN | models add P M --display-name --context-window --modalities --reasoning-efforts --default-reasoning-effort; models list-custom --json; models edit ID ...; models remove ID\|P/M --yes | All GUI custom CRUD fields exist. Add/remove are local and call syncCustomModelsIfLive; add/remove lack --json, while edit is live HTTP. Need isolated same-target convergence proof before declaring complete or runtime gap. | Do not invent missing CRUD. If machine parity required, add --json with saved/convergence receipt to local add/remove; optionally route live operations through custom-models API while retaining explicit offline mode. | src/cli/models.ts:185; src/cli/models.ts:197; src/cli/models.ts:280; src/cli/models.ts:359; src/cli/models-runtime.ts:195; gui/src/pages/Models.tsx:1310; src/server/management/model-routes.ts:743 | +| set-M07 — Override/restore discovered-model capability metadata | COMPLETE | models set P/M --context-window N\|0\|- --modalities CSV\|- --reasoning-efforts CSV\|""\|- --default-reasoning-effort LEVEL\|-; --reset --json | All GUI metadata overrides and full null-reset exist; empty reasoning array versus inherited null is preserved. Catalog refresh failures have saved-state guidance. | Retain existing writer and schema; no generic JSON body option needed. | src/cli/models-runtime.ts:262; gui/src/components/ModelSettingsDialog.tsx:153; src/server/management/model-routes.ts:764 | +| set-M08 — Override provider/per-model advertised context window | IMPLEMENTATION_GAP | models set P/M --context-window N\|0\|- covers per-model override | Provider-level contextWindow default and one patch containing touched modelContextWindows lack flags. Per-model individual override is already covered; do not duplicate it. | Extend provider edit P --context-window N\|- and repeatable --model-context-window MODEL=N\|-; null clears, untouched keys remain absent. Atomic multi-model patch is optional if parent accepts equivalent individual tasks; provider default is required. | src/cli/provider-runtime.ts:59; src/cli/models-runtime.ts:281; gui/src/pages/Models.tsx:854; gui/src/pages/Models.tsx:825; src/server/management/provider-routes.ts:1412 | +| set-M09 — Configure context caps: per-provider, global default, apply/remove all | DISCOVERY_ONLY | models context status; models context value N [--set-all]; models context provider P on\|off [--value N]; models context all on\|off --json | All three cap shapes covered, including per-provider explicit value and apply/remove-all. No implementation gap. | Improve discovery only; preserve distinction between global default and applying to every provider. | src/cli/models-runtime.ts:500; gui/src/pages/Models.tsx:939; src/server/management/provider-routes.ts:1881 | +| set-M10 — Configure picker order manually or by ranking policy | IMPLEMENTATION_GAP | agent subagents status shows picker fields; agent subagents set writes featured models only | No pickerOrder/pickerOrderMode writer. Manual order, default reset, alphabetical/provider/most-used modes all missing. | models order status; models order set --models CSV; models order set --mode default\|alphabetical\|provider\|most-used; models order reset --json. Manual/reset => mode null; ranking computes complete order from visible identities and usage where needed. Never write models for this task. | src/cli/agent.ts:163; src/cli/models-runtime.ts:566; gui/src/pages/Models.tsx:1904; gui/src/components/ModelPickerOrderEditor.tsx:83; src/server/management/subagent-model-routes.ts:19 | +| set-M11 — Show generated Fast catalog rows | IMPLEMENTATION_GAP | system settings --json reads fastRows | No global fastRows flag; not covered by provider fastEnabled or ultraFastTier. | Add models fast-rows on\|off --json or system settings --fast-rows on\|off, choose one canonical verb and document alias if needed; PUT {fastRows}. | src/cli/system-command.ts:124; src/cli/models-runtime.ts:566; gui/src/components/ModelCatalogSettingsPanels.tsx:11; src/server/management/config-routes.ts:519 | +| set-M12 — Configure shadow-call interception target | DISCOVERY_ONLY | models shadow status; models shadow set M\|- --enabled on\|off --json | Enable/disable target and empty-string clear covered. | Index existing command; retain validation on enable and target clear. | src/cli/models-runtime.ts:544; gui/src/pages/Models.tsx:480; src/server/management/config-routes.ts:1159 | +| set-M13 — Configure multi-agent surface and per-session thread limit | UNKNOWN | v2 status; v2 mode v1\|default\|v2; v2 keep-native-v1 on\|off; v2 threads N (local, prose output) | All GUI effects have existing local commands. Mode/keep-native save config and resync; threads uses shared transition helper. No structured --json contract or GUI advisory-ack write in cmdV2. Same live-target and receipt equivalence remains unproven; these are NOT absent operations. | Keep ocx v2 taxonomy. Add strict --json parsing/receipts if machine parity is required; do not create agent mode. Parent decides whether advisory is GUI-only or needs an explicit v2 acknowledgment option. Verify local/shared helpers versus live management path before choosing transport changes. | src/cli/v2.ts:109; src/cli/v2.ts:177; src/cli/v2.ts:191; src/cli/v2.ts:220; src/cli/dispatch.ts:539; src/server/management/agent-settings-routes.ts:415; gui/src/pages/Models.tsx:1101 | +| set-C01 — Inspect combos, target inventory, quota and catalog exposure | DISCOVERY_ONLY | combo list/show I; models live; inspect config; provider quota --json | All combo inventory/target/quota inputs present; GUI grouping doesn't require a separate command. | Index combo/route combo family; no new transport. | src/cli/combo.ts:54; src/cli/combo.ts:65; src/cli/dispatch.ts:849; gui/src/pages/Combos.tsx:138; src/server/management/combo-routes.ts:122 | +| set-C02 — Create/edit/rename/remove combo and target policy | IMPLEMENTATION_GAP | combo set\|create\|update I --targets P/M[:W],... --strategy S --sticky N\|- --effort E\|- --alias A\|- --native-alias --display-name TEXT\|- --decision-provider P\|- --decision-model M\|- --decision-timeout N\|- --rename-from OLD; remove I --yes | Core CRUD/rename/JEV resets exist. Missing imageInput auto/disabled, reasoningEffortMode strict/adaptive, target reasoningEfforts/modelProfile; native-alias cannot explicitly switch off while keeping a native-shaped alias. --effort-mode is defaultEffortMode, NOT reasoningEffortMode. Replacing targets loses metadata without expressive parser. | Extend combo set with --image-input auto\|disabled --reasoning-effort-mode strict\|adaptive --native-alias on\|off (backward-compatible bare flag); --targets-file FILE for typed ordered targets incl optional reasoningEfforts/modelProfile, or repeatable structured --target flags. Preserve omitted fields and explicit clears. | src/cli/combo.ts:32; src/cli/combo.ts:80; src/cli/combo.ts:137; src/cli/combo.ts:163; gui/src/pages/Combos.tsx:301; src/server/management/combo-routes.ts:134 | +| set-C03 — Probe selected JEV decision backend | COMPLETE | combo test [--combo I] [--decision-provider P\|--decision-model M] [--decision-timeout N] --json | Existing probe resolves saved selector client-side when --combo; explicit args probe chosen draft. Discovery command also exists. | No gap; keep potential model-call cost visible and do not treat successful configuration-only response as probe success. | src/cli/combo.ts:186; src/cli/combo.ts:215; gui/src/components/combo-workspace-jev-decision.tsx:107; src/server/management/decision-routes.ts:53 | +| set-C04 — Explain a saved combo's protocol behavior | COMPLETE | api protocols --json; api explain --model combo/I --inbound responses\|chat\|messages --feature F[,F] ... --json | Saved combo plan and features covered by semantic protocol command. | No combo-specific duplicate required; document usage with public alias. | src/cli/api-protocols.ts:121; src/cli/api-protocols.ts:131; gui/src/components/combo-workspace-detail-panel.tsx:416; src/server/management/protocol-routes.ts:45 | +| set-C05 — Inspect JEV combo decision outcomes and savings | IMPLEMENTATION_GAP | usage --range ... --model combo/I exists but returns ordinary usage | No jev=1/comboId report selector in usage parser; ordinary model-filtered usage is not JEV decisions/savings/backends report. | Add combo stats I --range 7d\|30d\|all --json, exact GET usage?jev=1&comboId=I&range=; sibling usage owner can share transport/formatting. Do not claim cost savings from missing/partial data. | src/cli/observe.ts:164; src/cli/combo.ts:251; gui/src/components/jev-stats-panel.tsx:90; gui/src/components/jev-stats-panel.tsx:90; src/server/management/logs-usage-routes.ts:188 | +| set-R01 — Inspect routing profiles, candidates, scoring and compatibility suite choices | DISCOVERY_ONLY | route policy list/show I --json; inspect routing-analytics --json; models live; lab catalog --json | Existing commands expose profile/revision, scoring context, inventory and Lab suite choices. | Index leaves; local Lab query is valid transport for local target. | src/cli/route-policy.ts:27; src/cli/route-policy.ts:43; src/cli/inspect.ts:211; src/cli/lab.ts:87; gui/src/pages/RoutingProfiles.tsx:351; src/server/management/routing-profile-routes.ts:226 | +| set-R02 — Create/update/remove routing profile | IMPLEMENTATION_GAP | route policy only list/show/dry-run/evaluate | No create/update/delete. Missing all profile-write fields and expectedRevision conflict workflow. | route policy create I --file PROFILE.json --json; route policy update I --file PROFILE.json --expected-revision REV --json; route policy remove I --yes --json. Domain profile schema is exact GUI profile object, not arbitrary endpoint JSON. Omitted profile branches are removed according to server full-profile semantics. | src/cli/route-policy.ts:85; src/server/management/routing-profile-routes.ts:233; gui/src/routing-profile-editor-data.ts:280; gui/src/pages/RoutingProfiles.tsx:458; src/server/management/routing-profile-routes.ts:233 | +| set-R03 — Dry-run a saved route against requirements | DISCOVERY_ONLY | route policy dry-run\|evaluate I --model-context N --tools --image --structured-output --json | All four GUI evidence inputs supported. Advanced encrypted/reasoning/tier/candidate evidence are server-only and not GUI parity debt. | Index command; optional broader API support should be separate scope. | src/cli/route-policy.ts:55; gui/src/pages/RoutingProfiles.tsx:559; src/server/management/routing-profile-routes.ts:364 | +| set-S01 — Choose/reorder featured subagent roster | DISCOVERY_ONLY | agent subagents\|roster status\|set CSV\|clear --json | Featured ordered roster, five-item max and empty-list clear covered; this does not cover M10 picker ordering. | Index leaf actions without creating a second roster writer. | src/cli/agent.ts:163; src/cli/agent.ts:426; gui/src/pages/Subagents.tsx:213; src/server/management/subagent-model-routes.ts:54 | +| set-S02 — Force subagent model and configure fallback chain | COMPLETE | agent subagents force M\|-; agent fallback status\|set [CSV] [--poll-ms 5000..600000]\|clear --json | Force null and fallback empty-list clear/poll range match GUI. Server-only poll null reset not exposed in GUI, so not a GUI gap. | Retain implementation; document identity and clear semantics. | src/cli/agent.ts:173; src/cli/agent.ts:195; gui/src/components/subagents-workspace/SubagentForceControl.tsx:67; src/server/management/subagent-model-routes.ts:101 | +| set-S03 — Configure delegation guidance/default model/effort and synchronize defaults | IMPLEMENTATION_GAP | agent injection\|guidance set --model M\|- --effort E\|- --guidance on\|off; status --json | Model, effort and guidance covered; syncCodexSubagentDefaults missing. Existing set outputs write result without GUI's normalized reread. | Add --sync-codex-defaults on\|off, exact field. Read authoritative injection DTO after successful save if write doesn't return normalized state; retain null clears. | src/cli/agent.ts:111; src/cli/agent.ts:137; src/server/management/agent-settings-routes.ts:608; gui/src/pages/use-subagent-delegation.ts:15; src/server/management/agent-settings-routes.ts:564 | +| set-S04 — Set delegation mode and editable proactive hint | UNKNOWN | v2 mode v1\|default\|v2; v2 mode-hint TEXT; v2 mode-hint --clear; v2 status (local) | Mode and hint set/null-reset already exist. mode-hint uses same setMultiAgentModeHintText helper as management route; blank text rejected. Root registry omits mode-hint and cmdV2 lacks JSON/strict trailing-argument receipt handling. Shared mode live-equivalence/advisory issue is M13, not missing hint writer. | Document/index v2 mode-hint and --clear; extend existing v2 machine contract, not agent mode. A hint-file convenience is optional, not GUI parity debt. Test local scope/new-session behavior and shared writer failures before classifying local/live coverage complete. | src/cli/v2.ts:144; src/cli/v2.ts:167; src/cli/v2.ts:191; src/cli/registry.ts:575; src/server/management/agent-settings-routes.ts:394; gui/src/pages/Subagents.tsx:131 | +| set-S05 — Ask for delegation model recommendation, then separately apply | COMPLETE | agent injection suggest WORK [--model SIZING_MODEL] [--apply] --json; agent injection set --model M --effort E | Suggestion, no-write default and explicit apply cover GUI propose/accept; includes optional sizing override beyond GUI. | No new command; preserve proposal failure/unsized and explicit apply semantics. | src/cli/agent.ts:73; gui/src/components/subagents-workspace/DelegationSuggest.tsx:49; src/server/management/agent-settings-routes.ts:578 | +| set-K01 — Inspect/filter/paginate compatibility verdicts and subjects | DISCOVERY_ONLY | lab status; lab verdicts --subject --layer --suite --verdict --limit --cursor; lab subjects --limit --cursor --json | Filters/pagination and status read via local projection query already exist. Remote target equivalence is not proven and outside this local scope. | Index local read family; avoid new HTTP-only duplicates. | src/cli/lab.ts:76; src/cli/lab.ts:365; src/cli/lab.ts:385; gui/src/pages/compatibility-matrix-api.ts:35; src/server/management/lab-routes.ts:354 | +| set-K02 — Inspect one verdict's evidence lineage and production context | DISCOVERY_ONLY | lab subject I; observations --subject I --layer L --suite T --limit --cursor; event I; artifact D; production-signals --subject I --limit --json | All lineage resources exposed; GUI aggregation is composition over named reads. No need to mimic bounded visual panel in CLI; preserve not_verification marker. | Document an evidence-lineage recipe and local target caveat; optional consolidated explain command is convenience, not confirmed missing data. | src/cli/lab.ts:76; src/cli/lab.ts:418; src/cli/lab.ts:428; src/cli/lab.ts:468; gui/src/pages/compatibility-matrix-api.ts:150; src/server/management/lab-routes.ts:358 | +| set-K03 — Filter protocol pairs and view community trust context | DISCOVERY_ONLY | lab subject I --json; lab public community --json | Community trust DTO and subject protocol pairs exposed. Pair dropdown filters are client-side presentation over subject details; no new protocol-pair endpoint. | Index command/recipe; no mutation gap. If parent wants server-side pair filtering, treat it as separate enhancement. | src/cli/lab.ts:92; src/cli/lab.ts:297; src/cli/lab.ts:418; gui/src/pages/compatibility-protocol-pairs.ts:14; src/server/management/lab-routes.ts:287 | +| set-K04 — Inspect provider upstream wire/protocol and conversion plan | COMPLETE | api protocols [--provider P] --json; api explain --model M --inbound PROTOCOL [--feature F] --json | Provider wire, global policy revision and plan features covered. | Retain semantic CLI commands; not generic passthrough. | src/cli/api-protocols.ts:121; src/cli/api-protocols.ts:131; gui/src/components/provider-workspace/ProviderProtocolPanel.tsx:1; src/server/management/protocol-routes.ts:67 | +| set-K05 — Control protocol exposure/rollout | COMPLETE | api policy --messages on\|off --unrepresentable legacy\|reject --rollout SWITCH=on\|off ... --json | Messages toggle and all server rollout fields already supported. Actual GUI control is on API-surface cards, a sibling boundary. | No gap. Preserve strict feature/rollout validation; sibling can index overlapping entrypoint. | src/cli/api-protocols.ts:151; gui/src/pages/api-surface-cards.tsx:57; src/server/management/protocol-routes.ts:143 | + +## Priority remediation specifications and next proof + +These are bounded implementation candidates for the parent; several matrix rows share a single change. The 24 IMPLEMENTATION_GAP rows are **not** 24 independent command families. M13/S04 are now UNKNOWN for local/live equivalence, with existing effects confirmed. + +| Priority / rows | Exact implementation contract | Required isolated proof (not run here) | +|---|---|---| +| First: set-M05 display names | `models display-name P/M --set TEXT` or `--clear` sends PUT `/api/providers/P/model-display-names` `{modelId:M,displayName:TEXT|null}`. Add regex route declaration. Keep custom model edit unchanged. Server can save and then return failed convergence; CLI must retain saved state/error receipt instead of saying no change happened. | Set, clear, missing model, encoded provider/model identifiers, saved-but-refresh-failed response; prove correct resource and that retry does not invent a custom definition. Source `src/server/management/model-routes.ts:447`; GUI receipt comment `gui/src/pages/Models.tsx:647`. | +| First: set-R02 routing profile writes | Create `{mode:"create",id,profile}`; update `{mode:"update",id,expectedRevision,profile}`; remove query id with explicit destructive intent. Profile file is bounded/validated domain input. Exact fields: alias,candidates[{provider,model}],require{minContextWindow,minQuotaHeadroom,tools,imageInput,structuredOutput,reasoningEffort,serviceTier,localOnly,remoteAllowed,encryptedCodexTasks},optimize{latency,health,cost,quota},limits{maxEstimatedCostUsd,onUnknownCost},unknownEvidence,compatibility{requiredSuites,minStatus,maxEvidenceAgeMs,unknownEvidence,degradedEvidence}. | Create collision; update missing/stale revision leaves existing profile unchanged; delete dependent/in-use refusal; optional branch removal semantics and unknown field validation. Sources `src/cli/route-policy.ts:85`, `src/server/management/routing-profile-routes.ts:233`, `gui/src/routing-profile-editor-data.ts:280`. | +| First: set-P07 provider snapshot/apply | Snapshot projected `{defaultProvider,providers}` only; apply exact `{baseline,next}` through PUT providers. No port/system/secret dump; strip derived GUI fields same as DTO projection. Never auto-retry stale baseline with fresh state because that would authorize overwriting intervening edits. | Stale-baseline 409; invalid endpoint/row; removal with dependencies; baseline read includes only permitted projection; no write after preview refusal; confirmed saved/catalog receipt. Sources `gui/src/hooks/useJsonConfigEditor.ts:16`, `src/server/management/provider-routes.ts:1055`. | +| First: set-A07/set-A06/set-P15/set-P19 account gaps | Credit policy: `{id,creditsAfterLimit:boolean}` OR `{all:boolean}`; reject ambiguous selector/all. Codex override `{id,threshold:number|null}` with inherit -> null; pool default remains `{threshold}`. Unified pool PATCH/PUT fields provider,enabled,strategy,stickyLimit,autoSwitchThreshold,quotaWindow; quotaWindow enum five-hour/weekly/max-utilization is Anthropic-only. Anthropic grants command is GET-only; consume session gate remains excluded. | One versus all, on/off, explicit main identity, unknown id, inheritance versus zero, invalid quota window, unsupported provider fields, no secret output, consume refusal without user GUI session. Sources `src/codex/auth-api/routes.ts:122`, `src/codex/auth-api/routes.ts:310`, `src/server/management/oauth-account-routes.ts:559`, `src/server/management/anthropic-reset-grant-routes.ts:131`. | +| Next: set-M10 picker order | `models order` owns pickerOrder and pickerOrderMode only; never changes featured models or force. Manual ordered ids + null mode; default/reset -> empty/default order + null mode; alphabetical/provider/most-used computes order using current visible identities, preserves supported model namespaces, sends matching mode. Most-used refuses incomplete usage evidence rather than sorting a partial sample. | Capture exact body; roster/force unchanged; native/routed id collision; duplicate/invisible ids; null/default reset; most-used incomplete usage refusal. Sources `src/server/management/subagent-model-routes.ts:74`, `gui/src/pages/Models.tsx:1904`. | +| Next: set-S03 injection field; set-S04/set-M13 existing v2 contract | Extend injection set only with syncCodexSubagentDefaults boolean and normalized reread. Existing `ocx v2 mode`, `keep-native-v1`, `threads`, `mode-hint TEXT` and `mode-hint --clear` already implement the other GUI effects locally. Add strict JSON parsing/receipt support in the existing family if required; advisory acknowledgment remains a parent product-contract decision. No duplicate agent-mode writer. | Injection effort normalization; local/live same-home/target and sync outcome; structured v2 output without swallowed trailing flags; hint blank rejection/null reset; advisory not auto-acknowledged. Sources `src/cli/agent.ts:125`, `src/cli/v2.ts:109`, `src/cli/v2.ts:144`, `src/cli/v2.ts:177`, `src/cli/v2.ts:191`, `src/cli/v2.ts:220`, `src/server/management/agent-settings-routes.ts:415`. | +| Next: set-C02 combo fields | Typed targets input includes ordered provider/model, optional weight, reasoningEfforts, modelProfile. Add imageInput auto/disabled and reasoningEffortMode strict/adaptive. Do not confuse defaultEffortMode with reasoningEffortMode. Explicit nativeAlias false needed to disable while alias remains native-shaped. Existing renameFrom/JEV null selector/timeouts retained. | Metadata survives unrelated edit and target reorder; auto/strict explicitly revert disabled/adaptive; remove a target override intentionally; nativeAlias on/off; JEV provider/model mutual exclusion and null resets; rename retains dependencies. Sources `src/cli/combo.ts:32`, `src/cli/combo.ts:137`, `gui/src/combo-workspace-data.ts:507`. | +| Next: set-P03/set-P04/set-P17/set-M08 provider fields | HTTP override null clears. Provider contextWindow null clears; modelContextWindows merges touched keys with per-key null deletes. requestPacing is whole-object replacement, not server merge: flags must either read/merge existing provider state or require a full typed pacing file; `--clear` sends requestPacing:null. fastEnabled boolean has separate meaning from global fastRows. | Exact PATCH body includes only intended fields; per-model pacing edit retains other rules; clear removes object; context null removes only selected key; Cursor protocol validation; provider fast toggle doesn't affect global fastRows. Sources `src/server/management/provider-routes.ts:479`, `src/server/management/provider-routes.ts:493`, `src/server/management/provider-routes.ts:513`, `src/server/management/provider-routes.ts:542`. | +| Parent/sibling merge: set-A09/set-A11/set-A16/set-M11/set-C05 | Settings flags write showCodexCredits,codexAccountPickerEnabled,codexMainAccountHardLock,ultraFastTier,fastRows. Quota activation writes `{codexQuotaAutoRefresh:{id,window:"fiveHour"|"weekly",enabled}}`; do not confuse this enum with pool quotaWindow. Combo stats reads `usage?jev=1&comboId=I&range=7d|30d|all`, not ordinary usage model filter. | Independent field bodies; true/false defaults; unavailable activation window returns 409; JEV-specific response/partial data; no duplicate ownership with operations sibling. Sources `src/server/management/config-routes.ts:564`, `src/cli/system-command.ts:124`, `src/cli/observe.ts:164`. | +| Requires behavior proof: set-P02/set-P05/set-M06/P10 local-live portions | Preserve working offline/local commands; do not claim live management equivalence from local save alone. Add with --json currently returns before --sync; remove default differs from GUI and local dependency checks differ. Custom add/remove invoke live sync helper but need same-target fixture before deciding on a transport rewrite. | Isolated local config + fake live transport: same target selected, save/sync order and outcome, default deletion semantics, dependent combo refusal, JSON mode still applies requested sync, logout live cache convergence. Sources `src/cli/provider.ts:64`, `src/cli/provider.ts:279`, `src/cli/provider.ts:345`, `src/cli/models.ts:185`, `src/cli/dispatch.ts:425`. | + +## Explicit scope limits and exclusions + +- No changes to the settings GUI/API inventory in this pass. Corrections above are recorded here so parent can reconcile without concurrent edits. +- Prompt mutation rows set-A13/set-A14 remain EXCLUDED; Anthropic grant consumption within set-P19 is EXCLUDED even though its read is an implementation gap. Human consent is not a flag to silently auto-answer. +- Browser tabs/dialogs/search/collapse/clipboard/SSE invalidation are presentation mechanisms, not missing command operations. Protocol pair filtering over existing subject data belongs to this category; preserving unknown/trust evidence is still required. +- Existing API protocol commands are complete, context-cap shapes are complete, model-settings full null reset is complete, and native-main reauth is complete. Do not duplicate these under new nouns. +- Lab local projection readers are implementation, not missing HTTP calls. A future remote-target contract needs separate evidence; current source inventory doesn't authorize that expansion. +- Main owns final command naming, roadmap/FSM, fixtures and implementation. This report recommends syntax but does not execute commands or claim runtime parity. + +## Final correction audit and bounded remaining unknowns + +Root-family cross-check followed `src/cli/registry.ts:277` provider, `:311` account, `:333` alias, `:337` models/model, `:369` combo/route, `:380` effort, `:393` agent, `:404` inspect, `:413` usage/observe, `:575` v2, plus already-inspected system/settings, API protocols and Lab handlers. Targeted checks of v2, effort, access and config-command found no dedicated writer for the remaining claimed pacing/fast/picker/credit/quota-activation fields. Generic config remains explicitly outside task-parity proof. No whole-CLI rescan was performed. + +Bounded unknowns: + +- **set-M13 / set-S04:** all operations exist under v2. Compare local config/CODEX_HOME, catalog sync result, existing shared transition/hint helpers, and GUI live receipt/advisory semantics with isolated fixtures. Missing JSON/strict argument contract and unindexed mode-hint are confirmed; whether GUI advisory acknowledgment should become a CLI field is a parent decision. +- **set-M06:** custom model CRUD fields exist; local add/remove and live edit need isolated same-target save/convergence proof. Missing JSON on add/remove is confirmed; no claim of absent CRUD. +- **Partial uncertainty within known-gap rows:** provider add/remove/set-default and OAuth local logout need live equivalence proof; their concrete missing fields or behavior differences are documented separately, so UNKNOWN transport does not erase those gaps. +- **Sibling boundaries:** quota activation/settings and JEV stats recommendations need deduplication with operations/client-settings owner. Their GUI mounts and missing dedicated field parsers were inspected; ownership, not existence, is unresolved. + +Final matrix totals: 67 rows = 16 COMPLETE + 22 DISCOVERY_ONLY + 24 IMPLEMENTATION_GAP + 2 EXCLUDED + 3 UNKNOWN. Source-only evidence; no tests or live operations executed. diff --git a/devlog/_plan/261003_cli_gui_parity/005_operations_coverage.md b/devlog/_plan/261003_cli_gui_parity/005_operations_coverage.md new file mode 100644 index 00000000000..26480746bc1 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/005_operations_coverage.md @@ -0,0 +1,158 @@ +# Operational task parity join + +Source-only bounded second pass, 2026-10-03. Root: `the task checkout`. Joined the operations GUI/API inventory with the CLI source inventory and targeted handlers only. No runtime requests, credentials, source edits, tests or Git writes. Source presence is not runtime proof. Main owns command conventions and the implementation roadmap. + +Status meanings: COMPLETE = existing domain command or documented sequence supports the task; DISCOVERY_ONLY = effect exists but task/leaf/route metadata is incomplete; IMPLEMENTATION_GAP = a necessary action/field/workflow cannot be expressed by the inspected handler; EXCLUDED = current deliberate session/consent or pure presentation boundary; UNKNOWN = target scope or sibling ownership prevents an honest equivalence claim. COMPLETE does not certify global JSON error/exit contracts; those are shared CLI audit work. New syntax below is a recommendation, never a claim of an existing command. + +## Highest-value confirmed gaps + +- `ops-K03`: key rename. Existing `access key set` only scopes providers/models (`src/cli/access.ts:168`); no name operand, despite sharing the GUI PATCH endpoint. Recommend `ocx access key rename [--json]`. +- `ops-T07`: cleanup threshold and reduction target. Policy parser (`src/cli/storage.ts:162`) has enabled/percent/mode/schedule only; GUI submits trigger.archivedBytesOver and target.reduceToBytes (`gui/src/pages/Storage.tsx:709`). Recommend mutually exclusive `--remove-oldest-percent` / `--reduce-to-bytes`, plus `--archived-bytes-over`. +- `ops-D15`, `ops-D16`: sidecar fields. Actual parser (`src/cli/agent.ts:256`) omits webSearch.streamRoutedModelOutput and vision.timeoutMs, both writable in GUI. Recommend `agent sidecar web --stream-routed-output on|off`, `agent sidecar vision --timeout-ms N`. +- `ops-O13`, `ops-I15`, `ops-I16`: timeline and Cursor reads are advertised by capabilities but absent from real handlers. Recommend `companion timeline` and `integration native cursor status|local-installer` (read-only). +- `ops-I10`/profile part of `ops-I13`, `ops-R01`/`ops-R07`: declared journal retirement and Hub read debt. Preserve registry owners; executor-local remote-workspace status is not Hub status. +- `ops-I06`, `ops-L07`: Droid reasoning-default payload and link force-removal option absent from existing writer/parser. +- `ops-K08`: `access test` exists, but does not accept the newly created data key and uses runtimeRequest management headers (`src/cli/access.ts:255`, `src/cli/runtime-api.ts:142`). It is not proof that the chosen key works. Recommend a separate `--api-key-stdin` path with explicit inference authorization and no secret echo; do not use the admin-header helper for data-plane key verification. + +Local/native counterexamples: startup repair invokes `ocx service repair`; shim repair invokes `ocx codex-shim install` (`src/server/startup-action-control.ts:109`); Windows tray writes invoke `ocx tray --json` (`src/server/windows-tray-control.ts:9`). None is a missing effect merely because an HTTP route has no literal CLI caller. + +## Per-task join + +Commands below omit the common `ocx` prefix for readability. Each ID maps to the operations inventory. Proposed flags are recommendations, not existing features. + +| Task and GUI anchor | Status | Existing commands | Missing field/workflow or recommended syntax | Targeted proof | +|---|---|---|---|---| +| **ops-D01** — Read live health/version/uptime and provider overview; `gui/src/pages/dashboard-core-poll.ts:275` | UNKNOWN | status --json; health --json; system status --json | Liveness exists; system status bundles settings/startup/memory, not system/health. Exact remote version/uptime/spendLedger projection requires target comparison. Proposed system status extension only if needed. | src/cli/system-command.ts:35; src/cli/dispatch.ts:787; src/cli/index.ts:1677 | +| **ops-D02** — Read model catalog and 30d usage; `gui/src/pages/dashboard-core-poll.ts:135`, `:142` | DISCOVERY_ONLY | models live --json; usage --range 30d --json | Catalog and usage reads exist; publish model live leaf. Provider/account projection details remain sibling-owned. | src/cli/models-runtime.ts:73; src/cli/observe.ts:209 | +| **ops-D03** — Read runtime/client preferences; `gui/src/pages/dashboard-core-poll.ts:218` | DISCOVERY_ONLY | system settings --json | No field gap; complete settings leaf metadata. | src/cli/system-command.ts:123 | +| **ops-D04** — Set Codex autostart; `gui/src/pages/use-dashboard-data.ts:753`, `:777` | DISCOVERY_ONLY | system settings --auto-start on/off --json | Boolean supported; no new setter needed. | src/cli/system-command.ts:127 | +| **ops-D05** — Set Desktop authless / client compaction; `gui/src/pages/use-dashboard-data.ts:768`, `:778` | DISCOVERY_ONLY | system settings --desktop-authless on/off --client-compaction on/off --json; then system sync --json | Stored/effective/file-apply result exists. GUI auto-sync is expressible as sequence; document partial apply and explicit sync. | src/cli/system-command.ts:61; src/cli/system-command.ts:139; src/cli/system-command.ts:206 | +| **ops-D06** — Sync client catalogs/configuration; `gui/src/pages/use-dashboard-data.ts:790`, `:796` | DISCOVERY_ONLY | system sync --json | Same POST/result; register leaf. Connected machine uses S05, not shared-hub target. | src/cli/system-command.ts:206 | +| **ops-D07** — Read project-config warnings; `gui/src/pages/dashboard-core-poll.ts:126` | DISCOVERY_ONLY | system diagnostics --json | No missing query; register child metadata. | src/cli/system-command.ts:204 | +| **ops-D08** — Read startup protection; `gui/src/pages/dashboard-core-poll.ts:104`; `gui/src/pages/Startup.tsx:140` | DISCOVERY_ONLY | system startup health/status --json | Startup protection readable. Existing hidden __startup-health is not a proposed public task. | src/cli/system-command.ts:150; src/cli/dispatch.ts:760 | +| **ops-D09** — Read memory/storage pressure and active turns; `gui/src/components/MemoryObservabilityCard.tsx:243` | DISCOVERY_ONLY | observe memory --json; memory --json | Full metrics/active-turn payload readable; register diagnostic leaf. | src/cli/observe.ts:280 | +| **ops-D10** — Drain and restart proxy; `gui/src/components/MemoryObservabilityCard.tsx:359` | COMPLETE | restart | Live drain/replacement exists; fallback ensure if stopped. Do not replace with ordinary stop/start. JSON/error-contract work is shared audit. | src/cli/dispatch.ts:777; src/cli/system-restart-client.ts:1 | +| **ops-D11** — Check latest/preview package update; `gui/src/pages/use-dashboard-data.ts:824` | DISCOVERY_ONLY | system update check --channel latest/preview --json | Both GUI channels supported; register leaf. | src/cli/system-command.ts:166 | +| **ops-D12** — Run package update, optionally restart; `gui/src/pages/use-dashboard-data.ts:909` | DISCOVERY_ONLY | system update run --channel latest/preview --restart on/off --yes --json | All payload fields exist. Accepted job is not completed update; use D13. | src/cli/system-command.ts:184 | +| **ops-D13** — Observe update job; `gui/src/pages/use-dashboard-data.ts:493` | DISCOVERY_ONLY | system update status JOB-ID --json | Polling can be composed; --wait is optional convenience, not absent backend capability. | src/cli/system-command.ts:169 | +| **ops-D14** — Desktop-shell update navigation; `gui/src/pages/use-dashboard-data.ts:6` (openDesktopUpdatePage dependency), `gui/src/pages/dashboard-overview-sections.tsx:220` | EXCLUDED | Desktop update UI panel | Shell navigation/native updater display differs from package job; preserve desktop-internal snapshot exemption. | src/server/management/route-registry.ts:376; gui/src/pages/use-dashboard-data.ts:6 | +| **ops-D15** — Web search sidecar off/on/model/stream; `gui/src/pages/dashboard-overview-sections.tsx:585`, `:606`; save `gui/src/pages/use-dashboard-data.ts:563` | IMPLEMENTATION_GAP | agent sidecar web --model ID --backend BACKEND --enabled on/off --json | Missing webSearch.streamRoutedModelOutput. Recommend --stream-routed-output on/off. Selecting a model after Off needs --enabled on, already supported. | src/cli/agent.ts:256; gui/src/pages/dashboard-overview-sections.tsx:606 | +| **ops-D16** — Vision sidecar off/on/model/reasoning/limits/timeout; `gui/src/pages/dashboard-overview-sections.tsx:467`, `:480`, `:628`, `:648` | IMPLEMENTATION_GAP | agent sidecar vision --model ID --backend BACKEND --reasoning LEVEL --max-descriptions N --enabled on/off --json | Missing vision.timeoutMs. Recommend --timeout-ms N; preserve backend/model coherence and sibling fields. | src/cli/agent.ts:256; gui/src/pages/dashboard-overview-sections.tsx:480 | +| **ops-D17** — Shadow-call interception toggle/model; `gui/src/pages/dashboard-overview-sections.tsx:716`, `:728`; save `gui/src/pages/use-dashboard-data.ts:610` | DISCOVERY_ONLY | models shadow status --json; models shadow set MODEL --enabled on/off --json | Enabled/model supported, '-' clears model. Publish leaf, no new writer. | src/cli/models-runtime.ts:546 | +| **ops-D18** — Multi-agent mode/advisory, injection/guidance/defaults, effort caps; `gui/src/pages/use-dashboard-data.ts:640`, `:679`, `:727`; `gui/src/pages/dashboard-overview-sections.tsx:78`, `:103` | UNKNOWN | v2; agent injection/effort/subagents/roles | Sibling owns multi-agent/advisory/injection/compaction/memory-model field join. No duplicate completeness claim here. | gui/src/pages/use-dashboard-data.ts:640; gui/src/pages/use-dashboard-data.ts:679; src/cli/agent.ts:48 | +| **ops-S01** — Install service / repair service / install shim; `gui/src/pages/Startup.tsx:290`, `:294` | COMPLETE | service install; service repair; codex-shim install; system startup install-service/install-shim --json | GUI launcher directly maps to these commands. system startup has no --repair, but direct service repair is equivalent; shim repair is install. | src/server/startup-action-control.ts:109; src/service/cli.ts:233; src/cli/dispatch.ts:679 | +| **ops-S02** — Windows tray status; `gui/src/pages/Startup.tsx:176` | COMPLETE | tray status --json; inspect windows-tray --json | Local command and management read both exist; platform support reported. | src/tray/windows.ts:784; src/cli/inspect.ts:213 | +| **ops-S03** — Windows tray install/start/stop/uninstall; `gui/src/pages/Startup.tsx:268` | COMPLETE | tray install/start/stop/uninstall --json | GUI backend invokes this actual CLI; no missing route-effect gap. | src/server/windows-tray-control.ts:9; src/tray/windows.ts:784 | +| **ops-S04** — Connected-machine shim status/install/repair/uninstall; `gui/src/pages/Startup.tsx:97`, `:104` | COMPLETE | codex-shim status/install/uninstall | Same diagnose/install/uninstall functions; repair maps to install in machine owner. Must run on client machine, not hub. Structured status is output enhancement only. | src/client/machine-api.ts:113; src/client/machine-api.ts:125; src/cli/dispatch.ts:695 | +| **ops-S05** — Read connected-machine selected clients / sync them; `gui/src/pages/Integrations.tsx:62`, `:72` | UNKNOWN | sync on connected machine | Mutation exists; selectedClients+journalOwner display and machine-target receipt need client-state owner join. Keep domain sync syntax, not generic machine HTTP. | src/client/machine-api.ts:87; src/cli/dispatch.ts:508 | +| **ops-C01** — Read Claude Code effective state/model choices; `gui/src/pages/ClaudeCode.tsx:88` | COMPLETE | claude config status --json | Same effective-state GET and fields. | src/cli/integrations.ts:64 | +| **ops-C02** — Enable/disable Claude connection immediately; `gui/src/pages/ClaudeCode.tsx:166`; `gui/src/pages/use-claude-connection.ts:2` | COMPLETE | integration native claude on/off --json | Same immediate native mutation; local config edit alone would not count. | src/cli/inspect.ts:85; src/cli/inspect.ts:113 | +| **ops-C03** — Enable/disable CLI first-party proxy environment; `gui/src/pages/ClaudeCode.tsx:178` | COMPLETE | claude config set --first-party on/off --json | cliFirstParty sent alone; shared-proxy-retained warning preserved. | src/cli/integrations.ts:78; src/cli/integrations.ts:121 | +| **ops-C04** — Save Code behavior/auth/env/model mappings/helpers; `gui/src/pages/ClaudeCode.tsx:217` | COMPLETE | claude config set --enabled --auth-mode --system-env --fast-mode --auto-context --compact-window --inject-agents --small-fast-model --model-map --web-model --web-backend --vision-model --vision-backend | All GUI fields supported. Restore helper inheritance with both --web-model - --web-backend - (vision analog); backend removes empty override. Use typed values shown by handler usage. | src/cli/integrations.ts:16; src/cli/integrations.ts:78; src/server/management/agent-settings-routes.ts:1642 | +| **ops-C05** — Start configured Claude intercept; `gui/src/components/ClaudeInterceptStart.tsx:18` | COMPLETE | claude intercept start --json | Exact configured-proxy start exists; no trust-install bypass. | src/cli/integrations.ts:372 | +| **ops-C06** — Read Desktop editable profile/catalog and applied health; `gui/src/pages/ClaudeDesktop.tsx:270`, `:354` | UNKNOWN | claude desktop status --json; claude desktop show --json | status is live, show builds local desired profile; connected GUI editor reads hub. Consider explicit runtime-scope profile read after main target design. | src/cli/claude-desktop.ts:742; src/cli/claude-desktop.ts:751; src/cli/claude-desktop.ts:790 | +| **ops-C07** — Edit Desktop assignment family/alias/default and save; `gui/src/pages/ClaudeDesktop.tsx:24`, `:418`, `:806`, `:826` | UNKNOWN | claude desktop move ROUTE FAMILY [--default]; default FAMILY ROUTE-or-none; import FILE | Local assignments/defaults/import exist; hub desired-profile target differs. Alias can be imported as profile JSON. Parent owns live-vs-local contract, no generic config workaround. | src/cli/claude-desktop.ts:806; src/cli/claude-desktop.ts:815; src/cli/claude-desktop.ts:833 | +| **ops-C08** — Save then apply Desktop first-party/gateway; `gui/src/pages/ClaudeDesktop.tsx:433` | COMPLETE | claude desktop apply --first-party; apply --gateway | Mode-aware apply exists and preserves applied-marker warning. import --apply is gateway-only; separate apply selects first-party. Local/client paths guarded. | src/cli/claude-desktop.ts:676; src/cli/claude-desktop.ts:393; src/cli/claude-desktop.ts:479 | +| **ops-C09** — Bind/unbind native picker ID to route; `gui/src/components/ClaudeFirstPartyBindings.tsx:59` | COMPLETE | claude desktop bind PICKER-ID ROUTE; unbind PICKER-ID | Exact set/remove live binding payloads exist. | src/cli/claude-desktop.ts:766 | +| **ops-C10** — Enable/disable Desktop picker proxy; `gui/src/components/ClaudeDesktopPicker.tsx:97` | COMPLETE | claude desktop picker status/on/off | GET/PUT and trust workflow exist. Preserve trusted-local and interactive requirements; no raw persist/trust bypass. | src/cli/claude-desktop.ts:554; src/cli/claude-desktop.ts:623; src/cli/claude-desktop.ts:746 | +| **ops-C11** — Export Desktop profile JSON; `gui/src/pages/ClaudeDesktop.tsx:468` | COMPLETE | claude desktop export PATH-or-dash | Artifact export exists. GUI can export unsaved draft; CLI has no GUI draft and exports persisted local profile. Draft-state visualization is not absent export capability. | src/cli/claude-desktop.ts:824; gui/src/pages/ClaudeDesktop.tsx:468 | +| **ops-C12** — Import Desktop profile JSON; `gui/src/pages/ClaudeDesktop.tsx:480` | UNKNOWN | claude desktop import FILE [--apply] | CLI local import immediately persists; GUI imports draft then saves selected runtime. Connected/hub target ambiguity remains C07; reuse parser rather than inventing second one. | src/cli/claude-desktop.ts:833; gui/src/pages/ClaudeDesktop.tsx:480 | +| **ops-G01** — Read Grok fence/catalog/status; `gui/src/pages/Grok.tsx:81` | DISCOVERY_ONLY | grok status/show --json | Same status implemented; incomplete route/leaf declaration in CLI inventory. | src/cli/integrations.ts:142 | +| **ops-G02** — Save included/excluded Grok model selection; `gui/src/pages/Grok.tsx:151` | DISCOVERY_ONLY | grok set/include/exclude CSV --json; grok clear --json | Excluded-list replacement/add/remove/clear supported; publish precise grammar. | src/cli/integrations.ts:160 | +| **ops-G03** — Save and apply Grok fence; `gui/src/pages/Grok.tsx:171` | DISCOVERY_ONLY | grok set CSV --json; then grok apply --json | Save then apply expressible; changed/skippedReason preserved in JSON. Register leaves; no duplicated writer. | src/cli/integrations.ts:153; src/cli/integrations.ts:174 | +| **ops-I01** — List native integration desired/observed state; `gui/src/pages/integrations/native-api.ts:144`; overview `IntegrationsOverview.tsx:605` | COMPLETE | integration native list --json | Same desired/observed four-client collection. | src/cli/inspect.ts:90 | +| **ops-I02** — Toggle native Grok / Codex / Claude Desktop; `gui/src/pages/integrations/native-api.ts:155`; overview `IntegrationsOverview.tsx:604` | COMPLETE | integration native grok/codex/claude-desktop on/off --json | All three mutations exist; backend disable refusal remains authoritative. | src/cli/inspect.ts:49; src/cli/inspect.ts:113 | +| **ops-I03** — List file-client state / inspect one; `gui/src/pages/integrations/integration-api.ts:435`, `:441` | DISCOVERY_ONLY | integration client status/list/show [--client ID] --json | Collection and one-client reads exist. Capability focuses Aside; declare ordinary client routes too. | src/cli/integrations.ts:232; src/cli/integrations.ts:49 | +| **ops-I04** — Preview apply / overwrite / disable; `gui/src/pages/integrations/FileIntegrationPage.tsx:219`; `integration-api.ts:475` | EXCLUDED | Existing apply/disable at I05 | Interactive-preview exemption intentional. Optional future integration client preview --client ID --operation apply/overwrite/disable requires parent policy change and bound follow-up mutation. | src/server/management/route-registry.ts:232; src/cli/integrations.ts:299 | +| **ops-I05** — Apply / overwrite conflicting config / disable owned block; `gui/src/pages/integrations/FileIntegrationPage.tsx:251`; `integration-api.ts:512` | DISCOVERY_ONLY | integration client enable/disable --client ID [--overwrite-conflict] --json | Effects exist; no planFingerprint under current interactive-preview exemption. Preserve explicit overwrite waiver. Droid map is separate I06 gap. | src/cli/integrations.ts:299; src/cli/integrations.ts:319 | +| **ops-I06** — Set/clear per-model Droid reasoning defaults; `gui/src/pages/integrations/DroidReasoningDefaultsPanel.tsx:27`, `:38` | IMPLEMENTATION_GAP | integration client enable --client droid | No droidReasoningDefaults input. Recommend repeatable --reasoning-default MODEL=EFFORT and explicit --clear-reasoning-defaults; if preview adopted, same map must bind apply. | src/cli/integrations.ts:299; gui/src/pages/integrations/integration-api.ts:483; gui/src/pages/integrations/integration-api.ts:520 | +| **ops-I07** — Read rollback journal; `gui/src/pages/integrations/integration-api.ts:454` | DISCOVERY_ONLY | integration client history/journal [--client ID] --json | Journal read exists; publish non-Aside route/leaf and retain snapshot-expired status. | src/cli/integrations.ts:258 | +| **ops-I08** — Preview rollback, including drift-confirmed retry; `gui/src/pages/integrations/RestoreDialog.tsx:143`; `integration-api.ts:496` | EXCLUDED | integration client restore --op ID [--confirm-drift] | Preview intentionally exempt. Optional restore --op ID --preview needs explicit bound confirmation policy, not new generic POST access. | src/server/management/route-registry.ts:233; src/cli/integrations.ts:278 | +| **ops-I09** — Restore rollback snapshot; `gui/src/pages/integrations/RestoreDialog.tsx:191`; `integration-api.ts:543` | DISCOVERY_ONLY | integration client restore --op ID [--confirm-drift] --json | Restore and drift waiver implemented. Fingerprint not current scripted contract; don't label entire rollback missing. | src/cli/integrations.ts:278 | +| **ops-I10** — Retire older rollback entry/snapshot; `gui/src/pages/integrations/FileIntegrationPage.tsx:446`; overview `IntegrationsOverview.tsx:851`; `integration-api.ts:571` | IMPLEMENTATION_GAP | history and restore only | No journal DELETE task. Recommend integration client history remove --op ID --yes --json; preserve newest-row refusal and snapshotRemoved:false receipt. | src/cli/integrations.ts:258; src/cli/integrations.ts:299; src/server/management/route-registry.ts:230 | +| **ops-I11** — Disable all eligible file integrations; `gui/src/pages/integrations/IntegrationsOverview.tsx:443`, `:460`, `:512` | COMPLETE | Repeat integration client disable --client ID for explicit set | Existing sequential commands can disable the explicitly selected eligible set; this is a real write workflow, not presentation. GUI confirmation previews remain exempt. No atomic bulk endpoint; do not silently introduce wildcard/default-all scope. | gui/src/pages/integrations/IntegrationsOverview.tsx:443; gui/src/pages/integrations/IntegrationsOverview.tsx:512 | +| **ops-I12** — List Aside profiles / read one / toggle selected profile; `gui/src/pages/integrations/AsideProfilesPage.tsx:54`, `:89`, `:116`; `integration-api.ts:424` | COMPLETE | integration client status/enable/disable --client aside --profile N --json | Canonical per-profile selection exists; omitted profile intentionally aggregate. Preview remains I04 exemption. | src/cli/integrations.ts:40; src/cli/integrations.ts:49; src/cli/integrations.ts:230 | +| **ops-I13** — Aside profile rollback list/preview/restore/retire; `gui/src/pages/integrations/integration-api.ts:465`, `:503`, `:550`, `:585` | IMPLEMENTATION_GAP | history --client aside --profile N; restore --client aside --profile N --op ID [--confirm-drift] | Only retirement absent; preview exempt. Recommend history remove --client aside --profile N --op ID --yes --json with profile-response binding. | src/cli/integrations.ts:258; src/cli/integrations.ts:278; src/server/management/route-registry.ts:191 | +| **ops-I14** — Refresh all server-selected Aside profiles; `gui/src/pages/integrations/aside-profile-api.ts:38` | UNKNOWN | sync reaches refreshAsideProfilesThroughServer | Refresh effect exists, but broad sync also synchronizes catalogs/other clients. Parent decide if broader scope is acceptable or add integration client sync --client aside reusing helper. | src/cli/aside-profiles.ts:9; src/cli/aside-profiles.ts:69; src/cli/dispatch.ts:526 | +| **ops-I15** — Inspect Cursor installed builds/gateway/last-seen state; `gui/src/pages/integrations/CursorIntegrationPage.tsx:113`; `cursor-api.ts:34` | IMPLEMENTATION_GAP | integration native list/on/off; Cursor advertised only | Actual allowlist has no Cursor. Recommend integration native cursor status --json; read-only build/gateway/last-seen status. | src/cli/inspect.ts:49; src/cli/inspect.ts:99; src/cli/capabilities.ts:1015 | +| **ops-I16** — Check advertised Cursor local installer; `gui/src/pages/integrations/CursorIntegrationPage.tsx:81`; `cursor-api.ts:59` | IMPLEMENTATION_GAP | No Cursor installer-read command | Recommend integration native cursor local-installer --json. Explicit update-channel query only; URL/version output never triggers install. | src/cli/inspect.ts:85; gui/src/pages/integrations/cursor-api.ts:59; src/server/management/cursor-integration-routes.ts:152 | +| **ops-O01** — Read debug flags/env/runtime overrides; `gui/src/pages/Debug.tsx:48` | DISCOVERY_ONLY | observe debug --json; debug SCOPE status | Flags/env/overrides readable; publish scope grammar. | src/cli/observe.ts:281; src/cli/debug.ts:144 | +| **ops-O02** — Toggle provider/usage/injection/Claude inbound capture; `gui/src/pages/Debug.tsx:180`, `:210` | DISCOVERY_ONLY | debug provider/usage/injection/claude on/off | All four toggles supported. Legacy JSON mutation output absence is shared machine-output work, not missing action. | src/cli/debug.ts:144; src/cli/debug.ts:150 | +| **ops-O03** — Reset all capture overrides to env; `gui/src/pages/Debug.tsx:213` | COMPLETE | debug provider reset; debug usage reset; debug injection reset; debug claude reset | Four commands reach same final reset state; GUI atomic reset:true has no one-shot alias. Atomic reset-all optional unless parent contract requires it. | src/cli/debug.ts:163; gui/src/pages/Debug.tsx:213 | +| **ops-O04** — Read/follow provider, usage, injection debug buffers; `gui/src/pages/Debug.tsx:97`, `:115` | IMPLEMENTATION_GAP | debug provider logs -f; debug usage logs -f; observe injection --json | Injection snapshot exists, continuous follow/after cursor does not. debug injection logs refuses. Recommend observe injection --follow --jsonl with bounded cursor polling. | src/cli/debug.ts:171; src/cli/observe.ts:283; gui/src/pages/Debug.tsx:115; gui/src/pages/Debug.tsx:168 | +| **ops-O05** — Read Claude inbound metadata captures; `gui/src/pages/Debug.tsx:65` | DISCOVERY_ONLY | observe claude-inbound --json | Complete metadata snapshot read. Expose leaf with honest limit semantics. | src/cli/observe.ts:282 | +| **ops-O06** — Read/retry/incrementally poll request log; `gui/src/pages/Logs.tsx:614` | COMPLETE | logs --limit 2000 --json; logs --follow --jsonl | Read/follow exists. GUI cursor amendments differ from CLI new-ID dedupe; an in-flight-to-terminal fixture is needed before claiming identical update visibility. No new API necessary. | src/cli/observe.ts:79; src/cli/observe.ts:100; gui/src/pages/Logs.tsx:614 | +| **ops-O07** — Filter log snapshot by surface/model/provider/status/time/speed/interception/conversation/protocol; `gui/src/pages/Logs.tsx:728`; `gui/src/pages/logs-filter.ts:16`, `:103` | EXCLUDED | logs has provider/model/status/conversation/account filters | GUI local speed/intercept/protocol/time/view projections are presentation, not missing management mutations. More CLI read filters optional product choice. | gui/src/pages/Logs.tsx:728; gui/src/pages/logs-filter.ts:16; src/cli/observe.ts:85 | +| **ops-O08** — Read usage by preset/custom window, surface and local-machine attribution; `gui/src/pages/Usage.tsx:1110` | UNKNOWN | usage --range --surface --since --until --provider --model --json | Custom bounds exist. Connected CLI uses own-key Hub report; GUI chooses machine vs whole-Hub via apiKeyId. Need target/principal join before proposing --scope machine/hub; don't infer missing from absent apiKeyId flag alone. | src/cli/observe.ts:164; src/cli/observe.ts:188; gui/src/pages/Usage.tsx:1110 | +| **ops-O09** — Model text search, expand rows, tab and chart display; `gui/src/pages/Usage.tsx:1093`; chart components | EXCLUDED | No CLI task needed | Local search, expansion, tabs/graph styling. Server bounds remain O08. | gui/src/pages/Usage.tsx:1093 | +| **ops-O10** — Read companion preferences/presence; `gui/src/pages/usage-companion-panel.tsx:215`; Tray `gui/src/pages/Tray.tsx:100` | COMPLETE | companion show --json | Settings/defaults/presence/corrupt payload available. | src/cli/companion.ts:13 | +| **ops-O11** — Persist companion model/provider visibility and chart/menu appearance; `gui/src/pages/usage-companion-panel.tsx:302`, `:503` | COMPLETE | companion set KEY=VALUE ... --json | Domain settings map covers all GUI fields including JSON arrays, models=null and booleans. This is not generic API passthrough. | src/cli/companion.ts:20; gui/src/pages/usage-companion-utils.ts:9 | +| **ops-O12** — Restore companion defaults (including corrupt-state recovery); `gui/src/pages/usage-companion-panel.tsx:350` | COMPLETE | companion reset --json | Same reset:true and corrupt-settings recovery. | src/cli/companion.ts:36 | +| **ops-O13** — Read usage timeline for companion/chart/tray; `gui/src/pages/usage-companion-panel.tsx:257`; `gui/src/pages/Tray.tsx:118` | IMPLEMENTATION_GAP | companion show/set/reset only | Recommend companion timeline --hours N --bucket-minutes N --metric total/input/output/cached --aggregation sum/average/max --grouping model/modelAccount [--model ID repeated] [--hide-provider ID repeated] --json. Preserve truncated/missingMeasurements. | src/cli/companion.ts:46; gui/src/pages/usage-companion-utils.ts:52; src/server/management/usage-timeline-routes.ts:11 | +| **ops-O14** — Open companion view in system browser; `gui/src/pages/usage-companion-panel.tsx:367` | EXCLUDED | No standalone operator equivalent required | Browser navigation is declared session-only. No forged dashboard principal/open-url passthrough. | src/server/management/route-registry.ts:268; src/server/management/companion-routes.ts:30 | +| **ops-O15** — Tray refresh totals/accounts/quota; `gui/src/pages/Tray.tsx:79`, `:86`, `:104`; `gui/src/pages/tray-data.ts:27` | UNKNOWN | usage/companion show plus account read families | Sibling certifies account/quota fields; Tray display alone is excluded. | gui/src/pages/Tray.tsx:79; gui/src/pages/tray-data.ts:27 | +| **ops-O16** — Tray switch current account/key; `gui/src/pages/Tray.tsx:39`; `gui/src/pages/tray-data.ts:36` | UNKNOWN | Account selection families in inventory-cli.md | Sibling owns exact Codex/OAuth/provider-key switch join. Prefer account command, not Tray-specific verb. | gui/src/pages/Tray.tsx:39; gui/src/pages/tray-data.ts:36 | +| **ops-T01** — Inspect storage sizes/categories/Log Guard state; `gui/src/pages/Storage.tsx:1358` | COMPLETE | storage report --json | Same live storage/log-guard scan payload. | src/cli/storage.ts:233; src/server/management/storage-log-guard-routes.ts:216 | +| **ops-T02** — Preview oldest archived-session cleanup percentage; `gui/src/pages/Storage.tsx:177` | COMPLETE | storage cleanup --percent N --json | Default preview emits digest/candidates; registry mutates declaration doesn't change handler's preview semantics. | src/cli/storage.ts:73; src/cli/storage.ts:88 | +| **ops-T03** — Quarantine / permanently delete previewed archives; `gui/src/pages/Storage.tsx:201` | COMPLETE | storage cleanup --percent N --mode quarantine/permanent --yes --json | Fresh preview then exact returned digest. Standalone prior preview is recomputed, not reused; immutable preview receipt UX is optional, guard preserved. | src/cli/storage.ts:88; src/cli/storage.ts:105 | +| **ops-T04** — List quarantine batches; `gui/src/pages/Storage.tsx:392` | COMPLETE | storage trash list --json | Full quarantine batch list. | src/cli/storage.ts:117 | +| **ops-T05** — Restore a quarantine batch; `gui/src/pages/Storage.tsx:431` | COMPLETE | storage trash restore ENTRY-ID --yes --json | ID mutation with explicit confirmation exists; partial outcomes preserved in JSON/error. | src/cli/storage.ts:126; src/cli/storage.ts:141 | +| **ops-T06** — Read policy/job; `gui/src/pages/Storage.tsx:672`, `:865` | COMPLETE | storage policy show --json | Policy/job state available. | src/cli/storage.ts:153 | +| **ops-T07** — Enable/disable recurring cleanup / save threshold, target, schedule, mode; `gui/src/pages/Storage.tsx:709`, `:738` | IMPLEMENTATION_GAP | storage policy set --enabled --percent --mode --schedule --json | Missing trigger.archivedBytesOver and target.reduceToBytes. Recommend --archived-bytes-over BYTES plus exclusive --reduce-to-bytes BYTES / --remove-oldest-percent N, retaining --percent alias if chosen. Never implicitly enable. | src/cli/storage.ts:162; gui/src/pages/Storage.tsx:709 | +| **ops-T08** — Run cleanup policy now; `gui/src/pages/Storage.tsx:790`, `:809` | COMPLETE | storage policy set EXISTING-FIELDS; policy run --yes --json; policy show --json | Run + poll expressible; disabled stays disabled. T07 separately limits draft fields. Optional --wait must preserve skipped/deferred/failed terminal outcomes. | src/cli/storage.ts:207; src/cli/storage.ts:214; src/cli/storage.ts:153 | +| **ops-T09** — Inspect log protection fresh; `gui/src/components/storage-workspace/StorageWorkspace.tsx:515` | COMPLETE | storage codex-logs status --json; observe storage codex-logs status --json | Existing alias dispatch reaches actual read. | src/cli/storage.ts:223; src/cli/observe.ts:245 | +| **ops-T10** — Protect logs compat / quiet; `gui/src/components/storage-workspace/StorageWorkspace.tsx:251`, `:261`, `:460` | COMPLETE | storage codex-logs protect --mode compat/quiet --json | Exact protection payload. | src/cli/observe.ts:248 | +| **ops-T11** — Remove log protection / repair protection / compact logs; `gui/src/components/storage-workspace/StorageWorkspace.tsx:440`, `:463` | COMPLETE | storage codex-logs unprotect/repair/compact --json | Dynamic suffix dispatch reaches all three; no missing literal-route gap. | src/cli/observe.ts:258 | +| **ops-K01** — List access keys/usage/pending rotations, endpoints, auth matrix, API/audio surfaces; `gui/src/pages/ApiKeys.tsx:155` | COMPLETE | access key list --json; access endpoints --json | Full list JSON includes auth/audio/usage/pending rotation; endpoint-only helper projects fewer fields. Discover existing complete payload, don't add duplicate read. | src/cli/access.ts:136; src/cli/access.ts:241 | +| **ops-K02** — Create key with name; `gui/src/pages/ApiKeys.tsx:268` | COMPLETE | access key create NAME --json | Secret returned once. Preserve operating-skill restriction on agent receipt of raw keys; no credentials generated here. | src/cli/access.ts:143 | +| **ops-K03** — Rename key; `gui/src/pages/ApiKeys.tsx:327` | IMPLEMENTATION_GAP | access key set edits scopes only | Recommend access key rename ID-or-NAME NEW-NAME --json; reuse unambiguous findKeyRow, PATCH only {id,name}, leave scope unchanged. | src/cli/access.ts:168; src/cli/access.ts:109; gui/src/pages/ApiKeys.tsx:327 | +| **ops-K04** — Revoke key; `gui/src/pages/ApiKeys.tsx:302` | COMPLETE | access key remove ID --yes --json | Explicit ID revocation and confirmation exist. | src/cli/access.ts:224 | +| **ops-K05** — Start rotation; `gui/src/pages/ApiKeys.tsx:349` | COMPLETE | access key rotate ID --json | Start returns key and rotationId. Actual grammar is rotate ID, not rotate start ID. | src/cli/access.ts:197 | +| **ops-K06** — Commit rotation / abort rotation; `gui/src/pages/ApiKeys.tsx:371` | COMPLETE | access key rotate commit ID ROTATION-ID --json; rotate abort ID ROTATION-ID --json | Both methods and fields supported. | src/cli/access.ts:198; src/cli/access.ts:217 | +| **ops-K07** — Read public external-model catalog; `gui/src/pages/ApiKeys.tsx:192` | DISCOVERY_ONLY | access models --json | Public /v1/models read exists, distinct from management models live; publish leaf. | src/cli/access.ts:246; src/cli/access.ts:279 | +| **ops-K08** — Test newly created key on Responses / Chat / Messages for selected model; `gui/src/pages/ApiKeys.tsx:443`, `:456` | IMPLEMENTATION_GAP | access test MODEL --protocol responses/chat/messages --json | Existing inference test has no selected-key input and uses management headers; cannot prove newly created key works. Recommend --api-key-stdin with no secret echo/argv/env and explicit inference authorization. Ping text/token limit differences alone not the gap. | src/cli/access.ts:255; src/cli/runtime-api.ts:142; gui/src/pages/ApiKeys.tsx:456 | +| **ops-K09** — Read generated client configuration / copy snippet; `gui/src/components/apikeys-workspace/ClientConfigRow.tsx:53` | COMPLETE | inspect client-config --client ID --json | Same generated config envelope. Export artifact and integration apply remain separate tasks. | src/cli/inspect.ts:157 | +| **ops-K10** — Toggle public Messages API; `gui/src/pages/api-surface-cards.tsx:52` | COMPLETE | api policy --messages on/off --json | Exact messagesEnabled field; backend also updates legacy Claude inbound on closing. | src/cli/api-protocols.ts:152; src/server/management/protocol-settings-patch.ts:132 | +| **ops-K11** — Preview model's protocol path/features; `gui/src/components/protocols/ProtocolPlanPanel.tsx` → `gui/src/protocol-api.ts:91` | COMPLETE | api explain --model ID --inbound responses/chat/messages --feature FEATURE [repeated] --json | Same preview/features/policy revision. Never call preview a successful live model probe. | src/cli/api-protocols.ts:130 | +| **ops-K12** — Dictation file upload and cancel; `gui/src/components/apikeys-workspace/AudioApiPanel.tsx:2`; `gui/src/audio-api-client.ts:13` | UNKNOWN | No scoped audio CLI identified in supplied CLI inventory | Real data-plane upload, parent inclusion decision. If included: access audio transcribe FILE --model ID --api-key-stdin --json, bounded upload/cancel. Do not silently create new audio product. | gui/src/audio-api-client.ts:13; src/server/index/serve-options.ts:1594 | +| **ops-K13** — Live voice connect/disconnect probe; `gui/src/audio-api-client.ts:88` | UNKNOWN | No scoped live-audio probe identified in supplied CLI inventory | Parent inclusion decision. If included: access audio live-check --model ID --api-key-stdin --json with timeout/session.close; connection-only, no microphone/delegation execution claim. | gui/src/audio-api-client.ts:88; src/server/live.ts:348 | +| **ops-K14** — Download generated client configuration; `gui/src/components/apikeys-workspace/ClientConfigPanel.tsx:78` | COMPLETE | export --client ID --out PATH [--force] [--json] | Existing artifact task, explicit destination/non-clobber default. Native format default; --json requests JSON representation, not apply. | src/cli/export-command.ts:158; gui/src/components/apikeys-workspace/ClientConfigPanel.tsx:78 | +| **ops-R01** — Hub devices/runtime availability/session status; `gui/src/pages/RemoteWorkspace.tsx:93` | IMPLEMENTATION_GAP | remote-workspace status is executor-local | Recommend remote-workspace hub status --json aggregating devices/runtimes/sessions via runtime management auth/target, not executor file store. | src/cli/remote-workspace.ts:80; src/server/management/route-registry.ts:397; src/server/management/remote-workspace-routes.ts:61 | +| **ops-R02** — Create device enrollment code; `gui/src/pages/RemoteWorkspace.tsx:172` | EXCLUDED | remote-workspace pair consumes enrollment code | Grant creation is paired-dashboard consent; no --yes CLI minting/session impersonation. Preserve create-vs-consume roles. | src/server/management/route-registry.ts:400; src/server/management/remote-workspace-routes.ts:12 | +| **ops-R03** — Start hub model session on selected remote root; `gui/src/pages/RemoteWorkspace.tsx:184` | EXCLUDED | No CLI proposed | Hub-authenticated model session start and access mode remain dashboard consent. | src/server/management/route-registry.ts:401 | +| **ops-R04** — Submit prompt to bound session; `gui/src/pages/RemoteWorkspace.tsx:208` | EXCLUDED | No CLI proposed | Prompt may execute remote tools; do not use task parity to bypass session principal. | src/server/management/route-registry.ts:402 | +| **ops-R05** — Stop session; `gui/src/pages/RemoteWorkspace.tsx:243` | EXCLUDED | No CLI proposed | Interactive remote session stop remains paired-session action. | src/server/management/route-registry.ts:404 | +| **ops-R06** — Revoke device and stop its sessions; `gui/src/pages/RemoteWorkspace.tsx:256` | EXCLUDED | No CLI proposed | Device identity revocation and related session stops remain paired-session actions. | src/server/management/route-registry.ts:403 | +| **ops-R07** — Read individual Hub runtimes/sessions endpoints | IMPLEMENTATION_GAP | No Hub runtime/session list command | Recommend remote-workspace hub runtimes --json and hub sessions --json. Declared debt; GUI currently reads both through aggregate R01 rather than distinct buttons. | src/server/management/route-registry.ts:398; src/server/management/route-registry.ts:399 | +| **ops-L01** — Read link topology/status; `gui/src/pages/RemoteLink.tsx:186` | COMPLETE | link status --json | Admin topology DTO intentionally omits dashboard joinAvailable; do not forge consent field to match presentation. | src/cli/link.ts:256; src/server/management/link-routes.ts:580 | +| **ops-L02** — Discover/rescan SSH aliases; `gui/src/pages/RemoteLink.tsx:262` | EXCLUDED | No CLI proposed | SSH candidates discovery remains dashboard-session-only contract. | src/server/management/route-registry.ts:389 | +| **ops-L03** — Probe host key; `gui/src/pages/RemoteLink.tsx:282` | EXCLUDED | No CLI proposed | Host-key probe is interactive fingerprint-consent flow. | src/server/management/route-registry.ts:390 | +| **ops-L04** — Accept shown fingerprint and validate remote OCX; `gui/src/pages/RemoteLink.tsx:298` | EXCLUDED | No CLI proposed | Persisting fingerprint requires observed pending key and consent; never auto-confirm from metadata. | src/server/management/route-registry.ts:391 | +| **ops-L05** — Home adds child; `gui/src/pages/RemoteLink.tsx:313` | EXCLUDED | link issue is existing lower-level admin primitive | Not equivalent to Home-adds-Child transaction; retain session-only boundary rather than generic wrapper. | src/server/management/route-registry.ts:393; src/cli/link.ts:234 | +| **ops-L06** — Standalone child joins Home and restarts; `gui/src/pages/RemoteLink.tsx:333` | EXCLUDED | No CLI proposed | Child join/restart consent contract unchanged; issue/port primitives alone not workflow parity. | src/server/management/route-registry.ts:392 | +| **ops-L07** — Disconnect link / force-remove after remote cleanup failure; `gui/src/pages/RemoteLink.tsx:371`, `:422` | IMPLEMENTATION_GAP | link revoke --link-id ID --json | Normal revoke exists; parser rejects --force and sends no body. Recommend --force --yes for explicit forced local removal with residual remote-cleanup warning, normal defaults unchanged. | src/cli/link.ts:260; src/server/management/link-routes.ts:510; gui/src/pages/RemoteLink.tsx:371 | + +## Declared debt and intentional exclusions + +- Journal retirement: registry `src/server/management/route-registry.ts:230`, `:188`, `:191`; owner `260904_priority65_closeout WP7`, tracked source `devlog/_fin/260904_priority65_closeout/060_wp7_rollback_journal_crud.md`. Global/profile mutations are GUI reachable; aggregate Aside DELETE is declared but current helper does not use that aggregate spelling. +- Remote Workspace Hub reads: registry `src/server/management/route-registry.ts:397`, `:398`, `:399`; owner `remote-workspace-cli-followup`, tracked source `docs-site/src/content/docs/reference/management-api.md:214`. Existing executor-local status is not a replacement. +- Interactive plans: registry `src/server/management/route-registry.ts:232`, `:233`, `:190`. Excluded under current declared contract, although useful plan-first CLI workflows are a product option. Do not omit planFingerprint if adopting bound confirmation; stale plans require renewed confirmation. +- Link GUI admissions and Remote Workspace writes retain registry session-only classifications. GitHub star POST must never gain an agent action (`src/server/management/route-registry.ts:380`); current inspect star is read-only (`src/cli/inspect.ts:192`). +- App session logout (`src/server/management/route-registry.ts:372`), desktop update snapshot (`:376`), companion browser navigation (`:268`), old Aside aliases (`:180`, `:181`), disabled config PUT (`:223`) and storage test streams (`:261`, `:263`) do not create new operational CLI debt. + +## Proof to request during implementation + +No code or tests were executed in this pass. Use isolated HTTP fixtures with RuntimeApiDeps (`src/cli/runtime-api.ts:136`) and controlled homes; shared auth helpers otherwise read normal user state. Assert parser → exact method/path/body/query → projection/exit status; no live proxy or real keys needed. + +1. Timeline/Cursor/Hub reads: route/flag encoding, read-only behavior, malformed response and meaningful empty state. Validate actual handler dispatch, not only capabilities route membership. +2. Rename: PATCH exactly id/name, preserve provider/model scopes, reject ambiguous selector without write. Sidecar additions: partial patch retains siblings, booleans and timeout bounds preserved. +3. Cleanup fields: mutually exclusive target forms and trigger threshold; absent enabled preserved. Droid defaults: same submitted map reaches chosen client/profile and any plan binding. +4. Journal retire: global and Aside-profile route, newest-row 409, missing-row 404, snapshotRemoved:false visible. Link force: explicit confirmation, only requested force:true body, residual remote cleanup stays visible. +5. Key test: fake sentinel secret from controlled stdin, dedicated data header only, no management token injection, no secret in stdout/stderr/errors. Prove selected-key rejection cannot pass via loopback bypass. +6. Follow injection: after cursor advances, empty poll/no duplicates, interruption, malformed/error response. Log row amendment visibility is separately unresolved in O06. +7. Target-dependent UNKNOWNs: verify Desktop local versus Hub profile, connected usage own-key versus Hub scope, machine sync selected-client projection, and narrow Aside-only refresh before promoting to COMPLETE or a gap. + +Parent boundary: command spelling/flags above are proposals. Main owns final convention, receipt/error/exit design, authorization policy and roadmap sequencing. Audio probe inclusion and sibling account/subagent joins remain explicitly UNKNOWN. No generic API passthrough or generic config editing is counted as parity. + + +Static artifact receipt: 109 unique ops task rows; all 344 explicit source file/line anchors resolve; every operations-inventory ID has exactly one join row; Markdown column counts checked. Status totals: UNKNOWN=12, DISCOVERY_ONLY=23, COMPLETE=43, EXCLUDED=16, IMPLEMENTATION_GAP=15. No application execution or runtime success inferred. diff --git a/devlog/_plan/261003_cli_gui_parity/006_target_contracts.md b/devlog/_plan/261003_cli_gui_parity/006_target_contracts.md new file mode 100644 index 00000000000..e57512092ff --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/006_target_contracts.md @@ -0,0 +1,219 @@ +# wp0 target crux: local versus live settings workflows + +2026-10-03, source-only bounded decision record. Resolves set-M06/M13/S04, provider P02/P05 and logout P10 for roadmap selection. No tracked files, prior artifacts, user config, credentials, proxy, upstream or tests were changed/run. Source establishes the transport/side-effect differences sufficiently to choose implementation; it does not establish runtime parity. Existing isolated tests were inspected, not executed. + +## Concrete roadmap choice + +**Retain existing roots and local behavior. Add an explicit `--live` option to the existing commands for exact management-target GUI behavior, with structured receipts. Do not auto-fallback between local and live; do not create `agent mode` or a generic API passthrough.** The only new API surface work needed by these cruxes is CLI transport/options, not new server routes. `--json` selects output, never target. + +| Tasks | Accepted implementation choice for roadmap | Smallest before → after | +|---|---|---| +| set-M06 | Existing `models add/remove` gain `--live --json`; keep existing local add/remove default and existing live `models edit`. Add proper local JSON save/sync disposition as output enhancement. | Before: add/remove modify local config and optionally perform broad Codex sync, emit prose; edit is live. After: explicit live add/remove use the same server custom-model handlers as GUI, return its identity and catalog receipt; local remains available and is labeled local. | +| set-M13 | Reuse `v2 status`, `mode`, `keep-native-v1`, `threads`, plus existing on/off. Add `--live --json` and explicit advisory acknowledgment for live mode changes. Keep current local implementation and add strict JSON output/argument parsing. | Before: local files/Codex helpers, mode/keep sync, prose, no advisory-version write; trailing flags are not systematically rejected. After: live option operates on the selected management target and returns server post-write state/advisory/catalogRefresh; no-live remains existing local functionality. | +| set-S04 | Reuse `v2 mode-hint TEXT` and `v2 mode-hint --clear`; route through the same narrow v2 live option when requested. Local set/null writer already exists and needs only machine output/discovery. | Before: shared local hint helper already implements set/null and rejects blanks. After: no duplicate hint implementation; optional live path receives the target runtime's capability/refusal and receipt. | +| set-P02 | Existing `provider add` gains explicit live path; preserve offline default. Add missing typed fields (responses path/auth mode) to the same domain parser. | Before: local seed/save, `--json` bypasses `--sync`; target runtime not the mutation owner. After: live preset read/POST provider and receipt belong to one resolved server; local `--sync --json` actually executes the requested sync and reports disposition. | +| set-P05 | Existing `provider remove` and `provider set-default` gain `--live`. Existing `provider edit --enabled` already uses management and does not need a second endpoint. | Before: local remove refuses current default and only deletes local provider/custom-model config; live GUI can reassign default and removes OAuth account set/caps. After: explicit live operations use exactly those server validations and effects, with destructive confirmation for removal. | +| set-P10 logout | Existing top-level `logout P` gains `--live --json`; keep local logout default and its current removed/not-found semantics. | Before: shared auth-store removal occurs locally, but live caches/login state aren't cleared by this CLI branch. After: explicit live logout invokes `/api/oauth/logout?provider=P` and returns its actual success receipt; no unproved `removed:true` claim. | + +“Accepted” here is the explorer's concrete recommended lock for the parent's roadmap, not a claim that implementation or user-state mutation has occurred. Main retains naming/final phase authority. This choice is intentionally narrower than changing all existing command defaults. + +## Why machine-output enhancement alone is insufficient for live GUI parity + +### Shared persistence is not a shared target or completion receipt + +- `saveConfig` writes local config under a mutation lock and bumps a generation; its body is persistence, not a management request: `src/config.ts:370`. +- Server handlers mutate their retained live `config`, use preserving/rebase-aware persistence (`src/config/live-reconcile.ts:443`), and perform explicit live-store/cache/convergence work. Their GET config returns that retained config: `src/server/management/config-routes.ts:306`. +- `runtimeBaseUrl` selects the identity-checked live proxy or rejects absent/client-role management; it does not promise the dashboard's remote-relay target: `src/cli/runtime-api.ts:70`. Therefore `--live` means **the existing CLI management target**, not arbitrary GUI apiBase/remote equivalence. No new raw `--url` capability is proposed. +- Resolve base URL **once per multi-request workflow**, then pass a pinned `RuntimeApiDeps.baseUrl` to every request. Otherwise list/resolve/delete can re-resolve the listener between calls (`src/cli/runtime-api.ts:136`). This is a per-command target fix, not a new transport framework. +- Do not invoke the local handler before deciding `--live`; a refused or unreachable live request must never have already saved local config. Do not fall back after a transport error, timeout, 409 or partial receipt. + +### set-M06: custom model CRUD + +Local add writes `config.customModels`, calls `saveConfig`, then `syncCustomModelsIfLive`: `src/cli/models.ts:197`, `src/cli/models.ts:250`. Local remove follows the same save/sync family: `src/cli/models.ts:280`, `src/cli/models.ts:331`. The sync helper catches failures and emits warning text rather than returning a durable save/catalog receipt (`src/cli/models.ts:185`). + +`syncModelsToCodex(port, config=loadConfig())` checks local desired integration/service-home authority; depending on path it can refresh catalog/cache **and inject config** (`src/codex/sync.ts:99`, `src/codex/sync.ts:209`, `src/codex/sync.ts:293`). It is not equivalent to the GUI handler's catalog-only convergence. + +Live POST builds the same core `OcxCustomModel` fields, validates provider/collisions and mutates retained live config, then returns 201 `{...entry,catalogRefresh}` (`src/server/management/model-routes.ts:961`, `src/server/management/model-routes.ts:1001`). Live DELETE accepts UUID, updates live config, and returns `{ok:true,catalogRefresh}` (`src/server/management/model-routes.ts:1079`). Management convergence is bound to retained config and catalog-only scope (`src/server/management-api.ts:255`, `src/codex/management-convergence.ts:144`). + +**Resolved:** CRUD effects already exist, but a new live option is needed to claim the same target/management receipt. JSON-only changes cannot supply that. Existing local source remains a supported offline workflow. + +Exact live grammar: + +- `ocx models add P M [existing metadata flags] --live --json` → POST `/api/custom-models` with provider/modelId and provided displayName/contextWindow/inputModalities/reasoningEfforts/defaultReasoningEffort. No local `loadConfig()` preflight; target server validates provider. +- `ocx models remove UUID --yes --live --json` → DELETE `/api/custom-models/UUID`. +- Retain `P/M` removal convenience by GET `/api/custom-models` on the **same pinned target**, resolve exact-or-refuse using existing collision/slug rules, then DELETE UUID. Never resolve from local `customModels` before live deletion. +- Preserve empty reasoning `[]` versus inherit omission/null. Existing live edit parser already handles clear variants (`src/cli/models-runtime.ts:195`). + +### set-M13 / set-S04: reuse v2 + +Existing implementations are substantive, not aliases: `src/cli/v2.ts:109` status, `:144` hint set/clear, `:177` thread transition, `:191` mode save/sync, `:220` keep-native save/sync. Dispatch wires the root directly (`src/cli/dispatch.ts:539`). + +Server and local paths use the same `transitionMultiAgentV2` and `setMultiAgentModeHintText` helpers (`src/server/management/agent-settings-routes.ts:391`, `:415`, `:464`). Source establishes **local scalar/transition equivalence**, including blank hint rejection and null clear. It does not establish equivalence of surrounding target and convergence behavior: CLI sync is broad and local, while server returns post-write readings plus `catalogRefresh` (`src/server/management/agent-settings-routes.ts:484`). Local hint and threads paths do not issue management requests. + +Advisory semantics are now resolved: the GUI modal records explicit choice (`gui/src/pages/Models.tsx:2026`); the server validates acknowledgment is boolean and only true writes the advisory version **after** mode has landed (`src/server/management/agent-settings-routes.ts:372`, `:444`). There is no session-only principal gate or mandatory pre-write acknowledgment in `/api/v2`. Do not invent such a security guard. Do not auto-acknowledge just because a script requests a mode. + +Exact live grammar/mapping: + +| Existing root + proposed option | Exact live operation | +|---|---| +| `v2 status --live --json` | GET `/api/v2` | +| `v2 mode v1|default|v2 --live [--acknowledge-surface-advisory] --json` | PUT `{multiAgentMode, multiAgentSurfaceAdvisoryAcknowledged?:true}`; omission preserves unacknowledged state; default remains string `default`, not null. | +| `v2 keep-native-v1 on|off --live --json` | PUT `{keepNativeChatGptOnV1:boolean}` | +| `v2 threads N --live --json` | PUT `{maxConcurrentThreadsPerSession:N}`, integer >=1 | +| `v2 mode-hint TEXT --live --json` | PUT `{multiAgentModeHintText:TEXT}`; nonblank raw text retained. | +| `v2 mode-hint --clear --live --json` | PUT `{multiAgentModeHintText:null}` | +| `v2 on|off --live --json` | PUT `{enabled:boolean}`; retain server hybrid conflict refusal. | + +Use the same strict parser for local/live flags. `--json` must be consumed and unknown/trailing args rejected before local writers run; it must not be silently ignored. Local JSON must report `transport:local`, actual helper changed/no-op state and sync outcome without manufacturing server advisory or catalog receipts. Live JSON should preserve server returned state/warnings/catalogRefresh. If catalog refresh fails after persistence, do not claim rollback. + +### set-P02 / set-P05: provider lifecycle + +Local add parser seeds from registry/custom flags and writes local config (`src/cli/provider.ts:144`, `:192`, `:212`, `:274`). JSON mode returns before `--sync` handling (`:279`, `:292`). Existing test explicitly pins `needsSync:true` despite its misleading title (`tests/cli/cli-provider.test.ts:680`); fixing JSON-plus-sync is a deliberate behavior correction, not an untested assumption. + +Live POST validates the candidate, mutates retained live provider config, reconciles state stores, clears model cache and returns `{success:true,name,catalogRefresh}` (`src/server/management/provider-routes.ts:1372`, `:1400`). Live default selection rejects a disabled row and persists/reconciles a standalone `{setDefault:true}` (`:1459`). Local set-default only verifies existence before saving (`src/cli/provider.ts:439`, `:459`). + +Live remove is materially broader: default replacement and combo dependency checks (`src/server/management/provider-routes.ts:1824`), custom-model removal, cap cleanup, OAuth account-set removal, live-store reconciliation, model-cache invalidation and catalog receipt (`:1854`). Local remove refuses current default and deletes provider/custom-model config (`src/cli/provider.ts:345`, `:355`, `:364`). **Do not silently substitute the live delete in the existing unflagged command**: it would add credential deletion/default reassignment side effects. + +Exact live grammar: + +- `provider add P [existing fields plus --auth-mode MODE --responses-path PATH] --live --json` → POST `/api/providers` `{name,provider,setDefault?}`. Fetch target presets for canonical reserved provider seed; no local config mutation. Retain explicit `--force` overwrite intent. Existing POST is upsert: a read-before-post duplicate guard is not atomic create-only CAS; document that limit, do not claim a nonexistent server precondition. +- `provider set-default P --live --json` → standalone PATCH `{setDefault:true}`. +- `provider remove P --live --yes --json` → DELETE providers by name; server performs atomic default selection within its mutation path. Include removed credential scope in help/confirmation, and preserve dependentShadowIntercept/droppedCustomModels/catalogRefresh fields. +- `provider edit P --enabled on|off --json` is already management-backed; no new implementation needed for enable/disable. Do not overload adding `--live` on this already-live branch into a new transport selector. +- Reject `--live --sync`: live lifecycle endpoint already converges the catalog; broad local sync is a different action. Fix local `--sync --json` by running the requested local sync and reporting its actual returned/refused/skipped status; do not force it to `needsSync:false`. + +### set-P10: logout + +Both paths call `removeCredential`, which removes the active credential and chooses the next usable account under the store mutation lock (`src/oauth/store.ts:1093`). Local dispatch preserves useful removed/not-found semantics (`src/cli/dispatch.ts:425`). Store mutation persists and publishes account selection (`src/oauth/store.ts:828`), but publication uses in-process listeners (`src/lib/account-selection-events.ts:25`, `:36`); it is not a management cache-cleanup receipt. + +Server logout additionally clears login state, model/inflight catalog caches, provider/account quota caches and Devin direct caches (`src/server/management/oauth-account-routes.ts:373`). This is a concrete source difference; no timing probe against user state is needed to choose the live path. + +- `ocx logout P --live --json` → POST `/api/oauth/logout?provider=P`; no local credential read/remove first. +- Keep local `logout P --json` existing exit 4/removed receipt semantics. The live route returns `{success:true}` and is effectively idempotent for a missing credential; do not synthesize `removed:true` or local exit 4 from it. No server response extension is necessary for minimum GUI parity. +- Do not broaden login work in this crux. Browser preference/initial-login variants remain the separate P10/P20 parser gap already recorded. + +## Exact file plan + +New filenames below were checked absent at inspection time. Source files named existing must be extended narrowly; no shared transport framework is needed. + +| Work slice | Existing files to edit | New files proposed | Smallest responsibilities | +|---|---|---|---| +| Custom live add/remove + local receipts | `src/cli/models.ts`, `src/cli/models-runtime-subcommands.ts` only if dispatcher contract needs it | `src/cli/models-custom-runtime.ts`; `tests/cli/cli-models-custom-runtime.test.ts` | Route explicit live add/remove before local config access; typed bodies/same-target ID resolution; JSON local outcome separation. Reuse existing `src/cli/models-runtime.ts` edit implementation. | +| v2 target/JSON contract | `src/cli/v2.ts`, `src/cli/dispatch.ts`, `src/cli/registry.ts` | `src/cli/v2-runtime.ts`; `tests/cli/cli-v2-runtime.test.ts` | Parse common flags once, reuse existing local functions, route live operations to `/api/v2`, project truthful receipts. Add mode-hint to root help. No agent.ts mode taxonomy. | +| Provider live lifecycle | `src/cli/provider.ts`, `src/cli/provider-runtime.ts` only for shared parser/dispatch seam, `src/cli/registry.ts` | `src/cli/provider-lifecycle-runtime.ts`; `tests/cli/cli-provider-lifecycle-runtime.test.ts` | Explicit live add/default/remove; fetch target preset; reject local sync combination; preserve offline behavior. Existing local JSON-plus-sync test updated in `tests/cli/cli-provider.test.ts`. | +| Live logout | `src/cli/dispatch.ts`, `src/cli/registry.ts` | `src/cli/logout-command.ts`; `tests/cli/cli-logout-runtime.test.ts` | Extract or wrap existing validated root grammar, add explicit live branch and injectable RuntimeApiDeps, keep local behavior. No new account logout alias required. | +| Discovery/contracts/docs | `src/cli/capabilities.ts`; `skills/ocx/references/03_recipes.md`; `structure/runtime.md`, `structure/config.md`, `structure/clients/chatgpt-desktop.md`, `structure/ops/docs-and-release.md` as affected by each slice | none required for transport | Declare existing/new leaf options and distinguish local/live. Main owns canonical output/error envelope work. | +| Test layout | `scripts/test-layout/layout.json`, `tests/fixtures/test-layout-expected.json` | none | Register every new test file in both maps. Avoid enlarging ratcheted `tests/codex-integration/codex-v2-gate.test.ts`; use focused new siblings. | + +Verified ownership mapping is `structure/INDEX.md:124`: CLI is jointly owned by runtime/config/client-integration/desktop/docs-and-release documents. The file plan names the applicable existing owners; main should update only the affected invariants, following their nested instructions. No server source change is necessary to expose these existing routes. A future atomic create-only provider contract or richer logout removed receipt would be separate scope, not hidden in this roadmap. + +## Source evidence versus required implementation proof + +Existing test source confirms that these are real existing features, not names inferred from declarations: `tests/codex-integration/codex-v2-gate.test.ts:1641` covers hint write/clear; `:1661` covers nonblank whitespace preservation and missing/blank rejection; `:1742` covers v1/v2 thread-slot transitions. `tests/cli/cli-provider.test.ts:473` deliberately expects local default-provider removal refusal; `:680` pins JSON skip-sync. None were run in this pass. + +The plan can be locked from source: a local sync and an HTTP catalog-only receipt have demonstrably different code paths; local versus live logout cleanup is explicit; provider removal side effects differ. Running those existing local tests would not establish cross-target live parity, so no scratch probe or test run was warranted merely to choose the roadmap. + +Implementation gate (for main, not claimed complete): + +1. Fake `RuntimeApiDeps.fetchImpl/baseUrl/findLiveProxy`, temporary home/auth context only, with every unexpected network call failing. Test target pinning across read/resolve/write and no local read/write on live refusal. +2. Custom add/remove: exact metadata/null/empty variants; UUID versus slug collision; created entry and saved/catalog failure receipts; unflagged local path unchanged. +3. V2: all seven live mappings above; strict unknown/trailing args before any mutation; hint null/blank cases; advisory omitted by default and true only by explicit flag; mixed live target local home remains untouched; server partial persistence/convergence outcome stays visible. +4. Provider: live default delete reassigns through one DELETE, offline continues to refuse; dependent combos and credential cleanup are handler authority; missing provider and disabled default errors; live --sync rejected; local --sync --json calls sync and keeps truthful skipped/refused outcomes. Never assert read-before-create is CAS. +5. Logout: live request never calls local removeCredential; server receipt preserved; local removed/not-found JSON/exit unchanged; mocked handler tests demonstrate cleanup functions invoked, not upstream calls. +6. Use existing nonzero/error-body machinery; parent-owned machine-envelope work must retain RuntimeApiError.body on partial/failed-convergence responses. A tool exit or 2xx alone is not proof that persisted state and live/client state all converged. + +Remaining bounded limits: the existing CLI management target intentionally refuses a connected-client listener; dashboard remote relay equivalence is outside this change. Runtime receipts, target isolation and failure behavior remain to be tested during implementation. The transport choice and file plan no longer depend on an unexplained UNKNOWN. + + +# Operational parity target decisions + +2026-10-03, bounded explorer follow-up. Repository root `the task checkout`; all source anchors are relative to that root. This artifact supersedes the target-dependent labels in `gaps-operations.md` for the rows below. Main owns roadmap and command conventions. No tracked files, live proxy, real credentials, upstream traffic, branch state or orchestration were touched. Two focused test files ran with pure/mock inputs; details below distinguish executed proof from inspected tests. + +## Decisions ready for the roadmap + +| Existing task IDs | Resolved classification | Decision and smallest command choice | Implementation boundary / source evidence | +|---|---|---|---| +| ops-C06 | IMPLEMENTATION_GAP for live desired-profile read; existing live status COMPLETE | Keep `ocx claude desktop show --json` explicitly local. Add **`ocx claude desktop profile show --json`**, a fixed GET `/api/claude-desktop` on the existing local management runtime. Invoke it on the hub host to inspect the Hub profile. Existing `desktop status --json` remains the applied-health read. | GUI receives sharedBase at `gui/src/App.tsx:584`, GET at `gui/src/pages/ClaudeDesktop.tsx:270`. CLI show builds disk state at `src/cli/claude-desktop.ts:790`; status uses live route at `:751`. `src/cli/runtime-api.ts:71` rejects a client-role listener and does not automatically authenticate to a Hub. Do not introduce `--url`, remote admin-token storage, or automatic relay login. | +| ops-C07, ops-C12 | IMPLEMENTATION_GAP for live save/import; existing local editing retained | Add **`ocx claude desktop profile import FILE --json`**, validates one bounded DesktopProfile and sends `{profile}` to PUT `/api/claude-desktop`. It saves only; use existing `ocx claude desktop apply --gateway` or `--first-party` separately. Existing local `move`, `default`, `import`, `export` retain current meaning. A file-based profile operation is a domain operation, not generic config editing. | `src/cli/claude-desktop.ts:203` writes only persisted local profile under connection/CAS guards; it does not adopt live server config. GUI PUT `src/server/management/agent-settings-routes.ts:907` validates routes, protects applied markers, performs conflict check and explicitly adopts live config at `:959`. Existing connected import --apply is refused at `src/cli/claude-desktop.ts:736`. New handler: small `src/cli/claude-desktop-profile.ts`, dispatch through existing `src/cli/claude-desktop.ts:676`; do not grow a second parser or change auth. | +| ops-S05 | COMPLETE for actual GUI task; discovery/output clarification only | **`ocx status --json`** already exposes `connection.selectedClients`; **`ocx sync`** on connected machine already runs the same domain sync. No `machine clients` command or journal inspection task is needed to match this GUI. | `gui/src/pages/Integrations.tsx:64` consumes only selectedClients; renders at `:137`. Although API also returns journalOwner/shim, that page does not display them. CLI projection `src/cli/status.ts:918` includes selectedClients. GUI machine API calls deps.sync (`src/client/machine-api.ts:94`), whose default is syncConnectedClient at `:30`; connected CLI uses syncConnectedClient at `src/cli/dispatch.ts:450`. No new remote transport. | +| ops-O08 | Existing client-self + Hub-total COMPLETE in their authorized execution contexts; IMPLEMENTATION_GAP for administrator selecting one key on Hub | Keep **`ocx usage ... --json`** on a connected machine as own-key data-plane usage, and the same command on the Hub host as whole-Hub management usage. Add only **`--api-key-id ID`** to `ocx usage` for the existing non-client management branch. Reject this option on connected client before reading secret/transport; do not forward it to `/v1/usage`. | GUI machine button adds apiKeyId; Hub button omits it (`gui/src/pages/Usage.tsx:1113`, `:1275`). Management API accepts filter (`src/server/management/logs-usage-routes.ts:243`). CLI branch `src/cli/observe.ts:188` uses stored enrolled data key + `/v1/usage` for client; local Hub uses `/api/usage` at `:209`. `/v1/usage` authenticates exact configured key, projects `scope:'client'`, rejects caller-selected identity and strips accounts (`src/server/hub-usage.ts:15`, `:25`; `src/remote/hub-usage.ts:8`). This intentionally does NOT promise remote Hub-total access using a client data key. | +| ops-I14 | IMPLEMENTATION_GAP for narrow invocation, not missing backend/helper | Add **`ocx integration client sync --client aside --json`**. No profile selector: GUI refreshes server-selected enabled profiles. Call existing **refreshAsideProfilesThroughServer**, preserving its direct-local attestation capability. Emit per-profile outcomes, and nonzero on any unsuccessful outcome; do not turn partial 207 into blanket success. | GUI uses exact POST `/api/client-integrations/aside/sync {}` at `gui/src/pages/integrations/aside-profile-api.ts:38`; owner `src/server/management/aside-profile-routes.ts:308`. Helper already exists in `src/cli/aside-profiles.ts:9`; capability transport at `:24`, `:50`; controlled baseUrl seam at `:69`. Current `ocx sync` first syncs Codex and other file clients, then calls helper at `src/cli/dispatch.ts:526`, so it is an effect superset with warning-only failure handling, not the narrow task. Add branch in `src/cli/integrations.ts:222` with lazy helper import; no new backend owner. | +| ops-O06 | Snapshot read COMPLETE; follow amendment semantics IMPLEMENTATION_GAP | Keep command **`ocx logs --follow --jsonl`**. Make this existing follow workflow cursor/reset aware and surface changed already-seen rows; don't invent a history endpoint. Minimal compatible JSONL choice: re-emit a row when its canonical payload changes, with same id; document consumers should upsert. Preserve duplicate IDs when server explicitly returns them, resets and removals; see exact output decision below. | CLI `src/cli/observe.ts:100` never sends cursor and suppresses any seen ID at `:108`. Server content hash deliberately sends reset for same-ID content changes (`src/server/request-log-cursor.ts:50`, `:57`, `:77`); GUI replaces snapshot on reset (`gui/src/pages/Logs.tsx:621`) and merges only valid deltas. Probe below proves the mismatch with actual cursor/parser modules and the exact source-equivalent dedupe predicate. | +| ops-D01 | IMPLEMENTATION_GAP for authenticated runtime-health projection | Add **`ocx system health --json`**, fixed GET `/api/system/health` via existing runtimeRequest, run on the serving runtime's host. Keep existing `ocx health` liveness contract and `system status` aggregate unchanged. | Endpoint returns status/service/version/uptime/pid/spendLedger at `src/server/management/system-routes.ts:66`. `ocx health --json` emits only ok/pid/port (`src/cli/dispatch.ts:787`); `status --json` emits health ok/url/message plus other machine state (`src/cli/status.ts:873`), not this projection; `system status` fetches only settings/startup/memory (`src/cli/system-command.ts:35`). New leaf in `src/cli/system-command.ts:193`; no new API or remote credential scheme. | + +The Desktop additions are deliberately scoped to the currently serving **local management runtime**, which may be a Hub. Running them on a connected client should preserve the existing client-role refusal and guidance to run on the Hub. The connected browser's independently authorized shared dashboard session is not a CLI credential. Existing connected Desktop **apply** intentionally downloads the Hub's resolved Desktop model snapshot and writes the connected machine's gateway config (`src/cli/claude-desktop.ts:238`, `:260`); that is a separate target from editing the Hub's desired profile. + +The GUI profile import stages a draft only (`gui/src/pages/ClaudeDesktop.tsx:480`) whereas a terminal import command naturally commits when explicitly invoked. This does not require implementing a persistent CLI draft editor: file inspection followed by explicit `profile import` and separate `apply` preserves the meaningful save/apply boundary. Reuse `parseDesktopProfile`; retain server's unavailable-model validation and trusted applied-marker handling. No automatic mode switch or apply is added to import. + +## Exact follow-output choice + +`ops-O06` is a workflow gap, not merely inefficient repeated polling. With a stable request id, CLI seen-ID dedupe loses later status/token/pricing updates even though `/api/logs` exposes them. + +Smallest bounded change is to extract cursor/snapshot state into **`src/cli/log-follow.ts`** and call it from **`src/cli/observe.ts`**. It should: + +1. Parse cursor/reset envelopes defensively. Legacy array/snapshot responses remain accepted and never manufacture a cursor. +2. Replace the local bounded window on reset; append suffixes otherwise. The server explicitly permits repeated IDs, so do not use an id-only set to represent the window. +3. Existing text/row-JSONL follow can re-emit changed rows; an explicit removed/reset event would be a different output contract. If deletion/reset visibility is required for exact machine reconstruction, add **`--events`** to follow and emit `{type:'snapshot',rows,cursor}`, `{type:'append',rows,cursor}` rather than silently breaking the existing row JSONL stream. This is the smallest additive exact-state option. No `--api-path` or new backend route. +4. Keep `--json` one-shot; `--follow --jsonl` streaming. Bound window/cursor sizes, handle interruption, and never claim an accepted stale snapshot is new data. + +Recommended roadmap split: fix row amendments and cursor transport in existing follow; add `--events` only in the same reviewed output-contract unit if exact reset/removal projection is an acceptance requirement. GUI-to-CLI read parity must at least stop losing amendments. Full event schema is main's shared output-contract decision, not a new unresolved target/auth question. + +## Duplicate settings tasks: use existing IDs + +These are aliases for existing owner tasks, **not additional UNKNOWN roadmap rows**. + +| Operations row | Canonical settings IDs | Why | +|---|---|---| +| ops-D18 multi-agent mode/thread/native behavior and advisory | **set-M13**, **set-S04** | Existing v2 root and advisory/local-live join belong to these rows; do not introduce another agent-mode taxonomy. | +| ops-D18 injection model/effort/guidance/default synchronization | **set-S03** | Same injection/default contract. Featured roster and fallback references, where rendered, map to **set-S01**, **set-S02**. Effort-cap metadata should be reconciled with this settings-owned unit, not counted again. | +| ops-O15 account/quota/active-selection reads in Tray | **set-A01**, **set-P09**, **set-P12**, **set-P14** | Codex readiness/quota plus generic OAuth/API-key roster. Usage/companion reads stay ops-O08/O10/O13. | +| ops-O16 Tray switches | **set-A04** (Codex), **set-P12** (OAuth), **set-P14** (provider API-key pool) | `gui/src/pages/tray-data.ts:36` selects these exact three route families. No tray-specific command. | + +Canonical titles/IDs verified from `.tmp/cli-parity/gaps-settings.md`. These references are stable task identities; that artifact may continue gaining source evidence while main assembles the roadmap. + +**Coverage expansion requiring main allocation, not a duplicate UNKNOWN:** the first inventory's D18 footnote also mentioned `MemoryModelsPanel` and `CompactionRoutingPanel`, but neither has a matching dedicated `set-*` row in the current 67-row settings join. They write `memoryModels` and `compactionRouting` through PUT `/api/settings` (`gui/src/components/MemoryModelsPanel.tsx:111`, `gui/src/components/CompactionRoutingPanel.tsx:180`); they are not injection or v2 fields and must not be falsely mapped to set-S03/M13. Parent should allocate these two field groups to its runtime/model settings unit before calling all dashboard fields closed. Exact values: memoryModels `{extract?:{...phase},consolidation?:{...phase}}|null`; compactionRouting `{model,reasoningEffort?,triggers?,sourceModels?}|null`. Existing system settings parser only handles autostart/stream-mode/desktop-authless/client-compaction (`src/cli/system-command.ts:123`), so generic `config set` would not establish live PUT parity. This pass does not create new set IDs or edit sibling artifacts. + +## Accepted C4 data-plane unit + +Parent explicitly accepted terminal model test, transcription and connection-only voice probe as tasks. **ops-K08/K12/K13 are included IMPLEMENTATION_GAPs**, not pending product scope. Browser microphone capture, playback widgets, copy buttons and waveform UI remain excluded. Authorization authority is unchanged. + +| ID | Smallest command | Code/contract and proof requirements | +|---|---|---| +| ops-K08 | **`ocx access test MODEL --protocol responses\|chat\|messages --api-key-stdin --json`** | Keep existing access test grammar, add explicit chosen-key input. Current `src/cli/access.ts:255` uses runtimeRequest, whose headers start with management auth (`src/cli/runtime-api.ts:142`); that is not GUI newly-created-key proof. Use bounded `readSecretBytes` (`src/cli/runtime-api.ts:398`) with a 4096-byte key limit, strict UTF-8/single-line decoding, explicit TTY refusal, input deadline and returned-buffer cleanup and a dedicated fixed data-plane transport that sets only the chosen `x-opencodex-api-key`, never management bearer/header defaults. Existing no-flag test must not newly claim selected-key validation. | +| ops-K12 | **`ocx access audio transcribe FILE --model ID --api-key-stdin --json`** | Multipart file/model/response_format=json to fixed `/v1/audio/transcriptions`, bounded file size/deadline/body, abort on signal. GUI contract at `gui/src/audio-api-client.ts:13`; actual admitted route `src/server/index/serve-options.ts:1594`. Output transcript only by explicit task result, not incidental debug logging; no background retries that spend usage again. | +| ops-K13 | **`ocx access audio live-check --model ID --api-key-stdin --json`** | Fixed WebSocket `/v1/live?model=...`, same data-key subprotocol scheme and session.update/client-delegation settings as GUI (`gui/src/audio-api-client.ts:71`, `:88`). Wait for server session id/status, then session.close; bounded readiness/session lifetime. No microphone, audio uploads, delegation execution or auto-reconnect. Return connection outcome, not a claim of usable voice roundtrip. | + +Recommended file boundaries: **`src/cli/access-data-plane.ts`** for fixed allowlisted HTTP test/transcription origin+headers+bounded response helpers, **`src/cli/access-audio.ts`** for the two audio verbs and WebSocket lifecycle; wire through **`src/cli/access.ts:274`**. These are domain-specific internal helpers, not an operator-visible arbitrary-URL request command. Reuse existing stdin/timeout/error primitives where safe; never call runtimeRequest for the chosen-key wire request. + +Target resolution reuses current topology, not a new credential store: standalone/Hub use the existing local serving origin; connected client uses its already-enrolled normalized serverUrl, analogous to `fetchHubUsage` (`src/client/hub-client.ts:484`). The explicit key is still provided for this task through stdin; never implicitly substitute the enrolled key or admin token. Revalidate connection identity around an async read on connected clients and retain HTTPS-or-loopback, redirect refusal, safe headers, and origin policy. Do not add `--base-url`, token argv/env flags, token file caches, or a management-relay credential exchange in this unit. + +For review, require fixture evidence for wrong chosen key, missing key, all three protocol shapes, explicit refusal when the target does not enforce the chosen key, no admin-header leakage, no redirects, no stderr/stdout secret echo, bounded file/body/session sizes, timeout/interruption and correct session.close. Existing auth/scope policy remains authoritative; adding a CLI cannot make a data key a management principal. All synthetic keys must stay fixture-only. The final 070 observational guard supersedes any unconditional chosen-key-enforcement assumption in this source proposal. + +## Focused proof and proposed test placement + +Executed, using only mocked/pure inputs: + +- From repository root: `bun test gui/tests/log-poll.test.ts tests/clients/client-hub-usage.test.ts` — Bun selected **only the client file**, 16 pass / 0 fail / 40 assertions. Do not claim this invocation ran GUI tests. +- From `gui/`: `bun test tests/log-poll.test.ts` — 4 pass / 0 fail / 22 assertions. Covers legacy snapshots, reset metadata, malformed cursor rejection and repeated-ID preservation. +- A fileless `bun -e` probe imported actual `src/server/request-log-cursor.ts` and `gui/src/pages/log-poll.ts`, fed two snapshots `{id:'fixture-same-id',status:200,totalTokens:1}` then tokens=9, and applied the exact source-equivalent CLI `seen.has(String(row.id))` predicate. Output: **`{"serverReset":true,"guiAmendedTokens":9,"cliDedupeEmitted":0}`**. This is proof of cursor/parser behavior plus a source-level CLI predicate reproduction, **not execution of the whole CLI follow loop**. + +Inspected only, not executed: + +- `tests/claude-integration/claude-desktop-cli.test.ts:402` asserts connected show/export/move/default remain local and warn; `:280` asserts connected import --apply refuses before writing; `:501` asserts apply delegates profile to live owner. +- `tests/clients/aside-profile-sync-owner.test.ts:211` covers stale CLI refreshing only live-server-enabled Aside profiles; existing helper is the owner to reuse. +- `tests/server/hub-usage.test.ts:66` rejects absent/environment/admin keys for data-plane usage; `:76` rejects caller-selected identity; `:85` retains authenticated scope with bounds/filters. Executed client-side mocks additionally verify dedicated data key/no Authorization and dropping management-only DTO fields. + +New focused files proposed (no edits made): + +| Change | Proposed focused test file | Essential assertions | +|---|---|---| +| Desktop live profile show/import | `tests/cli/cli-claude-desktop-profile.test.ts` | Fixed GET/PUT shape, bounded parse-before-write, missing/invalid file zero write, 409 does not rebase, live adoption result, client-role refusal, existing local verbs untouched. | +| Runtime health read | `tests/cli/cli-system-health.test.ts` | Current runtime GET, version/uptime/pid/spendLedger preserved, remote/client refusal, no invented liveness success. | +| Usage admin filter | `tests/cli/cli-usage-scope.test.ts` | Hub query includes apiKeyId only when explicit; connected rejection before secret/transport; default connected self read unchanged; invalid connection fails closed. | +| Narrow Aside sync | `tests/cli/cli-aside-sync.test.ts` | Calls existing helper only, no Codex/other-client sync, no profile flag, partial outcomes nonzero, attestation refusal no fallback. Keep stale-owner test as server proof. | +| Log amendments/events | `tests/cli/cli-log-follow.test.ts` | Changed same ID, repeated IDs, valid suffix, reset/removal, legacy snapshots, malformed cursor, bounded state, interruption. GUI parser tests are not CLI coverage. | +| Data-plane chosen key/audio | `tests/cli/cli-access-data-plane.test.ts`, `tests/cli/cli-access-audio.test.ts` | Injected HTTP/WebSocket and fake stdin only; auth/secret/redirect/failure/cancel matrix above. No provider traffic. | + +Any new test files must be registered in both repository layout maps under the existing AGENTS rule. Prefer these siblings over extending already-large legacy parity/desktop files. Exact-head integration/test execution and final receipt design remain main-owned. + +Static receipt: 47 explicit source file/line anchors resolve; all 10 referenced set-* task IDs exist in the current settings join. Proposed new implementation/test paths are explicitly proposals and were not created. diff --git a/devlog/_plan/261003_cli_gui_parity/007_architecture_decisions.md b/devlog/_plan/261003_cli_gui_parity/007_architecture_decisions.md new file mode 100644 index 00000000000..978685d754b --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/007_architecture_decisions.md @@ -0,0 +1,42 @@ +# Architecture decisions + +The reader is a maintainer reviewing named terminal workflows. Existing domain handlers and the existing management client remain the execution authority; the capability index becomes an accurate, scalable discovery layer. + +| Decision | Main disposition | Consequence | +| --- | --- | --- | +| CP-ARCH-01 | Accept fixed named metadata with handwritten domain handlers | No arbitrary method/URL API client, no generic config fallback counted as parity. | +| CP-ARCH-02 | Amend: reuse Capability, without NamedCommandMeta/DomainCommand interfaces | Split type/data files only for size and pure-import boundaries. Handler signatures remain compatible. | +| CP-ARCH-03 | Accept existing server validation/persistence/ownership | CLI parses grammar and bounded input; no second persistence engine or live-to-local fallback. | +| CP-ARCH-04 | Accept additive optional Capability.usage | Exact operand grammar is available for verified leaves; old metadata output stays compatible when absent. | +| CP-UX-01/02 | Accept fixed grammar, explicit JSON sources and scoped confirmation | Ordinary reversible changes do not gain gratuitous confirmation. Destructive actions preserve --yes and identity checks. | +| CP-UX-03 | Amend: preserve legacy stderr prose and exit codes | No global JSON error-envelope migration. New diagnostics are safe and retain reason/hint/status. Partial receipts remain observable. | +| CP-UX-04 | Scope observational claims | Help remains offline/write-free. Do not promise all legacy reads bypass shim preflight; new strict observational paths need their own proof. | +| CP-AUDIT-01/02 | Accept task ledger plus separate API debt | Counts are not endpoint-prefix coverage. Local/native equivalence, duplicate GUI entry points and consent exclusions are explicit. | +| CP-SIZE-01 | Accept capacity work before metadata expansion | Split generated reference into flat domain chapters; add a CLI structure owner by moving existing contracts, never raising line caps. | +| CP-TEST-01 | Accept handler-wire, real route, CLI and negative evidence | No live user state/upstream traffic. Source declarations are not runtime proof. | +| CP-DATA-01/02 | Accept bounded credentialless malformed-body observation before a chosen-key model probe | Fail unavailable on unproved enforcement, preserve existing server policy, and state the cross-request identity/policy limits; exact mechanism and real-route tests are in 070. | +| CP-DELIVERY-01 | Accept dependency slices with sequential branch ownership | Main alone switches branches; implementation leaves have disjoint file scopes. Six manual PR layers, each with its own CI. | + +## Local and live are explicit targets + +Preserve offline/local commands. Add --live to provider add/remove/set-default, custom models add/remove, v2 and logout where the source comparison proves different retained runtime state or receipts. Decide the target before touching local config. A multi-request workflow resolves its management base once and reuses it. A refusal never falls back to local writes. --json is output selection, never target selection. + +For Desktop, use the existing namespace with profile show/import for the live desired profile; existing show/move/default/import remain local and apply remains separate. Management commands run on the serving runtime host, including a Hub; a connected-client management refusal remains a refusal. No remote admin credential scheme is introduced. + +## Capability usage field chain + +Creation: optional usage literals in pure capability domain files; type in src/cli/capability-types.ts. Serialization: capabilities-command.ts uses an explicit field projection; it must add usage conditionally while retaining the exact legacy shape for declarations without it. A real runCapabilities --json fixture verifies the field is not silently dropped. Deserialization: N/A, no persisted/external capability ingestion is introduced. Consumers: declared help renderer and generated reference use usage beneath canonical headings; command matching/recovery and capabilityInvocation remain based on command tokens. Tests cover absent-field compatibility, exact grammar, alias resolution and pure import closure. + +## Input and result boundaries + +New JSON file/stdin input is explicit, bounded to the management JSON contract (4 MiB), rejects interactive waiting, invalid UTF-8/JSON and wrong top-level shapes, and never echoes payloads. Domain files validate keys/shapes and reuse pure existing validators where appropriate. Composite requests are checked against the whole serialized body limit. Never read stdin twice in one invocation. + +Server errors retain their normal exit classification. A new safe nested-error projection in runtime-api preserves an existing nested code/message without dumping the raw body. Domain writers distinguish saved, applied, deferred, conflict and unknown completion; no blind write retry. Human text uses terminal escaping. JSON success remains the safe existing DTO, not a universal new envelope. + +## Explicit scope for data-plane tools + +The API Keys page's selected-key test, audio transcription and connection-only live probe are included as terminal tasks. They use a dedicated fixed data-plane transport with an explicit stdin key, never management auth or arbitrary URLs. Browser microphone capture/playback and waveform controls are presentation exclusions. No secret-returning creation/pairing operation is executed by the development agents. + +## Consultation provenance + +Architect: Epicurus, returned handle 01a1021d-2d94-7d20-95c1-a18da31958a8. Proposal and decision amendment are retained in task scratch. The architect accepted optional usage with exact legacy fallbacks and accepted retaining existing v2 roots after main corrected an inventory false-negative. Whole-plan reflection by the same architect is ALIGNED for SHA256 a095a4e514d6d8e5a37dbf05a66b2c9156ebaeeb28a8e0fb878bc76f931c27b1: all 178 IDs, unit assignments and acyclic aliases were checked, with no essential mismatch. This is separate from the earlier concept agreement. Reflection artifact is retained in task scratch; its decision mapping covers every accepted CP decision. Independent A remains a separate gate. diff --git a/devlog/_plan/261003_cli_gui_parity/008_task_ledger.json b/devlog/_plan/261003_cli_gui_parity/008_task_ledger.json new file mode 100644 index 00000000000..e8e5db4dc27 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/008_task_ledger.json @@ -0,0 +1,185 @@ +{ + "baseline": "9f89b7265b754eb681215ad327fc9459af37b9e1", + "candidateRows": 178, + "scopeNote": "176 initial rows plus two confirmed embedded settings groups; aliases are retained and excluded from unique eligible denominator, not silently dropped.", + "rows": [ + {"id":"set-P01","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-P01 — Inspect configured providers, presets, authentication availability","existingCli":"provider list/show/presets; inspect config; account list/current; status --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P02","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp3","evidence":[],"task":"set-P02 — Add a preset/custom provider; enable canonical OpenAI account provider","existingCli":"provider add P [--adapter A --base-url U --api-key ... --default-model M --allow-private-network --force --set-default --sync]; provider edit openai --enabled on","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P03","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp3","evidence":[],"task":"set-P03 — Edit provider transport, discovery, default model, note, network permission","existingCli":"provider edit/update P --adapter A --base-url U --default-model M\\|- --auth-mode MODE\\|- --note TEXT\\|- --api-key-transport MODE\\|- --enabled on\\|off --live-models on\\|off --allow-private-network on\\|off","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P04","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp3","evidence":[],"task":"set-P04 — Configure and inspect request pacing","existingCli":"inspect pacing --name P --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P05","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp3","evidence":[],"task":"set-P05 — Enable/disable, choose default, remove provider","existingCli":"provider edit P --enabled on\\|off; provider set-default P; provider remove P","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P06","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-P06 — Change OpenAI account mode","existingCli":"provider account-mode pool\\|direct --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P07","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp3","evidence":[],"task":"set-P07 — Atomically edit provider JSON","existingCli":"config import exists but is not provider-editor CAS parity","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P08","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-P08 — Check provider connectivity","existingCli":"provider test P --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P09","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-P09 — Inspect provider quota/capacity/usage","existingCli":"provider quota [--refresh] --json; account list P --quota [--refresh] --json; usage --range 30d --surface codex\\|all --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P10","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-P10 — OAuth login, add another account, reauthenticate, submit callback, cancel, logout","existingCli":"account login P [--reauth --id I] [--no-wait]; account reauth/code/cancel; login P (local); logout P --json (local)","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P11","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-P11 — Kiro native device login","existingCli":"account login kiro --method builder-id\\|google\\|github [--no-wait] --json; account cancel kiro --flow F --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P12","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-P12 — Manage OAuth account roster","existingCli":"account list/current/use P I; account alias P I TEXT\\|-; account pause/resume P I; account remove P I --yes; all support --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P13","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-P13 — Import Antigravity accounts","existingCli":"account import google-antigravity --format cockpit-tools --file F\\|--stdin --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P14","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-P14 — Manage API-key pool","existingCli":"account list/use P I; account add-key P [--label L] (stdin); account alias P I TEXT\\|-; account remove P I --yes --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P15","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-P15 — Set account-pool strategy and thresholds","existingCli":"account strategy P STRATEGY; account sticky P N; account auto-switch P on\\|off\\|threshold N\\|status; account routes anthropic ...","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P16","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-P16 — Set per-Anthropic-account auto-switch override","existingCli":"account auto-switch anthropic status\\|on\\|off\\|inherit\\|threshold N --account I --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P17","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp3","evidence":[],"task":"set-P17 — Control xAI Responses opt-in and model Fast variants","existingCli":"provider edit xai --xai-chat on\\|off --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P18","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-P18 — Inspect/redeem Grok reset coupons","existingCli":"account grok-reset-coupons [I] [--consume --yes --token-id T --operation-id UUID] --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P19","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-P19 — Inspect/redeem Anthropic reset grants","existingCli":"No Anthropic grant read command in account-auth dispatcher; Grok/Codex reset commands target different contracts","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P20","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-P20 — Choose whether OAuth launches browser on proxy host","existingCli":"account login currently omits openBrowser; GUI local preference feeds request field","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A01","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-A01 — Inspect/refresh account readiness, quotas and active selection","existingCli":"account list openai --quota [--refresh] --json; account current openai --json; account refresh openai --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A02","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-A02 — Add/re-authenticate pool account with browser or device flow","existingCli":"account login openai --id I --reauth --device --no-wait --json; account code/cancel openai --flow F","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A03","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-A03 — Reauthenticate native main in place","existingCli":"account main reauth --device [--no-wait] --json; account main reauth status\\|cancel --flow F --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A04","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-A04 — Select active account, rename, remove","existingCli":"account current/use/clear openai; account alias openai I TEXT\\|-; account remove openai I --yes --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A05","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-A05 — Pause/resume, pause exhausted accounts, set priority","existingCli":"account pause/resume openai I; account pause-exhausted openai; account priority openai I N\\|first\\|earlier\\|normal\\|later\\|last\\|reset --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A06","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-A06 — Set per-account auto-switch threshold","existingCli":"account auto-switch openai on\\|off\\|threshold N\\|status is pool-wide only","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A07","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-A07 — Permit paid credits after quota exhaustion","existingCli":"Only generic config fallback; no account-auth/extended credits policy handler","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A08","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-A08 — Inspect/redeem Codex reset credits","existingCli":"account reset-credits I\\|main [--consume --yes --operation-id UUID] --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A09","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-A09 — Configure quota-window activation and credit display","existingCli":"system settings --json reads settings; account refresh handles immediate refresh only","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A10","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-A10 — Native-main profile inventory, register, switch/recover","existingCli":"account main list\\|doctor\\|register LABEL\\|switch I --yes\\|recover [--rollback --yes] --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A11","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-A11 — Account-picker setting and main hard lock","existingCli":"system settings --json reads values","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A12","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-A12 — Read prompt layer stack and effective prompt text","existingCli":"inspect codex-prompt --json; inspect codex-prompt --text (mutually exclusive)","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A13","domain":"settings","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"set-A13 — Toggle/edit/order custom prompt layers and base variants","existingCli":"inspect codex-prompt is read-only","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A14","domain":"settings","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"set-A14 — Adopt existing prompt configuration or repair prompt drift","existingCli":"inspect codex-prompt can expose drift","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A15","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-A15 — Enable default-mode request-user-input","existingCli":"agent request-user-input [on\\|off] --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-A16","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-A16 — Toggle Ultra Fast tier","existingCli":"system settings --json reads ultraFastTier","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M01","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-M01 — Inspect catalog, exposed selection, context limits and provider metadata","existingCli":"models live --provider P --json; models selected P; models context status; models preset show; models new-policy; alias list; inspect config/catalog","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M02","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-M02 — Show/hide selected models or all models of one provider","existingCli":"models enable\\|disable P/M [--native] --json; models provider P on\\|off --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M03","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-M03 — Choose curated/provider model preset and default policy for newly discovered models","existingCli":"models preset show [--provider P]; models preset apply P [--all]; models new-policy on\\|off [--provider P]; models new-arrivals --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M04","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-M04 — Edit provider/model aliases and default alias policy","existingCli":"alias list; alias set P\\|P/M ALIAS; alias rm P\\|P/M; alias defaults on\\|off [--provider P] --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M05","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp4","evidence":[],"task":"set-M05 — Edit/reset model display label and cost override","existingCli":"models price P/M; models set-price P/M --input N --output N [--cache-read N --cache-write N] or --auto; custom models edit --display-name only","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M06","domain":"settings","baseline":"UNKNOWN","status":"pending","unit":"wp4","evidence":[],"task":"set-M06 — Create/edit/delete custom model definitions","existingCli":"models add P M --display-name --context-window --modalities --reasoning-efforts --default-reasoning-effort; models list-custom --json; models edit ID ...; models remove ID\\|P/M --yes","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M07","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-M07 — Override/restore discovered-model capability metadata","existingCli":"models set P/M --context-window N\\|0\\|- --modalities CSV\\|- --reasoning-efforts CSV\\|\"\"\\|- --default-reasoning-effort LEVEL\\|-; --reset --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M08","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp3","evidence":[],"task":"set-M08 — Override provider/per-model advertised context window","existingCli":"models set P/M --context-window N\\|0\\|- covers per-model override","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M09","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-M09 — Configure context caps: per-provider, global default, apply/remove all","existingCli":"models context status; models context value N [--set-all]; models context provider P on\\|off [--value N]; models context all on\\|off --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M10","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp4","evidence":[],"task":"set-M10 — Configure picker order manually or by ranking policy","existingCli":"agent subagents status shows picker fields; agent subagents set writes featured models only","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M11","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-M11 — Show generated Fast catalog rows","existingCli":"system settings --json reads fastRows","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M12","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-M12 — Configure shadow-call interception target","existingCli":"models shadow status; models shadow set M\\|- --enabled on\\|off --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-M13","domain":"settings","baseline":"UNKNOWN","status":"pending","unit":"wp5","evidence":[],"task":"set-M13 — Configure multi-agent surface and per-session thread limit","existingCli":"v2 status; v2 mode v1\\|default\\|v2; v2 keep-native-v1 on\\|off; v2 threads N (local, prose output)","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-C01","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-C01 — Inspect combos, target inventory, quota and catalog exposure","existingCli":"combo list/show I; models live; inspect config; provider quota --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-C02","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp4","evidence":[],"task":"set-C02 — Create/edit/rename/remove combo and target policy","existingCli":"combo set\\|create\\|update I --targets P/M[:W],... --strategy S --sticky N\\|- --effort E\\|- --alias A\\|- --native-alias --display-name TEXT\\|- --decision-provider P\\|- --decision-model M\\|- --decision-timeout N\\|- --rename-from OLD; remove I --yes","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-C03","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-C03 — Probe selected JEV decision backend","existingCli":"combo test [--combo I] [--decision-provider P\\|--decision-model M] [--decision-timeout N] --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-C04","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-C04 — Explain a saved combo's protocol behavior","existingCli":"api protocols --json; api explain --model combo/I --inbound responses\\|chat\\|messages --feature F[,F] ... --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-C05","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp4","evidence":[],"task":"set-C05 — Inspect JEV combo decision outcomes and savings","existingCli":"usage --range ... --model combo/I exists but returns ordinary usage","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-R01","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-R01 — Inspect routing profiles, candidates, scoring and compatibility suite choices","existingCli":"route policy list/show I --json; inspect routing-analytics --json; models live; lab catalog --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-R02","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp4","evidence":[],"task":"set-R02 — Create/update/remove routing profile","existingCli":"route policy only list/show/dry-run/evaluate","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-R03","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-R03 — Dry-run a saved route against requirements","existingCli":"route policy dry-run\\|evaluate I --model-context N --tools --image --structured-output --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-S01","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-S01 — Choose/reorder featured subagent roster","existingCli":"agent subagents\\|roster status\\|set CSV\\|clear --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-S02","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-S02 — Force subagent model and configure fallback chain","existingCli":"agent subagents force M\\|-; agent fallback status\\|set [CSV] [--poll-ms 5000..600000]\\|clear --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-S03","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"set-S03 — Configure delegation guidance/default model/effort and synchronize defaults","existingCli":"agent injection\\|guidance set --model M\\|- --effort E\\|- --guidance on\\|off; status --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-S04","domain":"settings","baseline":"UNKNOWN","status":"pending","unit":"wp5","evidence":[],"task":"set-S04 — Set delegation mode and editable proactive hint","existingCli":"v2 mode v1\\|default\\|v2; v2 mode-hint TEXT; v2 mode-hint --clear; v2 status (local)","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-S05","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-S05 — Ask for delegation model recommendation, then separately apply","existingCli":"agent injection suggest WORK [--model SIZING_MODEL] [--apply] --json; agent injection set --model M --effort E","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-K01","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-K01 — Inspect/filter/paginate compatibility verdicts and subjects","existingCli":"lab status; lab verdicts --subject --layer --suite --verdict --limit --cursor; lab subjects --limit --cursor --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-K02","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-K02 — Inspect one verdict's evidence lineage and production context","existingCli":"lab subject I; observations --subject I --layer L --suite T --limit --cursor; event I; artifact D; production-signals --subject I --limit --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-K03","domain":"settings","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"set-K03 — Filter protocol pairs and view community trust context","existingCli":"lab subject I --json; lab public community --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-K04","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-K04 — Inspect provider upstream wire/protocol and conversion plan","existingCli":"api protocols [--provider P] --json; api explain --model M --inbound PROTOCOL [--feature F] --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-K05","domain":"settings","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"set-K05 — Control protocol exposure/rollout","existingCli":"api policy --messages on\\|off --unrepresentable legacy\\|reject --rollout SWITCH=on\\|off ... --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"ops-D01","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp7","evidence":[],"task":"ops-D01 — Read live health/version/uptime and provider overview; `gui/src/pages/dashboard-core-poll.ts:275`","existingCli":"status --json; health --json; system status --json","sourceInventory":"005_operations_coverage.md","disposition":"Included task; target/contract resolved in operational crux decision."}, + {"id":"ops-D02","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D02 — Read model catalog and 30d usage; `gui/src/pages/dashboard-core-poll.ts:135`, `:142`","existingCli":"models live --json; usage --range 30d --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D03","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D03 — Read runtime/client preferences; `gui/src/pages/dashboard-core-poll.ts:218`","existingCli":"system settings --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D04","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D04 — Set Codex autostart; `gui/src/pages/use-dashboard-data.ts:753`, `:777`","existingCli":"system settings --auto-start on/off --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D05","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D05 — Set Desktop authless / client compaction; `gui/src/pages/use-dashboard-data.ts:768`, `:778`","existingCli":"system settings --desktop-authless on/off --client-compaction on/off --json; then system sync --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D06","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D06 — Sync client catalogs/configuration; `gui/src/pages/use-dashboard-data.ts:790`, `:796`","existingCli":"system sync --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D07","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D07 — Read project-config warnings; `gui/src/pages/dashboard-core-poll.ts:126`","existingCli":"system diagnostics --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D08","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D08 — Read startup protection; `gui/src/pages/dashboard-core-poll.ts:104`; `gui/src/pages/Startup.tsx:140`","existingCli":"system startup health/status --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D09","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D09 — Read memory/storage pressure and active turns; `gui/src/components/MemoryObservabilityCard.tsx:243`","existingCli":"observe memory --json; memory --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D10","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-D10 — Drain and restart proxy; `gui/src/components/MemoryObservabilityCard.tsx:359`","existingCli":"restart","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D11","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D11 — Check latest/preview package update; `gui/src/pages/use-dashboard-data.ts:824`","existingCli":"system update check --channel latest/preview --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D12","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D12 — Run package update, optionally restart; `gui/src/pages/use-dashboard-data.ts:909`","existingCli":"system update run --channel latest/preview --restart on/off --yes --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D13","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D13 — Observe update job; `gui/src/pages/use-dashboard-data.ts:493`","existingCli":"system update status JOB-ID --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D14","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-D14 — Desktop-shell update navigation; `gui/src/pages/use-dashboard-data.ts:6` (openDesktopUpdatePage dependency), `gui/src/pages/dashboard-overview-sections.tsx:220`","existingCli":"Desktop update UI panel","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D15","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"ops-D15 — Web search sidecar off/on/model/stream; `gui/src/pages/dashboard-overview-sections.tsx:585`, `:606`; save `gui/src/pages/use-dashboard-data.ts:563`","existingCli":"agent sidecar web --model ID --backend BACKEND --enabled on/off --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D16","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp5","evidence":[],"task":"ops-D16 — Vision sidecar off/on/model/reasoning/limits/timeout; `gui/src/pages/dashboard-overview-sections.tsx:467`, `:480`, `:628`, `:648`","existingCli":"agent sidecar vision --model ID --backend BACKEND --reasoning LEVEL --max-descriptions N --enabled on/off --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D17","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-D17 — Shadow-call interception toggle/model; `gui/src/pages/dashboard-overview-sections.tsx:716`, `:728`; save `gui/src/pages/use-dashboard-data.ts:610`","existingCli":"models shadow status --json; models shadow set MODEL --enabled on/off --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-D18","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp8","evidence":[],"task":"ops-D18 — Multi-agent mode/advisory, injection/guidance/defaults, effort caps; `gui/src/pages/use-dashboard-data.ts:640`, `:679`, `:727`; `gui/src/pages/dashboard-overview-sections.tsx:78`, `:103`","existingCli":"v2; agent injection/effort/subagents/roles","sourceInventory":"005_operations_coverage.md","aliasOf":["set-M13","set-S03","set-S04","set-S01","set-S02","set-S06","set-S07"]}, + {"id":"ops-S01","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-S01 — Install service / repair service / install shim; `gui/src/pages/Startup.tsx:290`, `:294`","existingCli":"service install; service repair; codex-shim install; system startup install-service/install-shim --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-S02","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-S02 — Windows tray status; `gui/src/pages/Startup.tsx:176`","existingCli":"tray status --json; inspect windows-tray --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-S03","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-S03 — Windows tray install/start/stop/uninstall; `gui/src/pages/Startup.tsx:268`","existingCli":"tray install/start/stop/uninstall --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-S04","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-S04 — Connected-machine shim status/install/repair/uninstall; `gui/src/pages/Startup.tsx:97`, `:104`","existingCli":"codex-shim status/install/uninstall","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-S05","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp2","evidence":[],"task":"ops-S05 — Read connected-machine selected clients / sync them; `gui/src/pages/Integrations.tsx:62`, `:72`","existingCli":"sync on connected machine","sourceInventory":"005_operations_coverage.md","disposition":"Existing status selectedClients and syncConnectedClient are the same GUI task; discovery proof."}, + {"id":"ops-C01","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-C01 — Read Claude Code effective state/model choices; `gui/src/pages/ClaudeCode.tsx:88`","existingCli":"claude config status --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-C02","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-C02 — Enable/disable Claude connection immediately; `gui/src/pages/ClaudeCode.tsx:166`; `gui/src/pages/use-claude-connection.ts:2`","existingCli":"integration native claude on/off --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-C03","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-C03 — Enable/disable CLI first-party proxy environment; `gui/src/pages/ClaudeCode.tsx:178`","existingCli":"claude config set --first-party on/off --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-C04","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-C04 — Save Code behavior/auth/env/model mappings/helpers; `gui/src/pages/ClaudeCode.tsx:217`","existingCli":"claude config set --enabled --auth-mode --system-env --fast-mode --auto-context --compact-window --inject-agents --small-fast-model --model-map --web-model --web-backend --vision-model --vision-backend","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-C05","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-C05 — Start configured Claude intercept; `gui/src/components/ClaudeInterceptStart.tsx:18`","existingCli":"claude intercept start --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-C06","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp6","evidence":[],"task":"ops-C06 — Read Desktop editable profile/catalog and applied health; `gui/src/pages/ClaudeDesktop.tsx:270`, `:354`","existingCli":"claude desktop status --json; claude desktop show --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-C07","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp6","evidence":[],"task":"ops-C07 — Edit Desktop assignment family/alias/default and save; `gui/src/pages/ClaudeDesktop.tsx:24`, `:418`, `:806`, `:826`","existingCli":"claude desktop move ROUTE FAMILY [--default]; default FAMILY ROUTE-or-none; import FILE","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-C08","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-C08 — Save then apply Desktop first-party/gateway; `gui/src/pages/ClaudeDesktop.tsx:433`","existingCli":"claude desktop apply --first-party; apply --gateway","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-C09","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-C09 — Bind/unbind native picker ID to route; `gui/src/components/ClaudeFirstPartyBindings.tsx:59`","existingCli":"claude desktop bind PICKER-ID ROUTE; unbind PICKER-ID","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-C10","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-C10 — Enable/disable Desktop picker proxy; `gui/src/components/ClaudeDesktopPicker.tsx:97`","existingCli":"claude desktop picker status/on/off","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-C11","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-C11 — Export Desktop profile JSON; `gui/src/pages/ClaudeDesktop.tsx:468`","existingCli":"claude desktop export PATH-or-dash","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-C12","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp6","evidence":[],"task":"ops-C12 — Import Desktop profile JSON; `gui/src/pages/ClaudeDesktop.tsx:480`","existingCli":"claude desktop import FILE [--apply]","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-G01","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-G01 — Read Grok fence/catalog/status; `gui/src/pages/Grok.tsx:81`","existingCli":"grok status/show --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-G02","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-G02 — Save included/excluded Grok model selection; `gui/src/pages/Grok.tsx:151`","existingCli":"grok set/include/exclude CSV --json; grok clear --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-G03","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-G03 — Save and apply Grok fence; `gui/src/pages/Grok.tsx:171`","existingCli":"grok set CSV --json; then grok apply --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I01","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-I01 — List native integration desired/observed state; `gui/src/pages/integrations/native-api.ts:144`; overview `IntegrationsOverview.tsx:605`","existingCli":"integration native list --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I02","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-I02 — Toggle native Grok / Codex / Claude Desktop; `gui/src/pages/integrations/native-api.ts:155`; overview `IntegrationsOverview.tsx:604`","existingCli":"integration native grok/codex/claude-desktop on/off --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I03","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-I03 — List file-client state / inspect one; `gui/src/pages/integrations/integration-api.ts:435`, `:441`","existingCli":"integration client status/list/show [--client ID] --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I04","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp6","evidence":[],"task":"ops-I04 — Preview apply / overwrite / disable; `gui/src/pages/integrations/FileIntegrationPage.tsx:219`; `integration-api.ts:475`","existingCli":"Existing apply/disable at I05","sourceInventory":"005_operations_coverage.md","disposition":"Included preview task; interactive-preview exemption is not a consent prohibition."}, + {"id":"ops-I05","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-I05 — Apply / overwrite conflicting config / disable owned block; `gui/src/pages/integrations/FileIntegrationPage.tsx:251`; `integration-api.ts:512`","existingCli":"integration client enable/disable --client ID [--overwrite-conflict] --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I06","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp6","evidence":[],"task":"ops-I06 — Set/clear per-model Droid reasoning defaults; `gui/src/pages/integrations/DroidReasoningDefaultsPanel.tsx:27`, `:38`","existingCli":"integration client enable --client droid","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I07","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-I07 — Read rollback journal; `gui/src/pages/integrations/integration-api.ts:454`","existingCli":"integration client history/journal [--client ID] --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I08","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp6","evidence":[],"task":"ops-I08 — Preview rollback, including drift-confirmed retry; `gui/src/pages/integrations/RestoreDialog.tsx:143`; `integration-api.ts:496`","existingCli":"integration client restore --op ID [--confirm-drift]","sourceInventory":"005_operations_coverage.md","disposition":"Included preview task; interactive-preview exemption is not a consent prohibition."}, + {"id":"ops-I09","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-I09 — Restore rollback snapshot; `gui/src/pages/integrations/RestoreDialog.tsx:191`; `integration-api.ts:543`","existingCli":"integration client restore --op ID [--confirm-drift] --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I10","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp6","evidence":[],"task":"ops-I10 — Retire older rollback entry/snapshot; `gui/src/pages/integrations/FileIntegrationPage.tsx:446`; overview `IntegrationsOverview.tsx:851`; `integration-api.ts:571`","existingCli":"history and restore only","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I11","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-I11 — Disable all eligible file integrations; `gui/src/pages/integrations/IntegrationsOverview.tsx:443`, `:460`, `:512`","existingCli":"Repeat integration client disable --client ID for explicit set","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I12","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-I12 — List Aside profiles / read one / toggle selected profile; `gui/src/pages/integrations/AsideProfilesPage.tsx:54`, `:89`, `:116`; `integration-api.ts:424`","existingCli":"integration client status/enable/disable --client aside --profile N --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I13","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp6","evidence":[],"task":"ops-I13 — Aside profile rollback list/preview/restore/retire; `gui/src/pages/integrations/integration-api.ts:465`, `:503`, `:550`, `:585`","existingCli":"history --client aside --profile N; restore --client aside --profile N --op ID [--confirm-drift]","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I14","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp6","evidence":[],"task":"ops-I14 — Refresh all server-selected Aside profiles; `gui/src/pages/integrations/aside-profile-api.ts:38`","existingCli":"sync reaches refreshAsideProfilesThroughServer","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I15","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp6","evidence":[],"task":"ops-I15 — Inspect Cursor installed builds/gateway/last-seen state; `gui/src/pages/integrations/CursorIntegrationPage.tsx:113`; `cursor-api.ts:34`","existingCli":"integration native list/on/off; Cursor advertised only","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-I16","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp6","evidence":[],"task":"ops-I16 — Check advertised Cursor local installer; `gui/src/pages/integrations/CursorIntegrationPage.tsx:81`; `cursor-api.ts:59`","existingCli":"No Cursor installer-read command","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O01","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-O01 — Read debug flags/env/runtime overrides; `gui/src/pages/Debug.tsx:48`","existingCli":"observe debug --json; debug SCOPE status","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O02","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-O02 — Toggle provider/usage/injection/Claude inbound capture; `gui/src/pages/Debug.tsx:180`, `:210`","existingCli":"debug provider/usage/injection/claude on/off","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O03","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-O03 — Reset all capture overrides to env; `gui/src/pages/Debug.tsx:213`","existingCli":"debug provider reset; debug usage reset; debug injection reset; debug claude reset","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O04","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp7","evidence":[],"task":"ops-O04 — Read/follow provider, usage, injection debug buffers; `gui/src/pages/Debug.tsx:97`, `:115`","existingCli":"debug provider logs -f; debug usage logs -f; observe injection --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O05","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-O05 — Read Claude inbound metadata captures; `gui/src/pages/Debug.tsx:65`","existingCli":"observe claude-inbound --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O06","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp7","evidence":[],"task":"ops-O06 — Read/retry/incrementally poll request log; `gui/src/pages/Logs.tsx:614`","existingCli":"logs --limit 2000 --json; logs --follow --jsonl","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O07","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-O07 — Filter log snapshot by surface/model/provider/status/time/speed/interception/conversation/protocol; `gui/src/pages/Logs.tsx:728`; `gui/src/pages/logs-filter.ts:16`, `:103`","existingCli":"logs has provider/model/status/conversation/account filters","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O08","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp7","evidence":[],"task":"ops-O08 — Read usage by preset/custom window, surface and local-machine attribution; `gui/src/pages/Usage.tsx:1110`","existingCli":"usage --range --surface --since --until --provider --model --json","sourceInventory":"005_operations_coverage.md","disposition":"Included task; target/contract resolved in operational crux decision."}, + {"id":"ops-O09","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-O09 — Model text search, expand rows, tab and chart display; `gui/src/pages/Usage.tsx:1093`; chart components","existingCli":"No CLI task needed","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O10","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-O10 — Read companion preferences/presence; `gui/src/pages/usage-companion-panel.tsx:215`; Tray `gui/src/pages/Tray.tsx:100`","existingCli":"companion show --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O11","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-O11 — Persist companion model/provider visibility and chart/menu appearance; `gui/src/pages/usage-companion-panel.tsx:302`, `:503`","existingCli":"companion set KEY=VALUE ... --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O12","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-O12 — Restore companion defaults (including corrupt-state recovery); `gui/src/pages/usage-companion-panel.tsx:350`","existingCli":"companion reset --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O13","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp7","evidence":[],"task":"ops-O13 — Read usage timeline for companion/chart/tray; `gui/src/pages/usage-companion-panel.tsx:257`; `gui/src/pages/Tray.tsx:118`","existingCli":"companion show/set/reset only","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O14","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-O14 — Open companion view in system browser; `gui/src/pages/usage-companion-panel.tsx:367`","existingCli":"No standalone operator equivalent required","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-O15","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp8","evidence":[],"task":"ops-O15 — Tray refresh totals/accounts/quota; `gui/src/pages/Tray.tsx:79`, `:86`, `:104`; `gui/src/pages/tray-data.ts:27`","existingCli":"usage/companion show plus account read families","sourceInventory":"005_operations_coverage.md","aliasOf":["set-A01","set-P09","set-P12","set-P14","ops-O08","ops-O10","ops-O13"]}, + {"id":"ops-O16","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp8","evidence":[],"task":"ops-O16 — Tray switch current account/key; `gui/src/pages/Tray.tsx:39`; `gui/src/pages/tray-data.ts:36`","existingCli":"Account selection families in inventory-cli.md","sourceInventory":"005_operations_coverage.md","aliasOf":["set-A04","set-P12","set-P14"]}, + {"id":"ops-T01","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-T01 — Inspect storage sizes/categories/Log Guard state; `gui/src/pages/Storage.tsx:1358`","existingCli":"storage report --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-T02","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-T02 — Preview oldest archived-session cleanup percentage; `gui/src/pages/Storage.tsx:177`","existingCli":"storage cleanup --percent N --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-T03","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-T03 — Quarantine / permanently delete previewed archives; `gui/src/pages/Storage.tsx:201`","existingCli":"storage cleanup --percent N --mode quarantine/permanent --yes --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-T04","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-T04 — List quarantine batches; `gui/src/pages/Storage.tsx:392`","existingCli":"storage trash list --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-T05","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-T05 — Restore a quarantine batch; `gui/src/pages/Storage.tsx:431`","existingCli":"storage trash restore ENTRY-ID --yes --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-T06","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-T06 — Read policy/job; `gui/src/pages/Storage.tsx:672`, `:865`","existingCli":"storage policy show --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-T07","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp6","evidence":[],"task":"ops-T07 — Enable/disable recurring cleanup / save threshold, target, schedule, mode; `gui/src/pages/Storage.tsx:709`, `:738`","existingCli":"storage policy set --enabled --percent --mode --schedule --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-T08","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-T08 — Run cleanup policy now; `gui/src/pages/Storage.tsx:790`, `:809`","existingCli":"storage policy set EXISTING-FIELDS; policy run --yes --json; policy show --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-T09","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-T09 — Inspect log protection fresh; `gui/src/components/storage-workspace/StorageWorkspace.tsx:515`","existingCli":"storage codex-logs status --json; observe storage codex-logs status --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-T10","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-T10 — Protect logs compat / quiet; `gui/src/components/storage-workspace/StorageWorkspace.tsx:251`, `:261`, `:460`","existingCli":"storage codex-logs protect --mode compat/quiet --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-T11","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-T11 — Remove log protection / repair protection / compact logs; `gui/src/components/storage-workspace/StorageWorkspace.tsx:440`, `:463`","existingCli":"storage codex-logs unprotect/repair/compact --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K01","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-K01 — List access keys/usage/pending rotations, endpoints, auth matrix, API/audio surfaces; `gui/src/pages/ApiKeys.tsx:155`","existingCli":"access key list --json; access endpoints --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K02","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-K02 — Create key with name; `gui/src/pages/ApiKeys.tsx:268`","existingCli":"access key create NAME --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K03","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp7","evidence":[],"task":"ops-K03 — Rename key; `gui/src/pages/ApiKeys.tsx:327`","existingCli":"access key set edits scopes only","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K04","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-K04 — Revoke key; `gui/src/pages/ApiKeys.tsx:302`","existingCli":"access key remove ID --yes --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K05","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-K05 — Start rotation; `gui/src/pages/ApiKeys.tsx:349`","existingCli":"access key rotate ID --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K06","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-K06 — Commit rotation / abort rotation; `gui/src/pages/ApiKeys.tsx:371`","existingCli":"access key rotate commit ID ROTATION-ID --json; rotate abort ID ROTATION-ID --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K07","domain":"operations","baseline":"DISCOVERY_ONLY","status":"pending","unit":"wp2","evidence":[],"task":"ops-K07 — Read public external-model catalog; `gui/src/pages/ApiKeys.tsx:192`","existingCli":"access models --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K08","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp7","evidence":[],"task":"ops-K08 — Test newly created key on Responses / Chat / Messages for selected model; `gui/src/pages/ApiKeys.tsx:443`, `:456`","existingCli":"access test MODEL --protocol responses/chat/messages --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K09","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-K09 — Read generated client configuration / copy snippet; `gui/src/components/apikeys-workspace/ClientConfigRow.tsx:53`","existingCli":"inspect client-config --client ID --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K10","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-K10 — Toggle public Messages API; `gui/src/pages/api-surface-cards.tsx:52`","existingCli":"api policy --messages on/off --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K11","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-K11 — Preview model's protocol path/features; `gui/src/components/protocols/ProtocolPlanPanel.tsx` → `gui/src/protocol-api.ts:91`","existingCli":"api explain --model ID --inbound responses/chat/messages --feature FEATURE [repeated] --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-K12","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp7","evidence":[],"task":"ops-K12 — Dictation file upload and cancel; `gui/src/components/apikeys-workspace/AudioApiPanel.tsx:2`; `gui/src/audio-api-client.ts:13`","existingCli":"No scoped audio CLI identified in supplied CLI inventory","sourceInventory":"005_operations_coverage.md","disposition":"Included task; target/contract resolved in operational crux decision."}, + {"id":"ops-K13","domain":"operations","baseline":"UNKNOWN","status":"pending","unit":"wp7","evidence":[],"task":"ops-K13 — Live voice connect/disconnect probe; `gui/src/audio-api-client.ts:88`","existingCli":"No scoped live-audio probe identified in supplied CLI inventory","sourceInventory":"005_operations_coverage.md","disposition":"Included task; target/contract resolved in operational crux decision."}, + {"id":"ops-K14","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-K14 — Download generated client configuration; `gui/src/components/apikeys-workspace/ClientConfigPanel.tsx:78`","existingCli":"export --client ID --out PATH [--force] [--json]","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-R01","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp6","evidence":[],"task":"ops-R01 — Hub devices/runtime availability/session status; `gui/src/pages/RemoteWorkspace.tsx:93`","existingCli":"remote-workspace status is executor-local","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-R02","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-R02 — Create device enrollment code; `gui/src/pages/RemoteWorkspace.tsx:172`","existingCli":"remote-workspace pair consumes enrollment code","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-R03","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-R03 — Start hub model session on selected remote root; `gui/src/pages/RemoteWorkspace.tsx:184`","existingCli":"No CLI proposed","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-R04","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-R04 — Submit prompt to bound session; `gui/src/pages/RemoteWorkspace.tsx:208`","existingCli":"No CLI proposed","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-R05","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-R05 — Stop session; `gui/src/pages/RemoteWorkspace.tsx:243`","existingCli":"No CLI proposed","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-R06","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-R06 — Revoke device and stop its sessions; `gui/src/pages/RemoteWorkspace.tsx:256`","existingCli":"No CLI proposed","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-R07","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp6","evidence":[],"task":"ops-R07 — Read individual Hub runtimes/sessions endpoints","existingCli":"No Hub runtime/session list command","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-L01","domain":"operations","baseline":"COMPLETE","status":"pending","unit":"wp2","evidence":[],"task":"ops-L01 — Read link topology/status; `gui/src/pages/RemoteLink.tsx:186`","existingCli":"link status --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-L02","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-L02 — Discover/rescan SSH aliases; `gui/src/pages/RemoteLink.tsx:262`","existingCli":"No CLI proposed","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-L03","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-L03 — Probe host key; `gui/src/pages/RemoteLink.tsx:282`","existingCli":"No CLI proposed","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-L04","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-L04 — Accept shown fingerprint and validate remote OCX; `gui/src/pages/RemoteLink.tsx:298`","existingCli":"No CLI proposed","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-L05","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-L05 — Home adds child; `gui/src/pages/RemoteLink.tsx:313`","existingCli":"link issue is existing lower-level admin primitive","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-L06","domain":"operations","baseline":"EXCLUDED","status":"pending","unit":"wp8","evidence":[],"task":"ops-L06 — Standalone child joins Home and restarts; `gui/src/pages/RemoteLink.tsx:333`","existingCli":"No CLI proposed","sourceInventory":"005_operations_coverage.md"}, + {"id":"ops-L07","domain":"operations","baseline":"IMPLEMENTATION_GAP","status":"pending","unit":"wp6","evidence":[],"task":"ops-L07 — Disconnect link / force-remove after remote cleanup failure; `gui/src/pages/RemoteLink.tsx:371`, `:422`","existingCli":"link revoke --link-id ID --json","sourceInventory":"005_operations_coverage.md"}, + {"id":"set-S06","task":"Memory extraction and consolidation model settings","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","existingCli":"No dedicated live block writer","sourceInventory":"gui/src/pages/dashboard-overview-panels.tsx:24; gui/src/components/MemoryModelsPanel.tsx:111","evidence":[],"unit":"wp5"}, + {"id":"set-S07","task":"Compaction route model, effort, triggers and source scope","domain":"settings","baseline":"IMPLEMENTATION_GAP","status":"pending","existingCli":"No dedicated live block writer","sourceInventory":"gui/src/pages/dashboard-overview-panels.tsx:23; gui/src/components/CompactionRoutingPanel.tsx:180","evidence":[],"unit":"wp5"} + ] +} diff --git a/devlog/_plan/261003_cli_gui_parity/009_roadmap_lock.md b/devlog/_plan/261003_cli_gui_parity/009_roadmap_lock.md new file mode 100644 index 00000000000..7b264cf297b --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/009_roadmap_lock.md @@ -0,0 +1,9 @@ +# wp0 roadmap lock + +The source-audited CLI parity roadmap is locked for implementation. It assigns 178 GUI task-entry rows, including explicit aliases/exclusions, to eight executable work phases and six manual PR layers. No production source was changed in wp0. + +Whole-plan architecture reflection passed at a095a4e514d6d8e5a37dbf05a66b2c9156ebaeeb28a8e0fb878bc76f931c27b1. The later bounded key-test contract received the same architect's ALIGNED reflection at be1f17444ce9d83b230ee8ab33bf9e5357623a5fef77f27134eb39062448031f. Exact metadata JSON projection ownership was made explicit. Both independent plan reviews ended PASS after their recorded amendments; detailed analysis stays in ignored task scratch. + +Verification before implementation: docs checker validates all eight phase specs, 178 unique IDs, phase/alias ownership, source anchors and document bounds. Existing baseline contract tests/typecheck/structure/generated surface results are recorded in 003; they are not evidence that future commands work. Independent reviewers additionally verified selected existing resolver/parser/GUI fixture contracts with no live targets. + +Next: wp1 revalidates 010 against the latest integration base, then implements pure discovery and generated-document capacity. Every later phase keeps its assigned functionality and evidence obligations. No source implementation, PR publication or final product completion is claimed by this roadmap lock. diff --git a/devlog/_plan/261003_cli_gui_parity/010_discovery_foundation.md b/devlog/_plan/261003_cli_gui_parity/010_discovery_foundation.md new file mode 100644 index 00000000000..35616c7289d --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/010_discovery_foundation.md @@ -0,0 +1,45 @@ +# wp1 — Keep discovery pure and make room for complete task documentation + +Depends on wp0. Class C3. Layer 1. No management behavior or user-state changes. Outcome: the existing 74 declarations remain compatible while metadata, exact usage and generated chapters can grow without breaking import or file-size boundaries. + +## Exact change map + +| Kind | Path | Before → after | +| --- | --- | --- | +| NEW | src/cli/capability-types.ts | Move CapabilityRoute, CapabilityFlag, CapabilityJsonMode, Capability and HeadCapability declarations here; add only optional readonly usage?: string. No runtime imports. | +| NEW | src/cli/capabilities-base.ts | Move existing HEAD_CAPABILITIES and CAPABILITIES literal data byte-faithfully; type-only imports from capability-types. No handler/config/Lab dependencies. | +| MODIFY | src/cli/capabilities.ts | Preserve public type/function/array export names and existing order. Aggregate/re-export pure data only. capabilityInvocation remains canonical token joining; exact usage is a separate rendering concern. | +| MODIFY | src/cli/capabilities-command.ts | Its explicit JSON projection currently drops unknown metadata fields. Add usage only when cap.usage is defined; preserve every existing field and no-usage shape. | +| MODIFY | src/cli/help.ts | For a leaf with usage, render its exact Usage line and omit only that leaf's incomplete-operand warning. With no usage, preserve existing Command/partial-grammar output exactly. Matching and aliases stay in help-catalog. | +| MODIFY | scripts/generate-ocx-skill-surface.ts | Export deterministic renderManagementSurfaces() returning a filename→text map; retain renderManagementSurface() as the index renderer for existing callers. Write/check compact 01_management_surface.md plus flat 01_surface_.md chapters. Canonical capability headings do not change; optional usage appears beneath. | +| MODIFY | tests/cli/cli-capabilities.test.ts | Replace the no-relative-import syntax assertion with a stronger transitive pure-data allowlist boundary; no command/config/Lab import, dynamic import or unexpected dependency. Preserve all rendering/route/debt assertions. | +| NEW | tests/cli/cli-capability-data.test.ts | Exercise graph refusal fixtures, type-only edges, optional usage JSON/rendering compatibility, aliases and default output. Exercise runCapabilities --json itself with an explicit usage fixture; a helper-only rendering check cannot certify serializer propagation. | +| MODIFY | tests/ci-workflows/skill-ocx.test.ts | Compare every generated file to its owner map; index links resolve; every capability appears once across chapters. Scan all shipped references for command/consent rules, not only the old five-file list. | +| NEW | structure/cli-management.md | Move existing CLI help/capability/management-client contracts from runtime into this owner; preserve factual content and links. Describe pure metadata and generated chapter contract after it exists. | +| MODIFY | structure/runtime.md, structure/manifest.json, structure/INDEX.md | Replace moved prose with explicit owner links; add Tier 5 CLI doc with src/cli ownership and regenerate index. Do not raise 600-line cap or describe unbuilt phases as implemented. | +| MODIFY/NEW | skills/ocx/references/01_management_surface.md, 01_surface_.md, skills/ocx/SKILL.md | Index/domain navigation replaces one growing generated blob. Remove 'safe at any time' blanket claims; distinguish non-config-mutating probes from cost-free observation. | + +Chapter domains are stable command-family groups: lifecycle, providers-models, accounts, agents-routing, integrations, observe-system, access-remote, lab. Resolve each root into exactly one group; unknown roots fail generation instead of disappearing. The index includes all canonical invocation links and derived counts. Generated filenames are a closed owner-produced set; check fails for missing/stale content. No arbitrary filesystem cleanup. + +## Field chain and safeguards + +usage literals → pure typed metadata → additive capabilities JSON → help and generated reference. No persisted deserializer is introduced. Existing omissions serialize as before. Help consumers do not import execution modules. Metadata purity is a test-time static import-graph assertion (E3), not a sandbox: dynamic evaluated code can evade a naive scanner, so disallow dynamic imports/require in these modules and keep literal-data review. Runtime enforcement layer: none; wording is 'checked dependency boundary'. + +## Acceptance + +- Original capability/HEAD JSON is identical except intentionally absent optional fields; count/order/root aliases unchanged. +- A verified usage leaf renders operands; a legacy leaf retains exact prior help; alias resolution and recovery destinations stay canonical. +- A synthetic data module importing a handler/config/Lab fails the graph guard; legal data/type edges pass. +- Regeneration then --check succeeds; a changed/missing generated chapter fails; counts derive from arrays, never handwritten totals. +- All generated chapters <2000 lines and structure docs ≤600; existing source caps are unchanged. +- Focused commands: baseline four contract files plus new cli-capability-data and existing cli-help-paths/navigation/recovery files. No GUI render/build needed for this code-free visual surface. + +## Shared completion contract + +This phase follows 002_terminal_ux.md and 003_verification_strategy.md. Main owns registry/dispatch integration, layout-map registration, generated output and Git branch state; executor write scopes are disjoint and named before B. Existing method/path/body semantics come from the referenced source inventories, not endpoint-name guessing. + +Update the phase's capability domain, generated references, relevant public CLI pages and owning structure contracts in the same layer. Every new test file enters scripts/test-layout/layout.json and tests/fixtures/test-layout-expected.json. Existing tests are retained; no baseline cap increases or green-on-retry acceptance. + +Planned new test paths below become executable verification only after B creates them. The current baseline gates in 003 have actually run. C invokes the exact focused files, typecheck, structure and skill-surface checks, privacy where data is handled, a source-bound cxc receipt and real isolated CLI QA (stdout/stderr/exit/teardown). A successful function mock is transport proof only; relevant existing server tests or isolated real handlers verify accepted state. No live user proxy, credentials or upstream requests. + +Before P>A, revalidate this document against the parent layer and record the prior D conclusion. Consult an architect for actual decision changes; independent A review is separate. C must preserve saved-versus-applied/refused outcomes. D records exact checks and ledger evidence before the next cycle. Publishing is main-owned; this request stops at open PRs. diff --git a/devlog/_plan/261003_cli_gui_parity/020_existing_workflow_discovery.md b/devlog/_plan/261003_cli_gui_parity/020_existing_workflow_discovery.md new file mode 100644 index 00000000000..3ab07e527bc --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/020_existing_workflow_discovery.md @@ -0,0 +1,33 @@ +# wp2 — Declare the operational CLI that already exists + +Depends on wp1. Class C3. Finish layer 1. Outcome: users/agents can discover existing task-specific verbs and exact operands without reverse-engineering source, while false route claims are removed rather than propagated. + +## Exact change map + +NEW pure data leaves: src/cli/capabilities-provider-models.ts, capabilities-accounts.ts, capabilities-agents-routing.ts, capabilities-integrations.ts, capabilities-observe-system.ts, capabilities-access-remote.ts, capabilities-lab.ts. MODIFY capabilities-base.ts and capabilities.ts to move ownership once and aggregate each command exactly once. Leaves import only Capability types, never handlers. Preserve relative ordering of existing entries where possible; do not hide duplicates through last-wins merging. + +Use the command/route/flag matrix in the source inventory and 004/005: provider edit/test/quota/presets/account-mode/selected; models live/edit/visibility/selected/presets/new-policy/context/shadow; alias; combo CRUD; route-policy reads; account/current/switch/auth and policy leaves; agent and v2; client/Desktop/Grok operations; storage/debug/usage/system; access/remote and actual local Lab commands. Internal/hidden executables remain excluded. Only implemented leaves are declared in this phase; later missing actions are not advertised early. + +MODIFY src/cli/registry.ts and help.ts to remove the incorrect 'read-only Lab' description and reflect supported public groups. No new handler dispatch is introduced. Exact usage strings come from inspected handlers; flags which take values remain distinct from booleans. Add details for local versus management transport, user confirmation, caller-spend probes and safe read-back sequences. + +MODIFY src/server/management/route-registry.ts and tests/cli/cli-capabilities.test.ts only with evidence: shrink declaration debt when real HTTP calls are registered; do not invent HTTP calls for local provider/custom-model/Lab commands. Correct stale Lab 'no CLI' reasons to the actual local equivalent or narrower remaining runtime debt. Temporarily mark the falsely advertised timeline/Cursor routes as owned deferred work (wp6/wp7, these tracked phase docs), then remove that temporary debt in the implementing layer. No session-only reason is weakened. + +MODIFY skills/ocx/SKILL.md and references/02_json_shapes.md, 03_recipes.md, 04_failure_semantics.md, 05_remote_hub.md. Preserve consent/secret handoff rules. Correct incomplete discovery examples once indexed; distinguish legacy 64 usage errors, missing JSON support and local/live target semantics. Generated chapters are regenerated, not hand edited. Public docs reference/cli.md and reference/cli/{providers-accounts,agents,lifecycle}.md are the verified existing topic pages; extend the appropriate one rather than inventing a parallel root. + +NEW tests/cli/cli-capability-workflows.test.ts and tests/ci-workflows/skill-ocx-workflows.test.ts compare declared operand/flag examples with independently specified representative real handler invocations on isolated fixtures. Preserve the existing route ratchet, negative CLI argument tests and skill secret checks. Complete grammar is not proven by testing only the first word. + +## Acceptance + +Each baseline DISCOVERY_ONLY row has a canonical capability/help path and a task recipe or clear reference. Each declared management method/path is actually driven by that command; local equivalents use routes:[] plus honest transport detail. Capabilities --route works for newly indexed HTTP operations. No empty route lookup is misreported as proof of feature absence. + +Human-only and secret-returning tasks remain handoffs. No examples spend live quota, create keys, pair machines, star GitHub or copy plaintext credentials into agent transcripts. Unknown child help and --help remain offline and write-free. Metadata/skill tests, pure import boundary, route registry, structure, privacy and generated-surface check must pass before layer 1 publication. + +## Shared completion contract + +This phase follows 002_terminal_ux.md and 003_verification_strategy.md. Main owns registry/dispatch integration, layout-map registration, generated output and Git branch state; executor write scopes are disjoint and named before B. Existing method/path/body semantics come from the referenced source inventories, not endpoint-name guessing. + +Update the phase's capability domain, generated references, relevant public CLI pages and owning structure contracts in the same layer. Every new test file enters scripts/test-layout/layout.json and tests/fixtures/test-layout-expected.json. Existing tests are retained; no baseline cap increases or green-on-retry acceptance. + +Planned new test paths below become executable verification only after B creates them. The current baseline gates in 003 have actually run. C invokes the exact focused files, typecheck, structure and skill-surface checks, privacy where data is handled, a source-bound cxc receipt and real isolated CLI QA (stdout/stderr/exit/teardown). A successful function mock is transport proof only; relevant existing server tests or isolated real handlers verify accepted state. No live user proxy, credentials or upstream requests. + +Before P>A, revalidate this document against the parent layer and record the prior D conclusion. Consult an architect for actual decision changes; independent A review is separate. C must preserve saved-versus-applied/refused outcomes. D records exact checks and ledger evidence before the next cycle. Publishing is main-owned; this request stops at open PRs. diff --git a/devlog/_plan/261003_cli_gui_parity/030_provider_management.md b/devlog/_plan/261003_cli_gui_parity/030_provider_management.md new file mode 100644 index 00000000000..73834e820dd --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/030_provider_management.md @@ -0,0 +1,44 @@ +# wp3 — Add exact live provider workflows and bounded structured input + +Depends on wp2. Class C3 with C4 review for credential/destination/deletion boundaries. Layer 2. Keep server authority and offline defaults; GUI-equivalent live mutations are explicit. + +## New shared input with its first consumer + +NEW src/cli/json-input.ts: explicit path or '-' reader with a 4 MiB ceiling matching src/server/management/body.ts:9, bounded stdin deadline, EOF/error cleanup and no TTY wait. Use existing readSecretBytes for injected stdin or existing bounded-body stream utilities; payload labels/errors never include raw JSON or credentials. Decode UTF-8 strictly, allow normal UTF-8 BOM behavior, parse once, expose unknown to the domain shape validator. Duplicate/conflicting sources are rejected before reading. Composite body byte size is checked before sending. No endpoint/method selection comes from input data. + +NEW tests/cli/cli-json-input.test.ts: empty/invalid/array/BOM/multiline input, exact cap and cap+1, stdin EOF/error/deadline/TTY refusal, cleanup and no value echo. This helper ships with provider snapshot/apply, not as an unused framework. + +## Provider command contracts + +| Command | Exact behavior | +| --- | --- | +| provider add P ... --live [--json] | Resolve runtime once; load target preset when needed; POST /api/providers {name,provider,setDefault?}. Add --responses-path and --auth-mode to domain parsing. Retain explicit --force overwrite intent and document existing upsert race; no invented atomic create-only guarantee. Reject --live --sync. | +| provider set-default P --live --json | Standalone PATCH /api/providers?name=P with {setDefault:true}; server rejects disabled/unknown rows. | +| provider remove P --live --yes --json | One DELETE /api/providers?name=P; disclose default reassignment and credential/custom-model cleanup. No local pre-write, emulated two-step deletion or fallback. | +| provider edit P --upstream-http-version http1.1\|- --fast on\|off --context-window N\|- | Extend existing PATCH with upstreamHttpVersion (null clear), fastEnabled and provider contextWindow. Existing flags/omission semantics preserved. Per-model context already exists; optional repeated model-context-window only if atomic GUI update needs it. | +| provider pacing P [--json] | GET provider-request-pacing?name=P, with meaningful no-rules state. | +| provider pacing P --file FILE [--json] | PATCH only {requestPacing:}; domain rules contain enabled and optional provider/model RPM/minIntervalMs/maxConcurrentRequests. Provide common scalar flags for provider-level fields; preserve untouched rules for partial flags using one pinned read. Setting enabled:false disables pacing; per-model rules use the explicit complete rules file, not a speculative clear flag. | +| provider snapshot --json | GET /api/config and project exactly GUI editor {defaultProvider,providers}, excluding hasApiKey/hasHeaders/xaiResponsesOptInState/initialModelSelection. No secret export. | +| provider apply --baseline FILE --file FILE --json | PUT /api/providers exactly {baseline,next}; validate DTO shape, no credential/derived fields; preserve stale-baseline 409 and never auto-refresh/rebase. Removal within batch requires --yes with explicit affected scope in help. | + +MODIFY src/cli/provider.ts to route --live before local load/save, retain offline defaults and local removal refusal. Correct explicit local --sync --json: call existing syncModelsToCodex with quiet log parameter and report actual saved/synced/skipped/refused disposition; output mode must not cancel a requested effect. No false 'synced' message when stopped/failure. MODIFY provider-runtime.ts for extension dispatch only; NEW provider-lifecycle-runtime.ts, provider-settings.ts and provider-batch.ts own cohesive new behavior. RuntimeApiDeps is injectable; all multi-request workflows pin baseUrl once. + +MODIFY runtime-api.ts only for safe nested error code/message projection needed by routing/provider responses, retaining exit mapping/prose stderr. Never dump arbitrary RuntimeApiError.body. Domain failed-convergence output retains safe saved/catalog receipt rather than claiming rollback or unconditional success. + +Metadata: capabilities-provider-models.ts, registry usage and generated chapters. Structure: cli-management.md, config.md and existing provider destination contracts as affected; no provider adapter logic change. Public provider docs/skill recipes show snapshot/edit/apply/read-back and explicit live/offline distinction. + +NEW tests/cli/cli-provider-lifecycle-runtime.test.ts, cli-provider-settings.test.ts, cli-provider-batch.test.ts. MODIFY the original local provider sync JSON test to the deliberately corrected contract; retain its no-live case. Existing tests/providers/provider-config-batch-management.test.ts supplies server CAS/validation truth. + +## Acceptance + +Assert exact named requests, pinned target, zero local mutation on live refusal, wrong/missing/duplicate argument rejection before write, scalar omission/null/false/0, target preset handling and stale CAS refusal. Live deletion uses server dependency/default handling. Saved-but-unapplied receipts and missing proxy are honest. Body failures and credential-shaped data never leak. Baseline offline provider behavior stays tested. Explicit security review covers auth headers, input buffers, destination validation reuse and delete scope. + +## Shared completion contract + +This phase follows 002_terminal_ux.md and 003_verification_strategy.md. Main owns registry/dispatch integration, layout-map registration, generated output and Git branch state; executor write scopes are disjoint and named before B. Existing method/path/body semantics come from the referenced source inventories, not endpoint-name guessing. + +Update the phase's capability domain, generated references, relevant public CLI pages and owning structure contracts in the same layer. Every new test file enters scripts/test-layout/layout.json and tests/fixtures/test-layout-expected.json. Existing tests are retained; no baseline cap increases or green-on-retry acceptance. + +Planned new test paths below become executable verification only after B creates them. The current baseline gates in 003 have actually run. C invokes the exact focused files, typecheck, structure and skill-surface checks, privacy where data is handled, a source-bound cxc receipt and real isolated CLI QA (stdout/stderr/exit/teardown). A successful function mock is transport proof only; relevant existing server tests or isolated real handlers verify accepted state. No live user proxy, credentials or upstream requests. + +Before P>A, revalidate this document against the parent layer and record the prior D conclusion. Consult an architect for actual decision changes; independent A review is separate. C must preserve saved-versus-applied/refused outcomes. D records exact checks and ledger evidence before the next cycle. Publishing is main-owned; this request stops at open PRs. diff --git a/devlog/_plan/261003_cli_gui_parity/040_models_routing.md b/devlog/_plan/261003_cli_gui_parity/040_models_routing.md new file mode 100644 index 00000000000..5b8ea8630a3 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/040_models_routing.md @@ -0,0 +1,38 @@ +# wp4 — Complete model, picker, combo and policy editing + +Depends on wp3. Class C3; deletion and public routing identities receive focused C4 review. Layer 3. + +## Exact change map and contracts + +| Files | Before → after / command | +| --- | --- | +| NEW src/cli/models-custom-runtime.ts; MODIFY models.ts | `models add P M [existing metadata flags] --live --json` POSTs /api/custom-models. `models remove UUID-or-P/M --live --yes --json` resolves on the same pinned target then DELETEs UUID; no local lookup/fallback. Local add/remove gain truthful JSON save/sync receipts while retaining local behavior. | +| NEW src/cli/models-order.ts; MODIFY models-runtime.ts, models-runtime-subcommands.ts | Add `models display-name P/M --set TEXT\|--clear --json` → PUT providers/P/model-display-names {modelId,displayName:string|null}; pricing stays separate. Add `models order status`, `set --models CSV`, `set --mode default\|alphabetical\|provider\|most-used`, `reset`. Write pickerOrder/pickerOrderMode, never featured models. NEW src/cli/model-picker-ordering.ts implements the pure projection grounded in gui/src/model-picker-order.ts:43-92; do not import GUI runtime source into shipped CLI. Known independent sorting fixtures and a test-only GUI/CLI conformance comparison guard the deliberate duplicate projection. Default/reset sends pickerOrder:null and pickerOrderMode:null. Other modes derive a complete order from pickerAvailable plus exact observed identities; most-used fetches all/all usage and refuses usageIncomplete:true. Manual writes preserve featured-prefix constraints and reject ambiguous identities. Preserve native/routed public identities. | +| MODIFY src/server/management/route-registry.ts | Declare implemented model-display-names PUT with correct regex mechanism/module. Do not change the endpoint. | +| NEW src/cli/route-policy-write.ts; MODIFY route-policy.ts | `route policy create I --file PROFILE --json` PUTs {id,mode:create,profile}. update requires explicit --expected-revision copied from show; never silently reads a fresh revision or retries conflict. remove requires --yes and DELETE query id. Domain profile file covers alias/candidates/require/optimize/limits/unknownEvidence/compatibility, using existing validation. | +| MODIFY src/cli/combo.ts (extract combo-input.ts if needed) | Extend set with --image-input auto\|disabled, --reasoning-effort-mode strict\|adaptive, --targets-file FILE and explicit native-alias off while retaining bare legacy flag. Targets preserve reasoningEfforts/modelProfile/lastResort and ordering. Omitted fields remain omitted; defaultEffortMode and reasoningEffortMode stay distinct. | +| NEW src/cli/combo-stats.ts; wire combo.ts | `combo stats I --range 7d\|30d\|all --json` GET /api/usage with jev=1, comboId, range; show actual decisions/savings and incomplete evidence, not generic model usage. | + +Update pure provider-models/agents-routing capabilities, exact usages, generated chapters, CLI model/routing docs and recipes; source owners cli-management/config/catalog/subagents as affected. Do not change routing evaluator/provider algorithms. + +NEW tests/cli/cli-models-custom-runtime.test.ts, cli-models-order.test.ts, cli-models-display-name.test.ts, cli-route-policy-write.test.ts, cli-combo-parity.test.ts. Use existing tests/codex-integration/model-display-names-management-api.test.ts, tests/routing/routing-profile-management-editor.test.ts and model metadata regressions for real handler/persistence truth. + +## Activation matrix + +- Native and routed duplicate model labels remain separate identities; encoded provider/model delimiters survive requests. +- Display reset sends null; invalid label causes zero accepted write; saved/convergence-failed response remains visible. +- Ordering shows full current order; manual/policy/default/reset match GUI semantics; most-used consumes the correct usage scope and cannot drop unranked entries. +- Revision changes between read and update produce 409/exit 5 with no automatic overwrite. Create-existing, update-missing, invalid profile and nonconfirmed delete retain distinct failures. +- Targets-file and --targets are exclusive; unsupported nested fields/invalid effort/profile are refused. Existing omitted target metadata survives partial edits; scalar effort-mode names do not alias each other. +- JEV report uses exact query and preserves missing/incomplete totals. No real decision probe/upstream request is part of tests. +- Local and live custom model branches use different temporary homes/servers; prove no wrong-target writes and preserve catalog-only versus broader local-sync receipts. + +## Shared completion contract + +This phase follows 002_terminal_ux.md and 003_verification_strategy.md. Main owns registry/dispatch integration, layout-map registration, generated output and Git branch state; executor write scopes are disjoint and named before B. Existing method/path/body semantics come from the referenced source inventories, not endpoint-name guessing. + +Update the phase's capability domain, generated references, relevant public CLI pages and owning structure contracts in the same layer. Every new test file enters scripts/test-layout/layout.json and tests/fixtures/test-layout-expected.json. Existing tests are retained; no baseline cap increases or green-on-retry acceptance. + +Planned new test paths below become executable verification only after B creates them. The current baseline gates in 003 have actually run. C invokes the exact focused files, typecheck, structure and skill-surface checks, privacy where data is handled, a source-bound cxc receipt and real isolated CLI QA (stdout/stderr/exit/teardown). A successful function mock is transport proof only; relevant existing server tests or isolated real handlers verify accepted state. No live user proxy, credentials or upstream requests. + +Before P>A, revalidate this document against the parent layer and record the prior D conclusion. Consult an architect for actual decision changes; independent A review is separate. C must preserve saved-versus-applied/refused outcomes. D records exact checks and ledger evidence before the next cycle. Publishing is main-owned; this request stops at open PRs. diff --git a/devlog/_plan/261003_cli_gui_parity/050_accounts_runtime_settings.md b/devlog/_plan/261003_cli_gui_parity/050_accounts_runtime_settings.md new file mode 100644 index 00000000000..2e735ca1b7e --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/050_accounts_runtime_settings.md @@ -0,0 +1,48 @@ +# wp5 — Complete account policy, login options and model-runtime settings + +Depends on wp4. Class C3 with scoped C4 credential/cost/ownership review. Layer 4. Existing v2/account/agent roots remain; no duplicate agent-mode family. + +## Account and auth contracts + +NEW src/cli/account-policy.ts, MODIFY account.ts/account-extended.ts/account-auth.ts only at owned dispatch/parsing seams: + +- `account pool P [--enabled on|off] [--threshold N] [--quota-window W] [--strategy S] [--sticky N] --json`: GET/PUT unified /api/pool/settings. Respect per-provider supported fields; absent fields preserved. Pool enabled is not threshold zero. Existing strategy/sticky/Anthropic per-account commands remain. +- `account auto-switch openai ACTION --account I --json`: resolve ID/alias/main, PUT /api/codex-auth/auto-switch {id,threshold}; inherit sends null. Without --account preserve existing pool scope. +- `account credits openai I on|off --json` or `account credits openai --all on|off --json`: exclusive selectors, exact /accounts/credits {id,creditsAfterLimit} or {all}. Clearly name paid-credit opt-in; display preference never implies permission. Read-back is the roster. +- `account quota-activation openai I --window W on|off --json`: PUT settings {codexQuotaAutoRefresh:{id,window,enabled}} with existing window vocabulary and no other settings changes. +- `account anthropic-reset-grants [I] --json`: GET-only existing endpoint. No consume command; session-only spend stays a GUI handoff. +- Extend account login with explicit --open-browser on|off and --add-account on|off. Omitted flags preserve prior CLI defaults, not a guessed new default. Device, account id and flow id remain distinct. No automatic human verification. +- NEW logout-command.ts, MODIFY dispatch.ts: `logout P --live --json` uses fixed runtime logout endpoint; no local credential removal before target selection or after failure. No-live retains removed/not-found behavior. No new stored credential system. + +## Runtime/model settings contracts + +NEW src/cli/agent-settings.ts and v2-runtime.ts; MODIFY agent.ts, system-command.ts, v2.ts and dispatch/registry where needed: + +- system settings adds --show-codex-credits, --account-picker, --main-account-hard-lock, --ultra-fast-tier, --fast-rows booleans mapped to existing keys only. Provider Fast is separate. +- agent injection/guidance adds --sync-codex-defaults on|off, preserving model/effort/null semantics and normalized returned state. +- agent sidecar web adds --stream-routed-output; vision adds --timeout-ms. Partial fields must retain siblings and inherited helper behavior. +- agent memory-models show/set/clear: fixed settings memoryModels block with extract/consolidation model + optional reasoningEffort. set accepts --extract-model/--extract-effort and --consolidation-model/--consolidation-effort, or exclusive --file. Each invocation replaces the full memoryModels block; omitted phase means off, effort without a model is refused, clear sends null. No empty phase objects. Reuse existing memoryModelsSchema. +- agent compaction-routing show/set/clear: set accepts required --model plus optional --effort, --triggers manual,auto and --sources selectors, or exclusive --file; clear sends null. Each set replaces the full block; omitted triggers/sources retain server default/all scope. Reuse compactionRoutingSchema; preserve exact selectors, no surprise upstream call. +- Existing v2 status/on/off/mode/keep-native-v1/threads/mode-hint gain explicit --live and --json. Live maps exactly to GET/PUT /api/v2: enabled, multiAgentMode, keepNativeChatGptOnV1, maxConcurrentThreadsPerSession, multiAgentModeHintText. Only explicit --acknowledge-surface-advisory writes true; never auto-ack. Parse output/target flags and reject extra operands before local writers. Local transition/hint helpers remain; JSON reports local changed/sync outcome, not fabricated server receipts. + +All commands reuse established API and identity helpers. Runtime base is pinned across resolution/write. No credential writes or settings switches are performed against the operator's proxy in development QA. + +Metadata and docs: capabilities-accounts/agents-routing/observe-system, exact help, skill recipes and public account/agent docs. Update cli-management.md, config.md, subagents.md, account-control/provider ownership docs and Desktop integration contracts only where changed. + +NEW tests/cli/cli-account-policy.test.ts, cli-account-login-options.test.ts, cli-logout-runtime.test.ts, cli-agent-settings.test.ts, cli-system-settings-parity.test.ts, cli-v2-runtime.test.ts. Reuse existing account pool, threshold, native-main, schema and v2 tests. No additions to capped codex-v2-gate file. + +## Activation matrix + +Invalid/mixed selectors, unsupported pool fields, off/false/zero/null, threshold inheritance and account-not-found are distinct. Credits all/one cannot combine and never consume reset grants. Quota activation writes only its nested mutation. Login cancellation/expiry/refusal retains flow identity and no hidden fresh retry. Live refusal cannot fall back to local auth/config. + +Memory phases round-trip independently; disabling removes effort; compaction clear/null is distinct from omitted setting. v2 local and live targets use disjoint fixtures; hybrid conflicts and persisted-but-convergence-failed receipts remain visible. Machine output remains one safe JSON payload with no progress prose or secret values. Explicit security review covers spend intent, auth scope and native ownership. + +## Shared completion contract + +This phase follows 002_terminal_ux.md and 003_verification_strategy.md. Main owns registry/dispatch integration, layout-map registration, generated output and Git branch state; executor write scopes are disjoint and named before B. Existing method/path/body semantics come from the referenced source inventories, not endpoint-name guessing. + +Update the phase's capability domain, generated references, relevant public CLI pages and owning structure contracts in the same layer. Every new test file enters scripts/test-layout/layout.json and tests/fixtures/test-layout-expected.json. Existing tests are retained; no baseline cap increases or green-on-retry acceptance. + +Planned new test paths below become executable verification only after B creates them. The current baseline gates in 003 have actually run. C invokes the exact focused files, typecheck, structure and skill-surface checks, privacy where data is handled, a source-bound cxc receipt and real isolated CLI QA (stdout/stderr/exit/teardown). A successful function mock is transport proof only; relevant existing server tests or isolated real handlers verify accepted state. No live user proxy, credentials or upstream requests. + +Before P>A, revalidate this document against the parent layer and record the prior D conclusion. Consult an architect for actual decision changes; independent A review is separate. C must preserve saved-versus-applied/refused outcomes. D records exact checks and ledger evidence before the next cycle. Publishing is main-owned; this request stops at open PRs. diff --git a/devlog/_plan/261003_cli_gui_parity/060_integrations_maintenance.md b/devlog/_plan/261003_cli_gui_parity/060_integrations_maintenance.md new file mode 100644 index 00000000000..a2521e79ba8 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/060_integrations_maintenance.md @@ -0,0 +1,47 @@ +# wp6 — Complete integration recovery, maintenance settings and Hub observation + +Depends on wp5. Class C3 with C4 destructive/ownership review. Layer 5. + +## Exact command and module changes + +| Command | Existing authority and payload | Files | +| --- | --- | --- | +| claude desktop profile show --json | GET /api/claude-desktop on current management runtime; existing desktop show stays local | NEW src/cli/claude-desktop-profile.ts; MODIFY claude-desktop.ts dispatch | +| claude desktop profile import FILE --json | Bounded DesktopProfile parsed by existing validator; PUT {profile}, save only, separate existing apply. Preserve conflict/unavailable-model/applied-marker guards | same module; no server behavior change | +| integration client enable --client droid --reasoning-default MODEL=EFFORT (repeatable) / --clear-reasoning-defaults | Existing integration payload gains droidReasoningDefaults; same map in any adopted preview/apply plan; no other client accepts it | MODIFY integrations.ts; NEW integration-input.ts if needed | +| integration client history remove --op ID --yes --json [--client aside --profile N] | DELETE exact global/Aside/profile journal path with op identity; newest-row refusal, missing row and snapshotRemoved:false retained | NEW integration-journal.ts; wire integrations.ts | +| integration client sync --client aside --json | Reuse refreshAsideProfilesThroughServer, not broad sync; report per-profile partial failures nonzero; no profile override | integrations.ts/aside-profiles.ts existing helper | +| integration native cursor status/local-installer --json | Fixed existing Cursor GET routes; installer read never installs | MODIFY inspect.ts; small sibling if needed | +| remote-workspace hub status/runtimes/sessions --json | Fixed Hub GET routes; keep existing remote-workspace status executor-local | NEW remote-workspace-hub.ts; MODIFY remote-workspace.ts | +| storage policy set --archived-bytes-over N [--reduce-to-bytes N or --remove-oldest-percent N] | PUT nested trigger.archivedBytesOver and exclusive target shape; retain --percent alias; never implicitly enable | MODIFY storage.ts | +| link revoke --link-id ID --force --yes --json | Only explicit force sends body {force:true}; CLI output explicitly derives remoteCleanup:skipped/unverified from force intent (the endpoint returns only linkId), with a remote disconnect recovery hint. Never claim a failed remote attempt. Ordinary revoke default unchanged | MODIFY link.ts | + +## Preview and optional checked commit + +Add integration client preview --client ID --operation apply|overwrite|disable [--profile N] [Droid defaults] --json and integration client restore --op ID --preview [--client aside --profile N] [--confirm-drift] --json. NEW src/cli/integration-preview.ts owns response/target validation; wire existing integrations.ts. + +Generic preview POSTs /api/client-integrations/preview {clientId,operation,droidReasoningDefaults?}; generic restore preview POSTs /api/client-integrations/restore/preview {opId,confirmDrift?}. Aside always uses /api/client-integrations/aside/profiles/N/preview with operation and optional restore intent. No aggregate Aside preview. All use existing admin management admission, not a GUI-session workaround. + +The returned version-1 plan has clientId, operation, optional profileId, state/foreignEdit, changes, fingerprint, canApply and willChange. It is an observation, not a stored authorization. Validate identity and render refused/no-op/applicable states distinctly. Fingerprint versions are p[0-9]+ with the supported hash shape; never accept an unbound marker. + +Existing enable/disable/restore gain optional --plan-fingerprint TOKEN. Derive operation from the actual command, enabled and overwrite intent, then send the flat pair operation + planFingerprint (not a nested plan object). Repeat exactly the preview's profile/opId/confirmDrift/Droid defaults. No required new preview step for direct legacy commands. Stale 409 returns a failure/re-preview instruction and never silently commits the returned replacement fingerprint. Reject --preview combined with --plan-fingerprint before any request. A stale-plan failure tells the operator to rerun the explicit preview; no unvalidated error-body dump is added to legacy stderr. Add tests/cli/cli-integration-preview.test.ts with real server plan/binding tests for unchanged, changed file/roster, wrong action/profile and passive-cache-unavailable scenarios. + +No new management authority or automatic GUI-session bootstrap. Remote Workspace enroll/start/prompt/revoke and SSH fingerprint/credential workflows remain current consent-session exclusions; Hub read commands do not unlock them. Client-role refusal is truthful. File-client apply/restore retain direct mode; the new optional preview/bound mode covers the GUI inspection workflow. No speculative snapshot or provider refresh occurs inside preview. + +Update capabilities-integrations/access-remote/observe-system, remove fulfilled route deferred entries, regenerate chapters and update skills/ocx remote/recovery recipes plus public integration/storage/remote docs. Structure owners: cli-management, clients/integrations, clients/claude-desktop, remote-workspace, remote-link and storage ownership. No GUI component changes or installation/service deployment. + +NEW tests/cli/cli-claude-desktop-profile.test.ts, cli-integration-journal.test.ts, cli-integration-droid.test.ts, cli-aside-sync.test.ts, cli-integration-cursor.test.ts, cli-remote-workspace-hub.test.ts, cli-storage-policy-fields.test.ts, cli-link-force.test.ts. Existing server integration/journal/Aside-owner/storage policy/link tests prove persistence/ownership contracts. + +## Activation matrix + +A wrong client/profile, missing op, nonconfirmed delete/force, newest journal row, concurrent profile save during the live handler and unreadable file must not silently mutate. A failed live profile save never writes local profile. Partial Aside results stay visible in both modes. Forced link results say remote cleanup was skipped/unverified, derived from the explicit invocation; do not invent a server residual field. Hub empty devices differs from unavailable Hub; executor status does not substitute. Cleanup targets cannot combine, omitted enable stays unchanged, integer boundaries reject incorrect shapes. Explicit security review checks irreversible backup retirement, credentials/trust boundaries and forced link semantics. + +## Shared completion contract + +This phase follows 002_terminal_ux.md and 003_verification_strategy.md. Main owns registry/dispatch integration, layout-map registration, generated output and Git branch state; executor write scopes are disjoint and named before B. Existing method/path/body semantics come from the referenced source inventories, not endpoint-name guessing. + +Update the phase's capability domain, generated references, relevant public CLI pages and owning structure contracts in the same layer. Every new test file enters scripts/test-layout/layout.json and tests/fixtures/test-layout-expected.json. Existing tests are retained; no baseline cap increases or green-on-retry acceptance. + +Planned new test paths below become executable verification only after B creates them. The current baseline gates in 003 have actually run. C invokes the exact focused files, typecheck, structure and skill-surface checks, privacy where data is handled, a source-bound cxc receipt and real isolated CLI QA (stdout/stderr/exit/teardown). A successful function mock is transport proof only; relevant existing server tests or isolated real handlers verify accepted state. No live user proxy, credentials or upstream requests. + +Before P>A, revalidate this document against the parent layer and record the prior D conclusion. Consult an architect for actual decision changes; independent A review is separate. C must preserve saved-versus-applied/refused outcomes. D records exact checks and ledger evidence before the next cycle. Publishing is main-owned; this request stops at open PRs. diff --git a/devlog/_plan/261003_cli_gui_parity/070_observation_api_tools.md b/devlog/_plan/261003_cli_gui_parity/070_observation_api_tools.md new file mode 100644 index 00000000000..2a3091f0a85 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/070_observation_api_tools.md @@ -0,0 +1,60 @@ +# wp7 — Preserve diagnostic state and test selected data-plane credentials + +Depends on wp6. Layer 6. Observation is C3; chosen-key/model/audio consumers are a separate C4-reviewed part of this phase. No server admission changes or upstream production tests. + +## Observation contracts + +- Add system health --json, fixed GET /api/system/health. Existing health liveness and system status aggregate stay unchanged (src/cli/system-command.ts). +- Add companion timeline with hours/bucket-minutes/metric/aggregation/grouping/model/provider filters matching usage-timeline route, preserving truncated/missingMeasurements. Keep companion show/set/reset (new src/cli/companion-timeline.ts, wire companion.ts). +- Extend non-client usage with --api-key-id; reject it on connected clients before reading/transporting a key. Existing connected /v1/usage remains authenticated self-only; Hub host supports management total/key views. No admin privilege synthesized from a data key (observe.ts). +- Extract src/cli/log-follow.ts: send/validate cursor, retain a bounded snapshot window, surface changed same-ID rows and repeated IDs. Existing row JSONL re-emits amendments for upsert consumers. Add --events only for --follow to emit versioned snapshot/append events containing rows/cursor for exact reset/removal reconstruction; do not silently replace legacy row output. --json stays one-shot. Legacy arrays stay accepted without manufactured cursor. +- Add observe injection --follow --jsonl using its real after cursor and bounded polling; preserve snapshot command. SIGINT stops polls and leaves no running process. No write retry. + +## Fixed data-plane task contracts + +NEW src/cli/access-data-plane.ts and access-audio.ts; MODIFY access.ts: + +| Command | Wire behavior | +| --- | --- | +| access key rename ID-or-NAME NAME --json | Existing unambiguous key resolver; PATCH only {id,name}; preserve scopes and no plaintext output. | +| access test MODEL --protocol responses\|chat\|messages --api-key-stdin --json | Reuse named protocol payloads, read explicit chosen key from bounded 4 KiB stdin; reject internal newline, empty/oversized/invalid UTF-8, TTY wait and input timeout without echo. Fixed /v1/responses, /v1/chat/completions or /v1/messages; dedicated x-opencodex-api-key only, never management-header helper. Existing unkeyed test cannot claim chosen-key verification. | +| access audio transcribe FILE --model ID --api-key-stdin --json | Fixed /v1/audio/transcriptions multipart file/model/JSON response format; bounded file/body/time, cancellation, no retry. Output is the requested transcript/result only. | +| access audio live-check --model ID --api-key-stdin --json | Fixed /v1/live WebSocket with the existing GUI key-subprotocol and session-update contract. Wait for actual session readiness, send session.close and close socket. No microphone, upload, delegation execution, reconnect or full voice-roundtrip claim. | + +Standalone/Hub origin is the existing identity-checked local serving origin. Connected clients may use their already-enrolled normalized serverUrl with connection identity rechecked around async key read; never substitute the enrolled key for the explicit key. Preserve HTTPS-or-loopback policy and refusal of redirects/cross-origin auth forwarding. No --base-url, secret argv/env, key cache or management-relay credential exchange. + +Shared input/output uses existing bounded readers and error/exit vocabulary. Chosen-key mode must first establish that the selected target enforces data credentials; it refuses unsupported/authless targets without a paid model probe. Wrong keys fail in stable key-enforcing fixtures; cross-request policy stability is not guaranteed. Fixtures must use actual admission/parser contracts, not a mocked 401 that assumes loopback key enforcement, and assert no administrative header/fallback is attached. Do not echo a raw error response that could contain credentials or arbitrary terminal controls. Key creation/rotation-start and pairing remain human-terminal handoffs in the skill. + +Update pure capability leaves, generated references, JSONL/event schema docs, skill observation/API recipes and public reference pages. Structure owners: cli-management, dashboard-and-usage, GUI/API authority, audio/live contract as affected. No change to router/data-plane server authentication. + +NEW tests/cli/cli-system-health.test.ts, cli-companion-timeline.test.ts, cli-usage-scope.test.ts, cli-log-follow.test.ts, cli-injection-follow.test.ts, cli-access-rename.test.ts, cli-access-data-plane.test.ts, cli-access-audio.test.ts. Reuse existing request-log cursor/GUI parser tests as independent expectations, not as substitutes for CLI behavior. Auth/server audio fixtures stay synthetic. + +## Selected-key model-test guard (CP-DATA-01) + +This is an observational two-request workflow, not an atomic key-admission certificate. Existing unkeyed testing stays unchanged. No server auth policy or endpoint is changed. + +1. Validate grammar, protocol/model and existing target trust/origin. Read a single explicit UTF-8 key through bounded readSecretBytes (4096 bytes, 30-second input deadline), reject TTY waiting/internal newlines/empty input, and clear returned mutable buffers after use. Recheck observable runtime/enrollment identity after asynchronous input; pin one origin and selected protocol path. +2. Send one fresh credentialless POST to that exact model endpoint with literal body bytes `{`, Content-Type: application/json, optional Accept: application/json, credentials:omit and redirect:error. No auth/key/cookie/session/relay/caller headers, content encoding or user-defined body. Control limits: 5 seconds total through body consumption, 4096 response bytes. Cancel/release on every exit; no retry or cached observation. +3. Continue only for HTTP 401 with the exact current native key-required envelope: OpenAI-shaped error has message 'opencodex API key required', type authentication_error and code invalid_api_key; Messages may also use its native top-level type:error with the same message/type, or the OpenAI shape from the existing Hub-link gate. Reject generic/nonmatching 401, unknown/malformed/oversized body, redirect, timeout/cancel/network failure and every other status before sending inference. Response shape never establishes a new trusted origin or cryptographic process identity. +4. Recheck available identity/connection evidence and refuse detected drift. Only then issue one fixed 16-token model request with the supplied dedicated key, bounded to 60 seconds total and 2 MiB response. No management or enrolled-key fallback. A Messages control 401 followed by keyed 403 means failed/disabled test, not success. Audio uses its own explicit-key admission and does not run/reuse this control. +5. Report observations exactly: 'Credentialless request was refused; the model request using the supplied key succeeded.' In selected-key JSON mode, use a versioned probe report with safe control/request observations plus response; unkeyed legacy JSON remains its existing payload. Never say unqualified key verified, key scope certified or billed-to-this-key. No key/fingerprint/raw request metadata is serialized. + +On current supported routes the fixed malformed body parses before routing and cannot dispatch model inference; local logging/rate/admission bookkeeping may occur, so this is not advertised as globally side-effect-free. The observation is invocation/protocol/target scoped. Listener restart/rebind, remote backend change or policy change between calls cannot be atomically excluded by a client. Identity checks detect some changes, not all; no reused connection or extra control is presented as a lease. An authless/unrecognized target returns explicit verification unavailable/nonzero without the inference payload. + +NEW tests/cli/cli-access-key-guard.test.ts and tests/server/cli-key-probe-admission.test.ts exercise actual resolver+handler route compositions with a provider-call trap for all three protocols: enforcing/no key -> native 401 before handler; authless/literal malformed body -> parse/disabled refusal and zero provider calls; accepted control/wrong key -> 401 and zero provider calls under stable enforcing policy; valid key -> one controlled mock inference; disabled Messages -> control 401 then keyed 403; Hub-link native envelope; nonmatching/spoof-shaped/malformed/oversized errors; redirect; interruption; identity drift. State-change fixtures explicitly demonstrate the cross-request claim limit instead of claiming an atomic guarantee. Record whether the fixture invokes the real serve dispatcher or composes real resolvers/handlers; a hand-written fetch 401 alone is only transport coverage. + +## Activation matrix + +Same request id with new tokens/status must emit an amendment; reset/deletion event reconstructs GUI state; duplicate/suffix/legacy/malformed cases are distinct and bounded. Empty polls don't flood output. Connected caller-specified key scope is refused before key read. Timeline incomplete evidence isn't zero. + +For API consumers verify all three protocol shapes, missing/wrong key on an enforcing target, authless-target refusal before a paid probe, no admin leakage, redirect refusal, non-JSON/malformed/oversized responses, file cap, timeout, interruption, origin changes and session.close. No fake key reaches a real provider. Security reviewer separately assesses data-key authority, secret lifecycle and bounded WebSocket cleanup before publication. + +## Shared completion contract + +This phase follows 002_terminal_ux.md and 003_verification_strategy.md. Main owns registry/dispatch integration, layout-map registration, generated output and Git branch state; executor write scopes are disjoint and named before B. Existing method/path/body semantics come from the referenced source inventories, not endpoint-name guessing. + +Update the phase's capability domain, generated references, relevant public CLI pages and owning structure contracts in the same layer. Every new test file enters scripts/test-layout/layout.json and tests/fixtures/test-layout-expected.json. Existing tests are retained; no baseline cap increases or green-on-retry acceptance. + +Planned new test paths below become executable verification only after B creates them. The current baseline gates in 003 have actually run. C invokes the exact focused files, typecheck, structure and skill-surface checks, privacy where data is handled, a source-bound cxc receipt and real isolated CLI QA (stdout/stderr/exit/teardown). A successful function mock is transport proof only; relevant existing server tests or isolated real handlers verify accepted state. No live user proxy, credentials or upstream requests. + +Before P>A, revalidate this document against the parent layer and record the prior D conclusion. Consult an architect for actual decision changes; independent A review is separate. C must preserve saved-versus-applied/refused outcomes. D records exact checks and ledger evidence before the next cycle. Publishing is main-owned; this request stops at open PRs. diff --git a/devlog/_plan/261003_cli_gui_parity/080_acceptance_publication.md b/devlog/_plan/261003_cli_gui_parity/080_acceptance_publication.md new file mode 100644 index 00000000000..93f1efe07b4 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/080_acceptance_publication.md @@ -0,0 +1,35 @@ +# wp8 — Close the task ledger and publish the reviewed manual stack + +Depends on wp7. Class C3 verification/docs; no speculative feature additions. Finish layer 6. Any genuinely new eligible gap discovered here is appended as an in-scope P-phase work unit, not hidden as an exclusion or ignored to finish. + +## Exact completion work + +MODIFY 008_task_ledger.json with per-row final commands/target, phase/PR, executed behavioral test or explicit source-equivalence plus relevant suite proof, help/skill evidence and terminal disposition. Reconcile overlapping GUI entry points through aliasOf arrays; keep baseline rows visible. Add memory-model and compaction-routing rows with confirmed dashboard-overview-panels mount anchors. Every excluded row names presentation/native/session/consent cause and evidence; implementation debt is never relabeled excluded. + +MODIFY skills/ocx/SKILL.md and references/02_json_shapes.md, 03_recipes.md, 04_failure_semantics.md, 05_remote_hub.md plus generated domain references to accurately describe delivered workflows. Add a compact task-to-command reference and examples for local/live choice, bounded body files, read-back and partial failure. Preserve all human-only/secret handoffs. Correct the opening coverage claim to the measured scope, not 'everything'. + +MODIFY affected public CLI docs and structure docs with final behavior; eliminate stale capability/debt counts by deriving them. Verify translated docs do not contradict changed English claims. Archive this unit to devlog/_fin only when every phase is complete; repair any tracked plan references in the same closure change. Record remaining pre-existing/API-only debt separately. + +## Publication contract + +Six manual layers, own topic/verification/template and current head. Publish after each layer is locally scoped-validated; create parent PR before child so legitimate bases pass enforce-target. Attach every created PR to this chat. Never register a native stack. No merge/release/deploy in this request. + +Inspect each actual current-head CI: event, attempt, jobs, tested checkout SHA, success of required Linux shards/gates and any triggered platform work. Canceled/skipped/missing/older-head checks are not passing tests. Independent review and required security review are recorded separately. Resolve correct findings and propagate lower-layer fixes upward with attribution and exact leases if rewriting becomes necessary; then refresh all affected proof. No workflow/queue/check bypass. + +## Acceptance + +- Task ledger has no unexplained pending/UNKNOWN/implementation gap; all eligible rows map to verified named workflows, or a specific acknowledged product limitation justified by actual platform/consent authority. +- Existing supported effects retained; representative workflows exercise real handlers/CLI, target separation, machine output, invalid/missing inputs, server refusal, empty state, confirmation and cancellation. +- Every new command appears in capability/help/skill/public docs with true flags and request effects; no generic endpoint or raw config fallback is counted. +- Exact-head CI passes per PR. Worktree contains no uncommitted source; all authorized implementation is recoverable from the open PR stack. +- Final report names PR URLs/heads/CI, measured coverage and specific genuine exclusions. No full local/platform pass is invented from baseline or skipped jobs. + +## Shared completion contract + +This phase follows 002_terminal_ux.md and 003_verification_strategy.md. Main owns registry/dispatch integration, layout-map registration, generated output and Git branch state; executor write scopes are disjoint and named before B. Existing method/path/body semantics come from the referenced source inventories, not endpoint-name guessing. + +Update the phase's capability domain, generated references, relevant public CLI pages and owning structure contracts in the same layer. Every new test file enters scripts/test-layout/layout.json and tests/fixtures/test-layout-expected.json. Existing tests are retained; no baseline cap increases or green-on-retry acceptance. + +Planned new test paths below become executable verification only after B creates them. The current baseline gates in 003 have actually run. C invokes the exact focused files, typecheck, structure and skill-surface checks, privacy where data is handled, a source-bound cxc receipt and real isolated CLI QA (stdout/stderr/exit/teardown). A successful function mock is transport proof only; relevant existing server tests or isolated real handlers verify accepted state. No live user proxy, credentials or upstream requests. + +Before P>A, revalidate this document against the parent layer and record the prior D conclusion. Consult an architect for actual decision changes; independent A review is separate. C must preserve saved-versus-applied/refused outcomes. D records exact checks and ledger evidence before the next cycle. Publishing is main-owned; this request stops at open PRs. From ff8eb3ca759dcfe96a6065b6db0d85ead1ad4b19 Mon Sep 17 00:00:00 2001 From: JUN Date: Sun, 4 Oct 2026 00:25:55 +0900 Subject: [PATCH 002/113] docs(cli): link roadmap review and verification receipts --- .../_plan/261003_cli_gui_parity/009_roadmap_lock.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/devlog/_plan/261003_cli_gui_parity/009_roadmap_lock.md b/devlog/_plan/261003_cli_gui_parity/009_roadmap_lock.md index 7b264cf297b..74a1fd03698 100644 --- a/devlog/_plan/261003_cli_gui_parity/009_roadmap_lock.md +++ b/devlog/_plan/261003_cli_gui_parity/009_roadmap_lock.md @@ -7,3 +7,16 @@ Whole-plan architecture reflection passed at a095a4e514d6d8e5a37dbf05a66b2c9156e Verification before implementation: docs checker validates all eight phase specs, 178 unique IDs, phase/alias ownership, source anchors and document bounds. Existing baseline contract tests/typecheck/structure/generated surface results are recorded in 003; they are not evidence that future commands work. Independent reviewers additionally verified selected existing resolver/parser/GUI fixture contracts with no live targets. Next: wp1 revalidates 010 against the latest integration base, then implements pure discovery and generated-document capacity. Every later phase keeps its assigned functionality and evidence obligations. No source implementation, PR publication or final product completion is claimed by this roadmap lock. + +## Locating the review and check evidence + +Task-local artifacts (intentionally ignored, not public security working notes): + +- `.tmp/cli-parity/architect-reflection.md`: whole-plan ALIGNED and final CP-DATA-01/02 ALIGNED, reviewer handle 01a1021d-2d94-7d20-95c1-a18da31958a8. +- `.tmp/cli-parity/audit-roadmap.md`: independent roadmap re-audit PASS, no remaining blockers, reviewer 01a10243-08df-7542-b1ff-57b2b08918e9. +- `.tmp/cli-parity/audit-security.md`: independent scoped planning re-audit PASS for be1f1744, no remaining planning blockers, reviewer 01a10243-09a5-76e2-91c6-097f65e474b5. This is not code-security certification. +- `.tmp/cli-parity/fresh-reader.md` or the retained Euclid response (01a1025d-7ebb-7bc2-96f5-6c37cd0c6cf7): delivery/grounding/next-step read was clear; requested exact evidence locators, added here. +- Check command: `python3 .tmp/cli-parity/check-plan.py` → exit 0, `PASS: 8 phase specs, 178 unique ledger IDs, valid phase/alias ownership, source anchors, no invented completion, bounded docs`. +- Source-bound Check receipt: `.codexclaw/evidence/01a10024-8d6f-7500-b528-38212c4bc396/test-receipt.json`, produced by `cxc receipt test --session 01a10024-8d6f-7500-b528-38212c4bc396 -- python3 .tmp/cli-parity/check-plan.py`. + +These artifacts establish plan validation only. The later implementation phases must produce their own current-source tests, CLI QA and public PR/CI evidence. From 167881a8505f58a6981237378346714085c07e61 Mon Sep 17 00:00:00 2001 From: JUN Date: Sun, 4 Oct 2026 01:25:22 +0900 Subject: [PATCH 003/113] refactor(cli): separate capability data and task references --- .../010_discovery_foundation.md | 16 +- .../011_foundation_revalidation.md | 15 + .../012_foundation_verification.md | 27 + scripts/generate-ocx-skill-surface.ts | 238 ++-- scripts/test-layout/layout.json | 2 + skills/ocx/SKILL.md | 28 +- .../ocx/references/01_management_surface.md | 1257 ++--------------- .../references/01_surface_access-remote.md | 237 ++++ skills/ocx/references/01_surface_accounts.md | 307 ++++ .../references/01_surface_agents-routing.md | 141 ++ .../ocx/references/01_surface_integrations.md | 207 +++ skills/ocx/references/01_surface_lab.md | 13 + skills/ocx/references/01_surface_lifecycle.md | 94 ++ .../references/01_surface_observe-system.md | 407 ++++++ .../references/01_surface_providers-models.md | 130 ++ src/cli/capabilities-base.ts | 1128 +++++++++++++++ src/cli/capabilities-command.ts | 1 + src/cli/capabilities.ts | 1217 +--------------- src/cli/capability-types.ts | 54 + src/cli/help.ts | 7 +- structure/INDEX.md | 5 +- structure/cli-management.md | 31 + structure/manifest.json | 11 + structure/ops/docs-and-release.md | 2 +- structure/runtime.md | 6 +- .../ci-workflows/skill-ocx-generated.test.ts | 232 +++ tests/ci-workflows/skill-ocx.test.ts | 33 +- tests/cli/cli-capabilities.test.ts | 18 +- tests/cli/cli-capability-data.test.ts | 352 +++++ tests/fixtures/test-layout-expected.json | 2 + tests/helpers/cli-capability-data.ts | 197 +++ 31 files changed, 3958 insertions(+), 2457 deletions(-) create mode 100644 devlog/_plan/261003_cli_gui_parity/011_foundation_revalidation.md create mode 100644 devlog/_plan/261003_cli_gui_parity/012_foundation_verification.md create mode 100644 skills/ocx/references/01_surface_access-remote.md create mode 100644 skills/ocx/references/01_surface_accounts.md create mode 100644 skills/ocx/references/01_surface_agents-routing.md create mode 100644 skills/ocx/references/01_surface_integrations.md create mode 100644 skills/ocx/references/01_surface_lab.md create mode 100644 skills/ocx/references/01_surface_lifecycle.md create mode 100644 skills/ocx/references/01_surface_observe-system.md create mode 100644 skills/ocx/references/01_surface_providers-models.md create mode 100644 src/cli/capabilities-base.ts create mode 100644 src/cli/capability-types.ts create mode 100644 structure/cli-management.md create mode 100644 tests/ci-workflows/skill-ocx-generated.test.ts create mode 100644 tests/cli/cli-capability-data.test.ts create mode 100644 tests/helpers/cli-capability-data.ts diff --git a/devlog/_plan/261003_cli_gui_parity/010_discovery_foundation.md b/devlog/_plan/261003_cli_gui_parity/010_discovery_foundation.md index 35616c7289d..1013985bee9 100644 --- a/devlog/_plan/261003_cli_gui_parity/010_discovery_foundation.md +++ b/devlog/_plan/261003_cli_gui_parity/010_discovery_foundation.md @@ -32,7 +32,7 @@ usage literals → pure typed metadata → additive capabilities JSON → help a - A synthetic data module importing a handler/config/Lab fails the graph guard; legal data/type edges pass. - Regeneration then --check succeeds; a changed/missing generated chapter fails; counts derive from arrays, never handwritten totals. - All generated chapters <2000 lines and structure docs ≤600; existing source caps are unchanged. -- Focused commands: baseline four contract files plus new cli-capability-data and existing cli-help-paths/navigation/recovery files. No GUI render/build needed for this code-free visual surface. +- Focused commands: baseline four contract files plus new cli-capability-data and existing cli-help-paths/navigation/recovery files. No GUI render/build is needed; real CLI help and machine-output QA remains required. ## Shared completion contract @@ -43,3 +43,17 @@ Update the phase's capability domain, generated references, relevant public CLI Planned new test paths below become executable verification only after B creates them. The current baseline gates in 003 have actually run. C invokes the exact focused files, typecheck, structure and skill-surface checks, privacy where data is handled, a source-bound cxc receipt and real isolated CLI QA (stdout/stderr/exit/teardown). A successful function mock is transport proof only; relevant existing server tests or isolated real handlers verify accepted state. No live user proxy, credentials or upstream requests. Before P>A, revalidate this document against the parent layer and record the prior D conclusion. Consult an architect for actual decision changes; independent A review is separate. C must preserve saved-versus-applied/refused outcomes. D records exact checks and ledger evidence before the next cycle. Publishing is main-owned; this request stops at open PRs. + +## wp1 execution refinements (same-architect stale check) + +The exact pure-data graph initially contains only capability-types.ts, capabilities-base.ts and the capabilities.ts facade. Types has no imports/runtime initializer; base imports types only; facade imports/re-exports base values and types while retaining the three existing pure helpers. Use an explicit allowlist, not a wildcard that also admits capabilities-command.ts. The test-owned scanner handles imports, side-effect imports, re-exports and type edges, rejects unresolved/bare/outside/cyclic/computed loads, and ignores comment/string lookalikes. Reuse the existing narrow tokenization seam in tests/helpers/warmup-tokens.ts or a proven Bun scanner; do not assume a TypeScript 5 parser exists under this repository's native TS7 tooling. The same predicate must run against real files and bad/good fixtures. It checks dependencies, not arbitrary-code sandboxing. + +All shipped capability literals remain byte-faithful in wp1. Exercise a present usage value by adding a temporary property to a real existing leaf only inside an isolated Bun subprocess, then invoke actual runCapabilities JSON/help/generator consumers. A separate unmodified process checks absence compatibility. No production setter, synthetic command or shared-test global mutation. + +Closed chapter map for current roots: lifecycle={chatgpt,status,resolve,capabilities,sync}; providers-models={provider,models}; accounts={account}; agents-routing={agent,combo}; integrations={claude,integration}; observe-system={companion,usage,logs,storage,inspect,system}; access-remote={link,remote-workspace,hub,connect,api}; lab is an honestly empty reserved chapter until wp2. Unknown roots fail and wp2 extends the map deliberately. Preserve global invocation order in the index and original per-chapter order. Keep each old canonical index fragment as a short forwarding heading/link, so existing file-plus-fragment references continue to work. Test exact file+anchor reachability and collisions, not only substring presence. + +The generator checks the expected map and rejects extra owner-marked 01_surface_*.md files; it does not delete unrelated or stale files automatically. Scan every actually shipped reference Markdown for command/consent safety. SKILL may reach chapters through its index; test transitive navigation rather than require every chapter to be linked at the top level. + +Structure extraction is deliberately narrow: move substantive runtime CLI-readiness content and the two detailed head/help/catalog table contracts into cli-management.md. Keep old runtime headings and concise pointers to preserve anchors. Leave executable lifecycle ownership in runtime. Review the other mapped CLI docs; unchanged accurate contracts do not need copied prose. Register the new Tier 5 owner, stage paths before structure:check and regenerate INDEX through its owner script. + +Implementation leaves: (1) metadata/types/facade/serializer/help + CLI tests; (2) generator/skill/generated chapters + skill workflow tests. Main owns structure docs, both test-layout maps, integration/commits and all branch operations. Neither leaf edits the other's paths or runs a global typecheck while the other is writing. diff --git a/devlog/_plan/261003_cli_gui_parity/011_foundation_revalidation.md b/devlog/_plan/261003_cli_gui_parity/011_foundation_revalidation.md new file mode 100644 index 00000000000..6d0ad53fbab --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/011_foundation_revalidation.md @@ -0,0 +1,15 @@ +# wp1 revalidation + +Previous D direction from 009: wp1 revalidates 010 against the latest integration base, then implements pure discovery and generated-document capacity. No change of direction is needed. + +Current source baseline for wp1 is aa720907314ed2c5ca68f5c22d851148d66b1d0d, merging dev a141b83623a3f1677f23477e91b9a42a74f495f7 after the docs-only cycle. Incoming changes concern native upload bytes, Ollama commentary replay and test-layout cleanup. Comparing the audited 9f89b7265b baseline to this tree found no changes in src/cli, the skill generator/skill files, structure/runtime.md or structure/manifest.json. The exact 010 source/consumer design remains applicable. + +The independent wp0 audit already corrected the explicit capabilities-command JSON projection owner. Current 010 includes that edit and a real serializer test; no helper-only proof is substituted. Optional usage leaves canonical invocation matching unchanged. The phase remains a pure metadata/documentation foundation with no management authority or runtime mutation change. + +Current test-layout baseline was checked because the incoming integration commits changed both layout maps. New tests will be registered against these current maps rather than copied from the earlier baseline. The original structure owner is at its 600-line cap, so the mapped CLI contract move stays necessary. + +The existing whole-unit architect proposal and concrete ALIGNED reflection cover CP-ARCH-02/04 and CP-SIZE-01 for 010. A bounded same-architect wp1 stale-check is requested; its resulting refinements and reflection will be recorded before A. Independent plan audit and actual B/C implementation proof are still required. + +Same-architect wp1 proposal confirmed all relevant committed seams unchanged and supplied exact export/edge roles, isolated usage fixtures, closed chapter ownership/link preservation and minimal structure extraction. Main accepted these under existing CP-ARCH-02/04 and CP-SIZE-01 and appended them to 010; no new framework or authority was introduced. Current layout baseline: 18 pass, 0 fail, 555 assertions. Concrete refinement is returned to that same architect before independent wp1 A. + +Same-architect reflection is ALIGNED for the concrete wp1 refinement (010 digest 11a4dd5ac83fe3578d580e9faea64f5882fb0f21092b12a7524cef1298511212). Artifact: `.tmp/cli-parity/wp1-reflection.md`. CP-ARCH-02, CP-ARCH-04 and CP-SIZE-01 have no essential mismatch; implementation and independent A/C proof remain separate. diff --git a/devlog/_plan/261003_cli_gui_parity/012_foundation_verification.md b/devlog/_plan/261003_cli_gui_parity/012_foundation_verification.md new file mode 100644 index 00000000000..e9952330bdc --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/012_foundation_verification.md @@ -0,0 +1,27 @@ +# wp1 implementation and verification + +The discovery foundation is implemented: capability types and literal data have separate owners behind the stable facade; optional exact usage reaches the real JSON/help renderers; generated operating references have a compact index and eight bounded domain chapters. The 74 existing capability rows and two HEAD rows preserve their values and ordering. This phase adds capacity and correctness checks, not the later GUI task commands. + +## Observed checks + +| Check | Result / scope | +| --- | --- | +| Capability boundary and actual consumer tests | 71 pass, 0 fail, 597 assertions across cli-capability-data, cli-capabilities and cli-capabilities-arguments after review repairs. | +| Existing CLI help regressions | 47 pass, 0 fail; actual alias/fallback/root behavior retained. | +| Generated skill/reference tests | 21 pass, 0 fail, 617 assertions; missing/stale/extra owned files, fragment links, usage and limits exercised. | +| Current test-layout maps | 18 pass, 0 fail, 555 assertions; both new test files registered. | +| Integrated typecheck | exit 0 after the final helper repair. | +| Actual metadata comparison | All original fields and ordering match the captured pre-source-change JSON. | +| Generated source check | All nine generated files are current. | +| Structure owner/index | Generated INDEX and structure checks passed after owned files were staged. Other mapped CLI contracts were inspected and remained accurate; only the affected runtime/release pointers changed. | +| Staged whitespace | passed after removing two trailing blank EOF lines in new files. | + +The new dependency checker is deliberately limited to an admitted metadata grammar. Refusal fixtures cover computed/ambiguous expressions, loader aliases and reserved ambient host bindings. Independent implementation re-review is PASS with no remaining findings; exact probes and unchanged production hashes are recorded in the private review evidence. Harmless quoted data remains supported. This does not certify arbitrary JavaScript as sandboxed, and the existing metadata contains none of those loader forms. + +## Evidence and C gate + +Worker records: `.codexclaw/evidence/wp1-metadata-worker.md`, `wp1-f1-repair.md`, `wp1-f1-r2-repair.md`, and `wp1-surface-worker/verification.json`. Main integration logs use `.tmp/cli-parity/wp1-*`; the independent implementation review is `.tmp/cli-parity/wp1-code-review.md`. Actual CLI QA captures stdout/stderr/exit under this session's `qa/parity-wp1` evidence directory, with network denied and isolated configuration homes. Bun's private transpilation cache is accounted separately from application configuration and removed with the test sandbox. + +Final C receipt and review disposition remain separate from worker reports. Full/changed local suites were not run: focused scope is recorded above, and broad/platform verification belongs to each published PR's current-head hosted CI. No user proxy, credentials, paid upstream or client configuration was operated on. + +Next work phase consumes 020 to declare already-working tasks, add exact synopses and improve operating recipes; the base still has the original 74 declarations at this checkpoint. diff --git a/scripts/generate-ocx-skill-surface.ts b/scripts/generate-ocx-skill-surface.ts index b0ede70217e..513987f9f1a 100644 --- a/scripts/generate-ocx-skill-surface.ts +++ b/scripts/generate-ocx-skill-surface.ts @@ -1,111 +1,167 @@ /** - * Generates `skills/ocx/references/01_management_surface.md` from the capability table. + * Generate the compact operating-skill index and its owned domain chapters. + * Pure renderers use the public capability facade; I/O stays in the CLI entry point. * - * Generated rather than written, because a hand-maintained surface map is a SECOND description - * of the CLI that is free to drift from the first -- the same defect class this unit removed from - * the help text. `tests/ci-workflows/skill-ocx.test.ts` asserts the committed file matches this output, so a - * capability added without regenerating fails CI instead of silently shipping a stale skill. - * - * Usage: - * bun scripts/generate-ocx-skill-surface.ts # write - * bun scripts/generate-ocx-skill-surface.ts --check # exit 1 if stale + * bun scripts/generate-ocx-skill-surface.ts # write expected files only + * bun scripts/generate-ocx-skill-surface.ts --check # reject missing/stale/extra owned files */ -import { writeFileSync, readFileSync, existsSync } from "node:fs"; +import { writeFileSync, readFileSync, existsSync, readdirSync } from "node:fs"; import { join } from "node:path"; -import { CAPABILITIES, HEAD_CAPABILITIES, capabilityInvocation } from "../src/cli/capabilities"; +import { CAPABILITIES, HEAD_CAPABILITIES, capabilityInvocation, type Capability } from "../src/cli/capabilities"; -const TARGET = join(import.meta.dir, "..", "skills", "ocx", "references", "01_management_surface.md"); +const DIRECTORY = join(import.meta.dir, "..", "skills", "ocx", "references"); +const INDEX = "01_management_surface.md"; +const OWNER = "GENERATED by scripts/generate-ocx-skill-surface.ts"; +const PREAMBLE = `\n\n`; -export function renderManagementSurface(): string { - const lines: string[] = []; - lines.push(""); - lines.push(""); - lines.push(""); - lines.push("# The `ocx` management surface"); - lines.push(""); - lines.push("Every capability the CLI declares, with the management routes it drives and whether it"); - lines.push("mutates state. This file is generated from the same table `ocx capabilities --json`"); - lines.push("serves, so it cannot describe a command that does not exist."); - lines.push(""); - lines.push("Ask the running binary instead of trusting this file when the two disagree:"); - lines.push(""); - lines.push("```bash"); - lines.push("ocx capabilities --json # the whole table"); - lines.push("ocx capabilities --mutating-only --json # only state-changing verbs"); - lines.push("ocx capabilities --route /api/logs # which verbs drive one route"); - lines.push("```"); - lines.push(""); +// Navigation groups, not command dispatch. New roots require an explicit assignment. +const DOMAINS = [ + { name: "lifecycle", roots: ["chatgpt", "status", "resolve", "capabilities", "sync"] }, + { name: "providers-models", roots: ["provider", "models"] }, + { name: "accounts", roots: ["account"] }, + { name: "agents-routing", roots: ["agent", "combo"] }, + { name: "integrations", roots: ["claude", "integration"] }, + { name: "observe-system", roots: ["companion", "usage", "logs", "storage", "inspect", "system"] }, + { name: "access-remote", roots: ["link", "remote-workspace", "hub", "connect", "api"] }, + { name: "lab", roots: [] }, +]; - lines.push("## Resolved before dispatch"); - lines.push(""); - lines.push("These answer in the CLI head and never reach the proxy, so they work with nothing running."); - lines.push(""); - lines.push("| Invocation | Purpose |"); - lines.push("|---|---|"); - for (const head of HEAD_CAPABILITIES) { - lines.push(`| \`${head.invocations.join("\` \`")}\` | ${head.summary} |`); - } - lines.push(""); +function chapterFilename(domain: string): string { + return `01_surface_${domain}.md`; +} - const mutating = CAPABILITIES.filter(c => c.mutates); - const reading = CAPABILITIES.filter(c => !c.mutates); +// GitHub Markdown anchors for canonical CLI headings (backticks are presentation only). +function invocationAnchor(invocation: string): string { + return invocation.toLowerCase().replace(/[^\p{L}\p{N}_\-\s]/gu, "").replace(/ /g, "-"); +} - for (const [title, group, note] of [ - ["Read-only capabilities", reading, "Safe to run at any time; none of these change state."], - ["State-changing capabilities", mutating, "Each of these writes. Check the flags column before running one unattended."], - ] as const) { - lines.push(`## ${title}`); - lines.push(""); - lines.push(note); - lines.push(""); - for (const cap of group) { - lines.push(`### \`${capabilityInvocation(cap)}\``); - lines.push(""); - lines.push(cap.summary); - lines.push(""); - if (cap.routes.length > 0) { - lines.push("| Method | Route |"); - lines.push("|---|---|"); - for (const route of cap.routes) lines.push(`| ${route.method} | \`${route.path}\` |`); - } else { - lines.push("Drives no management route."); - } - lines.push(""); - if (cap.flags.length > 0) { - lines.push("| Flag | Value | Meaning |"); - lines.push("|---|---|---|"); - for (const flag of cap.flags) lines.push(`| \`${flag.name}\` | ${flag.value} | ${flag.summary} |`); - lines.push(""); - } - lines.push(`JSON mode: \`${cap.json}\`.`); - lines.push(""); - for (const detail of cap.details ?? []) lines.push(`- ${detail}`); - if ((cap.details ?? []).length > 0) lines.push(""); +function assignChapters(): Map { + const roots = new Map(); + for (const domain of DOMAINS) { + for (const root of domain.roots) { + if (roots.has(root)) throw new Error(`Duplicate surface root: ${root}`); + roots.set(root, chapterFilename(domain.name)); } } + const assignments = new Map(); + const anchors = new Set(); + for (const cap of CAPABILITIES) { + const file = roots.get(cap.command[0]!); + if (!file) throw new Error(`Unknown surface root: ${cap.command[0]}`); + const invocation = capabilityInvocation(cap); + const anchor = invocationAnchor(invocation); + if (anchors.has(anchor)) throw new Error(`Surface anchor collision: ${invocation} (#${anchor})`); + anchors.add(anchor); + assignments.set(cap, file); + } + return assignments; +} - lines.push("## Counts"); - lines.push(""); - lines.push(`- declared capabilities: ${CAPABILITIES.length}`); - lines.push(`- of those, state-changing: ${mutating.length}`); - lines.push(`- head-resolved invocations: ${HEAD_CAPABILITIES.length}`); - lines.push(""); +function renderIndex(assignments: Map): string { + const lines = [PREAMBLE, "# The `ocx` management surface", "", + "Declared capabilities, grouped by operating task. This index is not every CLI verb.", + "Read the chapter for routes, flags and mutation notes; use the running binary when versions differ.", "", + "```bash", "ocx capabilities --json # the declared table", + "ocx capabilities --mutating-only --json # declared state-changing verbs", + "ocx capabilities --route /api/logs # declarations for one route", "```", "", + "## Resolved before dispatch", "", + "These answer in the CLI head and never reach the proxy, so they work with nothing running.", "", + "| Invocation | Purpose |", "|---|---|"]; + for (const head of HEAD_CAPABILITIES) { + lines.push(`| \`${head.invocations.join("` `")}\` | ${head.summary} |`); + } + lines.push("", "## Task chapters", "", "| Chapter | Declared capabilities |", "|---|---|"); + for (const domain of DOMAINS) { + const file = chapterFilename(domain.name); + const count = [...assignments.values()].filter(value => value === file).length; + lines.push(`| [${domain.name}](${file}) | ${count} |`); + } + lines.push("", "## Read-only capabilities", "", + "Read-oriented tasks are marked non-mutating in the registry. Probes may contact providers,", + "consume quota or refresh caches; this label does not promise cost-free or effect-free execution.", "", + "## State-changing capabilities", "", + "Check the chapter's flags, the requested authority and the operating skill's consent and secret rules.", "", + "## Canonical invocation index", "", + "Original invocation order. These headings preserve links to the previous single-file reference.", ""); + for (const cap of CAPABILITIES) { + const invocation = capabilityInvocation(cap); + lines.push(`### \`${invocation}\``, "", + `[${cap.mutates ? "State-changing task" : "Read-oriented task"}](${assignments.get(cap)}#${invocationAnchor(invocation)})`, ""); + } + lines.push("## Counts", "", `- declared capabilities: ${CAPABILITIES.length}`, + `- of those, state-changing: ${CAPABILITIES.filter(cap => cap.mutates).length}`, + `- head-resolved invocations: ${HEAD_CAPABILITIES.length}`, ""); return lines.join("\n"); } +function renderCapability(cap: Capability): string[] { + const lines = [`### \`${capabilityInvocation(cap)}\``, ""]; + if (cap.usage !== undefined) lines.push(`Usage: \`${cap.usage}\``, ""); + lines.push(cap.summary, "", `State-changing: ${cap.mutates ? "yes" : "no"}.`, ""); + if (cap.routes.length > 0) { + lines.push("| Method | Route |", "|---|---|"); + for (const route of cap.routes) lines.push(`| ${route.method} | \`${route.path}\` |`); + } else { + lines.push("Drives no management route."); + } + lines.push(""); + if (cap.flags.length > 0) { + lines.push("| Flag | Value | Meaning |", "|---|---|---|"); + for (const flag of cap.flags) lines.push(`| \`${flag.name}\` | ${flag.value} | ${flag.summary} |`); + lines.push(""); + } + lines.push(`JSON mode: \`${cap.json}\`.`, ""); + for (const detail of cap.details ?? []) lines.push(`- ${detail}`); + if ((cap.details ?? []).length > 0) lines.push(""); + return lines; +} + +/** Deterministic filename → Markdown map; no filesystem reads or metadata mutation. */ +export function renderManagementSurfaces(): Record { + const assignments = assignChapters(); + const files: Record = { [INDEX]: renderIndex(assignments) }; + for (const domain of DOMAINS) { + const file = chapterFilename(domain.name); + const caps = CAPABILITIES.filter(cap => assignments.get(cap) === file); + const lines = [PREAMBLE, `# ${domain.name}: declared management tasks`, "", + `[Management index](${INDEX}) · [Operating rules](../SKILL.md#secret-bearing-commands)`, "", + "Use these declarations to choose a task, then check its flags and authority before execution.", + "Non-mutating probes may still contact providers, consume quota or refresh caches.", "", + `Declared capabilities: ${caps.length}.`, ""]; + if (caps.length === 0) lines.push("No declared capabilities yet. This chapter reserves navigation space; it does not promise a command.", ""); + for (const cap of caps) lines.push(...renderCapability(cap)); + files[file] = lines.join("\n"); + } + for (const [file, content] of Object.entries(files)) { + if (content.split("\n").length - 1 >= 2000) throw new Error(`Surface file must stay below 2000 lines: ${file}`); + } + return files; +} + +/** Compatibility entry point: the compact index, including old fragment forwarders. */ +export function renderManagementSurface(): string { + return renderManagementSurfaces()[INDEX]!; +} + if (import.meta.main) { - const rendered = renderManagementSurface(); + const files = renderManagementSurfaces(); + const extra = readdirSync(DIRECTORY).filter(file => + /^01_surface_.*\.md$/.test(file) && !Object.hasOwn(files, file) + && readFileSync(join(DIRECTORY, file), "utf8").includes(OWNER)).sort(); + for (const file of extra) console.error(`Unexpected generated chapter: ${file}. Review and remove it explicitly; generation never deletes files.`); if (process.argv.includes("--check")) { - const current = existsSync(TARGET) ? readFileSync(TARGET, "utf8") : ""; - if (current === rendered) { - console.log("skills/ocx/references/01_management_surface.md is current."); - process.exit(0); + const stale = Object.entries(files).filter(([file, content]) => + !existsSync(join(DIRECTORY, file)) || readFileSync(join(DIRECTORY, file), "utf8") !== content); + for (const [file] of stale) console.error(`${file} is missing or STALE.`); + if (stale.length || extra.length) { + console.error("Regenerate: bun scripts/generate-ocx-skill-surface.ts"); + process.exit(1); + } + console.log(`All ${Object.keys(files).length} generated management surface files are current.`); + } else { + for (const [file, content] of Object.entries(files)) { + writeFileSync(join(DIRECTORY, file), content); + console.log(`wrote skills/ocx/references/${file}`); } - console.error("skills/ocx/references/01_management_surface.md is STALE."); - console.error("Regenerate: bun scripts/generate-ocx-skill-surface.ts"); - process.exit(1); } - writeFileSync(TARGET, rendered); - console.log(`wrote ${TARGET}`); } - diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json index 63c69bc2ab6..43b1eb6406d 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -2,6 +2,8 @@ "version": 1, "root": "tests", "explicit": { + "cli-capability-data.test.ts": "cli", + "skill-ocx-generated.test.ts": "ci-workflows", "provider-antigravity-wire-snapshot.test.ts": "providers", "antigravity-discovered-families.test.ts": "adapters/google", "provider-antigravity-effort-families.test.ts": "providers", diff --git a/skills/ocx/SKILL.md b/skills/ocx/SKILL.md index 700a0c974b1..4e3d1b632f0 100644 --- a/skills/ocx/SKILL.md +++ b/skills/ocx/SKILL.md @@ -169,21 +169,27 @@ proven safe: another process owns the token, no journal records the pre-connect different client key owns the journal, or the restore was only partial. Details, including the one-port recipe, the invite flow and key rotation's two-step commit: -`references/05_remote_hub.md`. Service and launchd semantics, including why +[remote hub reference](references/05_remote_hub.md). Service and launchd semantics, including why `ocx service repair` can correctly do nothing while `ocx service restart` always restarts — so a restart is never a hand-written `launchctl kickstart`: -`references/04_failure_semantics.md`. +[failure semantics](references/04_failure_semantics.md). ## References | File | Use it for | |---|---| -| `references/01_management_surface.md` | the full capability → route map (generated) | -| `references/02_json_shapes.md` | response envelopes and error shapes | -| `references/03_recipes.md` | copy-paste sequences for real tasks | -| `references/04_failure_semantics.md` | exit codes, 503 classes, what to retry | -| `references/05_remote_hub.md` | hub/client roles, when pairing is and is not needed, key rotation, disconnection | - -`01_management_surface.md` is generated by `scripts/generate-ocx-skill-surface.ts` and a test fails -if the committed copy drifts from the capability table. When it and the running binary disagree, -believe `ocx capabilities --json`. +| [Management index](references/01_management_surface.md) | declared capabilities in eight task chapters, with routes, flags and mutation notes (generated) | +| [JSON shapes](references/02_json_shapes.md) | response envelopes and error shapes | +| [Recipes](references/03_recipes.md) | copy-paste sequences for real tasks | +| [Failure semantics](references/04_failure_semantics.md) | exit codes, 503 classes, what to retry | +| [Remote hub](references/05_remote_hub.md) | hub/client roles, when pairing is and is not needed, key rotation, disconnection | + +The management index routes to lifecycle, providers/models, accounts, agents/routing, +integrations, observation/system, access/remote and the reserved Lab chapter. Lab has no +current declarations. Each chapter retains canonical command headings; the index preserves +old fragment links. Read-oriented declarations may contact providers, consume quota or refresh +caches, so check task details before running a probe. + +The index and its eight chapters are generated by `scripts/generate-ocx-skill-surface.ts`. +Checks reject missing, stale or extra generated chapters. When documentation and the running +binary disagree, believe `ocx capabilities --json`. diff --git a/skills/ocx/references/01_management_surface.md b/skills/ocx/references/01_management_surface.md index 817a98fbc03..a3f31bfe4eb 100644 --- a/skills/ocx/references/01_management_surface.md +++ b/skills/ocx/references/01_management_surface.md @@ -3,16 +3,13 @@ # The `ocx` management surface -Every capability the CLI declares, with the management routes it drives and whether it -mutates state. This file is generated from the same table `ocx capabilities --json` -serves, so it cannot describe a command that does not exist. - -Ask the running binary instead of trusting this file when the two disagree: +Declared capabilities, grouped by operating task. This index is not every CLI verb. +Read the chapter for routes, flags and mutation notes; use the running binary when versions differ. ```bash -ocx capabilities --json # the whole table -ocx capabilities --mutating-only --json # only state-changing verbs -ocx capabilities --route /api/logs # which verbs drive one route +ocx capabilities --json # the declared table +ocx capabilities --mutating-only --json # declared state-changing verbs +ocx capabilities --route /api/logs # declarations for one route ``` ## Resolved before dispatch @@ -24,1311 +21,327 @@ These answer in the CLI head and never reach the proxy, so they work with nothin | `--version` `-v` `version` | Print the CLI version and exit. | | `help` `--help` `-h` | Print the command list, or one command's usage with `ocx help `. | -## Read-only capabilities - -Safe to run at any time; none of these change state. - -### `ocx link port` - -Allocate a free loopback port for a remote home link. - -Drives no management route. - -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the selected port as JSON. | - -JSON mode: `payload`. - -### `ocx link status` - -Read link listener and tunnel status. - -| Method | Route | -|---|---| -| GET | `/api/link/status` | - -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the K16 status payload as JSON. | - -JSON mode: `payload`. - -### `ocx remote-workspace status` - -Read local executor enrollment and available capabilities without printing credentials. - -Drives no management route. - -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the public local executor status. | - -JSON mode: `payload`. - -- Executor-local operation; Hub consent and session control stay in the dashboard. - -### `ocx models price` - -Read the saved manual price for an exact provider/model selector. - -| Method | Route | -|---|---| -| GET | `/api/providers/{provider}/model-costs` | - -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit provider, modelId, and cost (null for automatic pricing). | - -JSON mode: `envelope`. - -- The provider must be configured; everything after the first slash is the exact upstream model ID. - -### `ocx status` - -Proxy status, injection state, and version skew between this CLI and the running proxy. - -Drives no management route. - -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the status envelope as JSON. | - -JSON mode: `envelope`. - -- Reads /healthz plus local config; drives no management API route. - -### `ocx resolve` - -One JSON document naming the config home, the effective port, and the identity-checked proxy liveness verdict. - -Drives no management route. - -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the resolve document as JSON (the shell contract). | - -JSON mode: `envelope`. - -- Exit 0 carries a trustworthy verdict (live or proven absent); exit 1 means the CLI could not resolve and a caller must refuse to guess — unknown liveness never reads as absent. -- Built for embedding shells (desktop app): the liveness budgets stay owned by src/server/proxy-liveness.ts. - -### `ocx capabilities` - -List the declared CLI capabilities and the management routes they drive. - -Drives no management route. - -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the full capability table as JSON. | -| `--mutating-only` | boolean | Restrict output to capabilities that mutate state. | -| `--route` | string | Show which capabilities drive a management route. | - -JSON mode: `envelope`. - -- Start here when driving ocx programmatically: it is the declared surface index, not a complete verb list. - -### `ocx provider list` - -Configured providers with connectivity and selected models. - -Drives no management route. - -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the provider list as JSON. | -| `--jsonl` | boolean | Emit one configured provider per JSON line. | - -JSON mode: `envelope`. - -- Reads local config; drives no management API route. - -### `ocx provider resets` - -Recently detected quota resets and whether reset notifications are enabled. - -| Method | Route | -|---|---| -| GET | `/api/quota-resets` | - -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit reset events as JSON. | -| `--limit` | number | Limit returned events; defaults to 20, capped at 100. | - -JSON mode: `payload`. - -### `ocx account history` - -Cached quota observations for one stored Codex pool account. - -| Method | Route | -|---|---| -| GET | `/api/codex-auth/quota/history` | - -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the bounded observation history. | -| `--limit` | number | Return the newest 1 to 200 observations. | - -JSON mode: `payload`. - -- Use account history openai . Reads cached observations only; no refresh or warmup. Native main is not included. - -### `ocx account list` - -Codex OAuth accounts with pool priority and pause state. - -| Method | Route | -|---|---| -| GET | `/api/codex-auth/accounts` | - -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the account list as JSON. | - -JSON mode: `payload`. - -- STATUS names `paused` alongside `selected`: a paused-but-selected account still receives requests. -- `--quota` shows cached Codex windows (including 5h); `--refresh` bypasses the server TTL. - -### `ocx usage` - -Token and estimated-cost report over a time range. - -| Method | Route | -|---|---| -| GET | `/api/usage` | - -| Flag | Value | Meaning | -|---|---|---| -| `--range` | string | today | 1d | 7d | 30d | all | -| `--since` | string | Inclusive start: epoch milliseconds or full ISO datetime with timezone; requires --until and overrides --range. | -| `--until` | string | Inclusive end: epoch milliseconds or full ISO datetime with timezone; requires --since. | -| `--provider` | string | Restrict to one provider. | -| `--model` | string | Restrict to one model id. | -| `--json` | boolean | Emit the usage report as JSON. | - -JSON mode: `payload`. - -- Per-account totals are withheld under `--provider` or `--model`: account rows cannot be honestly re-partitioned by provider, so the report says so rather than printing an empty table. -- An `(ambiguous)` account row aggregates several accounts; do not read it as one identity. - -### `ocx logs` - -Recent request log rows, filterable by provider, model, conversation, account, and status. - -| Method | Route | -|---|---| -| GET | `/api/logs` | - -| Flag | Value | Meaning | -|---|---|---| -| `--provider` | string | Restrict to one provider, matching failover attempts too. | -| `--model` | string | Restrict to one model id, matching failover attempts too. | -| `--conversation` | string | Restrict to one conversation id (`--conversationId` is accepted too). | -| `--account` | string | Restrict to one account log label (`main`, `p`, `o`), matching failover attempts too. | -| `--status` | string | An exact code (429) or a class (5xx). | -| `--limit` | number | Row cap; defaults to 200. | -| `--follow` | boolean | Poll for new rows; add --jsonl to emit JSONL. | -| `--json` | boolean | Emit the server payload as JSON. | -| `--jsonl` | boolean | Emit one row per line. | - -JSON mode: `payload`. - -- `--provider` and `--model` both match a failover attempt, so a request is findable by what actually served it, not only by what was asked for. -- Rows print `conv=` when the entry carries one, so a conversation filter can be told apart from an empty result. -- Rows print `acct=