c5eeec471f262c756916e17ef4227c4b513a052d
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0f5ef0be63 |
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> |
||
|
|
e99f1169f7 |
rename(547): what people read says Grimoire
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / integration (push) Successful in 1m1s
CI & Build / Python tests (push) Successful in 1m55s
CI & Build / Build & push image (push) Successful in 36s
Step 1 of the Scribe -> Grimoire rename: every capitalised "Scribe" in prose
becomes "Grimoire" ("Fabled Scribe" -> "Fabled Grimoire") across the UI,
the PWA manifest and page title, the MCP instructions and tool docstrings,
hook and skill text, docs and README, with the tests that assert on that
prose moving with it. Old migrations keep their wording.
Identifiers are untouched here: the package, plugin name, MCP server key,
hook file names, env vars, the .scribe marker and FabledScribe repo/image
names move in steps 2 and 3, along with prose that quotes them.
The sweep matched "Scribe" only as a whole word, so describe/subscribe and
friends are untouched. The longer name took the MCP instructions one
character over their 1,600 budget; two phrases are shortened to fit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|
|
d41e72d26c |
docs(6209): twelve more test files say which behaviour they pin
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 14s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / integration (push) Successful in 1m12s
CI & Build / Python tests (push) Successful in 1m53s
CI & Build / Build & push image (push) Successful in 12s
shape ledger, MCP projects/search/rulebooks tools, backup, chunking, plugin context, derived mirror, rule band, shape form gate, plugin version mint and note usage tests drop issue, milestone and rule numbers, dates and one-install figures from docstrings, comments and messages. Three shape-form-gate test names that told the discovery story now name the property: a registry module's helpers are not service functions, the divergence gate silences only a family contradiction, and callable helpers beside a callable canon still prompt. The rulebook tool-count comment that logged each milestone's additions is replaced by the reason it is a count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
66e21a6c60 |
refactor(notes): a snippet's and lesson's stored title is its name; the trigger joins it only in the embedded document (milestone 427)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 14s
CI & Build / integration (push) Successful in 52s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / Python tests (push) Successful in 1m35s
CI & Build / Build & push image (push) Successful in 32s
The title was `subject — trigger` because the stored title WAS the embedded one, and the join is what makes these kinds rank on the situation they apply to (#2485). Every surface that shows a title then showed the trigger too -- menus, lists and search rows ran to kilobytes. - embeddings.document_title(title, note_type, data, body) joins the trigger from `data` (body fallback) at embed time. Idempotent: an un-migrated composed title comes out the same, never doubled. The embed path, the startup backfill and the dedup gate's semantic signal all use it, so the embedded text -- and every vector -- is unchanged. - Writers store the subject: snippet create/update (service, REST, MCP) and lesson_document. Both compose_title helpers are removed. - Readers: dedup takes `data`; the menus strip the embedded title from a passage; list rows project `when_to_use`, which SnippetListView reads. - 0108 rewrites existing rows on an exact `' — ' || <own trigger>` suffix with raw SQL, leaving updated_at alone so the backfill does not re-embed the corpus for identical vectors. Downgrade recomposes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1252d0e305 |
fix(lessons): a derived mirror survives the generic note door, by kind not by name (#3734)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / integration (push) Successful in 49s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / Python tests (push) Successful in 1m31s
CI & Build / Build & push image (push) Successful in 23s
Groundwork for step 7, and a data-integrity fix in its own right. Two kinds keep a queryable mirror in `notes.data` derived from their body: snippets and, since milestone 385, lessons. Every read prefers the mirror — deliberately, because parsing markdown to answer what an index can answer is how a hot path rots. So a write that moves the body must move the mirror. #3128 found that hole for snippets and plugged it with a hard-coded `if note.note_type == SNIPPET_NOTE_TYPE`. The plug was correct and did not generalise: lessons arrived with the same design and none of the protection, which is precisely the "don't add a fourth instance" defect #3734 was told to avoid. The cost is higher for a lesson. A stale snippet mirror reports the wrong path. A stale lesson mirror reports the wrong TRIGGER, and the trigger is the whole retrieval story — the lesson goes on firing for the situation it used to name while displaying the one it now names. Silent, and confident. So `update_note` now dispatches through `_mirror_recomposers()`, a note_type -> recomposer table. A kind with a derived mirror is covered by registering it, not by someone remembering to widen an if. `lessons.recompose_data` is the lesson's entry. It recovers the subject with `embeddings.untrigger_title` — new, and deliberately placed beside the join it inverts rather than in the caller that wanted it, because a separator spelled in two files is a separator that will one day be changed in one of them (#3207). `TRIGGER_SEP` is now the one spelling, and `parse_snippet_fields` uses it too; it had the third copy inline. The two inverses stay distinct on purpose: a snippet partitions at the first separator (its name is a symbol), a lesson strips an exact known suffix (its subject may legitimately contain a dash). Different algorithms, one constant, so they cannot disagree about where the seam is. Provenance is DROPPED when the body drops it, which is the opposite call from a snippet's `verification` — that is carried because it was never in the body to delete. The body is the authority; carrying a value the reader just removed is the failure the recompose exists to prevent. Tests: test_snippet_mirror_generic_door.py becomes test_derived_mirror_generic_door.py, since the concern is now plural. The registry property is asserted directly (every kind with a mirror is in the table; the dispatch names no kind inline), plus the lesson cases and the join/inverse round-trip. `fake_lesson` moves to tests/helpers.py — it existed in test_lesson_surfacing.py and a second copy was about to be written — and gains the explicit `None`s `fake_snippet` carries, because update_note reads `verify_with` and a MagicMock is truthy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01821k5B3Ysecp9fNYs92Kuy |