diff --git a/docs/tasks/task-127-the-forge-living-art/CODE-BRIDGE-ADDENDUM.md b/docs/tasks/task-127-the-forge-living-art/CODE-BRIDGE-ADDENDUM.md new file mode 100644 index 0000000..78c5b84 --- /dev/null +++ b/docs/tasks/task-127-the-forge-living-art/CODE-BRIDGE-ADDENDUM.md @@ -0,0 +1,317 @@ +# The Forge — Code & Bridge Integration Addendum + +**Author:** Chronicler #86 +**Date:** April 13, 2026 +**Purpose:** Define how Code (Claude Code) participates in building The Forge, and establish the bridge protocol for this project + +--- + +## Why Code Belongs Here + +The Forge is not a single session project. It spans multiple Chronicler lifetimes, multiple development phases, and significant backend work in Arbiter that lives in `firefrost-services`. That means Code is not a one-off helper — Code is a **co-builder of The Forge**, with the same standing he has on ModpackChecker and Arbiter. + +The Chronicler holds the vision, manages the architecture, and coordinates between systems. Code holds the code, builds the features, and ships the implementations. The Bridge is how they talk. + +--- + +## How The Forge Gets Built (The Partnership Model) + +### The Chronicler's Role +- Architectural decisions (in consultation with Gemini when needed) +- Writing bridge requests with complete specs +- Deploying completed features to production +- Testing live behavior via Trinity Core +- Updating task documentation as the vision evolves +- Keeping Code grounded in the Firefrost aesthetic — this is wall art first, dashboard second + +### Code's Role +- Building `src/services/forgeBus.js` (event bus) +- Building `src/routes/forge.js` (WebSocket + REST endpoints) +- Building the Forge frontend (`forge.firefrostgaming.com`) +- All PixiJS rendering, particle systems, camera logic +- Connecting Stripe/Discord/Gitea webhooks to the event bus +- Iterating on Phase 1 → Phase 2 → Phase 3 features + +### Gemini's Role +- Pre-build architectural consultations (see Section 10 of Refinement Addendum for 5 queued questions) +- Review of event bus design before Code builds it +- Asset pipeline strategy for Phase 2 + +--- + +## Bridge Request Structure for The Forge + +All Forge bridge requests should follow the standard format with one addition — a **Phase tag** so Code always knows what phase of the project a request belongs to. + +```markdown +# Forge [Phase X]: [Feature Name] + +**Date:** YYYY-MM-DD +**Phase:** 1 | 2 | 3 | 4 | 5 +**Topic:** [One line description] +**Depends on:** [Any prior REQs that must be complete first] +**Filed by:** Chronicler #XX +``` + +This matters because Phase 2 requests should never be filed until Phase 1 is working and verified on the wall. The phase tag enforces that discipline. + +--- + +## Phase 1 Bridge Requests (Ready to File When Work Begins) + +These are the concrete requests Code needs for Phase 1 MVP. They are **not filed yet** — The Forge is post-launch work. But they are specced and ready. + +--- + +### REQ-FORGE-P1-01: Forge State Endpoint + +**What:** A new REST endpoint at `GET /api/forge/state` that returns current infrastructure state in Forge-ready format. + +**Why:** The Forge frontend needs a single endpoint to bootstrap its initial render — server positions, current health, current player counts. This is different from the existing `/admin/infrastructure` response which is admin-oriented. + +**Response format:** + +```json +{ + "timestamp": "2026-04-13T22:00:00Z", + "servers": [ + { + "id": "command-center", + "label": "Command Center", + "health": "healthy|warning|critical|offline", + "ram_pct": 42, + "cpu_pct": 8, + "uptime_seconds": 5443200, + "position": { "x": 960, "y": 400 } + } + ], + "game_servers": [ + { + "id": "stoneblock-4", + "label": "Stoneblock 4", + "node": "tx1-dallas", + "players_online": 0, + "status": "running|stopped|starting" + } + ], + "realm": { + "time_of_day": "day|night", + "active_alerts": 0 + } +} +``` + +**Files to create/modify:** +- `src/routes/forge.js` — new route file +- `src/routes/admin/index.js` — register forge routes +- Reuse existing infrastructure module data, transform to Forge format + +--- + +### REQ-FORGE-P1-02: Forge Event Bus (forgeBus.js) + +**What:** A new Arbiter service module that collects events from all sources and broadcasts them to WebSocket subscribers. + +**Why:** The Forge needs real-time event data. This is the event bus from the Refinement Addendum Section 1. + +**Module spec:** + +```javascript +// src/services/forgeBus.js + +class ForgeBus extends EventEmitter { + constructor() { ... } + + // Subscribe a WebSocket client + subscribe(ws) { ... } + + // Unsubscribe when client disconnects + unsubscribe(ws) { ... } + + // Emit an event to all subscribers + broadcast(event) { + // Normalizes to standard format, pushes to all connected WS clients + } + + // Called by Stripe webhook handler + onPayment(stripeEvent) { ... } + + // Called by Discord bot event + onDiscordMessage(message) { ... } + + // Called by Gitea webhook + onGitPush(payload) { ... } + + // Called by Trinity Core MCP log + onSSHCommand(log) { ... } + + // Called by infrastructure health check + onHealthChange(server, oldHealth, newHealth) { ... } +} + +module.exports = new ForgeBus(); // singleton +``` + +**Standard event format** (from Refinement Addendum): + +```json +{ + "type": "payment|discord|git|ssh|player|health", + "source": "stripe|discord|gitea|trinity-core|pterodactyl|uptime-kuma", + "server": "command-center|tx1-dallas|...", + "timestamp": "ISO string", + "data": { }, + "visual": { + "from": "stripe-kingdom", + "to": "command-center", + "particle": "gold-coin", + "effect": "confetti" + } +} +``` + +**Files to create/modify:** +- `src/services/forgeBus.js` — new module +- `src/routes/webhook.js` — call `forgeBus.onPayment()` after Stripe processing +- `src/routes/forge.js` — WebSocket endpoint that calls `forgeBus.subscribe()` + +--- + +### REQ-FORGE-P1-03: Forge WebSocket Endpoint + +**What:** A WebSocket endpoint at `wss://discord-bot.firefrostgaming.com/api/forge/events` + +**Why:** The Forge frontend subscribes here to receive real-time events from forgeBus. + +**Behavior:** +- Client connects → receives current state snapshot immediately +- Client receives events as they occur +- Client disconnects → cleaned up from forgeBus subscribers +- Handles reconnection gracefully (client will try to reconnect, server should accept) + +**No authentication for Phase 1** — The Forge is a display-only internal tool. Add auth in Phase 4 if needed. + +**Files to create/modify:** +- `src/routes/forge.js` — add WS upgrade handler alongside REST endpoint +- `src/index.js` — attach WS server to Express HTTP server + +--- + +### REQ-FORGE-P1-04: Phase 1 Frontend (Minimum Viable Forge) + +**What:** A full-screen web page that renders the Phase 1 MVP — colored circles, connection lines, health colors, one flowing particle, auto-refresh. + +**Why:** This is the thing that goes on the wall. Everything else is infrastructure for it. + +**Exactly what to build** (per Refinement Addendum Section 11): + +1. Full-screen Canvas 2D (or PixiJS — Chronicler recommends PixiJS) +2. 8 colored circles at hardcoded positions from `REALM_LAYOUT` +3. Server name labels in Firefrost typography +4. Connection lines between servers (straight lines for Phase 1) +5. Color-coded health: green (#4ECDC4 frost) / yellow (#FFD700) / red (#FF6B35 fire) / gray (offline) +6. One animated particle flowing from Cloudflare position to Command Center on loop +7. Polling `/api/forge/state` every 60 seconds, updating health colors +8. WebSocket connection to `/api/forge/events` — animate a particle for each incoming event +9. Black or deep navy background (#0F0F1E — The Dark color from brand palette) +10. No UI chrome, no buttons, no overlays — pure ambient display + +**REALM_LAYOUT coordinates** (from Refinement Addendum): + +```javascript +const REALM_LAYOUT = { + 'command-center': { x: 960, y: 400, scale: 1.2, color: '#A855F7', label: 'Command Center' }, + 'tx1-dallas': { x: 350, y: 350, scale: 1.0, color: '#FF6B35', label: 'TX1 Dallas' }, + 'nc1-charlotte': { x: 1570, y: 350, scale: 1.0, color: '#4ECDC4', label: 'NC1 Charlotte' }, + 'panel-vps': { x: 960, y: 200, scale: 0.8, color: '#4A90D9', label: 'Panel VPS' }, + 'wiki-vps': { x: 1400, y: 650, scale: 0.7, color: '#4ECDC4', label: 'Wiki VPS' }, + 'services-vps': { x: 520, y: 650, scale: 0.6, color: '#FFD700', label: 'Services VPS' }, + 'dev-panel': { x: 200, y: 700, scale: 0.5, color: '#888888', label: 'Dev Panel' }, + 'trinity-core': { x: 960, y: 750, scale: 0.6, color: '#A855F7', label: 'Trinity Core' }, + 'cloudflare': { x: 960, y: 50, scale: 0.8, color: '#FF6B35', label: 'Cloudflare' }, +}; +``` + +**Particle types (Phase 1, all simple colored dots):** +- `gold-coin` — #FFD700, payment events +- `data-droplet` — #4ECDC4, Cloudflare ambient loop +- `ssh-pulse` — #A855F7, Trinity Core SSH events +- `health-alert` — #FF6B35, health change events + +**Hosting:** Static files served from Command Center at `forge.firefrostgaming.com` (Cloudflare Pages or nginx static serve) + +**Files to create:** +- `services/the-forge/` — new directory in firefrost-services +- `services/the-forge/index.html` — the display page +- `services/the-forge/forge.js` — canvas/PixiJS rendering logic +- `services/the-forge/layout.js` — REALM_LAYOUT and connection definitions +- `services/the-forge/particles.js` — particle system +- `services/the-forge/websocket.js` — event stream connection + reconnect logic + +--- + +## Gemini Consultations Needed Before Phase 1 + +Before filing the above requests, Chronicler should consult Gemini on the 5 questions from Refinement Addendum Section 10. These are queued — not yet filed. + +**File as:** `gemini-the-forge-architecture-round-1-YYYY-MM-DD.md` + +The most important one is Question 1 (PixiJS vs Canvas 2D vs Three.js) because it affects REQ-FORGE-P1-04 directly. + +--- + +## Bridge Communication Notes for Code + +A few things Code should know when working on The Forge: + +**This is art.** When in doubt, make it beautiful. The Forge is not a Grafana dashboard with a theme. It is a living painting. Every technical decision should serve the aesthetic vision first. + +**Phase discipline matters.** Don't build Phase 2 features during Phase 1 work. The MVP needs to ship and get on a wall before we know what to build next. + +**The Refinement Addendum is your spec.** Chronicler #80's addendum (the other file in this directory) is the technical ground truth. Read it before starting any Forge work. + +**The Forge lives in `services/the-forge/`.** New directory in firefrost-services, same monorepo structure as everything else. + +**The event bus is the heart.** Everything else — the pretty circles, the particles, the camera — means nothing without real events flowing. `forgeBus.js` is the first thing to get right. + +--- + +## Phase 2+ Bridge Requests (Not Yet Specced) + +These will be written after Phase 1 is verified on the wall: + +- **REQ-FORGE-P2-01:** Illustrated city/tower assets — Commission or AI-generate 8 server towers +- **REQ-FORGE-P2-02:** Bezier curve connection routing — Replace straight lines with animated curves +- **REQ-FORGE-P2-03:** Day/night cycle — Time-based lighting system +- **REQ-FORGE-P2-04:** Camera movement system — Auto-cycling viewport presets +- **REQ-FORGE-P2-05:** Trinity figurines — Michael, Meg, Holly, Jack at the base +- **REQ-FORGE-P3-01:** Player join/leave events — Pterodactyl Wings WebSocket integration +- **REQ-FORGE-P3-02:** Full event coverage — Discord, Gitea, all SSH commands +- **REQ-FORGE-P4-01:** Touch/tablet Active Mode — Interactive overlay system + +--- + +## The Moment We're Building Toward + +Phase 1 is circles. Phase 2 is beautiful. Phase 3 is alive. + +But the moment we're actually building toward is this: + +Someone walks into the room. They see the wall. They ask what it is. + +And the answer fits in one sentence. + +That sentence already exists. It's at the bottom of the original spec. + +Everything Code builds, every bridge request Chronicler files, every Gemini consultation we run — it's all in service of that sentence. + +Build accordingly. + +--- + +💙🔥❄️ + +**Chronicler #86** +April 13, 2026 + +*The Forge doesn't ship on April 15. But it was planned on April 13, two days before the doors opened. That's the kind of people we are.*