docs(6209): coverage, guidance-ownership, shape, warnings tests and shared fixtures
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / integration (push) Successful in 1m12s
CI & Build / Python tests (push) Successful in 1m56s
CI & Build / Build & push image (push) Successful in 13s

test_pattern_coverage, test_guidance_ownership, test_integration_shape_classify,
test_instruction_surfaces_agree, test_retrieval_warnings, helpers.py and
conftest.py state the property each test or fixture holds. The issue and
milestone numbers, consolidation dates and one-install measurements that
recorded how each was found are dropped; fixture dates and ids stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 21:21:52 -04:00
co-authored by Claude Opus 5.5
parent 8518afb54d
commit 91c96a8b8a
7 changed files with 199 additions and 256 deletions
+19 -20
View File
@@ -7,8 +7,8 @@ in the environment before importing the app.
For unit tests of pure functions no database is needed at all.
The fixtures below are the ONE definition of three things that used to be
copied into a dozen test modules each (#2825). They are deliberately not
The fixtures below are the ONE definition of things a dozen test modules
each need. They are deliberately not
autouse: a module opts in with
``pytestmark = pytest.mark.usefixtures("<name>")`` (or a test names the
fixture as a parameter), so a unit test that never touches the engine or the
@@ -80,7 +80,7 @@ def _no_embedding():
"""
from unittest.mock import MagicMock
# Milestones embed too since milestone 415; a plan created in a test would
# Milestones embed too; a plan created in a test would
# otherwise detach the same model-loading task.
with patch("scribe.services.notes.embed_note", MagicMock()), \
patch("scribe.services.milestones.embed_milestone", MagicMock()):
@@ -89,7 +89,7 @@ def _no_embedding():
@pytest.fixture
def _no_supersession():
"""Stub the auto-inject menu's "which lines are superseded?" lookup (#278).
"""Stub the auto-inject menu's "which lines are superseded?" lookup.
That is a real database call on a path the plugin-context tests exercise
without one. Stubbed to "nothing superseded" — the ordinary state — rather
@@ -104,7 +104,7 @@ def _no_supersession():
@pytest.fixture(autouse=True)
def _no_reply_shape_log():
"""Stub the reply-shape delivery row (milestone 500 step 3).
"""Stub the reply-shape delivery row.
Autouse for _no_system_labels' reason: every turn's retrieval, every
moment request and every Scribe tool that reaches a shaped moment writes
@@ -118,7 +118,7 @@ def _no_reply_shape_log():
@pytest.fixture(autouse=True)
def _no_system_labels():
"""Stub the menu's "which System is each line about?" lookup (#4364).
"""Stub the menu's "which System is each line about?" lookup.
Autouse because every test that renders an injected menu reaches it, and
it is a real database call on a path those tests run without one. Stubbed
@@ -132,7 +132,7 @@ def _no_system_labels():
@pytest.fixture(autouse=True)
def _no_rulings_arm():
"""Stub the rulings arm both PreToolUse builders run (milestone 444).
"""Stub the rulings arm both PreToolUse builders run.
Autouse for _no_system_labels' reason: every write-path and tool-rule
test with a project in scope reaches it, and its first act is reading the
@@ -147,8 +147,7 @@ def _no_rulings_arm():
@pytest.fixture(autouse=True)
def _no_system_usage_readout():
"""Stub the per-System usage lookup the Systems list and get_system carry
(#4769).
"""Stub the per-System usage lookup the Systems list and get_system carry.
Autouse for _no_rulings_arm's reason: every route and tool test that
reads a System now reaches a GROUP BY on system_usage_events. Stubbed to
@@ -168,7 +167,7 @@ def _no_system_usage_readout():
@pytest.fixture(autouse=True)
def _no_task_log_arm():
"""Stub the task-log read arm that get_task / list_tasks / get_milestone
grew in #4241.
carry.
Autouse for the reason _no_rule_arm is: those three tools now read work
logs, and the reads go through the access layer to Postgres. Every unit
@@ -193,7 +192,7 @@ def _no_task_log_arm():
@pytest.fixture(autouse=True)
def _no_lesson_rule_links(request):
"""Stub the lesson↔rule link decorations (milestone 440).
"""Stub the lesson↔rule link decorations.
Every door that returns a lesson or a rule now attaches its links, and the
read is a real database call — so every unit test that opens either would
@@ -201,16 +200,16 @@ def _no_lesson_rule_links(request):
Both decorations are fail-open, so the cost would be a slow failed connect
per test rather than a failure, which is worse: it would never be noticed.
The candidate search a new lesson runs (#4631) is stubbed to "nothing
The candidate search a new lesson runs is stubbed to "nothing
resembles it" for the same reason: it embeds, and the model load would
otherwise ride along with every unit test that creates a lesson. The
co-surfacing recorder (#4637) is stubbed to "no proposal": every hook
co-surfacing recorder is stubbed to "no proposal": every hook
builder test that renders a lesson beside a rule would otherwise reach
for the database to count the pair. And the via-lesson rule step (#4633)
for the database to count the pair. And the via-lesson rule step
is stubbed to "no lesson brought a rule": all three rule arms run it, and
its first act is a database read. tests/test_rule_via_lesson.py binds the
real function at import time, before this patch runs. The convergence
check a "no rule fits" answer runs (#4634) is stubbed to "no group" for
check a "no rule fits" answer runs is stubbed to "no group" for
the same reason; tests/test_lesson_convergence.py binds the real one.
Skipped for integration tests, which exercise the real links against
@@ -231,7 +230,7 @@ def _no_lesson_rule_links(request):
@pytest.fixture(autouse=True)
def _no_family_triggers(request):
"""Stub family canon's write-time triggers (milestone 463 step 3).
"""Stub family canon's write-time triggers.
create_note, create_task, create_snippet, the updates that change a body,
and update_milestone(status="done") now look for a pattern carried between
@@ -255,7 +254,7 @@ def _no_family_triggers(request):
@pytest.fixture(autouse=True)
def _no_moment_delivery(request):
"""Stub the moment lookup the mapped MCP tools attach (milestone 458).
"""Stub the moment lookup the mapped MCP tools attach.
update_task, the create_* record tools and the milestone tools now hand
back the rules mounted on the moment they mark, and finding those is two
@@ -276,7 +275,7 @@ def _no_moment_delivery(request):
@pytest.fixture(autouse=True)
def _no_rule_arm():
"""Stub the write-path hint's standing-RULES arm (milestone 307).
"""Stub the write-path hint's standing-RULES arm.
Autouse, and deliberately so. The arm calls semantic_search_rules, which
loads the embedding model — so every unrelated plugin-context test that
@@ -297,7 +296,7 @@ def _no_rule_arm():
@pytest.fixture(autouse=True)
def _no_rule_overlap():
"""Stub the rule/preference create path's overlap check (#4134).
"""Stub the rule/preference create path's overlap check.
The same reason as _no_rule_arm, one door over: every create_rule /
create_project_rule / create_preference now asks semantic_search_rules
@@ -314,7 +313,7 @@ def _no_rule_overlap():
@pytest.fixture(autouse=True)
def _default_gate_bars():
"""Read the create gate's bars as their defaults, not from settings (#4385).
"""Read the create gate's bars as their defaults, not from settings.
Every create through the note gate now asks the user's settings for its
similarity bars, which is a database read on a path the gate's unit tests