docs(6207): migrations 0088 and 0090-0094 state their rationale in terms of the data
Milestone/step labels, record ids, the rescoped-rule date and the 296-call measurement go; each header states what the change protects. "rule 36" citations become the DROP + ADD practice they named. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
"""rules gain a trigger, a tier, canon tags and typed edges (milestone 307
|
||||
step 3, decision note 3026)
|
||||
"""rules gain a trigger, a tier, canon tags and typed edges
|
||||
|
||||
Revision ID: 0088
|
||||
Revises: 0087
|
||||
@@ -31,8 +30,8 @@ down_revision = "0087"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
# Kept in one place so upgrade and the CHECK agree by construction (rule 36:
|
||||
# a whitelisted value means DROP + ADD CONSTRAINT in the same migration —
|
||||
# Kept in one place so upgrade and the CHECK agree by construction (a
|
||||
# whitelisted value means DROP + ADD CONSTRAINT in the same migration —
|
||||
# there is no prior constraint here, so the pair is created together).
|
||||
_TIERS = ("always_on", "conditional")
|
||||
_RELATION_KINDS = ("co_surfaces", "overrides", "elaborates")
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
"""a rule can carry its own check — verify_with, expires_when, verified_at
|
||||
(milestone 312 step 1)
|
||||
|
||||
Revision ID: 0090
|
||||
Revises: 0089
|
||||
@@ -11,10 +10,9 @@ know they did. A CONSTRAINT is a fact about someone else's software: a
|
||||
runner's shell, a bot's config, a tool that exists. Nobody is present when
|
||||
that goes false.
|
||||
|
||||
Milestone 307's rulebook audit found nine stale sites. Every one was a
|
||||
constraint; not one norm had rotted. One of them had been telling every
|
||||
session to skip database-backed tests for weeks while the integration lane
|
||||
sat green in the workflow.
|
||||
What goes stale in a rulebook is the constraints, not the norms — and a
|
||||
stale constraint keeps instructing every session that loads it, long after
|
||||
the world it described has moved.
|
||||
|
||||
Three nullable columns, so a rule can say how to check itself:
|
||||
|
||||
@@ -31,7 +29,7 @@ none of them. A null `verify_with` is not an omission — it is the honest
|
||||
marker of "this one is a decision, and there is nothing to go and check."
|
||||
That signal only works if the field stays empty wherever it belongs empty.
|
||||
|
||||
No CHECK constraint is involved, so rule 36 does not apply here. Nothing is
|
||||
No CHECK constraint is involved. Nothing is
|
||||
backfilled: a migration cannot invent a check any more than 0088 could
|
||||
invent a trigger.
|
||||
"""
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
"""task_kind gains 'spike' — the investigation, not the change
|
||||
(milestone 312 step 5)
|
||||
|
||||
Revision ID: 0091
|
||||
Revises: 0090
|
||||
@@ -12,12 +11,12 @@ end of it. "Find out whether the runner can be given a bash shell" is not
|
||||
work, and filing it as work makes a finished investigation look like an
|
||||
abandoned change.
|
||||
|
||||
It is the record a failed check asks for. Milestone 312 gave rules a
|
||||
It is the record a failed check asks for. Rules carry a
|
||||
`verify_with`; when one of those fails, the rule is wrong and the next move
|
||||
is often to go and find out what replaced it. `notes.arose_from_id` already
|
||||
exists (0065), so that constraint -> spike link needs no further schema.
|
||||
|
||||
Rule 36: `task_kind` is gated by a CHECK whitelist, so the value and the
|
||||
`task_kind` is gated by a CHECK whitelist, so the value and the
|
||||
widened constraint land in the SAME migration — DROP then ADD, exactly as
|
||||
0065 did when it introduced 'issue'. Adding the value and constraining it
|
||||
later leaves a window where the database accepts anything.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
"""a note can carry its own check — verify_with, expires_when, verified_at
|
||||
(milestone 317 step 1)
|
||||
|
||||
Revision ID: 0092
|
||||
Revises: 0091
|
||||
@@ -32,8 +31,7 @@ Three nullable columns:
|
||||
|
||||
WHICH ROWS THESE ARE FOR. `notes` is one table holding notes, tasks,
|
||||
snippets and processes, so these columns land on all of them. Only non-task,
|
||||
non-snippet records are OFFERED them (milestone 317 decisions 1 and 2, gated
|
||||
at the service in step 2): a task's decay is its status, and a snippet
|
||||
non-snippet records are OFFERED them (gated at the service): a task's decay is its status, and a snippet
|
||||
already carries a richer, location-aware verdict in `data.verification`. The
|
||||
columns exist on the other rows and stay null there; a gate that lives in
|
||||
the schema would have meant a partial index or a CHECK across three columns
|
||||
@@ -44,7 +42,7 @@ value of the sweep is that its output is short. A null `verify_with` is not
|
||||
an omission; it is the honest marker of "this one is a decision, and there
|
||||
is nothing to go and check."
|
||||
|
||||
No CHECK constraint is involved, so rule 36 does not apply. Nothing is
|
||||
No CHECK constraint is involved. Nothing is
|
||||
backfilled: a migration cannot invent a check.
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
@@ -69,9 +67,8 @@ def upgrade() -> None:
|
||||
#
|
||||
# Still a sequential scan's job at this size, and an index on
|
||||
# (verified_at) filtered to `verify_with IS NOT NULL` would be maintained
|
||||
# on every note write to serve one operator-initiated query. If step 3's
|
||||
# live acceptance measures otherwise, add it there against a real plan
|
||||
# rather than guessing here.
|
||||
# on every note write to serve one operator-initiated query. If a real
|
||||
# plan says otherwise, add it then rather than guessing here.
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""rules gain an edit history — rule_versions (milestone 323 step 1)
|
||||
"""rules gain an edit history — rule_versions
|
||||
|
||||
Revision ID: 0093
|
||||
Revises: 0092
|
||||
@@ -7,12 +7,9 @@ Create Date: 2026-08-29
|
||||
The sibling `note_versions` has had for a long time. A note's every meaningful
|
||||
edit is snapshotted, and the design-system note calls that history "the
|
||||
changelog". A RULE — which binds behaviour on every session that loads it —
|
||||
had nothing: an edit destroyed what it used to say, with no record anywhere.
|
||||
|
||||
Rescoping rule 79 on 2026-08-29 is what surfaced it. The superseded statement
|
||||
had to be hand-copied into a task log to survive the edit (#3237), which is
|
||||
not a process, it is a person remembering. The more consequential record had
|
||||
the weaker protection.
|
||||
had nothing: an edit destroyed what it used to say, with no record anywhere,
|
||||
and keeping a superseded statement meant a person remembering to copy it
|
||||
somewhere. The more consequential record had the weaker protection.
|
||||
|
||||
Three things are deliberately NOT copied from note_versions, and each is a
|
||||
guard that exists there for a reason that does not hold here:
|
||||
@@ -31,7 +28,7 @@ guard that exists there for a reason that does not hold here:
|
||||
CASCADE: deleting a user must not erase the history of the rules they edited.
|
||||
The edit still happened and the rule still binds because of it.
|
||||
|
||||
No CHECK constraint, so rule 36 does not apply. Nothing is backfilled — a
|
||||
No CHECK constraint is involved. Nothing is backfilled — a
|
||||
migration cannot invent the text a rule used to have, and inventing "the
|
||||
current text, as of now" would be worse than an empty history, because it
|
||||
would look like a record of an edit that never occurred.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""add rule_usage_events — was a surfaced rule ever read? (milestone 333 step 1)
|
||||
"""add rule_usage_events — was a surfaced rule ever read?
|
||||
|
||||
Revision ID: 0094
|
||||
Revises: 0093
|
||||
@@ -9,18 +9,15 @@ table to arrive after `rule_embeddings` and `rule_versions` — each one added
|
||||
because the rule side kept inheriting machinery built for notes and getting
|
||||
the weaker version of it.
|
||||
|
||||
WHAT IT MEASURES. The write-path standing-rule arm is the only retrieval
|
||||
surface in Scribe whose usefulness cannot be observed, and — not coincidentally
|
||||
— the only one that has never declined to fire. Over 30 days it took 296 calls,
|
||||
returned something on every one, and cleared its threshold 100% of the time,
|
||||
while every other surface declines most of the time (#3311). That is either a
|
||||
perfectly tuned surface or a bar it cannot fail to clear, and `retrieval_logs`
|
||||
WHAT IT MEASURES. A standing-rule arm that returns something on every call
|
||||
and clears its threshold every time is either a perfectly tuned surface or a
|
||||
bar it cannot fail to clear, and `retrieval_logs`
|
||||
cannot tell them apart: it records what the ranker scored, never whether the
|
||||
hint was any use.
|
||||
|
||||
WHY NOT A rule_id COLUMN ON note_usage_events. The row shares no note-specific
|
||||
fields and the aggregate readout is the same shape, which is the strongest case
|
||||
for sharing that note #3163 admits. What decides against it is identity at
|
||||
for sharing there is. What decides against it is identity at
|
||||
RESTORE: `note_usage_events`'s importer maps `note_id` through `note_id_map`
|
||||
and drops what does not resolve. A rule id parked in that column would come
|
||||
back from a backup silently reattached to whatever note took that number —
|
||||
@@ -34,8 +31,8 @@ and dies with it; telemetry outlives the row it describes. Deleting a rule must
|
||||
not erase the evidence that it was surfaced forty times and opened never, since
|
||||
that evidence is exactly the case for having deleted it.
|
||||
|
||||
No CHECK on `event`, matching the note twin. Rule 36 governs adding a value to
|
||||
a column that is already gated; it does not require gating one that never was,
|
||||
No CHECK on `event`, matching the note twin. DROP + ADD governs adding a value
|
||||
to a column that is already gated; it does not require gating one that never was,
|
||||
and a two-member enum whose members are written by two functions in one module
|
||||
is not where that discipline earns its cost.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user