docs(6204): shipped instruction text describes the product, not this instance's records
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 15s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 1m10s
CI & Build / Python tests (push) Successful in 1m55s
CI & Build / Build & push image (push) Successful in 39s

MCP tool docstrings and comments, the server's orientation notes, the plugin
skills, every hook script and the plugin README/PACKAGING drop record ids,
milestone numbers, dates and incident stories, and state each non-obvious why
as a present-tense fact. History stays in the task logs.

Corrections found on the way:
- plugin README/PACKAGING said every hook is a GET; moment, rule-opened and
  reply-rules POST, so the plugin's key needs write scope. Both now say so,
  name Settings -> MCP Access, and list every wired hook and endpoint.
- the contract-change hint printed "(lesson #4207)", this instance's record,
  to every install. It no longer cites a record.
- tasks.py claimed there is no delete_task; there is.
- rulebooks.py cited delete_event and a design spec that no longer exist.
- scribe_after_write.sh carried an always-empty etag_q; removed.
- test_write_path_trigger pinned "| tac | scribe_defs | head -1", text that
  existed only in a comment about the old code; it now pins the real tail -1
  pipeline.
- docs/development.md: CI runs on Gitea Actions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 19:45:09 -04:00
co-authored by Claude Opus 5.5
parent fc8f554cee
commit 17777e9bb1
43 changed files with 641 additions and 777 deletions
+34 -11
View File
@@ -17,7 +17,8 @@ instance into a first-class Claude Code extension:
any client's package would ship: using-scribe, writing-plans, reporting-back
(reply to the operator in a shape that says where the work stands),
systematic-debugging, verification, brainstorming, reusing-code (record and
recall reusable code as snippets). Replaces superpowers.
recall reusable code as snippets), shape-accounting and family-canon.
Replaces superpowers.
- **Your Scribe Processes as skills** — saved Processes are synced into local
`~/.claude/skills/scribe-proc-*` stubs that auto-surface by relevance; the
stub fetches the live procedure via `get_process`. Refreshed each session and
@@ -27,7 +28,7 @@ It is designed so you can uninstall `superpowers` and depend on Scribe instead
of auto-memory — leave auto-memory at its default; Scribe replaces its job by
holding the one copy, not by switching it off.
**How the pieces divide the work** (decision #4027): the Scribe server orients
**How the pieces divide the work**: the Scribe server orients
every MCP client and serves live state; the skills in `skills/` state every
reflex in full and name no client; this plugin is the Claude Code adapter —
hooks that deliver at the right moment, `/scribe:sync`, and the few things only
@@ -49,7 +50,7 @@ On install you'll be asked for:
| Setting | What |
|---|---|
| **Scribe base URL** | e.g. `https://scribe.example.com` (no trailing slash) |
| **Scribe API key** | an `fmcp_` key from **Settings → API Keys** (stored in your OS keychain) |
| **Scribe API key** | a write-scoped `fmcp_` key from **Settings → MCP Access** (stored in your OS keychain) |
| **Active project id** | optional — numeric project id to scope the session-start context |
## What gets wired
@@ -71,7 +72,23 @@ On install you'll be asked for:
in time is said, once per outage ("Scribe did not answer … this write went
UNCHECKED"), so a session can tell "checked, nothing there" from "never
checked"; an answer clears the marker. The local by-name arm needs no
server and always runs. Toggle in **Settings → Knowledge auto-inject**.
server and always runs. Toggle in **Settings → General → Knowledge
auto-inject**.
- `hooks/hooks.json` → UserPromptSubmit hook (`hooks/scribe_autoinject.sh`) →
`GET /api/plugin/retrieve`: the rules, preferences and records that match the
message, as a short menu of titles and matched passages.
- `hooks/hooks.json` → PreToolUse hook on `Bash` (`hooks/scribe_tool_rules.sh`)
→ `GET /api/plugin/tool-rules`: the rules that match the command about to run.
- `hooks/hooks.json` → PreToolUse hook on every tool (`hooks/scribe_moment.sh`)
→ `POST /api/plugin/moment`: the rules mounted on the moments the call
reaches. It skips tools that `GET /api/plugin/moment-tools` says reach
nothing mounted, and Scribe's own tools, whose responses carry
`moment_rules`.
- `hooks/hooks.json` → PostToolUse hooks on Scribe's `get_rule`,
`rule_outcome`, `update_task` and `add_task_log`: they keep the session's
ledgers of rules opened and acted on (`get_rule` also reports to
`POST /api/plugin/rule-opened`), and claim the task being worked
(`GET /api/plugin/claim-session`) so it comes back after a compaction.
- `hooks/hooks.json` → PostToolUse hook on `Bash`
(`hooks/scribe_after_write.sh`): code written through sed/heredocs/scripts
never reaches the PreToolUse hook, so this one diffs the working tree after
@@ -106,16 +123,22 @@ On install you'll be asked for:
command → generate `~/.claude/skills/scribe-proc-*` stubs from your Scribe
Processes (via `GET /api/plugin/processes`); also **fail-open**, and pruned to
match what exists in Scribe.
- `hooks/hooks.json` → PreCompact hook (`hooks/scribe_precompact_preserve.sh`):
tells the summarizer which parts of the conversation to keep literally. Local
only, and it never blocks, because a blocked compaction is skipped outright.
- `hooks/hooks.json` → SessionEnd hook (`hooks/scribe_session_end.sh`) →
`GET /api/plugin/release-session`: releases the session's task claims.
## Notes
- **Do not hand-edit `version` in `.claude-plugin/plugin.json`.** It is minted
from the clock — run `python3 scripts/mint_plugin_version.py` (or `make
mint-plugin`, where `make` is installed) after changing anything under
`plugin/`, and commit the result. The installer decides whether to refresh the cache it
executes from by comparing that string, so content that ships without a new
version reaches the repo and stops there (#2209). CI fails the lane if you
forget.
- The session-start, auto-inject and prior-art hooks need only a **read**-scoped
key; the MCP tools need **write** scope to create/update. Every hook is a GET
for that reason — a read key cannot POST.
`plugin/`, and commit the result. The installer decides whether to refresh
the cache it executes from by comparing that string, so content that ships
without a new version reaches the repo and stops there. CI fails the lane if
you forget.
- The plugin uses one key for its MCP tools and its hooks, so give it **write**
scope: the MCP tools create and update records, and the moment, rule-opened
and reply hooks POST. A read-scoped key runs the GET hooks only; the others
fail open and add nothing.