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..9acce9af42b --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/004_settings_coverage.md @@ -0,0 +1,144 @@ +# 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. + +## Dashboard-mounted panels added in roadmap reconciliation + +| ID | Task and source | Current CLI coverage | Work phase | +|---|---|---|---| +| set-S06 | Memory extraction/consolidation model settings; `gui/src/pages/dashboard-overview-panels.tsx`, `gui/src/components/MemoryModelsPanel.tsx` | No dedicated live block writer; the existing memory family does not prove these GUI fields | wp5 | +| set-S07 | Compaction route model, effort, triggers and source scope; `gui/src/pages/dashboard-overview-panels.tsx`, `gui/src/components/CompactionRoutingPanel.tsx` | No dedicated live block writer | wp5 | + +These two source-backed implementation gaps supplement the historical 67-row settings inventory above. The task ledger is authoritative for current cross-domain aliases and completion evidence. 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..d45b836874e --- /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..4a8531ffade --- /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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"task":"set-P08 — Check provider connectivity","existingCli":"provider test P --json","sourceInventory":"004_settings_coverage.md"}, + {"id":"set-P09","domain":"settings","baseline":"COMPLETE","status":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"task":"ops-K02 — Create key with name; `gui/src/pages/ApiKeys.tsx:268`","existingCli":"access key create NAME --json","sourceInventory":"005_operations_coverage.md","disposition":"Existing human-only secret-returning operation; indexed as a family handoff with safe list/get/rotation follow-ups. No agent execution recipe or consent bypass."}, + {"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"task":"ops-K05 — Start rotation; `gui/src/pages/ApiKeys.tsx:349`","existingCli":"access key rotate ID --json","sourceInventory":"005_operations_coverage.md","disposition":"Existing human-only secret-returning operation; indexed as a family handoff with safe list/get/rotation follow-ups. No agent execution recipe or consent bypass."}, + {"id":"ops-K06","domain":"operations","baseline":"COMPLETE","status":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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":"complete","unit":"wp2","evidence":["022_discovery_verification.md","src/cli/capabilities.ts","skills/ocx/references/01_management_surface.md"],"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..74a1fd03698 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/009_roadmap_lock.md @@ -0,0 +1,22 @@ +# 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. + +## 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. 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..1013985bee9 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/010_discovery_foundation.md @@ -0,0 +1,59 @@ +# 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 is needed; real CLI help and machine-output QA remains required. + +## 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. + +## 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/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..ce0cfc9c806 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/020_existing_workflow_discovery.md @@ -0,0 +1,47 @@ +# 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. Keep the original 74 entries in capabilities-base.ts; main adds exact usage and reviewed corrections there. MODIFY capabilities.ts to append seven new unique arrays after the baseline in the listed domain order. Leaves import only Capability types, never handlers. Preserve baseline row reference identity and relative order; full facade/base array identity intentionally ends with aggregation. 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. + +## wp2 execution refinement + +Exact new exports, in aggregate append order: PROVIDER_MODEL_CAPABILITIES, ACCOUNT_CAPABILITIES, AGENT_ROUTING_CAPABILITIES, INTEGRATION_CAPABILITIES, OBSERVE_SYSTEM_CAPABILITIES, ACCESS_REMOTE_CAPABILITIES, LAB_CAPABILITIES. Import original base CAPABILITIES under a local alias; export one stable readonly aggregate. Existing public types, HEAD identity and three query helpers stay unchanged; helpers must inspect the aggregate. Leaf arrays are implementation details, not new facade exports. + +Extend tests/helpers/cli-capability-data.ts with seven exact owner filenames and role edges: each new leaf imports Capability types only; the facade imports those named values. Preserve restricted grammar, bad-edge/cycle/host/ambiguous-expression refusals and all prior negative fixtures. Update tests/cli/cli-capability-data.test.ts deliberately: baseline rows remain once, first and referentially identical; appended rows equal explicit leaf ownership; duplicate canonical keys fail. Remove only the no-longer-true full-array equality and universal no-usage assumption. Isolated fixtures still force both absent and present usage through real JSON/help, so legacy fallback coverage survives actual metadata growth. + +Main alone updates existing base entries from source-anchored worker proposals. Do not clone/rewrite all literals, reorder baseline rows or claim a local operation fetches HTTP. First-order field corrections and synopsis additions are static data, not a metadata registration framework. + +Progressive skill discovery starts with offline root/family/leaf help and the needed chapter. Full capabilities JSON is optional for an actual broad inventory; exact route lookup remains available and matches declared templates. Readiness/version checks apply before live management work, not offline help or explicitly local operations. Add --json only where the command's declaration/handler supports it. No new filtering flag or global output/error migration. + +Secret-returning human-only actions remain discoverable as family descriptions and handoffs, with safe follow-up leaves. Do not emit literal creation/rotation-start invocation or usage alternatives as executable-looking recipes in generated headings. Do not exempt generated pages from existing secret detectors or obscure spellings to evade them. Human-only task ledger rows remain accounted for rather than dropped. + +Worker scopes: A owns new provider-model/account leaf files and uniquely named tests; B owns new agent-routing/integration/Lab leaves and tests; C owns new observation-system/access-remote leaves and tests. Each returns scratch proposals for existing base rows and source anchors, without editing base/facade/guard/generator/registry/maps. A single docs leaf owns handwritten skill and existing public CLI pages. Main integrates all shared files and generated chapters after writers settle, checks exact method/route truth and records task coverage. All code/skill examples cover existing implementations only; future wp3..7 flags are not advertised yet. diff --git a/devlog/_plan/261003_cli_gui_parity/021_discovery_revalidation.md b/devlog/_plan/261003_cli_gui_parity/021_discovery_revalidation.md new file mode 100644 index 00000000000..66578c52ae9 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/021_discovery_revalidation.md @@ -0,0 +1,9 @@ +# wp2 revalidation and consultation + +Previous D: wp1 foundation completed at 167881a850 with stable original metadata, generated-domain capacity, independent code review PASS and ten real offline CLI scenarios. Its final source-bound gate passed 67 structure/hygiene tests plus generated-surface/privacy checks. The source-bound receipt was archived before continuing. + +wp2 consumes 020. Current integration is 77ac2a93d2, merging dev e601cefcebcc20b2e04a04821ab45df6538d98f9. Only both test-layout maps conflicted; resolution retained the upstream maps and the two new foundation test registrations, without reviving retired entries. Incoming source changes concern provider/account/transport behavior and do not change the CLI/generator/skill seams this phase declares. Source anchors in the baseline inventories remain historical; workers verify actual handlers before declaring a verb. + +The same architect proposed keeping baseline data first and appending seven unique arrays, instead of rewriting/moving unchanged objects for grouping. Main accepts CP-ARCH-02's incremental composition, CP-ARCH-04's actual serializer/absent-present fixture coverage, CP-INTEGRATION-01's progressive task discovery and human handoffs, and CP-SIZE-01's closed generated map. Exact write ownership and export/guard changes are appended to 020. Concrete reflection and independent A precede implementation. + +Same-architect reflection is ALIGNED for concrete020 digest53ed87a26394cd0c5d5ae2fee9983d55042ad94385e68982bbbd950b8d3bfc49, covering incremental aggregation, actual JSON/fallback proof, human-only descriptions and disjoint ownership. Artifact: `.tmp/cli-parity/wp2-reflection.md`. The current layout baseline passed18 tests/555 assertions; no full local suite ran. diff --git a/devlog/_plan/261003_cli_gui_parity/022_discovery_verification.md b/devlog/_plan/261003_cli_gui_parity/022_discovery_verification.md new file mode 100644 index 00000000000..cad505c7709 --- /dev/null +++ b/devlog/_plan/261003_cli_gui_parity/022_discovery_verification.md @@ -0,0 +1,29 @@ +# wp2 — Existing workflow discovery verified + +The existing CLI is now indexed by task: 289 capability entries replace the former 74-entry partial index. The original 74 rows retain their identity/order, seven pure domain leaves append existing workflows, and verified synopses distinguish local configuration from live management requests. This closes the ledger's 104 existing/discovery rows. It does not implement the missing GUI operations assigned to wp3–wp7. + +## Delivered behavior + +Offline leaf help includes actual operands, flags and output semantics. Eight generated chapters give the operating skill a progressive task entry point; the root index retains existing anchors. Handwritten examples use real parser-supported invocations, saved-versus-applied read-back and explicit authority for side effects. Public English CLI pages and contradictory claims in seven translations are synchronized. + +Timeline and Cursor routes previously appeared in metadata despite having no caller; they now have explicit roadmap debt. Lab descriptions acknowledge existing local controls without claiming those commands manage a selected running server. The PATCH pool-settings alias remains a server compatibility path; actual CLI writes use PUT. The bidirectional route debt guard still rejects unexplained new routes and stale exemptions. + +## Independent review and repairs + +Two inherited-model reviewers independently inspected the seven domain tables and main integration against handlers. Both finished with PASS after four material corrections: JSON reads require explicit key-list/companion-show actions; selected-model reads use CLI envelope metadata and document write receipts separately; secret-returning link/Hub/raw-export operations have prose handoffs instead of generated usage recipes; routing evaluation examples disclose Lab activation and already-enabled automation. Tests exercise the actual parser/output cases, omitted-action refusal, and accidental secret usage injection. No credential-bearing operation was executed. + +Private review receipts are `.tmp/cli-parity/wp2-review-discovery.md` and `wp2-review-integration.md`. Their prior FAIL sections remain historical; the final re-review verdict is PASS. Production authentication, credential storage, provider behavior and handlers are unchanged. + +## Verification and limits + +The integrated focused set passed 266 tests before the review repairs. The repaired provider read/write tests passed 31 cases; the final help/access repair set passed 35. The 97-case metadata/help/file-size set passed. New regressions retain the full negative dependency/host-import grammar fixtures and absent/present usage consumer coverage rather than replacing them with self-matching metadata assertions. Both layout maps register all eight new test files. + +Typecheck, structure ownership, privacy and whitespace checks passed during integration. Public docs built 561 pages and checked 77,947 internal links. The final source-bound receipt is archived under `.codexclaw/evidence/01a10024-8d6f-7500-b528-38212c4bc396/`; final command/output and commit identity accompany the PR. + +Seventeen actual CLI subprocess scenarios passed with closed stdin, network denial, isolated application homes and color disabled. They cover root/full/nested/alias help, provider/account/sidecar/Lab/storage/access tasks, repeated help, capability JSON, a known route lookup, empty/unmatched route errors and an unknown root. Main read the provider-edit and key-family output: required operands, clear sentinels, live/local distinction and human-only handoff are visible; no arbitrary model/credential values were introduced. Root help remains compact. The full JSON inventory is large, so the skill deliberately starts with the needed family/chapter. Teardown recorded zero network attempts, unchanged application configuration and removal of the temporary home; isolated Bun compilation cache writes are accounted for. + +Local full/changed suites were not run because their resource cost is disproportionate for this metadata/docs layer across concurrent worktrees. Relevant parser, transport, indirect source-oracle, layout, generated-file and help regressions were exercised. Broad suite and platform proof remains the published PR's exact-head hosted CI obligation; no pending CI is represented as a pass. The QA evidence matrix is `.codexclaw/evidence/01a10024-8d6f-7500-b528-38212c4bc396/qa/parity-wp2/`. + +## What did not improve + +No missing provider/model/account/settings/integration operation becomes implemented merely by appearing in the inventory. A declared command still needs its own target/version/authority checks; metadata is not execution permission or proof that an arbitrary server accepts every value. Mocked transport tests prove parser requests and output, not universal provider behavior. A remaining counterexample would be a declared synopsis rejected by its actual handler or a route claim without a caller; either must reopen this phase rather than be relabeled as coverage. wp3 starts from the provider-management plan and the verified existing metadata, with a fresh P/A cycle. 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..b99b9681b6a --- /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. diff --git a/docs-site/src/content/docs/fr/reference/cli/agents.md b/docs-site/src/content/docs/fr/reference/cli/agents.md index 290ebbea5e3..60a99fe7dfe 100644 --- a/docs-site/src/content/docs/fr/reference/cli/agents.md +++ b/docs-site/src/content/docs/fr/reference/cli/agents.md @@ -129,13 +129,16 @@ les valeurs par défaut du débogage sont `OPENCODEX_USAGE_DEBUG=1`. ### `ocx access ...` -Gérez les clés d'admission OpenCodex et examinez les points de terminaison et les modèles externes. `ocx api-key - ...` est un alias de `ocx access key`. +Consultez la liste des clés API d’accès à OpenCodex, les points de terminaison externes et les modèles. `ocx api-key` est un alias de la famille de commandes `ocx access key`. + +La création d’une clé et le lancement d’une rotation renvoient un secret en clair, affiché une seule fois, aussi bien en texte qu’en JSON. Les agents doivent confier ces étapes à une personne utilisant directement un terminal en dehors de la session de l’agent. Ne demandez jamais la clé dans la conversation : demandez uniquement la confirmation de la configuration et du test de connexion, ainsi que les identifiants non secrets de la clé et de la rotation. ```bash -ocx access key create deployment +ocx access key list --json ``` +La confirmation du fonctionnement de la nouvelle clé n’autorise pas la révocation de l’ancienne. Pour finaliser la rotation ou supprimer l’ancienne clé, obtenez une autorisation explicite distincte pour révoquer cette clé. Consultez à nouveau la liste après l’opération autorisée. Ne contournez pas cette procédure par un appel direct à l’API. + ## Intégrations client ### `ocx integration ...` diff --git a/docs-site/src/content/docs/fr/reference/cli/providers-accounts.md b/docs-site/src/content/docs/fr/reference/cli/providers-accounts.md index 91b74330991..fef31abe62e 100644 --- a/docs-site/src/content/docs/fr/reference/cli/providers-accounts.md +++ b/docs-site/src/content/docs/fr/reference/cli/providers-accounts.md @@ -420,10 +420,7 @@ entrées de catalogue ; `enable`, `disable` et `provider` contrôlent la visibi liste d'autorisation des fournisseurs ; `context` contrôle les plafonds de contexte du fournisseur ; et `shadow` gère l'arrière-plan interception d'appel fantôme. -Chaque opération par modèle proposée par le tableau de bord est disponible ici, donc une installation sans tête n'est jamais nécessaire -appuyez sur GUI pour gérer un catalogue. `add`, `remove` et `list-custom` fonctionnent sur le fichier de configuration et appliquent -à un proxy en cours d'exécution via une synchronisation de catalogue ; les autres parlent à la direction en direct API et exigent le -proxy en cours d'exécution (`ocx start` ou un service installé). +Le tableau ci-dessous décrit les opérations de catalogue prises en charge par la CLI, sans couvrir toutes les actions du tableau de bord. Modifier le nom affiché d’un modèle découvert automatiquement est différent de l’opération `edit` sur un modèle personnalisé. `add`, `remove` et `list-custom` utilisent la configuration locale ; une modification de modèle personnalisé peut tenter de synchroniser le catalogue si le proxy est en cours d’exécution. Un enregistrement local réussi ne prouve pas que la synchronisation est terminée. Les autres opérations de gestion des modèles utilisent l’API de gestion du proxy actif : vérifiez son état de préparation et sa version avant de les appeler. Il n’est pas nécessaire de démarrer le proxy pour consulter les modèles ou la configuration hors ligne. | Sous-commande | Drapeaux pris en charge | Actions | | --- | --- | --- | diff --git a/docs-site/src/content/docs/ja/reference/cli/agents.md b/docs-site/src/content/docs/ja/reference/cli/agents.md index d71c6a90336..9152d6d7f68 100644 --- a/docs-site/src/content/docs/ja/reference/cli/agents.md +++ b/docs-site/src/content/docs/ja/reference/cli/agents.md @@ -97,12 +97,16 @@ ocx debug usage logs [-f|--follow] ### `ocx access ...` -OpenCodex アドミッション API キーを管理し、外部エンドポイントとモデルを検査します。 `ocx api-key ...` は `ocx access key` の別名です。 +OpenCodex へのアクセス用 API キーの一覧、外部エンドポイント、モデルを確認します。`ocx api-key` は `ocx access key` コマンド群の別名です。 + +キーの作成とローテーションの開始では、通常のテキスト出力でも JSON 出力でも、一度だけ表示される平文の認証情報が返されます。エージェントはこれらの手順を実行せず、エージェントセッション外で人が直接操作するターミナルに委ねてください。キーそのものをチャットで求めず、設定と接続の確認結果、および秘密情報ではないキー ID とローテーション ID だけを受け取ってください。 ```bash -ocx access key create deployment +ocx access key list --json ``` +新しいキーの設定と接続の確認は、古いキーの失効承認ではありません。ローテーションの確定や古いキーの削除には、そのキーを失効させるための明示的な承認が別途必要です。承認された操作の後は一覧を再確認してください。API の直接呼び出しでこの手順を回避しないでください。 + ## クライアントの統合 ### `ocx integration ...` diff --git a/docs-site/src/content/docs/ja/reference/cli/providers-accounts.md b/docs-site/src/content/docs/ja/reference/cli/providers-accounts.md index 5f46501bbb9..5b55efbff67 100644 --- a/docs-site/src/content/docs/ja/reference/cli/providers-accounts.md +++ b/docs-site/src/content/docs/ja/reference/cli/providers-accounts.md @@ -313,7 +313,7 @@ native-main トラフィックまたはジャーナル復旧を受け入れる `ocx model` は `ocx models` の別名です。サブコマンドを使用しない場合、構成されたプロバイダーに静的にシードされたモデルを一覧表示します。 `--provider` は 1 つの構成済みプロバイダーをフィルターし、`--json` はモデル メタデータを返します。 `live` は実行中のカタログを読み取ります。 `add`、`edit`、`remove`、および `list-custom` は手動カタログ エントリを管理します。 `enable`、`disable`、および `provider` は可視性を制御します。 `selected` はプロバイダー許可リストを制御します。 `context` はプロバイダーのコンテキストの上限を制御します。 `shadow` はバックグラウンドのシャドウ コール インターセプトを管理します。 -ダッシュボードが提供するモデルごとの操作はすべてここで利用できるため、ヘッドレスインストールではカタログを管理するために GUI が必要ありません。 `add`、`remove`、および `list-custom` は設定ファイルに対して機能し、カタログ同期を通じて実行中のプロキシに適用されます。残りはライブ管理 API と通信し、プロキシが実行されている必要があります (`ocx start`、またはインストールされたサービス)。 +以下の表は、CLI が対応するカタログ操作を示しています。ダッシュボードのすべての操作を網羅するものではありません。自動検出されたモデルの表示名変更は、カスタムモデルの `edit` 操作とは別です。`add`、`remove`、`list-custom` はローカル設定を使用し、カスタムモデルの変更時にプロキシが稼働していればカタログの同期を試みる場合があります。ローカルへの保存完了は、同期完了を意味しません。それ以外のモデル管理操作は稼働中のプロキシの管理 API を使用するため、呼び出す前に準備状態とバージョンを確認してください。オフラインでモデルや設定を確認するためにプロキシを起動する必要はありません。 |サブコマンド |サポートされているフラグ |アクション | | --- | --- | --- | diff --git a/docs-site/src/content/docs/ko/reference/cli/agents.md b/docs-site/src/content/docs/ko/reference/cli/agents.md index 681e1ca9f7d..34d781cd8e4 100644 --- a/docs-site/src/content/docs/ko/reference/cli/agents.md +++ b/docs-site/src/content/docs/ko/reference/cli/agents.md @@ -122,13 +122,16 @@ scope를 지정하지 않으면 `ocx debug`는 사용량을 출력하고, 프록 ### `ocx access ...` -OpenCodex admission API key를 관리하고 외부 endpoint와 model을 검사합니다. `ocx api-key - ...`는 `ocx access key`의 별칭입니다. +OpenCodex 접속용 API 키 목록, 외부 엔드포인트와 모델을 조회합니다. `ocx api-key`는 `ocx access key` 명령 계열의 별칭입니다. + +키 생성과 교체 시작은 일반 텍스트와 JSON 출력 모두에서 일회성 평문 자격 증명을 반환합니다. 에이전트는 이 단계를 에이전트 세션 밖에서 사람이 직접 조작하는 터미널에 맡겨야 합니다. 키 자체를 채팅으로 요청하지 말고, 설정·연결 확인 결과와 비밀이 아닌 키·교체 ID만 전달받으세요. ```bash -ocx access key create deployment +ocx access key list --json ``` +새 키의 설정과 연결 확인은 기존 키 폐기 승인이 아닙니다. 교체를 확정하거나 기존 키를 삭제하려면 해당 키 폐기에 대한 별도의 명시적 승인이 필요합니다. 승인된 작업 후에는 목록을 다시 조회하세요. 직접 API를 호출해 이 절차를 우회하지 마세요. + ## 클라이언트 통합 ### `ocx integration ...` diff --git a/docs-site/src/content/docs/ko/reference/cli/providers-accounts.md b/docs-site/src/content/docs/ko/reference/cli/providers-accounts.md index 9fd3cd1a649..fcb91a8a7e7 100644 --- a/docs-site/src/content/docs/ko/reference/cli/providers-accounts.md +++ b/docs-site/src/content/docs/ko/reference/cli/providers-accounts.md @@ -429,7 +429,7 @@ native-main 트래픽이나 저널 복구를 허용하기 전에 수명 주기 `ocx model`은 `ocx models`의 별칭입니다. 하위 명령이 없으면 설정된 제공자에 사전 등록된 모델을 나열합니다. `--provider`는 설정된 제공자 하나를 필터링하고 `--json`은 모델 메타데이터를 반환합니다. `live`는 실행 중인 카탈로그를 읽습니다. `add`, `edit`, `remove`, `list-custom`은 수동 카탈로그 항목을 관리합니다. `enable`, `disable`, `provider`는 가시성을 제어합니다. `selected`는 제공자 허용 목록을 제어합니다. `context`는 제공자 컨텍스트 한도를 제어합니다. `shadow`는 백그라운드 shadow-call 가로채기를 관리합니다. -대시보드가 제공하는 모델별 작업은 모두 여기에서도 사용할 수 있으므로, 헤드리스 설치에서는 카탈로그를 관리할 때 GUI가 필요하지 않습니다. `add`, `remove`, `list-custom`은 구성 파일을 대상으로 하며 카탈로그 동기화를 통해 실행 중인 프록시에 적용됩니다. 나머지는 실시간 관리 API와 통신하며 프록시가 실행 중이어야 합니다(`ocx start` 또는 설치된 서비스). +아래 표는 CLI가 지원하는 카탈로그 작업을 설명합니다. 대시보드의 모든 작업을 지원하는 것은 아닙니다. 자동으로 발견된 모델의 표시 이름 변경은 사용자 정의 모델의 `edit` 작업과 다릅니다. `add`, `remove`, `list-custom`은 로컬 구성을 사용하며, 사용자 정의 모델을 변경할 때 프록시가 실행 중이면 카탈로그 동기화를 시도할 수 있습니다. 로컬 저장이 완료되어도 동기화 완료를 뜻하지는 않습니다. 나머지 모델 관리 작업은 실행 중인 프록시의 관리 API를 사용하므로 호출 전에 준비 상태와 버전을 확인하세요. 오프라인 모델·구성 조회를 위해 프록시를 시작할 필요는 없습니다. | 하위 명령 | 지원 플래그 | 동작 | | --- | --- | --- | diff --git a/docs-site/src/content/docs/reference/cli.md b/docs-site/src/content/docs/reference/cli.md index 7bb9e2f1dc6..c1a58bb73e4 100644 --- a/docs-site/src/content/docs/reference/cli.md +++ b/docs-site/src/content/docs/reference/cli.md @@ -19,8 +19,8 @@ opencodex state. ## Nested help Family help such as `ocx help models` preserves the family's usage and details, then -lists known declared child paths with summaries. These lists are marked as partial; -they do not enumerate every runtime operation. Alias help retains the alias's own usage +lists known declared child paths with summaries. These lists describe declared children; +they do not guarantee exhaustive runtime coverage. Alias help retains the alias's own usage and details and points to its canonical family: `ocx help model` leads to `ocx help models`. Models help also links the curated `models context` topic separately from declared capabilities. @@ -72,7 +72,7 @@ children. Suggestions are guidance only: the CLI never executes them or retries | `ocx modles` or `ocx help modles` | Suggests `ocx help models`. | | `ocx help account lisst` | Suggests `ocx help account list` within the account family. | | `ocx help qzxv` | Offers `ocx help --all` without guessing a command. | -| `ocx help service install` | Reports unavailable detailed help and points to `ocx help service`; the runtime install operation remains valid. | +| `ocx help models qzxv` | Reports unavailable detailed help and points to the known models family. | The Bun CLI rejects an unknown root before shim auto-restore or other command preflight. Recognized commands retain their existing preflight; hidden commands and the internal runner @@ -139,7 +139,7 @@ Codex or npm, control a running process, or write configuration/cache state. For Windows x64 installation observation, see [the `attest` command](/reference/cli/agents/#explicit-installation-observation-on-windows-x64). Without explicit paths it observes the selected candidate identified from the proof-bound launcher snapshot; it does not grant update authority or attest runtime selection. -List or status is the default where unambiguous. Use `--json` for structured snapshots and +List or status is the default where unambiguous. Use `--json` only on leaves that support it, and `ocx observe logs --follow --jsonl` for a streaming request-log feed. Theme, language, navigation, and other purely visual browser state have no CLI equivalent; Cloudflare Tunnel setup is outside this command set. @@ -173,17 +173,18 @@ and unavailable required services exit nonzero. `ocx health` specifically exits proxy is healthy and 1 otherwise, so it can be used as a service probe. Scripts should test the exit code instead of scraping human-readable output. -The specific codes are set in one place, so every management command agrees: +Many management commands share these mappings; other CLI families retain their own exit contracts: | Code | Cause | |---|---| | 0 | success | -| 2 | usage error — bad, missing, or unknown arguments; nothing was sent | +| 2 | local usage refusal in management handlers; also unsupported `doctor --json` | +| 64 | invalid arguments to `capabilities`, `ready`, or `resolve`, before their discovery/request work | | 4 | HTTP 404 — the named account, provider, key, or route does not exist | | 5 | HTTP 409 — conflict; a lock is held or state changed underneath | | 1 | everything else, including transport failure and other HTTP errors | -Exit 0 means no error was reported. Preview verbs (for example `ocx storage cleanup` without `--yes`) also exit 0 without mutating. A command never prints an error and exits 0. +Exit 0 means no error was reported. Preview verbs (for example `ocx storage cleanup` without `--yes`) also exit 0 without mutating. A saved setting can still carry a skipped or incomplete apply result; read the receipt and stderr warnings. Destructive removal, import, credit-consumption, and update operations that advertise confirmation require `--yes` in non-interactive use. The flag is an explicit opt-in; omitting it must not silently @@ -195,18 +196,45 @@ a prompt an automated caller can answer is not a safety boundary, so the flag is ## Driving the CLI from an agent -`ocx capabilities --json` is the machine-readable index of declared capabilities, their management -routes, known flags, and mutation metadata. It is not an exhaustive command grammar or a list of -every runtime subcommand. Start there rather than parsing help text: +Discover progressively, without starting a proxy: + +```bash +ocx help +ocx help models +ocx help models preset show +``` + +Read the corresponding chapter in the repository's `skills/ocx/references/01_management_surface.md` +or one of the public command-family pages above. Full `ocx help --all` is an +escape to the top-level reference. A broad machine inventory is optional: ```bash ocx capabilities --json ocx capabilities --mutating-only --json -ocx capabilities --route /api/logs +ocx capabilities --route '/api/providers/{provider}/model-costs' --json ``` -An unmatched `--route` exits 4 rather than reporting empty success. The repository ships a fuller -operating guide at `skills/ocx/`, whose surface map is generated from the same table. +Route lookup matches the literal declared template, not concrete provider IDs or +an HTTP method. A miss exits 4 and does not prove that a runtime command is absent. +Declarations include local commands as well as management commands; only the +latter need a live target. Before live operations, run `ocx ready --json` and +`ocx status --json`, inspect the target and `versionSkew.relation`, and resolve +version mismatch. `unknown` does not confirm matching builds. Offline help, +local configuration and local Lab inspection do not require startup. + +Output flags are per command. `doctor` rejects `--json` with exit 2; `v2` has no +JSON output contract. Even for JSON-capable management commands, API failures +normally use stderr prose with optional `reason:` and `hint:` lines, not a JSON +error envelope. Keep stdout, stderr and exit status separate. + +Coverage is measured by named workflows, not by shared route prefixes. Existing +model presets, visibility, account controls and routing-profile reads do not imply +support for discovered-model display-name edits or routing-profile writes. +Session-only consent actions and browser presentation remain separate boundaries. +Access-key creation and rotation-start return plaintext credentials: agents must +hand those steps to a human-operated terminal outside the session and accept only +non-secret IDs and confirmation. Never ask for credentials in chat or bypass a +session-only action with another API client. ## Recent behavior changes @@ -216,8 +244,8 @@ These are corrections to commands that previously misreported their own results: exited 0, so a script could not tell success from failure. - Client errors from `account` map HTTP 404 to exit 4 and HTTP 409 to exit 5, instead of collapsing everything into 1. -- `--json` is honored in any argument position, including `ocx restore back --json`, which - previously accepted the flag and ignored it. +- `ocx restore back --json` now honors its output flag, which it previously accepted and ignored. + This does not make `--json` a global option for every command. - `ocx logs --model` now actually filters. It was accepted and silently ignored, so the output looked filtered while showing every row. - `ocx storage` gained `cleanup`, `trash`, and `policy` subcommands. A bare `ocx storage` still diff --git a/docs-site/src/content/docs/reference/cli/agents.md b/docs-site/src/content/docs/reference/cli/agents.md index 178a57ab4cd..7ee064ef992 100644 --- a/docs-site/src/content/docs/reference/cli/agents.md +++ b/docs-site/src/content/docs/reference/cli/agents.md @@ -92,6 +92,8 @@ for the request surfaces where caps apply. ### `ocx v2 |keep-native-v1 |threads |mode-hint >` Manage the Codex `multi_agent_v2` feature flag and the three-state multi-agent surface mode. +These are local controls with human output; do not append `--json`. Re-read +`ocx v2 status` after a change and distinguish stored settings from new-session behavior. | Subcommand | Action | | --- | --- | @@ -141,7 +143,7 @@ gate: it requires the native feature to be enabled with an explicit v2 surface ### `ocx combo ...` · `ocx route combo ...` Manage combo failover and round-robin virtual models. `ocx route combo` is the hierarchical alias; -combo is currently the supported routing resource. Targets use +combos and routing profiles are distinct resources. Combo targets use `provider/model[:weight],provider/model[:weight]`. ```bash @@ -170,6 +172,50 @@ like decision models, with the derived endpoint. See [Combos](/guides/combos/) for routing behavior and configuration guidance. +## Routing profiles + +Existing profiles support inspection and evaluation through the live API: + +```bash +ocx route policy list --json +ocx route policy show reliable --json +ocx route policy dry-run reliable --model-context 128000 --tools --image --structured-output --json +``` + +Only run this evaluation with authority to activate Lab on the target. The management POST can activate Lab and start automation that is already enabled there, including upstream probes. Use list/show for observation without that activation effect. + +Replace `reliable` with a listed ID. `evaluate` is an alias for `dry-run`; both +send requirements to the saved profile's evaluator without an inference request. +Creation, update and deletion remain dashboard operations. Combo writes do not +edit routing profiles. Re-read the profile and revision when an evaluation +surprises you; missing IDs return exit 4 and missing operands return 2. + +## Compatibility Lab + +Lab is local inspection **and** explicit evidence/automation management. Reads +use the local projection and do not require a running management API: + +```bash +ocx lab status --json +ocx lab catalog --json +ocx lab subjects --limit 10 --json +ocx lab automation status --json +ocx lab automation runs --limit 10 --json +ocx lab public community --json +``` + +`subject`, `observations`, `event`, `artifact`, and `production-signals` follow +local evidence lineage. The public family offers preview/export by repeated +`--event `, verification/import through `--file `, and community +context. Export and import write local evidence. Verification can print its +result and still exit nonzero when the bundle is not cryptographically valid. + +Automation enable/disable changes local policy; manual `lab run` selects a layer +and scenario and may spend upstream quota. Read `ocx help lab` and the relevant +leaf before these authorized operations. A saved local policy does not prove +that a separately running proxy's scheduler adopted it. Full automation policy +editing and run cancellation are not exposed by these CLI controls. + ## Observability and debug ### `ocx observe ...` @@ -233,13 +279,24 @@ debug defaults from `OPENCODEX_USAGE_DEBUG=1`. ### `ocx access ...` -Manage OpenCodex admission API keys and inspect external endpoints and models. `ocx api-key - ...` is an alias of `ocx access key`. +Inspect admission keys, external endpoints and models with the access family. +`ocx api-key` aliases the access-key family. Creation and rotation-start return a +one-time plaintext credential in text and JSON output. Agents must leave those +steps to a human-operated terminal outside the agent session; request only +confirmation and non-secret key/rotation IDs, never the credential. ```bash -ocx access key create deployment +ocx access key list --json ``` +After the human configures and verifies the replacement, committing its rotation +or removing the old key requires separate explicit revocation authority. Safe +non-secret follow-ups are `ocx access key rotate commit --json` +and `ocx access key rotate abort --json`, with authority for +the chosen action. Re-list afterward. Missing pending state alone does not prove +commit: expiry or abort can also clear it. Do not route around consent by issuing +the secret-returning management request directly. + ### `ocx api ...` Inspect and set how requests travel between the client APIs and provider wires. See diff --git a/docs-site/src/content/docs/reference/cli/lifecycle.md b/docs-site/src/content/docs/reference/cli/lifecycle.md index ea1eb252960..fafb9e62304 100644 --- a/docs-site/src/content/docs/reference/cli/lifecycle.md +++ b/docs-site/src/content/docs/reference/cli/lifecycle.md @@ -5,6 +5,23 @@ description: Setup, start, stop, service, diagnostics, sync, and update commands These commands install, run, inspect, repair, and update the local opencodex proxy and its Codex integration. +## Discover before starting services + +`ocx help`, `ocx help ` and `ocx help ` are offline. +Use `ocx help --all` when the compact root is insufficient. Help, local config +validation and local Lab inspection do not require starting a proxy. + +Before a live management workflow, run `ocx ready --json` and `ocx status --json`. +Readiness distinguishes `pending`, `failed` and `unreachable`; only `ready: true` +confirms readiness. Check the target and `versionSkew.relation`: `unknown` is not +proof of matching versions. A version mismatch calls for resolving the intended +installation, not repeatedly trying a newer flag against an older server. + +Output and exit conventions are command-specific. `ready` and `resolve` reject +invalid arguments with 64, while `doctor --json` is unsupported and exits 2. +A successful local save or accepted restart request does not prove convergence; +read the command receipt and re-check status after the requested operation. + ## Setup ### `ocx init` · `ocx setup` diff --git a/docs-site/src/content/docs/reference/cli/providers-accounts.md b/docs-site/src/content/docs/reference/cli/providers-accounts.md index a5453b3f12c..5d799beb0ae 100644 --- a/docs-site/src/content/docs/reference/cli/providers-accounts.md +++ b/docs-site/src/content/docs/reference/cli/providers-accounts.md @@ -31,7 +31,7 @@ both `--adapter` and `--base-url`. ocx provider list --json ocx provider list --jsonl # one configured provider object per line ocx provider test ark -ocx provider add anthropic --api-key sk-ant-... --set-default --sync +ocx provider add anthropic --set-default --sync ocx provider add local-dev --adapter openai-chat --base-url http://localhost:11434/v1 ocx provider show anthropic --json ocx provider edit github-copilot --model-context-tier gpt-5.6-luna=long_context @@ -60,9 +60,23 @@ boundary is yours to respect. Two reasons it matters: - Header values are persisted in `config.json` in cleartext, unlike API keys, which have their own storage and masking path. -Use `--api-key` or an OAuth login for anything secret. +Use the supported credential login or stdin flow for secret entry. Do not place +keys in an agent transcript or copy them into command examples. ::: +### Local saves and live provider state + +`list`, `show`, `add`, `remove`, and `set-default` use local configuration; +`edit`, `test`, `quota`, `selected`, `presets`, and `account-mode` use management +calls. Check `ocx ready --json` and `ocx status --json` before live work. A local +list does not establish that an already-running proxy adopted the configuration. + +`provider add --json` reports `needsSync: true` and returns before the human +`--sync` path, even when both flags are supplied. After authorized convergence, +read `ocx inspect config --json` and `ocx models live --provider --json`. +`provider test` checks discovery connectivity; `applicable: false` is an expected +static-catalog result, not successful inference or a failed connection. + ## Authentication ### Diagnosing missing main-account quota @@ -771,10 +785,12 @@ verified official-price fallbacks. Unknown models return `null`; no price is inv Automatic defaults are derived on read and do not populate `modelCosts` in your config, so catalog updates remain effective. Use `set-price` to save provider-specific rates. -Every per-model operation the dashboard offers is available here, so a headless install never needs -the GUI to manage a catalog. `add`, `remove`, and `list-custom` work against the config file and apply -to a running proxy through a catalog sync; the rest talk to the live management API and require the -proxy to be running (`ocx start`, or an installed service). +The table below describes supported catalog workflows. It does not cover every dashboard +operation: editing a discovered model's display name is not the custom-model `edit` operation. +`add`, `remove`, and `list-custom` use local configuration; custom-model writes may attempt +catalog convergence when a proxy is running. A local save does not prove that sync completed. +The remaining model-management operations use the live API. Check readiness and version +before those calls; offline model/config inspection does not require startup. | Subcommand | Supported flags | Action | | --- | --- | --- | @@ -790,6 +806,10 @@ proxy to be running (`ocx start`, or an installed service). | `disable ` | `--native`, `--json` | Hide one model from Codex. | | `provider ` | `--json` | Enable or disable every model of one provider in a single write. | | `selected ` | `--set `, `--clear`, `--json` | Read or replace the provider model allowlist. `--clear` removes the allowlist so every model is offered. | +| `preset show` | `--provider `, `--json` | Read shipped preset versions and the applied mode, optionally for one provider. | +| `preset apply ` | `--all`, `--json` | Apply the curated preset; `--all` clears the allowlist. A zero-match preset leaves selection unchanged and reports `fallback: "preset-empty"`. | +| `new-policy [on\|off]` | `--provider `, `--json` | Read or change exposure policy for newly discovered models; omission of provider selects global policy. A provider read can report `inherit`. | +| `new-arrivals` | `--json` | Read recorded recent discoveries by provider; does not force a new upstream discovery. | | `context [--set-all]\|provider on [--value ]\|provider off\|all >` | `--json` | Read or set the context-window cap, globally or per provider. `value --set-all` also re-points every routed provider (like the dashboard toggle); without it the value only becomes the default. `provider ... on --value ` sets an explicit cap for that provider only (`--value` is valid with `on` only). | | `shadow [model\|-]` | `--enabled `, `--json` | Read or set the replacement model for Codex's background helper calls. `-` clears the model. `status` also reports `sourceModels`, the helper slugs the proxy intercepts (default: `gpt-6-luna`, `gpt-5.6-luna`; clients through 0.144.x used `gpt-5.4-mini`, which an explicit `sourceModels` override can restore). | @@ -814,6 +834,23 @@ and rejects an entire catalog containing any other value, so `add`, `edit`, and all refuse the bad value rather than storing something the catalog writer would have to strip later (#759). +### Apply a preset and verify selection + +```bash +ocx models preset show --provider anthropic --json +ocx models preset apply anthropic --json +ocx models selected anthropic --json +ocx models new-policy --provider anthropic --json +ocx models new-policy off --provider anthropic --json +ocx models new-policy --provider anthropic --json +ocx models new-arrivals --json +``` + +The writes require intent to change selection or discovery policy. Read back the +selection and policy; a saved preset fallback can leave the previous selection +intact. `preset apply --all` is the supported all-models mode; the +dashboard's disabled custom preset does not add another selectable mode. + ### Mark one model text-only Use `ocx provider add mine --adapter openai-chat --base-url https://example.com/v1 --default-model model-a --text-only` when registering a provider, or `ocx provider edit mine --model model-a --text-only` for an existing provider. Add can use `--model` or its default model; edit requires `--model`. The flag updates only that exact model's `modelCapabilities.inputModalities` to `["text"]`, preserving other models and axes. diff --git a/docs-site/src/content/docs/ru/reference/cli/agents.md b/docs-site/src/content/docs/ru/reference/cli/agents.md index 6221a4beed4..bb724a4f9d7 100644 --- a/docs-site/src/content/docs/ru/reference/cli/agents.md +++ b/docs-site/src/content/docs/ru/reference/cli/agents.md @@ -109,13 +109,16 @@ ocx debug usage logs [-f|--follow] ### `ocx access ...` -Управляйте admission API-key'ами OpenCodex и проверяйте внешние endpoint'ы и модели. -`ocx api-key ...` — alias `ocx access key`. +Просматривайте список API-ключей доступа к OpenCodex, внешние конечные точки и модели. `ocx api-key` — псевдоним семейства команд `ocx access key`. + +Создание ключа и начало ротации возвращают секрет в открытом виде, показываемый только один раз, как в текстовом формате, так и в JSON. Агент должен передать эти действия человеку, который выполнит их вручную в терминале вне сеанса агента. Не запрашивайте сам ключ в чате: нужны только подтверждение настройки и проверки подключения, а также несекретные идентификаторы ключа и ротации. ```bash -ocx access key create deployment +ocx access key list --json ``` +Подтверждение работы нового ключа не является разрешением отозвать старый. Для завершения ротации или удаления старого ключа требуется отдельное явное разрешение на отзыв именно этого ключа. После разрешённой операции снова проверьте список. Не обходите этот порядок прямым вызовом API. + ## Интеграции клиентов ### `ocx integration ...` diff --git a/docs-site/src/content/docs/ru/reference/cli/providers-accounts.md b/docs-site/src/content/docs/ru/reference/cli/providers-accounts.md index 899594aa3ab..e7c68ee0d96 100644 --- a/docs-site/src/content/docs/ru/reference/cli/providers-accounts.md +++ b/docs-site/src/content/docs/ru/reference/cli/providers-accounts.md @@ -377,10 +377,7 @@ ocx account main recover [--rollback --yes] [--json] `selected` управляет allowlist'ом провайдера; `context` — provider context cap'ами; `shadow` управляет intercept'ом background shadow-call'ов. -Любая per-model операция, которую умеет дашборд, доступна и здесь, так что headless-установке не -нужен GUI для управления каталогом. `add`, `remove` и `list-custom` работают напрямую с файлом -конфига и применяются к работающему прокси через sync каталога; остальные обращаются к live -management API и требуют, чтобы прокси уже работал (`ocx start` или установленная служба). +В таблице ниже перечислены поддерживаемые CLI операции с каталогом, а не все действия панели управления. Изменение отображаемого имени автоматически обнаруженной модели отличается от операции `edit` для пользовательской модели. Команды `add`, `remove` и `list-custom` работают с локальной конфигурацией; при изменении пользовательской модели может выполняться попытка синхронизации каталога, если прокси запущен. Успешное локальное сохранение не означает, что синхронизация завершена. Остальные операции управления моделями используют API работающего прокси: перед вызовом проверьте его готовность и версию. Для автономного просмотра моделей и конфигурации запускать прокси не нужно. | Подкоманда | Поддерживаемые флаги | Действие | | --- | --- | --- | diff --git a/docs-site/src/content/docs/tr/reference/cli/agents.md b/docs-site/src/content/docs/tr/reference/cli/agents.md index d8a3f847eeb..ad961696fb8 100644 --- a/docs-site/src/content/docs/tr/reference/cli/agents.md +++ b/docs-site/src/content/docs/tr/reference/cli/agents.md @@ -144,14 +144,16 @@ varsayılan olarak `OCX_DEBUG=1`'den gelir (eski `OCX_DEBUG_FRAMES=1` de ### `ocx access ...` -OpenCodex kabul API anahtarlarını yönetin ve harici uç noktaları ile modelleri -inceleyin. `ocx api-key ...`, `ocx access key`'in bir takma -adıdır. +OpenCodex erişim API anahtarlarının listesini, harici uç noktaları ve modelleri inceleyin. `ocx api-key`, `ocx access key` komut ailesinin takma adıdır. + +Anahtar oluşturma ve anahtar yenilemeyi başlatma işlemleri, hem metin hem de JSON çıktısında yalnızca bir kez gösterilen açık metin kimlik bilgisi döndürür. Ajanlar bu adımları, ajan oturumu dışında bir insanın doğrudan kullandığı terminale bırakmalıdır. Anahtarın kendisini sohbette istemeyin; yalnızca yapılandırmanın ve bağlantı testinin tamamlandığına dair onayı ve gizli olmayan anahtar ile yenileme kimliklerini alın. ```bash -ocx access key create deployment +ocx access key list --json ``` +Yeni anahtarın yapılandırılıp doğrulanması, eski anahtarı iptal etme izni değildir. Yenilemeyi kesinleştirmek veya eski anahtarı silmek için o anahtarın iptaline yönelik ayrıca açık izin gerekir. İzin verilen işlemden sonra listeyi yeniden kontrol edin. Doğrudan API çağrılarıyla bu süreci aşmaya çalışmayın. + ## İstemci entegrasyonları ### `ocx integration ...` diff --git a/docs-site/src/content/docs/tr/reference/cli/providers-accounts.md b/docs-site/src/content/docs/tr/reference/cli/providers-accounts.md index 8e8bef8b9e0..81fdff667b7 100644 --- a/docs-site/src/content/docs/tr/reference/cli/providers-accounts.md +++ b/docs-site/src/content/docs/tr/reference/cli/providers-accounts.md @@ -483,12 +483,7 @@ görünürlüğü kontrol eder; `selected` bir sağlayıcı izin listesini kontr `context` sağlayıcı bağlam sınırlarını kontrol eder; ve `shadow` arka plan gölge çağrı müdahalesini yönetir. -Kontrol panelinin sunduğu model başına her işlem burada mevcuttur, bu nedenle -başsız bir kurulum bir kataloğu yönetmek için asla GUI'ye ihtiyaç duymaz. `add`, -`remove` ve `list-custom` yapılandırma dosyasına karşı çalışır ve bir katalog -senkronizasyonu aracılığıyla çalışan bir proxy'ye uygulanır; geri kalanı canlı -yönetim API'si ile konuşur ve proxy'nin çalışmasını gerektirir (`ocx start` veya -kurulu bir servis). +Aşağıdaki tablo, CLI tarafından desteklenen katalog işlemlerini açıklar; kontrol panelindeki tüm işlemleri kapsamaz. Otomatik keşfedilen bir modelin görünen adını değiştirmek, özel bir model üzerindeki `edit` işleminden farklıdır. `add`, `remove` ve `list-custom` yerel yapılandırmayı kullanır; özel model değişiklikleri, proxy çalışıyorsa katalog eşitlemesini deneyebilir. Yerel kaydın başarılı olması, eşitlemenin tamamlandığını göstermez. Diğer model yönetimi işlemleri çalışan proxy’nin yönetim API’sini kullanır; çağrıdan önce hazır olma durumunu ve sürümünü kontrol edin. Modelleri veya yapılandırmayı çevrimdışı incelemek için proxy’yi başlatmak gerekmez. | Alt komut | Desteklenen bayraklar | Eylem | | --- | --- | --- | diff --git a/docs-site/src/content/docs/zh-cn/reference/cli/agents.md b/docs-site/src/content/docs/zh-cn/reference/cli/agents.md index 5607ead7a94..239bf080052 100644 --- a/docs-site/src/content/docs/zh-cn/reference/cli/agents.md +++ b/docs-site/src/content/docs/zh-cn/reference/cli/agents.md @@ -101,13 +101,16 @@ ocx debug usage logs [-f|--follow] ### `ocx access ...` -管理 OpenCodex 准入 API 密钥,并检查外部端点和模型。`ocx api-key - ...` 是 `ocx access key` 的别名。 +查看 OpenCodex 接入 API 密钥列表、外部端点和模型。`ocx api-key` 是 `ocx access key` 命令组的别名。 + +创建密钥和开始轮换时,无论选择文本还是 JSON 输出,都会返回仅显示一次的明文凭据。代理应将这些步骤交给人在代理会话之外直接操作的终端完成。不要索要密钥本身,也不要让用户将其粘贴到聊天中;只接收配置和连接验证的确认,以及非秘密的密钥 ID 和轮换 ID。 ```bash -ocx access key create deployment +ocx access key list --json ``` +确认新密钥已配置并验证连接,不等于批准撤销旧密钥。提交轮换或删除旧密钥前,需要另行获得撤销该密钥的明确授权。执行获准的操作后,再次查看列表。不要通过直接调用 API 绕过这一流程。 + ## Client integrations ### `ocx integration ...` diff --git a/docs-site/src/content/docs/zh-cn/reference/cli/providers-accounts.md b/docs-site/src/content/docs/zh-cn/reference/cli/providers-accounts.md index 6f77503e6b3..e8b01867515 100644 --- a/docs-site/src/content/docs/zh-cn/reference/cli/providers-accounts.md +++ b/docs-site/src/content/docs/zh-cn/reference/cli/providers-accounts.md @@ -344,9 +344,7 @@ v1 恢复矩阵覆盖的是事务文件通过重命名发布后 OpenCodex 进程 `disable` 和 `provider` 控制可见性;`selected` 控制提供方允许列表;`context` 控制提供方 上下文上限;`shadow` 管理后台 shadow-call 拦截。 -这里提供仪表盘中所有逐模型操作,因此无头安装永远不需要 GUI 来管理目录。`add`、 -`remove` 和 `list-custom` 针对配置文件工作,并通过目录同步应用到正在运行的代理; -其余命令会与在线管理 API 通信,并要求代理正在运行(`ocx start`,或已安装的服务)。 +下表说明 CLI 支持的模型目录操作,并不涵盖仪表盘中的所有操作。修改自动发现模型的显示名称与自定义模型的 `edit` 操作不同。`add`、`remove` 和 `list-custom` 使用本地配置;修改自定义模型时,如果代理正在运行,可能会尝试同步目录。本地保存成功并不代表同步已完成。其他模型管理操作使用运行中代理的管理 API,调用前应检查就绪状态和版本。离线查看模型或配置不需要启动代理。 | 子命令 | 支持的标志 | 操作 | | --- | --- | --- | diff --git a/docs-site/src/content/docs/zh-tw/reference/cli/agents.md b/docs-site/src/content/docs/zh-tw/reference/cli/agents.md index 6b33b91c165..8e89e66d454 100644 --- a/docs-site/src/content/docs/zh-tw/reference/cli/agents.md +++ b/docs-site/src/content/docs/zh-tw/reference/cli/agents.md @@ -96,13 +96,16 @@ ocx debug usage logs [-f|--follow] ### `ocx access ...` -管理 OpenCodex 許可 API 金鑰並檢查外部端點與模型。`ocx api-key - ...` 是 `ocx access key` 的別名。 +檢視 OpenCodex 存取用 API 金鑰清單、外部端點與模型。`ocx api-key` 是 `ocx access key` 指令群組的別名。 + +建立金鑰與開始輪替時,無論使用文字或 JSON 輸出,都會傳回僅顯示一次的明文憑證。代理應將這些步驟交由人在代理工作階段之外直接操作的終端機完成。不要索取金鑰本身,也不要請使用者貼到聊天中;只接收設定與連線驗證的確認,以及非機密的金鑰 ID 和輪替 ID。 ```bash -ocx access key create deployment +ocx access key list --json ``` +確認新金鑰已設定並通過連線驗證,不等於核准撤銷舊金鑰。確認輪替或刪除舊金鑰前,必須另行取得撤銷該金鑰的明確授權。執行獲准的操作後,請再次檢視清單。不要透過直接呼叫 API 繞過此流程。 + ## 客戶端整合 ### `ocx integration ...` diff --git a/docs-site/src/content/docs/zh-tw/reference/cli/providers-accounts.md b/docs-site/src/content/docs/zh-tw/reference/cli/providers-accounts.md index e35f067cd8b..3be101615ff 100644 --- a/docs-site/src/content/docs/zh-tw/reference/cli/providers-accounts.md +++ b/docs-site/src/content/docs/zh-tw/reference/cli/providers-accounts.md @@ -325,7 +325,7 @@ Preview 建置使用 `/native-main-profiles`。該配置絕不 `ocx model` 是 `ocx models` 的別名。無子指令時,列出已設定供應商中靜態播種的模型。`--provider` 過濾一個已設定的供應商,而 `--json` 回傳模型中繼資料。`live` 讀取執行中的目錄;`add`、`edit`、`remove` 與 `list-custom` 管理手動目錄項目;`enable`、`disable` 與 `provider` 控制可見性;`selected` 控制供應商允許清單;`context` 控制供應商 context 上限;而 `shadow` 管理背景 shadow-call 攔截。 -儀表板提供的每個 per-model 操作在此皆可用,因此無頭安裝永不需要 GUI 來管理目錄。`add`、`remove` 與 `list-custom` 針對設定檔運作並透過目錄同步套用於執行中的代理;其餘與即時管理 API 通訊並需要代理正在執行(`ocx start` 或已安裝的服務)。 +下表說明 CLI 支援的模型目錄操作,並未涵蓋儀表板中的所有操作。修改自動探索模型的顯示名稱,與自訂模型的 `edit` 操作不同。`add`、`remove` 和 `list-custom` 使用本機設定;修改自訂模型時,如果代理伺服器正在執行,可能會嘗試同步目錄。本機儲存成功不代表同步已完成。其他模型管理操作使用執行中代理伺服器的管理 API,呼叫前應檢查就緒狀態與版本。離線檢視模型或設定不需要啟動代理伺服器。 | 子指令 | 支援的旗標 | 動作 | | --- | --- | --- | diff --git a/scripts/generate-ocx-skill-surface.ts b/scripts/generate-ocx-skill-surface.ts index b0ede70217e..f54fcc1c92d 100644 --- a/scripts/generate-ocx-skill-surface.ts +++ b/scripts/generate-ocx-skill-surface.ts @@ -1,111 +1,182 @@ /** - * 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", "start", "stop", "restart", "service", "gui"] }, + { name: "providers-models", roots: ["provider", "models", "alias"] }, + { name: "accounts", roots: ["account", "auth", "login", "logout"] }, + { name: "agents-routing", roots: ["agent", "combo", "route", "v2", "effort", "memory"] }, + { name: "integrations", roots: ["claude", "integration", "grok", "codex-shim"] }, + { name: "observe-system", roots: ["companion", "usage", "logs", "storage", "inspect", "system", "observe", "debug", "export", "import", "cost", "update", "config", "tray"] }, + { name: "access-remote", roots: ["link", "remote-workspace", "hub", "connect", "api", "access"] }, + { name: "lab", roots: ["lab"] }, +]; - 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("|---|---|"); +function chapterFilename(domain: string): string { + return `01_surface_${domain}.md`; +} + +// 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, "-"); +} + +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; +} + +// These existing discoverable names return plaintext credentials. Preserve their anchors +// as prose handoffs, never turn them into executable-looking recipes. +const SECRET_HANDOFFS = new Set(["ocx link issue", "ocx hub invite", "ocx config export"]); +function capabilityHeading(invocation: string): string { + return SECRET_HANDOFFS.has(invocation) ? `### ${invocation}` : `### \`${invocation}\``; +} + +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(`| \`${head.invocations.join("` `")}\` | ${tableCell(head.summary)} |`); } - lines.push(""); + 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(capabilityHeading(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"); +} - const mutating = CAPABILITIES.filter(c => c.mutates); - const reading = CAPABILITIES.filter(c => !c.mutates); +/** Preserve literal prose inside a Markdown table cell, including enum separators. */ +function tableCell(value: string | undefined): string { + return (value ?? "").replaceAll("\\", "\\\\").replaceAll("|", "\\|").replace(/\r\n|[\r\n]/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); +function renderCapability(cap: Capability): string[] { + const invocation = capabilityInvocation(cap); + const handoff = SECRET_HANDOFFS.has(invocation); + const lines = [capabilityHeading(invocation), ""]; + if (handoff) lines.push("Human-only handoff: ask the operator to perform this in their own terminal or dashboard; do not capture the secret-bearing result.", ""); + if (!handoff && 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}\` | ${tableCell(flag.value)} | ${tableCell(flag.summary)} |`); 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(""); - } } + 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; +} - 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(""); - return lines.join("\n"); +/** 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 6d4c2773830..5392c79fc37 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -2,6 +2,9 @@ "version": 1, "root": "tests", "explicit": { + "cli-capability-integration-workflows.test.ts": "cli", "cli-capability-account-workflows.test.ts": "cli", "cli-capability-agent-workflows.test.ts": "cli", "cli-capability-operation-workflows.test.ts": "cli", + "cli-capability-provider-workflows.test.ts": "cli", "cli-capability-access-workflows.test.ts": "cli", "cli-capability-lab-workflows.test.ts": "cli", "skill-ocx-workflows.test.ts": "ci-workflows", + "cli-capability-data.test.ts": "cli", "skill-ocx-generated.test.ts": "ci-workflows", "cli-update-restart.test.ts": "cli", "cli-update-restart-child.test.ts": "cli", "cli-update-restart-transport.test.ts": "cli", diff --git a/skills/ocx/SKILL.md b/skills/ocx/SKILL.md index 700a0c974b1..075aa807454 100644 --- a/skills/ocx/SKILL.md +++ b/skills/ocx/SKILL.md @@ -1,90 +1,74 @@ --- name: ocx -description: "Drive a running opencodex (`ocx`) proxy from the CLI — account pools, provider routing, model catalog, usage and cost attribution, request logs, access keys, storage cleanup, and the management API. Use when a task involves controlling or inspecting an opencodex proxy rather than editing the opencodex codebase. Triggers: ocx, opencodex, proxy control, account pool, pause account, pool strategy, provider routing, usage report, cost attribution, access key, request log, conversation trace, storage cleanup, management API." +description: "Operate opencodex (`ocx`): discover CLI tasks offline, inspect local configuration, and manage a running proxy’s account pool, providers, models, routing, usage report, and management API. Use for proxy operation rather than editing the opencodex codebase." --- # Operating `ocx` -`ocx` controls a locally running opencodex proxy. The CLI covers the dashboard's operational -surface, subject to Consent and Secret-bearing commands below. `ocx capabilities` -lists the *declared* index, not every verb. +`ocx` supports local configuration and named live management workflows. Coverage is +per task: provider edits, account selection, model visibility, routing reads, client +integration controls and diagnostics have different transports and limits. A shared +API prefix does not prove that every dashboard action has a CLI equivalent. -Be precise about the gap, because guessing costs you more than reading: the capability index below -is complete and authoritative for what it lists, and it does not yet list every management route. -A route with no declared capability may still have a working command — `ocx access key` and -`ocx route policy` both work while `capabilities --route` returns nothing for them. So use the -index first, and fall back to `ocx help` before concluding a capability is missing. +This skill is for **operating** a proxy. `AGENTS_INSTALL.md` covers installation +and operating consent; the repository `AGENTS.md` covers code changes. -This skill is for **operating** a proxy. Two neighbours cover different jobs: `AGENTS_INSTALL.md` -is for installing one, and the repository `AGENTS.md` is for changing the codebase. +## Find the task offline -## Start here +Start at the smallest useful level; no running proxy is needed for help: ```bash -ocx capabilities --json +ocx help # compact root +ocx help models # family and declared children +ocx help models preset show # exact leaf, when declared +ocx help --all # full top-level reference, when needed ``` -That is the machine-readable index of declared verbs, the routes they drive, their flags, and whether they -mutate. Read it first rather than guessing a command name. It is not exhaustive — an unmatched -`--route` exits 4 when the table has no row, even if a working verb exists. The converse of -generation also holds: a verb can exist without appearing here (`ocx access key`, `ocx route policy`). +Then read only the matching [task chapter](references/01_management_surface.md). +For example, use [providers/models](references/01_surface_providers-models.md) +for catalog work or [Lab](references/01_surface_lab.md) for local evidence. +Use `ocx help ` or appended `--help`, not a trailing bare `help` +after nested operands. Missing detail can fall back to family help; it is not +proof that a runtime operation is absent. -Narrow it when you already know what you want: +For a route you already know, an optional lookup is: ```bash -ocx capabilities --mutating-only --json # only state-changing verbs -ocx capabilities --route /api/logs # which verbs drive one route +ocx capabilities --route '/api/providers/{provider}/model-costs' --json ``` -An unmatched `--route` exits 4 rather than printing an empty success. +This matches the **declared path template**, not a concrete provider URL or HTTP +method. Exit 4 means no declaration matched. Full `ocx capabilities --json` and +`--mutating-only --json` are useful for broad inventories, not mandatory preflight. +Declarations describe the installed CLI; actual handlers remain the grammar authority. -## Three steps before any management call +## Before live management work -1. `ocx ready --json` — is the proxy up and admitting requests? -2. `ocx status --json` — is this binary the same build as the running proxy? A version skew means - the help and flags you just read describe a *different* build than the one answering. -3. Then the real command, with `--json`. +1. `ocx ready --json` checks readiness (`ready`, `pending`, `failed`, `unreachable`). +2. `ocx status --json` checks the target and `versionSkew.relation`. `unknown` is + not a confirmed match; a mismatch needs the intended installation resolved. +3. Run the task with `--json` **only when that leaf supports it**. `ocx doctor` + rejects it; `ocx v2` has human output, not a JSON contract. -Skipping step 2 is how an agent ends up reporting that a flag "does not work" when it simply does -not exist in the running build yet. +These checks do not require starting a proxy for offline help, local provider +configuration, config validation or local Lab inspection. On a connected client, +ordinary management commands do not automatically target the hub: perform them +on the hub or use its dashboard. See [remote targeting](references/05_remote_hub.md). -## Exit codes - -| Code | Meaning | -|---|---| -| 0 | success | -| 2 | usage error — bad or missing arguments; nothing was sent | -| 4 | not found — the named account, provider, key, or route does not exist | -| 5 | conflict — a lock is held or the state changed under you; usually retryable | -| 1 | everything else, including transport failure and any other HTTP error | - -**Never read a printed error with exit 0 as success.** Commands used to print a failure and exit 0; -they no longer do, and a source scan keeps it that way. Exit 0 means no error was reported; -inspect the result to see whether anything mutated (cleanup without `--yes` is a preview). - -## Reading a failure - -A management failure prints up to three lines: the message, then `reason:`, then `hint:`. The -`reason` is the machine-actionable part — branch on it, not on the prose. - -Four named classes are worth handling specifically: - -| Reason | What it means | What to do | -|---|---|---| -| `oauth_mutation_busy` | another credential write is in flight (503, `Retry-After: 1`) | retry once after a second | -| `catalog_busy` | a catalog gather is in flight (503, `Retry-After: 1`) | retry once after a second | -| a config-mutation lock reason | a config write holds the lock | retry shortly | -| a credential-conflict reason | the install is broken, not busy | run `ocx doctor`; retrying will not help | - -The first two are transient by construction and the server tells you how long to wait. The last is -the one to stop on: repeating it just produces the same error more times. +Inspect both the exit code and receipt. Saved config, runtime application, client +file convergence, skipped work and partial completion are different outcomes; +read back the relevant setting after a write. Exit 0 also covers previews and +intentional no-ops. Management failures normally print stderr prose even with +`--json`; usage codes include 2 and legacy 64 exceptions for `capabilities`, +`ready`, and `resolve`. See [JSON shapes](references/02_json_shapes.md) and +[failure semantics](references/04_failure_semantics.md) before scripting recovery. ## Consent: one thing you must not do **Do not star the repository on the user's behalf.** `ocx inspect star` reads the status, and that -is the entire CLI surface for it. The starring POST requires a real dashboard session precisely so -an agent cannot answer that question for its user — it spends *their* GitHub identity, which no -flag can delegate. Do not route around it with `gh`, a direct HTTP call, or a minted session. If +is the entire CLI surface for it. The starring POST requires a dashboard session, so an ordinary admin-token +management call cannot perform it. That is not a barrier against a determined local +agent; the consent rule still binds every mechanism because it spends *their* GitHub identity. Do not route around it with `gh`, a direct HTTP call, or a minted session. If starring would be useful, say so and let the user decide. The same boundary covers the session-gated `/api/codex-prompt` writes: read them with @@ -132,58 +116,38 @@ Report the count and bytes from that output and get explicit approval before add `--mode quarantine` (the default) can be undone with `storage trash restore`; `--mode permanent` cannot. -## Remote hub: three things agents get wrong - -**A hub is one port, and `ocx hub invite` writes the join command for you.** Remote machines dial -`hostname:port` with their own per-client key; the hub's own processes dial `127.0.0.1:` with no credential, through the loopback companion listener -(`unauthenticatedLoopbackListener: {"enabled": true}`, no port). Have the operator run `ocx hub invite` -on the hub outside the agent session rather than assembling an `ocx connect` line: it mints a single-use code and prints the exact -command, with both origins already filled in. Its `--management-url` is a confirmation of -`hub.managementPublicOrigin`, not an override. The operator transfers the command directly to the joining machine; keep it out of the transcript. - -Two consequences that look like bugs and are not. `ocx status` on a hub prints a `Hub:` block — -read it before asking the operator anything about ports or tokens. And a hub does not rewrite its -**own** Codex/Grok/Claude configs unless that listener is enabled; the skip says so in those words, -and it is a gate, not the `clientIntegrations` toggle. - -**Pairing is not hub setup.** Configuring a hub — providers, accounts, routing, keys — never -needs a pairing code. `GET /opencodex-session` mints a session by itself for a loopback -request, and for a `hub` reached over the trusted Tailscale ingress when the login is in -`remoteGui.allowedTailscaleUsers`. A pairing grant is the fallback for a remote browser that -neither position nor identity vouches for. The management API is a separate ladder again: an -agent driving a hub uses the admin token and never pairs. When a human asks "do I have to pair -to set this up?", the answer is no. - -**`ocx disconnect` is only half of leaving a hub.** It restores local state and clears the -connection, then tells you the hub key is still valid. Revoke it too: `ocx connect revoke ---admin-token-stdin` while still connected, or delete the key in the hub dashboard under -Integrations → API Keys once the device is gone. Stopping after `disconnect` leaves a working -credential behind. - -Credentials for these commands are stdin-only — `--pairing-code-stdin` and -`--admin-token-stdin`. There is no argv or environment form, and that is deliberate. - -When `disconnect` refuses, do not route around it. Each refusal means the unwind cannot be -proven safe: another process owns the token, no journal records the pre-connect state, a -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 -`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`. +## Remote hub + +Read `ocx status` on the hub and `ocx connect status --json` on the client before +changing their configuration. Pairing is not required to configure the hub. +The optional loopback companion serves inference only, never management calls. +A human transfers the invite directly to the joining machine outside this session. +Remote credential inputs remain stdin-only (`--pairing-code-stdin`, +`--admin-token-stdin`), never literal argv or environment values. + +Disconnect restores local state but leaves the hub key valid. With explicit +revocation authority, revoke while still connected, or have the operator revoke +on the hub after disconnection. Do not work around ownership or partial-restore +refusals. [Remote hub](references/05_remote_hub.md) covers the one-port setup, +credential handoff, managed rotation and disconnection order. ## 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 generated index routes to eight task chapters. Lab includes local reads, +public evidence operations and explicit automation controls; it is not read-only. +Read-oriented probes can contact providers, consume quota or refresh caches. +Routing-profile writes and discovered-model display-name edits are current CLI +gaps; custom-model editing is a different workflow. Browser presentation and +session-only consent actions remain outside agent management authority. + +The index and chapters are generated by `scripts/generate-ocx-skill-surface.ts`. +If metadata and execution disagree, check the installed CLI version and the live +target before reporting unsupported behavior; do not infer a new flag. diff --git a/skills/ocx/references/01_management_surface.md b/skills/ocx/references/01_management_surface.md index 817a98fbc03..c32773037ae 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,1314 +21,1190 @@ 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 `. | +## Task chapters + +| Chapter | Declared capabilities | +|---|---| +| [lifecycle](01_surface_lifecycle.md) | 12 | +| [providers-models](01_surface_providers-models.md) | 40 | +| [accounts](01_surface_accounts.md) | 36 | +| [agents-routing](01_surface_agents-routing.md) | 38 | +| [integrations](01_surface_integrations.md) | 33 | +| [observe-system](01_surface_observe-system.md) | 87 | +| [access-remote](01_surface_access-remote.md) | 22 | +| [lab](01_surface_lab.md) | 21 | + ## Read-only capabilities -Safe to run at any time; none of these change state. +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. -### `ocx link port` +## State-changing capabilities -Allocate a free loopback port for a remote home link. +Check the chapter's flags, the requested authority and the operating skill's consent and secret rules. -Drives no management route. +## Canonical invocation index -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the selected port as JSON. | +Original invocation order. These headings preserve links to the previous single-file reference. -JSON mode: `payload`. +### `ocx chatgpt` -### `ocx link status` +[State-changing task](01_surface_lifecycle.md#ocx-chatgpt) -Read link listener and tunnel status. +### `ocx link port` -| Method | Route | -|---|---| -| GET | `/api/link/status` | +[Read-oriented task](01_surface_access-remote.md#ocx-link-port) -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the K16 status payload as JSON. | +### ocx link issue -JSON mode: `payload`. +[State-changing task](01_surface_access-remote.md#ocx-link-issue) -### `ocx remote-workspace status` +### `ocx link status` -Read local executor enrollment and available capabilities without printing credentials. +[Read-oriented task](01_surface_access-remote.md#ocx-link-status) -Drives no management route. +### `ocx link revoke` -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the public local executor status. | +[State-changing task](01_surface_access-remote.md#ocx-link-revoke) -JSON mode: `payload`. +### `ocx remote-workspace pair` -- Executor-local operation; Hub consent and session control stay in the dashboard. +[State-changing task](01_surface_access-remote.md#ocx-remote-workspace-pair) -### `ocx models price` +### `ocx remote-workspace agent` -Read the saved manual price for an exact provider/model selector. +[State-changing task](01_surface_access-remote.md#ocx-remote-workspace-agent) -| Method | Route | -|---|---| -| GET | `/api/providers/{provider}/model-costs` | +### `ocx remote-workspace status` -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit provider, modelId, and cost (null for automatic pricing). | +[Read-oriented task](01_surface_access-remote.md#ocx-remote-workspace-status) -JSON mode: `envelope`. +### `ocx models price` -- The provider must be configured; everything after the first slash is the exact upstream model ID. +[Read-oriented task](01_surface_providers-models.md#ocx-models-price) -### `ocx status` +### `ocx models set-price` -Proxy status, injection state, and version skew between this CLI and the running proxy. +[State-changing task](01_surface_providers-models.md#ocx-models-set-price) -Drives no management route. +### `ocx models set` -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the status envelope as JSON. | +[State-changing task](01_surface_providers-models.md#ocx-models-set) -JSON mode: `envelope`. +### `ocx status` -- Reads /healthz plus local config; drives no management API route. +[Read-oriented task](01_surface_lifecycle.md#ocx-status) ### `ocx resolve` -One JSON document naming the config home, the effective port, and the identity-checked proxy liveness verdict. +[Read-oriented task](01_surface_lifecycle.md#ocx-resolve) -Drives no management route. +### ocx hub invite -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the resolve document as JSON (the shell contract). | +[State-changing task](01_surface_access-remote.md#ocx-hub-invite) -JSON mode: `envelope`. +### `ocx connect rotate` -- 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. +[State-changing task](01_surface_access-remote.md#ocx-connect-rotate) ### `ocx capabilities` -List the declared CLI capabilities and the management routes they drive. +[Read-oriented task](01_surface_lifecycle.md#ocx-capabilities) -Drives no management route. +### `ocx provider list` -| 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. | +[Read-oriented task](01_surface_providers-models.md#ocx-provider-list) -JSON mode: `envelope`. +### `ocx provider resets` -- Start here when driving ocx programmatically: it is the declared surface index, not a complete verb list. +[Read-oriented task](01_surface_providers-models.md#ocx-provider-resets) -### `ocx provider list` +### `ocx provider keychain` -Configured providers with connectivity and selected models. +[State-changing task](01_surface_providers-models.md#ocx-provider-keychain) -Drives no management route. +### `ocx companion` -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the provider list as JSON. | -| `--jsonl` | boolean | Emit one configured provider per JSON line. | +[State-changing task](01_surface_observe-system.md#ocx-companion) -JSON mode: `envelope`. +### `ocx account login` -- Reads local config; drives no management API route. +[State-changing task](01_surface_accounts.md#ocx-account-login) -### `ocx provider resets` +### `ocx account history` -Recently detected quota resets and whether reset notifications are enabled. +[Read-oriented task](01_surface_accounts.md#ocx-account-history) -| Method | Route | -|---|---| -| GET | `/api/quota-resets` | +### `ocx account main reauth` -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit reset events as JSON. | -| `--limit` | number | Limit returned events; defaults to 20, capped at 100. | +[State-changing task](01_surface_accounts.md#ocx-account-main-reauth) -JSON mode: `payload`. +### `ocx account list` -### `ocx account history` +[Read-oriented task](01_surface_accounts.md#ocx-account-list) -Cached quota observations for one stored Codex pool account. +### `ocx account import-orca` -| Method | Route | -|---|---| -| GET | `/api/codex-auth/quota/history` | +[State-changing task](01_surface_accounts.md#ocx-account-import-orca) -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the bounded observation history. | -| `--limit` | number | Return the newest 1 to 200 observations. | +### `ocx account refresh` -JSON mode: `payload`. +[State-changing task](01_surface_accounts.md#ocx-account-refresh) -- Use account history openai . Reads cached observations only; no refresh or warmup. Native main is not included. +### `ocx account grok-reset-coupons` -### `ocx account list` +[State-changing task](01_surface_accounts.md#ocx-account-grok-reset-coupons) -Codex OAuth accounts with pool priority and pause state. +### `ocx usage` -| Method | Route | -|---|---| -| GET | `/api/codex-auth/accounts` | +[Read-oriented task](01_surface_observe-system.md#ocx-usage) -| Flag | Value | Meaning | -|---|---|---| -| `--json` | boolean | Emit the account list as JSON. | +### `ocx account pause` -JSON mode: `payload`. +[State-changing task](01_surface_accounts.md#ocx-account-pause) -- 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 account resume` -### `ocx usage` +[State-changing task](01_surface_accounts.md#ocx-account-resume) -Token and estimated-cost report over a time range. +### `ocx account pause-exhausted` -| Method | Route | -|---|---| -| GET | `/api/usage` | +[State-changing task](01_surface_accounts.md#ocx-account-pause-exhausted) + +### `ocx account strategy` -| 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. | +[State-changing task](01_surface_accounts.md#ocx-account-strategy) -JSON mode: `payload`. +### `ocx account sticky` -- 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. +[State-changing task](01_surface_accounts.md#ocx-account-sticky) -### `ocx logs` +### `ocx account routes` -Recent request log rows, filterable by provider, model, conversation, account, and status. +[State-changing task](01_surface_accounts.md#ocx-account-routes) -| 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=