diff --git a/docs/superpowers/plans/2026-04-13-rebrand.md b/docs/superpowers/plans/2026-04-13-rebrand.md new file mode 100644 index 0000000..89a0ff9 --- /dev/null +++ b/docs/superpowers/plans/2026-04-13-rebrand.md @@ -0,0 +1,927 @@ +# Roundtable 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 Roundtable: 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 2–4 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, `` +- `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/` → `roundtable/` (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` → `roundtable/config.py` (already moved in PR 2) — read both `ROUNDTABLE_*` and `FABLEDSCRYER_*` with deprecation warning +- `.env.example`, `config.example.yaml` — new names +- First-boot migration of `~/.config/fabledscryer` → `~/.config/roundtable` (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 +- `roundtable/templates/base.html` — wordmark text "Fabled Scryer" → "Roundtable", `<title>` +- `roundtable/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):** +- `roundtable/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 13–35) 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 9–11) 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 188–213) 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 68–71) 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 42–46) 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 266–369)** — 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 %}Roundtable{% endblock %} +``` + +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 `` 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 — Roundtable{% 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 — Roundtable{% 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: roundtable visual reskin (pewter & gold)`. + +--- + +## PR 2 — Python Package Rename + +### Task 10: Rename the package directory + +**Files:** +- Rename: `fabledscryer/` → `roundtable/` + +- [ ] **Step 1: Rename the directory** + +```bash +git mv fabledscryer roundtable +``` + +- [ ] **Step 2: Confirm the move** + +```bash +ls roundtable/ | head +git status | head +``` + +Expected: see `__init__.py`, `app.py`, `cli.py`, etc. inside `roundtable/`. + +- [ ] **Step 3: Commit** + +```bash +git commit -m "refactor: rename package directory fabledscryer → roundtable" +``` + +### Task 11: Rewrite all `fabledscryer` imports to `roundtable` + +**Files:** +- Modify: every file under `roundtable/`, `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" roundtable/ 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" roundtable/ tests/ | xargs sed -i 's/fabledscryer/roundtable/g' +``` + +This touches only files under `roundtable/` 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 "roundtable\|fabledscryer" roundtable/app.py roundtable/cli.py roundtable/config.py roundtable/migrations/env.py +``` + +Expected: only `roundtable` references remain; no stray `fabledscryer`. + +- [ ] **Step 4: Commit** + +```bash +git add -A +git commit -m "refactor: update imports fabledscryer → roundtable" +``` + +### Task 12: Update `pyproject.toml` + +**Files:** +- Modify: `pyproject.toml` + +- [ ] **Step 1: Replace the project name, script entry, and hatch packages** + +```toml +[project] +name = "roundtable" +version = "0.1.0" +# ... dependencies unchanged ... + +[project.scripts] +roundtable = "roundtable.cli:main" + +[tool.hatch.build.targets.wheel] +packages = ["roundtable"] +``` + +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 roundtable in pyproject" +``` + +### Task 13: Update `alembic.ini` + +**Files:** +- Modify: `alembic.ini` + +- [ ] **Step 1: Change `script_location`** + +```ini +[alembic] +script_location = roundtable/migrations +prepend_sys_path = . +version_path_separator = os +``` + +- [ ] **Step 2: Commit** + +```bash +git add alembic.ini +git commit -m "build: point alembic at roundtable/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 roundtable; import roundtable.app; import roundtable.cli; print('ok')" +/tmp/rt-verify/bin/roundtable --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 → roundtable`. + +--- + +## PR 3 — Config & Environment Variables + +### Task 15: Add env-var fallback shim in `roundtable/config.py` + +**Files:** +- Modify: `roundtable/config.py` + +- [ ] **Step 1: Replace the env var lookups with a fallback helper** + +Open `roundtable/config.py` and replace the existing `load_bootstrap` body so it reads `ROUNDTABLE_*` 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("ROUNDTABLE_DATABASE_URL", "FABLEDSCRYER_DATABASE_URL") + or _env_with_fallback("ROUNDTABLE_DATABASE__URL", "FABLEDSCRYER_DATABASE__URL") + or raw.get("database", {}).get("url") +) +if not database_url: + raise ValueError( + "Database URL is required. Set ROUNDTABLE_DATABASE_URL env var " + "or add 'database.url' to config.yaml." + ) + +# ... +plugin_dir = ( + _env_with_fallback("ROUNDTABLE_PLUGIN_DIR", "FABLEDSCRYER_PLUGIN_DIR") + or raw.get("plugin_dir", "plugins") +) +``` + +And in `_resolve_secret_key`: + +```python +from_env = ( + _env_with_fallback("ROUNDTABLE_SECRET_KEY", "FABLEDSCRYER_SECRET_KEY") + or raw.get("secret_key") +) +``` + +- [ ] **Step 2: Grep for any other `FABLEDSCRYER_` or `FABLEDNETMON_` env var reads across `roundtable/`** + +```bash +grep -rn "FABLEDSCRYER_\|FABLEDNETMON_" roundtable/ +``` + +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 roundtable/config.py +git commit -m "feat: ROUNDTABLE_* 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 `ROUNDTABLE_*`. Add a short comment at top: + +``` +# Roundtable environment configuration. +# Only ROUNDTABLE_DATABASE_URL is required. Other settings live in the DB. +``` + +- [ ] **Step 2: Rewrite `config.example.yaml`** + +Replace the header and example strings: + +```yaml +# Roundtable — Bootstrap Configuration Example +# +# The only REQUIRED setting is the database URL. +# Set it via env var (recommended for Docker): +# +# ROUNDTABLE_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://roundtable:password@localhost/roundtable" +``` + +- [ ] **Step 3: Commit** + +```bash +git add .env.example config.example.yaml +git commit -m "docs: ROUNDTABLE_* env var examples" +``` + +### Task 17: Manual config verification + +- [ ] **Step 1: Run the app with only the new env var** + +```bash +ROUNDTABLE_DATABASE_URL=postgresql+asyncpg://fabledscryer:fabledscryer@localhost/fabledscryer \ + python -m roundtable.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 roundtable.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: ROUNDTABLE_* 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 roundtable/ roundtable/ +``` + +Change the CMD: +```dockerfile +CMD ["roundtable", "--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 roundtable 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/roundtable/nut_setup.py`. + +Update any comment that says "FabledScryer container entrypoint." to "Roundtable container entrypoint." + +- [ ] **Step 2: Commit** + +```bash +git add entrypoint.sh +git commit -m "build: entrypoint.sh uses roundtable package path" +``` + +### Task 20: Update `docker-compose.yml` + +**Files:** +- Modify: `docker-compose.yml` + +- [ ] **Step 1: Replace the service definition** + +```yaml +services: + roundtable: + build: . + container_name: roundtable + image: roundtable: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: + - ROUNDTABLE_DATABASE_URL=postgresql+asyncpg://roundtable:roundtable@db/roundtable + depends_on: + db: + condition: service_healthy + restart: unless-stopped + + db: + image: postgres:16-alpine + environment: + POSTGRES_USER: roundtable + POSTGRES_PASSWORD: roundtable + POSTGRES_DB: roundtable + volumes: + - pgdata:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U roundtable"] + 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 → roundtable" +``` + +### Task 21: Flip user-visible wordmark and title + +**Files:** +- Modify: `roundtable/templates/base.html` + +- [ ] **Step 1: Update the `<title>` block (around line 6)** + +```html +<title>{% block title %}Roundtable{% endblock %} +``` + +- [ ] **Step 2: Update the nav wordmark (around line 214)** + +Change `Fabled Scryer` inside `nav .brand` to `Roundtable`. + +- [ ] **Step 3: Grep for any other user-visible "Fabled Scryer" strings in templates** + +```bash +grep -rn "Fabled Scryer\|FabledScryer" roundtable/templates/ +``` + +Replace each with "Roundtable". + +- [ ] **Step 4: Commit** + +```bash +git add roundtable/templates/ +git commit -m "copy: flip visible wordmark → Roundtable" +``` + +### Task 22: Manual container verification + +- [ ] **Step 1: Rebuild and run** + +```bash +docker compose down +docker compose up --build +``` + +- [ ] **Step 2: Verify** + - Container named `roundtable` runs + - Browser shows "Roundtable" 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: roundtable 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/Roundtable/g' \ + -e 's/fabledscryer/roundtable/g' \ + -e 's/Fabled Scryer/Roundtable/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: roundtable rename sweep" +``` + +### Task 24: Rename the Forgejo repo + +- [ ] **Step 1: Via Forgejo UI or API, rename the repo from `FabledScryer` to `Roundtable`.** The old URL will redirect for one grace period. + +- [ ] **Step 2: Update your local remote URL** + +```bash +git remote set-url origin +git remote -v +``` + +- [ ] **Step 3: Optionally rename the local working directory** + +```bash +# from the parent dir +cd .. +mv FabledScryer Roundtable +cd Roundtable +``` + +- [ ] **Step 4: No commit.** + +**PR 5 done.** Open PR with title `docs: roundtable rename sweep`. + +--- + +## PR 6 — Cleanup (deferred one release cycle) + +### Task 25: Remove env var fallback shim + +**Files:** +- Modify: `roundtable/config.py` + +- [ ] **Step 1: Delete `_env_with_fallback` and inline direct `os.environ.get("ROUNDTABLE_*")` lookups** + +Replace each `_env_with_fallback("ROUNDTABLE_X", "FABLEDSCRYER_X")` call with `os.environ.get("ROUNDTABLE_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 roundtable/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 1–5; 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 `ROUNDTABLE_DATABASE_URL`, `ROUNDTABLE_PLUGIN_DIR`, `ROUNDTABLE_SECRET_KEY` consistently. +- Tests intentionally skipped per project feedback; verification is manual (browser + container).