Skip to content

daily use app server

Kazushi Kamegawa edited this page Oct 7, 2026 · 1 revision

Daily-use App Server Features — Issue #155

日本語

Date: 2026-10-08 Tracking: Issue #155, under #149. Umbrella plan: Codex App Server Update and Remote Connection, Phase 6. Status: Approved design and plan (2026-10-08). Implementation not started.

Summary

Complete the remaining daily-use App Server features against CLI 0.159.1 stable, with 0.155.1 regression fixtures, by extending the merged #152 (mapping/ownership), #153 (history and saved-attachment metadata recovery) and #154 (questions/permissions/MCP interaction) foundations. Baseline: commit 69deda1 (PR #169 merged), Worker contract v20; allocate the next available contract version at merge time. No CLI, SDK, runtime or package upgrade.

Reuse, do not rebuild: catalog model IDs/defaults/hidden defaults/reasoning efforts/service tiers with inherited/persistent/next-turn settings, structured turn/plan/updated steps, composer attachments and localImage, #153 bounded thread/attachment/list paging/tombstones/single-flight recovery, and #154 MCP authentication/elicitation.

Design

Plans and status

  • Keep turn/plan/updated as the structured step snapshot. Add item/plan/delta as bounded provisional text per item; the completed plan item replaces it (final text may differ from concatenated deltas). Never parse text into duplicate steps.
  • The pinned stable schema describes item/plan/delta as EXPERIMENTAL: treat it as optional, render a completed plan correctly without any delta, and record it as experimental-described in the contract file.
  • Completed state wins over duplicate/late deltas and history/live overlap. Bounds: plan text 64 KiB UTF-8, 200 structured steps, existing history and notification buffers, 50–100 ms batching.
  • Handle thread/status/changed, configWarning, model/rerouted, model/verification and item/mcpToolCall/progress in a bounded notice area (50 notices/thread, 4 KiB each, coalesced by kind and identity). Connection readiness and thread status are shown separately. model/verification is informational and never answers or launches native verification.

Catalog and input admission

  • The live catalog is the source of truth; accept max/ultra only when advertised and never hard-code a default model.
  • Add bounded inputModalities and availableAccessPrograms to the model projection. Omitted inputModalities uses the schema default (text, image); an explicit empty list or unknown value is not permission.
  • Validate the effective model in the composer and in the Worker immediately before turn/start. Unsupported input stays in the composer with a reason; the model is never silently changed. Non-image files stay mention inputs (mapped server path references) needing text support only, images require image support, there is no generic file modality; audio/unknown modalities are display-only.

Explicit shell

  • Entry point is only /shell [--timeout-ms N] -- <command>; suggestion selection never executes. /shell becomes the ninth built-in, and the suggestion list shows up to nine built-ins without dropping skills.
  • Preserve the command after -- exactly. Reject empty command, duplicate/unknown options, negative, malformed and over-int64 timeouts. Omission uses the server default (one hour); zero is immediate timeout; no value means unlimited.
  • Only a joined, current-owner idle thread is eligible. A confirmation shows connection/profile, thread, exact command (inert text, never logged raw), server cwd, timeout and that thread/shellCommand always runs unsandboxed with full access in 0.159.1.
  • After Execute, revalidate target/generation/cwd and evaluate IApprovalPolicyEngine locally; policy denial cannot be overridden and Full access or old grants never skip confirmation.
  • The empty RPC response is an acknowledgement, not completion; its deadline is independent of the execution timeout. Events are shown by their real thread/turn/item IDs without claiming correlation to the request.
  • One pending shell submission per thread: released on a definitive acknowledgement or error; after acknowledgement timeout or disconnect it stays locked until the generation retires, and a new generation allows submission only once thread/status reports idle.
  • Cancel before dispatch sends nothing. No request-specific Stop after dispatch and no interrupt inferred from timing or text. No replay, no fallback to command/exec or a local process.

Typed results and local file actions

  • Project text, MCP content, imageView/imageGeneration and fileChange into typed bounded parts; generic JSON is a reasoned fallback. Track server truncation and local display limits separately.
  • Raw payloads and server paths stay in the Worker; Remote UI receives sanitized metadata and opaque owner/generation-bound action IDs.
  • Changed-file links, artifacts, Open and Reveal go through RemotePathMapper and LocalPathBoundary and are revalidated (existence, type, owner, symlink/junction) immediately before the action. Raw server paths are never opened.
  • Preview PNG/JPEG only: MIME/signature agreement, at most 10 MiB input, 4,096 × 4,096 and 16 million pixels, checked before full decode; owner/generation-scoped cleanup. No SVG/HTML, remote fetch, automatic browser launch or raw URI binding. fileId is opaque; mcpAppUi gets a text fallback, not an embedded web runtime.

Saved attachments

  • Saved attachments are metadata records, not uploads or composer chips, and never auto-insert model input. The wire contract has only attachmentType, identityKey and arbitrary payload.
  • Client-owned type relaycodex.file.v1 with payload { version: 1, serverPath, mimeType, displayName }; serverPath is an absolute normalized server-domain path. identityKey is a version-prefixed SHA-256 of the server path normalized by the server OS path rules from initialization, independent of the local profile mapping.
  • Known MIME: text/plain, application/pdf, image/png, image/jpeg (preview PNG/JPEG only). Unknown types/versions and malformed payloads stay visible and read-only with a reason.
  • Add revalidates source, protected-directory policy, profile/root mapping and physical containment; respects created/existing without overwriting. Remove sends type + identityKey, requires confirmation and policy evaluation, validates owner/profile/root and payload provenance but not the target file's existence; absent removal succeeds.
  • Keep #153 bounds and reconciliation (limit 50, 100/page, 100 active/thread, 64 KiB payload, 256-byte type/key). Record NotSent / definitive / OutcomeUnknown; idempotency never authorizes retry; uncertain outcomes are checked by read-only list without claiming causality.

Local Windows sandbox setup

  • Offered only for owned local stdio after initialization confirms Windows; never for remote profiles.
  • Explicit elevated/unelevated mode and Start. The optional cwd is the active solution root validated by LocalPathBoundary and shown before Start, or null when no solution is open.
  • States: Not observed, Starting, Running, Succeeded, Failed, Unsupported, OutcomeUnknown. started=true is not success; started=false is not proof of success; completion may precede the acknowledgement. Indeterminate progress only.
  • One attempt per connection generation (including after failure or unknown outcome); stale or unsolicited completions are ignored. Errors are bounded and redacted; no automatic retry.

0.159.1 additive fields

availableAccessPrograms read-only; disabledPluginIds displayed without a plugin editor; MCP serverName/httpOrigin/serverCapabilities as filtered status metadata; mcpAppUi with text fallback; opaque image.fileId; distinct flexUnavailable/tooManyDenials reasons without retry; promax displayed without quotas. rollout/compress is excluded. No daemon/worktree, Realtime, dynamic tools, ExternalMessage, plugin import/editor, native verification success or attestation.

Work packages

Package Content Depends on
P0 Contract version, used-method registration (stable vs experimental), pinned-schema fixtures, typed DTOs and payload registry —
P1 Plan delta/final, thread/config/model/MCP notices, modality admission on both sides of the Bridge, additive fields P0
P2 Typed parts, PNG/JPEG preview lifecycle, changed-file Open/Reveal with action-time validation P0, P1 envelope
P3 relaycodex.file.v1 reader/writer, explicit add/remove, outcome tracking on the existing store P2
P4 /shell parser, confirmation, policy gate, dispatch and pending lock P0, P1
P5 Local Windows setup state machine P0
P6 Integration, sub-agent review, full validation and screenshots P1–P5

Files

Worker: CodexSessionService, WorkerRpcService, notification parsers. Contracts: WorkerContracts, InteractionContracts. Extension: WorkerBridge, ChatViewModel, tool window XAML, FilePickerService. Shared: RemotePathMapper, LocalPathBoundary, IApprovalPolicyEngine, SafeMarkdownService, ISecretRedactor. Contract: app-server-contract.json.

Tests

Fake App Server and pinned 0.159.1 / 0.155.1 fixtures: completed plan without delta, final-before-late-delta, status bursts, owner switch during catalog load; unsupported modality kept in composer; shell parsing/timeouts/policy denial/pre-dispatch cancel/no Stop/other-client turns/pending-lock release/zero replay; typed mixed results, invalid and oversized media, junction escape between render and action; attachment created/existing, absent remove, stale pages, unknown types, missing target, reconnect/history/fork, uncertain delivery; sandbox completion-before-response, started=false, unsupported method, cwd validation, retired generation and remote refusal.

Docs

Repository: doc/daily-use-app-server-design.md, doc/daily-use-app-server-plan.md and their _ja pairs, ADR-016 amendment, doc/design.md section 17, doc/plan.md section 13, doc/app-server-update-plan.md Phase 6. Update doc/slash-commands.md with the shell implementation.

Verification

Targeted then full Core/UI tests, warning-free Debug and Release builds, pinned schema and used-method checks, VSIX DTO/XAML integrity. Experimental Instance screenshots for Light, Dark, High Contrast, narrow width, keyboard/focus and accessibility. Missing screenshots remain unmet criteria. #155 stays open until all evidence is recorded; #156 keeps the release gate.

Clone this wiki locally