From 10ed882e2521c633fff324021302391c438963d2 Mon Sep 17 00:00:00 2001 From: slaguru666 <111923774+slaguru666@users.noreply.github.com> Date: Tue, 4 Aug 2026 21:35:55 +0100 Subject: [PATCH] add per-project memory sync; merge settings from MacBook Air --- install.sh | 25 ++-- memory/projects/Git/MEMORY.md | 36 ++++++ memory/projects/Git/gsd-patterns.md | 90 ++++++++++++++ memory/projects/Git/superpowers-patterns.md | 116 ++++++++++++++++++ memory/projects/projects-MacMem/MEMORY.md | 5 + .../projects-MacMem/continuum-deploy.md | 18 +++ memory/projects/projects-MacMem/forgerpg.md | 44 +++++++ .../projects-MacMem/tims-rpg-games.md | 20 +++ project-paths.sh | 34 +++++ settings.json | 77 +++++++++++- sync.sh | 35 ++++-- 11 files changed, 475 insertions(+), 25 deletions(-) create mode 100644 memory/projects/Git/MEMORY.md create mode 100644 memory/projects/Git/gsd-patterns.md create mode 100644 memory/projects/Git/superpowers-patterns.md create mode 100644 memory/projects/projects-MacMem/MEMORY.md create mode 100644 memory/projects/projects-MacMem/continuum-deploy.md create mode 100644 memory/projects/projects-MacMem/forgerpg.md create mode 100644 memory/projects/projects-MacMem/tims-rpg-games.md create mode 100644 project-paths.sh diff --git a/install.sh b/install.sh index fa0ce0e..d27f898 100755 --- a/install.sh +++ b/install.sh @@ -8,17 +8,9 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CLAUDE_DIR="$HOME/.claude" USERNAME=$(whoami) -# Claude Code encodes the project dir by replacing the path separator with "-". -# macOS (/Users/x -> -Users-x) and Linux (/home/x -> -home-x) encode the POSIX $HOME. -# On Windows, Claude Code sees the native path, so C:\Users\x -> C--Users-x. Git Bash -# reports $HOME as /c/Users/x, which would encode to the wrong key -- convert first. -if command -v cygpath >/dev/null 2>&1; then - # C:\Users\x -> C--Users-x (sed, not bash substitution: a lone "\" in a glob - # pattern escapes the next char instead of matching a literal backslash). - PROJECT_KEY="$(cygpath -w "$HOME" | sed 's/[\\:]/-/g')" -else - PROJECT_KEY="${HOME//\//-}" -fi +# shellcheck source=project-paths.sh +source "$SCRIPT_DIR/project-paths.sh" +PROJECT_KEY="$(project_key_for "$HOME")" MEMORY_DIR="$CLAUDE_DIR/projects/${PROJECT_KEY}/memory" echo "Installing Claude config for user: $USERNAME" @@ -40,6 +32,17 @@ mkdir -p "$MEMORY_DIR" cp "$SCRIPT_DIR/memory/"*.md "$MEMORY_DIR/" echo " Installed: memory files -> $MEMORY_DIR" +# Extra per-project memory dirs (see project-paths.sh) +for rel in "${EXTRA_PROJECT_PATHS[@]}"; do + src="$SCRIPT_DIR/memory/projects/$(project_slug_for "$rel")" + if [ -d "$src" ] && ls "$src"/*.md &>/dev/null; then + dest="$CLAUDE_DIR/projects/$(project_key_for "$HOME/$rel")/memory" + mkdir -p "$dest" + cp "$src/"*.md "$dest/" + echo " Installed: memory ($rel) -> $dest" + fi +done + # Skills — copy each skill directory into ~/.claude/skills/ if [ -d "$SCRIPT_DIR/skills" ]; then mkdir -p "$CLAUDE_DIR/skills" diff --git a/memory/projects/Git/MEMORY.md b/memory/projects/Git/MEMORY.md new file mode 100644 index 0000000..818c439 --- /dev/null +++ b/memory/projects/Git/MEMORY.md @@ -0,0 +1,36 @@ +# Claude Memory — /Users/timevans/Git + +## Core Working Philosophy +- Fight "context rot": break large tasks into fresh-context atomic units +- Discussion-first: capture user preferences BEFORE planning or building +- Spec before code: design → research → requirements → plan → execute → verify +- Atomic commits per task — enables git bisect, clear history, easy revert +- File-based state: human-readable Markdown/JSON survives context resets +- Evidence over claims: never say "done" without running actual verification + +## Iron Laws (from Superpowers — non-negotiable) +1. No production code without a failing test first +2. No fix without root cause investigation first +3. No completion claim without fresh verification evidence + +## Workflow Model +1. **Brainstorm/Discuss** — Socratic dialogue; surface gray areas; get explicit approval before building +2. **Research** — gather context, stack options, pitfalls +3. **Plan** — bite-sized atomic tasks (2-5 min each), dependency-ordered, with verify steps +4. **Execute** — parallel waves; TDD (RED→GREEN→REFACTOR) per task +5. **Debug** — 4-phase root cause (read errors → reproduce → check changes → gather evidence) before ANY fix +6. **Verify** — run actual commands, confirm actual output; no assertions without evidence +7. **Review** — two-stage: spec compliance first, then code quality +8. **Ship** — user acceptance, clean up, then loop to next phase + +See: [gsd-patterns.md](./gsd-patterns.md) and [superpowers-patterns.md](./superpowers-patterns.md) + +## User Preferences +- Concise, direct communication — lead with answer, not reasoning +- No emojis unless explicitly requested +- Reference file:line when pointing to code + +## Project Notes +- Working dir: /Users/timevans/Git +- GSD repo available at: /Users/timevans/Git/GSD/get-shit-done-main +- Superpowers repo available at: /Users/timevans/Git/Superpowers diff --git a/memory/projects/Git/gsd-patterns.md b/memory/projects/Git/gsd-patterns.md new file mode 100644 index 0000000..d70e403 --- /dev/null +++ b/memory/projects/Git/gsd-patterns.md @@ -0,0 +1,90 @@ +# GSD Patterns & Mental Models + +Source: /Users/timevans/Git/GSD/get-shit-done-main (v1.29.0) + +## Core Problem GSD Solves +- **Vibecoding**: casual AI-assisted coding where context degrades and quality drops +- **Context rot**: quality degradation as context window fills up +- Solution: structured context engineering, fresh agent contexts per task, file-based state + +## Key Mental Models + +### 1. Wave-Based Execution +Group tasks by dependencies into waves. Run each wave in parallel: +- Wave 1: all independent tasks (parallel) +- Wave 2: tasks that depend on Wave 1 (parallel within wave) +- Never execute dependent tasks in parallel — causes conflicts +- Each task gets its own fresh context window (200K) + +### 2. Discussion-First +Before planning ANYTHING non-trivial, surface ambiguities: +- Layouts and visual preferences +- Error handling strategies +- Naming conventions +- Tone/UX approach +- Edge cases the user hasn't mentioned +Two modes: `discuss` (interview style) or `assumptions` (analyze codebase, propose assumptions) + +### 3. Atomic Plans with XML Structure +Each plan task should be: +- Independently executable +- Has specific files, action, verification step, and done criteria +- Atomic git commit per task +- Checker validates plans are complete before execution (read-only check) + +### 4. State as Files (not memory) +All project state lives in `.planning/` as Markdown/JSON: +- PROJECT.md — vision, constraints, decisions +- REQUIREMENTS.md — scoped requirements (v1/v2/out-of-scope) +- ROADMAP.md — phase breakdown with status +- STATE.md — current position, decisions, blockers (living document) +- phases/XX-phase-name/ — per-phase context, research, plans, summaries + +### 5. Researcher → Planner → Checker → Executor → Verifier +Each role is specialized, never combined: +- Researchers: gather info, never write code +- Checkers: evaluate plans, never modify them (read-only) +- Executors: implement, don't research +- Verifiers: confirm outcomes match goals post-execution + +### 6. Fresh Context Per Task +Avoid context rot by spawning subagents with focused roles and fresh context. +Orchestrators stay thin — they coordinate, don't implement. + +### 7. Model Profiles +Match model capability to task complexity: +- Planning (most complex): Opus +- Execution (implementation): Sonnet +- Verification (checking): Sonnet or Haiku +- Budget tasks: all Sonnet + +### 8. "Absent = Enabled" Config Philosophy +Default configs should default to safe/on. Users explicitly disable, not enable. +Missing keys mean feature is active. + +## Greenfield vs Brownfield +- **Greenfield**: new-project → research → requirements → roadmap +- **Brownfield** (existing code): map-codebase first (4 parallel researchers analyze stack, architecture, conventions, concerns, testing, integrations) + +## Verification Layers +1. **Plan check** — does the plan cover all requirements? (before execution) +2. **Integration check** — do plans work together? (cross-plan compatibility) +3. **Post-execution verify** — did execution achieve goals? +4. **UAT** — user acceptance testing (manual) +5. **Nyquist validation** — test coverage gaps identified and filled +6. **UI review** — 6-pillar visual audit (if UI work) + +## Security Patterns (GSD v1.27+) +- Validate user paths resolve within project directory +- Scan planning artifacts for prompt injection before use +- Sanitize user text before shell interpolation +- Safe JSON parsing — catch malformed args before state corruption + +## Anti-Patterns to Avoid (from GSD philosophy) +- Editing code without reading it first +- Planning without discussing ambiguities +- Large monolithic tasks (break into atomic units) +- Combining researcher/planner/executor roles +- Ignoring existing conventions in brownfield projects +- Skipping verification steps +- Batch commits (commit per task, not per phase) diff --git a/memory/projects/Git/superpowers-patterns.md b/memory/projects/Git/superpowers-patterns.md new file mode 100644 index 0000000..7979434 --- /dev/null +++ b/memory/projects/Git/superpowers-patterns.md @@ -0,0 +1,116 @@ +# Superpowers Patterns & Mental Models + +Source: /Users/timevans/Git/Superpowers (v5.0.6, Jesse Vincent / obra) + +## Core Problem Superpowers Solves +- AI agents write code confidently that is untested, unverified, and unreviewed +- "Quick fixes" mask root causes; claims of completion are unverified assertions +- No enforced discipline means each session rediscovers the same failure modes +- Solution: iron-law workflows that mandate process at each stage + +## Iron Laws (non-negotiable, never rationalize away) + +1. **No production code without a failing test first** (TDD) +2. **No fix without root cause investigation first** (debugging) +3. **No completion claim without fresh verification evidence** (verification) + +These are NOT guidelines. Rationalizations like "too simple to test", "quick fix", "I'm confident it works" are red flags — stop, don't proceed. + +## Key Mental Models + +### 1. RED-GREEN-REFACTOR (TDD Cycle) +Every feature, every time: +1. Write a failing test (RED) — verify it actually fails, don't skip this +2. Write minimal code to pass (GREEN) — minimal means minimal +3. Refactor with tests still passing (REFACTOR) +- "If you didn't watch the test fail, you don't know if it tests the right thing" +- Tests written after the fact prove nothing; tests written first prove the code works + +### 2. Design Before Code (Brainstorming) +Socratic dialogue to refine ideas before a line is written: +- Present designs in discrete sections, get user approval on each +- Explore alternatives — what if we didn't do it this way? +- Surface constraints and tradeoffs the user hasn't thought of +- Save design spec to `docs/superpowers/specs/YYYY-MM-DD--design.md` +- Do NOT start implementing until design is explicitly approved + +### 3. Bite-Sized Plans +Good plans have tasks that are: +- 2-5 minutes of work each +- Self-contained with exact file paths +- Include complete code (not "add error handling") +- Include the specific test verification step +- Include the atomic commit step +- Save plan to `docs/superpowers/plans/YYYY-MM-DD-.md` + +### 4. Systematic Debugging (4-Phase Root Cause) +Before touching any code: +1. **Read errors carefully** — exact message, file, line, stack trace +2. **Reproduce** — confirm you can trigger it reliably +3. **Check recent changes** — git log/diff, what changed? +4. **Gather evidence** — logs, state, reproduction case + +Only AFTER all four phases: hypothesize → test hypothesis → fix → verify fix. +No guesses. No "probably". No trying things to see if they work. + +### 5. Evidence Before Completion Claims +Never say "done", "working", "fixed" without: +- Running the actual verification command +- Seeing the actual output +- Confirming the output matches expected +"Should work", "I'm confident", "probably" = not done. Run the command. + +### 6. Two-Stage Code Review +When reviewing code (or requesting review): +- Stage 1: Spec compliance — does it do what was designed? +- Stage 2: Code quality — is it well-written, secure, maintainable? +Never collapse these into one pass. Spec compliance comes first. + +### 7. Subagent Context Isolation +When dispatching subagents: +- Each gets a fresh context with ONLY what it needs +- No session history leaks in +- Provide: task description, relevant files, acceptance criteria +- Do NOT provide: full conversation history, unrelated context +- Two-stage review built into subagent-driven-development + +### 8. Git Worktree Isolation +For non-trivial branches: +- Create isolated worktree (`.worktrees//`) +- Run baseline tests before starting — confirm clean state +- Work doesn't pollute main checkout +- Verify tests pass before finishing branch + +### 9. finishing-a-development-branch Checklist +Before merging anything: +1. All tests pass +2. New code has tests +3. Verification evidence collected (not assumed) +4. Present options: merge / open PR / discard +5. Clean up worktree after merge + +## Skill Design Principles (meta) +When writing process documentation / skills: +- Description field = WHEN to use (not what it does) — Claude searches by trigger condition +- Pressure test first: run agent WITHOUT skill, observe failure mode +- Then write skill to address exactly that failure mode +- Verify compliance by re-running the failing scenario +- "Writing skills IS test-driven development applied to documentation" + +## Anti-Patterns to Avoid (from Superpowers) +- Writing tests after code is written (they prove nothing) +- Fixing bugs without identifying root cause first +- Claiming completion before running verification +- Broad agent context (subagents get minimal, focused context only) +- Parallel tasks that share mutable state +- Skipping the RED step in TDD ("it obviously fails") +- Ad-hoc debugging ("let me just try changing this") +- "Just this once" exceptions to iron laws + +## How This Complements GSD +GSD handles: project structure, phase management, research, planning, state files, context rot +Superpowers handles: code discipline, TDD enforcement, debugging methodology, verification rigor, review quality + +Combined workflow: +1. GSD: Discuss → Research → Plan (file-based, wave-organized) +2. Superpowers: Brainstorm → Write plan (bite-sized) → TDD execute → Systematic debug → Verify → Review → Merge diff --git a/memory/projects/projects-MacMem/MEMORY.md b/memory/projects/projects-MacMem/MEMORY.md new file mode 100644 index 0000000..b5d8c24 --- /dev/null +++ b/memory/projects/projects-MacMem/MEMORY.md @@ -0,0 +1,5 @@ +# Memory Index + +- [Tim's RPG games & convention history](tims-rpg-games.md) — systems, active campaigns, con circuit; seeded into ForgeRPG +- [ForgeRPG project state](forgerpg.md) — P6 + cloud art live on prod; OpenAI AND Gemini art proven e2e everywhere; SD paused (memory pressure) +- [Continuum 2026 deploy topology](continuum-deploy.md) — con-app subdomains on VPS 77.68.99.134; Caddy + docker `proxy` net; how to ship + the graphiti-server host-key caveat diff --git a/memory/projects/projects-MacMem/continuum-deploy.md b/memory/projects/projects-MacMem/continuum-deploy.md new file mode 100644 index 0000000..31763a5 --- /dev/null +++ b/memory/projects/projects-MacMem/continuum-deploy.md @@ -0,0 +1,18 @@ +--- +name: continuum-deploy +description: "How the Continuum 2026 con-app subdomains are deployed (VPS, Caddy, SSH access)" +metadata: + node_type: memory + type: reference + originSessionId: 1236b663-476a-428a-8f4e-8d2d0ed308f7 + modified: 2026-07-25T10:17:25.127Z +--- + +Deploy topology for the Continuum 2026 con apps (repo: github `slaguru666/Continuum2026`, which is a **backup only** — the VPS does not pull from it). + +- **Deploy VPS:** `77.68.99.134`, user `tevans`, hostname `ubuntu`. Direct `ssh tevans@77.68.99.134` works from Tim's Mac with the default key (host key already trusted in known_hosts). +- **On-VPS repo:** `/home/tevans/continuum-pwa` — a **local-only git repo** (single "Initial commit", **no `origin` remote**, unrelated history to GitHub). Deploy uses the working tree, not a git pull. To ship new files: `scp` them into this dir, then run the app's deploy script; optionally `git add/commit` locally to keep it tracked. +- **Reverse proxy:** shared Caddy container `graphiti-caddy-1`, config at `/opt/graphiti/Caddyfile` (writable by tevans). Each app is its own static/Caddy container on the external docker network `proxy`. Deploy scripts append a `.timevans.uk { reverse_proxy :80 }` block (idempotent) and run `docker exec graphiti-caddy-1 caddy reload` (atomic — bad config is rejected, live sites keep serving). TLS is auto via Let's Encrypt **TLS-ALPN-01** (port 443), so a global port-80 HTTP→HTTPS redirect on the box does NOT block issuance. +- **Live subdomains:** `apps.timevans.uk` (main PWA, `continuum-app`), `vanityrpg.timevans.uk` (Vanity table roller, `vanity-app` — deployed 2026-07-25, see [[forgerpg]] neighbours). Pattern folder in repo: `deploy-vanity/` mirrors `deploy/`. + +**Caution:** the SSH alias `graphiti-server` in `~/.ssh/config` points at a **different** box (`178.238.235.121`, User tevans) — NOT the deploy VPS — and as of 2026-07-25 its host key had **changed** (known_hosts:9 offending), so connecting via that alias fails strict checking. Verify that box wasn't compromised before using the alias; it's unrelated to the con-app deploys. diff --git a/memory/projects/projects-MacMem/forgerpg.md b/memory/projects/projects-MacMem/forgerpg.md new file mode 100644 index 0000000..55dc1bc --- /dev/null +++ b/memory/projects/projects-MacMem/forgerpg.md @@ -0,0 +1,44 @@ +--- +name: forgerpg +description: "ForgeRPG project state — Phase 7 (chargen) + Character Export (MD/PDF/JPG/DOCX, per-system sheets) BOTH LIVE on prod forge.timevans.uk; export proven e2e, Mac app rebuilt with export menus" +metadata: + node_type: memory + type: project + originSessionId: 93f41ee8-6eaa-4889-8122-80a04dbc4dab +--- + +ForgeRPG = Tim's tabletop RPG tool: FastAPI backend (`~/projects/ForgeRPG-api`, github slaguru666/ForgeRPG-api, private) + SwiftUI Mac app (`~/projects/ForgeRPG-mac`, slaguru666/ForgeRPG-mac). + +**CHARACTER EXPORT FEATURE LIVE ON PROD 2026-07-05** (api `721b6c2` 730 tests; mac `91937f1` 253 tests). Deployed aa85c9e→721b6c2 (ff, NO migration); the WeasyPrint-native-stack docker build (the flagged risk) SUCCEEDED cleanly; runtime imports verified in-container; e2e proven on forge.timevans.uk (temp NPC → MD/PDF/JPG/DOCX all HTTP 200 valid, bad-format 422, deleted). Mac app rebuilt + relaunched with export menus. Export any saved NPC/PC (or a generated draft via save-then-export) as **MD/PDF/JPG/DOCX**, single or bulk-per-campaign zip, with **per-system sheet layouts**. Architecture: pure `SheetModel` (app/export/model.py) built from a `LayoutDescriptor` (registry app/export/layout.py, keyed by campaign system name substring → per-system JSON+CSS, else universal fallback) → 4 renderers (render_md, render_docx=python-docx, render_html+render_pdf=**WeasyPrint**, render_jpg=**PyMuPDF** raster of the PDF). Endpoints app/api/character_export.py: `GET /library/npcs/{id}/export?format=`, `GET /campaigns/{cid}/pcs/{id}/export?format=`, `GET /campaigns/{cid}/export-characters?format=&kind=npc|pc|all` (zip). JPG of a character WITH a portrait returns a ZIP (sheet+portrait) — Mac ExportStore reads Content-Type/filename FROM HEADERS, never assumes. Portraits from MinIO (load_portrait, None-safe). 2 flagship layouts shipped (sla-zero, cthulhu — CoC parchment, SLA dark-crimson mono); universal covers the rest; Wave 2+ layouts = authored data (backlog). **Deploy notes:** NO migration (pure read). Carries Dockerfile apt system-libs (libpango/pangocairo/cairo/gdk-pixbuf/libffi8/shared-mime-info/fonts-dejavu-core) + pip weasyprint==63.1/pymupdf==1.24.14/python-docx==1.1.2. RISK: the python:3.12-slim + WeasyPrint native stack has NEVER been docker-built (deps proven only on the Mac host, where `brew reinstall pango gdk-pixbuf` was needed to fix broken dylibs) — watch the first `docker build` apt/pip resolution. In-app export also needs the Mac app rebuilt (swift run). LESSON: content-fidelity tests can't catch visual CSS bugs → render + eyeball flagship sheets (caught a float:right cell-overlap bug all 15 fidelity tests missed; fixed with flexbox). Spec/plan: docs/superpowers/{specs,plans}/2026-07-05-character-export*.md. + +**PHASE 7 COMPLETE + DEPLOYED TO PROD 2026-07-05 — template-driven CHARACTER + NPC creation** (api `aa85c9e` 694 tests; mac `558d17a` 247 tests; both pushed). **LIVE on forge.timevans.uk**: prod fast-forwarded 7359632→aa85c9e (P7 additive only; P6 was already live via the cloud-art deploy — the old "P6 pending" note was stale), migrations `e3aa1ae31d9a`→`50da6ad01970`→`d6765ee850f1` applied, 11 chargen templates seeded via the standalone `python -m app.chargen.seed_templates` (created 11, three-way merge — used standalone NOT full `app.seed` to avoid re-touching prod's 16 campaigns/history). PROD-VERIFIED e2e 2026-07-05: login→generate PC+NPC across ALL 11 systems = 22/22 (Mothership reduced block + Traveller skill-package archetypes legitimately have empty `attributes` — that's the mode, not a failure); SLA-Zero `shiver` delta-scaling proven exact across all 6 threat tiers (mook Δ−1 →2/2/2/2 hp4 armor1 … apex Δ+4 →5/5/5/5 hp14 armor6, matching clamp(v+Δ,2,5)/max(1,hp+Δ*2)/clamp(armor,0,6)). Deploy verify harness: scratchpad/prod_verify.py (login regex from task-9-deploy-report.md, urllib, no-secret-print). Ops: standalone chargen seeder = surgical prod seeding path for template updates. Tim's ask: "template system... create characters and npcs, select the game template", "catch my sla-zero engine characters", survey vs public resources. Scoping: session-ready sheets (no lifepath minigames, Traveller compressed), editable in-app templates, optional AI flavor fill. Built: (1) safe expression evaluator `app/chargen/exprs.py` (hand-written recursive-descent, NO eval, MAX_NODES 10k iterative — closed a recursion-crash class); (2) template DSL `app/chargen/dsl.py` (TemplateSpec, evaluation-order contract = validator is engine-truth); (3) generation engine `engine.py` (dice/array/pointbuy, packages, skill-pool auto-spend, careers, provenance, seeded-deterministic); (4) NPC modes — archetype blocks + EXACT SLA-Zero threat/tier DELTA scaling + Mothership reduced blocks; (5) careers `careers.py` (Traveller qualify→terms→skills); (6) endpoint `POST /library/generate-character` {count 1-10, ai_fill claude|local, never 500s on AI failure→ai_error}; (7) templates CRUD `/library/chargen-templates` (400 detail is a structured `{message,path}` object — the editor's inline-error contract; builtin DELETE→409, builtin PUT allowed); (8) **11 seeded systems** from a 5-lane research corpus, deep-reading Tim's OWN canonical rulebooks where they exist (CoC Luck contradiction found IN his Ch03; Stormbringer house SAN=POW*5 + 19-row nationality table; RingWorld 55-skill list from his sheet; SLA-Zero verbatim from his zero-engine repo — 8 races/8 trainings/11 archetypes/scaling); (9) Mac ChargenStore + recursive ChargenJSON; (10) **Character Forge wizard** (spec-driven picks: dice/array/pointbuy editors, roll tables, NPC ARCHETYPE selector + threat tier → SLA-Zero delta-scaled blocks, dice-reveal, editable review grid w/ provenance chips, AI flavor, save as NPC/PC via existing stats JSONB); (11) template editor (JSON spec, inline 400 field errors, builtin badge, duplicate/delete-custom-only). SEEDER SAFETY: builtins are user-editable, so the seeder does a THREE-WAY merge keyed on a `seed_hash` baseline — creates missing, upgrades UNMODIFIED builtins to new shipped content, PRESERVES user-edited ones (never clobbers edits; "Reset built-ins" = the explicit restore path). Whole-phase 4-seam integration review: DSL round-trip / materialization / ai_fill all CLEAN; caught + FIXED the NPC archetype path being unreachable from the wizard (the SLA-Zero NPC feature Tim called out). SDD process: 10 tasks, every one implementer→adversarial-reviewer gated, controller closed test loops; 2 crash/data-loss classes closed (evaluator recursion T1, seeder overwrite T6). Backlog: custom-template camelCase pick/attr keys get snake_case-mangled on the wire (shipped seeds unaffected — all-caps/lowercase); client-side species-cap resolution for interactive pointbuy (currently auto-assigned); Grange Hill + Meta Alpha templates (Tim deferred); form-based editor v2. See [[tims-rpg-games]]. + +**As of 2026-07-04 BOTH are COMPLETE and pushed.** Backend (HEAD `98a6d4e`, 101/101 tests): full CRUD, JWT auth, MinIO assets, Claude streaming/structured generation, markdown importer, search, session journal, dice + random tables, entity backlinks, plot threads, AI recaps/preps, campaign export, pregen roster, procedural map system (BSP/CA/modern/scifi, top-down + isometric, Universal VTT export), art job queue (A1111 Stable Diffusion + Midjourney bridge) with /ws/jobs. Dev DB seeded with Tim's real gaming history (see [[tims-rpg-games]]). + +**P6.1 CLOUD ART DEPLOYED 2026-07-05** — api `7359632` (380 tests) + mac `3503a88` (231), BOTH LIVE ON PROD (server @ 7359632, keys in prod .env): "openai" + "gemini" providers in the artgen registry (key-presence availability; keys header-only, leak-proof error paths); Mac picker now server-driven. BOTH PROVEN e2e on local AND prod (real PNGs via forge.timevans.uk; OpenAI ~4¢/img gpt-image-1-mini medium; Gemini ~4¢/img gemini-2.5-flash-image). Gemini gotcha: his first "AQ.-prefix" key wasn't a Gemini API key (429) — working key is classic AIza format from AI Studio. Local SD is PAUSED by choice (renders under 16GB memory pressure took 3-12 min and starved the Mac; artgen read-timeout widened to 1800s in d370d3b so slow renders aren't orphaned when he does run it via forge-sd.sh up). MJ: still no official API (2026-07) — subscription/manual only. iPad companion design exploration published (ForgeRPG Table artifact) — kit is iOS-portable (Foundation+Security only), P7 candidate alongside multi-floor maps. + +**PHASE 6 COMPLETE 2026-07-05 (overnight autonomous night shift)** — api `031419b` 364 tests; mac `1982833` 231 tests; both pushed; **PROD REDEPLOY PENDING Tim's "redeploy"** (carries migration `e3aa1ae31d9a` + SSE framing fix — prod content/recap/prep streaming is silently lossy until then). Shipped: map EDITOR (paint cells/stamps/room-renames/annotations over a locked JSONB edits overlay, PATCH regenerates assets so saves are visible, stroke-level undo surviving missed onEnded via @GestureState latch, top-down-only gate), village generator (roads/buildings/wells, zero-rng-when-disabled goldens), library v2 (PC creation, system stat templates from /library/stat-templates, art→portrait flow via single-key PUT), local AI (LM Studio provider `llm:"claude"|"local"` on content/recap/prep + forge-step, /generate/llm-providers), Scenario Forge wizard (5-step: premise→outline→scenes→NPCs/hooks→materialize, all streams editable, offline-capable). CRITICAL CONTRACT: SSE framing is now spec-compliant multi-line — api `_sse_event` splits chunks into per-line `data:` fields; mac streamSSE reassembles events joining with `\n` (NEVER parse SSE via AsyncLineSequence — it swallows the blank-line event boundaries); any new streaming endpoint MUST use `_sse_event`, wire fixtures MUST contain newlines. Fable phase-final review streak now 4/4 real seam bugs (P2 identity bleed, P3 editor swap, P5 status vocab, P6 SSE framing — both suites green on single-line fictions). Backlog in progress.md PHASE 6 COMPLETE entry; multi-floor maps = P7 candidate. + +**PHASE 5 COMPLETE 2026-07-05** (api `392cadf` 227 tests; mac `fe5ff44` 183 tests; prod redeploy PENDING): maps overhaul (preview fit/zoom rebuild — the "empty map" was a 2× viewport illusion; Decor system + furnish/windows/density/decor/water options behind byte-identical goldens; render v2 glyphs/plates/room-numbers+legend; form presets) + WORKING LOCAL ART: A1111 proved broken at core on this Mac (step-count-dependent corruption; diffusers control clean) → replaced by `scripts/forge_sd_server.py` (159-line FastAPI diffusers microserver, same /sdapi/v1/txt2img subset, port 7860, managed by forge-sd.sh; DreamShaper 8 checkpoint at ~/ForgeRPG-sd/webui/models/). Status-vocab seam bug fixed (API pending/processing/complete ≠ Mac queued/running/completed — ingest normalization; BOTH suites had mocked their own fiction). Providers endpoint + honest failure UI + retry. LESSONS: cross-repo contract fixtures must use WIRE values; A1111 is abandonware-fragile on new macOS — diffusers direct is the durable path. PHASE 6 SCOPED (Tim): maps EDITOR (paint/stamps/annotations/village generator), library v2 (rich NPC/PC editors — PC creation flow currently missing, portraits from art studio, system-aware stat templates), Scenario Forge wizard with LOCAL AI via LM Studio (offline con prep). + +**PHASE 4 COMPLETE 2026-07-04** (mac `f16bf28` 168 tests; api `eed7d42` 127 tests): "Arcane Modern" design system (Theme.swift tokens — ember/arcane/ink/rust/wheel, one spring, reduceMotion-gated everywhere, DARK-PINNED — light mode is future work; app must launch via activation-policy fix, unbundled swift-run apps can't focus text fields otherwise), full restyle of chrome/dashboard/editor/tools, LOCAL MODE (api scripts/forge-local.sh + forge-checkout/checkin con scripts with hard size gates + type-PUSH confirm; runbook scripts/README.md), server switcher menu + login quick-picks (KnownServers) + sign-out. GOTCHAS LEARNED: Tim's Mac = light mode (design must pin dark); Tim confused foundry↔forge hostname (quick-picks fix); MJ pipeline scripts NOT on this Mac (RPGS/Stormbringer/scripts empty — stale memory in [[tims-rpg-games]]); prod art providers unconfigured so art jobs fail (Phase 5: local SD install + providers-availability endpoint; Tim chose MJ+SD, rejected OpenAI images). + +**PHASE 3 COMPLETE + DEPLOYED 2026-07-04** (api `1768a14` LIVE on VPS — image rebuilt with reportlab+jinja2, share_links migration `b44e4a01f0c6` applied, foundry/pdf/portal smoke-verified through forge.timevans.uk; mac `ad30af7`, 168 tests). Adds: ⌘K deep-links into scenario/scene (NavigationCoordinator; two identity-reset fixes: `.id(campaign.id)` on dashboard, `.id(scenario.id)` on editor — SwiftUI stores capture ids at init, EVERY in-place swap needs an id reset); field clearing via `clears: Set` on payloads (explicit JSON null; backend exclude_unset semantics); Foundry VTT export (zip of importable journals [GM pages ownership.default=0], actors, walled scenes); con-pack PDF (`/export/pdf`, reportlab); player portal (share tokens, `/portal/{token}` jinja2 pages, handout-tagged assets only, security-reviewed — GM content provably absent); Share menu in dashboard. Polish backlog (12 items) in progress.md ledger. + +**Mac app — Phases 1 + 2 + Amendment A COMPLETE** (HEAD `9ca30b4`, 123/123 tests; backend companion `fa53fb9`, 105 tests, deployed to prod): pure SwiftPM (`swift run ForgeRPG`), zero deps. Full feature set: login/Keychain + server-URL switching (stable injected client, 401→login sheet), campaign browser, scenario/scene markdown editor (GM notes, AI drawer, backlinks Links pane), library (NPCs/locations/factions/pregens), campaign dashboard tabs Scenarios|Sessions|Threads|Prep (journal with AI recaps, plot-thread lifecycle, Lazy-DM prep streaming + save-as-sheet), JSON/Markdown campaign export, dice roller + random tables, maps studio (4 kinds, 3 styles, topdown/iso preview, rerender, PNG + .dd2vtt export), art studio (SD/MJ jobs, live /ws/jobs status, thumbnails), ⌘K search palette (named results). Phase 2 ledger + polish backlog in `.superpowers/sdd/progress.md` (11 recorded non-blocking items; biggest: field-clearing explicit-null amendment, SceneStore flush-on-back, palette deep-links = Phase 3). + +**DEPLOYED 2026-07-04** to VPS root@77.68.99.134 (same box as graphiti/mailu/gitea/nextcloud — scope rule: only touch /opt/forgerpg + compose project `forgerpg`). SSH: this Mac's ed25519 key authorized for root AND tevans. Stack: `/opt/forgerpg/app-src` @ 98a6d4e, `docker compose -p forgerpg -f docker-compose.prod.yml` (server-side compose file; base compose's 9001 MinIO console port couldn't be suppressed by merge override). API on 0.0.0.0:8000, postgres/minio internal-only. Migrations+seed applied; on-box smoke all green. ADMIN_PASSWORD in `.superpowers/sdd/task-9-deploy-report.md` (MacMem). + +**LIVE at https://forge.timevans.uk** (2026-07-04): Tim added the DNS A record and the Caddy vhost (`reverse_proxy 172.18.0.1:8000` — host-gateway style, his edit) himself; real ANTHROPIC_API_KEY loaded; E2E verified from outside (login, 16 campaigns, real Claude SSE generation). Provider firewall keeps 8000/2222 closed externally — all traffic via Caddy 443, which is the intended end state. + +**Ops gotcha (bit us once):** `docker compose restart` does NOT reload `.env` — env is baked at container creation. To apply .env changes: `docker compose -p forgerpg -f /opt/forgerpg/app-src/docker-compose.prod.yml up -d --force-recreate api`. + +**Mac Amendment A (client injection) DONE 2026-07-04** — app is production-ready: one stable SessionStore-owned APIClient (`updateBaseURL` retargets in place, `client` is `let`), zero ad-hoc APIClient() in views, 401 hook survives server switches; 27/27 tests. Commits a380771/f4c635c/6a0dcf4 (+ push once authorized). To use remotely: launch app, set Server URL to https://forge.timevans.uk in the login sheet, admin password from task-9-deploy-report.md. Toolchain gotcha: `swift test` prints two runner summaries — the "0 tests" line is swift-testing; XCTest's real line says "Executed 27 tests". + +**Remaining optional/deferred:** +- Gitea mirror: needs Tim to register this Mac's pubkey in Gitea (gitea.timevans.uk) settings; then push via `-J root@77.68.99.134` jump (external 2222 firewalled). +- Art providers: SD_API_URL → Tailscale URL to his Mac's AUTOMATIC1111; MJ_BRIDGE_CMD → wrapper around `RPGS/Stormbringer/scripts/mj_bridge.py`. +- MinIO creds hardcoded `minioadmin` in compose (internal-network-only exposure; tidy in a future backend amendment). +- V2 sync design decision parked: soft-deletes don't bump sync_version (updated_at auto-bumps via onupdate; backfillable). + +Plan/spec/ledger live in MacMem repo: `docs/superpowers/{plans,specs}/2026-06-29-forgerpg-*.md`, `.superpowers/sdd/progress.md`. diff --git a/memory/projects/projects-MacMem/tims-rpg-games.md b/memory/projects/projects-MacMem/tims-rpg-games.md new file mode 100644 index 0000000..9e5f641 --- /dev/null +++ b/memory/projects/projects-MacMem/tims-rpg-games.md @@ -0,0 +1,20 @@ +--- +name: tims-rpg-games +description: "Tim's tabletop RPG systems, campaigns, and convention GM history (source: iCloud RPGS folder)" +metadata: + node_type: memory + type: user + originSessionId: 93f41ee8-6eaa-4889-8122-80a04dbc4dab +--- + +Tim is a convention GM (UK circuit) and long-time Chaosium player. Source of truth: `~/Library/Mobile Documents/com~apple~CloudDocs/RPGS/`. + +**Systems he runs:** Call of Cthulhu 7e, Basic Roleplaying (BRP), RingWorld, Stormbringer, Pendragon (all Chaosium); Shadowdark, Daggerheart, Mothership, Traveller, SLA Industries. + +**Active campaigns (as of 2026-07):** Beyond the Mountains of Madness (CoC), RingWorld: The Forgotten Engine (custom character sheets + creature/explorer books in progress), Stormbringer Campaign (has the Midjourney Discord-bot art pipeline in `RPGS/Stormbringer/scripts/`). + +**Conventions he GMs at:** Contingency (2020, 2024, 2025, 2026), Airecon (2025, 2026), Continuum 2024, Convulsion 2025, Chaosium Con, plus local games (Worthing 2024, Roll20 online). + +**Past one-offs:** Grange Hill: Boiler Room (homebrew), SLA FL Scenario 1. + +This history is seeded into the [[forgerpg]] app database via `app/seed.py` in ForgeRPG-api (Task 12 of the Phase 1 plan). diff --git a/project-paths.sh b/project-paths.sh new file mode 100644 index 0000000..c0f258b --- /dev/null +++ b/project-paths.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# Shared helpers for install.sh and sync.sh. Sourced, not executed. +# +# Claude Code stores per-project memory at ~/.claude/projects//memory, where +# is the project's absolute path with the path separator replaced by "-". +# The home project ($HOME) syncs into memory/. Any *other* project dir holding +# memory worth keeping is listed below and syncs into memory/projects//. +# +# Entries are relative to $HOME so the list stays portable: "projects/MacMem" +# resolves to -Users-timevans-projects-MacMem on macOS and +# -home-timevans-projects-MacMem on Linux. +EXTRA_PROJECT_PATHS=( + "projects/MacMem" + "Git" +) + +# Encode an absolute path into the key Claude Code uses for its project dir. +# macOS (/Users/x -> -Users-x) and Linux (/home/x -> -home-x) encode the POSIX path. +# On Windows, Claude Code sees the native path, so C:\Users\x -> C--Users-x. Git Bash +# reports /c/Users/x, which would encode to the wrong key -- convert first. +project_key_for() { + if command -v cygpath >/dev/null 2>&1; then + # sed, not bash substitution: a lone "\" in a glob pattern escapes the next + # char instead of matching a literal backslash. + cygpath -w "$1" | sed 's/[\\:]/-/g' + else + echo "${1//\//-}" + fi +} + +# Repo-side folder name for an entry in EXTRA_PROJECT_PATHS. +project_slug_for() { + echo "${1//\//-}" +} diff --git a/settings.json b/settings.json index 04cbb7e..ef78095 100644 --- a/settings.json +++ b/settings.json @@ -11,7 +11,78 @@ "Bash(mj-capture-command *)", "Bash(/Users/timevans/bin/mj-gen *)", "Bash(/Users/timevans/bin/mj-auth-check *)", - "Bash(/Users/timevans/bin/mj-capture-command *)" + "Bash(/Users/timevans/bin/mj-capture-command *)", + "Read", + "Edit", + "Write", + "Glob", + "Grep", + "Bash(git status)", + "Bash(git diff)", + "Bash(git log)", + "Bash(git add )", + "Bash(git commit )", + "Bash(git push)", + "Bash(git pull)", + "Bash(git branch)", + "Bash(git checkout )", + "Bash(git stash)", + "Bash(git fetch)", + "Bash(npm run )", + "Bash(npm install)", + "Bash(npm test)", + "Bash(npm ci)", + "Bash(npx )", + "Bash(node )", + "Bash(ls)", + "Bash(dir)", + "Bash(mkdir )", + "Bash(mv )", + "Bash(cp )", + "Bash(touch )", + "Bash(cat )", + "Bash(head )", + "Bash(tail )", + "Bash(wc )", + "Bash(find )", + "Bash(grep )", + "Bash(sort )", + "Bash(uniq )", + "Bash(diff )", + "Bash(which )", + "Bash(where )", + "Bash(echo )", + "Bash(pwd)", + "Bash(cd )", + "Bash(type )", + "Bash(file )", + "Bash(whoami)", + "Bash(hostname)", + "Bash(date)", + "Bash(yarn )", + "Bash(pnpm )", + "Bash(python )", + "Bash(python3 )", + "Bash(pip )", + "Bash(pip3 )", + "Bash(cargo )", + "Bash(go )", + "Bash(dotnet )" + ], + "deny": [ + "Bash(rm -rf )", + "Bash(rm -r )", + "Bash(rmdir /s)", + "Bash(del /s)", + "Bash(sudo )", + "Bash(chmod 777)", + "Bash(format )", + "Read(.env)", + "Read(**/.env)", + "Read(**/.env.*)", + "Read(**/credentials*)", + "Read(**/*.pem)", + "Read(**/*.key)" ] }, "model": "opus", @@ -24,6 +95,7 @@ "feature-dev@claude-plugins-official": true, "huggingface-skills@claude-plugins-official": true, "amazon-location-service@claude-plugins-official": true, + "swift-lsp@claude-plugins-official": true, "ui-ux-pro-max@ui-ux-pro-max-skill": true, "impeccable@impeccable": true }, @@ -60,5 +132,6 @@ "preferredNotifChannel": "terminal_bell", "autoUpdaterStatus": "enabled", "agentPushNotifEnabled": true, - "inputNeededNotifEnabled": true + "inputNeededNotifEnabled": true, + "skipWorkflowUsageWarning": true } diff --git a/sync.sh b/sync.sh index a27bc0d..1ca7a51 100755 --- a/sync.sh +++ b/sync.sh @@ -6,17 +6,9 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CLAUDE_DIR="$HOME/.claude" -# Claude Code encodes the project dir by replacing the path separator with "-". -# macOS (/Users/x -> -Users-x) and Linux (/home/x -> -home-x) encode the POSIX $HOME. -# On Windows, Claude Code sees the native path, so C:\Users\x -> C--Users-x. Git Bash -# reports $HOME as /c/Users/x, which would encode to the wrong key -- convert first. -if command -v cygpath >/dev/null 2>&1; then - # C:\Users\x -> C--Users-x (sed, not bash substitution: a lone "\" in a glob - # pattern escapes the next char instead of matching a literal backslash). - PROJECT_KEY="$(cygpath -w "$HOME" | sed 's/[\\:]/-/g')" -else - PROJECT_KEY="${HOME//\//-}" -fi +# shellcheck source=project-paths.sh +source "$SCRIPT_DIR/project-paths.sh" +PROJECT_KEY="$(project_key_for "$HOME")" MEMORY_DIR="$CLAUDE_DIR/projects/${PROJECT_KEY}/memory" MSG="${1:-sync config}" @@ -37,8 +29,27 @@ else echo " Warning: no memory files found at $MEMORY_DIR — skipping" fi +# Extra per-project memory dirs (see project-paths.sh). A machine that lacks one +# of these projects skips it, leaving the repo copy intact — never deletes it. +for rel in "${EXTRA_PROJECT_PATHS[@]}"; do + src="$CLAUDE_DIR/projects/$(project_key_for "$HOME/$rel")/memory" + slug="$(project_slug_for "$rel")" + if [ -d "$src" ] && ls "$src"/*.md &>/dev/null; then + mkdir -p "$SCRIPT_DIR/memory/projects/$slug" + rm -f "$SCRIPT_DIR/memory/projects/$slug/"*.md + cp "$src/"*.md "$SCRIPT_DIR/memory/projects/$slug/" + echo " Copied: memory/projects/$slug/" + else + echo " Skipped: memory/projects/$slug/ — not present on this machine" + fi +done + if [ -d "$CLAUDE_DIR/skills" ]; then - rsync -a --delete "$CLAUDE_DIR/skills/" "$SCRIPT_DIR/skills/" + # --no-links: skills installed by other tools (firecrawl, composio) are symlinks + # into ~/.agents/skills. Copying them as symlinks would commit links that dangle + # on every other machine; dereferencing them would vendor someone else's skills. + # Only real skill directories belong in this repo. + rsync -a --delete --no-links "$CLAUDE_DIR/skills/" "$SCRIPT_DIR/skills/" echo " Copied: skills/" fi