fix(#4022): instruction surfaces stop describing the always-on tier milestone 394 removed
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / integration (push) Successful in 47s
CI & Build / TypeScript typecheck (push) Successful in 58s
CI & Build / Python tests (push) Successful in 1m41s
CI & Build / Build & push image (push) Successful in 28s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / integration (push) Successful in 47s
CI & Build / TypeScript typecheck (push) Successful in 58s
CI & Build / Python tests (push) Successful in 1m41s
CI & Build / Build & push image (push) Successful in 28s
Skill bodies and tool docstrings still taught the deleted model: using-scribe said always-on rules "arrive whether or not you ask" and that SessionStart may inject a rule index; create_project, decide_project_inception and enter_project said an undecided project gets "every always-on rulebook"; create_rule pointed standards at "the always-on one"; the verification sweeps and retrieval_telemetry listed always-on paths and a live preload. Every passage now describes the current model: every rule is retrieved, a rulebook binds only by subscription, an undecided project inherits nothing, and the preload survives only in telemetry rows older than 394. Also repairs three sentences left half-replaced by the 394 edits: the static context's "If you have not loaded the no rule has arrived", create_rule's "an A subscribed rulebook", and create_project's doubled subscribe_rulebooks entry. Plugin version minted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "scribe",
|
"name": "scribe",
|
||||||
"description": "Scribe system-of-record for Claude Code: MCP tools over your notes/tasks/projects/rules, a session-start push channel that surfaces your active-project context, process-skills (writing-plans, reporting-back, systematic-debugging, verification, brainstorming, reusing-code), and your saved Scribe Processes auto-surfaced as skills (/scribe:sync). Replaces superpowers + file-memory with one app-backed plugin.",
|
"description": "Scribe system-of-record for Claude Code: MCP tools over your notes/tasks/projects/rules, a session-start push channel that surfaces your active-project context, process-skills (writing-plans, reporting-back, systematic-debugging, verification, brainstorming, reusing-code), and your saved Scribe Processes auto-surfaced as skills (/scribe:sync). Replaces superpowers + file-memory with one app-backed plugin.",
|
||||||
"version": "2026.09.14.1411",
|
"version": "2026.09.14.1438",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Bryan Van Deusen"
|
"name": "Bryan Van Deusen"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ for the operator's work, and as your own working memory across sessions.
|
|||||||
commit / push, or any other hard-to-reverse or outward-facing action, the
|
commit / push, or any other hard-to-reverse or outward-facing action, the
|
||||||
operator's Scribe rules decide what to do — NOT generic conventions baked
|
operator's Scribe rules decide what to do — NOT generic conventions baked
|
||||||
into the harness or your defaults (e.g. "branch before committing," "open a
|
into the harness or your defaults (e.g. "branch before committing," "open a
|
||||||
feature branch per task," "push to a fork"). If you have not loaded the
|
feature branch per task," "push to a fork"). If no rule has arrived for the
|
||||||
no rule has arrived for the act in front of you, `search(content_type=
|
act in front of you, `search(content_type="rule")` BEFORE acting rather than
|
||||||
"rule")` BEFORE acting rather than falling back on a default habit. When a
|
falling back on a default habit. When a
|
||||||
retrieved rule and a default habit disagree, the rule wins; if no rule
|
retrieved rule and a default habit disagree, the rule wins; if no rule
|
||||||
speaks to it, ask rather than assume.
|
speaks to it, ask rather than assume.
|
||||||
- **Rules bind; preferences do not.** A record's `kind` says which. A **rule**
|
- **Rules bind; preferences do not.** A record's `kind` says which. A **rule**
|
||||||
|
|||||||
@@ -27,10 +27,9 @@ If the working repo maps to a Scribe project (you're in a known repo, or
|
|||||||
project plus the rules bound to the areas it works in, open tasks, and recent
|
project plus the rules bound to the areas it works in, open tasks, and recent
|
||||||
notes in one shot.
|
notes in one shot.
|
||||||
|
|
||||||
Do this actively. A SessionStart hook *may* also inject a rule index, but treat
|
Do this actively. Nothing is handed to a session up front to stand in for it —
|
||||||
that as a bonus, not a precondition: it can be absent (e.g. when the instance is
|
rules arrive by retrieval, when your work or the operator's message matches
|
||||||
unreachable, or the token didn't reach the hook), so the reliable path is this
|
one — so asking and entering the project are the reliable path.
|
||||||
explicit pull. Rules loaded this way are **binding** for the session.
|
|
||||||
|
|
||||||
## Scribe holds these functions — don't keep a second copy
|
## Scribe holds these functions — don't keep a second copy
|
||||||
|
|
||||||
@@ -88,17 +87,16 @@ Two constraints on *how* that's achieved:
|
|||||||
asks. If what you learned is that something MUST be done a certain way,
|
asks. If what you learned is that something MUST be done a certain way,
|
||||||
that is a rule to propose, not a preference to harden in place.
|
that is a rule to propose, not a preference to harden in place.
|
||||||
|
|
||||||
Rules come in two tiers. **Always-on** rules are delivered — they arrive
|
Every rule is RETRIEVED: one reaches you when a command, the code you are
|
||||||
whether or not you ask. **Conditional** rules are RETRIEVED, and one binds
|
writing or the operator's message resembles what it is about, and a rule
|
||||||
just as hard for never having been handed to you. So before a consequential
|
binds just as hard for never having been handed to you. So before a
|
||||||
act, `search(content_type="rule")` on what you are about to do. An empty
|
consequential act, `search(content_type="rule")` on what you are about to
|
||||||
loaded set is not evidence that no rule applies; it is only evidence that
|
do. An empty session is not evidence that no rule applies; it is only
|
||||||
none was pushed, and those are different claims.
|
evidence that nothing has matched yet, and those are different claims.
|
||||||
|
|
||||||
The tier split exists because delivery does not scale: every resident rule
|
Retrieval is what lets a rulebook keep growing — a rule costs nothing in a
|
||||||
costs tokens in every session forever, so a rulebook that grows past a few
|
session it has nothing to do with — but retrieval only fires if something
|
||||||
dozen either stops growing or stops fitting. Retrieval is what lets the
|
asks.
|
||||||
rulebook keep growing — but retrieval only fires if something asks.
|
|
||||||
|
|
||||||
**Ask hardest where you feel most certain.** Rules about which TOOL to reach
|
**Ask hardest where you feel most certain.** Rules about which TOOL to reach
|
||||||
for — use the forge's MCP client rather than curling its API, don't stand up
|
for — use the forge's MCP client rather than curling its API, don't stand up
|
||||||
|
|||||||
@@ -384,8 +384,8 @@ async def notes_due_for_verification(
|
|||||||
thing there is. 0 = no age filter.
|
thing there is. 0 = no age filter.
|
||||||
project_id: narrow to one project. 0 = every project. Unlike the rules
|
project_id: narrow to one project. 0 = every project. Unlike the rules
|
||||||
sweep, this filter is safe: a note belongs to at most one project
|
sweep, this filter is safe: a note belongs to at most one project
|
||||||
outright, with none of the subscription and always-on paths that
|
outright, with none of the subscription paths that would make a
|
||||||
would make a project filter UNDER-report a rule.
|
project filter UNDER-report a rule.
|
||||||
never_only: only notes nobody has ever verified.
|
never_only: only notes nobody has ever verified.
|
||||||
"""
|
"""
|
||||||
uid = current_user_id()
|
uid = current_user_id()
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ async def enter_project(project_id: int) -> dict:
|
|||||||
|
|
||||||
`inception` (milestone 297) appears ONLY when the project is yours and
|
`inception` (milestone 297) appears ONLY when the project is yours and
|
||||||
nobody has decided what it inherits: it carries the current defaults
|
nobody has decided what it inherits: it carries the current defaults
|
||||||
(which always-on rulebooks bind, design system, Systems), what to ask the
|
(the rulebooks it could subscribe to, design system, Systems), what to ask the
|
||||||
operator — once — and the decide_project_inception call that answers it;
|
operator — once — and the decide_project_inception call that answers it;
|
||||||
it repeats on every enter until a decision is recorded.
|
it repeats on every enter until a decision is recorded.
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ async def enter_project(project_id: int) -> dict:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# The inception ask (milestone 297): a project nobody has decided on
|
# The inception ask (milestone 297): a project nobody has decided on
|
||||||
# inherits its defaults silently — always-on rulebooks, no design system,
|
# inherits nothing, silently — no rulebook subscriptions, no design system,
|
||||||
# no Systems. Owner-only (deciding is the owner's), and only until a
|
# no Systems. Owner-only (deciding is the owner's), and only until a
|
||||||
# decision is recorded; the key is ABSENT otherwise (#2483).
|
# decision is recorded; the key is ABSENT otherwise (#2483).
|
||||||
inception_ask = None
|
inception_ask = None
|
||||||
@@ -288,8 +288,8 @@ async def create_project(
|
|||||||
before calling, ask the operator the four inception questions and pass
|
before calling, ask the operator the four inception questions and pass
|
||||||
the answers; a project created without any of them is UNDECIDED and
|
the answers; a project created without any of them is UNDECIDED and
|
||||||
enter_project will ask until decide_project_inception records it.
|
enter_project will ask until decide_project_inception records it.
|
||||||
Defaults if nobody decides: every always-on rulebook binds, nothing is
|
Defaults if nobody decides: no rulebook subscriptions, no design system,
|
||||||
subscribed, no design system, no Systems.
|
no Systems.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
title: Project name (required).
|
title: Project name (required).
|
||||||
@@ -297,11 +297,10 @@ async def create_project(
|
|||||||
goal: The desired outcome or definition of done for the project.
|
goal: The desired outcome or definition of done for the project.
|
||||||
status: one of active (default), paused, completed, archived.
|
status: one of active (default), paused, completed, archived.
|
||||||
color: Optional hex colour for the project card (e.g. "#6366f1").
|
color: Optional hex colour for the project card (e.g. "#6366f1").
|
||||||
subscribe_rulebooks: rulebook ids this project opts into. Since
|
subscribe_rulebooks: rulebook ids this project opts into.
|
||||||
milestone 394 subscription is the only way a rulebook binds a
|
Subscription is the only way a rulebook binds a project, so a
|
||||||
project, so there is no automatic tier left to decline. Was
|
rulebook left out simply does not apply. list_rulebooks shows
|
||||||
NOT inherit ([] = inherit them all). list_rulebooks shows which are
|
which exist.
|
||||||
subscribe_rulebooks: rulebook ids to subscribe (the non-always-on ones).
|
|
||||||
design_system_id: the design system this project's UI is built from
|
design_system_id: the design system this project's UI is built from
|
||||||
(list_design_systems); -1 = explicitly none; 0 = not stated.
|
(list_design_systems); -1 = explicitly none; 0 = not stated.
|
||||||
seed_systems: true mints the standard starter Systems (CI & Release,
|
seed_systems: true mints the standard starter Systems (CI & Release,
|
||||||
@@ -351,9 +350,9 @@ async def decide_project_inception(
|
|||||||
unsubscribe_project_from_rulebook to undo one), replaces the design
|
unsubscribe_project_from_rulebook to undo one), replaces the design
|
||||||
system, and never re-seeds Systems a project already has.
|
system, and never re-seeds Systems a project already has.
|
||||||
|
|
||||||
Args: as create_project's inception args. Passing nothing records an
|
Args: as create_project's inception args. Passing nothing records a
|
||||||
inherit-all decision (every always-on rulebook binds, no subscriptions,
|
decision to take nothing (no subscriptions, no design system, no seed) —
|
||||||
no design system, no seed) — a valid answer, stated.
|
a valid answer, stated.
|
||||||
"""
|
"""
|
||||||
uid = current_user_id()
|
uid = current_user_id()
|
||||||
choices = _inception_choices(
|
choices = _inception_choices(
|
||||||
|
|||||||
@@ -308,13 +308,12 @@ async def create_rule(
|
|||||||
and let the answer stand; re-raising a declined proposal argues a rule
|
and let the answer stand; re-raising a declined proposal argues a rule
|
||||||
into existence, which is the thing this whole loop exists to prevent.
|
into existence, which is the thing this whole loop exists to prevent.
|
||||||
|
|
||||||
A rulebook rule is shared by every project that gets the rulebook: an
|
A rulebook rule is shared by every project subscribed to the rulebook, so
|
||||||
A subscribed rulebook binds the
|
it must read as a general standard —
|
||||||
projects that opt in. So a rulebook rule must read as a general standard —
|
|
||||||
never pin it to one project's files, paths, or quirks. For a rule that
|
never pin it to one project's files, paths, or quirks. For a rule that
|
||||||
applies to a single project only, use create_project_rule instead (no
|
applies to a single project only, use create_project_rule instead (no
|
||||||
rulebook+topic ceremony). If it's a standard a CATEGORY of projects shares,
|
rulebook+topic ceremony). If it's a standard a CATEGORY of projects shares,
|
||||||
put it in a themed subscribed rulebook, not the always-on one.
|
put it in a rulebook for that category and subscribe those projects to it.
|
||||||
|
|
||||||
Write it general WITHOUT hedging for the exceptions. A project that needs
|
Write it general WITHOUT hedging for the exceptions. A project that needs
|
||||||
to strengthen, narrow or replace this rule writes its own and links it
|
to strengthen, narrow or replace this rule writes its own and links it
|
||||||
@@ -1048,8 +1047,8 @@ async def rules_due_for_verification(
|
|||||||
never_only: only rules nobody has ever verified.
|
never_only: only rules nobody has ever verified.
|
||||||
|
|
||||||
NOT filterable by project, deliberately: a project reaches rules through
|
NOT filterable by project, deliberately: a project reaches rules through
|
||||||
project scope, subscriptions, always-on rulebooks and exclusions, and a
|
project scope and rulebook subscriptions, and a filter that missed one of
|
||||||
filter that missed one of those paths would UNDER-report — which is the
|
those paths would UNDER-report — which is the
|
||||||
exact failure this whole surface exists to prevent. Read the whole list.
|
exact failure this whole surface exists to prevent. Read the whole list.
|
||||||
"""
|
"""
|
||||||
uid = current_user_id()
|
uid = current_user_id()
|
||||||
|
|||||||
@@ -280,19 +280,20 @@ It is an UPPER BOUND per surface: a pull records the door it came
|
|||||||
|
|
||||||
`surfaced` VS `ambient` IS THE READING THAT MATTERS HERE. `surfaced` counts
|
`surfaced` VS `ambient` IS THE READING THAT MATTERS HERE. `surfaced` counts
|
||||||
rules a ranker chose — today only the write-path arm — and those are claims
|
rules a ranker chose — today only the write-path arm — and those are claims
|
||||||
a pull can settle. `ambient` counts BULK DELIVERIES: the SessionStart
|
a pull can settle. `ambient` counts BULK DELIVERIES: the `rules_payload`
|
||||||
preload and the `rules_payload` surfaces
|
surfaces (`enter_project`, `get_project`, `get_milestone`,
|
||||||
(`enter_project`, `get_project`, `get_milestone`, `start_planning`,
|
`start_planning`, `get_task`), which hand over the whole applicable set at
|
||||||
`get_task`), which hand over the whole applicable set at once with nobody
|
once with nobody choosing anything — plus, in rows older than milestone
|
||||||
choosing anything. A large `ambient` says the resident set is big and
|
394, the SessionStart preload it removed. A large `ambient` says a bulk set
|
||||||
arrives often — never that it is useful, and never that it is read.
|
is big and arrives often — never that it is useful, and never that it is
|
||||||
|
read.
|
||||||
|
|
||||||
`pull_through` therefore divides by `surfaced` alone. Fold the preload in
|
`pull_through` therefore divides by `surfaced` alone. Fold the preload in
|
||||||
and growing the always-on set would depress the arm's measured precision
|
and growing a bulk set would depress the arm's measured precision while
|
||||||
while trimming it would flatter it, for reasons having nothing to do with
|
trimming it would flatter it, for reasons having nothing to do with the
|
||||||
the arm. To judge the PRELOAD instead, compare `ambient` against pulls of
|
arm. To judge a BULK surface instead, compare `ambient` against pulls of
|
||||||
those same rules over time: a resident set surfaced thousands of times and
|
those same rules over time: a set surfaced thousands of times and opened
|
||||||
opened never is the dead-weight signal, one tier up.
|
never is the dead-weight signal, one level up.
|
||||||
|
|
||||||
Read it against `sources["write_path_rule"]`. That arm was once believed
|
Read it against `sources["write_path_rule"]`. That arm was once believed
|
||||||
never to decline — the reading that scoped #3311 — but it was the arm's
|
never to decline — the reading that scoped #3311 — but it was the arm's
|
||||||
|
|||||||
Reference in New Issue
Block a user