docs(6205): retrieval_surfaces and family_adoption comments drop citations and the decision quote
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 1m25s
CI & Build / Python tests (push) Successful in 2m9s
CI & Build / Build & push image (push) Successful in 20s

retrieval_surfaces' header states why the arms read their numbers from one
table and why a floor is moved by reading the refused record, without the
quoted decision, the retired arm or the declined-rule instance.
family_adoption drops milestone/step labels from its section headers and
states the no-ids reason instead of naming the trap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 20:29:52 -04:00
co-authored by Claude Opus 5.5
parent dd4bc234e9
commit 32ebc2b1d4
2 changed files with 33 additions and 56 deletions
+9 -8
View File
@@ -1,4 +1,4 @@
"""Family canon's adoption ledger (milestone 463 step 4).
"""Family canon's adoption ledger.
Promotion (services/family.py) decides that an idea is canon for some
platforms. This module decides what each project on those platforms does
@@ -44,7 +44,7 @@ The losing side's reasoning is folded into the idea's note — as a trap, an
alternative, or the branch for its condition — and is never dropped. The
substance changed, so the version moves.
SHAPES (step 5). The shape ledger answers too: a shape classified against an
SHAPES. The shape ledger answers too: a shape classified against an
idea's reference — in any language — is the project's code saying `adopted`
(an instance) or `variant` (with the shape's reason). The two ledgers never
disagree: a classification moves the row, an assessment or undo the shapes
@@ -77,7 +77,7 @@ logger = logging.getLogger(__name__)
# --- the assessment and the conflict order, as product text --------------------
#
# Judged on every install (rules 115, 119); the tool docstrings quote them.
# Judged on every install by the same text; the tool docstrings quote them.
OUTCOMES = (
{
@@ -241,8 +241,9 @@ def needs_recheck(row_status: str, row_version: int | None, idea_status: str,
def _row_state(row: FamilyAdoption) -> dict:
"""An answer as a decision's before/after. No ids (the #3182 trap): the
owed task is the row's column, not part of the snapshot."""
"""An answer as a decision's before/after. No ids, because an id inside
JSON cannot be remapped by a restore: the owed task is the row's column,
not part of the snapshot."""
return {"status": row.status, "reason": row.reason or "", "canon_version": row.canon_version}
@@ -294,7 +295,7 @@ async def _project_languages(session, project_id: int) -> list[str]:
return [r[0] for r in rows]
# --- the shape ledger as evidence (milestone 463 step 5) ----------------------------
# --- the shape ledger as evidence ---------------------------------------------------
#
# A shape classified against an idea's reference IS an answer to the idea: an
# `instance` — or the reference's own `canonical` location — says the project
@@ -618,7 +619,7 @@ async def adoption_matrix(
select(Note).where(Note.id.in_(task_ids), Note.deleted_at.is_(None))
)).scalars().all()
} if task_ids else {}
# The code that answers each cell (step 5): live shapes classified
# The code that answers each cell: live shapes classified
# against one of the idea's references.
evidence: dict[tuple[int, int], list[dict]] = {}
for iid, shape in (await session.execute(
@@ -1215,7 +1216,7 @@ async def _shapes_follow(user_id: int, project_id: int, idea_id: int, outcome: s
return int(result.get("classified") or 0)
# --- delivery (milestone 463 step 6) -------------------------------------------------
# --- delivery -----------------------------------------------------------------------
#
# The ledger reaches a session three ways: a count on entering a project, the
# ideas themselves by retrieval, and the owed answers filed while a task was
+24 -48
View File
@@ -1,34 +1,19 @@
"""One registry of the retrieval surfaces, and the two numbers each one has (#4102).
"""One registry of the retrieval surfaces, and the two numbers each one has.
WHY THIS EXISTS
Six push arms each carried their own loose copy of the same shape: a settings
key, a default, and a limit that was usually a module constant nobody could
change. The read-and-clamp was written out separately in `plugin_context` (twice
over, for auto-inject and the write path), in three rule arms, and again in
the completion-report arm (since retired, milestone 500). That was survivable
while the numbers were shipped constants an operator occasionally edited.
Every push arm has the same shape: a settings key, a default, and a limit. A
floor is chosen and adjusted by the model that uses it, with the operator able
to touch it — and a tuning surface cannot be consistent for the model if every
arm spells its own configuration differently. So the arms do not own their
numbers; they read them from here, and the tuning tool, the routes and the
Settings UI all enumerate THIS table rather than hard-coding special cases.
It stops being survivable once the numbers are meant to MOVE. The operator's
decision for this step:
"the floor should be chosen and adjusted by the model using it. we've come
back to something either fails or has to be looked at by the user we need a
model consistent surface for the adjustment of these floor values. the user
should be able to touch it but the model should be the thing handling it 9
times out of 10."
A tuning surface cannot be "model consistent" if every arm spells its own
configuration differently. So the arms stop owning their numbers and read them
from here instead, and the tuning tool, the routes and the Settings UI all
enumerate THIS table rather than hard-coding six special cases.
WHAT A FLOOR IS NOW, AND WHAT IT IS NOT
WHAT A FLOOR IS, AND WHAT IT IS NOT
It is not a relevance judgement. Relevance is decided by the reader, which is
the only participant that can read a trigger against a situation — that is the
milestone's whole argument, and the injected line has always said so out loud
("read it before deciding it does not apply").
the only participant that can read a trigger against a situation — and the
injected line says so out loud ("read it before deciding it does not apply").
A floor answers the cheaper question: *is this worth ranking at all*. `k` is
what binds, and `k` is a BUDGET — how much of this surface's attention a
@@ -38,29 +23,21 @@ afford what an arm that fires once a turn can.
WHY THE DEFAULTS BELOW ARE STARTING POINTS AND NOT ANSWERS
A cosine score is a distance in BAAI/bge-small-en-v1.5's vector space, measured
against THIS corpus. It cannot transfer to an install with different records,
and rule 115 forbids defending a shipped default from this instance's
telemetry — which is what made the old design unbuildable: every number was a
guess everywhere except here, and there was no mechanism that could ever
improve it.
The mechanism is the fix. Scribe ships a starting point and the means to
correct it, so the values below carry the measurement that motivated them (see
the long comments in `plugin_context.py`, which are kept where they are because
they record how each number was first arrived at) without claiming to be right
for anybody else.
against one corpus. It cannot transfer to an install with different records,
and a shipped default cannot be defended from any one install's telemetry.
Scribe ships a starting point and the means to correct it, so the values carry
the measurement that motivated them without claiming to be right for anybody
else.
HOW A FLOOR SHOULD ACTUALLY BE MOVED
By reading the records the floor refused — `retrieval_telemetry(
near_miss_samples=N)` returns them by id — and never by the percentile alone.
That is not a style preference; it is the one case where the two disagreed and
was checked. `report_preference` logged 69 consecutive declines with the
refused score 0.0006 under the bar, and every percentile said "lower it".
Reading the refused record showed it was rule 77 "Extract intent from loose
phrasing", a false positive, so lowering the bar would have delivered that rule
on every completion report ever written. The statistic and the correct action
pointed in opposite directions, and only opening the record could tell.
An arm can log dozens of consecutive declines with the refused score a hair
under the bar while every percentile says "lower it", and the refused record,
once read, turns out to be a false positive that a lower bar would deliver on
every matching act. The statistic and the correct action can point in opposite
directions, and only opening the record tells them apart.
"""
from __future__ import annotations
@@ -76,11 +53,10 @@ from scribe.services.retrieval_pipeline import ( # noqa: F401 - Surface re-expo
MAX_BUDGET = 10
# THE TABLE IS READ OFF THE SPECS (milestone 456 step 5). Each ranked arm in
# THE TABLE IS READ OFF THE SPECS. Each ranked arm in
# `retrieval_pipeline` carries its own `Surface` — the floor and budget pair,
# its settings keys and defaults, and the prose a tuner reads — so an arm added
# there is tunable by construction, and nothing here can drift from it. The
# keys and defaults are the ones this table held before the move, unchanged.
# there is tunable by construction, and nothing here can drift from it.
SURFACES: dict[str, Surface] = {
arm.tuning.name: arm.tuning for arm in TUNED_ARMS if arm.tuning is not None
}
@@ -88,10 +64,10 @@ SURFACES: dict[str, Surface] = {
# Reserved slots are deliberately absent. `preference_slot`, `reuse_slot` and
# `lesson_slot` borrow their parent arm's floor and are hard-limited to one hit
# each, because their entire purpose is to guarantee a single line to a kind of
# record that keeps losing a general score contest (#2246, #3894) — or, for
# record that keeps losing a general score contest — or, for
# `lesson_slot`, to a kind whose loss is total rather than merely a lost
# convenience, since a lesson has no act arm to fall back on and nobody browses
# lessons looking for one (milestone 385). A budget of "1" is the feature;
# lessons looking for one. A budget of "1" is the feature;
# exposing it as tunable would invite setting it to 0 and silently removing the
# guarantee.
#