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
+16 -18
View File
@@ -17,7 +17,7 @@ pytestmark = pytest.mark.usefixtures("_bind_user")
@pytest.fixture(autouse=True)
def _no_systems():
"""enter_project now surfaces the project's Systems as the tagging
vocabulary (#2546). These are tool-layer unit tests with no database, so
vocabulary. These are tool-layer unit tests with no database, so
the lookup is stubbed to the common case — a project with none. The
populated shape is asserted in its own test below.
"""
@@ -40,7 +40,7 @@ def _no_platforms():
@pytest.fixture(autouse=True)
def _no_coverage():
"""enter_project also reads the pattern-coverage cache (#2692) — same
"""enter_project also reads the pattern-coverage cache — same
deal: no database here, stub the common case (nothing computed). The
populated line is asserted in tests/test_pattern_coverage.py.
"""
@@ -51,7 +51,7 @@ def _no_coverage():
@pytest.fixture(autouse=True)
def _no_family():
"""enter_project reads the family-canon readout (milestone 463 step 6) —
"""enter_project reads the family-canon readout —
no database here, so the common case is stubbed: nothing to answer. The
populated key is asserted in its own test below."""
with patch("scribe.mcp.tools.projects.family_adoption_svc.family_readout",
@@ -61,7 +61,7 @@ def _no_family():
@pytest.fixture(autouse=True)
def _no_background_seed():
"""enter_project now fire-and-forgets a coverage self-seed (#2802). These
"""enter_project fire-and-forgets a coverage self-seed. These
are no-database unit tests, so the spawn is stubbed out; the firing shape
has its own test below."""
with patch("scribe.mcp.tools.projects.spawn") as mock:
@@ -71,7 +71,7 @@ def _no_background_seed():
@pytest.fixture(autouse=True)
def _no_bootstrap():
"""With _no_systems stubbing an empty vocabulary, every test here reaches
the zero-Systems branch, whose bootstrap ask (#2683) counts the project's
the zero-Systems branch, whose bootstrap ask counts the project's
records — a database read. Stub the common case (young project, no ask);
the firing shape has its own test below.
"""
@@ -117,7 +117,7 @@ async def test_get_project_enriches_with_milestone_summary():
async def test_get_project_includes_applicable_rules_and_project_rules():
"""The augmented get_project response includes applicable_rules and
project_rules pulled from services/rulebooks.get_applicable_rules, and
nothing about subscriptions (milestone 414).
nothing about subscriptions.
"""
p = fake_project(id=3, title="Fabled Assistant")
milestone_summary = []
@@ -191,7 +191,7 @@ async def test_update_project_raises_when_not_found():
@pytest.mark.asyncio
async def test_enter_project_composes_full_context():
"""enter_project pulls project + rule titles + milestone summary + open
tasks in one composed call, each in its brief handshake form (#4045)."""
tasks in one composed call, each in its brief handshake form."""
p = fake_project(id=5, title="P")
applicable_payload = {
"rules": [{"id": 1, "title": "r1", "statement": "s",
@@ -226,7 +226,7 @@ async def test_enter_project_composes_full_context():
assert out["project"] == {"id": 5, "title": "P", "status": "active", "goal": ""}
assert out["milestone_summary"] == milestone_summary
# Rules arrive in full by retrieval; the handshake lists the project's own
# by id and title (#4045), and nothing about subscriptions (milestone 414).
# by id and title, and nothing about subscriptions.
assert out["project_rules"] == [{"id": 99, "title": "pr1"}]
for gone in ("applicable_rules", "applicable_rules_truncated", "subscribed_rulebooks",
"suppressed_rules", "suppressed_topics", "recent_notes"):
@@ -244,16 +244,14 @@ async def test_enter_project_composes_full_context():
# create-the-System instruction acts on.
assert out["systems"] == []
# Young project, no bootstrap ask -> the key is ABSENT, not null: it exists
# to be acted on, and a key that usually says null gets skipped (#2483).
# to be acted on, and a key that usually says null gets skipped.
assert "systems_bootstrap" not in out
@pytest.mark.asyncio
async def test_enter_project_surfaces_the_systems_vocabulary():
"""The tagging instruction is only executable if the vocabulary is in
front of the agent when it writes. It never was, and tagging stopped three
days after the feature landed — one System, nothing tagged since July 28
(#2546's audit). Trimmed to id/name/first-line: it rides on every session
front of the agent when it writes. Trimmed to id/name/first-line: it rides on every session
start, and the full charter is get_system's job."""
p = fake_project(id=5)
sys1 = MagicMock()
@@ -298,7 +296,7 @@ def _enter_project_stubs(p):
@pytest.mark.asyncio
async def test_enter_project_carries_the_bootstrap_ask_when_it_fires():
"""The arrival-moment half of #2683: a mature zero-Systems project greets
"""The arrival-moment half of the bootstrap ask: a mature zero-Systems project greets
the session with the concrete bootstrap ask, before it is deep in a task —
the moment minting a starter vocabulary is cheapest."""
import contextlib
@@ -341,7 +339,7 @@ async def test_enter_project_never_asks_bootstrap_once_a_vocabulary_exists(
async def test_enter_project_fires_the_coverage_seed_on_the_owner(
_no_background_seed,
):
"""The arrival self-seed (#2802): entering spawns refresh_if_stale on the
"""The arrival self-seed: entering spawns refresh_if_stale on the
project OWNER's id with the cache read the enter already did — fire and
forget, so a missing ledger seeds itself without the UI button, and the
enter stays fast."""
@@ -393,7 +391,7 @@ async def test_enter_project_hands_back_the_design_system_when_the_project_has_o
assert out["design_system"]["token_count"] == 95
assert out["design_system"]["inherits_from"] == ["House"]
# Summary only: the guidance is one call away (#4045).
# Summary only: the guidance is one call away.
assert "guidance" not in out["design_system"]
assert out["design_system"]["guidance_call"] == "get_design_system(9) → resolved_guidance"
assert ctx.await_args.args == (7, 9) # caller's id, the project's system
@@ -418,7 +416,7 @@ def test_enter_project_registered_in_register():
assert "enter_project" in mcp.names
# --- milestone 297: the inception doors ---------------------------------------
# --- the inception doors -----------------------------------------------------
@pytest.mark.asyncio
@@ -491,7 +489,7 @@ def test_inception_routes_and_tool_are_registered():
tool = mcp._tool_manager.get_tool("create_project")
for name in ("design_system_id", "seed_systems"):
assert name in tool.parameters.get("properties", {}), name
# Rules left inception with subscriptions (milestone 414).
# Inception carries no rulebook subscriptions.
assert "subscribe_rulebooks" not in tool.parameters.get("properties", {})
@@ -500,7 +498,7 @@ def test_inception_routes_and_tool_are_registered():
async def test_enter_project_carries_the_family_line_only_when_it_asks_something(_no_family):
"""The `family` key is attached when the project has family canon to
answer, and absent otherwise — a key that usually says null trains
readers to skip it (#2483)."""
readers to skip it."""
line = {"line": "family canon on this project's platforms: 2 unassessed",
"unassessed": 2, "owed": 0, "needs_recheck": 0,
"calls": {"unassessed": 'list_family_adoptions(project_id=5, status="unassessed")'}}