From 63e97a6f0fefaa507c1fca03406c964d995d094a Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Wed, 21 Oct 2026 21:37:15 -0400 Subject: [PATCH] =?UTF-8?q?docs(6209):=20seventeen=20more=20test=20files?= =?UTF-8?q?=20=E2=80=94=20lesson=20shape=20and=20round=20trip,=20rule=20sc?= =?UTF-8?q?ope/moments/kind/surfacing,=20drift,=20deadlock=20race,=20backu?= =?UTF-8?q?p,=20inception,=20backfill,=20claims,=20supersession,=20ledgers?= =?UTF-8?q?,=20family=20shapes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docstrings and comments state the property and its reason in the present tense. The session-context ledger test no longer describes the decision it "used to pin"; the supersession tests state demote-not-filter without the quote; one-row measurements become the general shape with their figures. Co-Authored-By: Claude Opus 5.5 --- tests/test_backfill_reads_current_text.py | 8 +++--- tests/test_family_shapes.py | 9 +++---- tests/test_inception.py | 15 +++++------ .../test_integration_backup_note_roundtrip.py | 12 ++++----- ..._integration_embedding_yields_to_delete.py | 21 +++++++-------- tests/test_integration_preference_drift.py | 12 ++++----- tests/test_integration_rule_kind.py | 11 ++++---- tests/test_integration_rule_moments.py | 8 +++--- tests/test_integration_rule_scope.py | 12 ++++----- tests/test_integration_rule_surfacing.py | 15 +++++------ tests/test_lesson_document_shape.py | 19 +++++++------- tests/test_lesson_insight_round_trip.py | 14 +++++----- tests/test_services_supersession.py | 6 ++--- tests/test_session_context_ledger.py | 26 +++++-------------- tests/test_supersession_ranking.py | 15 +++++------ tests/test_system_usage_readout.py | 7 +++-- tests/test_task_claims.py | 8 +++--- 17 files changed, 95 insertions(+), 123 deletions(-) diff --git a/tests/test_backfill_reads_current_text.py b/tests/test_backfill_reads_current_text.py index 6668a2ad..f1c4c7fb 100644 --- a/tests/test_backfill_reads_current_text.py +++ b/tests/test_backfill_reads_current_text.py @@ -1,4 +1,4 @@ -"""A backfill repairs to current truth; it does not replay a snapshot (#4262). +"""A backfill repairs to current truth; it does not replay a snapshot. The bug these pin: every backfill used to SELECT the text alongside the id and then iterate that snapshot, sleeping between records. A run over a real corpus @@ -90,8 +90,8 @@ async def test_a_record_deleted_between_the_scan_and_the_loop_is_skipped(): @pytest.mark.asyncio async def test_a_record_whose_text_outran_its_vectors_is_re_embedded(): - """The repair half (#4202 — a guard that refuses to write a bad value does - not undo the bad values already stored). Note 5 IS at the current version, + """The repair half: a guard that refuses to write a bad value does not + undo the bad values already stored. Note 5 IS at the current version, so the version comparison alone would skip it forever; its text is newer than its vectors, which is the only signal that separates "embedded from stale text" from "embedded correctly".""" @@ -131,7 +131,7 @@ async def test_a_task_logged_since_its_vectors_is_re_embedded(): @pytest.mark.asyncio async def test_a_corpus_that_is_genuinely_current_embeds_nothing(): - """The guard must be able to stay quiet, or it is not a guard (#167) — and + """The guard must be able to stay quiet, or it is not a guard — and a backfill that re-embeds everything every boot is a different bug.""" scan = _scan_session(all_ids=[1, 2, 3], current_ids=[1, 2, 3]) diff --git a/tests/test_family_shapes.py b/tests/test_family_shapes.py index baa2090b..81005286 100644 --- a/tests/test_family_shapes.py +++ b/tests/test_family_shapes.py @@ -1,10 +1,9 @@ -"""The shape ledger judging against family ideas, without a database -(milestone 463 step 5). +"""The shape ledger judging against family ideas, without a database. Pinned here: what a project's shapes say about an idea, when an answer contradicts them, which reference a shape in a given language is judged -against, and the family arm's rule — measured on 2026-10-06 (#4991), and -replayed below as the table it was chosen from. The two ledgers moving +against, and the family arm's rule — measured, and replayed below as the +table it was chosen from. The two ledgers moving together against Postgres are in tests/test_integration_family_adoption.py. """ from __future__ import annotations @@ -95,7 +94,7 @@ OWN, REF, OTHER = 1, 2, 3 @pytest.mark.parametrize("name,hits,expected", [ - # #4991's pairs, the reference as REF and the best other hit as OTHER. + # The measured pairs, the reference as REF and the best other hit as OTHER. ("A py->go", [(0.728, REF), (0.703, OTHER)], "family"), ("B py->go", [(0.715, REF), (0.675, OTHER)], "family"), ("D kt->kt", [(0.816, REF), (0.734, OTHER)], "family"), diff --git a/tests/test_inception.py b/tests/test_inception.py index c85dc43a..698d0dbc 100644 --- a/tests/test_inception.py +++ b/tests/test_inception.py @@ -1,11 +1,10 @@ -"""Project inception (milestone 297) — step 1: the record's shape. +"""Project inception — the record's shape. The WHY a project inherits what it does lives on projects.inception. Pure -validation is pinned here; the effects are step 3's integration tests. +validation is pinned here; the effects are the integration tests. -Rules left inception in two steps: the always-on opt-out with the tier -(milestone 394), and the rulebook subscription with subscriptions (milestone -414). A rule in a rulebook is global, so there is nothing to choose. +Rules are not an inception choice: a rule in a rulebook is global, so there is +nothing to choose. """ from scribe.models.project import Project from scribe.services.inception import ( @@ -39,7 +38,7 @@ def test_validate_inception_pins_the_choice_vocabulary(): # believe a rulebook had been declined. assert "unknown inception choice" in validate_inception( {"exclude_always_on_rulebooks": [1]}) - # Same for the subscription choice since milestone 414. + # Same for a rulebook subscription choice. assert "unknown inception choice" in validate_inception({"subscribe_rulebooks": [2]}) assert "positive id or null" in validate_inception({"design_system_id": 0}) assert "positive id or null" in validate_inception({"design_system_id": True}) @@ -71,8 +70,8 @@ def test_normalize_choices_is_canonical_and_complete(): def test_standard_systems_vocabulary_reads_the_catalog_not_a_constant(): - """The vocabulary moved from a module constant to the global catalog table - (milestone 307): a constant cannot be a foreign key, so nothing outside a + """The vocabulary is the global catalog table, not a module constant: a + constant cannot be a foreign key, so nothing outside a project could reference an area. The seed and the bootstrap ask must both read the table, or the list they show and the list they mint diverge.""" import inspect diff --git a/tests/test_integration_backup_note_roundtrip.py b/tests/test_integration_backup_note_roundtrip.py index f6210fc4..7af665f7 100644 --- a/tests/test_integration_backup_note_roundtrip.py +++ b/tests/test_integration_backup_note_roundtrip.py @@ -1,4 +1,4 @@ -"""Real-Postgres round trip for the note fields #3182 restored. +"""Real-Postgres round trip for the note fields a restore carries. The unit lane can prove a serialiser EMITS a key. It cannot prove a restore puts the value back on the right row, and the note->note edges are exactly @@ -7,8 +7,6 @@ the SOURCE database, so a restore that writes them straight through succeeds, reports success, and silently points every edge at whatever record happens to hold that number here. -That is why #3182 was not fixed in passing. - These drive the REAL `restore_full_backup`, not a reimplementation of its loop. A test that re-derives the remap it is checking would agree with whatever the product does, including nothing. @@ -162,10 +160,10 @@ async def _no_leftover_restored_user(): async def test_a_restored_record_keeps_what_it_IS(restored): - """#3182's headline. Without note_type and task_kind a restore reported - success and handed back a corpus where every snippet and process was a - plain note and every issue and spike was `work` — the whole vocabulary - milestone 312 and #3128 were about, gone, with nothing to notice it by.""" + """Without note_type and task_kind a restore reports success and hands + back a corpus where every snippet and process is a plain note and every + issue and spike is `work` — the record vocabulary gone, with nothing to + notice it by.""" by_title, _ = restored assert by_title["debounce — rate-limit"].note_type == "snippet" diff --git a/tests/test_integration_embedding_yields_to_delete.py b/tests/test_integration_embedding_yields_to_delete.py index 265b44e8..91b3753a 100644 --- a/tests/test_integration_embedding_yields_to_delete.py +++ b/tests/test_integration_embedding_yields_to_delete.py @@ -1,17 +1,17 @@ -"""#3262 against a real Postgres: the embedder loses the race, it doesn't run it. +"""Against a real Postgres: the embedder loses the race, it doesn't run it. -The reported failure was a deadlock — `DELETE FROM rulebooks` killed by the -server while a detached `upsert_rule_embedding` held the other half of the -cycle. It cannot be reproduced with mocks, because there is nothing to +The failure is a deadlock — `DELETE FROM rulebooks` killed by the server +while a detached `upsert_rule_embedding` holds the other half of the cycle. +It cannot be reproduced with mocks, because there is nothing to deadlock: the whole bug lives in the ORDER two transactions take two row locks, which only a lock manager can adjudicate. So each test here holds a real delete open in one transaction and calls the embedder in another. What is being pinned is that the embedder RETURNS — -promptly, having written nothing. Before the fix it would sit on the chunk -rows waiting for a delete that is itself waiting on the insert's foreign key, -and the test would hang rather than fail, which is why every call carries a -deadline (rule 156). +promptly, having written nothing. An embedder that sits on the chunk rows +waiting for a delete that is itself waiting on the insert's foreign key would +hang the test rather than fail it, which is why every call carries a +deadline. """ import asyncio from unittest.mock import AsyncMock, patch @@ -53,8 +53,7 @@ SETTLE_DEADLINE_SECONDS = 30 async def seeded(): """A rule and a note to race against. - CLEANED AT SETUP, NOT TEARDOWN — the same constraint #3241 hit and the - reason this file exists. `create_rule` fires its own detached embedding + CLEANED AT SETUP, NOT TEARDOWN. `create_rule` fires its own detached embedding task; a teardown that deleted the rulebook would be racing exactly the thing under test, on a loop that is closing. """ @@ -141,7 +140,7 @@ async def test_a_rule_refresh_yields_to_a_delete_cascading_from_its_rulebook(see async def test_a_note_refresh_yields_to_a_delete_of_the_note(seeded): - """The note twin, which #3262 recorded as unverified. Notes are soft-deleted + """The note twin. Notes are soft-deleted day to day, so the hard delete a trash purge issues is the one that can put a lock on the row while a refresh is in flight.""" async with async_session() as blocker: diff --git a/tests/test_integration_preference_drift.py b/tests/test_integration_preference_drift.py index cdeb8e0e..9408e8c7 100644 --- a/tests/test_integration_preference_drift.py +++ b/tests/test_integration_preference_drift.py @@ -1,4 +1,4 @@ -"""Real-Postgres tests for the drift surface (milestone 399 step 5, #3895). +"""Real-Postgres tests for the drift surface. WHY THIS EXISTS @@ -20,8 +20,8 @@ subquery picking the newest version per rule, an ownership clause spanning two paths, and a write that has to leave the history longer than it found it. A stand-in session returns whatever the test handed it, so it could confirm none of those. `test_the_restore_is_recorded_as_an_edit` is the one that matters -most: it is the whole basis for allowing a one-click revert here when -milestone 323 refused one for rules, and if it were ever to pass while the +most: it is the whole basis for allowing a one-click revert here when rules +have none, and if it were ever to pass while the restore silently overwrote history, the carve-out would be indefensible. """ import pytest @@ -228,8 +228,8 @@ async def test_restoring_puts_the_old_wording_back(world): async def test_the_restore_is_recorded_as_an_edit(world): """THE ONE THAT MATTERS MOST — it is why this carve-out is defensible. - Milestone 323 refused a one-click restore for rules because "a silent - revert would erase the only record of why the rewrite happened". The + Rules have no one-click restore because a silent revert would erase the + only record of why the rewrite happened. The preference carve-out survives that objection only while nothing is erased: the restore goes through `update_rule`, so it takes its own snapshot and the history GAINS an entry. @@ -262,7 +262,7 @@ async def test_the_restore_is_recorded_as_an_edit(world): async def test_a_rule_refuses_the_one_click_restore(world): - """Milestone 323 stands for rules, and the kind check is in the service + """Rules still have no restore, and the kind check is in the service rather than only in the route — so a caller reaching this directly cannot forget it.""" await rulebooks_svc.update_rule( diff --git a/tests/test_integration_rule_kind.py b/tests/test_integration_rule_kind.py index 613df6f8..d975fd4d 100644 --- a/tests/test_integration_rule_kind.py +++ b/tests/test_integration_rule_kind.py @@ -1,6 +1,6 @@ -"""Real-Postgres tests for `rules.kind` and its CHECK (0098, #3849 step 1). +"""Real-Postgres tests for `rules.kind` and its CHECK (migration 0098). -Rule 36 exists because a value and its constraint drift apart: the code +A value and its constraint drift apart: the code starts writing a new kind while the database still refuses it, and nothing catches it until a write fails in front of someone. A mock cannot show that — it has no CHECK — so the constraint gets a real-DB test, exactly as 0091's @@ -94,8 +94,7 @@ async def test_an_unknown_kind_is_refused(topic_id): """The half that proves the constraint is there at all. Without this, every other assertion in this file would pass against a - table whose CHECK had been dropped — the exact failure rule 36 is written - against. + table whose CHECK had been dropped — the exact drift this guards. """ _uid, topic = topic_id with pytest.raises(IntegrityError): @@ -119,8 +118,8 @@ async def test_a_rule_can_become_a_preference_after_the_fact(topic_id): """The read-back is the whole test. A version asserting only that the update call succeeded would pass against - code that accepted `kind` and dropped it — which is how the same bug - survived on `task_kind` long enough to be found by hand (#3129). + code that accepted `kind` and dropped it — a bug that otherwise surfaces + only when someone finds it by hand. This is also the migration path the always-on triage needs: the rules that turn out to be preferences change one column and keep their id, history diff --git a/tests/test_integration_rule_moments.py b/tests/test_integration_rule_moments.py index 8b883453..686da178 100644 --- a/tests/test_integration_rule_moments.py +++ b/tests/test_integration_rule_moments.py @@ -1,4 +1,4 @@ -"""Real-Postgres tests for rule mounts (milestone 458 step 3). +"""Real-Postgres tests for rule mounts. A mount is the claim "this rule arrives at this moment". These pin what that claim depends on: @@ -7,7 +7,7 @@ claim depends on: - the rule's detail reads its mounts back; - a backup carries them, attached to the RESTORED rule's new id rather than the old number; -- the delivery lookup (step 4) answers by home: a project's mounted rule +- the delivery lookup answers by home: a project's mounted rule reaches only work bound to that project, and nobody else's mount arrives. """ import pytest @@ -150,7 +150,7 @@ async def test_a_backup_carries_the_mounts_to_the_restored_rule(world): assert sorted(r["moment"] for r in payload["rule_moments"]) == [ "reply.report", "work.finish", ] - # The mount was an edit, so it was also recorded as two judgments (step 7) + # The mount was an edit, so it was also recorded as two judgments # — and those travel too, onto the restored rule. payload["rule_moment_judgments"] = [ row for row in exported["rule_moment_judgments"] if row["rule_id"] == rule.id @@ -238,7 +238,7 @@ async def test_the_delivery_lookup_answers_by_home(world): async def test_moment_usage_counts_deliveries_and_the_agent_opens_that_followed(world): - """The per-moment readout (step 6), on real SQL: an EXISTS inside a + """The per-moment readout, on real SQL: an EXISTS inside a COUNT(CASE …) is a shape no mock can vouch for, and the block's own guard would turn a database refusal into a quiet `moment_usage_failed`.""" from datetime import datetime, timedelta, timezone diff --git a/tests/test_integration_rule_scope.py b/tests/test_integration_rule_scope.py index 8c551d3c..68e8571e 100644 --- a/tests/test_integration_rule_scope.py +++ b/tests/test_integration_rule_scope.py @@ -1,4 +1,4 @@ -"""Real-Postgres tests for WHERE a rule reaches (milestone 414, step 1). +"""Real-Postgres tests for WHERE a rule reaches. A rule lives in a rulebook topic (global) or on one project. Retrieval used to ignore that and search every rule the user owned, so each project's rules were @@ -78,7 +78,7 @@ async def _found(user_id: int, **scope) -> set[int]: """The rule ids a search finds — and a failure, not an empty set, when the search never ran. `semantic_search_rules` fails open (an exception becomes []), so without `report["searched"]` an error and a scoping miss read the - same (#4958).""" + same.""" report: dict = {} raised: list[str] = [] with patch("scribe.services.embeddings.get_embedding", @@ -109,7 +109,7 @@ async def test_retrieval_reaches_a_rule_only_from_its_home(homes): async def test_a_shared_project_brings_its_rules_to_a_collaborator(homes): - """Readability goes through access.can_read_project (rule 78): a viewer on + """Readability goes through access.can_read_project: a viewer on A gets A's rules. Not the owner's global rules — rulebooks are the owner's — and not B's, which is not shared.""" collaborator = homes["collaborator"] @@ -118,9 +118,9 @@ async def test_a_shared_project_brings_its_rules_to_a_collaborator(homes): async def test_an_in_scope_rule_is_found_however_many_closer_rules_are_out_of_scope(): - """#4958. Ordered through the HNSW index, the search took the ~40 nearest - chunks from every owner and filtered them AFTERWARDS — so a reader's own - rule ranked past the 40th chunk overall was never returned. Here another + """A search ordered through the HNSW index takes the ~40 nearest chunks + from every owner, and filtering them AFTERWARDS loses a reader's own rule + ranked past the 40th chunk overall. Here another user's 80 rules all sit nearer the query than the reader's one rule; the reader's search must still find it.""" tag = uuid.uuid4().hex[:8] diff --git a/tests/test_integration_rule_surfacing.py b/tests/test_integration_rule_surfacing.py index f85fd749..ea85c290 100644 --- a/tests/test_integration_rule_surfacing.py +++ b/tests/test_integration_rule_surfacing.py @@ -10,12 +10,9 @@ planning read carries — and what mocks can't prove about it: comparison, never a similarity score. 2. An UNTAGGED global rule is not listed: it applies everywhere and arrives by retrieval, and listing every one under every project would say nothing. -3. A `co_surfaces` partner arrives with its other half — the failure that made - merging rule 144 into rule 46 look like the only fix — unless the partner - lives on a different project, because an edge is not a way in. - -Milestone 414 dropped the suppression claim ("an explicit suppression outranks -an edge") with suppressions themselves. +3. A `co_surfaces` partner arrives with its other half — without it, merging + two rules that must arrive together looks like the only fix — unless the + partner lives on a different project, because an edge is not a way in. """ import pytest import pytest_asyncio @@ -102,9 +99,9 @@ async def test_a_tagged_global_rule_is_listed_for_a_project_that_works_in_its_ar @pytest.mark.integration async def test_co_surfaces_drags_in_the_half_that_would_have_been_missed(world): - """Rule 144 was split off rule 46 and folded back the same day because - "either rule could surface without the other". This is the edge that makes - that unnecessary: the partner arrives even though nothing else selected + """Two rules that must arrive together get folded into one because either + could surface without the other. This is the edge that makes that + unnecessary: the partner arrives even though nothing else selected it, and says why it is here.""" partner = await rulebooks_svc.create_rule( world["topic"], world["owner"], "Version names are labels", diff --git a/tests/test_lesson_document_shape.py b/tests/test_lesson_document_shape.py index 21af5def..360fb6b4 100644 --- a/tests/test_lesson_document_shape.py +++ b/tests/test_lesson_document_shape.py @@ -1,4 +1,4 @@ -"""The document a lesson is embedded as (milestone 385 step 3; milestone 427). +"""The document a lesson is embedded as. WHY THIS IS THE STEP THAT DECIDES THE MILESTONE @@ -9,17 +9,16 @@ anywhere would report that. WHERE THE SHARP SHAPE LIVES -A snippet, which note #2485 measured as the only sharp record in the corpus (a -0.153 top-to-second gap against 0.010–0.023 for everything else), is sharp +A snippet, measured as the sharpest record kind in a corpus (a 0.153 +top-to-second gap against 0.010–0.023 for everything else), is sharp because its document states its purpose twice: `name — when to use` as the title, and again as the body's first line. A lesson follows the snippet. -Until milestone 427 that `subject — trigger` title was also the STORED title, -so every listing, menu and search row showed the trigger too — kilobytes of it. -Now the stored title is the subject, and `embeddings.document_title` joins the -trigger back from `data` at embed time. The embedded TEXT is what it always -was, which is the property these guards pin: nothing re-embeds, and the floors -tuned against these vectors stay calibrated. +The STORED title is the subject alone, so listings, menus and search rows do +not carry kilobytes of trigger; `embeddings.document_title` joins the trigger +back from `data` at embed time. The embedded TEXT keeps the `subject — +trigger` shape, which is the property these guards pin: the floors tuned +against these vectors stay calibrated. No similarity number is asserted anywhere: a threshold pins the embedder's behaviour rather than this code's, and breaks on a model change that is not a @@ -44,7 +43,7 @@ def _embedded(what: str, trigger: str, insight: str) -> tuple[str, str]: def test_the_stored_title_is_the_subject_alone(): - """Milestone 427. The trigger lives in `data` and the body's first line; the + """The trigger lives in `data` and the body's first line; the title a listing shows is what the lesson is ABOUT.""" title, _ = lessons_svc.lesson_document(SUBJECT, TRIGGER, INSIGHT) assert title == SUBJECT diff --git a/tests/test_lesson_insight_round_trip.py b/tests/test_lesson_insight_round_trip.py index dd6bde43..3487d504 100644 --- a/tests/test_lesson_insight_round_trip.py +++ b/tests/test_lesson_insight_round_trip.py @@ -1,4 +1,4 @@ -"""Reading a lesson's insight back and re-composing it returns the same body (#4272). +"""Reading a lesson's insight back and re-composing it returns the same body. THE PROPERTY. `update_lesson` is field-wise: an edit that touches only `system_ids`, or only `what`, passes `insight=None`, and the service then @@ -24,11 +24,9 @@ insight", the full trigger was prepended again, and the stored lesson gained (n-1) paragraphs per update — silently, compounding, and in the half of the document that does the retrieving. -Measured on the one real row this damaged (lesson #4207, a three-paragraph -trigger): the body grew by exactly 607 characters per edit — the length of -paragraphs 2 and 3 with their separators — taking it from 1291 characters to -7361 over ten edits, at which point the trigger appears eleven times and the -insight is 17% of the record. +On a three-paragraph trigger the body grows by the length of paragraphs 2 and +3 with their separators on every edit — after ten edits the trigger appears +eleven times and the insight is a sixth of the record. WHY A MARKER COULD NOT HAVE FIXED IT. There is no end-of-trigger marker in the body and adding one would not repair a row already written without it. @@ -99,7 +97,7 @@ def _stored(trigger: str, insight: str, sources: list[int]): MagicMock auto-creates truthy and coerces to `1`. A no-sources shape then recomposes with `**Learned from:** #1` and the round trip fails for a reason that has nothing to do with the trigger. `fake_lesson` pins that - field to None — note #2109's point, which is why the fixture exists. + field to None, which is why the fixture exists. """ title, body = lessons_svc.lesson_document(WHAT, trigger, insight, sources) data = lessons_svc.compose_data(WHAT, trigger, sources) @@ -137,7 +135,7 @@ def test_an_edit_that_changes_nothing_changes_nothing(_name, trigger, insight, s # Reported as a size delta rather than left to a diff of two multi-kilobyte # strings: the failure this catches is duplication, and the number of # characters gained says which paragraph came back far faster than an - # equality dump does (rule 167 — a guard has to name what broke). + # equality dump does (a guard has to name what broke). assert (title, body) == (note.title, note.body), ( f"a no-op edit rewrote the lesson: title {len(title) - len(note.title):+d} " f"chars, body {len(body) - len(note.body):+d} chars" diff --git a/tests/test_services_supersession.py b/tests/test_services_supersession.py index 11aca143..551057d3 100644 --- a/tests/test_services_supersession.py +++ b/tests/test_services_supersession.py @@ -1,7 +1,7 @@ """The supersession claim — who may make it, and what it refuses. -Step 2 of #278. Ranking behaviour is step 3; this covers only recording and -reading the relation. +Ranking behaviour is in test_supersession_ranking.py; this covers only +recording and reading the relation. The cycle tests are the ones worth reading. Under FLAT demotion a ring of records that supersede each other claims every member is obsolete, so all of @@ -53,7 +53,7 @@ async def test_superseding_a_note_you_can_only_READ_is_refused_not_dropped(): Demoting someone else's record out of their retrieval is damage that is invisible from the outside — the caller would believe it worked, and the - owner would have no symptom to trace. Rule #47. + owner would have no symptom to trace. """ # writable for the superseder (id 1), not for the target (id 2) writable = AsyncMock(side_effect=lambda uid, nid: nid == 1) diff --git a/tests/test_session_context_ledger.py b/tests/test_session_context_ledger.py index 61332285..8a5ebfd4 100644 --- a/tests/test_session_context_ledger.py +++ b/tests/test_session_context_ledger.py @@ -1,4 +1,4 @@ -"""The SessionStart hook clears the rule ledger exactly when context dies (#3749). +"""The SessionStart hook clears the rule ledger exactly when context dies. WHY THIS EXISTS @@ -109,28 +109,16 @@ def test_the_rules_ledger_survives_exactly_when_the_context_does(tmp_path): def test_the_note_ledgers_are_cleared_too_now_that_a_repeat_is_shown(tmp_path): - """The decision this test used to pin, reversed — and why it could be. + """The note ledgers are cleared on a compaction too. - It read: the note arms were deliberately left out of #3749, whether a - surfaced NOTE should come back after a compaction is a different question, - and a glob over `.*` would decide it by accident. That was right when - it was written, and the reason was the note arms' behaviour rather than the - note arms' nature: a note repeat was WITHHELD, so clearing their ledger - meant re-injecting whole menu lines the session had already been given. - Against that, leaving them was the cheaper mistake. - - #4101 removed the premise. A note repeat is now rendered again with a - `seen` marker instead of dropped from the search, so the ledger no longer - decides whether a record is reachable — only whether its line says the + A note repeat is rendered again with a `seen` marker rather than dropped + from the search, so the ledger does not decide whether a record is + reachable — only whether its line says the session has met it before. Across a compaction that marker becomes a false statement: it tells a freshly-summarised session it has already seen a record that is nowhere in its context. Keeping the ledger buys nothing and - asserts something untrue. - - Kept as a named test rather than deleted, because the roster it guards - moved to tests/test_session_ledger_clear.py and what is worth keeping HERE - is the record that the answer changed, with the reason attached — a - deleted test takes the old decision's reasoning with it. + asserts something untrue. The full roster is guarded in + tests/test_session_ledger_clear.py. """ env = _env(tmp_path) sid = "sess-scope" diff --git a/tests/test_supersession_ranking.py b/tests/test_supersession_ranking.py index 307b6357..9e79e285 100644 --- a/tests/test_supersession_ranking.py +++ b/tests/test_supersession_ranking.py @@ -1,9 +1,7 @@ """Demotion: superseded records rank behind their equals, and are never hidden. -Step 3 of #278. The distinction these tests exist to protect is DEMOTE vs -FILTER. The operator was explicit: - - "the failure is pollution, not existence" +The distinction these tests exist to protect is DEMOTE vs FILTER: the failure +is pollution, not existence. Hiding a superseded record would turn every one of them into something you must already know exists in order to find, and would destroy "what did we think @@ -131,11 +129,10 @@ async def test_an_empty_candidate_set_short_circuits(): def test_the_penalty_is_sized_to_reorder_a_cluster_not_shuffle_within_it(): """Sized against a measurement, not by feel. - Measured 2026-08-07 (#2486): the notes competing on a dev-log's own title - phrase sat within ~0.014 of each other, spanning 0.6506 down to 0.6120. A - penalty smaller than that spread would move a record within a tie without - changing which one wins — the failure #2486 already proved cannot be tuned - away, because the neighbours are not barely passing, they are tied. + Notes competing on a dev-log's own title phrase sit within ~0.014 of each + other (0.6506 down to 0.6120 on one measured cluster). A penalty smaller + than that spread moves a record within a tie without changing which one + wins — a failure that cannot be tuned away, because the neighbours are not barely passing, they are tied. The upper bound is the operator's constraint, not an optimisation: a penalty large enough to bury a superseded record outright is hiding by another name. diff --git a/tests/test_system_usage_readout.py b/tests/test_system_usage_readout.py index c1560630..c4ad4180 100644 --- a/tests/test_system_usage_readout.py +++ b/tests/test_system_usage_readout.py @@ -1,7 +1,6 @@ -"""Rulings are counted where someone will read them (#4769). +"""Rulings are counted where someone will read them. -`system_usage_events` was written from milestone 444 step 4 and read by -nothing. These pin the two readouts: +`system_usage_events` is read in two places, and these pin both readouts: - PER SYSTEM: `usage_for_systems` — one GROUP BY, a zero shape for a System nothing touched — carried by the Systems list, the REST detail and MCP @@ -10,7 +9,7 @@ nothing. These pin the two readouts: the areas named, and deliberately NO pull-through ratio. Integration for both aggregates, not mocked: a GROUP BY the database rejects -is swallowed by the fail-open guard and reads as zero, which is #2663 exactly. +is swallowed by the fail-open guard and reads as zero. """ from unittest.mock import AsyncMock, patch diff --git a/tests/test_task_claims.py b/tests/test_task_claims.py index ffe05807..b3f69b73 100644 --- a/tests/test_task_claims.py +++ b/tests/test_task_claims.py @@ -1,9 +1,9 @@ -"""A task's claim — which session is working it, and how it dies (milestone 381 step 2). +"""A task's claim — which session is working it, and how it dies. WHAT THIS PINS 1. **The write that is the work stamps it.** Reaching `in_progress` — by - update OR by a create that names it (#3683) — claims the task for whoever + update OR by a create that names it — claims the task for whoever made the change. Nothing asks the model to claim anything. 2. **Ending or un-starting the work releases it**, and releasing is idempotent. @@ -287,8 +287,8 @@ async def test_ending_a_session_releases_only_that_sessions_claims(users): @pytest.mark.integration async def test_a_collaborator_with_write_access_can_log_and_so_claims(users): - """create_log used to filter on the task's OWNER (a rule #78 violation), so - a collaborator on a shared task could not log on it — nor, since logging + """create_log filters on who may write the TASK, not on its owner, so a + collaborator on a shared task can log on it — nor, since logging stamps the claim, ever be seen working it.""" from scribe.services import sharing, task_logs