/nav/rack returns each crate's virtual_crate_type.material_color + type name;
drawRack fills/strokes/arrows each crate in its real colour (Blue Crate #0000FF,
Wooden Rack Bin #BA906A, White Tub #FFFFFF, Black Tub #191970, Shelf #C0C0C0…)
instead of all-blue. Legend lists the crate types present on the rack.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per-crate panel under Crate Contents: rename (label_text) + a Facing segment
(↑back/↓front/←left/→right) that rotates the crate live — the map arrow flips on
click. CrateEditIn gained 'direction'. Restores the crate editing my tabbed rewrite
dropped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sources stay the pick-ordered crates; targets default to those same real crate IDs
sorted ascending (4,3,2,1 → pour A–Z into 1,2,3,4), shown in an editable field so you
can consolidate/spread. Plan now shows where items land per crate. Drops the Start+Count
inputs (which could target non-existent crate IDs and orphan items).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
One persistent central store/rack map with a top tab strip (Scanner / Returns /
Reorganize / Collections / Stock Finder) all driving the shared map, + Store/Rack/
Crate/Item view buttons and an omni scan bar (release/SKU/c12/r3). Reorganize: click
crates IN ORDER (numbered pick badges feed the A–Z distribution planner) + drag racks
to move them on the store map (persists pos_x/pos_z; RackEditIn gained position fields).
Collections edit highlights picked crates on the map. Returns = stub (manual path via
Scanner + Release Info for now).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Storefront /wantlist form (themed, email-keyed, guest-friendly) posts to
/shop/wantlist → wantlist table (lazy DDL). Release pages deep-link to it
(prefilled; 'not in stock — request this record' when no copies). Admin gets
a Wantlist tab: pending/found/fulfilled queue with one-click status actions.
Default storefront menu → Records + Wanted.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
records.html reads /artist|label|genre|style/{val} from the path, sets the
filter + an entity header (artist/label name via /shop/{kind}/{id}). /shop/browse
gains artist/label EXISTS filters + primary artist_id; release page links
artist→/artist/{id} and genre/style pills→/{kind}/{name}.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Scene was dumping all 3 rooms' racks/crates/lights into one room, and the
served decals + portals were never rendered (trapped in booth-room).
- /virtual/scene scopes to ONE room (?space=, default = is_default space);
filters racks/crates/lights/cameras/portals/decals/covers by space_id
- render decals (image + canvas-text planes) and portal doorways; walk into
a portal -> loads the linked room
- portal links_to_id is the PAIRED portal's id, not a space — resolve through
it to the destination room (to_space)
- copy the 29 referenced decal webp/svg into webstore/assets (self-contained,
served /store/assets); rewrite WP /wp-content/uploads/ paths in the scene API
- skip the 17MB logo .glb mesh decal (flat logo-blue.webp covers branding)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reframed from backend-only to three layers (Lighthouse measures speed, not records-features):
A Discovery (clickable genre/artist/style/label, audio samples, find-in-store), B In-store ops
(item location, store map, A-Z refile/crate-reorg — the deepest moat, nothing else does it),
C Market intel (value/underpricing/scarcity/arbitrage — mostly Have today). Added per-feature
matrix (layer / today / RecordGod / Shopify+Discogs-sync can't / build effort) + Jackson as
co-design partner for the ops layer, not just a reference.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Data-driven dossier on waxmuseumrecords (Jackson, free-year test case). Key finding: their
Shopify is technically excellent (Lighthouse perf 99/SEO 100, no search-app tax) AND already
Discogs-sync-native (titles = Artist-Title(Format)(Grade), body = Media/Sleeve condition +
country/year) — so the pitch is NOT speed/cost, it's cross-store market intelligence on data
they already publish. DealGod under-captures it (condition 0%, release_id 26% despite perfect
titles). Includes honest do-NOT-pitch list, the underpricing/$ hook, read-only onboarding plan,
and DealGod-side ingest fixes (parse Media/Sleeve condition; lift Discogs-format match rate).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
POST /settings/test/{service} validates stored creds against the live service
(Discogs identity, Woo orders, DealGod /api/me) so "connected" means connected.
Dash gets per-service Test buttons with green/amber status.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wraps migrate.py + migrate_virtual.py + build_disc_cache.py + pg_dump→VPS. Vault
(app_secret) excluded so dash credentials survive a refresh. Clean-rebuild for now;
make non-destructive once dash intake is in use (RECORDGOD_PLAN §6).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- schema: disc_cache (release_id→title/artist/thumb/weight); build_disc_cache.py populates it
from the full Discogs dump on ultra (30,694 stocked releases).
- app/mirror.py: enrich() now reads RecordGod's OWN disc_cache via the main DB — no live
discogs_full / dealgod-DB dependency. DealGod reached only via API key.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- app/mirror.py: centralised enrichment, DISCOGS_MIRROR_KIND selects full (ultra `release`)
vs vps (`discogs_release`); virtual.py + wowplatter_v1.py use it.
- Dockerfile + .dockerignore for the VPS container.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- app/vault.py: Fernet-encrypted credential store (app_secret table); key lives only in
RECORDGOD_SECRET_KEY (.env, gitignored) — refuses to store anything if the key is unset.
- app/settings_routes.py: admin-gated GET/POST /settings/secrets; values encrypted at rest,
NEVER returned. Known fields: Woo / Discogs / Cloudflare / DealGod credentials.
- site/index.html: recordgod.com landing. site/dash.html: control room (token gate +
paste-your-credentials form). main.py loads .env, mounts site at /, store at /store.
- Proven: 401 on bad token; DB holds ciphertext (gAAAA…), not plaintext.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
dig.js: enter a crate → records stand packed in a bin; scroll/drag riffles a damped
cursor through them; each sleeve hinges forward at its bottom edge as you pass (smoothstep
wave); tap the front sleeve to pull it out and inspect (price/condition/add-to-cart panel).
Depth-LOD cover loading (±8 around cursor). Procedural fwip/thunk audio, no asset files.
Wired into index.html: click crate → dig scene; render loop branches on dig.active.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- FastAPI twin of DealGod (async SQLAlchemy/asyncpg). wowplatter/v1: ping,
inventory/lookup, inventory/intake (enriches from discogs_full by release_id).
- schema v2: unified inventory (vinyl+general), slim crate, sales/sale_items.
Discogs catalog NOT copied — joined from discogs_full at read time.
- migrate.py: 34,543 shop rows moved (vs ~3.2M in the WowPlatter clone).
- Smoke test green; plan/readme carry the architecture + UI boundary.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>