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
+6 -6
View File
@@ -20,9 +20,9 @@ import inspect
import re
from pathlib import Path
from scribe.models.lesson_rule_link import LINK_STATES
from scribe.services import lesson_rules as links_svc
from scribe.services.access import PERMISSION_RANK
from grimoire.models.lesson_rule_link import LINK_STATES
from grimoire.services import lesson_rules as links_svc
from grimoire.services.access import PERMISSION_RANK
FRONTEND = Path(__file__).resolve().parents[1] / "frontend" / "src"
@@ -133,7 +133,7 @@ def _payload_fn(view: str) -> str:
def test_the_editor_sends_the_answer_under_the_names_both_routes_read():
"""The contract check: a field the form sends under another name is
dropped without an error, and the lesson saves unjudged."""
from scribe.routes import lessons as routes
from grimoire.routes import lessons as routes
body = _payload_fn(_read("views/LessonEditorView.vue"))
assert "rule_ids:" in body and "no_rule:" in body
@@ -157,7 +157,7 @@ def test_leaving_it_open_after_linking_clears_the_links_rather_than_nothing():
def test_the_candidates_route_is_where_the_client_asks_and_above_the_id_route():
from scribe.routes import lessons as routes
from grimoire.routes import lessons as routes
src = inspect.getsource(routes)
assert src.index('"/rule-candidates"') < src.index('"/<int:lesson_id>"')
@@ -168,7 +168,7 @@ def test_the_candidates_route_keeps_unavailable_apart_from_none():
"""The service returns None when the search could not run. The route has
to pass that through as null, not coerce it to an empty list, because
"nothing resembles it" is a claim the editor shows to the writer."""
from scribe.routes import lessons as routes
from grimoire.routes import lessons as routes
src = inspect.getsource(routes.lesson_rule_candidates_route)
assert 'jsonify({"candidates": candidates})' in src