feat(rules)!: retire rulebook subscriptions and per-project suppressions (#4052)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / integration (push) Successful in 49s
CI & Build / TypeScript typecheck (push) Successful in 57s
CI & Build / Python tests (push) Failing after 1m3s
CI & Build / Build & push image (push) Skipped
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / integration (push) Successful in 49s
CI & Build / TypeScript typecheck (push) Successful in 57s
CI & Build / Python tests (push) Failing after 1m3s
CI & Build / Build & push image (push) Skipped
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 (#4074). A subscription had stopped changing anything a session received; a suppression muted rules from a subscription. Operator, 2026-09-15: "we have global and project scoped rules, we don't need the subscriptions now." What goes, whole (rule 22): - Migration 0101 drops project_rulebook_subscriptions, project_rule_suppressions and project_topic_suppressions, and strips subscribe_rulebooks (and 394's leftover exclude_always_on_rulebooks) from stored inception choices. - Service, MCP and REST: subscribe/unsubscribe and the four suppress/unsuppress operations. The Subscribers checklist, the subscribe chips, the skip buttons and the Suppressed section in the rules UI. - Inception asks two questions (design system, seed Systems). create_project and decide_project_inception lose subscribe_rulebooks. - Backup v15 stops exporting the three sections; older archives still restore, the keys simply unread. Trash no longer hard-deletes suppression rows. What changes meaning: - get_applicable_rules is a project's LISTING: its own rules, plus the global rules tagged to an area it works in. Untagged global rules apply everywhere and arrive by retrieval, so they are not listed. A co_surfaces partner on a different project is not dragged in. - list_rules(project_id) lists that project's own rules. - rules_payload drops subscribed_rulebooks and suppressed_*; the handshake's brief form is project_rules alone. - using-scribe's "Where a new rule goes" and inception sections, tool docstrings and docs say global vs project. Plugin 2026.09.15.1620. Milestone 414 step 2. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01821k5B3Ysecp9fNYs92Kuy
This commit is contained in:
@@ -62,8 +62,10 @@ Two constraints on *how* that's achieved:
|
||||
empty session is not evidence of an empty rulebook. Retrieval fires when
|
||||
something asks: before a consequential act, `search(content_type="rule")` on
|
||||
what you are about to do, and pull a record's full statement with
|
||||
`get_rule(id)` when it is about to bite. When a project is in scope,
|
||||
`enter_project(id)` also returns the rules bound to its areas.
|
||||
`get_rule(id)` when it is about to bite. When a project is in scope, pass
|
||||
its `project_id`: the answer is then the global rules plus that project's
|
||||
own, never another project's. `enter_project(id)` lists the project's own
|
||||
rules by title.
|
||||
|
||||
**`kind` says how much force a record carries, and it is never something to
|
||||
infer.** A **rule** must be followed: ignoring it breaks something or
|
||||
@@ -243,40 +245,40 @@ bound — confine the session to it:
|
||||
## Starting a project: decide what it inherits
|
||||
|
||||
A project's inheritance is a **decision, not a default**. Before
|
||||
`create_project`, ask the operator the three inception questions and pass the
|
||||
`create_project`, ask the operator the two inception questions and pass the
|
||||
answers — never create a project bare by default:
|
||||
|
||||
- which rulebooks to **subscribe** (`list_rulebooks` shows them; default: none
|
||||
— a rulebook binds a project only when it opts in) →
|
||||
`subscribe_rulebooks=[...]`
|
||||
- which **design system** its UI is built from (`list_design_systems`; or
|
||||
none) → `design_system_id=<id | -1>`
|
||||
- whether to **seed the standard starter Systems** so records can be tagged
|
||||
from day one → `seed_systems=true|false`
|
||||
|
||||
Rules are not an inception question: a global rule already applies to every
|
||||
project, and a project's own rules are written on it as they come up.
|
||||
|
||||
If `enter_project` returns an `inception` key, the project was never decided
|
||||
(it inherits its defaults silently): raise that ask once, with the defaults it
|
||||
carries, then `decide_project_inception(project_id, …)`. Existing projects
|
||||
were stamped "legacy" (inherit-all) and do not ask; any project can be
|
||||
re-decided. The rules/design-system/Systems tools still work one at a time —
|
||||
inception is the moment they are decided together, and the record of why.
|
||||
were stamped "legacy" and do not ask; any project can be re-decided. The
|
||||
design-system and Systems tools still work one at a time — inception is the
|
||||
moment they are decided together, and the record of why.
|
||||
|
||||
## Where a new rule goes
|
||||
|
||||
When codifying a rule, pick its home by **who it should bind** — and keep
|
||||
shared homes general:
|
||||
A rule has one of two homes, and the home IS its reach:
|
||||
|
||||
- **Rulebook** (`create_rule` + `subscribe_project_to_rulebook`) — a reusable,
|
||||
*themed* module of general rules that binds the projects which opt in (e.g. a
|
||||
review checklist → every service). Themed, but project-agnostic.
|
||||
- **Project rule** (`create_project_rule`) — anything specific to one project
|
||||
(its files, paths, quirks).
|
||||
- **Global** — in a rulebook (`create_rule` into a topic). It applies in every
|
||||
project, and reaches a session wherever the work matches it. A rulebook is a
|
||||
*themed* grouping of general rules (e.g. a review checklist), not a list of
|
||||
projects it binds — there is no subscribing a project to one.
|
||||
- **Project** (`create_project_rule`) — anything specific to one project (its
|
||||
files, paths, quirks). It reaches only that project's sessions.
|
||||
|
||||
There used to be a third home — an `always_on` rulebook that bound every
|
||||
project automatically. It is gone: subscription is the only reach a rulebook
|
||||
has. Names one project's specifics → project rule; anything a category of
|
||||
projects shares → rulebook. Never put project-specific detail in a rulebook —
|
||||
it leaks to every other project that subscribes.
|
||||
Names one project's specifics → project rule; a standard that holds wherever
|
||||
the kind of work it describes happens → global. Never put project-specific
|
||||
detail in a rulebook — it would reach every other project. A project that
|
||||
departs from a global rule writes its own and links it with
|
||||
`relate_rules(kind="overrides")`, which says why.
|
||||
|
||||
**Whichever home it gets, a rule needs `when_to_apply`.** It is the only thing
|
||||
that decides whether the rule is ever seen: nothing is preloaded, so a rule
|
||||
|
||||
Reference in New Issue
Block a user