rename(547): the server is grimoire — package, image, DB defaults, backups
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 56s
CI & Build / integration (push) Successful in 1m4s
CI & Build / Python tests (push) Successful in 1m55s
CI & Build / Build & push image (push) Successful in 44s

Step 2 of the Scribe -> Grimoire rename.

- src/scribe -> src/grimoire, and every import, patch target, module path,
  hypercorn entry point and `python -m grimoire.restore` with it; pyproject,
  uv.lock and the frontend package are named grimoire.
- Image git.fabledsword.com/bvandeusen/fabledgrimoire; CI's Postgres service
  runs as grimoire / grimoire_test.
- Compose files default the DB user, database and (prod) volume to grimoire,
  each overridable from .env, so an install created as Scribe keeps its data
  by setting POSTGRES_USER, POSTGRES_DB and PGDATA_VOLUME.
- Backups are written as grimoire-<ts>.tar with format grimoire-backup-tar.
  Archives named scribe-* with the scribe-backup-tar manifest still restore
  and are still counted at the destination (folder and S3), with tests.
- Exports, the MCP auth realm, the ASGI scope key and the persistent logger
  carry the new name.

Kept on purpose: the secret-sealing key label stays "scribe.secrets.v1",
because every stored secret was derived under it.

Plugin identity (plugin name, hooks, env vars, .scribe marker, skills) is
step 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-22 10:50:45 -04:00
co-authored by Claude Opus 5.5
parent e99f1169f7
commit 0f5ef0be63
447 changed files with 3611 additions and 3558 deletions
+14 -14
View File
@@ -4,19 +4,19 @@ import inspect
def test_snippets_blueprint_registered():
from scribe.routes.snippets import snippets_bp
from grimoire.routes.snippets import snippets_bp
assert snippets_bp.name == "snippets"
assert snippets_bp.url_prefix == "/api/snippets"
def test_snippets_blueprint_registered_in_app():
from scribe.app import create_app
from grimoire.app import create_app
app = create_app()
assert "snippets" in app.blueprints
def test_snippet_handlers_callable():
from scribe.routes import snippets as routes
from grimoire.routes import snippets as routes
for name in (
"list_snippets_route", "create_snippet_route", "get_snippet_route",
"update_snippet_route", "delete_snippet_route", "merge_snippet_route",
@@ -28,7 +28,7 @@ def test_snippet_handlers_callable():
def test_service_functions_take_user_id():
"""Routes must call snippet services with user_id — verify the contract."""
from scribe.services import snippets as svc
from grimoire.services import snippets as svc
for fn_name in (
"create_snippet", "list_snippets", "get_snippet", "update_snippet",
"delete_snippet", "merge_snippets", "record_verification",
@@ -43,8 +43,8 @@ def test_agent_and_web_surfaces_stay_at_parity():
"""The MCP tools and the REST routes are two callers of one service; a
capability on one has to exist on the other. Two doors maintained
separately drift — a delete on one, a near-duplicate gate on the other."""
from scribe.mcp.tools import snippets as tools
from scribe.routes import snippets as routes
from grimoire.mcp.tools import snippets as tools
from grimoire.routes import snippets as routes
# Every write verb the web surface offers, the agent surface offers too.
for verb in ("create", "get", "list", "update", "delete", "merge", "verify",
@@ -78,9 +78,9 @@ def test_agent_and_web_surfaces_stay_at_parity():
def test_project_scoping_reaches_every_caller():
"""A snippet search has to be narrowable to one project from both surfaces."""
from scribe.mcp.tools import snippets as tools
from scribe.routes import snippets as routes
from scribe.services import snippets as svc
from grimoire.mcp.tools import snippets as tools
from grimoire.routes import snippets as routes
from grimoire.services import snippets as svc
assert "project_id" in inspect.signature(svc.list_snippets).parameters
assert "project_id" in inspect.signature(tools.list_snippets).parameters
assert "project_id" in inspect.getsource(routes.list_snippets_route)
@@ -90,9 +90,9 @@ def test_location_lookup_reaches_every_caller():
"""The reverse lookup — "what already lives here?" — has to be askable from
both surfaces, or an agent and a human get different answers about the same
file."""
from scribe.mcp.tools import snippets as tools
from scribe.routes import snippets as routes
from scribe.services import snippets as svc
from grimoire.mcp.tools import snippets as tools
from grimoire.routes import snippets as routes
from grimoire.services import snippets as svc
for key in ("repo", "path", "symbol"):
assert key in inspect.signature(svc.list_snippets).parameters
assert key in inspect.signature(tools.list_snippets).parameters
@@ -102,8 +102,8 @@ def test_location_lookup_reaches_every_caller():
def test_update_field_map_matches_service_kwargs():
"""Every field the PATCH route forwards must be a real update_snippet kwarg
(interface-contract parity)."""
from scribe.routes import snippets as routes
from scribe.services import snippets as svc
from grimoire.routes import snippets as routes
from grimoire.services import snippets as svc
params = inspect.signature(svc.update_snippet).parameters
for field in routes._STR_FIELDS:
assert field in params, f"update_snippet has no '{field}' kwarg"