Files
FabledSteward/docs/superpowers/plans/2026-04-13-rebrand.md
T
bvandeusen 88ab5b917e chore: rename project Roundtable → Steward
Renames the Python package directory, CLI command, env var prefix,
docker-compose service/container/image, Postgres role/db, and all
visible branding. Marketing form is "Fabled Steward".

Clean break from the previous rebrand: drops the fabledscryer→roundtable
import shim in __init__.py and the FABLEDSCRYER_* env var fallback in
config.py and migrations/env.py. Env vars are now STEWARD_* only.

Heads-up for existing deployments:
- Postgres user/db renamed fabledscryer → steward in docker-compose.yml.
  Existing volumes need the role/db renamed inside Postgres, or override
  POSTGRES_USER/POSTGRES_DB to keep the old names.
- Host-agent systemd unit is now steward-agent.service. Existing agents
  keep running under the old name; reinstall to switch.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 16:20:14 -04:00

928 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Steward Rebrand Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
>
> **Testing:** Per project feedback, skip all test authoring and test runs during this work. Verify manually by running the app.
**Goal:** Rebrand FabledScryer to Steward: full visual reskin plus full rename of package, config, containers, and docs.
**Architecture:** Staged as six sequential PRs. PR 1 is a pure visual/copy reskin that still ships under the FabledScryer name. PRs 24 perform the mechanical rename in order (package → config → container + user-visible strings) with a fallback shim in PR 3 so self-hosters don't break mid-upgrade. PR 5 updates docs. PR 6 removes the shim after one release cycle.
**Tech Stack:** Python 3.13, Quart, SQLAlchemy + Alembic (asyncpg), Jinja2 templates, Docker Compose, Postgres 16.
**Spec:** `docs/superpowers/specs/2026-04-13-rebrand-design.md`
---
## File Structure
**Modified (PR 1 — visual reskin):**
- `fabledscryer/templates/base.html` — palette tokens, logo SVG, font, background, wordmark, `<title>`
- `fabledscryer/templates/auth/login.html` — themed tagline
- `fabledscryer/templates/errors/404.html` (create if missing) — themed 404
- `fabledscryer/templates/errors/500.html` (create if missing) — themed 500
- `fabledscryer/templates/dashboard/*.html` — hero title "Under Watch, Under Care"
- Any template with an empty-state message — themed line
**Renamed (PR 2 — package):**
- `fabledscryer/``steward/` (directory + every `from fabledscryer` / `import fabledscryer` reference)
- `pyproject.toml` — name, entry point, hatch packages
- `alembic.ini``script_location`
- `tests/**` — imports (tests not executed, but must not break collection; update imports mechanically)
**Modified (PR 3 — config & env):**
- `fabledscryer/config.py``steward/config.py` (already moved in PR 2) — read both `STEWARD_*` and `FABLEDSCRYER_*` with deprecation warning
- `.env.example`, `config.example.yaml` — new names
- First-boot migration of `~/.config/fabledscryer``~/.config/steward` (if the app uses it — verify during task)
**Modified (PR 4 — container + user strings):**
- `Dockerfile` — COPY paths, CMD, image labels
- `docker-compose.yml` — service name, image, container_name, volumes, env
- `entrypoint.sh` — package path for `nut_setup.py` invocation
- `steward/templates/base.html` — wordmark text "Fabled Scryer" → "Steward", `<title>`
- `steward/templates/auth/login.html` — any residual "Fabled Scryer" text
- `README.md` — first-page references (full doc sweep is PR 5)
**Modified (PR 5 — docs):**
- `README.md`, `docs/**/*.md`
**Modified (PR 6 — cleanup):**
- `steward/config.py` — remove fallback shim
---
## PR 1 — Visual Reskin
### Task 1: Replace palette tokens in `base.html`
**Files:**
- Modify: `fabledscryer/templates/base.html:13-35`
- [ ] **Step 1: Open `fabledscryer/templates/base.html` and replace the `:root` block (lines 1335) with the Pewter & Gold palette**
```css
:root {
--bg: #131315;
--bg-card: #1d1d20;
--bg-elevated: #24242a;
--border: #30303a;
--border-mid: #3a3a44;
--text: #d4d0c0;
--text-muted: #b8b8b0;
--text-dim: #8a8a92;
--gold: #c8a840;
--gold-hover: #d8b850;
--gold-dim: #2a2410;
--pewter: #8a8a92;
--accent: var(--gold);
--accent-hover: var(--gold-hover);
--green: #4aa86a;
--green-dim: #162a1c;
--yellow: #d4a840;
--yellow-dim: #2a2410;
--orange: #c87840;
--orange-dim: #2a1a10;
--red: #c84048;
--red-dim: #2a1014;
--font-serif: 'EB Garamond', Georgia, serif;
}
```
- [ ] **Step 2: Commit**
```bash
git add fabledscryer/templates/base.html
git commit -m "style: pewter & gold palette tokens"
```
### Task 2: Swap Google Font to EB Garamond
**Files:**
- Modify: `fabledscryer/templates/base.html:9-11`
- [ ] **Step 1: Replace the font preconnect + stylesheet link (lines 911) with EB Garamond**
```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,600;0,700;1,400&display=swap" rel="stylesheet">
```
- [ ] **Step 2: Commit**
```bash
git add fabledscryer/templates/base.html
git commit -m "style: swap Libertinus Serif → EB Garamond"
```
### Task 3: Replace crystal ball logo with Heraldic Seal
**Files:**
- Modify: `fabledscryer/templates/base.html:187-214`
- [ ] **Step 1: Replace the `<svg>` block inside `nav .brand` (lines 188213) with the locked seal SVG**
```html
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<circle cx="12" cy="12" r="10.5" fill="none" stroke="#c8a840" stroke-width="1.5"/>
<circle cx="12" cy="12" r="9.3" fill="#8a8a92" opacity="0.1"/>
<path d="M7 10 L7 5.8 L9 7.8 L10.5 5 L12 7.2 L13.5 5 L15 7.8 L17 5.8 L17 10 Z" fill="#c8a840"/>
<ellipse cx="12" cy="15.5" rx="5.2" ry="1" fill="#c8a840"/>
<rect x="9.6" y="15.5" width="1" height="3.8" fill="#c8a840"/>
<rect x="13.4" y="15.5" width="1" height="3.8" fill="#c8a840"/>
</svg>
```
- [ ] **Step 2: Change the brand wordmark gradient (lines 6871) to solid gold**
Replace:
```css
background: linear-gradient(110deg, #c8b4f8 0%, var(--gold) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
```
With:
```css
color: var(--gold);
```
- [ ] **Step 3: Commit**
```bash
git add fabledscryer/templates/base.html
git commit -m "feat: heraldic seal logo (crown & ellipse table)"
```
### Task 4: Replace star field with candlelit glow
**Files:**
- Modify: `fabledscryer/templates/base.html:42-46` (CSS), `182` (markup), `266-369` (script)
- [ ] **Step 1: Replace the `#star-field` CSS rules (lines 4246) with a candlelit glow rule**
```css
#candle-glow {
position: fixed;
inset: 0;
pointer-events: none;
z-index: 0;
background:
radial-gradient(ellipse 80% 60% at 50% 40%, rgba(200, 168, 64, 0.045) 0%, transparent 70%),
radial-gradient(ellipse 50% 40% at 20% 80%, rgba(200, 168, 64, 0.025) 0%, transparent 65%);
}
```
- [ ] **Step 2: Rename the markup `<div id="star-field">` (line 182) to `<div id="candle-glow">`**
```html
<div id="candle-glow"></div>
```
- [ ] **Step 3: Delete the entire star-field IIFE script block (lines 266369)** — from `<script>` through `</script>` that contains `var field = document.getElementById('star-field');`. The glow is CSS-only; no JS needed.
- [ ] **Step 4: Commit**
```bash
git add fabledscryer/templates/base.html
git commit -m "style: candlelit glow background replaces star field"
```
### Task 5: Update `<title>` tag
**Files:**
- Modify: `fabledscryer/templates/base.html:6`
- [ ] **Step 1: Change the title block**
```html
<title>{% block title %}Steward{% endblock %}</title>
```
Note: the visible wordmark text still reads "Fabled Scryer" — that flips in PR 4. This only changes the browser tab title, which is acceptable to flip early since it's not visible inside the UI.
Actually, leave the visible `<title>` as "Fabled Scryer" in PR 1 to keep this PR purely about palette/logo/font/background. Revert this change if already applied.
- [ ] **Step 2: Revert line 6 back to `Fabled Scryer` if modified, then commit nothing for this task.** (PR 1 does not change any user-visible strings.)
### Task 6: Add themed empty-state and login tagline
**Files:**
- Modify: `fabledscryer/templates/auth/login.html`
- Modify: existing empty-state markup in list templates (identify via grep)
- [ ] **Step 1: Identify empty-state lines**
Run:
```bash
grep -rn 'class="empty"' fabledscryer/templates/
```
- [ ] **Step 2: Replace each empty-state copy with a one-line themed variant**
For each hit, replace the inner text with a single themed sentence. Examples:
- Hosts list empty → `No hosts yet. Summon one to the table.`
- Alerts list empty → `Silence in the realm. No alerts to show.`
- Plugins list empty → `No plugins installed. The table awaits new seats.`
Use judgment — one sentence per list. Keep them short.
- [ ] **Step 3: Add login tagline**
Open `fabledscryer/templates/auth/login.html`. Below the wordmark/heading, add:
```html
<p style="color: var(--text-dim); font-family: var(--font-serif); font-style: italic; font-size: 0.95rem; margin-top: 0.25rem;">Where the realm's watch convenes.</p>
```
- [ ] **Step 4: Commit**
```bash
git add fabledscryer/templates/
git commit -m "copy: themed empty states + login tagline"
```
### Task 7: Add 404 and 500 templates
**Files:**
- Check: `fabledscryer/templates/errors/` (create if missing)
- Create or modify: `fabledscryer/templates/errors/404.html`, `fabledscryer/templates/errors/500.html`
- [ ] **Step 1: Check if error templates and handlers already exist**
Run:
```bash
ls fabledscryer/templates/errors/ 2>/dev/null
grep -rn "errorhandler\|@app.error" fabledscryer/app.py fabledscryer/*/routes.py
```
- [ ] **Step 2: If templates exist, update their copy to themed messages. If they don't exist, create them and wire handlers in `fabledscryer/app.py`.**
Content for `fabledscryer/templates/errors/404.html`:
```html
{% extends "base.html" %}
{% block title %}Not Found — Steward{% endblock %}
{% block content %}
<div style="text-align:center; padding: 4rem 2rem; font-family: var(--font-serif);">
<h1 style="color: var(--gold); font-size: 2.5rem; margin-bottom: 0.5rem;">404</h1>
<p style="color: var(--text); font-size: 1.2rem; margin-bottom: 0.25rem;">No such seat at this table.</p>
<p style="color: var(--text-dim); margin-bottom: 1.5rem;">The page you sought is not among us.</p>
<a href="/" class="btn">Return to the hall</a>
</div>
{% endblock %}
```
Content for `fabledscryer/templates/errors/500.html`:
```html
{% extends "base.html" %}
{% block title %}Error — Steward{% endblock %}
{% block content %}
<div style="text-align:center; padding: 4rem 2rem; font-family: var(--font-serif);">
<h1 style="color: var(--red); font-size: 2.5rem; margin-bottom: 0.5rem;">500</h1>
<p style="color: var(--text); font-size: 1.2rem; margin-bottom: 0.25rem;">The watch has faltered.</p>
<p style="color: var(--text-dim); margin-bottom: 1.5rem;">An unexpected error occurred. The cause has been logged.</p>
<a href="/" class="btn">Return to the hall</a>
</div>
{% endblock %}
```
- [ ] **Step 3: If handlers are missing, add them to `fabledscryer/app.py` near other Quart error wiring**
```python
@app.errorhandler(404)
async def not_found(_):
return await render_template("errors/404.html"), 404
@app.errorhandler(500)
async def server_error(_):
return await render_template("errors/500.html"), 500
```
Match `render_template` import style already used in the file.
- [ ] **Step 4: Commit**
```bash
git add fabledscryer/templates/errors/ fabledscryer/app.py
git commit -m "feat: themed 404 and 500 pages"
```
### Task 8: Dashboard hero title "Under Watch, Under Care"
**Files:**
- Modify: `fabledscryer/templates/dashboard/index.html` (or equivalent)
- [ ] **Step 1: Locate the dashboard top-of-page template**
Run:
```bash
ls fabledscryer/templates/dashboard/
grep -rn "page-title\|dashboard" fabledscryer/templates/dashboard/ | head
```
- [ ] **Step 2: At the top of the dashboard page content block, add a hero title**
```html
<h1 class="page-title" style="text-align:center; color: var(--gold); font-size: 1.8rem; letter-spacing: 0.02em;">Under Watch, Under Care</h1>
```
If the dashboard already has a `.page-title`, replace its text content with "Under Watch, Under Care" rather than adding a second title.
- [ ] **Step 3: Commit**
```bash
git add fabledscryer/templates/dashboard/
git commit -m "copy: dashboard hero title"
```
### Task 9: Manual visual verification
- [ ] **Step 1: Start the app**
Run:
```bash
docker compose up --build
```
- [ ] **Step 2: Open `http://localhost:5000` in a browser and walk through**
- Login page — tagline visible, gold wordmark, candle glow background
- Dashboard — hero title, logo in nav, no purple anywhere
- Hosts / Alerts / Plugins / Settings — palette applied consistently
- Trigger a 404 (e.g. `/nope`) — themed page renders
- Check any empty state you can produce
- [ ] **Step 3: Note visually off items in a scratch file, fix them, and commit**
```bash
git add -A
git commit -m "style: visual polish after manual review"
```
**PR 1 done.** Open PR with title `feat: steward visual reskin (pewter & gold)`.
---
## PR 2 — Python Package Rename
### Task 10: Rename the package directory
**Files:**
- Rename: `fabledscryer/``steward/`
- [ ] **Step 1: Rename the directory**
```bash
git mv fabledscryer steward
```
- [ ] **Step 2: Confirm the move**
```bash
ls steward/ | head
git status | head
```
Expected: see `__init__.py`, `app.py`, `cli.py`, etc. inside `steward/`.
- [ ] **Step 3: Commit**
```bash
git commit -m "refactor: rename package directory fabledscryer → steward"
```
### Task 11: Rewrite all `fabledscryer` imports to `steward`
**Files:**
- Modify: every file under `steward/`, `tests/`, `alembic.ini`, `entrypoint.sh`, `Dockerfile` that imports from the old package
- [ ] **Step 1: Find every remaining `fabledscryer` reference in Python code**
Run:
```bash
grep -rn "fabledscryer" steward/ tests/ alembic.ini entrypoint.sh Dockerfile pyproject.toml
```
Keep the output visible as a checklist.
- [ ] **Step 2: Run a safe codemod across Python files**
```bash
grep -rl "fabledscryer" steward/ tests/ | xargs sed -i 's/fabledscryer/steward/g'
```
This touches only files under `steward/` and `tests/`. Do NOT run it across the whole repo yet — `docs/`, `.env.example`, `docker-compose.yml`, `config.example.yaml` and `README.md` are handled in later PRs.
- [ ] **Step 3: Spot-check a few critical files**
```bash
grep -n "steward\|fabledscryer" steward/app.py steward/cli.py steward/config.py steward/migrations/env.py
```
Expected: only `steward` references remain; no stray `fabledscryer`.
- [ ] **Step 4: Commit**
```bash
git add -A
git commit -m "refactor: update imports fabledscryer → steward"
```
### Task 12: Update `pyproject.toml`
**Files:**
- Modify: `pyproject.toml`
- [ ] **Step 1: Replace the project name, script entry, and hatch packages**
```toml
[project]
name = "steward"
version = "0.1.0"
# ... dependencies unchanged ...
[project.scripts]
steward = "steward.cli:main"
[tool.hatch.build.targets.wheel]
packages = ["steward"]
```
Leave `[project.optional-dependencies]`, `[tool.pytest.ini_options]`, and all dependency pins untouched.
- [ ] **Step 2: Commit**
```bash
git add pyproject.toml
git commit -m "build: rename package to steward in pyproject"
```
### Task 13: Update `alembic.ini`
**Files:**
- Modify: `alembic.ini`
- [ ] **Step 1: Change `script_location`**
```ini
[alembic]
script_location = steward/migrations
prepend_sys_path = .
version_path_separator = os
```
- [ ] **Step 2: Commit**
```bash
git add alembic.ini
git commit -m "build: point alembic at steward/migrations"
```
### Task 14: Verify the package installs and imports cleanly
- [ ] **Step 1: Install in editable mode into a throwaway venv**
```bash
python -m venv /tmp/rt-verify
/tmp/rt-verify/bin/pip install -e .
/tmp/rt-verify/bin/python -c "import steward; import steward.app; import steward.cli; print('ok')"
/tmp/rt-verify/bin/steward --help
```
Expected: `ok` and CLI help output. No ImportError.
- [ ] **Step 2: Remove venv**
```bash
rm -rf /tmp/rt-verify
```
- [ ] **Step 3: No commit needed (verification only).**
**PR 2 done.** Open PR with title `refactor: rename python package fabledscryer → steward`.
---
## PR 3 — Config & Environment Variables
### Task 15: Add env-var fallback shim in `steward/config.py`
**Files:**
- Modify: `steward/config.py`
- [ ] **Step 1: Replace the env var lookups with a fallback helper**
Open `steward/config.py` and replace the existing `load_bootstrap` body so it reads `STEWARD_*` first and falls back to `FABLEDSCRYER_*` with a deprecation warning.
```python
def _env_with_fallback(new_name: str, old_name: str) -> str | None:
val = os.environ.get(new_name)
if val is not None:
return val
val = os.environ.get(old_name)
if val is not None:
logger.warning(
"%s is deprecated, use %s instead. Fallback will be removed "
"in a future release.",
old_name, new_name,
)
return val
return None
```
Then inside `load_bootstrap`, replace the existing env lookups with:
```python
database_url = (
_env_with_fallback("STEWARD_DATABASE_URL", "FABLEDSCRYER_DATABASE_URL")
or _env_with_fallback("STEWARD_DATABASE__URL", "FABLEDSCRYER_DATABASE__URL")
or raw.get("database", {}).get("url")
)
if not database_url:
raise ValueError(
"Database URL is required. Set STEWARD_DATABASE_URL env var "
"or add 'database.url' to config.yaml."
)
# ...
plugin_dir = (
_env_with_fallback("STEWARD_PLUGIN_DIR", "FABLEDSCRYER_PLUGIN_DIR")
or raw.get("plugin_dir", "plugins")
)
```
And in `_resolve_secret_key`:
```python
from_env = (
_env_with_fallback("STEWARD_SECRET_KEY", "FABLEDSCRYER_SECRET_KEY")
or raw.get("secret_key")
)
```
- [ ] **Step 2: Grep for any other `FABLEDSCRYER_` or `FABLEDNETMON_` env var reads across `steward/`**
```bash
grep -rn "FABLEDSCRYER_\|FABLEDNETMON_" steward/
```
For each hit, apply the same pattern (new name first, old as fallback with warning). If `FABLEDNETMON_` is pure residue with no current consumer, delete the reference.
- [ ] **Step 3: Commit**
```bash
git add steward/config.py
git commit -m "feat: STEWARD_* env vars with FABLEDSCRYER_* fallback"
```
### Task 16: Update `.env.example` and `config.example.yaml`
**Files:**
- Modify: `.env.example`, `config.example.yaml`
- [ ] **Step 1: Rewrite `.env.example`**
```bash
grep -n "FABLEDSCRYER\|FABLEDNETMON" .env.example
```
Replace every occurrence with `STEWARD_*`. Add a short comment at top:
```
# Steward environment configuration.
# Only STEWARD_DATABASE_URL is required. Other settings live in the DB.
```
- [ ] **Step 2: Rewrite `config.example.yaml`**
Replace the header and example strings:
```yaml
# Steward — Bootstrap Configuration Example
#
# The only REQUIRED setting is the database URL.
# Set it via env var (recommended for Docker):
#
# STEWARD_DATABASE_URL=postgresql+asyncpg://user:pass@host/db
#
# All other settings are stored in the database and managed via
# the Settings UI at /settings/.
database:
url: "postgresql+asyncpg://steward:password@localhost/steward"
```
- [ ] **Step 3: Commit**
```bash
git add .env.example config.example.yaml
git commit -m "docs: STEWARD_* env var examples"
```
### Task 17: Manual config verification
- [ ] **Step 1: Run the app with only the new env var**
```bash
STEWARD_DATABASE_URL=postgresql+asyncpg://fabledscryer:fabledscryer@localhost/fabledscryer \
python -m steward.cli --host 127.0.0.1 --port 5001
```
(Use whatever local DB you have; the old db name is fine — data isn't being renamed.)
Expected: app starts, no deprecation warning.
- [ ] **Step 2: Run the app with only the old env var**
```bash
FABLEDSCRYER_DATABASE_URL=postgresql+asyncpg://fabledscryer:fabledscryer@localhost/fabledscryer \
python -m steward.cli --host 127.0.0.1 --port 5001
```
Expected: app starts, deprecation warning logged once.
- [ ] **Step 3: Kill processes.** No commit.
**PR 3 done.** Open PR with title `feat: STEWARD_* env vars (FABLEDSCRYER_* fallback)`.
---
## PR 4 — Container, Deploy, User-Visible Strings
### Task 18: Update `Dockerfile`
**Files:**
- Modify: `Dockerfile`
- [ ] **Step 1: Replace `fabledscryer` references**
Change:
```dockerfile
COPY fabledscryer/ fabledscryer/
```
to
```dockerfile
COPY steward/ steward/
```
Change the CMD:
```dockerfile
CMD ["steward", "--host", "0.0.0.0", "--port", "5000"]
```
Leave everything else (apt packages, gosu, app user, EXPOSE 5000) untouched.
- [ ] **Step 2: Commit**
```bash
git add Dockerfile
git commit -m "build: update Dockerfile for steward package"
```
### Task 19: Update `entrypoint.sh`
**Files:**
- Modify: `entrypoint.sh`
- [ ] **Step 1: Replace the `nut_setup.py` invocation path**
Change every `/app/fabledscryer/nut_setup.py` to `/app/steward/nut_setup.py`.
Update any comment that says "FabledScryer container entrypoint." to "Steward container entrypoint."
- [ ] **Step 2: Commit**
```bash
git add entrypoint.sh
git commit -m "build: entrypoint.sh uses steward package path"
```
### Task 20: Update `docker-compose.yml`
**Files:**
- Modify: `docker-compose.yml`
- [ ] **Step 1: Replace the service definition**
```yaml
services:
steward:
build: .
container_name: steward
image: steward:latest
ports:
- "5000:5000"
volumes:
- app_data:/data
- ./plugins:/app/plugins:ro
- /mnt/Data/traefik/log:/var/log/traefik:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- STEWARD_DATABASE_URL=postgresql+asyncpg://steward:steward@db/steward
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: steward
POSTGRES_PASSWORD: steward
POSTGRES_DB: steward
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U steward"]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
pgdata:
app_data:
```
**Data note:** the existing dev database is named `fabledscryer` with user `fabledscryer`. For local dev, either (a) drop and recreate the DB with the new name, or (b) leave the existing compose `environment` values pointing at the old DB name if you want to preserve data. Pick based on whether the local DB has data worth keeping — document the choice in the commit message.
- [ ] **Step 2: Commit**
```bash
git add docker-compose.yml
git commit -m "build: docker-compose service → steward"
```
### Task 21: Flip user-visible wordmark and title
**Files:**
- Modify: `steward/templates/base.html`
- [ ] **Step 1: Update the `<title>` block (around line 6)**
```html
<title>{% block title %}Steward{% endblock %}</title>
```
- [ ] **Step 2: Update the nav wordmark (around line 214)**
Change `Fabled Scryer` inside `nav .brand` to `Steward`.
- [ ] **Step 3: Grep for any other user-visible "Fabled Scryer" strings in templates**
```bash
grep -rn "Fabled Scryer\|FabledScryer" steward/templates/
```
Replace each with "Steward".
- [ ] **Step 4: Commit**
```bash
git add steward/templates/
git commit -m "copy: flip visible wordmark → Steward"
```
### Task 22: Manual container verification
- [ ] **Step 1: Rebuild and run**
```bash
docker compose down
docker compose up --build
```
- [ ] **Step 2: Verify**
- Container named `steward` runs
- Browser shows "Steward" in tab title and nav
- Login, dashboard, and error pages all render with the new palette and wordmark
- Logs show no import errors and no unhandled deprecation warnings
- [ ] **Step 3: Stop**
```bash
docker compose down
```
**PR 4 done.** Open PR with title `feat: steward container & wordmark flip`.
---
## PR 5 — Docs & Repo
### Task 23: Sweep `README.md` and `docs/`
**Files:**
- Modify: `README.md`, `docs/**/*.md`
- [ ] **Step 1: Find every remaining reference**
```bash
grep -rn "fabledscryer\|FabledScryer\|Fabled Scryer" README.md docs/
```
- [ ] **Step 2: Replace mechanically, then proofread**
```bash
grep -rl "fabledscryer\|FabledScryer\|Fabled Scryer" README.md docs/ \
| xargs sed -i \
-e 's/FabledScryer/Steward/g' \
-e 's/fabledscryer/steward/g' \
-e 's/Fabled Scryer/Steward/g'
```
Then read each changed file top-to-bottom and fix any mangled sentences (e.g. capitalization at the start of sentences, code blocks that now reference a directory that still needs a `./` prefix, etc.). Pay extra attention to:
- `docs/architecture.md`
- `docs/reference/code-map.md`
- `docs/core/configuration.md`
- `docs/plugins/writing-a-plugin.md`
- [ ] **Step 3: Commit**
```bash
git add README.md docs/
git commit -m "docs: steward rename sweep"
```
### Task 24: Rename the Forgejo repo
- [ ] **Step 1: Via Forgejo UI or API, rename the repo from `FabledScryer` to `Steward`.** The old URL will redirect for one grace period.
- [ ] **Step 2: Update your local remote URL**
```bash
git remote set-url origin <new-url>
git remote -v
```
- [ ] **Step 3: Optionally rename the local working directory**
```bash
# from the parent dir
cd ..
mv FabledScryer Steward
cd Steward
```
- [ ] **Step 4: No commit.**
**PR 5 done.** Open PR with title `docs: steward rename sweep`.
---
## PR 6 — Cleanup (deferred one release cycle)
### Task 25: Remove env var fallback shim
**Files:**
- Modify: `steward/config.py`
- [ ] **Step 1: Delete `_env_with_fallback` and inline direct `os.environ.get("STEWARD_*")` lookups**
Replace each `_env_with_fallback("STEWARD_X", "FABLEDSCRYER_X")` call with `os.environ.get("STEWARD_X")`. Delete the helper.
- [ ] **Step 2: Grep to confirm no `FABLEDSCRYER_` references remain**
```bash
grep -rn "FABLEDSCRYER_\|FABLEDNETMON_" .
```
Expected: zero hits (or only historical commit messages, which don't show up in `grep`).
- [ ] **Step 3: Commit**
```bash
git add steward/config.py
git commit -m "refactor: remove FABLEDSCRYER_* env var fallback shim"
```
### Task 26: Final sweep
- [ ] **Step 1: Search the entire repo one last time**
```bash
grep -rn "fabledscryer\|FabledScryer\|Fabled Scryer\|FABLEDSCRYER\|FABLEDNETMON" .
```
Expected: zero results outside of `.git/` and historical `docs/superpowers/plans/` or `docs/superpowers/specs/` files (those record the rename intentionally — leave them).
- [ ] **Step 2: If any unexpected hits appear, fix and commit**
```bash
git add -A
git commit -m "refactor: final rename sweep"
```
**PR 6 done.** Rebrand complete.
---
## Self-Review Notes
- Spec coverage: all 5 spec sections mapped to PRs 15; PR 6 handles the cleanup implied by the shim in PR 3.
- No placeholders — every template replacement includes concrete code; every grep includes the actual pattern.
- Type consistency: config helper is `_env_with_fallback` in both Task 15 and Task 25; env var names are `STEWARD_DATABASE_URL`, `STEWARD_PLUGIN_DIR`, `STEWARD_SECRET_KEY` consistently.
- Tests intentionally skipped per project feedback; verification is manual (browser + container).