OMP Workbook

Read the source. Follow the evidence.

Boundary Desk: when the host can ask

Nia next hears that RPC is headless and concludes it cannot ask for approval. That conclusion confuses a physical terminal with a semantic UI adapter.

The wrapper asks its extension runner whether UI is available. In the supplied runner, hasUI() is implemented as a comparison against the built-in no-op UI context. It is not a test for a keyboard, TTY, window, or working client display.

Separate three questions

Ask these independently:

  1. What host mode is running?
  2. Which UI context was installed on the runner or tool context?
  3. Does that adapter actually support the requested selection operation?

The SDK’s initial hasUI and interactivePrompts options, the tool context’s UI state, and ExtensionRunner.hasUI() serve related but distinct consumers. A boolean from one is not proof of every capability in the others.

Host pathSource-backed approval surfaceImportant limit
TUIExtensionUiController installs selector-based UI.Component/controller evidence is not physical key-delivery proof.
RPCrunRpcMode() installs RpcExtensionUIContext on extension initialization; select uses RPC request/response helpers.A connected client must handle the semantic request. Native custom components and raw terminal input are not provided.
ACPcreateAcpExtensionUiContext() translates supported dialogs into form elicitations.Support depends on negotiated elicitation.form; other methods remain stubbed.
Default print/JSON extension initializationNo UI context is supplied to the runner.A required approval fails closed; automatically allowed calls need not prompt.

In runRpcMode(), the optional setToolUIContext callback is called with the adapter and true when supplied. main.ts supplies that callback for rpc-ui, not ordinary rpc. Nevertheless, both use the RPC adapter in initializeExtensions(), which is the runner UI consulted by this approval wrapper. This is why the initial tool-UI flag does not justify flattening ordinary RPC into no-UI.

Read the two RPC cases

boundary-rpc-approve and boundary-rpc-cancel use the same exec-tier fictional call in always-ask mode. Their ui value is rpc.

Prediction: what should a positive correlated response and a cancelled response do?

Recorded answer: each produced one select request through the real requestRpcSelect() helper and was answered through the real dispatchRpcControlFrame() helper. The positive response produced one inert execution. The cancelled response became undefined, produced no execution, and threw the user-denial error. Both left zero pending requests in the helper map.

This is stronger than merely printing an expected frame: the supplied verifier exercised the actual helper functions and wrapper. It is narrower than launching a full RPC process or proving a real client rendered a dialog. The runner itself was a structural adapter, and the responses were supplied in-process.

The source also gives RpcPendingExtensionRequests.rejectAll() a disconnect failure path. That is source-backed here, not an additional workbook disconnect scenario.

ACP requires capability-specific language

The ACP adapter checks clientCapabilities.elicitation.form. Without form support, select() returns undefined, confirm() returns false, and editor/input paths return their unavailable values.

AcpAgent.#configureExtensions() still passes a distinct UI adapter to the extension runner. As a result, the runner can report hasUI: true even when a particular form operation is unavailable. For a required generic tool approval, that unavailable selection can be refused as a non-Approve response rather than taking the runner’s literal no-UI branch.

This is not evidence that a person selected Deny. It is an adapter capability boundary. The supplied ACP setup also marks the tool UI available through its callback when form support is present, and exposes extension mode as rpc; neither means terminal components work.

ACP plan-proposal approval has its own control flow and capability fallback. It is not the generic two-choice tool gate. Do not borrow its behavior or menu to explain a tool_approval_requested event.

No UI is a reason to stop, not permission to skip

Compare boundary-no-ui with dispatch-inspect-no-ui. Both have no UI. The first needs a prompt and refuses; the second is read-tier at the applicable gates and returns without a prompt. Absence of UI does not automatically deny all tools, and it does not automatically approve a required prompt.

The stock no-UI error lists configuration-widening possibilities. This workbook does not recommend them as the generic repair. First establish why a prompt is required, whether the operation is still intended, and whether the owning host has a supported approval surface. On this route, simply record the refusal and continue reading.

Paper checkpoint: is hasUI: true sufficient proof that a native panel or an ACP form can be used? Worked answer: no. It can indicate only a non-no-op adapter. Check the specific mode and negotiated operation capability.

Failure boundary: no physical terminal, keyboard, full RPC client process, or ACP client flow was exercised by the new private scenarios. Transport-helper success does not upgrade itself into those claims.

Source anchors: packages/coding-agent/src/extensibility/extensions/runner.ts — hasUI, initialize; packages/coding-agent/src/modes/rpc/rpc-mode.ts — runRpcMode, requestRpcSelect, requestRpcDialog, dispatchRpcControlFrame, RpcPendingExtensionRequests; packages/coding-agent/src/modes/acp/acp-agent.ts — createAcpExtensionUiContext, AcpAgent.#configureExtensions; packages/coding-agent/src/modes/runtime-init.ts — initializeExtensions; packages/coding-agent/src/modes/print-mode.ts — runPrintMode; packages/coding-agent/src/main.ts — runRootCommand.

Tool permissions and approvals · Source chapter: permissions/boundary-desk-when-the-host-can-ask. Original evidence remains scoped to its recorded snapshot.

Read this chapter as Markdown

Your lesson ticks

A self-reported reading checklist, not proof of real OMP behavior. Only these ticks are saved in this browser. Reading a milestone does not resume, fork, reset or export a session.

Chapters I have worked through
Start here 1
Sessions, resets, and reviewable history 19
Memory and reusable knowledge 14
Tangent work and live control 17
Tool permissions and approvals 15
Extensions inside those boundaries 23
Connections and next steps 8
0 of 97 checked

Checklist saving needs JavaScript and available browser storage.