feat(reuse): recording model becomes the pattern library — every shape at first build (#2687)

Decision #2686: snippets are the project's pattern library, not a dedup
net. The floor, the reusing-code skill, and the snippet tool docstrings
now state the proactive model — record every shape the first time it is
built, with no will-it-recur judgment, and start later instances from
the recorded shape; second-copy consolidation stays as the backstop.
The floor guard test pins all three elements (tool, first-build trigger,
backstop) so the model cannot silently regress to the reactive wording.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 11:33:24 -04:00
co-authored by Claude Fable 5
parent 4107b17727
commit 2d58e74ec7
4 changed files with 70 additions and 42 deletions
+15 -10
View File
@@ -52,16 +52,21 @@ for the operator's work, and as your own working memory across sessions.
it. An untagged project record carries the `systems_hint` question instead, it. An untagged project record carries the `systems_hint` question instead,
on creates, updates, and work-logs alike — treat it as the tagging question on creates, updates, and work-logs alike — treat it as the tagging question
asked at the moment of work, not as noise to skip past. asked at the moment of work, not as noise to skip past.
- **Reuse before rebuilding — and record what you build** — before writing a - **The pattern library: start from recorded shapes, and record every shape
new helper/utility/component, search recorded **snippets** (reusable code at first build** — recorded **snippets** are the project's pattern library,
recorded once for recall) and reuse the prior art instead of re-solving it. not a dedup net. Before building ANY shape — a button, an input field, a
The recording half has NAMED TRIGGERS, not a vibe: the moment you extract a modal, a route handler, a service class, a test scaffold, up through complex
shared component, hoist a helper into a common module, or notice you are subsystem patterns — search snippets and START from the recorded shape; a
writing the second copy of anything, record it with `create_snippet` (name, deliberate departure is recorded as its own named variant, never left as
code, when-to-reach-for-it, location) in the same breath as the commit. silent drift. And the FIRST time a shape is built, record it with
Work that "refactors X into a shared Y" is not finished until Y is recorded `create_snippet` (name, when-to-reach-for-it, location, code) in the same
— an unrecorded shared component is invisible to every later session, which breath — do not judge whether it "might recur": the builder of the first
is how a codebase grows four `.btn-primary` definitions. instance can never know, and a missed record is invisible until it
resurfaces as an uninformed duplicate. A mature project's snippet corpus
should read as a map of every shape in it. The backstop still holds:
noticing the second copy of anything, or consolidating copies into a shared
X, means X gets recorded before that work is finished — which is how a
codebase is kept from growing four `.btn-primary` definitions.
- Do **not** keep the operator's rules, plans, or project notes in local - Do **not** keep the operator's rules, plans, or project notes in local
memory / CLAUDE.md in parallel with Scribe — Scribe holds the single copy. memory / CLAUDE.md in parallel with Scribe — Scribe holds the single copy.
- **Compact at clean seams** — because you record as you go, a context - **Compact at clean seams** — because you record as you go, a context
+26 -15
View File
@@ -1,20 +1,24 @@
--- ---
name: reusing-code name: reusing-code
description: Use when you're about to write a helper, utility, hook, or reusable component — search recorded snippets FIRST so prior art is reused instead of re-solved. And the moment you build or notice something reusable, record it as a snippet so a later session finds it. Triggers on "write a util/helper", "I need a function that…", "let me add a component", or just having built something worth reusing. description: Use when you're about to build ANY shape — a component, control, route handler, service class, helper, test scaffold — search recorded snippets FIRST and start from the recorded shape instead of re-solving it. And the FIRST time a shape is built, record it as a snippet so every later instance starts from it. Triggers on "write a util/helper", "I need a function that…", "let me add a component/button/field/route", or having just built the first instance of anything.
--- ---
# Reusing code — recall before you rebuild # Reusing code — the pattern library
Reusable code is worth writing once. Scribe stores **snippets** — a named, Snippets are the project's **pattern library**, not a dedup net. Each records a
reusable function or component recorded with its language, signature, canonical named shape — with its language, signature, canonical location (repo · path ·
location (repo · path · symbol), a one-line *"when to reach for it,"* and the symbol), a one-line *"when to reach for it,"* and the code — so every later
code itself — so prior art can surface *before* it's re-written as a one-off. instance STARTS from the recorded shape: buttons start from the button shape,
fields from the field shape, and "special" is a deliberate, named exception
rather than drift. A mature project's snippet corpus reads as a map of every
shape in it, from the humblest control to the most complex subsystem pattern.
Snippets are ordinary embedded notes, so a recorded one also surfaces on its own Snippets are ordinary embedded notes, so a recorded one also surfaces on its own
through recall/auto-inject; this skill is the active reflex around that. through recall/auto-inject; this skill is the active reflex around that.
## Before you write a new helper — search first ## Before you build any shape — search first
- About to write a utility, hook, formatter, adapter, or a reusable component? - About to build a component, control, route handler, service class, utility,
hook, formatter, adapter, or test scaffold?
**Search snippets before writing it.** `list_snippets(q="…")` (or a plain **Search snippets before writing it.** `list_snippets(q="…")` (or a plain
`search`) — a matching one may already exist, in this project or another. `search`) — a matching one may already exist, in this project or another.
`list_snippets` searches every project by default; that's deliberate, since a `list_snippets` searches every project by default; that's deliberate, since a
@@ -38,10 +42,15 @@ through recall/auto-inject; this skill is the active reflex around that.
duplicate — reuse it and drop yours — or it isn't, and the record needs the new duplicate — reuse it and drop yours — or it isn't, and the record needs the new
location adding. Both are cheaper now than after the duplicate settles in. location adding. Both are cheaper now than after the duplicate settles in.
## The moment you build something reusable — record it ## The first time a shape is built — record it
- Just wrote (or noticed) a helper, hook, pattern, or component worth repeating? - Just built the FIRST instance of anything with a shape — a component, a
Record it with `create_snippet` while it's fresh: field, a route, a service pattern, a scaffold? Record it with
`create_snippet` while it's fresh. Do **not** stop to judge whether it will
recur: the builder of the first instance can never know, and a missed record
is invisible until it resurfaces as an uninformed duplicate. Over-recording
is safe — dead weight shows up in the usage counters and can be pruned;
under-recording has no signal at all. The record is cheap — these fields:
- **name** — what it's called, e.g. `useDebouncedRef`. - **name** — what it's called, e.g. `useDebouncedRef`.
- **code** — the implementation. - **code** — the implementation.
- **when_to_use** — one sharp line on when to reach for it. This becomes part - **when_to_use** — one sharp line on when to reach for it. This becomes part
@@ -92,7 +101,9 @@ gate only hints at when it blocks a near-duplicate.
## Why this pays off ## Why this pays off
A one-off written a second time is the cost this avoids. Recording a snippet A one-off written a second time is the cost this avoids — and at project
once — with a location and a crisp "when to use" — means the next session is scale, the cost is an application whose buttons, fields, and services each
offered the prior art instead of re-solving it. Search before writing; record exist in four diverging shapes. Recording every shape once — with a location
what's worth reusing. and a crisp "when to use" — means every later session starts from the pattern
library instead of re-deriving it. Search before building; record every shape
at first build.
+17 -7
View File
@@ -23,7 +23,12 @@ async def list_snippets(
q: str = "", tag: str = "", limit: int = 50, project_id: int = 0, q: str = "", tag: str = "", limit: int = 50, project_id: int = 0,
repo: str = "", path: str = "", symbol: str = "", verification: str = "", repo: str = "", path: str = "", symbol: str = "", verification: str = "",
) -> dict: ) -> dict:
"""List recorded snippets (reusable functions/components). """List recorded snippets — the project's pattern library.
Search here BEFORE building any shape (a component, control, route
handler, service class, helper, scaffold): a recorded shape is the
starting point for every later instance, and building without checking is
how the same button ends up defined four diverging ways.
Two ways to ask, usable together: by MEANING (`q` — "what do I need this code Two ways to ask, usable together: by MEANING (`q` — "what do I need this code
to do?") and by PLACE (`repo`/`path`/`symbol` — "what canonical helpers to do?") and by PLACE (`repo`/`path`/`symbol` — "what canonical helpers
@@ -101,13 +106,18 @@ async def create_snippet(
system_ids: list[int] | None = None, system_ids: list[int] | None = None,
force: bool = False, force: bool = False,
) -> dict: ) -> dict:
"""Record a reusable function/component so future sessions can RECALL it """Record a shape in the project's pattern library, so every later
instead of writing a fresh one-off. instance starts from it instead of re-deriving it.
Reach for this the moment you build (or notice) something reusable: a helper, Reach for this the FIRST time any shape is built — a component, a control,
a hook, a component, a pattern worth repeating. Recording it once makes it a route handler, a service class, a helper, a test scaffold — not only
surface automatically when a similar problem comes up later. Before writing a when something is judged "reusable": the builder of the first instance
new utility, search first — a snippet may already exist. can't know what will recur, and a missed record is invisible until it
resurfaces as an uninformed duplicate. Over-recording is safe (dead weight
shows in the usage counters and can be pruned); under-recording has no
signal. A deliberate departure from a recorded shape is recorded as its
own named variant, not left as drift. Before building, search first — the
shape may already be recorded.
Args: Args:
name: Short name of the function/component, e.g. "useDebouncedRef". name: Short name of the function/component, e.g. "useDebouncedRef".
+12 -10
View File
@@ -129,21 +129,23 @@ def test_floor_states_the_systems_reflex():
def test_floor_names_the_snippet_recording_triggers(): def test_floor_names_the_snippet_recording_triggers():
"""The recording half of reuse needs NAMED trigger moments on the floor. """The floor must state the pattern-library recording model, by name.
#2664's behavioral finding: with recording guidance as a trailing clause of #2664's behavioral finding: recording guidance as a trailing clause of the
the reuse bullet, zero snippets were ever recorded outside sessions already reuse bullet converted zero times outside snippet-minded sessions. The
thinking about snippets — extracting a shared component (Roundtable's 2026-08-16 ruling (decision #2686) then replaced the reactive model
BaseModal) produced task prose and no record. The floor must name the entirely: every shape is recorded at FIRST build — no "will it recur?"
moments, not just the tool. judgment — and second-copy consolidation is only the backstop. The floor
is the delivery surface for that reflex, so all three elements must stay
stated: the tool, the first-build trigger, and the backstop.
""" """
floor = (ROOT / "plugin" / "hooks" / "scribe_static_context.md").read_text() floor = (ROOT / "plugin" / "hooks" / "scribe_static_context.md").read_text()
for needle in ("create_snippet", "second copy"): for needle in ("create_snippet", "first build", "second copy"):
assert needle in floor, ( assert needle in floor, (
f"plugin/hooks/scribe_static_context.md no longer states the " f"plugin/hooks/scribe_static_context.md no longer states the "
f"snippet-recording trigger ({needle!r}) — the record-as-you-build " f"snippet-recording model ({needle!r}) — record-every-shape-at-"
f"reflex must be stated on the floor with its trigger moments " f"first-build with second-copy consolidation as the backstop must "
f"(#2664)." f"be stated on the floor (#2664, decision #2686)."
) )