add per-project memory sync; merge settings from MacBook Air
This commit is contained in:
+14
-11
@@ -8,17 +8,9 @@ set -euo pipefail
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
CLAUDE_DIR="$HOME/.claude"
|
CLAUDE_DIR="$HOME/.claude"
|
||||||
USERNAME=$(whoami)
|
USERNAME=$(whoami)
|
||||||
# Claude Code encodes the project dir by replacing the path separator with "-".
|
# shellcheck source=project-paths.sh
|
||||||
# macOS (/Users/x -> -Users-x) and Linux (/home/x -> -home-x) encode the POSIX $HOME.
|
source "$SCRIPT_DIR/project-paths.sh"
|
||||||
# On Windows, Claude Code sees the native path, so C:\Users\x -> C--Users-x. Git Bash
|
PROJECT_KEY="$(project_key_for "$HOME")"
|
||||||
# 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
|
|
||||||
MEMORY_DIR="$CLAUDE_DIR/projects/${PROJECT_KEY}/memory"
|
MEMORY_DIR="$CLAUDE_DIR/projects/${PROJECT_KEY}/memory"
|
||||||
|
|
||||||
echo "Installing Claude config for user: $USERNAME"
|
echo "Installing Claude config for user: $USERNAME"
|
||||||
@@ -40,6 +32,17 @@ mkdir -p "$MEMORY_DIR"
|
|||||||
cp "$SCRIPT_DIR/memory/"*.md "$MEMORY_DIR/"
|
cp "$SCRIPT_DIR/memory/"*.md "$MEMORY_DIR/"
|
||||||
echo " Installed: memory files -> $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/
|
# Skills — copy each skill directory into ~/.claude/skills/
|
||||||
if [ -d "$SCRIPT_DIR/skills" ]; then
|
if [ -d "$SCRIPT_DIR/skills" ]; then
|
||||||
mkdir -p "$CLAUDE_DIR/skills"
|
mkdir -p "$CLAUDE_DIR/skills"
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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)
|
||||||
@@ -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).
|
||||||
@@ -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
@@ -11,7 +11,78 @@
|
|||||||
"Bash(mj-capture-command *)",
|
"Bash(mj-capture-command *)",
|
||||||
"Bash(/Users/timevans/bin/mj-gen *)",
|
"Bash(/Users/timevans/bin/mj-gen *)",
|
||||||
"Bash(/Users/timevans/bin/mj-auth-check *)",
|
"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",
|
"model": "opus",
|
||||||
@@ -24,6 +95,7 @@
|
|||||||
"feature-dev@claude-plugins-official": true,
|
"feature-dev@claude-plugins-official": true,
|
||||||
"huggingface-skills@claude-plugins-official": true,
|
"huggingface-skills@claude-plugins-official": true,
|
||||||
"amazon-location-service@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,
|
"ui-ux-pro-max@ui-ux-pro-max-skill": true,
|
||||||
"impeccable@impeccable": true
|
"impeccable@impeccable": true
|
||||||
},
|
},
|
||||||
@@ -60,5 +132,6 @@
|
|||||||
"preferredNotifChannel": "terminal_bell",
|
"preferredNotifChannel": "terminal_bell",
|
||||||
"autoUpdaterStatus": "enabled",
|
"autoUpdaterStatus": "enabled",
|
||||||
"agentPushNotifEnabled": true,
|
"agentPushNotifEnabled": true,
|
||||||
"inputNeededNotifEnabled": true
|
"inputNeededNotifEnabled": true,
|
||||||
|
"skipWorkflowUsageWarning": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,9 @@ set -euo pipefail
|
|||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
CLAUDE_DIR="$HOME/.claude"
|
CLAUDE_DIR="$HOME/.claude"
|
||||||
# Claude Code encodes the project dir by replacing the path separator with "-".
|
# shellcheck source=project-paths.sh
|
||||||
# macOS (/Users/x -> -Users-x) and Linux (/home/x -> -home-x) encode the POSIX $HOME.
|
source "$SCRIPT_DIR/project-paths.sh"
|
||||||
# On Windows, Claude Code sees the native path, so C:\Users\x -> C--Users-x. Git Bash
|
PROJECT_KEY="$(project_key_for "$HOME")"
|
||||||
# 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
|
|
||||||
MEMORY_DIR="$CLAUDE_DIR/projects/${PROJECT_KEY}/memory"
|
MEMORY_DIR="$CLAUDE_DIR/projects/${PROJECT_KEY}/memory"
|
||||||
MSG="${1:-sync config}"
|
MSG="${1:-sync config}"
|
||||||
|
|
||||||
@@ -37,8 +29,27 @@ else
|
|||||||
echo " Warning: no memory files found at $MEMORY_DIR — skipping"
|
echo " Warning: no memory files found at $MEMORY_DIR — skipping"
|
||||||
fi
|
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
|
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/"
|
echo " Copied: skills/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user