docs(6209): seventeen more test files — lesson shape and round trip, rule scope/moments/kind/surfacing, drift, deadlock race, backup, inception, backfill, claims, supersession, ledgers, family shapes
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 1m7s
CI & Build / Python tests (push) Successful in 1m54s
CI & Build / Build & push image (push) Successful in 12s

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 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 21:37:15 -04:00
co-authored by Claude Opus 5.5
parent ba0b56018e
commit 63e97a6f0f
17 changed files with 95 additions and 123 deletions
+4 -4
View File
@@ -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])
+4 -5
View File
@@ -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"),
+7 -8
View File
@@ -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
@@ -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"
@@ -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:
+6 -6
View File
@@ -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(
+5 -6
View File
@@ -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
+4 -4
View File
@@ -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
+6 -6
View File
@@ -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]
+6 -9
View File
@@ -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",
+9 -10
View File
@@ -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
+6 -8
View File
@@ -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"
+3 -3
View File
@@ -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)
+7 -19
View File
@@ -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 `<sid>.*` 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"
+6 -9
View File
@@ -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.
+3 -4
View File
@@ -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
+4 -4
View File
@@ -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