diff --git a/docs/dev/SPECIFICATION.md b/docs/dev/SPECIFICATION.md index 6cf88c6..53b4e97 100644 --- a/docs/dev/SPECIFICATION.md +++ b/docs/dev/SPECIFICATION.md @@ -113,7 +113,7 @@ The gate is the env var `UI_ENABLE_CONTENT_REPLACEMENT` (strict equality `=== 't When the gate is closed (default), the server's `tools/list` returns the 4 Bear-domain read-only tools plus `bear-capabilities`, a discovery tool registered conditionally (only when the gate is closed). The `initialize` response's `instructions` field carries the unlock guidance, but it's unreliable across MCP clients (Claude Desktop and OpenCode drop it; Codex CLI reroutes it), so `bear-capabilities` surfaces the same guidance through `tools/list` — the only channel guaranteed to reach the model in every client. When the gate is open, the 12 Bear-domain tools are advertised in `tools/list` and `instructions` carries the edit-mode guidance; `bear-capabilities` is not registered because there's nothing left to unlock. -The read/write classification is locked in by the system test at `tests/system/registration-gate.test.ts`. Its `EXPECTED_READ_ONLY_TOOLS` and `EXPECTED_WRITE_TOOLS` constants enumerate which tool falls in which class; `task test:system` (run locally before merge) fails if a future tool registration is misclassified. System tests cannot run in CI — see _Testing Constraints_ below. +The read/write classification is locked in by the system test at `tests/system/registration-gate.test.ts`. Its `EXPECTED_READ_ONLY_TOOLS`, `EXPECTED_OFF_ONLY_TOOLS`, and `EXPECTED_WRITE_TOOLS` constants enumerate which tool falls in which class; `task test:system` (run locally before merge) fails if a future tool registration is misclassified. System tests cannot run in CI — see _Testing Constraints_ below. **Why registration-time, not call-time.** With the gate at call time the LLM still sees write tools in `tools/list`, picks one, and receives a runtime error — wasted tokens and confusing UX. Registration-time gating gives the user a _provably_ read-only mode verifiable with a single MCP wire call. The gate also widens past content replacement: it now covers all 8 write operations, not just `bear-replace-text`. The user-facing label "Edit Mode" replaces the older "Content Replacement" to reflect this widened scope.