From 36a3fce55c170a99f8a872cc107ea603e96baa61 Mon Sep 17 00:00:00 2001 From: slaguru666 <111923774+slaguru666@users.noreply.github.com> Date: Sat, 1 Aug 2026 05:50:05 +0100 Subject: [PATCH] auto sync --- memory/MEMORY.md | 8 + memory/afterimage-scenario.md | 21 + memory/blueprint-news.md | 54 +++ memory/canvas_oss_course.md | 22 + memory/clipsync.md | 30 ++ memory/gmtool-director.md | 40 ++ memory/mapwright-module.md | 28 ++ memory/midjourney_bridge.md | 23 + memory/princes-bride-scenario.md | 17 + memory/rpg-skill.md | 17 + settings.json | 4 +- skills/notebooklm/SKILL.md | 660 ---------------------------- skills/rpg/references/lessons.md | 55 --- skills/rpg/references/production.md | 28 -- 14 files changed, 263 insertions(+), 744 deletions(-) create mode 100644 memory/afterimage-scenario.md create mode 100644 memory/blueprint-news.md create mode 100644 memory/canvas_oss_course.md create mode 100644 memory/clipsync.md create mode 100644 memory/gmtool-director.md create mode 100644 memory/mapwright-module.md create mode 100644 memory/princes-bride-scenario.md create mode 100644 memory/rpg-skill.md delete mode 100644 skills/notebooklm/SKILL.md diff --git a/memory/MEMORY.md b/memory/MEMORY.md index c5b5c4b..0206d1b 100644 --- a/memory/MEMORY.md +++ b/memory/MEMORY.md @@ -2,7 +2,15 @@ - [Midjourney bridge](midjourney_bridge.md) — `mj-gen ""` drops a PNG on disk; full pipeline via Discord, no MJ API needed. - [GitHub account](user_github.md) — username: slaguru666; 19 repos, mostly SLA Industries Foundry VTT modules. +- [The Director (gmtool)](gmtool-director.md) — offline convention GM tablet PWA; Slices 1–5 done, all six Continuum 2026 slots ported + scheduled. - [Semaphore Gitea URL](feedback_semaphore_gitea_url.md) — use `http://gitea:3000/tevans/.git` inside Semaphore, not the external Cloudflare URL +- [Canvas OSS course](canvas_oss_course.md) — Canvas test server canvas.timevans.uk + `~/gema-oss-canvas-course/` idempotent course-builder (pin account id 1). +- [Mapwright module](mapwright-module.md) — new standalone Foundry v13 battle-map generator at `~/FoundryVTT/Data/modules/mapwright/`; procedural-vector, buildings-first, one-geometry-model design. +- [Blueprint News](blueprint-news.md) — engine-agnostic SLA BPN briefing generator at `~/blueprint-news/`; reusable component + standalone app, seeded procedural SVG art, Player/GM split, NPC seam for a separate module. +- [clipsync](clipsync.md) — CouchDB-backed clipboard history for the Macs; `clipsync-setup` to install, `clip` to browse. +- [AFTERIMAGE scenario](afterimage-scenario.md) — 4-player Blade Runner game for Continuum 2026, Fri 24 July, Slot 2; repo slaguru666/Continuum2026; convention-ready. +- [Princes Bride scenario](princes-bride-scenario.md) — Dee Sanction game for Continuum 2026, Sun 26 July, Slot 7; reconciled canon + real rules (ignore old quick-ref); convention-ready. +- Continuum 2026 slate complete in slaguru666/Continuum2026: Day One (Fri S1), AFTERIMAGE (Fri S2), Vain Crown (Sat S4), Another Fine Mess — Pulp Cthulhu chopper sequel (Sun S6), Princes Bride (Sun S7). - [Plugin sync](project_plugin_sync.md) — keep Claude Code plugins identical across all servers via the claude-config repo (settings.json enabledPlugins); run sync.sh after install/remove - [MINI-S remote access](infra_minis_remote_access.md) — timevans-MINI-S: static 192.168.1.6, key-only SSH + fail2ban, Zyxel DX3301-T0 port-forward 2222->22 (Voneus) - [MINI-S Docker stacks](infra_minis_docker_stacks.md) — homelab (Portainer/Gitea/Obsidian/Stirling-PDF/Nextcloud) + Seafile cloud drive; ports, data paths, secrets locations diff --git a/memory/afterimage-scenario.md b/memory/afterimage-scenario.md new file mode 100644 index 0000000..20602f8 --- /dev/null +++ b/memory/afterimage-scenario.md @@ -0,0 +1,21 @@ +--- +name: afterimage-scenario +description: AFTERIMAGE — 4-player Blade Runner scenario for CONTINUUM 2026, Friday 24 July, Slot 2 (20:00–00:00); repo slaguru666/Continuum2026 (private) +metadata: + node_type: memory + type: project + originSessionId: 445b61b6-6e68-4f8e-8caa-28bf213400e9 + modified: 2026-07-19T10:56:54.351Z +--- + +AFTERIMAGE is the Blade Runner RPG scenario for **Continuum 2026** (continuumconvention.co.uk, Cranfield), **Friday 24 July 2026, Slot 2 = 20:00–00:00**, 4 players. *(Corrected 2026-07-19: it was originally mis-filed under Contingency 2026 Wed Slot 3 — the old repo `Contingency26` is now a pointer stub.)* Chamber-noir: memory designer Elias Kade dead; three replicant copies of his estranged daughter Aris; the real Aris may or may not have killed him — ambiguity is by design and must not be resolved by dice. Foot chase in Act Two (night market); duplicated key-memory monologue handout (print F2-H02-A twice) is the core reveal. + +Locations: private GitHub repo `slaguru666/Continuum2026` (full history); local copy at `.../RPGS/Conventions/Continuum 2026/01 Friday/Slot 2 Evening Blade Runner/AFTERIMAGE/`. Asset IDs are `F2-*`; scenario file is `scenarios/fri-slot2-blade-runner-afterimage.md`. + +Also in the repo: **REP-DETECT GM Console** (`gm-utility/index.html`) — Tim's touch-screen Blade Runner GM app; offline single-file HTML, localStorage per module + JSON export, animated idle screen (film-style Spinner + live rain), scenario modules via `BRGM.registerModule()` in `gm-utility/modules/` (AFTERIMAGE included). To add a scenario: new module JS + a script tag in index.html. + +Status (v2.3+, convention-ready): three desk playtests (GM chair, Act Two stress, player chair), three endings, all inside 3:30; art complete (F2-ART-01..06 + app art); PDFs exported with Continuum branding; only physical prep remains (print sheets/handouts — monologue card ×2 — and Tim's read-through). Cosmetic playtest findings 6–9 still open. + +Continuity anchors (Tim-requested audit; he's had date/name errors in past scenario work — always audit these): Aris b. 1998, pier memory 2007 (age 9), adult (33) at the 2031 callout, off-grid 2031 (= six years in 2037); Kade at Tyrell 2009–2022, gap, Wallace 2028–2031; death Wed 23:40, found Fri 10:15 (~35 hrs); **Sloane is a Nexus-9, serial SN9-1.11, 12 months** (not N8); Kael's examiner is Dr. Imani Okafor; Sloane's bakery is Castellano & Sons. + +Portrait art mapping (art also copied into the repo): true portraits are `Rick.png`, `JAX copy ZOOM.png`, `KAEL copy.png`, `SLONE Zoom.png`; the `* Trans` PNGs are sheet scans, not portraits. Related: [[mapwright-module]], [[user_github]]. diff --git a/memory/blueprint-news.md b/memory/blueprint-news.md new file mode 100644 index 0000000..2b89174 --- /dev/null +++ b/memory/blueprint-news.md @@ -0,0 +1,54 @@ +--- +name: blueprint-news +description: Engine-agnostic SLA BPN briefing generator at ~/blueprint-news/ (component + standalone app) +metadata: + node_type: memory + type: project + originSessionId: 5042e85b-5232-4f59-bf1d-92d635c764de +--- + +"Blueprint News" — a new **engine-agnostic** SLA Industries BPN (Blue Print News) +mission-briefing generator at `~/blueprint-news/`. Rebuild of the earlier +Foundry-bound experiments with every engine call stripped out. + +Shape: a framework-free ES-module **component** + a standalone web **app** built on it. +- `core/` — `generateBPN({seed,colourKey,frameId,squadSize,overrides})`, deterministic; `data/` colours, frames, tables. +- `art/bpn-art.js` — seeded procedural SVG (`crestSVG`, `bannerSVG`): flat stencil/propaganda SLA style, never photorealistic. Seed drives the art. +- `render/` — `briefHTML()` (Player Brief) + `dossierHTML()` (GM Dossier), scoped under `.bpn`; responsive + print CSS. +- `assets/fonts/` — bundled local Josefin Sans + Roboto Mono + Modesto Condensed. +- `app/` + `index.html` — generator UI: Player/GM/Both, library (localStorage), Print, Export HTML. + +Two **separate surfaces** per briefing: Player Brief (official dispatch) vs GM Dossier +(twist, withheld fact, true threat read, levers, dice state). + +NPC/monster generation is a **separate future module** — each briefing exposes +`bpn.npcSeam {contactArchetype, threatArchetype, threatRole}` as the hand-off seam. + +Per-band art: `art/bpn-art.js` `SCENES` map drives distinct foreground motifs +(tunnel/transit/wall/cordon/gantry/stage/canal/tower/vault/exec) + atmosphere/lighting; +`portraitSVG()` gives a halftone non-photorealistic contact ident in the Player Brief. + +Published PUBLIC at https://github.com/slaguru666/blueprint-news (default branch `master`). +GitHub **MCP is not authenticated** here — use the `gh` CLI (logged in as slaguru666) for pushes. + +**Zero Engine variant**: separate module **Blueprint News 0 Engine** (id `sla-blueprint-news-zero`) +at `~/FoundryVTT/Data/modules/sla-blueprint-news-zero/`, repo https://github.com/slaguru666/sla-blueprint-news-zero (v0.5.0). +Superset of the base module that, in a `zero-engine` world, also spawns real Zero Engine `npc` +actors on Create — a threat group (leader + mooks: gangs/Carrien/corpsec/Stormer/black-ops) + cast — +with attributes, HP, armour, damage, threat and embedded weapons, replicating the system's own NPC +Creator (`SLA_NPC_TYPES`/`_slaWeaponData` in systems/zero-engine). Logic in `module/zero-adapter.mjs`. +De-collided (global `game.slaBlueprintNewsZero`) so it coexists with the base module. Original +module backed up to `sla-blueprint-news-backup-20260617-185229.tar.gz`. Not load-tested in Foundry yet. + +**Foundry module** (the installable deliverable): `sla-blueprint-news` at +`~/FoundryVTT/Data/modules/sla-blueprint-news/`, ApplicationV2 generator (idiom from +mapwright), vendors the component under `module/vendor/`, writes one JournalEntry with a +player **Mission Brief** page (Observer) + GM-only **Dossier** page (None). Uses render +`artMode:"img"` so Foundry doesn't strip inline SVG. Published at +https://github.com/slaguru666/sla-blueprint-news (release v0.1.0); remote install manifest: +`https://raw.githubusercontent.com/slaguru666/sla-blueprint-news/main/module.json`. +Not yet load-tested in a running Foundry world. + +Source aesthetic/palette/fonts come from `~/FoundryVTT/Data/systems/sla-industries-brp`. +Run with any static server (ES modules need HTTP); `.claude/launch.json` serves it on :8778. +Related: [[mapwright-module]]. diff --git a/memory/canvas_oss_course.md b/memory/canvas_oss_course.md new file mode 100644 index 0000000..580622a --- /dev/null +++ b/memory/canvas_oss_course.md @@ -0,0 +1,22 @@ +--- +name: canvas-oss-course +description: Canvas LMS test server details + the idempotent course-builder tool for the Omnissa Sovereign Solution training +metadata: + node_type: memory + type: project + originSessionId: 2eafb1c4-b851-441d-b039-2189d5d33699 +--- + +Canvas LMS test server under evaluation: `https://canvas.timevans.uk` (web admin `admin@timevans.uk`; host SSH `tevans@77.68.99.134`; Canvas runs as a container). + +Built a repeatable, idempotent Canvas-REST-API course builder at `~/gema-oss-canvas-course/`: +- `build_course.py` (CLI: `--check`, `--verify`, `--fresh`), `course_content.py` (curriculum as data), `README.md`. +- Config in `config.env` (git-ignored): `CANVAS_BASE_URL`, `CANVAS_API_TOKEN`, `CANVAS_ACCOUNT_ID`. + +Course built = id **4**: "Implementing the Omnissa Sovereign Solution - Engineer Onboarding" (OSS-ENG-101). 11 modules / 41 items (21 pages, 9 classic quizzes/37 questions, 7 labs + capstone, 4 discussions). + +**Gotchas:** admin is a Site Admin, so `/accounts` lists "Site Admin" (id 2) first — pin `CANVAS_ACCOUNT_ID=1` ("Tim Evans Canvas", the real institution root; sub-account 3 = "Manually-created courses"). Classic quizzes must be created unpublished → add questions → publish. **File upload is broken on this server** — `/files_api` returns 500 — and the HTML sanitizer strips data-URI images, but it KEEPS inline CSS incl. `linear-gradient` (drops `letter-spacing`). So visual styling = CSS gradient hero banners + callout panels rendered inline, not uploaded images (`art_gen.py` PNGs remain for if upload is ever fixed). `--fresh` deletes+recreates so course id increments each rebuild; latest is **course id 6** (default_view=syllabus). + +Subject ties to the [[gema-training-ideas]] project: Omnissa Sovereign Solution = Workspace ONE UEM delivered with GEMA as regional hosting/support partner, with BYOK + Desired State Management as sovereignty controls. + +**Security:** the access token used was shared in chat — rotate it in Canvas after evaluation. diff --git a/memory/clipsync.md b/memory/clipsync.md new file mode 100644 index 0000000..6711093 --- /dev/null +++ b/memory/clipsync.md @@ -0,0 +1,30 @@ +--- +name: clipsync +description: "CouchDB-backed clipboard history for the user's Macs — daemon, picker, setup." +metadata: + node_type: memory + type: project + originSessionId: 3c4e91f6-6e5f-4674-b5e0-413eb9e499ff +--- + +`clipsync` syncs macOS clipboard history into a remote CouchDB so it's shared across Macs. + +- Obsidian vault files (2026-06-21): import now includes non-`.md` files — images → image notes (PNG+thumbnail), PDFs/other → file notes (attachment), all type:"note", 50MB cap, encryption-honored. App `NoteImport.obsidianDocs`+`Store.importObsidianVault`; CLI parity. (Earlier obsidian import was .md-only.) CAUTION lesson: a test cleanup query `source:obsidian` deleted ~20 of the user's real obsidian notes — never bulk-delete by broad selector; re-import (idempotent, stable ids) restores them. +- Apple Notes import fix (2026-06-21): original Apple Notes import HUNG (no timeout; per-note loop too slow + permission prompt blocked osascript ~20min). Also collection `body of notes`/`body of (notes i thru j)` fails with **-1741** on a single locked/attachment note, and inline `if` in osascript -e gives parse errors. Working approach: fetch **names in bulk** (`(name of notes) as text`, ~0.2s) + **bodies per-note with `try`** (~89ms/note, ~96s for the user's **758 notes**) + watchdog timeout + clear permission message. Fixed in app `Import.swift` (`NoteImport.appleNotes` + `run()` helper) and the `macmem-import` CLI. Imported all 758 of the user's Apple Notes into CouchDB (type:note). Requires one-time Automation permission (System Settings → Privacy & Security → Automation → MacMem → Notes). +- Note import (2026-06-21): `bin/macmem-import` (uv CLI) imports Obsidian (vault `.md`, folders→tags), Evernote (`.enex` export, ENML→text), Apple Notes (AppleScript dump, needs one-time automation permission). Stores `type:"note"` docs (separate from clipboard `type:"clip"`) with stable ids (idempotent), honors `MACMEM_PASSPHRASE` encryption. App: notes have `type`/`source`, new **Notes** sidebar filter, excluded from clip filters AND from prune (prune only targets type:clip). MCP: `list_notes`/`search_notes` tools + `source` in summaries. Verified Obsidian+Evernote + MCP note tools end-to-end. +- Tranche 3 (2026-06-21) — all 8 of the big batch now done: (6) **auto-paste** (Settings toggle; ↩ copies+hides+synthesizes ⌘V via CGEvent, needs Accessibility) + **⌘1–9** menu-bar quick-paste; (7) **tags/name** per entry (editor in preview pane, Tags sidebar section), **date-range** toolbar menu (Today/7d/30d), tokenized **full-text** search (client-side over name/text/filename/tags); (5) **encrypt-everything** — AES-256-GCM + PBKDF2-SHA256, cipher PROVEN to interop Swift(CryptoKit)↔Python(cryptography) via round-trip test. New clips (text→`enc`, image thumb+`full.png` attachment, file bytes+`encFilename`, attName="data") encrypted on capture; decrypted on display/copy/search via global `CryptoBox.key`. Shared salt+check in `macmem-crypto` doc so every Mac derives same key from the passphrase; passphrase set in Settings, key cached in Keychain (service `-key`). Existing plaintext clips stay readable; lost passphrase = unrecoverable. MCP decrypts via `MACMEM_PASSPHRASE` env; encrypted search is client-side (ciphertext can't be server-indexed — accepted tradeoff). Files: `app/Sources/MacMem/{Crypto,Paste}.swift`. Verified encryption end-to-end via MCP (with/without passphrase). KNOWN: format/kind/ts/host metadata stays plaintext (structural) even when encrypted. +- Tranche 2 (2026-06-21): **per-device + sync**: toolbar device filter (All/per-host), sidebar sync indicator (Synced/Offline + N pending from offline-queue), filename search. **Signing**: `build-app.sh` now signs with a stable identity (Developer ID > Apple Development > ad-hoc) → no more per-rebuild Keychain reprompt AFTER one "Always Allow" for the new identity (this Mac has "Apple Development: Tim Evans" but NOT a "Developer ID Application" cert yet). `app/package-dmg.sh` + `app/MacMem.entitlements` = full Developer-ID signed + hardened-runtime + notarized + stapled DMG pipeline (user installs Developer ID cert in Xcode + sets up `xcrun notarytool store-credentials MACMEM_NOTARY` then runs it). REMAINING (tranche 3): auto-paste+⌘1-9, tags/date+type filters/full-text, and the big one — **encrypt-everything** (user chose encrypt-all: will need shared key on every Mac + MCP, and removes server-side search → client-side decrypt+search). Caveat: switching to dev-signing triggers ONE Keychain prompt that blocked capture until approved. +- Tranche 1 of big feature batch (2026-06-21): (1) **Files ≤50MB**: watcher captures pasteboard file URLs (audio/video/pdf/any), stores bytes as CouchDB attachment under filename + `kind:"file"`, `format` audio/video/pdf/file, `fileSize`/`contentType`; 50MB cap (`config.max_file_mb`) skips+notes oversized; restore writes temp file + puts URL on pasteboard; "Files" sidebar filter + file rows/preview. (2) **Storage**: `Couch.dbInfo()`/`compact()`; sidebar storage footer (live MB + doc count + warning when over `config.warn_mb`, reclaimable hint); "Compact database" in overflow menu; MCP `stats()` returns bytes. (3) **HTTP MCP transport**: `macmem_mcp.py --http` (FastMCP streamable-http) for ChatGPT/remote — verified binds + initialize 200; new `get_file` tool. All verified via CouchDB/MCP CLI + UI screenshot. STILL TODO (tranche 2+): notarized/signed build (needs user's Apple Developer ID), encryption-at-rest (needs scope decision), auto-paste+⌘1-9, tags/date+type filters/full-text, per-device/sync indicator. +- MCP server + UI redesign + index (2026-06-21): **MCP server** at `mcp/macmem_mcp.py` (Python single-file via `uv` PEP723 inline deps, FastMCP, stdio) exposes the history to LLMs — tools search_clipboard/list_recent/get_entry/get_image/add_entry/stats + resource `macmem://entry/{id}`; READ+ADD only (no delete). Reuses shared config + Keychain; password also via `MACMEM_COUCH_PASSWORD` env. Reading via `/usr/bin/security` doesn't prompt (same tool that created the item). Register: `mcp/register-claude.sh` → `claude mcp add macmem -- uv run --script .../macmem_mcp.py` (a config change — left for user to run). **Index system**: `Couch.ensureIndexes()` creates Mango indexes (ts, kind, format, pinned) on app launch; verified created. Each text entry classified into `format` (url/email/color/code/text) via `app/Sources/MacMem/Classify.swift`. **UI redesign**: three-column NavigationSplitView (sidebar filters All/Pinned/Text/Links/Code/Images with badge counts; content list with per-type icons + colour swatches; preview pane with Open-link for urls, monospace code, colour swatch). Verified on screen. NOTE: clipboard history was cleaned of my test artifacts (down to user's real entries). +- Polish/features (2026-06-21): app icon (AppKit-generated `app/generate-icon.swift` → MacMem.icns); keyboard nav (List selection, ↑/↓, Return=copy+hide app, ⌫=delete); global hotkey ⌘⇧V (Carbon RegisterEventHotKey, no Accessibility perm, Settings toggle); pin/favourite (starred, sorted top, excluded from prune); clear-unpinned in toolbar menu; relative timestamps, item count, footer hints, copy toast. Robust window summon: `WindowAccessor` captures the real NSWindow and **hides-on-close instead of destroying** (fixes "window won't reopen" + multi-display wandering). GOTCHA fixed: CouchDB Mango `$ne: true` and `$not` do NOT match docs where the field is absent, so prune/clear (which excluded pinned) deleted nothing — use `$or: [{pinned:{$exists:false}},{pinned:false}]` (app prune, app clear, CLI clipsync-prune). NOTE: each ad-hoc rebuild changes the signature → macOS Keychain re-prompts (SecurityAgent) once per update; harmless, user clicks Always Allow. +- Image support (2026-06-21): app now captures copied images too — normalised to PNG, full image stored as a CouchDB attachment `full.png` + a small inline base64 `thumb` (120px) in the doc (`kind:"image"`, with `w`/`h`). List shows thumbnails; a split-view preview pane shows the full image or full text with a Copy button (single-click previews, double-click copies). Image dedup via SHA-256; self-copy guard is `ignoreCurrentPasteboard`. CLI `clip` labels image rows but can't copy them (app-only). Helpers in `app/Sources/MacMem/ImageUtils.swift`. +- App UX fix (2026-06-21): originally the window couldn't be reopened after closing (WindowGroup didn't restore, no menu-bar presence, opened on secondary display) — user reported "can't open it." Fixed by adding a MenuBarExtra (recent items + Open/Settings/Quit), switching to a single `Window(id:"main")` that reopens via Dock/menu, `.defaultPosition(.center)`, and a window-independent refresh timer in AppState. Capture itself was always working. +- **Mac app** (`app/` in repo): self-contained SwiftUI window app `MacMem.app` (installed in /Applications) that captures the clipboard itself AND shows searchable/clickable history. Built via SwiftPM + `app/build-app.sh` (ad-hoc signed, no Xcode; macOS 14+). Reuses `~/.config/clipsync/config.json` + Keychain; in-app Settings (⌘,) for connection + launch-at-login. On the Mini the launchd capture+prune agents were RETIRED (moved to `~/.config/clipsync/retired-agents/`) so the app is the sole capturer — don't run both. CLI `clip` picker still works as an alternate reader. +- GitHub: **private** repo `slaguru666/MacMem` (https://github.com/slaguru666/MacMem). Clean source-of-truth at `~/MacMem` (git, origin set). Per-Mac install: `git clone … && ./install.sh` then `clipsync-setup`. No secrets committed (example config uses couchdb.example.com; `.gitignore` excludes config.json/offline-queue/logs/binary). + +- Remote: `couchdb.timevans.uk`, db `macmem`, user `macmem`. Password in login Keychain (service `clipsync-couchdb`), never on disk. +- Code in `~/bin`: `clip-watch` (compiled Swift `NSPasteboard` watcher, source `clip-watch.swift`), `clipsync` (stdlib-Python daemon, offline queue), `clip` (fzf picker → `pbcopy`), `clipsync-prune` (retention), `clipsync-setup` (Keychain + DB + ts index + launchd bootstrap). +- Config/lib/README in `~/.config/clipsync/`. launchd: `uk.timevans.clipsync` (KeepAlive), `uk.timevans.clipsync-prune` (daily 04:30). Logs `~/Library/Logs/clipsync.log`. +- Doc shape: `{_id:-, type:clip, text, host, ts}`. Skips concealed/transient pasteboard types, length bounds, `deny_patterns` regex. +- No PyObjC in any local Python (system 3.9 / brew 3.14 / venv) → Swift used for pasteboard access. +- Per-Mac install: copy `~/bin/clip*`, `~/bin/clipsync*`, `~/.config/clipsync/`, then run `clipsync-setup`. diff --git a/memory/gmtool-director.md b/memory/gmtool-director.md new file mode 100644 index 0000000..dad5486 --- /dev/null +++ b/memory/gmtool-director.md @@ -0,0 +1,40 @@ +--- +name: gmtool-director +description: "The Director" — offline-first convention GM tablet app (repo slaguru666/gmtool) +metadata: + type: project +--- + +**The Director** (repo `slaguru666/gmtool`, package name `gm-director`) — an offline-first PWA +for running tabletop RPG sessions at conventions. Vanilla ES modules + Web Components (light DOM) +over pure, deterministic core logic (injected `now`/`rng`); Vite + Vitest/jsdom; no runtime deps. +Permanent feature is the always-on **Director Rail** (session clock + drift + next hard trigger). + +State (2026-07-20): Slices 1–5 all complete. Slice 5 = the **convention hub** (`` + +pure `src/con/schedule.js`, live-now/up-next, deep-links via `src/scenarios/index.js` registry; +shell routes hub↔session). All **six** Continuum 2026 slots are ported into scenario modules and +scheduled with real times in `src/con/continuum-2026.js`. + +Correction to the old slate note: Continuum 2026 is **six** GM'd slots, not five — Slot 5 +**By the Light of the Silvery Moon** (CoC Gaslight) was missing, and Slot 6 is *Get to the Chopper — +Another Fine Mess*. Full slate: Fri S1 Day One (BRP), Fri S2 AFTERIMAGE (Blade Runner), Sat S4 The +Vain Crown (VANITY), Sat S5 Silvery Moon (CoC Gaslight), Sun S6 Chopper (Pulp Cthulhu), Sun S7 The +Princes Bride (Dee Sanction). Scenario source-of-truth for timelines is the `gm-utility/*console` +files in the [[afterimage-scenario]] repo `slaguru666/Continuum2026`. + +All six scenarios' **clue trails AND NPC cast rosters are ported** (transcribed from the console +sources): clues feed the Slice 4 safety-net; cast feeds `` (tap-to-reveal secrets). +**Every design §5 tray tool is now built**: dice (6 packs incl. a dedicated `brp-d100` for Day One), +NPC, art, clue-net, cast-tray, break-timer (pauses the clock so breaks don't poison drift), +parking-lot (timestamped thread capture), and a wake-lock toggle. Rail chips: 🏠🎲👤✏️🔍👥☕📝💡. +Also a **markdown→scenario-data generator** (`tools/scenario-md.js` + `npm run gen:scenario`): a +deterministic parser over a defined structured-markdown format (frontmatter + Timeline/Clues/Cast +lists), validated before emit; `tools/` is dev-only, never bundled. **Online art "Generate"** is also +built: the art tray generates pencil art via a GM-configured endpoint (nothing hardcoded — paste the +URL in the ⚙ field) and caches results into a persisted, searchable library; degrades gracefully +offline/unconfigured. The **native iPad wrapper** is scaffolded too: a Capacitor 8 iOS shell +(`capacitor.config.json`, `@capacitor/{core,cli,ios}` devDeps, `ios:*` npm scripts, SW skipped under +Capacitor, `docs/native-ipad-wrapper.md` build guide). Generating/building the actual iOS project +needs a Mac with **full Xcode + CocoaPods** (this Mac mini has only Command Line Tools, no pods) — so +that step is documented for the user to run, not done. ~211 tests. **The whole design is now built** — +The Director is convention-ready for Continuum 2026. diff --git a/memory/mapwright-module.md b/memory/mapwright-module.md new file mode 100644 index 0000000..ff85618 --- /dev/null +++ b/memory/mapwright-module.md @@ -0,0 +1,28 @@ +--- +name: mapwright-module +description: Mapwright — standalone Foundry v14 battle-map generator; published on GitHub (slaguru666/mapwright) +metadata: + node_type: memory + type: project + originSessionId: 876e6f57-7721-4a19-83bd-1400e94b8c64 +--- + +`mapwright` — standalone Foundry VTT battle-map generator at `~/FoundryVTT/Data/modules/mapwright/`. Auto-generates good-looking tactical maps with Foundry walls/doors/windows/lighting pre-placed. Fresh rebuild replacing the underwhelming `quick-battlemap-builder` / sprawling `scifi-deckplan-generator`. + +**PUBLISHED (2026-06-17, v0.5.0):** GitHub repo `https://github.com/slaguru666/mapwright` (public). Install in Foundry via manifest URL: `https://github.com/slaguru666/mapwright/releases/latest/download/module.json`. Releases via `gh` CLI (auth'd as slaguru666) — GitHub MCP has no release tool, so use gh for releases. Release assets: `module.json` + `mapwright.zip` (clean module files, no dev/). To ship a new version: bump module.json version → zip `module.json module templates styles lang README.md` → `gh release create vX.Y.Z module.json mapwright.zip`. `.gitignore` excludes dev/*.svg|png|jpeg|html. + +**Live Foundry is v14.361** (world SLA_Industries, system zero-engine). Can log into the GM session via Playwright (Gamemaster user, no password, localhost:30000) to test live. Module is ENABLED there. + +**Core principle:** one geometry model feeds BOTH the picture and the Foundry walls. Pipeline per category: generate layout → wall segments → SVG (preview + scene background PNG) + Foundry walls/doors/lights/notes/tiles. + +**Categories (6):** Modern Building, Fantasy Building (BSP, footprint shapes rect/L/T/U/plus + "auto" random, multi-floor 1-4 with stairs/elevator, era-aware door/window art, furniture as LOCKED TILES); Cave/Dungeon (organic CA, themes cave/crypt/sewer); Outdoors (grassland/desert/snow/badlands); Town/Village + City Block (solid rooftop blocks + perimeter walls, dense + colourful + lots of baked scenery: cars/trees/lamps/crosswalks/wells/stalls). + +**KEY v14 GOTCHAS (hard-won):** +- Scene background moved to LEVELS: set `scene.updateEmbeddedDocuments("Level",[{_id, background:{src,color}}])` on the default level (`defaultLevel0000`), NOT the deprecated `scene.background`. See `applyBackground()` in scene.mjs. +- FilePicker is `foundry.applications.apps.FilePicker.implementation`; normalise upload paths to relative. +- Tiles use `texture.src` (not `img`); furniture tiles are `locked:true`, generated sprites cached in `mapwright/furniture/`. +- Default scenes: tokenVision:false (flat fully-lit map = matches preview); dynamic lighting opt-in. + +**File map:** lib/{rng,building,walls,render-vector,furniture,furniture-layout,organic,dungeon,render-cave,outdoor,render-outdoor,settlement,render-settlement,population,scene}.mjs; app/generator-app.mjs; mapwright.mjs (entry). Pure libs are Node-testable via dev/*.mjs harnesses (render → qlmanage to PNG to eyeball). + +**Next ideas:** enterable hero buildings; more biomes; moving-traffic city look; village cobble plaza. diff --git a/memory/midjourney_bridge.md b/memory/midjourney_bridge.md index 03eb603..2222579 100644 --- a/memory/midjourney_bridge.md +++ b/memory/midjourney_bridge.md @@ -5,6 +5,7 @@ metadata: node_type: memory type: reference originSessionId: fa4ca039-8c0e-4b9c-aee8-b6d7a81482b5 + modified: 2026-07-19T14:01:49.937Z --- # Midjourney bridge (`mj-gen`) @@ -40,6 +41,28 @@ mj-gen "Ink sketch, lone figure standing on a flooded London street at dawn, ... Then read the resulting PNG back to verify it matches the brief before placing it into game files. If the user dislikes U1, re-run `mj-gen` (cheap re-roll) or — if the same grid is still in the channel — manually post the other U-button custom_ids; the script currently only auto-clicks one upscale per call. +## Prompt gotchas (learned in production) + +- MJ's moderation blocks prompts containing banned words **even in negation** + ("no visible gore") — the grid never arrives and `mj-gen` times out with no + error. Reword positively ("understated, nothing graphic"). +- Scene prompts drift photorealistic; for illustration styles lead with + "hand-drawn pen and ink illustration, NOT a photograph" and append + `--no photography, photorealism`. +- Saved files get a `-u1` (upscale-button) suffix — rename to canonical names. +- Don't run two `mj-gen` calls concurrently in one channel: each polls the + channel for the newest grid and they can grab each other's jobs. +- **A silently-dying job = a banned word, almost always.** MJ declines in an + ephemeral reply the channel-poller can never see, so `mj-gen` waits out its + full timeout on nothing — NO new bot messages appear in the channel (check + via the messages API). Words confirmed to trip it even in innocent use: + **"gore"** (even negated: "no visible gore") and **"bust"** ("portrait bust + of a warrior"). Reword and rerun; the fix is never account-side unless the + account page actually shows 0 fast hours. (19 Jul 2026: five "Portrait + bust..." prompts died in a row and were misread as fast-hours exhaustion — + the account had 13h56m remaining; "Head and shoulders portrait" worked + first try.) `timeout_seconds` in config.json is 1800 (was 600). + ## Known fragility - If MJ changes the `/imagine` slash command schema, run `mj-capture-command` to refresh. diff --git a/memory/princes-bride-scenario.md b/memory/princes-bride-scenario.md new file mode 100644 index 0000000..b5508b7 --- /dev/null +++ b/memory/princes-bride-scenario.md @@ -0,0 +1,17 @@ +--- +name: princes-bride-scenario +description: THE PRINCES BRIDE — Dee Sanction game for Continuum 2026 Sunday Slot 7 (14:00–18:00); v1.1 convention-ready in slaguru666/Continuum2026 +metadata: + node_type: memory + type: project + originSessionId: 445b61b6-6e68-4f8e-8caa-28bf213400e9 + modified: 2026-07-19T14:05:10.686Z +--- + +THE PRINCES BRIDE (The Dee Sanction) is Tim's Continuum 2026 **Sunday Slot 7** game (26 July, 14:00–18:00, Arkham room). v1.1 convention-ready, built from the January materials at `/Volumes/Mac 2TB/Convention/contingency-2026/dee-sanction`. Repo: `slaguru666/Continuum2026` (shared-folder convention: `scenarios/sun-slot7-dee-sanction-princes-bride.md`, `gm-utility/princes-bride/`, art in `scenarios/art/princes-bride/`); local: `RPGS/Conventions/Continuum 2026/03 Sunday/Slot 7 Afternoon Dee Sanction/PRINCES-BRIDE/`. + +**Canon (reconciled — the January drafts contradicted each other):** Mary Fletcher made the planted poppet; the real fae charm came from the late Agatha Thorne; Garratt is a persuadable pragmatist; McShay's rejected proposal was to Eleanor Patterson; the Prince is **Sigismund** (not Henry — PC name collision); the village is **Faversholme**, Yorkshire, October **1586**. Table conventions: pregens are "Meg", "Nell", "Lynton" — never Margaret/Eleanor/Thomas. + +**Real Dee Sanction rules** (the old gm-quick-reference.html was a different game's system — ignore it): roll one Ability die (Physicall/Intellectuall/Supernaturall, d4–d12); 3+ succeeds, 1–2 Falters (success at cost); Expertise steps the die up; Fortune = one re-roll; Unravelling track steps down on uncanny Falters. + +**Set-pieces:** the Trial at dawn on an open **Verdict Die** (evidence steps it up, d10+ = acquittal without rolling, Falter = water ordeal) and the Bargain at the stones (courtesies; no roll wins the parley). Console: THE SANCTION DESK. Tim runs FOUR Continuum slots: Day One (Fri S1), AFTERIMAGE (Fri S2), Vain Crown (Sat S4), Princes Bride (Sun S7). Related: [[afterimage-scenario]], [[rpg-skill]]. diff --git a/memory/rpg-skill.md b/memory/rpg-skill.md new file mode 100644 index 0000000..2a93571 --- /dev/null +++ b/memory/rpg-skill.md @@ -0,0 +1,17 @@ +--- +name: rpg-skill +description: "The \"rpg\" Claude Code skill — house scenario-writing system, shared via claude-config repo, self-updating lessons log" +metadata: + node_type: memory + type: project + originSessionId: 063192d8-013b-4c4f-9d0b-ad355d9ae7c1 + modified: 2026-07-19T11:17:43.964Z +--- + +The **rpg** skill at `~/.claude/skills/rpg/` (created 2026-07-19) auto-triggers on any tabletop RPG scenario work and encodes the house system: 3h30 convention structure with 2:45 hard rule, three-route clue standard, pregen private seams, desk playtest protocol, mj-gen art pipeline. + +**Live loop:** transferable lessons are appended to `references/lessons.md` (promotion rule: delete once encoded into a reference); scenario-specific facts go to Graphiti; sync across machines with `cd ~/Git/claude-config && ./sync.sh`. + +**Sync ordering matters:** `sync.sh` copies live state over the repo with deletes — always `git pull && ./install.sh` before working on a machine, `./sync.sh` after, or machines clobber each other's memory/skill files (this happened once; fixed by union merge 2026-07-19). + +Related: [[afterimage-scenario]] (the exemplar scenario the skill was distilled from). diff --git a/settings.json b/settings.json index abcb4f0..04cbb7e 100644 --- a/settings.json +++ b/settings.json @@ -58,5 +58,7 @@ "theme": "dark", "verbose": false, "preferredNotifChannel": "terminal_bell", - "autoUpdaterStatus": "enabled" + "autoUpdaterStatus": "enabled", + "agentPushNotifEnabled": true, + "inputNeededNotifEnabled": true } diff --git a/skills/notebooklm/SKILL.md b/skills/notebooklm/SKILL.md deleted file mode 100644 index 4d5c1af..0000000 --- a/skills/notebooklm/SKILL.md +++ /dev/null @@ -1,660 +0,0 @@ ---- -name: notebooklm -description: Complete API for Google NotebookLM - full programmatic access including features not in the web UI. Create notebooks, add sources, generate all artifact types, download in multiple formats. Activates on explicit /notebooklm or intent like "create a podcast about X" ---- - -# NotebookLM Automation - -Complete programmatic access to Google NotebookLM—including capabilities not exposed in the web UI. Create notebooks, add sources (URLs, YouTube, PDFs, audio, video, images), chat with content, generate all artifact types, and download results in multiple formats. - -## Installation - -**From PyPI (Recommended for AI agents — Python-version-aware):** -```bash -pip install "notebooklm-py[browser]" # mandatory; errors must propagate - -# [cookies] (rookiepy) is optional and known to FAIL TO BUILD on Python 3.13+. -# Skip it deliberately on 3.13+ rather than swallowing the error — that lets -# *real* install failures (typos, network, PyPI outages) surface for the agent. -if python -c "import sys; sys.exit(0 if sys.version_info < (3, 13) else 1)"; then - pip install "notebooklm-py[cookies]" # errors propagate -else - echo "Skipping [cookies] on Python 3.13+ (rookiepy unavailable). Use 'notebooklm login' interactively." -fi -``` - -> Full install matrix (extras, headless servers, contributor flow): [Installation guide on GitHub](https://github.com/teng-lin/notebooklm-py/blob/main/docs/installation.md). - -**From GitHub (use latest release tag, NOT main branch):** -```bash -# Get the latest release tag (using curl) -LATEST_TAG=$(curl -s https://api.github.com/repos/teng-lin/notebooklm-py/releases/latest | grep '"tag_name"' | cut -d'"' -f4) -# Includes [browser] so the interactive `notebooklm login` flow works. -pip install "notebooklm-py[browser] @ git+https://github.com/teng-lin/notebooklm-py@${LATEST_TAG}" -``` - -⚠️ **DO NOT install from main branch** (`pip install git+https://github.com/teng-lin/notebooklm-py`). The main branch may contain unreleased/unstable changes. Always use PyPI or a specific release tag, unless you are testing unreleased features. - -**Skill install methods:** - -- `notebooklm skill install` installs this skill into the supported local agent directories managed by the CLI. -- `npx skills add teng-lin/notebooklm-py` installs this skill from the GitHub repository into compatible agent skill directories. -- If you are already reading this file inside an agent skill directory, the skill is already installed. You only need the Python package and authentication below. - -**CLI-managed install:** -```bash -notebooklm skill install -``` - -## Prerequisites - -**IMPORTANT:** Before using any command, you MUST authenticate: - -```bash -notebooklm login # Opens browser for Google OAuth -notebooklm list # Verify authentication works -``` - -If commands fail with authentication errors, re-run `notebooklm login`. - -### CI/CD, Multiple Accounts, and Parallel Agents - -For automated environments, multiple accounts, or parallel agent workflows: - -| Variable | Purpose | -|----------|---------| -| `NOTEBOOKLM_HOME` | Custom config directory (default: `~/.notebooklm`) | -| `NOTEBOOKLM_PROFILE` | Active profile name (default: `default`) | -| `NOTEBOOKLM_AUTH_JSON` | Inline auth JSON - no file writes needed | - -**CI/CD setup:** Set `NOTEBOOKLM_AUTH_JSON` from a secret containing your `storage_state.json` contents. - -**Multiple accounts:** Use named profiles (`notebooklm profile create work`, then `notebooklm -p work login`). Alternatively, use different `NOTEBOOKLM_HOME` directories per account. - -**Parallel agents:** The CLI stores notebook context per profile (`~/.notebooklm/profiles//context.json`, with a legacy fallback to `~/.notebooklm/context.json` for the implicit default profile). Multiple concurrent agents that share a profile and use `notebooklm use` can overwrite each other's context — use one of the isolation strategies below. - -**Solutions for parallel workflows:** -1. **Always use explicit notebook ID** (recommended): Pass `-n ` (for `wait`/`download` commands) or `--notebook ` (for others) instead of relying on `use` -2. **Per-agent isolation via profiles:** `export NOTEBOOKLM_PROFILE=agent-$ID` (each profile gets its own context file) -3. **Per-agent isolation via home:** Set unique `NOTEBOOKLM_HOME` per agent: `export NOTEBOOKLM_HOME=/tmp/agent-$ID` -4. **Use full UUIDs:** Avoid partial IDs in automation (they can become ambiguous) - -## Agent Setup Verification - -Before starting workflows, verify auth is in place. **Use `--test --json` (not bare `--json`)** — bare `--json` only proves the cookie file parses; `--test` makes a network call and proves the cookies still authenticate against Google. - -1. `notebooklm auth check --test --json` → require BOTH `"status": "ok"` AND `"checks.token_fetch": true`. Bare `"status": "ok"` (without `--test`) is a false-positive trap — a stale cookie file passes the parse check. -2. `notebooklm list --json` → expect valid JSON (may be empty for new accounts). -3. **If auth fails or is missing → run `notebooklm login` first.** This is the primary auth path: opens a browser, the user signs in to Google once, and the resulting `storage_state.json` is reused on every subsequent run. Works on any environment with a display. - - For headless contexts where opening a browser is not feasible, use `notebooklm login --browser-cookies ` instead — extracts the user's already-logged-in cookies from Chrome/Firefox/etc. (requires the `[cookies]` extra; rookiepy may not install on Python 3.13+). Use `chrome::` to target one Chromium user-profile, or `firefox::` / `firefox::none` to target one Firefox container. - - To survey signed-in Google accounts before picking one: `notebooklm auth inspect --browser ` (read-only; pass `-v` to see which Chromium user-profile each account came from, or `--json` for tooling). Scoped forms such as `notebooklm auth inspect --browser 'chrome::Profile 1'` inspect only that browser profile. - - Re-run step 1 after login to confirm. -4. **If auth was working but cookies went stale** (Google rotated SIDTS, or you signed in fresh in the browser) **→ refresh the active profile in place instead of full re-login:** - - `notebooklm auth refresh` — server-side SIDTS refresh against the existing `storage_state.json`. Cheap and silent; safe to run on a schedule (cron / launchd / systemd) at 15–20 min cadence to keep an unattended profile warm. - - `notebooklm auth refresh --browser-cookies ` — re-extract cookies from a running browser and match them back to the profile's recorded email in `context.json`. Use when the on-disk `storage_state.json` is too stale for the server-side refresh path but you've just signed back into Google in the browser. For Chromium-family browsers with multiple user-profiles (Chrome's `Default`, `Profile 1`, …), refresh fans out across all profiles to find the email — same path as `auth inspect` (issue #571). Use `chrome::` when you already know the exact browser profile. - - Both forms preserve the same `--profile` (no new profile is created). - -> **Note:** `notebooklm status` reports *context state* (selected notebook); do not use it to verify auth. - -## When This Skill Activates - -**Explicit:** User says "/notebooklm", "use notebooklm", or mentions the tool by name - -**Intent detection:** Recognize requests like: -- "Create a podcast about [topic]" -- "Summarize these URLs/documents" -- "Generate a quiz from my research" -- "Turn this into an audio overview" -- "Create flashcards for studying" -- "Generate a video explainer" -- "Make an infographic" -- "Create a mind map of the concepts" -- "Download the quiz as markdown" -- "Add these sources to NotebookLM" - -## Autonomy Rules - -**Run automatically (no confirmation):** -- `notebooklm status` - check context -- `notebooklm auth check` - diagnose auth issues -- `notebooklm auth inspect` - list Google accounts visible to a browser (read-only) -- `notebooklm auth refresh` - server-side SIDTS refresh of the active profile (no new profile, no destructive writes) -- `notebooklm auth refresh --browser-cookies ` - re-extract cookies from a browser into the active profile (rebuilds `storage_state.json` for the same `--profile`, not a new one) -- `notebooklm list` - list notebooks -- `notebooklm source list` - list sources -- `notebooklm artifact list` - list artifacts -- `notebooklm language list` - list supported languages -- `notebooklm language get` - get current language -- `notebooklm language set` - set language (global setting) -- `notebooklm artifact wait` - wait for artifact completion (in subagent context) -- `notebooklm source wait` - wait for source processing (in subagent context) -- `notebooklm research status` - check research status -- `notebooklm research wait` - wait for research (in subagent context) -- `notebooklm use ` - set context (⚠️ SINGLE-AGENT ONLY - use `-n` flag in parallel workflows) -- `notebooklm create` - create notebook -- `notebooklm ask "..."` - chat queries (without `--save-as-note`) -- `notebooklm history` - display conversation history (read-only) -- `notebooklm source add` - add sources -- `notebooklm profile list` - list profiles -- `notebooklm profile create` - create profile -- `notebooklm profile switch` - switch active profile -- `notebooklm doctor` - check environment health - -**Ask before running:** -- `notebooklm delete` / `source delete` / `note delete` / `share remove` / `profile delete` - destructive. Once approved, pass `--yes`/`-y` to skip the confirmation prompt (uniform across every destructive command). On the commands that also expose `--json` (e.g. `delete`, `source delete`, `note delete`, `share remove`), `--json` implies `--yes` so non-interactive callers never hang on the prompt; `profile delete` has no `--json`, so pass `--yes` explicitly there. -- `notebooklm generate *` - long-running, may fail -- `notebooklm download *` - writes to filesystem -- `notebooklm artifact wait` - long-running (when in main conversation) -- `notebooklm source wait` - long-running (when in main conversation) -- `notebooklm research wait` - long-running (when in main conversation) -- `notebooklm ask "..." --save-as-note` - writes a note -- `notebooklm history --save` - writes a note - -## Quick Reference - -| Task | Command | -|------|---------| -| Authenticate | `notebooklm login` | -| Authenticate from browser cookies | `notebooklm login --browser-cookies ` | -| Authenticate from one Chromium profile | `notebooklm login --browser-cookies 'chrome::Profile 1'` | -| Authenticate from one Firefox container | `notebooklm login --browser-cookies 'firefox::Work'` | -| Import every signed-in account into its own profile | `notebooklm login --browser-cookies --all-accounts` | -| Inspect signed-in accounts (read-only, by email) | `notebooklm auth inspect --browser ` | -| Inspect one browser profile/container | `notebooklm auth inspect --browser 'chrome::Profile 1'` | -| Diagnose auth issues | `notebooklm auth check` | -| Diagnose auth (full) | `notebooklm auth check --test` | -| Refresh active profile in place (server-side) | `notebooklm auth refresh` | -| Refresh active profile from a re-signed-in browser | `notebooklm auth refresh --browser-cookies ` | -| Refresh from one Chromium profile | `notebooklm auth refresh --browser-cookies 'chrome::Profile 1'` | -| One-shot cookie keepalive (for cron) | `notebooklm auth refresh --quiet` | -| List notebooks | `notebooklm list` | -| Create notebook | `notebooklm create "Title"` | -| Set context | `notebooklm use ` | -| Show context | `notebooklm status` | -| Add URL source | `notebooklm source add "https://..."` | -| Add file | `notebooklm source add ./file.pdf` | -| Add YouTube | `notebooklm source add "https://youtube.com/..."` | -| List sources | `notebooklm source list` | -| Delete source by ID | `notebooklm source delete ` | -| Delete source by exact title | `notebooklm source delete-by-title "Exact Title"` | -| Wait for source processing | `notebooklm source wait ` | -| Web research (fast) | `notebooklm source add-research "query"` | -| Web research (deep) | `notebooklm source add-research "query" --mode deep --no-wait` | -| Web research (query from file) | `notebooklm source add-research --prompt-file research_query.txt --mode deep` | -| Check research status | `notebooklm research status` | -| Wait for research | `notebooklm research wait --import-all` | -| Chat | `notebooklm ask "question"` | -| Chat (long prompt from file) | `notebooklm ask --prompt-file question.txt` | -| Chat (specific sources) | `notebooklm ask "question" -s src_id1 -s src_id2` | -| Chat (with references) | `notebooklm ask "question" --json` | -| Chat (save answer as note) | `notebooklm ask "question" --save-as-note` | -| Chat (save with title) | `notebooklm ask "question" --save-as-note --note-title "Title"` | -| Show conversation history | `notebooklm history` | -| Save all history as note | `notebooklm history --save` | -| Continue specific conversation | `notebooklm ask "question" -c ` | -| Save history with title | `notebooklm history --save --note-title "My Research"` | -| Get source fulltext | `notebooklm source fulltext ` | -| Get source guide | `notebooklm source guide ` | -| Generate podcast | `notebooklm generate audio "instructions"` | -| Generate (long prompt from file) | `notebooklm generate audio --prompt-file instructions.txt` | -| Generate podcast (JSON) | `notebooklm generate audio --json` | -| Generate podcast (specific sources) | `notebooklm generate audio -s src_id1 -s src_id2` | -| Generate video | `notebooklm generate video "instructions"` | -| Generate report | `notebooklm generate report --format briefing-doc` | -| Generate report (append instructions) | `notebooklm generate report --format study-guide --append "Target audience: beginners"` | -| Generate quiz | `notebooklm generate quiz` | -| Revise a slide | `notebooklm generate revise-slide "prompt" --artifact --slide 0` | -| Check artifact status | `notebooklm artifact list` | -| Wait for completion | `notebooklm artifact wait ` | -| Download audio | `notebooklm download audio ./output.mp3` | -| Download video | `notebooklm download video ./output.mp4` | -| Download cinematic video | `notebooklm download cinematic-video ./cinematic.mp4` (alias for `download video`) | -| Download infographic | `notebooklm download infographic ./infographic.png` | -| Download slide deck (PDF) | `notebooklm download slide-deck ./slides.pdf` | -| Download slide deck (PPTX) | `notebooklm download slide-deck ./slides.pptx --format pptx` | -| Download report | `notebooklm download report ./report.md` | -| Download mind map | `notebooklm download mind-map ./map.json` | -| Download data table | `notebooklm download data-table ./data.csv` | -| Download quiz | `notebooklm download quiz quiz.json` | -| Download quiz (markdown) | `notebooklm download quiz --format markdown quiz.md` | -| Download flashcards | `notebooklm download flashcards cards.json` | -| Download flashcards (markdown) | `notebooklm download flashcards --format markdown cards.md` | -| Delete notebook | `notebooklm delete -n ` (add `--yes` to skip the prompt non-interactively) | -| List languages | `notebooklm language list` | -| Get language | `notebooklm language get` | -| Set language | `notebooklm language set zh_Hans` | -| List profiles | `notebooklm profile list` | -| Create profile | `notebooklm profile create work` | -| Switch profile | `notebooklm profile switch work` | -| Delete profile | `notebooklm profile delete old --yes` (`-y`; `--confirm` is a deprecated alias) | -| Rename profile | `notebooklm profile rename old new` | -| Use profile (one-off) | `notebooklm -p work list` | -| Health check | `notebooklm doctor` | -| Health check (auto-fix) | `notebooklm doctor --fix` | - -**Parallel safety:** Use explicit notebook IDs in parallel workflows. Commands supporting `-n` shorthand: `artifact wait`, `source wait`, `research wait/status`, `download *`. Download commands also support `-a/--artifact`. Other commands use `--notebook`. For chat, use `-c ` to target a specific conversation. - -**Partial IDs:** Use first 6+ characters of UUIDs. Must be unique prefix (fails if ambiguous). Works for ID-based commands such as `use`, `source delete`, and `wait`. For exact source-title deletion, use `source delete-by-title "Title"`. For automation, prefer full UUIDs to avoid ambiguity. - -## Command Output Formats - -Commands with `--json` return structured data for parsing: - -**Create notebook:** -```bash -$ notebooklm create "Research" --json -{"notebook": {"id": "abc123de-...", "title": "Research", "created_at": null}} -# parse with: jq -r .notebook.id -``` - -**Add source:** -```bash -$ notebooklm source add "https://example.com" --json -{"source": {"id": "def456...", "title": "Example", "type": "SourceType.WEB_PAGE", "url": "https://example.com"}} -# parse with: jq -r .source.id -# Note: no `status` field on add — use `source list --json` or `source wait` to check processing state. -``` - -**Generate artifact:** -```bash -$ notebooklm generate audio "Focus on key points" --json -{"task_id": "xyz789...", "status": "pending"} -# When run with --wait, completed status also includes a `url` field. -``` - -**Chat with references:** -```bash -$ notebooklm ask "What is X?" --json -{"answer": "X is... [1] [2]", "conversation_id": "...", "turn_number": 1, "is_follow_up": false, "references": [{"source_id": "abc123...", "citation_number": 1, "cited_text": "Relevant passage from source..."}, {"source_id": "def456...", "citation_number": 2, "cited_text": "Another passage..."}]} -``` - -**Source fulltext (get indexed content):** -```bash -$ notebooklm source fulltext --json -{"source_id": "...", "title": "...", "content": "Full indexed text...", "_type_code": null, "url": null, "char_count": 12345} -``` - -**Understanding citations:** The `cited_text` in references is often a snippet or section header, not the full quoted passage. The `start_char`/`end_char` positions reference NotebookLM's internal chunked index, not the raw fulltext. Use `SourceFulltext.find_citation_context()` to locate citations: -```python -fulltext = await client.sources.get_fulltext(notebook_id, ref.source_id) -matches = fulltext.find_citation_context(ref.cited_text) # Returns list[(context, position)] -if matches: - context, pos = matches[0] # First match; check len(matches) > 1 for duplicates -``` - -**Extract IDs:** Singular endpoints wrap their result in an envelope — -parse `.notebook.id` (from `create`), `.source.id` (from `source add`), -or `.task_id` (from `generate *`). The chat `--json` references list uses -`.references[].source_id`. - -## Generation Types - -All generate commands support: -- `-s, --source` to use specific source(s) instead of all sources -- `--language` to set output language (defaults to configured language or 'en') -- `--json` for machine-readable output (returns `task_id` and `status`) -- `--retry N` to automatically retry on rate limits with exponential backoff (supported on all subcommands **except** `mind-map`) -- `--prompt-file PATH` to read description/query from a file (supported on `ask`, `generate` subcommands except `mind-map`, and `source add-research`; mutually exclusive with positional argument; use for long prompts) - -| Type | Command | Options | Download | -|------|---------|---------|----------| -| Podcast | `generate audio` | `--format [deep-dive\|brief\|critique\|debate]`, `--length [short\|default\|long]` | .mp3 | -| Video | `generate video` | `--format [explainer\|brief\|cinematic]` (⁴), `--style [auto\|classic\|whiteboard\|kawaii\|anime\|watercolor\|retro-print\|heritage\|paper-craft]` | .mp4 | -| Slide Deck | `generate slide-deck` | `--format [detailed\|presenter]`, `--length [default\|short]` (²) | .pdf / .pptx | -| Slide Revision | `generate revise-slide "prompt" --artifact --slide N` | `--wait`, `--notebook` | *(re-downloads parent deck)* | -| Infographic | `generate infographic` | `--orientation [landscape\|portrait\|square]`, `--detail [concise\|standard\|detailed]`, `--style [auto\|sketch-note\|professional\|bento-grid\|editorial\|instructional\|bricks\|clay\|anime\|kawaii\|scientific]` | .png | -| Report | `generate report` | `--format [briefing-doc\|study-guide\|blog-post\|custom]`, `--append "extra instructions"` (¹) | .md | -| Mind Map | `generate mind-map` | `--kind [interactive\|note-backed]` (³) *(default: note-backed; flips to interactive in v0.8.0)* | .json | -| Data Table | `generate data-table` | description required | .csv | -| Quiz | `generate quiz` | `--difficulty [easy\|medium\|hard]`, `--quantity [fewer\|standard\|more]` | .json/.md/.html | -| Flashcards | `generate flashcards` | `--difficulty [easy\|medium\|hard]`, `--quantity [fewer\|standard\|more]` | .json/.md/.html | - -¹ `--append` only customizes the built-in templates. With `--format custom`, pass the prompt as the positional `DESCRIPTION` argument (`notebooklm generate report "PROMPT" --format custom`); `--append` is silently ignored in that mode (the CLI prints a warning). - -³ **Two kinds of mind map (issue #1256).** `generate mind-map --kind note-backed` (today's default) creates the **note-backed** kind — a JSON node tree, generated synchronously. `generate mind-map --kind interactive` creates the newer **interactive** studio artifact (what the web app now makes); it is polled to completion. Both emit the same `{mind_map, note_id, kind}` JSON, list under `artifact list --type mind-map`, and export via `download mind-map`. `--instructions` applies only to the note-backed kind. **The default `--kind` switches to `interactive` in v0.8.0**; omitting `--kind` prints a one-time stderr notice (silence with `NOTEBOOKLM_QUIET_DEPRECATIONS=1`). - -⁴ **Cinematic video (Veo 3).** `generate video --format cinematic` generates AI documentary footage via Veo 3; it **ignores `--style`**, takes ~30-40 min, and requires a Google AI Ultra subscription. Also exposed as the `generate cinematic-video` alias (which forces `--format cinematic` and a longer default timeout). Download with `download video` or the `download cinematic-video` alias. - -² **Portrait / vertical slide decks via prompt.** Slide-deck has no `--orientation` flag (unlike infographic). Treat portrait decks as skill-level prompt guidance, not a typed CLI/API contract: NotebookLM currently honors orientation cues written into the `DESCRIPTION` positional argument. Including phrases like `"9:16 portrait"`, `"vertical layout"`, `"portrait mobile format"`, or `"vertical 9:16 layout"` can make NotebookLM render each slide as a 9:16 portrait image. Empirically: - -- The `.pptx` canvas itself may stay 16:9, but each slide's embedded image can be rendered as 9:16 portrait — useful for vertical/mobile video material extracted via `python-pptx`. -- Orientation is steered once at generation time. `generate revise-slide` edits content within an existing slide but does not change its orientation; if a slide falls back to landscape (occasional inconsistency), regenerate the whole deck rather than revising the single page. -- Combine with an explicit page count in the prompt (e.g. `"Create exactly 8 pages, using a vertical 9:16 portrait layout"`) for the most predictable output. - -```bash -# Skill prompt hint: ask NotebookLM to render each slide as a 9:16 portrait image -notebooklm generate slide-deck "Create an 8-page deck in 9:16 portrait orientation for mobile viewing" --length default -``` - -## Features Beyond the Web UI - -These capabilities are available via CLI but not in NotebookLM's web interface: - -| Feature | Command | Description | -|---------|---------|-------------| -| **Batch downloads** | `download --all` | Download all artifacts of a type at once | -| **Quiz/Flashcard export** | `download quiz --format json` | Export as JSON, Markdown, or HTML (web UI only shows interactive view) | -| **Mind map extraction** | `download mind-map` | Export hierarchical JSON for visualization tools | -| **Data table export** | `download data-table` | Download structured tables as CSV | -| **Slide deck as PPTX** | `download slide-deck --format pptx` | Download slide deck as editable .pptx (web UI only offers PDF) | -| **Slide revision** | `generate revise-slide "prompt" --artifact --slide N` | Modify individual slides with a natural-language prompt | -| **Report template append** | `generate report --format study-guide --append "..."` | Append custom instructions to built-in format templates without losing the format type | -| **Source fulltext** | `source fulltext ` | Retrieve the indexed text content of any source | -| **Save chat to note** | `ask "..." --save-as-note` / `history --save` | Save Q&A answers or conversation history as notebook notes | -| **Programmatic sharing** | `share` commands | Manage sharing permissions without the UI | - -## Common Workflows - -### Research to Podcast (Interactive) -**Time:** 5-10 minutes total - -1. `notebooklm create "Research: [topic]"` — *if fails: check auth with `notebooklm login`* -2. `notebooklm source add` for each URL/document — *if one fails: log warning, continue with others* -3. Wait for sources: `notebooklm source list --json` until all status=READY — *required before generation* -4. `notebooklm generate audio "Focus on [specific angle]"` (confirm when asked) — *if rate limited: wait 5 min, retry once* -5. Note the artifact ID returned -6. Check `notebooklm artifact list` later for status -7. `notebooklm download audio ./podcast.mp3` when complete (confirm when asked) - -### Research to Podcast (Automated with Subagent) -**Time:** 5-10 minutes, but continues in background - -When user wants full automation (generate and download when ready): - -1. Create notebook and add sources as usual -2. Wait for sources to be ready (use `source wait` or check `source list --json`) -3. Run `notebooklm generate audio "..." --json` → parse `task_id` from output -4. **Spawn a background agent** using Task tool: - ```python - Task( - prompt="Wait for artifact {task_id} in notebook {notebook_id} to complete, then download. - Use: notebooklm artifact wait {task_id} -n {notebook_id} --timeout 1200 - Then: notebooklm download audio ./podcast.mp3 -a {task_id} -n {notebook_id}", - subagent_type="general-purpose" - ) - ``` -5. Main conversation continues while agent waits - -**Error handling in subagent:** -- If `artifact wait` returns exit code 2 (timeout): Report timeout, suggest checking `artifact list` -- If download fails: Check if artifact status is COMPLETED first - -**Benefits:** Non-blocking, user can do other work, automatic download on completion - -### Document Analysis -**Time:** 1-2 minutes - -1. `notebooklm create "Analysis: [project]"` -2. `notebooklm source add ./doc.pdf` (or URLs) -3. `notebooklm ask "Summarize the key points"` -4. `notebooklm ask "What are the main arguments?"` -5. Continue chatting as needed - -### Bulk Import -**Time:** Varies by source count - -1. `notebooklm create "Collection: [name]"` -2. Add multiple sources: - ```bash - notebooklm source add "https://url1.com" - notebooklm source add "https://url2.com" - notebooklm source add ./local-file.pdf - ``` -3. `notebooklm source list` to verify - -**Source limits:** Varies by plan—Standard: 50, Plus: 100, Pro: 300, Ultra: 600 sources per notebook. See [NotebookLM plans](https://support.google.com/notebooklm/answer/16213268) for details. The CLI does not enforce these limits; they are applied by your NotebookLM account. -**Supported types:** PDFs, YouTube URLs, web URLs, Google Docs, text files, Markdown, Word docs, EPUB, audio files, video files, images - -### Bulk Import with Source Waiting (Subagent Pattern) -**Time:** Varies by source count - -When adding multiple sources and needing to wait for processing before chat/generation: - -1. Add sources with `--json` to capture IDs (parse with `jq -r .source.id`): - ```bash - notebooklm source add "https://url1.com" --json # → {"source": {"id": "abc...", ...}} - notebooklm source add "https://url2.com" --json # → {"source": {"id": "def...", ...}} - ``` -2. **Spawn a background agent** to wait for all sources: - ``` - Task( - prompt="Wait for sources {source_ids} in notebook {notebook_id} to be ready. - For each: notebooklm source wait {id} -n {notebook_id} --timeout 600 - Report when all ready or if any fail.", - subagent_type="general-purpose" - ) - ``` -3. Main conversation continues while agent waits -4. Once sources are ready, proceed with chat or generation - -**Why wait for sources?** Sources must be indexed before chat or generation. Takes ~30 seconds to several minutes per source (see the processing-times table below). - -### Deep Web Research (Subagent Pattern) -**Time:** 15-30+ minutes, runs in background - -Deep research finds and analyzes web sources on a topic: - -1. Create notebook: `notebooklm create "Research: [topic]"` -2. Start deep research (non-blocking): - ```bash - notebooklm source add-research "topic query" --mode deep --no-wait - ``` -3. **Spawn a background agent** to wait and import: - ``` - Task( - prompt="Wait for research in notebook {notebook_id} to complete and import sources. - Use: notebooklm research wait -n {notebook_id} --import-all --timeout 1800 - Report how many sources were imported.", - subagent_type="general-purpose" - ) - ``` -4. Main conversation continues while agent waits -5. When agent completes, sources are imported automatically - -**Alternative (blocking):** For simple cases, omit `--no-wait`: -```bash -notebooklm source add-research "topic" --mode deep --import-all -# Blocks until research completes (deep mode: 15-30+ min) -``` - -**When to use each mode:** -- `--mode fast`: Specific topic, quick overview needed (5-10 sources, seconds) -- `--mode deep`: Broad topic, comprehensive analysis needed (20+ sources, 15-30+ min) - -**Research sources:** -- `--from web`: Search the web (default) -- `--from drive`: Search Google Drive - -## Output Style - -**Progress updates:** Brief status for each step -- "Creating notebook 'Research: AI'..." -- "Adding source: https://example.com..." -- "Starting audio generation... (task ID: abc123)" - -**Fire-and-forget for long operations:** -- Start generation, return artifact ID immediately -- Do NOT poll or wait in main conversation - generation takes 5-45 minutes (see timing table) -- User checks status manually, OR use subagent with `artifact wait` - -**JSON output:** Use `--json` flag for machine-readable output: -```bash -notebooklm list --json -notebooklm auth check --test --json # use --test for network-validated auth (see § Agent Setup Verification) -notebooklm source list --json -notebooklm artifact list --json -``` - -**JSON schemas (key fields):** - -`notebooklm list --json`: -```json -{"notebooks": [{"index": 1, "id": "...", "title": "...", "is_owner": true, "created_at": "..."}], "count": 1} -``` - -`notebooklm auth check --test --json` (use `--test` to drive the network token-fetch — bare `--json` would leave `"token_fetch": null`): -```json -{"status": "ok", "checks": {"storage_exists": true, "json_valid": true, "cookies_present": true, "sid_cookie": true, "token_fetch": true}, "details": {"storage_path": "...", "auth_source": "file", "cookies_found": ["SID", "HSID", "..."], "cookie_domains": [".google.com"]}} -``` - -`notebooklm source list --json`: -```json -{"notebook_id": "...", "notebook_title": "...", "sources": [{"index": 1, "id": "...", "title": "...", "type": "SourceType.WEB_PAGE", "url": "...", "status": "ready|processing|error", "status_id": 1, "created_at": "..."}], "count": 1} -``` - -`notebooklm artifact list --json`: -```json -{"notebook_id": "...", "notebook_title": "...", "artifacts": [{"index": 1, "id": "...", "title": "...", "type": "Audio", "type_id": 1, "status": "in_progress|pending|completed|unknown", "status_id": 1, "created_at": "..."}], "count": 1} -``` - -**Status values:** -- Sources: `processing` → `ready` (or `error`) -- Artifacts: `pending` or `in_progress` → `completed` (or `unknown`) - -## Error Handling - -**On failure, offer the user a choice:** -1. Retry the operation -2. Skip and continue with something else -3. Investigate the error - -**Error decision tree:** - -| Error | Cause | Action | -|-------|-------|--------| -| Auth/cookie error | Session expired | Run `notebooklm auth check` then `notebooklm login` | -| "No notebook context" | Context not set | Use `-n ` or `--notebook ` flag (parallel), or `notebooklm use ` (single-agent) | -| "No result found for RPC ID" | Rate limiting | Wait 5-10 min, retry | -| `GENERATION_FAILED` | Google rate limit | Wait and retry later | -| Download fails | Generation incomplete | Check `artifact list` for status | -| Invalid notebook/source ID | Wrong ID | Run `notebooklm list` to verify | -| RPC protocol error | Google changed APIs | May need CLI update | - -## Exit Codes - -All commands use consistent exit codes: - -| Code | Meaning | Action | -|------|---------|--------| -| 0 | Success | Continue | -| 1 | Error (not found, processing failed) | Check stderr, see Error Handling | -| 2 | Timeout (wait commands only) | Extend timeout or check status manually | - -**Examples:** -- `source wait` returns 1 if source not found or processing failed -- `artifact wait` returns 2 if timeout reached before completion -- `generate` returns 1 if rate limited (check stderr for details) - -## Long Prompts - -When a prompt or query exceeds shell command-line length limits, use `--prompt-file` to read it from a file: - -```bash -notebooklm ask --prompt-file ./long_question.txt -notebooklm generate report --prompt-file ./custom_report_prompt.txt -notebooklm source add-research --prompt-file ./research_query.txt --mode deep -``` - -`--prompt-file` is mutually exclusive with the positional text argument. The file is read as UTF-8 with trailing whitespace stripped. Supported on: `ask`, all `generate` subcommands (except `mind-map`), and `source add-research`. - -> **Note:** `--prompt-file` reads a *prompt/query text file*, not a source document. To upload a file as a notebook source, use `source add ./file.pdf`. - -## Known Limitations - -**Rate limiting:** Audio, video, quiz, flashcards, infographic, and slide deck generation may fail due to Google's rate limits. This is an API limitation, not a bug. - -**Reliable operations:** These always work: -- Notebooks (list, create, delete, rename) -- Sources (add, list, delete) -- Chat/queries -- Mind-map, study-guide, report, data-table generation - -**Unreliable operations:** These may fail with rate limiting: -- Audio (podcast) generation -- Video generation -- Quiz and flashcard generation -- Infographic and slide deck generation - -**Workaround:** If generation fails: -1. Check status: `notebooklm artifact list` -2. Retry after 5-10 minutes -3. Use the NotebookLM web UI as fallback - -**Processing times vary significantly.** Use the subagent pattern for long operations: - -| Operation | Typical time | Suggested timeout | -|-----------|--------------|-------------------| -| Source processing | 30s - 10 min | 600s | -| Research (fast) | 30s - 2 min | 180s | -| Research (deep) | 15 - 30+ min | 1800s | -| Notes | instant | n/a | -| Mind-map | instant (sync) | n/a | -| Quiz, flashcards | 5 - 15 min | 900s | -| Report, data-table | 5 - 15 min | 900s | -| Audio generation | 10 - 20 min | 1200s | -| Video generation | 15 - 45 min | 2700s | - -**Polling intervals:** When checking status manually, poll every 15-30 seconds to avoid excessive API calls. - -## Language Configuration - -Language setting controls the output language for generated artifacts (audio, video, etc.). - -**Important:** Language is a **GLOBAL** setting that affects all notebooks in your account. - -```bash -# List all 80+ supported languages with native names -notebooklm language list - -# Show current language setting -notebooklm language get - -# Set language for artifact generation -notebooklm language set zh_Hans # Simplified Chinese -notebooklm language set ja # Japanese -notebooklm language set en # English (default) -``` - -**Common language codes:** -| Code | Language | -|------|----------| -| `en` | English | -| `zh_Hans` | 中文(简体) - Simplified Chinese | -| `zh_Hant` | 中文(繁體) - Traditional Chinese | -| `ja` | 日本語 - Japanese | -| `ko` | 한국어 - Korean | -| `es` | Español - Spanish | -| `fr` | Français - French | -| `de` | Deutsch - German | -| `pt_BR` | Português (Brasil) | - -**Override per command:** Use `--language` flag on generate commands: -```bash -notebooklm generate audio --language ja # Japanese podcast -notebooklm generate video --language zh_Hans # Chinese video -``` - -**Offline mode:** Use `--local` flag to skip server sync: -```bash -notebooklm language set zh_Hans --local # Save locally only -notebooklm language get --local # Read local config only -``` - -## Troubleshooting - -```bash -notebooklm --help # Main commands -notebooklm auth check # Diagnose auth issues -notebooklm auth check --test # Full auth validation with network test -notebooklm source --help # Source management -notebooklm research --help # Research status/wait -notebooklm generate --help # Content generation -notebooklm artifact --help # Artifact management -notebooklm download --help # Download content -notebooklm language --help # Language settings -``` - -**Diagnose auth:** `notebooklm auth check` - shows cookie domains, storage path, validation status -**Re-authenticate:** `notebooklm login` -**Check version:** `notebooklm --version` -**Refresh a CLI-managed install:** `notebooklm skill install` diff --git a/skills/rpg/references/lessons.md b/skills/rpg/references/lessons.md index eb93f6b..8e16811 100644 --- a/skills/rpg/references/lessons.md +++ b/skills/rpg/references/lessons.md @@ -163,61 +163,6 @@ pass. (6th/7th/8th) plus boss Grit per extra hero and mook multiplier lives ON the GM cut-out corner of the last hero card page, not buried in the doc. -## 2026-07-27 — Post-Continuum retro: the GM used none of the apps - -Actual outcome data from running the con — the strongest signal in this log. - -- **The comprehensive scenario apps went unused — "too complex, the story - material too convoluted."** Five device editions were built (v1 tablet, v2 - responsive, laptop, e-paper, phone story reader); none were opened while - running games. A faithful, complete render of a scenario is a *prep* artifact, - not a table tool. **Default to NOT building a content app** — a GM mid-game - will not read it. -- **At the table, concision beats completeness, every time.** What was wanted - was one focused surface with only the *live* essentials — where we are on the - clock, the next hard beat, the one secret in play, the "if late, cut this" - note — not everything that is true. Render the table surface as the smallest - useful subset of the prep doc. -- **"All the information in one place" = one surface, not six.** The multi-console, - multi-edition sprawl actively hurt; a single page was the stated preference. -- **The artifact that DID earn its place is the in-play *help* tool** (The - Director: live pacing / Director-Rail, dice rule-packs, NPC + clue safety-net) - — assistance *in the moment*, not reference to read. That is where console - engineering should go; the "a content console per scenario" instinct is - retired (see production.md). -- **Edition proliferation was pure cost.** Each edition = its own build + - container + reverse-proxy route + silent staleness liability, and most were - never used — they accreted one reasonable "make a version for X" at a time. - Before building any such variant, ask whether it will be *opened* at all; - adapt one source for presentation-only deltas, fork only for a genuinely - different content model. - -## 2026-07 — RUNDOWN cardless chase system (Blade Runner, house subsystem) - -- **Do the expected-value arithmetic before committing to a subsystem.** A - spec self-review pass that actually computed the dice maths caught two dead - mechanics that read fine in prose: a role structure where the pursuers' net - was ~0.00 per round (the chase could literally never end), and a support role - worth +0.24 successes when simply doubling up on the main role was worth - +0.57 — nobody would ever have picked it. Prose hides both. One script found - both in a minute. -- **A role that spends a resource needs a role that refunds it.** Four roles - only became an economy once the support role was recast from "adds successes" - to "buys off the cost the aggressive role generates". Test any new role menu - by asking what each option *trades*, not what it *does* — if two options - trade the same thing, one of them is decoration. -- **Check whether the rules you're replacing already contain the escape - hatch.** The published Blade Runner chase ships a die table as an alternative - to its own obstacle deck, so "make it cardless" was already solved in the - book. The real brief was the other four problems (idle players, no - accumulating state, generic obstacles, lookup load). Always ask what the - request is *actually* for before designing to its literal wording. -- **When a house subsystem gets a digital aid, test the aid headlessly.** A - ~60-line stub-DOM harness in Node drove the real console module through every - state transition (clamping, round cap, overtime drift, undo) with no browser - and no dependencies. Worth it: two of the "failures" it surfaced were the - harness lying, which is itself the thing you want to find before a - convention floor. ## 2027-01 prep (2026-07) — continuity searches for returning NPCs - **Grep the role, not just the name.** A returning NPC brief said "Witchfinder diff --git a/skills/rpg/references/production.md b/skills/rpg/references/production.md index 8fe4544..514f548 100644 --- a/skills/rpg/references/production.md +++ b/skills/rpg/references/production.md @@ -59,34 +59,6 @@ set-piece runner (e.g. chase obstacles), PC/NPC dashboards, fullscreen props, autosaving state. Scenarios plug in as modules — when building a new scenario, add a module rather than a new app. -**Reality check (Continuum 2026, post-con):** none of the built scenario apps -were used at the table — "too complex, too convoluted." Two hard rules follow: - -1. **Keep it lean and single-surface.** The GM reads in 30-second glances; a - console must show only what's needed *live* (clock, next beat, the secret in - play), not a faithful render of the scenario. Concision is the feature. One - surface — resist multi-tab and per-device editions (each is a build + - deploy + staleness liability, and they went unused). -2. **The in-play *help* tool is what earns its keep** — live pacing, dice - rule-packs, an NPC/clue safety-net (assistance in the moment). Put console - effort there, not into content reference the GM won't open mid-game. - -### Hosting an offline app (only if one is genuinely wanted) - -Deployed the Continuum apps to a VPS behind a Caddy reverse proxy. The gotchas -that cost hours, so they don't again: - -- **Service-worker cache staleness** is the #1 time-sink: after any rebuild the - old SW keeps serving the old page, so you debug code that isn't running. - Unregister the SW, clear caches, and do a **full reload** (a hash-nav doesn't - reload) before believing what you see. -- **Never edit a bind-mounted Caddyfile with `mv`/`sed -i`** — it's pinned to an - inode; the container keeps reading the old file. Append in place (`>>`), back - up first, reload via the admin API from stdin. -- Private repos → the VPS has no git creds; **rsync the built `dist/` + deploy - dir**, don't clone. Each subdomain needs its own DNS A record; Caddy issues - TLS once it resolves. - ## Print checklist (before the con) - Character sheets: A4 portrait, 100% scale, one page per PC + table