docs(6209): calibration stamp, after-write hook, usage seam, work log, duplicates, skill structure, tuning and rulebook routes, kind surface, prompt filter, moments, strict args, auth, lesson write path

Fourteen more test files: docstrings state the failure each guard defends
as a present-tense shape instead of the incident that found it, and issue,
milestone and rule numbers leave comments and assertion messages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 21:35:44 -04:00
co-authored by Claude Opus 5.5
parent d0d278dcce
commit ba0b56018e
14 changed files with 90 additions and 104 deletions
+8 -9
View File
@@ -1,13 +1,12 @@
"""Unknown tool arguments are rejected, never silently dropped (#2709).
"""Unknown tool arguments are rejected, never silently dropped.
The failure this pins: MCPServer validates tool arguments with a pydantic model
whose extra-field policy is "ignore", so `create_note(content=...)` — a
plausible near-miss for `body=`, primed by add_task_log's `content` — ran
successfully, stored `body: ""`, and left a record embedding/search cannot
see. The call REPORTED SUCCESS. Two real notes were persisted body-less
before the pattern was noticed.
plausible near-miss for `body=`, primed by add_task_log's `content` — would
run, store `body: ""`, and leave a record embedding/search cannot see, while
REPORTING SUCCESS.
The fix is at the dispatch seam, not per-tool: StrictArgsMCPServer rejects any
The rejection is at the dispatch seam, not per-tool: StrictArgsMCPServer rejects any
call carrying arguments the tool does not declare, with a did-you-mean when
one is close. An error the caller sees once beats data half-written forever.
"""
@@ -59,11 +58,11 @@ async def test_unknown_tool_keeps_the_upstream_error():
assert "no_such_tool" in str(exc.value)
# --- a refusal's text reaches the agent (#4794) -------------------------------
# --- a refusal's text reaches the agent ---------------------------------------
#
# SDK 2.x passes on only a ToolError's text; anything else is wrapped as
# "Error executing tool X" and its message is kept on the server. ValueError is
# how every Scribe tool refuses, so for weeks every refusal arrived bare.
# how every Scribe tool refuses, so without this every refusal arrives bare.
def _raising_server() -> StrictArgsMCPServer:
@@ -112,7 +111,7 @@ async def test_a_real_tools_refusal_reaches_the_caller():
async def test_the_original_regression_create_note_with_content():
"""Pin #2709 itself against the REAL server: `content=` on create_note
"""Against the REAL server: `content=` on create_note
must raise before dispatch — naming the bad argument and listing `body`
among the accepted ones — instead of creating a body-less note."""
from scribe.mcp.server import build_mcp_server