rename(547): the repo is FabledGrimoire, and no stray "scribe" is left
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 1m1s
CI & Build / Python tests (push) Successful in 2m2s
CI & Build / Build & push image (push) Successful in 28s
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 1m1s
CI & Build / Python tests (push) Successful in 2m2s
CI & Build / Build & push image (push) Successful in 28s
The forge repo is now bvandeusen/FabledGrimoire. The plugin marketplace default, the install commands in the docs and plugin README, the CI requirements title and the example repo URLs in comments and tests follow it. docs/development.md now names the image the build actually publishes, fabledgrimoire. Two test names still said "scribes_own"; they now say "grimoires_own". What still says scribe does so on purpose: - the backup reader's accepted archive names and prefix; - the label every stored secret is sealed under; - the notes on keeping an old install's database names; - the old migrations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
# CI Requirements — FabledScribe
|
# CI Requirements — FabledGrimoire
|
||||||
|
|
||||||
> Spec lives in [`docs/process.md`](https://git.fabledsword.com/bvandeusen/CI-runner/src/branch/main/docs/process.md)
|
> Spec lives in [`docs/process.md`](https://git.fabledsword.com/bvandeusen/CI-runner/src/branch/main/docs/process.md)
|
||||||
> in the CI-Runner repo.
|
> in the CI-Runner repo.
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ without a read-shaped name are spelled out here. A `write`-scoped key may call e
|
|||||||
The plugin connects the MCP server and adds the hooks and skills that put Grimoire's records in front of Claude as it works. Install it from this repo:
|
The plugin connects the MCP server and adds the hooks and skills that put Grimoire's records in front of Claude as it works. Install it from this repo:
|
||||||
|
|
||||||
```
|
```
|
||||||
/plugin marketplace add https://git.fabledsword.com/bvandeusen/FabledScribe.git
|
/plugin marketplace add https://git.fabledsword.com/bvandeusen/FabledGrimoire.git
|
||||||
/plugin install grimoire@grimoire-plugin
|
/plugin install grimoire@grimoire-plugin
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ CI runs on Gitea Actions (workflow in `.forgejo/workflows/ci.yml`) in the shared
|
|||||||
| `main` | `:latest`, `:<sha>` |
|
| `main` | `:latest`, `:<sha>` |
|
||||||
| a `v*` tag | `:latest`, `:<version>`, `:<sha>` |
|
| a `v*` tag | `:latest`, `:<version>`, `:<sha>` |
|
||||||
|
|
||||||
`:<sha>` never moves, so it is the rollback point. Images publish to `git.fabledsword.com/bvandeusen/fabledscribe`, with a registry layer cache at `:cache`. The build needs the `REGISTRY_USER` and `REGISTRY_TOKEN` (a token with `write:packages`) repository secrets.
|
`:<sha>` never moves, so it is the rollback point. Images publish to `git.fabledsword.com/bvandeusen/fabledgrimoire`, with a registry layer cache at `:cache`. The build needs the `REGISTRY_USER` and `REGISTRY_TOKEN` (a token with `write:packages`) repository secrets.
|
||||||
|
|
||||||
Work happens on `dev`. A release merges `dev` into `main` with a plain merge commit; a dated `vYYYY.MM.DD.HHMM` tag, matching the version the image reports, can mark it.
|
Work happens on `dev`. A release merges `dev` into `main` with a plain merge commit; a dated `vYYYY.MM.DD.HHMM` tag, matching the version the image reports, can mark it.
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
# Grimoire plugin for Claude Code
|
# Grimoire plugin for Claude Code
|
||||||
|
|
||||||
Turns a self-hosted [Grimoire](https://git.fabledsword.com/bvandeusen/FabledScribe)
|
Turns a self-hosted [Grimoire](https://git.fabledsword.com/bvandeusen/FabledGrimoire)
|
||||||
instance into a first-class Claude Code extension:
|
instance into a first-class Claude Code extension:
|
||||||
|
|
||||||
- **MCP tools** over your notes, tasks, projects, milestones, systems, and
|
- **MCP tools** over your notes, tasks, projects, milestones, systems, and
|
||||||
@@ -41,7 +41,7 @@ The plugin ships inside the Grimoire app repo, so the marketplace *is* that repo
|
|||||||
you always get the plugin version that matches your Grimoire instance.
|
you always get the plugin version that matches your Grimoire instance.
|
||||||
|
|
||||||
```
|
```
|
||||||
/plugin marketplace add https://git.fabledsword.com/bvandeusen/FabledScribe.git
|
/plugin marketplace add https://git.fabledsword.com/bvandeusen/FabledGrimoire.git
|
||||||
/plugin install grimoire@grimoire-plugin
|
/plugin install grimoire@grimoire-plugin
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1308,7 +1308,7 @@ grimoire_turn_fact() {
|
|||||||
# Nothing Grimoire should be holding goes in it.
|
# Nothing Grimoire should be holding goes in it.
|
||||||
#
|
#
|
||||||
# {"instance": "https://grimoire.example.com", "project_id": 2,
|
# {"instance": "https://grimoire.example.com", "project_id": 2,
|
||||||
# "project": "FabledScribe"}
|
# "project": "FabledGrimoire"}
|
||||||
#
|
#
|
||||||
# instance WHICH Grimoire the id belongs to, and the reason this file is
|
# instance WHICH Grimoire the id belongs to, and the reason this file is
|
||||||
# not just a number. A project id means nothing on its own: id 2
|
# not just a number. A project id means nothing on its own: id 2
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# requires-python = ">=3.10"
|
# requires-python = ">=3.10"
|
||||||
# dependencies = ["httpx>=0.27"]
|
# dependencies = ["httpx>=0.27"]
|
||||||
# ///
|
# ///
|
||||||
"""Benchmark Ollama models for FabledScribe chat / curator workloads.
|
"""Benchmark Ollama models for FabledGrimoire chat / curator workloads.
|
||||||
|
|
||||||
Measures time-to-first-token, total wall time, and tokens/sec for each
|
Measures time-to-first-token, total wall time, and tokens/sec for each
|
||||||
(model, scenario) pair. Designed to be runnable against both local and
|
(model, scenario) pair. Designed to be runnable against both local and
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class Config:
|
|||||||
# per-instance via the Plugin marketplace setting.
|
# per-instance via the Plugin marketplace setting.
|
||||||
PLUGIN_MARKETPLACE_URL: str = os.environ.get(
|
PLUGIN_MARKETPLACE_URL: str = os.environ.get(
|
||||||
"PLUGIN_MARKETPLACE_URL",
|
"PLUGIN_MARKETPLACE_URL",
|
||||||
"https://git.fabledsword.com/bvandeusen/FabledScribe.git",
|
"https://git.fabledsword.com/bvandeusen/FabledGrimoire.git",
|
||||||
)
|
)
|
||||||
|
|
||||||
# OIDC / OAuth2 SSO (e.g. Authentik)
|
# OIDC / OAuth2 SSO (e.g. Authentik)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class RepoBinding(Base, TimestampMixin):
|
|||||||
"""Maps a git repository to the Grimoire project it represents.
|
"""Maps a git repository to the Grimoire project it represents.
|
||||||
|
|
||||||
The SessionStart hook sends the working repo's normalized remote
|
The SessionStart hook sends the working repo's normalized remote
|
||||||
(`repo_key`, e.g. ``git.fabledsword.com/bvandeusen/fabledscribe``) and the
|
(`repo_key`, e.g. ``git.fabledsword.com/bvandeusen/fabledgrimoire``) and the
|
||||||
server resolves it to a project — so the operator can work across many
|
server resolves it to a project — so the operator can work across many
|
||||||
repos/projects without pinning a project id in plugin config. The key is a
|
repos/projects without pinning a project id in plugin config. The key is a
|
||||||
*stable identifier* (the git remote), not a dir-name heuristic.
|
*stable identifier* (the git remote), not a dir-name heuristic.
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ def location_matches(data: dict | None, parts: dict[str, str]) -> bool:
|
|||||||
if all(
|
if all(
|
||||||
_path_matches((loc.get(key) or "").strip(), want)
|
_path_matches((loc.get(key) or "").strip(), want)
|
||||||
if key == "path"
|
if key == "path"
|
||||||
# Repo names are recorded free-form ("Grimoire" / "FabledScribe" /
|
# Repo names are recorded free-form ("Grimoire" / "FabledGrimoire" /
|
||||||
# "fabledscribe") — case is never the distinguishing thing.
|
# "fabledgrimoire") — case is never the distinguishing thing.
|
||||||
else (loc.get(key) or "").strip().lower() == want.lower()
|
else (loc.get(key) or "").strip().lower() == want.lower()
|
||||||
if key == "repo"
|
if key == "repo"
|
||||||
else (loc.get(key) or "").strip() == want
|
else (loc.get(key) or "").strip() == want
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ def normalize_repo_key(raw: str) -> str:
|
|||||||
|
|
||||||
Collapses the equivalent clone URLs to one key, e.g.::
|
Collapses the equivalent clone URLs to one key, e.g.::
|
||||||
|
|
||||||
git@git.fabledsword.com:bvandeusen/FabledScribe.git
|
git@git.fabledsword.com:bvandeusen/FabledGrimoire.git
|
||||||
https://git.fabledsword.com/bvandeusen/fabledscribe.git
|
https://git.fabledsword.com/bvandeusen/fabledgrimoire.git
|
||||||
ssh://git@git.fabledsword.com:22/bvandeusen/fabledscribe
|
ssh://git@git.fabledsword.com:22/bvandeusen/fabledgrimoire
|
||||||
|
|
||||||
all normalize to ``git.fabledsword.com/bvandeusen/fabledscribe``.
|
all normalize to ``git.fabledsword.com/bvandeusen/fabledgrimoire``.
|
||||||
|
|
||||||
Returns "" for empty/garbage input so callers can treat it as "no repo".
|
Returns "" for empty/garbage input so callers can treat it as "no repo".
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ def test_a_bare_integer_is_a_valid_marker(tmp_path):
|
|||||||
|
|
||||||
|
|
||||||
def test_the_marker_is_found_from_a_subdirectory(tmp_path):
|
def test_the_marker_is_found_from_a_subdirectory(tmp_path):
|
||||||
_marker(tmp_path, instance=INSTANCE, project_id=2, project="FabledScribe")
|
_marker(tmp_path, instance=INSTANCE, project_id=2, project="FabledGrimoire")
|
||||||
deep = tmp_path / "src" / "grimoire" / "services"
|
deep = tmp_path / "src" / "grimoire" / "services"
|
||||||
deep.mkdir(parents=True)
|
deep.mkdir(parents=True)
|
||||||
assert _sh(f'grimoire_scope_query "{deep}"', tmp_path) == "project_id=2"
|
assert _sh(f'grimoire_scope_query "{deep}"', tmp_path) == "project_id=2"
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ def test_the_hook_and_the_routes_agree_on_every_name():
|
|||||||
assert name in route
|
assert name in route
|
||||||
|
|
||||||
|
|
||||||
def test_the_hook_leaves_scribes_own_tools_to_their_responses():
|
def test_the_hook_leaves_grimoires_own_tools_to_their_responses():
|
||||||
assert "mcp__*grimoire*__*) exit 0" in HOOK.read_text()
|
assert "mcp__*grimoire*__*) exit 0" in HOOK.read_text()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ def _acts(tmp: Path, sid: str = "s1") -> list[tuple[int, dict]]:
|
|||||||
return rows
|
return rows
|
||||||
|
|
||||||
|
|
||||||
def test_every_call_is_written_to_the_acts_ledger_scribes_own_included(sandbox):
|
def test_every_call_is_written_to_the_acts_ledger_grimoires_own_included(sandbox):
|
||||||
tmp, env = sandbox
|
tmp, env = sandbox
|
||||||
push = {"session_id": "s1", "tool_name": "Bash",
|
push = {"session_id": "s1", "tool_name": "Bash",
|
||||||
"tool_input": {"command": "git push origin dev"}}
|
"tool_input": {"command": "git push origin dev"}}
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ async def test_build_session_context_includes_project_when_scoped():
|
|||||||
# design_system_id explicitly None: a bare MagicMock would hand back a truthy
|
# design_system_id explicitly None: a bare MagicMock would hand back a truthy
|
||||||
# auto-attribute and send this through the design branch, which is the
|
# auto-attribute and send this through the design branch, which is the
|
||||||
# opposite of what this test is about.
|
# opposite of what this test is about.
|
||||||
project = MagicMock(id=2, title="FabledScribe", goal="ship it",
|
project = MagicMock(id=2, title="FabledGrimoire", goal="ship it",
|
||||||
design_system_id=None)
|
design_system_id=None)
|
||||||
with patch("grimoire.services.plugin_context.projects_svc.get_project",
|
with patch("grimoire.services.plugin_context.projects_svc.get_project",
|
||||||
AsyncMock(return_value=project)), \
|
AsyncMock(return_value=project)), \
|
||||||
@@ -120,8 +120,8 @@ async def test_build_session_context_includes_project_when_scoped():
|
|||||||
from grimoire.services.plugin_context import build_session_context
|
from grimoire.services.plugin_context import build_session_context
|
||||||
out = await build_session_context(user_id=7, project_id=2)
|
out = await build_session_context(user_id=7, project_id=2)
|
||||||
|
|
||||||
assert out["project"] == {"id": 2, "title": "FabledScribe"}
|
assert out["project"] == {"id": 2, "title": "FabledGrimoire"}
|
||||||
assert "## Active project: FabledScribe (id 2)" in out["context"]
|
assert "## Active project: FabledGrimoire (id 2)" in out["context"]
|
||||||
assert "Open todo tasks: 4" in out["context"]
|
assert "Open todo tasks: 4" in out["context"]
|
||||||
# No design system on the project -> no design block at all. An install with
|
# No design system on the project -> no design block at all. An install with
|
||||||
# none is the ordinary case, not a degraded one.
|
# none is the ordinary case, not a degraded one.
|
||||||
|
|||||||
@@ -6,18 +6,18 @@ from grimoire.services.repo_bindings import normalize_repo_key
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"raw",
|
"raw",
|
||||||
[
|
[
|
||||||
"git@git.fabledsword.com:bvandeusen/fabledscribe.git",
|
"git@git.fabledsword.com:bvandeusen/fabledgrimoire.git",
|
||||||
"git@git.fabledsword.com:bvandeusen/FabledScribe.git",
|
"git@git.fabledsword.com:bvandeusen/FabledGrimoire.git",
|
||||||
"https://git.fabledsword.com/bvandeusen/fabledscribe.git",
|
"https://git.fabledsword.com/bvandeusen/fabledgrimoire.git",
|
||||||
"https://git.fabledsword.com/bvandeusen/fabledscribe",
|
"https://git.fabledsword.com/bvandeusen/fabledgrimoire",
|
||||||
"http://git.fabledsword.com/bvandeusen/fabledscribe.git",
|
"http://git.fabledsword.com/bvandeusen/fabledgrimoire.git",
|
||||||
"ssh://git@git.fabledsword.com:22/bvandeusen/fabledscribe.git",
|
"ssh://git@git.fabledsword.com:22/bvandeusen/fabledgrimoire.git",
|
||||||
"ssh://git@git.fabledsword.com/bvandeusen/fabledscribe",
|
"ssh://git@git.fabledsword.com/bvandeusen/fabledgrimoire",
|
||||||
"https://user:token@git.fabledsword.com/bvandeusen/fabledscribe.git",
|
"https://user:token@git.fabledsword.com/bvandeusen/fabledgrimoire.git",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_normalize_collapses_equivalent_remotes(raw):
|
def test_normalize_collapses_equivalent_remotes(raw):
|
||||||
assert normalize_repo_key(raw) == "git.fabledsword.com/bvandeusen/fabledscribe"
|
assert normalize_repo_key(raw) == "git.fabledsword.com/bvandeusen/fabledgrimoire"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("raw", ["", " ", None])
|
@pytest.mark.parametrize("raw", ["", " ", None])
|
||||||
|
|||||||
Reference in New Issue
Block a user