diff --git a/tests/test_lesson_rest_door.py b/tests/test_lesson_rest_door.py index f2f83013..45336bb1 100644 --- a/tests/test_lesson_rest_door.py +++ b/tests/test_lesson_rest_door.py @@ -1,11 +1,11 @@ -"""The REST door for lessons — the half the web UI can actually reach (#3734). +"""The REST door for lessons — the half the web UI can actually reach. WHY THIS EXISTS AT ALL -Milestone 385 built the lesson kind through the MCP tools, which is the surface -an agent uses. The Vue app speaks REST, so until this blueprint existed a lesson -was a record a person could not create, read, edit or retire from the UI — rule -27's "no UI, no ship" failing at the door rather than in the view. +The MCP tools are the surface an agent uses; the Vue app speaks REST. Without +this blueprint a lesson is a record a person cannot create, read, edit or +retire from the UI — a feature with no UI, failing at the door rather than in +the view. WHAT THESE PIN @@ -17,7 +17,7 @@ kind: own title would produce lessons that rank differently from the agent's, and the document IS what ranks. - - ACL (rule 78). Share-aware resolve, write as the owner — the pattern + - ACL. Share-aware resolve, write as the owner — the pattern routes/snippets.py sets — so a shared editor isn't rejected by the owner-scoped service. @@ -50,7 +50,7 @@ def test_both_doors_share_one_serializer(): def test_the_rest_door_composes_nothing_itself(): - """Asserted on structure (rule 167). The document is what ranks, so a door + """Asserted on structure. The document is what ranks, so a door that built its own title would produce lessons that rank differently from the ones the agent writes.""" from scribe.routes import lessons as routes @@ -124,7 +124,7 @@ def test_the_subject_is_required_too(): assert "what is required" in src -# ── ACL: rule 78's pattern, not a bare owner filter ────────────────────────── +# ── ACL: the shared-access pattern, not a bare owner filter ────────────────── @pytest.mark.parametrize( @@ -139,12 +139,12 @@ def test_writes_check_permission_and_act_as_the_owner(handler): assert "can_write_note" in src, f"{handler} does not check write permission" assert "note.user_id" in src, ( f"{handler} writes as the caller rather than as the owner, which " - f"rejects a legitimately shared editor (rule 78)" + f"rejects a legitimately shared editor" ) def test_no_handler_builds_its_own_owner_filter(): - """Rule 78's actual failure mode: a route assembling its own + """The access layer's actual failure mode: a route assembling its own `Note.user_id == uid` clause instead of going through the service and the access helpers. Passing `user_id=uid` INTO a service is the correct call and is not what this looks for.""" @@ -238,7 +238,7 @@ def test_the_payload_reads_back_the_composed_fields(): def test_the_rest_guards_can_fail(): - """Rule 167: shown turning red once.""" + """Shown turning red once.""" from scribe.routes import lessons as routes src = inspect.getsource(routes) diff --git a/tests/test_note_pipeline.py b/tests/test_note_pipeline.py index 3b826cb2..dc6d0749 100644 --- a/tests/test_note_pipeline.py +++ b/tests/test_note_pipeline.py @@ -1,9 +1,9 @@ -"""The notes corpus on the one retrieval pipeline (milestone 456 step 4). +"""The notes corpus on the one retrieval pipeline. `run_note_arm` is driven directly here, with the search and both recorders stubbed through `NoteIO`: the stage order, the invariants the rule arms -already pin (#3497's call row before any return, #3752's fresh-only cut, -#4101's ledger-renders-not-removes), the write path's withheld menu (#3739), +already pin (the call row before any return, the fresh-only cut, the ledger +renders rather than removes), the write path's withheld menu, and the two reserved slots in their load-bearing order. The builders that compose these arms keep their own tests; these pin the stages they share. """ @@ -53,7 +53,7 @@ async def _run(arm, route, *, budget=3, **moment): return result, io, calls -# ── the call row (#3497, #3752) ─────────────────────────────────────────── +# ── the call row ────────────────────────────────────────────────────────── @pytest.mark.asyncio @@ -75,7 +75,7 @@ async def test_repeats_and_named_records_are_counted_not_reported(): (row,) = _rows(io.record_retrieval, "auto_inject") assert [int(n.id) for _s, n in row["results"]] == [22] assert row["suppressed"] == 2 - # The repeat stays on the menu (#4101); the named record does not — it is + # The repeat stays on the menu; the named record does not — it is # shown by its own block. assert [int(n.id) for _s, n in result.menu] == [11, 22] (surfaced,) = _rows(io.record_surfaced, "auto_inject") @@ -105,7 +105,7 @@ def test_every_notes_stage_logs_before_it_can_return(): @pytest.mark.asyncio async def test_the_band_narrows_the_menu_after_the_row_is_written(): - """Notes log BEFORE the band (#2085) — the row is the candidate set a + """Notes log BEFORE the band — the row is the candidate set a floor is tuned against, the surfacing rows are what the reader saw.""" hits = [_note(1, 0.90), _note(2, 0.70)] result, io, _ = await _run(rp.WRITE_PATH, lambda kw: hits) @@ -141,7 +141,7 @@ async def test_a_recorder_that_raises_costs_only_its_row(): assert [int(n.id) for _s, n in result.menu] == [1] -# ── the write path's withheld menu (#3739) ──────────────────────────────── +# ── the write path's withheld menu ──────────────────────────────────────── @pytest.mark.asyncio @@ -223,7 +223,7 @@ async def test_a_slot_stands_down_when_its_kind_won_on_score(): @pytest.mark.asyncio async def test_a_slot_spends_itself_on_a_repeat_without_booking_it_again(): """A record shown in an EARLIER call is exactly what a slot may spend - itself on (#4101) — it is rendered, but it is not a new surfacing.""" + itself on — it is rendered, but it is not a new surfacing.""" main = [_note(1, 0.70)] lesson = [_note(42, 0.58, note_type=LESSON_NOTE_TYPE)] result, io, _ = await _run( diff --git a/tests/test_retrieval_query_scrubbing.py b/tests/test_retrieval_query_scrubbing.py index d1aa18d5..395b3b4e 100644 --- a/tests/test_retrieval_query_scrubbing.py +++ b/tests/test_retrieval_query_scrubbing.py @@ -1,4 +1,4 @@ -"""A logged query never carries a credential (#3925). +"""A logged query never carries a credential. WHY THIS EXISTS @@ -9,8 +9,7 @@ that exported a token therefore stored the token. And storing it was not the worst of it. `near_miss_samples` is the readout the threshold documentation tells you to open before moving a bar, so the value -came back OUT into an agent's context on the next tuning pass — which is -exactly how this was found, during #3853's threshold spike. +would come back OUT into an agent's context on the next tuning pass. WHAT THIS PINS, IN BOTH DIRECTIONS, AND WHY THE SECOND HALF IS THE HARD ONE @@ -21,12 +20,11 @@ A scrubber has two ways to fail and only one of them is obvious. because it is silent: the whole worth of a near-miss sample is reading the query that was actually refused, and a scrubber that chewed up ordinary commands would turn the one instrument for tuning a bar into unreadable - stubs while still looking like it worked. That is the #2663 shape — a - surface that reads fine and has quietly stopped saying anything. + stubs while still looking like it worked — a surface that reads fine and + has quietly stopped saying anything. -So the second block is not padding. Its cases are REAL queries taken from this -install's `near_miss_samples` during #3853, and they must survive byte for -byte. If a future pattern is added and one of them changes, the pattern is too +So the second block is not padding. Its cases are REAL near-miss queries, and +they must survive byte for byte. If a future pattern is added and one of them changes, the pattern is too greedy — tighten it rather than editing the expectation. The secret cases use FABRICATED values in the real formats. Nothing here is or @@ -59,7 +57,7 @@ _SECRETS = [ "MIIEowIBAAKC"), ] -# Real queries, from this install's near-miss samples during #3853. +# Real queries, from near-miss samples. _EVIDENCE = [ "git push origin dev", 'git pull --rebase origin dev 2>&1 | tail -3; echo "=== HEAD ==="; git log --oneline -2', @@ -114,7 +112,7 @@ def test_empty_and_missing_queries_pass_through(): def test_the_write_path_scrubs_rather_than_the_read_path(): - """The payload built for storage carries the redacted text (#3925). + """The payload built for storage carries the redacted text. Pinned on `_build_payload` because that is the single seam every source reaches the column through. A per-caller scrub would be three places for @@ -135,21 +133,20 @@ def test_the_write_path_scrubs_rather_than_the_read_path(): assert "git push" in payload["query"] -# ── the SQL twin has its own word-boundary spelling (#3925) ───────────── +# ── the SQL twin has its own word-boundary spelling ───────────────────── # # Migration 0099 carries an inlined copy of these patterns, deliberately: a # migration is a frozen record of what already ran, and importing the live # ones would mean it quietly did something different next year. # -# Frozen is not the same as correct, and the first cut was neither. The -# boundary was dropped in the port, so `sk-` matched inside any word -# containing it — `` became `` across -# thousands of rows on the one install that ran it. And writing `\b` would not -# have saved it: in Postgres ARE `\b` is a BACKSPACE, not a word boundary. +# Frozen is not the same as correct. Without the boundary, `sk-` matches +# inside any word containing it — `` becomes +# ``. And writing `\b` does not help: in Postgres ARE `\b` +# is a BACKSPACE, not a word boundary. # `\m` (start of word) is the spelling that means what Python's `\b` means. # # So this pins the property no reader can eyeball, and it is a PRESENCE check -# on a token that must appear rather than an absence check on prose (#3352). +# on a token that must appear rather than an absence check on prose. def test_the_migrations_patterns_anchor_to_a_word_start_the_postgres_way(): """`\\m`, never `\\b` — the two are unrelated in Postgres.""" diff --git a/tests/test_services_rule_usage.py b/tests/test_services_rule_usage.py index 0142c7a2..57661fb3 100644 --- a/tests/test_services_rule_usage.py +++ b/tests/test_services_rule_usage.py @@ -1,4 +1,4 @@ -"""Rule usage telemetry — the parts that need no database (milestone 333 step 1). +"""Rule usage telemetry — the parts that need no database. The round trip lives in `test_integration_backup_rule_usage_roundtrip.py`. What is here is the payload building and the zero shape: cheap, and the half @@ -143,10 +143,10 @@ def test_the_model_serialises_the_fields_the_ratio_needs(): assert row["created_at"] is None -# ─── the readout (milestone 333 step 5) ────────────────────────────────────── -# Integration: a real GROUP BY over a real table. Step 1 unit-tested the WRITE -# path and the zero shape and left the aggregate uncovered, which only became -# load-bearing when the rule list started rendering it. +# ─── the readout ───────────────────────────────────────────────────────────── +# Integration: a real GROUP BY over a real table. The unit tests above cover +# the WRITE path and the zero shape; the aggregate the rule list renders needs +# a real database. @pytest.mark.integration @@ -212,7 +212,7 @@ async def test_usage_for_rules_on_an_empty_id_list_asks_the_database_nothing( @pytest.mark.integration @pytest.mark.asyncio async def test_a_preloaded_rule_does_not_read_as_a_ranked_surfacing(_dispose_engine): - """The split that makes the always-on set judgeable (#3473). + """The split that makes the always-on set judgeable. A resident rule is delivered every session by a surface that chose nothing. Counting those as `surfaced_count` would rank the always-on set @@ -262,12 +262,11 @@ async def test_a_preloaded_rule_does_not_read_as_a_ranked_surfacing(_dispose_eng await s.commit() -# ── the outcome stream (#4212, milestone 419) ───────────────────────────── +# ── the outcome stream ──────────────────────────────────────────────────── # -# What these guard is a distinction, not a payload. Before this existed, a -# rule read and obeyed and a rule read and ignored left byte-identical -# telemetry, so the readout could not name the failure the whole milestone -# was opened on. The tests that matter most below are the ones asserting +# What these guard is a distinction, not a payload. Without outcomes, a rule +# read and obeyed and a rule read and ignored leave byte-identical telemetry, +# so the readout cannot name the failure. The tests that matter most below are the ones asserting # that a REASONLESS DEPARTURE IS NEVER WRITTEN, and that an unacted rule is # a state in its own right rather than the absence of one. @@ -301,7 +300,7 @@ def test_a_departure_with_no_reason_is_never_written(captured, reason): miss, so writing one would collapse the two states this table exists to separate — silently, in the readout, where nobody would see it happen. Dropped and reported, never stored: telemetry that lies is worse than - telemetry that is absent (#2663).""" + telemetry that is absent.""" rule_usage.record_rule_outcome( user_id=7, rule_id=156, outcome=DEPARTED, source="mcp_rule_outcome", detail=reason or "", @@ -357,10 +356,9 @@ def test_a_rule_opened_and_departed_from_is_departed(): def test_a_rule_opened_and_never_acted_on_is_unacted() -> None: - """THE STATE THAT DID NOT EXIST, and the reason for the milestone. Not - "no data": the rule was surfaced, deliberately opened, and then left no - trace of having mattered. Until now that was arithmetically identical to - compliance, which is why nothing could report it.""" + """THE UNACTED STATE. Not "no data": the rule was surfaced, deliberately + opened, and then left no trace of having mattered. Without this state it + is arithmetically identical to compliance, and nothing can report it.""" assert rule_usage.outcome_state( _usage(surfaced_count=4, pull_count=2) ) == rule_usage.UNACTED @@ -389,5 +387,5 @@ def test_a_departure_outranks_an_application(): def test_the_state_reads_the_aggregate_the_readout_already_returns(): """`outcome_state` takes `usage_for_rules`' own shape, so the badge, the readout and any later session summary cannot disagree about what - "followed" means — the drift #3246 found across the rules system.""" + "followed" means.""" assert rule_usage.outcome_state(rule_usage.empty_rule_usage()) == rule_usage.UNREAD diff --git a/tests/test_session_ledger_clear.py b/tests/test_session_ledger_clear.py index 6ce0e825..be29ccdd 100644 --- a/tests/test_session_ledger_clear.py +++ b/tests/test_session_ledger_clear.py @@ -1,22 +1,18 @@ -"""A compaction clears every session ledger, by convention not by list (#4101). +"""A compaction clears every session ledger, by convention not by list. WHY THIS EXISTS -Milestone 386 established the claim: a ledger describes what a session HOLDS, -so the events that destroy context must destroy it too, or the records it names -become permanently unreachable mid-session. `scribe_session_context.sh` -implemented that — for the rules ledger, by name. - -Five ledgers live in that directory and two were on the list. The note arms' -three (`.ids`, `.sync.ids`, `.derive.ids`) were left, under a comment asserting -this was "a decision rather than an oversight". It was not a decision, and the -arms left out are the ones where it costs most: +A ledger describes what a session HOLDS, so the events that destroy context +must destroy it too, or the records it names become permanently unreachable +mid-session. A clear that names ledgers one by one misses the next one, and the +note arms' three (`.ids`, `.sync.ids`, `.derive.ids`) are where a miss costs +most: - their exclusions are HARD — `exclude_ids` is passed into `semantic_search_notes` itself, so a surfaced note leaves the result set - entirely, with no weaker rendering to fall back to the way #3750 gave a - repeated rule one; - - and they never AGE — #3751's TTL was added to the rules ledger only. + entirely, with no weaker rendering to fall back to the way a repeated + rule has one; + - and they never AGE — the TTL is on the rules ledger only. Hard, permanent and never cleared: a note surfaced in a session's first minute is unreachable for the rest of it, through any number of compactions. @@ -38,7 +34,7 @@ test. Both sides are asserted: And the negative: `.unreached` is not a ledger of held context but a record that the instance could not be reached, and a glob that swept it away -would make a hook forget an outage it is meant to report (#2932). +would make a hook forget an outage it is meant to report. """ import json import os @@ -137,7 +133,7 @@ def test_a_source_that_kept_the_context_keeps_the_ledgers(source, tmp_path): def test_the_outage_marker_is_not_swept_with_them(tmp_path): """`.unreached` records that the instance was down, not what was surfaced. - Different lifetime, different question. #2932's whole point is that "we + Different lifetime, different question. The marker's whole point is that "we checked and found nothing" and "we never managed to check" must stay distinguishable, and a clear that took this file out would quietly answer the second with the first. @@ -235,7 +231,7 @@ def test_the_clear_is_derived_and_not_a_list_of_names(): def test_the_evidence_twin_is_not_swept_with_them(tmp_path): - """The second thing that survives, and for the `.unreached` reason (#4217). + """The second thing that survives, and for the `.unreached` reason. `scribe_rules_append` writes each ledger twice: `..ids`, which says what this context HOLDS and must be forgotten here, and diff --git a/tests/test_snippet_live_body.py b/tests/test_snippet_live_body.py index 004e95b8..6585a1f1 100644 --- a/tests/test_snippet_live_body.py +++ b/tests/test_snippet_live_body.py @@ -1,9 +1,9 @@ -"""Pull-time freshness (#2690) — attach_live_body against a mocked forge. +"""Pull-time freshness — attach_live_body against a mocked forge. The properties that must hold, each with its own way of rotting: - - A no-forge instance's pull response is BYTE-IDENTICAL to today's (rule - #115 — the baseline, not a degraded mode). + - A no-forge instance's pull response is BYTE-IDENTICAL to a plain read + (the baseline, not a degraded mode). - The probe never rewrites the body: "current" refreshes provenance, "diverged" reports, and neither clobbers the record mid-read. - A 404 stamps the mechanically-true 'missing' verdict — once, not on @@ -57,8 +57,8 @@ def _file_response(content: str, commit_sha: str = SHA) -> httpx.Response: def _patched(forge): - """Stub the owner-keyring lookup (#2778): None → an empty selector, i.e. - the owner has no connections — the old 'no forge configured' state.""" + """Stub the owner-keyring lookup: None → an empty selector, i.e. the + owner has no connections — no forge configured.""" from scribe.services.forge import ForgeSelector selector = ForgeSelector(() if forge is None else (forge,)) @@ -112,7 +112,7 @@ async def test_current_with_same_stored_sha_skips_the_write(): async def test_stored_sha_short_circuit_skips_the_content_fetch(): - """#2693: when provenance already names a commit and the forge reports no + """When provenance already names a commit and the forge reports no newer commit touching the path, the pull is confirmed current WITHOUT a content transfer — the economy that fits pull-time freshness inside GitHub's rate limits.""" @@ -274,7 +274,7 @@ async def test_forge_failure_inside_lookup_never_breaks_the_pull(): assert "body_source" not in data -# --- #2782: an annotated record is not a diverged one ------------------------ +# --- an annotated record is not a diverged one ------------------------------ # Containment is right for a verbatim record and wrong for a deliberately # annotated one: the commentary that makes the record worth reading is exactly # what makes `cached in fetched` false, forever. These pin the escape hatch — @@ -326,7 +326,7 @@ async def test_an_expired_verdict_does_not_vouch(): async def test_a_push_invalidated_verdict_does_not_vouch(): - """A push touched the recorded location since the check (#2691) — the repo + """A push touched the recorded location since the check — the repo moved under the verdict even though the record didn't.""" data = _data(code=ANNOTATED, verification=_ok_verdict(invalidated_by="c" * 40)) assert await _freshness(data) == ("cache", "diverged") @@ -349,7 +349,7 @@ async def test_a_verbatim_record_still_takes_the_containment_path(): async def test_a_verdict_predating_commit_stamping_does_not_vouch(): - """Verdicts recorded before `commit_sha` existed (#2688) carry no commit to + """Verdicts recorded before `commit_sha` existed carry no commit to compare, so they cannot tie the body to a known state of the source. They fall through to containment rather than vouching on age alone.""" verdict = svc.compose_verification( diff --git a/tests/test_task_document_shape.py b/tests/test_task_document_shape.py index affa0eea..edd72374 100644 --- a/tests/test_task_document_shape.py +++ b/tests/test_task_document_shape.py @@ -1,10 +1,9 @@ -"""task_document — the document a TASK is embedded as, work logs included (#4251). +"""task_document — the document a TASK is embedded as, work logs included. A work log is the richest record Scribe holds of *why* something is the way it -is: prose written during the work, saying what was tried and ruled out. #4241 -made it readable. It was still not findable, so "has anyone tried this -approach?" — the question a log answers — could not reach one, and #4208 was -rebuilt in this very session because its logs were unreachable. +is: prose written during the work, saying what was tried and ruled out. A log +that is readable but not embedded is not findable, so "has anyone tried this +approach?" — the question a log answers — cannot reach it. These tests pin the shape and the two properties the decision rested on: a task without logs embeds EXACTLY as it always did, and a task with them stays as @@ -30,7 +29,7 @@ D2 = datetime.datetime(2026, 9, 21, 11, 0) def test_a_task_with_no_logs_embeds_exactly_as_it_did_before(): """Most notes are not tasks and most tasks carry no log. Their vectors are the corpus this instance's thresholds were measured against, and changing - them for nothing would move every tuned number underneath itself (#4225).""" + them for nothing would move every tuned number underneath itself.""" assert task_document("A title", "A body") == ("A title", "A body") assert task_document("A title", "A body", []) == ("A title", "A body") assert task_document("T", None) == ("T", None) @@ -81,10 +80,9 @@ def test_an_entry_with_no_timestamp_still_gets_its_own_section(): def test_each_log_becomes_its_own_title_anchored_chunk(): """THE decision this build turns on. The objection to putting logs in the - task's document is that a long log drowns a short title — true before #280, - when one vector per record meant a 2,000-word log averaged the task's - subject away and everything past ~400 words was truncated unread. Chunking - answers both: separate vectors, each carrying the title as its anchor.""" + task's document is that a long log drowns a short title — true of one + vector per record, where a 2,000-word log averages the task's subject away + and everything past ~400 words is truncated unread. Chunking answers both: separate vectors, each carrying the title as its anchor.""" def _entry(subject: str) -> str: para = " ".join([f"This log entry discusses the {subject} in detail."] * 8) return "\n\n".join(f"{para} (p{i})" for i in range(6)) @@ -102,7 +100,7 @@ def test_each_log_becomes_its_own_title_anchored_chunk(): # a log section and scored as part of it. assert any("Short body." in c and "alternative" not in c for c in chunks) - # And nothing is lost: this is what #280 exists for. Paragraph-shaped, + # And nothing is lost: this is what chunking exists for. Paragraph-shaped, # because that is what a log is and because a single unbroken 3,000-char # line is hard-split mid-line by design — `test_chunking` owns that case. joined = "\n".join(chunks) @@ -113,7 +111,7 @@ def test_each_log_becomes_its_own_title_anchored_chunk(): def test_a_short_task_with_a_short_log_is_still_one_sharp_chunk(): """Over-splitting is not the goal either. A task and one short log stay a - single document, the shape note #2485 measured as the sharpest.""" + single document, the shape that measures sharpest.""" title, body = task_document("T", "body", [(D1, "a short note about it")]) assert chunk_document(title, body) == [embedding_text(title, body)] @@ -122,8 +120,8 @@ def test_a_short_task_with_a_short_log_is_still_one_sharp_chunk(): # # The shaper above is pure. These pin that the writers actually call it — a # task whose logs are in the document but never re-indexed after one is written -# is #4241's half-surface one layer down: the entry is readable, and the search -# still answers as though it were never written. +# is a half-surface one layer down: the entry is readable, and the search still +# answers as though it were never written. from unittest.mock import AsyncMock, MagicMock, patch # noqa: E402