docs(6209): task document, query scrubbing, note pipeline, lesson door, live body, ledger clear, rule usage

Seven more test files: docstrings and comments state the property and its
reason, the SQL-twin note states why `\m` and not `\b` without the install
it broke, and fixture provenance says "real near-miss queries" rather than
naming the spike that collected them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 21:29:49 -04:00
co-authored by Claude Opus 5.5
parent 17e1931c0b
commit 0e658bf275
7 changed files with 81 additions and 92 deletions
+11 -11
View File
@@ -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 WHY THIS EXISTS AT ALL
Milestone 385 built the lesson kind through the MCP tools, which is the surface The MCP tools are the surface an agent uses; the Vue app speaks REST. Without
an agent uses. The Vue app speaks REST, so until this blueprint existed a lesson this blueprint a lesson is a record a person cannot create, read, edit or
was a record a person could not create, read, edit or retire from the UI — rule retire from the UI — a feature with no UI, failing at the door rather than in
27's "no UI, no ship" failing at the door rather than in the view. the view.
WHAT THESE PIN WHAT THESE PIN
@@ -17,7 +17,7 @@ kind:
own title would produce lessons that rank differently from the agent's, and own title would produce lessons that rank differently from the agent's, and
the document IS what ranks. 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 routes/snippets.py sets — so a shared editor isn't rejected by the
owner-scoped service. owner-scoped service.
@@ -50,7 +50,7 @@ def test_both_doors_share_one_serializer():
def test_the_rest_door_composes_nothing_itself(): 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 that built its own title would produce lessons that rank differently from
the ones the agent writes.""" the ones the agent writes."""
from scribe.routes import lessons as routes from scribe.routes import lessons as routes
@@ -124,7 +124,7 @@ def test_the_subject_is_required_too():
assert "what is required" in src 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( @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 "can_write_note" in src, f"{handler} does not check write permission"
assert "note.user_id" in src, ( assert "note.user_id" in src, (
f"{handler} writes as the caller rather than as the owner, which " 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(): 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 `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 access helpers. Passing `user_id=uid` INTO a service is the correct call
and is not what this looks for.""" 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(): def test_the_rest_guards_can_fail():
"""Rule 167: shown turning red once.""" """Shown turning red once."""
from scribe.routes import lessons as routes from scribe.routes import lessons as routes
src = inspect.getsource(routes) src = inspect.getsource(routes)
+8 -8
View File
@@ -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 `run_note_arm` is driven directly here, with the search and both recorders
stubbed through `NoteIO`: the stage order, the invariants the rule arms 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, already pin (the call row before any return, the fresh-only cut, the ledger
#4101's ledger-renders-not-removes), the write path's withheld menu (#3739), renders rather than removes), the write path's withheld menu,
and the two reserved slots in their load-bearing order. The builders that 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. 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 return result, io, calls
# ── the call row (#3497, #3752) ─────────────────────────────────────────── # ── the call row ──────────────────────────────────────────────────────────
@pytest.mark.asyncio @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") (row,) = _rows(io.record_retrieval, "auto_inject")
assert [int(n.id) for _s, n in row["results"]] == [22] assert [int(n.id) for _s, n in row["results"]] == [22]
assert row["suppressed"] == 2 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. # shown by its own block.
assert [int(n.id) for _s, n in result.menu] == [11, 22] assert [int(n.id) for _s, n in result.menu] == [11, 22]
(surfaced,) = _rows(io.record_surfaced, "auto_inject") (surfaced,) = _rows(io.record_surfaced, "auto_inject")
@@ -105,7 +105,7 @@ def test_every_notes_stage_logs_before_it_can_return():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_the_band_narrows_the_menu_after_the_row_is_written(): 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.""" floor is tuned against, the surfacing rows are what the reader saw."""
hits = [_note(1, 0.90), _note(2, 0.70)] hits = [_note(1, 0.90), _note(2, 0.70)]
result, io, _ = await _run(rp.WRITE_PATH, lambda kw: hits) 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] 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 @pytest.mark.asyncio
@@ -223,7 +223,7 @@ async def test_a_slot_stands_down_when_its_kind_won_on_score():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_a_slot_spends_itself_on_a_repeat_without_booking_it_again(): 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 """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)] main = [_note(1, 0.70)]
lesson = [_note(42, 0.58, note_type=LESSON_NOTE_TYPE)] lesson = [_note(42, 0.58, note_type=LESSON_NOTE_TYPE)]
result, io, _ = await _run( result, io, _ = await _run(
+14 -17
View File
@@ -1,4 +1,4 @@
"""A logged query never carries a credential (#3925). """A logged query never carries a credential.
WHY THIS EXISTS 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 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 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 would come back OUT into an agent's context on the next tuning pass.
exactly how this was found, during #3853's threshold spike.
WHAT THIS PINS, IN BOTH DIRECTIONS, AND WHY THE SECOND HALF IS THE HARD ONE 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 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 query that was actually refused, and a scrubber that chewed up ordinary
commands would turn the one instrument for tuning a bar into unreadable 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 stubs while still looking like it worked — a surface that reads fine and
surface that reads fine and has quietly stopped saying anything. has quietly stopped saying anything.
So the second block is not padding. Its cases are REAL queries taken from this So the second block is not padding. Its cases are REAL near-miss queries, and
install's `near_miss_samples` during #3853, and they must survive byte for they must survive byte for byte. If a future pattern is added and one of them changes, the pattern is too
byte. If a future pattern is added and one of them changes, the pattern is too
greedy — tighten it rather than editing the expectation. greedy — tighten it rather than editing the expectation.
The secret cases use FABRICATED values in the real formats. Nothing here is or The secret cases use FABRICATED values in the real formats. Nothing here is or
@@ -59,7 +57,7 @@ _SECRETS = [
"MIIEowIBAAKC"), "MIIEowIBAAKC"),
] ]
# Real queries, from this install's near-miss samples during #3853. # Real queries, from near-miss samples.
_EVIDENCE = [ _EVIDENCE = [
"git push origin dev", "git push origin dev",
'git pull --rebase origin dev 2>&1 | tail -3; echo "=== HEAD ==="; git log --oneline -2', '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(): 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 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 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"] 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 0099 carries an inlined copy of these patterns, deliberately: a
# migration is a frozen record of what already ran, and importing the live # migration is a frozen record of what already ran, and importing the live
# ones would mean it quietly did something different next year. # ones would mean it quietly did something different next year.
# #
# Frozen is not the same as correct, and the first cut was neither. The # Frozen is not the same as correct. Without the boundary, `sk-` matches
# boundary was dropped in the port, so `sk-` matched inside any word # inside any word containing it — `<task-notification>` becomes
# containing it — `<task-notification>` became `<ta[redacted:token]>` across # `<ta[redacted:token]>`. And writing `\b` does not help: in Postgres ARE `\b`
# thousands of rows on the one install that ran it. And writing `\b` would not # is a BACKSPACE, not a word boundary.
# have saved it: 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. # `\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 # 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(): def test_the_migrations_patterns_anchor_to_a_word_start_the_postgres_way():
"""`\\m`, never `\\b` — the two are unrelated in Postgres.""" """`\\m`, never `\\b` — the two are unrelated in Postgres."""
+15 -17
View File
@@ -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`. 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 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 assert row["created_at"] is None
# ─── the readout (milestone 333 step 5) ────────────────────────────────────── # ─── the readout ─────────────────────────────────────────────────────────────
# Integration: a real GROUP BY over a real table. Step 1 unit-tested the WRITE # Integration: a real GROUP BY over a real table. The unit tests above cover
# path and the zero shape and left the aggregate uncovered, which only became # the WRITE path and the zero shape; the aggregate the rule list renders needs
# load-bearing when the rule list started rendering it. # a real database.
@pytest.mark.integration @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.integration
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_a_preloaded_rule_does_not_read_as_a_ranked_surfacing(_dispose_engine): 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 A resident rule is delivered every session by a surface that chose
nothing. Counting those as `surfaced_count` would rank the always-on set 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() 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 # What these guard is a distinction, not a payload. Without outcomes, a rule
# rule read and obeyed and a rule read and ignored left byte-identical # read and obeyed and a rule read and ignored leave byte-identical telemetry,
# telemetry, so the readout could not name the failure the whole milestone # so the readout cannot name the failure. The tests that matter most below are the ones asserting
# was opened on. The tests that matter most below are the ones asserting
# that a REASONLESS DEPARTURE IS NEVER WRITTEN, and that an unacted rule is # 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. # 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 miss, so writing one would collapse the two states this table exists to
separate — silently, in the readout, where nobody would see it happen. separate — silently, in the readout, where nobody would see it happen.
Dropped and reported, never stored: telemetry that lies is worse than 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( rule_usage.record_rule_outcome(
user_id=7, rule_id=156, outcome=DEPARTED, user_id=7, rule_id=156, outcome=DEPARTED,
source="mcp_rule_outcome", detail=reason or "", 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: 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 """THE UNACTED STATE. Not "no data": the rule was surfaced, deliberately
"no data": the rule was surfaced, deliberately opened, and then left no opened, and then left no trace of having mattered. Without this state it
trace of having mattered. Until now that was arithmetically identical to is arithmetically identical to compliance, and nothing can report it."""
compliance, which is why nothing could report it."""
assert rule_usage.outcome_state( assert rule_usage.outcome_state(
_usage(surfaced_count=4, pull_count=2) _usage(surfaced_count=4, pull_count=2)
) == rule_usage.UNACTED ) == 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(): def test_the_state_reads_the_aggregate_the_readout_already_returns():
"""`outcome_state` takes `usage_for_rules`' own shape, so the badge, the """`outcome_state` takes `usage_for_rules`' own shape, so the badge, the
readout and any later session summary cannot disagree about what 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 assert rule_usage.outcome_state(rule_usage.empty_rule_usage()) == rule_usage.UNREAD
+12 -16
View File
@@ -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 WHY THIS EXISTS
Milestone 386 established the claim: a ledger describes what a session HOLDS, A ledger describes what a session HOLDS, so the events that destroy context
so the events that destroy context must destroy it too, or the records it names must destroy it too, or the records it names become permanently unreachable
become permanently unreachable mid-session. `scribe_session_context.sh` mid-session. A clear that names ledgers one by one misses the next one, and the
implemented that — for the rules ledger, by name. note arms' three (`.ids`, `.sync.ids`, `.derive.ids`) are where a miss costs
most:
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:
- their exclusions are HARD — `exclude_ids` is passed into - their exclusions are HARD — `exclude_ids` is passed into
`semantic_search_notes` itself, so a surfaced note leaves the result set `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 entirely, with no weaker rendering to fall back to the way a repeated
repeated rule one; rule has one;
- and they never AGE — #3751's TTL was added to the rules ledger only. - 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 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. is unreachable for the rest of it, through any number of compactions.
@@ -38,7 +34,7 @@ test. Both sides are asserted:
And the negative: `<sid>.unreached` is not a ledger of held context but a And the negative: `<sid>.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 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 json
import os 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): def test_the_outage_marker_is_not_swept_with_them(tmp_path):
"""`.unreached` records that the instance was down, not what was surfaced. """`.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 checked and found nothing" and "we never managed to check" must stay
distinguishable, and a clear that took this file out would quietly answer distinguishable, and a clear that took this file out would quietly answer
the second with the first. 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): 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: `<sid>.<kind>.ids`, which `scribe_rules_append` writes each ledger twice: `<sid>.<kind>.ids`, which
says what this context HOLDS and must be forgotten here, and says what this context HOLDS and must be forgotten here, and
+9 -9
View File
@@ -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: 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 - A no-forge instance's pull response is BYTE-IDENTICAL to a plain read
#115 — the baseline, not a degraded mode). (the baseline, not a degraded mode).
- The probe never rewrites the body: "current" refreshes provenance, - The probe never rewrites the body: "current" refreshes provenance,
"diverged" reports, and neither clobbers the record mid-read. "diverged" reports, and neither clobbers the record mid-read.
- A 404 stamps the mechanically-true 'missing' verdict — once, not on - 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): def _patched(forge):
"""Stub the owner-keyring lookup (#2778): None → an empty selector, i.e. """Stub the owner-keyring lookup: None → an empty selector, i.e. the
the owner has no connections — the old 'no forge configured' state.""" owner has no connections — no forge configured."""
from scribe.services.forge import ForgeSelector from scribe.services.forge import ForgeSelector
selector = ForgeSelector(() if forge is None else (forge,)) 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(): 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 newer commit touching the path, the pull is confirmed current WITHOUT a
content transfer — the economy that fits pull-time freshness inside content transfer — the economy that fits pull-time freshness inside
GitHub's rate limits.""" 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 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 # Containment is right for a verbatim record and wrong for a deliberately
# annotated one: the commentary that makes the record worth reading is exactly # annotated one: the commentary that makes the record worth reading is exactly
# what makes `cached in fetched` false, forever. These pin the escape hatch — # 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(): 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.""" moved under the verdict even though the record didn't."""
data = _data(code=ANNOTATED, verification=_ok_verdict(invalidated_by="c" * 40)) data = _data(code=ANNOTATED, verification=_ok_verdict(invalidated_by="c" * 40))
assert await _freshness(data) == ("cache", "diverged") 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(): 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 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.""" fall through to containment rather than vouching on age alone."""
verdict = svc.compose_verification( verdict = svc.compose_verification(
+12 -14
View File
@@ -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 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 is: prose written during the work, saying what was tried and ruled out. A log
made it readable. It was still not findable, so "has anyone tried this that is readable but not embedded is not findable, so "has anyone tried this
approach?" — the question a log answers — could not reach one, and #4208 was approach?" — the question a log answers — cannot reach it.
rebuilt in this very session because its logs were unreachable.
These tests pin the shape and the two properties the decision rested on: a task 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 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(): 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 """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 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("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) 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(): def test_each_log_becomes_its_own_title_anchored_chunk():
"""THE decision this build turns on. The objection to putting logs in the """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, task's document is that a long log drowns a short title — true of one
when one vector per record meant a 2,000-word log averaged the task's vector per record, where a 2,000-word log averages the task's subject away
subject away and everything past ~400 words was truncated unread. Chunking and everything past ~400 words is truncated unread. Chunking answers both: separate vectors, each carrying the title as its anchor."""
answers both: separate vectors, each carrying the title as its anchor."""
def _entry(subject: str) -> str: def _entry(subject: str) -> str:
para = " ".join([f"This log entry discusses the {subject} in detail."] * 8) 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)) 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. # a log section and scored as part of it.
assert any("Short body." in c and "alternative" not in c for c in chunks) 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 # 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. # line is hard-split mid-line by design — `test_chunking` owns that case.
joined = "\n".join(chunks) 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(): 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 """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")]) title, body = task_document("T", "body", [(D1, "a short note about it")])
assert chunk_document(title, body) == [embedding_text(title, body)] 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 # 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 # 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 # is a half-surface one layer down: the entry is readable, and the search still
# still answers as though it were never written. # answers as though it were never written.
from unittest.mock import AsyncMock, MagicMock, patch # noqa: E402 from unittest.mock import AsyncMock, MagicMock, patch # noqa: E402