add per-project memory sync; merge settings from MacBook Air

This commit is contained in:
slaguru666
2026-08-04 21:35:55 +01:00
parent 36a3fce55c
commit 10ed882e25
11 changed files with 475 additions and 25 deletions
+14 -11
View File
@@ -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"
+36
View File
@@ -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
+90
View File
@@ -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)
+116
View File
@@ -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-<topic>-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-<feature>.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/<branch-name>/`)
- 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
@@ -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
@@ -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 `<sub>.timevans.uk { reverse_proxy <app>: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.
@@ -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<String>` 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`.
@@ -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).
+34
View File
@@ -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/<KEY>/memory, where
# <KEY> 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/<slug>/.
#
# 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//\//-}"
}
+75 -2
View File
@@ -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
}
+23 -12
View File
@@ -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