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:
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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".
|
||||||
|
|||||||
@@ -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)."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user