From cad74df1902bcf79cab66fe14d302461206fceae Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Wed, 21 Oct 2026 20:38:01 -0400 Subject: [PATCH] docs(6206): rulebook model comments state the design, not the history of the rulebook The relation kinds say what each prevents without the rule-46 split story; the removed tier, subscriptions and suppressions are stated as what the model does not have, with the migration that dropped them. Co-Authored-By: Claude Opus 5.5 --- src/scribe/models/rulebook.py | 53 +++++++++++++++-------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/src/scribe/models/rulebook.py b/src/scribe/models/rulebook.py index 7a9c915d..2252e48f 100644 --- a/src/scribe/models/rulebook.py +++ b/src/scribe/models/rulebook.py @@ -92,15 +92,13 @@ class Rule(Base, TimestampMixin, SoftDeleteMixin): # WHEN this rule applies — the trigger, not the instruction. Required of # new rules at the service layer and nullable here, because rules written # before migration 0088 have none and a migration cannot invent one. - # It carries three jobs at once (note 3026): it is the readable form of - # the canon tag, the half of the document that makes a rule findable by - # meaning, and — since milestone 394 removed the always-on tier — the ONLY - # thing that decides whether a rule ever reaches a session at all. A rule + # It carries three jobs at once: it is the readable form of the canon tag, + # the half of the document that makes a rule findable by meaning, and — + # with no always-on tier — the ONLY thing that decides whether a rule ever reaches a session at all. A rule # with no trigger is not a quiet rule, it is an unreachable one. when_to_apply: Mapped[str | None] = mapped_column(Text, nullable=True) - # WHAT KIND of instruction this is. `tier` used to sit beside this and - # carry delivery; milestone 394 removed it, so kind is now the only axis - # on a rule and delivery belongs entirely to retrieval. + # WHAT KIND of instruction this is — the only axis on a rule; delivery + # belongs entirely to retrieval. # `rule` must be FOLLOWED: ignoring it breaks something or crosses a # boundary. `preference` is how this person wants work DONE: ignoring it # costs consistency, not correctness. @@ -116,7 +114,7 @@ class Rule(Base, TimestampMixin, SoftDeleteMixin): # trigger-dominated document, ownership-scoped search, the retrieval arms, # relations, and `rule_versions`, which is where its drift is recorded. # Defaults to `rule` so nothing changes force on upgrade. - # CHECK ck_rules_kind (migration 0098, rule 36). + # CHECK ck_rules_kind (migration 0098). kind: Mapped[str] = mapped_column(Text, default="rule", server_default="rule") why: Mapped[str | None] = mapped_column(Text, nullable=True) how_to_apply: Mapped[str | None] = mapped_column(Text, nullable=True) @@ -141,7 +139,7 @@ class Rule(Base, TimestampMixin, SoftDeleteMixin): DateTime(timezone=True), nullable=True ) # The record that caused this rule — the edge notes and tasks already - # have. Rule 46's `why` names note 2813 in prose; this is that link as a + # have. A `why` can name its origin in prose; this is that link as a # field, so it survives a rewording of the paragraph. arose_from_id: Mapped[int | None] = mapped_column( BigInteger, ForeignKey("notes.id", ondelete="SET NULL"), nullable=True @@ -175,10 +173,9 @@ class Rule(Base, TimestampMixin, SoftDeleteMixin): } -# Which global AREA a rule is about (milestone 307). Points at the canonical -# catalog, NEVER at a project's `systems` row: a rule that spans projects -# cannot be chained to one project's vocabulary. This is the edge three -# projects were drawing by hand, as rule text copied into a System's charter. +# Which global AREA a rule is about. Points at the canonical catalog, NEVER at +# a project's `systems` row: a rule that spans projects cannot be chained to +# one project's vocabulary. rule_systems = Table( "rule_systems", Base.metadata, @@ -188,7 +185,7 @@ rule_systems = Table( ) -# Which MOMENTS of work a rule arrives at (milestone 458). A rule mounted on a +# Which MOMENTS of work a rule arrives at. A rule mounted on a # moment is delivered whenever that moment happens, by lookup and with no # score — the route for a rule that is about WHEN something is done rather # than what it is about, which semantic retrieval structurally misses. The @@ -204,17 +201,15 @@ rule_moments = Table( ) class RuleRelation(Base, CreatedAtMixin): - """A typed edge between two rules. Each kind exists because its ABSENCE - forced a workaround somewhere in the operator's rulebook (note 3026). + """A typed edge between two rules. Each kind exists because without it a + rulebook needs a workaround. - ``co_surfaces`` — these fail together, so they must arrive together. - Without it, the only way to guarantee that was to merge them into one - row, which is what happened to rule 46: split into 144, folded back the - same day because "either rule could surface without the other." + Without it, the only way to guarantee that is to merge them into one + row, because either rule could surface without the other. Symmetric in meaning; stored once and read both ways. - - ``overrides`` — this rule supersedes that one for its scope. Only - *suppression* existed, so an override had to be written as a parallel - rule that then drifts from its parent. + - ``overrides`` — this rule supersedes that one for its scope. Without + it, an override is a parallel rule that drifts from its parent. - ``elaborates`` — this rule adds local specifics to that one; surfacing the parent brings the addendum with it. @@ -232,7 +227,7 @@ class RuleRelation(Base, CreatedAtMixin): to_rule_id: Mapped[int] = mapped_column( BigInteger, ForeignKey("rules.id", ondelete="CASCADE"), index=True ) - # CHECK ck_rule_relations_kind (migration 0088, rule 36). + # CHECK ck_rule_relations_kind (migration 0088). kind: Mapped[str] = mapped_column(Text) note: Mapped[str | None] = mapped_column(Text, nullable=True) @@ -251,10 +246,8 @@ class RuleRelation(Base, CreatedAtMixin): } -# `project_rulebook_subscriptions`, `project_rule_suppressions` and -# `project_topic_suppressions` lived here until milestone 414 (migration 0101). -# A rule's home is its scope now: a rule in a rulebook topic is global, a rule -# on a project applies to that project, and retrieval reads that directly. A -# subscription had stopped changing anything a session received, and a -# suppression muted rules from a subscription. A project that departs from a -# global rule writes a project rule with an `overrides` relation instead. +# A rule's home is its scope: a rule in a rulebook topic is global, a rule on +# a project applies to that project, and retrieval reads that directly. There +# are no per-project subscriptions or suppressions (migration 0101 dropped +# those tables); a project that departs from a global rule writes a project +# rule with an `overrides` relation.