Skip to content

feat(protocol): add runtime/capabilities - #242

Merged
oratis merged 1 commit into
mainfrom
feat/runtime-capabilities
Aug 8, 2026
Merged

feat(protocol): add runtime/capabilities#242
oratis merged 1 commit into
mainfrom
feat/runtime-capabilities

Conversation

@oratis

@oratis oratis commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary

PR 5 of docs/FLOATBOAT_ADOPTION_PLAN.md §2.C. Additive protocol method — no existing call changes shape.

initialize() already reports capabilities, but every flag in it is a protocol feature (threadResume, workspaceDiff, reviewActions). No client can ask the question that actually matters before it starts trusting a runtime: where will this write, and what will it stop to ask me about?

The distinction is load-bearing

Method Answers
initialize Which protocol methods work — flags about this server's feature set
runtime/capabilities What authority the runtime holds over the machine — write scope, always-confirmed actions, whether the sandbox is actually in effect, whether a contract is loaded

Keeping them apart is also the rule for where the next field goes: describes the server's implementationinitialize; describes the authority → here. docs/design/app-server-v1.md states that rule so it survives me.

This makes the alignment plan's P0 executable

CODEX_ALIGNMENT_PLAN.md lists "permissions and tool execution are not a unified runtime capability" as P0 — different hosts resolve the same settings differently.

The CLI (RuntimeHost.capabilities) and the app-server (capabilitiesFor) both build the payload through one function in core, and apps/server/src/capabilities.test.ts asserts they agree field-for-field on the same settings: sandbox posture, write scope, contract status, rule counts, ledger path. If they ever drift, it fails there rather than in someone's workspace.

VS Code and the LSP are thin protocol clients over the app-server (apps/vscode/src/extension.ts:1, apps/lsp/src/handler.ts:1), so they receive the server's answer verbatim and are equal by construction. Stating that rather than claiming four independently-verified hosts — only two resolve policy on their own.

Two deliberate choices in the payload

writeScope reports ["<everything: sandbox disabled>"] under danger-full-access, not []. An empty array reads as "writes nowhere" — the exact opposite of the truth, and the most dangerous thing this declaration could get wrong.

Permission rules are reported as counts, not contents. The rules can hold user paths; a count answers "is anything configured" without handing them to every client that asks. There's a test asserting a rule name never appears in the serialized payload.

Also

deepcode doctor prints the same declaration from the same builder, so it cannot describe a posture the runtime does not have — including the file-contract warnings from #239.

Adding the capability flag broke three client fixtures at compile time (desktop, LSP, VS Code). That's the signal working as intended; all three updated.

Test plan

  • pnpm test1360 passed, 16 skipped (+23: 914 core, 47 server, 31 protocol)
  • pnpm typecheck · pnpm lint · pnpm format:check · pnpm build · node scripts/check-docs.mjs
Area Cases
Builder Purity; workspace-write scope; explicit allowWrite paths; read-only ⇒ empty; danger-full-access ⇒ "everything", not empty; unconfigured falls to host default
Disclosure Rule names never appear in the payload, only counts
Status absent / loaded / invalid all surface; modules map to enabled/disabled
Cross-host agreement 6 cases comparing CLI and app-server output: defaults, sandbox off, rule counts, contract loaded, contract invalid ≠ absent, same ledger path

Documentation

  • docs/design/app-server-v1.md — method added to the table, plus a section on the initialize distinction, the payload shape, and the two choices above

Release notes label

  • release-notes:feature

Related

Plan §2.C (PR 5). Research: docs/research/floatboat.md §4.4(3). Addresses CODEX_ALIGNMENT_PLAN.md P0 "权限与工具执行不是运行时统一能力".

🤖 Generated with Claude Code

initialize() already reports capabilities, but every flag in it is a protocol
feature — threadResume, workspaceDiff, reviewActions. No client can ask the
question that actually matters before trusting a runtime: where will this write,
and what will it stop to ask me about?

Adds `runtime/capabilities`, kept separate from initialize on purpose. That one
answers "which methods work"; this one answers "what authority does this runtime
hold over my machine". The split is also the rule for where the next field goes.

Both the CLI and the app-server build the payload through one function in core,
and a test asserts they agree field-for-field on the same settings — sandbox
posture, write scope, contract status, rule counts, ledger path. The alignment
plan's P0 is that permissions and tool execution are not a unified runtime
capability; this makes that claim executable instead of aspirational. VS Code
and the LSP are thin protocol clients, so they get the server's answer verbatim.

Two deliberate choices in the payload:

- writeScope reports ["<everything: sandbox disabled>"] under
  danger-full-access, not []. An empty array reads as "writes nowhere", the
  exact opposite of the truth and the worst thing this could get wrong.
- Permission rules are reported as counts, not contents. The rules can hold user
  paths; a count answers "is anything configured" without handing them out.

`deepcode doctor` now prints the same declaration, so it cannot describe a
posture the runtime does not have.

Adding the capability flag broke three client fixtures at compile time, which is
the signal working as intended.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@oratis
oratis merged commit 6d91bb9 into main Aug 8, 2026
5 checks passed
@oratis
oratis deleted the feat/runtime-capabilities branch August 8, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant