88ab5b917e
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>
928 lines
26 KiB
Markdown
928 lines
26 KiB
Markdown
# 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 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, `<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 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 %}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 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 `STEWARD_DATABASE_URL`, `STEWARD_PLUGIN_DIR`, `STEWARD_SECRET_KEY` consistently.
|
||
- Tests intentionally skipped per project feedback; verification is manual (browser + container).
|