docs(6209): twelve more test files say which behaviour they pin
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 14s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / integration (push) Successful in 1m12s
CI & Build / Python tests (push) Successful in 1m53s
CI & Build / Build & push image (push) Successful in 12s

shape ledger, MCP projects/search/rulebooks tools, backup, chunking,
plugin context, derived mirror, rule band, shape form gate, plugin
version mint and note usage tests drop issue, milestone and rule numbers,
dates and one-install figures from docstrings, comments and messages.
Three shape-form-gate test names that told the discovery story now name
the property: a registry module's helpers are not service functions, the
divergence gate silences only a family contradiction, and callable helpers
beside a callable canon still prompt. The rulebook tool-count comment that
logged each milestone's additions is replaced by the reason it is a count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 21:24:50 -04:00
co-authored by Claude Opus 5.5
parent 91c96a8b8a
commit d41e72d26c
12 changed files with 223 additions and 265 deletions
+10 -21
View File
@@ -49,8 +49,7 @@ async def test_get_rulebook_raises_when_not_found():
await get_rulebook(rulebook_id=999)
# _plain_detail moved to tests/helpers on its second copy (#2825's own
# reason for existing): two stubs for one seam drift apart quietly, and a
# _plain_detail lives in tests/helpers: two stubs for one seam drift apart quietly, and a
# test stubbing it slightly differently asserts something slightly different
# than it appears to.
@@ -199,16 +198,7 @@ def test_register_attaches_every_tool():
mcp = FakeMCP()
register(mcp)
# 26 through milestone 307, +2 for the staleness sweep (milestone 312),
# +1 for a rule's edit history (milestone 323), +2 for preferences
# (milestone 399).
# 28 since milestone 394 took list_always_on_rules and the two
# always-on exclusion tools with the tier they served.
# 22 since milestone 414 retired subscriptions and suppressions: the two
# subscribe tools and the four suppress/unsuppress tools. 23 with move_rule
# (milestone 414 step 3), the way a rule changes home. 24 with
# rule_outcome (milestone 419 step 1), the way a rule says what it
# actually changed.
# Pinned as a count so a tool added or dropped is a deliberate edit here.
assert len(mcp.names) == 24
# spot-check a few names
assert "list_rulebooks" in mcp.names
@@ -221,12 +211,12 @@ def test_register_attaches_every_tool():
assert "update_preference" in mcp.names
assert "create_project_rule" in mcp.names
assert "move_rule" in mcp.names
# milestone 312: the sweep, and the stamp that answers it
# the sweep, and the stamp that answers it
assert "rules_due_for_verification" in mcp.names
assert "mark_rule_verified" in mcp.names
# milestone 323: what a rule used to say
# what a rule used to say
assert "rule_history" in mcp.names
# milestone 414: a rule's home is its scope; nothing subscribes or mutes.
# a rule's home is its scope; nothing subscribes or mutes.
for gone in ("subscribe_project_to_rulebook", "unsubscribe_project_from_rulebook",
"suppress_rule_for_project", "unsuppress_rule_for_project",
"suppress_topic_for_project", "unsuppress_topic_for_project"):
@@ -292,7 +282,7 @@ async def test_create_project_rule_uses_explicit_title_when_given():
assert kwargs["title"] == "no auto-docstrings"
# ── Typed edges between rules (milestone 307) ───────────────────────────
# ── Typed edges between rules ───────────────────────────────────────────
@pytest.mark.asyncio
async def test_relate_rules_forwards_the_kind_and_the_why():
@@ -336,7 +326,7 @@ async def test_unrelate_rules_raises_when_the_edge_is_gone():
await unrelate_rules(relation_id=99)
# ── rule_history (milestone 323 step 3) ────────────────────────────────
# ── rule_history ───────────────────────────────────────────────────────
def _fake_version(**over):
"""A RuleVersion-shaped stand-in. A real model instance rather than a
@@ -397,9 +387,8 @@ async def test_rule_history_opens_one_version_in_full():
@pytest.mark.asyncio
async def test_rule_history_says_an_empty_history_is_ordinary():
"""Most rules have never been reworded, and nothing was written before
milestone 323. Without this line an empty list reads as a lost history or
a broken tool."""
"""Most rules have never been reworded. Without this line an empty list
reads as a lost history or a broken tool."""
with patch(
"scribe.mcp.tools.rulebooks.rulebooks_svc.list_rule_versions",
AsyncMock(return_value=[]),
@@ -482,7 +471,7 @@ async def test_move_rule_on_someone_elses_rule_is_not_found():
await move_rule(rule_id=94, project_id=3)
# ── rule_outcome: what a rule actually changed (#4212, milestone 419) ─────
# ── rule_outcome: what a rule actually changed ───────────────────────────
@pytest.mark.asyncio
async def test_rule_outcome_records_an_application():