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 <noreply@anthropic.com>
This commit is contained in:
@@ -92,15 +92,13 @@ class Rule(Base, TimestampMixin, SoftDeleteMixin):
|
|||||||
# WHEN this rule applies — the trigger, not the instruction. Required of
|
# WHEN this rule applies — the trigger, not the instruction. Required of
|
||||||
# new rules at the service layer and nullable here, because rules written
|
# new rules at the service layer and nullable here, because rules written
|
||||||
# before migration 0088 have none and a migration cannot invent one.
|
# 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
|
# It carries three jobs at once: it is the readable form of the canon tag,
|
||||||
# the canon tag, the half of the document that makes a rule findable by
|
# the half of the document that makes a rule findable by meaning, and —
|
||||||
# meaning, and — since milestone 394 removed the always-on tier — the ONLY
|
# with no always-on tier — the ONLY thing that decides whether a rule ever reaches a session at all. A rule
|
||||||
# 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.
|
# with no trigger is not a quiet rule, it is an unreachable one.
|
||||||
when_to_apply: Mapped[str | None] = mapped_column(Text, nullable=True)
|
when_to_apply: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||||
# WHAT KIND of instruction this is. `tier` used to sit beside this and
|
# WHAT KIND of instruction this is — the only axis on a rule; delivery
|
||||||
# carry delivery; milestone 394 removed it, so kind is now the only axis
|
# belongs entirely to retrieval.
|
||||||
# on a rule and delivery belongs entirely to retrieval.
|
|
||||||
# `rule` must be FOLLOWED: ignoring it breaks something or crosses a
|
# `rule` must be FOLLOWED: ignoring it breaks something or crosses a
|
||||||
# boundary. `preference` is how this person wants work DONE: ignoring it
|
# boundary. `preference` is how this person wants work DONE: ignoring it
|
||||||
# costs consistency, not correctness.
|
# costs consistency, not correctness.
|
||||||
@@ -116,7 +114,7 @@ class Rule(Base, TimestampMixin, SoftDeleteMixin):
|
|||||||
# trigger-dominated document, ownership-scoped search, the retrieval arms,
|
# trigger-dominated document, ownership-scoped search, the retrieval arms,
|
||||||
# relations, and `rule_versions`, which is where its drift is recorded.
|
# relations, and `rule_versions`, which is where its drift is recorded.
|
||||||
# Defaults to `rule` so nothing changes force on upgrade.
|
# 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")
|
kind: Mapped[str] = mapped_column(Text, default="rule", server_default="rule")
|
||||||
why: Mapped[str | None] = mapped_column(Text, nullable=True)
|
why: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||||
how_to_apply: 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
|
DateTime(timezone=True), nullable=True
|
||||||
)
|
)
|
||||||
# The record that caused this rule — the edge notes and tasks already
|
# 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.
|
# field, so it survives a rewording of the paragraph.
|
||||||
arose_from_id: Mapped[int | None] = mapped_column(
|
arose_from_id: Mapped[int | None] = mapped_column(
|
||||||
BigInteger, ForeignKey("notes.id", ondelete="SET NULL"), nullable=True
|
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
|
# Which global AREA a rule is about. Points at the canonical catalog, NEVER at
|
||||||
# catalog, NEVER at a project's `systems` row: a rule that spans projects
|
# a project's `systems` row: a rule that spans projects cannot be chained to
|
||||||
# cannot be chained to one project's vocabulary. This is the edge three
|
# one project's vocabulary.
|
||||||
# projects were drawing by hand, as rule text copied into a System's charter.
|
|
||||||
rule_systems = Table(
|
rule_systems = Table(
|
||||||
"rule_systems",
|
"rule_systems",
|
||||||
Base.metadata,
|
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
|
# 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
|
# 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
|
# than what it is about, which semantic retrieval structurally misses. The
|
||||||
@@ -204,17 +201,15 @@ rule_moments = Table(
|
|||||||
)
|
)
|
||||||
|
|
||||||
class RuleRelation(Base, CreatedAtMixin):
|
class RuleRelation(Base, CreatedAtMixin):
|
||||||
"""A typed edge between two rules. Each kind exists because its ABSENCE
|
"""A typed edge between two rules. Each kind exists because without it a
|
||||||
forced a workaround somewhere in the operator's rulebook (note 3026).
|
rulebook needs a workaround.
|
||||||
|
|
||||||
- ``co_surfaces`` — these fail together, so they must arrive together.
|
- ``co_surfaces`` — these fail together, so they must arrive together.
|
||||||
Without it, the only way to guarantee that was to merge them into one
|
Without it, the only way to guarantee that is to merge them into one
|
||||||
row, which is what happened to rule 46: split into 144, folded back the
|
row, because either rule could surface without the other.
|
||||||
same day because "either rule could surface without the other."
|
|
||||||
Symmetric in meaning; stored once and read both ways.
|
Symmetric in meaning; stored once and read both ways.
|
||||||
- ``overrides`` — this rule supersedes that one for its scope. Only
|
- ``overrides`` — this rule supersedes that one for its scope. Without
|
||||||
*suppression* existed, so an override had to be written as a parallel
|
it, an override is a parallel rule that drifts from its parent.
|
||||||
rule that then drifts from its parent.
|
|
||||||
- ``elaborates`` — this rule adds local specifics to that one; surfacing
|
- ``elaborates`` — this rule adds local specifics to that one; surfacing
|
||||||
the parent brings the addendum with it.
|
the parent brings the addendum with it.
|
||||||
|
|
||||||
@@ -232,7 +227,7 @@ class RuleRelation(Base, CreatedAtMixin):
|
|||||||
to_rule_id: Mapped[int] = mapped_column(
|
to_rule_id: Mapped[int] = mapped_column(
|
||||||
BigInteger, ForeignKey("rules.id", ondelete="CASCADE"), index=True
|
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)
|
kind: Mapped[str] = mapped_column(Text)
|
||||||
note: Mapped[str | None] = mapped_column(Text, nullable=True)
|
note: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||||
|
|
||||||
@@ -251,10 +246,8 @@ class RuleRelation(Base, CreatedAtMixin):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# `project_rulebook_subscriptions`, `project_rule_suppressions` and
|
# A rule's home is its scope: a rule in a rulebook topic is global, a rule on
|
||||||
# `project_topic_suppressions` lived here until milestone 414 (migration 0101).
|
# a project applies to that project, and retrieval reads that directly. There
|
||||||
# A rule's home is its scope now: a rule in a rulebook topic is global, a rule
|
# are no per-project subscriptions or suppressions (migration 0101 dropped
|
||||||
# on a project applies to that project, and retrieval reads that directly. A
|
# those tables); a project that departs from a global rule writes a project
|
||||||
# subscription had stopped changing anything a session received, and a
|
# rule with an `overrides` relation.
|
||||||
# suppression muted rules from a subscription. A project that departs from a
|
|
||||||
# global rule writes a project rule with an `overrides` relation instead.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user