Merge pull request 'feat(plugin): Scribe replaces native memory by instruction; tighten project-scope discipline' (#70) from dev into main
This commit was merged in pull request #70.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "scribe",
|
"name": "scribe",
|
||||||
"description": "Scribe second brain for Claude Code: MCP tools over your notes/tasks/projects/rules, a session-start push channel that surfaces your always-on rules + active-project context, and a set of universal process-skills (brainstorm, debug, TDD, plan, verify). Replaces superpowers + file-memory with one app-backed plugin.",
|
"description": "Scribe second brain for Claude Code: MCP tools over your notes/tasks/projects/rules, a session-start push channel that surfaces your always-on rules + active-project context, and a set of universal process-skills (brainstorm, debug, TDD, plan, verify). Replaces superpowers + file-memory with one app-backed plugin.",
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"author": { "name": "Bryan Van Deusen" },
|
"author": { "name": "Bryan Van Deusen" },
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"scribe": {
|
"scribe": {
|
||||||
|
|||||||
@@ -24,6 +24,29 @@ that as a bonus, not a precondition: it can be absent (e.g. when the instance is
|
|||||||
unreachable, or the token didn't reach the hook), so the reliable path is this
|
unreachable, or the token didn't reach the hook), so the reliable path is this
|
||||||
explicit pull. Rules loaded this way are **binding** for the session.
|
explicit pull. Rules loaded this way are **binding** for the session.
|
||||||
|
|
||||||
|
## Scribe holds these functions — don't keep a second copy
|
||||||
|
|
||||||
|
This plugin makes Scribe the home for the operator's **rules, recall, and
|
||||||
|
planning** — the jobs Claude's native auto-memory would otherwise do. When the
|
||||||
|
plugin is present, route those jobs to Scribe and **do not also write them to
|
||||||
|
native memory**: codify rules with `create_rule` / `create_project_rule`,
|
||||||
|
capture durable knowledge as Scribe notes, and keep plans in `kind=plan` tasks —
|
||||||
|
not in `MEMORY.md` or `CLAUDE.md`. One copy, in Scribe; let any existing local
|
||||||
|
memory shrink as Scribe takes over. Don't maintain both stores in parallel.
|
||||||
|
|
||||||
|
Two constraints on *how* that's achieved:
|
||||||
|
|
||||||
|
- **Steer behavior; never flip a native switch.** The plugin must work with
|
||||||
|
native auto-memory at its default (ON). Never tell the operator to set
|
||||||
|
`autoMemoryEnabled:false` or otherwise disable a built-in function to make
|
||||||
|
Scribe "win" — a setting the operator may not know was changed (and wouldn't
|
||||||
|
know to restore) is exactly the hidden breakage to avoid. You replace memory's
|
||||||
|
functions by *doing the work in Scribe*, not by turning memory off.
|
||||||
|
- **A Scribe-shaped hole is acceptable.** If the plugin is later removed, the
|
||||||
|
operator recovers context over time — that's fine. You do **not** need to keep
|
||||||
|
native memory as a self-sufficient fallback. The only thing to avoid is
|
||||||
|
breakage caused by a settings change the operator didn't make knowingly.
|
||||||
|
|
||||||
## The reflex
|
## The reflex
|
||||||
|
|
||||||
1. **Recall before acting.** Before answering a question about the operator's
|
1. **Recall before acting.** Before answering a question about the operator's
|
||||||
@@ -48,6 +71,20 @@ explicit pull. Rules loaded this way are **binding** for the session.
|
|||||||
5. **Keep state honest.** Set a task `in_progress` when you start it, `done` the
|
5. **Keep state honest.** Set a task `in_progress` when you start it, `done` the
|
||||||
moment it's complete; log progress as you go.
|
moment it's complete; log progress as you go.
|
||||||
|
|
||||||
|
## Stay inside the active project's scope
|
||||||
|
|
||||||
|
Once a project is in scope — you called `enter_project`, or the working repo is
|
||||||
|
bound — confine the session to it:
|
||||||
|
|
||||||
|
- **Pass that `project_id` to every read** (`search`, `list_tasks`,
|
||||||
|
`list_notes`). An unscoped read bleeds every other project's work into your
|
||||||
|
context.
|
||||||
|
- **Only reference or offer work on the in-scope project.** Don't surface,
|
||||||
|
suggest, or start work on other projects unless the operator explicitly widens
|
||||||
|
scope.
|
||||||
|
- If something clearly belongs to a *different* project, say so and **ask before
|
||||||
|
switching** — never silently operate cross-project.
|
||||||
|
|
||||||
## Where a new rule goes
|
## Where a new rule goes
|
||||||
|
|
||||||
When codifying a rule, pick its home by **who it should bind** — and keep
|
When codifying a rule, pick its home by **who it should bind** — and keep
|
||||||
|
|||||||
+22
-15
@@ -48,12 +48,18 @@ not something you wait to be asked for:
|
|||||||
before you re-derive it or open a duplicate.
|
before you re-derive it or open a duplicate.
|
||||||
- Before creating a task, search for an existing one (search content_type=
|
- Before creating a task, search for an existing one (search content_type=
|
||||||
'task') — don't open a second ticket for work already tracked.
|
'task') — don't open a second ticket for work already tracked.
|
||||||
- Scope reads to the project in scope. When a project is active (you called
|
- Scope to the project in scope. When a project is active (you called
|
||||||
enter_project), pass its project_id to search / list_tasks / list_notes so
|
enter_project), pass its project_id to search / list_tasks / list_notes so
|
||||||
results stay inside that project. Querying with no project_id pulls in every
|
results stay inside that project. Querying with no project_id pulls in every
|
||||||
project and bleeds unrelated work into the session — only do it for a
|
project and bleeds unrelated work into the session — only do it for a
|
||||||
deliberate cross-project sweep. The active project does not stick on the
|
deliberate cross-project sweep. get_recent takes no project filter and spans
|
||||||
server (each call is self-contained); carrying its id forward is on you.
|
every project; when one is active, prefer the scoped list_* tools over it.
|
||||||
|
And this is not only about reads: once a project is in scope, only reference
|
||||||
|
or offer work on THAT project — don't surface or propose work from other
|
||||||
|
projects unless the operator widens scope. If something clearly belongs to a
|
||||||
|
different project, say so and ask before switching; never silently operate
|
||||||
|
cross-project. The active project does not stick on the server (each call is
|
||||||
|
self-contained); carrying its id forward is on you.
|
||||||
|
|
||||||
Keep task state honest — this is what makes the project a trustworthy record:
|
Keep task state honest — this is what makes the project a trustworthy record:
|
||||||
- When you begin working a task, set it to in_progress (update_task
|
- When you begin working a task, set it to in_progress (update_task
|
||||||
@@ -101,18 +107,19 @@ of thumb: names a specific project's files/paths/quirks -> project rule; a
|
|||||||
standard a CATEGORY of projects shares -> subscribed rulebook; a universal
|
standard a CATEGORY of projects shares -> subscribed rulebook; a universal
|
||||||
norm -> always-on rulebook. Coordinate with the operator on which home fits.
|
norm -> always-on rulebook. Coordinate with the operator on which home fits.
|
||||||
|
|
||||||
That boundary cuts the other way too. Because rules are pull-only, a fresh
|
One thing NOT to do: don't bridge Scribe into a session by writing to the
|
||||||
session won't reach for them unless its always-loaded context says to. So
|
host's native memory. Rules are pull-only, so a fresh session won't reach for
|
||||||
when the current project subscribes to a rulebook (enter_project /
|
them unless its always-loaded context says to — but the bridge for that is the
|
||||||
get_project reports subscribed_rulebooks), make sure the host's persistent
|
Scribe plugin's SessionStart hook, which pushes the always-on rules +
|
||||||
memory — the CLAUDE.md / AGENTS.md / ~/.claude memory the client loads at
|
active-project context into each session directly. So do NOT create or refresh
|
||||||
startup — carries a short pointer: that the engineering and workflow rules
|
a "rules live in Scribe" pointer in CLAUDE.md / AGENTS.md / ~/.claude memory,
|
||||||
for this work live in Scribe and must be loaded via list_always_on_rules (or
|
and do NOT keep rules, recall, or plans in those stores in parallel with Scribe
|
||||||
enter_project when a project is in scope), plus a one-line note of what the
|
— Scribe holds the single copy. Native auto-memory stays for facts about the
|
||||||
current project is and what is in flight. Add or refresh that pointer when
|
user; CLAUDE.md for codebase onboarding. Never make Scribe's correctness depend
|
||||||
it's missing or stale; never copy the rules' content into memory — the
|
on the operator disabling a native function (e.g. autoMemoryEnabled): the
|
||||||
pointer plus project context is the whole job. This is what lets the next
|
plugin must work with auto-memory at its default. If the plugin is ever removed
|
||||||
session reach for Scribe instead of trusting a stale local copy.
|
the session loses this push and rebuilds context over time — an acceptable cost,
|
||||||
|
and far better than a silent settings change the operator may not know about.
|
||||||
|
|
||||||
When you are working on a specific project, call enter_project(project_id)
|
When you are working on a specific project, call enter_project(project_id)
|
||||||
ONCE at session start (or whenever the active project changes). It returns the
|
ONCE at session start (or whenever the active project changes). It returns the
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ async def get_recent(days: int = 7, limit: int = 25) -> dict:
|
|||||||
Returns:
|
Returns:
|
||||||
{"items": [{"id", "type", "title", "updated_at"}], "total": int}
|
{"items": [{"id", "type", "title", "updated_at"}], "total": int}
|
||||||
Sorted by updated_at descending.
|
Sorted by updated_at descending.
|
||||||
|
|
||||||
|
Scope note: this spans ALL projects and takes no project filter. When a
|
||||||
|
project is in scope, prefer list_tasks(project_id=...) /
|
||||||
|
list_notes(project_id=...) so you don't surface other projects' activity.
|
||||||
"""
|
"""
|
||||||
uid = current_user_id()
|
uid = current_user_id()
|
||||||
days = max(1, min(days, 90))
|
days = max(1, min(days, 90))
|
||||||
|
|||||||
Reference in New Issue
Block a user