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
|
"""rules gain a trigger, a tier, canon tags and typed edges
|
||||||
step 3, decision note 3026)
|
|
||||||
|
|
||||||
Revision ID: 0088
|
Revision ID: 0088
|
||||||
Revises: 0087
|
Revises: 0087
|
||||||
@@ -31,8 +30,8 @@ down_revision = "0087"
|
|||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
# Kept in one place so upgrade and the CHECK agree by construction (rule 36:
|
# Kept in one place so upgrade and the CHECK agree by construction (a
|
||||||
# a whitelisted value means DROP + ADD CONSTRAINT in the same migration —
|
# whitelisted value means DROP + ADD CONSTRAINT in the same migration —
|
||||||
# there is no prior constraint here, so the pair is created together).
|
# there is no prior constraint here, so the pair is created together).
|
||||||
_TIERS = ("always_on", "conditional")
|
_TIERS = ("always_on", "conditional")
|
||||||
_RELATION_KINDS = ("co_surfaces", "overrides", "elaborates")
|
_RELATION_KINDS = ("co_surfaces", "overrides", "elaborates")
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
"""a rule can carry its own check — verify_with, expires_when, verified_at
|
"""a rule can carry its own check — verify_with, expires_when, verified_at
|
||||||
(milestone 312 step 1)
|
|
||||||
|
|
||||||
Revision ID: 0090
|
Revision ID: 0090
|
||||||
Revises: 0089
|
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
|
runner's shell, a bot's config, a tool that exists. Nobody is present when
|
||||||
that goes false.
|
that goes false.
|
||||||
|
|
||||||
Milestone 307's rulebook audit found nine stale sites. Every one was a
|
What goes stale in a rulebook is the constraints, not the norms — and a
|
||||||
constraint; not one norm had rotted. One of them had been telling every
|
stale constraint keeps instructing every session that loads it, long after
|
||||||
session to skip database-backed tests for weeks while the integration lane
|
the world it described has moved.
|
||||||
sat green in the workflow.
|
|
||||||
|
|
||||||
Three nullable columns, so a rule can say how to check itself:
|
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."
|
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.
|
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
|
backfilled: a migration cannot invent a check any more than 0088 could
|
||||||
invent a trigger.
|
invent a trigger.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
"""task_kind gains 'spike' — the investigation, not the change
|
"""task_kind gains 'spike' — the investigation, not the change
|
||||||
(milestone 312 step 5)
|
|
||||||
|
|
||||||
Revision ID: 0091
|
Revision ID: 0091
|
||||||
Revises: 0090
|
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
|
work, and filing it as work makes a finished investigation look like an
|
||||||
abandoned change.
|
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
|
`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
|
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.
|
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
|
widened constraint land in the SAME migration — DROP then ADD, exactly as
|
||||||
0065 did when it introduced 'issue'. Adding the value and constraining it
|
0065 did when it introduced 'issue'. Adding the value and constraining it
|
||||||
later leaves a window where the database accepts anything.
|
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
|
"""a note can carry its own check — verify_with, expires_when, verified_at
|
||||||
(milestone 317 step 1)
|
|
||||||
|
|
||||||
Revision ID: 0092
|
Revision ID: 0092
|
||||||
Revises: 0091
|
Revises: 0091
|
||||||
@@ -32,8 +31,7 @@ Three nullable columns:
|
|||||||
|
|
||||||
WHICH ROWS THESE ARE FOR. `notes` is one table holding notes, tasks,
|
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,
|
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
|
non-snippet records are OFFERED them (gated at the service): a task's decay is its status, and a snippet
|
||||||
at the service in step 2): a task's decay is its status, and a snippet
|
|
||||||
already carries a richer, location-aware verdict in `data.verification`. The
|
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
|
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
|
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
|
an omission; it is the honest marker of "this one is a decision, and there
|
||||||
is nothing to go and check."
|
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.
|
backfilled: a migration cannot invent a check.
|
||||||
"""
|
"""
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
@@ -69,9 +67,8 @@ def upgrade() -> None:
|
|||||||
#
|
#
|
||||||
# Still a sequential scan's job at this size, and an index on
|
# 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
|
# (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
|
# on every note write to serve one operator-initiated query. If a real
|
||||||
# live acceptance measures otherwise, add it there against a real plan
|
# plan says otherwise, add it then rather than guessing here.
|
||||||
# rather than guessing here.
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
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
|
Revision ID: 0093
|
||||||
Revises: 0092
|
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
|
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
|
edit is snapshotted, and the design-system note calls that history "the
|
||||||
changelog". A RULE — which binds behaviour on every session that loads it —
|
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.
|
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
|
||||||
Rescoping rule 79 on 2026-08-29 is what surfaced it. The superseded statement
|
somewhere. The more consequential record had the weaker protection.
|
||||||
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.
|
|
||||||
|
|
||||||
Three things are deliberately NOT copied from note_versions, and each is a
|
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:
|
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.
|
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.
|
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
|
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
|
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.
|
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
|
Revision ID: 0094
|
||||||
Revises: 0093
|
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
|
because the rule side kept inheriting machinery built for notes and getting
|
||||||
the weaker version of it.
|
the weaker version of it.
|
||||||
|
|
||||||
WHAT IT MEASURES. The write-path standing-rule arm is the only retrieval
|
WHAT IT MEASURES. A standing-rule arm that returns something on every call
|
||||||
surface in Scribe whose usefulness cannot be observed, and — not coincidentally
|
and clears its threshold every time is either a perfectly tuned surface or a
|
||||||
— the only one that has never declined to fire. Over 30 days it took 296 calls,
|
bar it cannot fail to clear, and `retrieval_logs`
|
||||||
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`
|
|
||||||
cannot tell them apart: it records what the ranker scored, never whether the
|
cannot tell them apart: it records what the ranker scored, never whether the
|
||||||
hint was any use.
|
hint was any use.
|
||||||
|
|
||||||
WHY NOT A rule_id COLUMN ON note_usage_events. The row shares no note-specific
|
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
|
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`
|
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
|
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 —
|
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
|
not erase the evidence that it was surfaced forty times and opened never, since
|
||||||
that evidence is exactly the case for having deleted it.
|
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
|
No CHECK on `event`, matching the note twin. DROP + ADD governs adding a value
|
||||||
a column that is already gated; it does not require gating one that never was,
|
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
|
and a two-member enum whose members are written by two functions in one module
|
||||||
is not where that discipline earns its cost.
|
is not where that discipline earns its cost.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user