• Extends the 跳舞直播间 (dance room) system to one independent live room
    per character, with an operator playback-management/blacklist layer
    (T39), a "我的作品" page for paid users (T38), a standalone 人衣图生成
    admin tool, and a new admin-dance-library.html page for curating the
    per-character dance clip pool with AI QC.
    
    On top of that, dance clips now have an explicit published (上架/下架)
    status: passing AI QC (or a manual admin override to "correct") auto-
    publishes a clip, failing it auto-unpublishes it, and only published
    clips are eligible for a room's random-fill pool — unreviewed/rejected
    clips stay in the library but no longer autoplay for viewers. Existing
    already-QC'd "correct" clips are backfilled to published on first boot
    so the room doesn't go quiet.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01MvkJsRcQ2qEuaFea31rBY8
    yibo authored
     
    Browse File »

  • New db.js opens data.sqlite (node:sqlite's DatabaseSync — a Node 24
    built-in, experimental but functional) and creates the users/sessions
    tables per dressup-dance-room-mvcp.md M.1/M.10. Zero new npm
    dependency: no bcrypt/argon2 (node:crypto's scryptSync covers password
    hashing in T19), no better-sqlite3, no package.json needed.
    
    Mirrors store.js's ergonomics (create/get/update, plain JS objects in
    and out — booleans and the oauthProviders array marshalled to/from
    SQLite's TEXT/INTEGER columns internally) rather than reaching for an
    ORM. Exports the openDb/createUsersStore/createSessionsStore factories
    alongside a default singleton so tests can point at an isolated tmp
    file instead of the real data.sqlite (same pattern
    dressup-generate.test.js uses for library.json).
    
    data.sqlite is gitignored under the secrets section, not the "runtime
    state" one — unlike library.json it holds real credential material
    (password hashes, session tokens), not just regenerable content.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
    yibo authored
     
    Browse File »
  • Same hue-recolor approach as the first 10 (dev-plan.md's exit bar
    needs >=30 garments given M.7's per-character-garment dedupe), batch
    generation for the new 20 already submitted to H3.
    
    Also stops tracking uploads/ — binary image/video content, not a good
    git citizen, and this content is explicitly placeholder ("占位旗袍" /
    "待替换") the user intends to replace wholesale later. The recipe
    (characters/garments/dance-refs.json) stays tracked; the files they
    point at don't.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
    yibo authored
     
    Browse File »
  • Same category as live-state.json/dance-state.json: rewritten by
    ingest.js's periodic sync and by every clip play (playCount/
    lastPlayedAt), so every commit touching it was just churn from
    whoever last had the server running locally. File stays on disk,
    just untracked going forward.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_011Deddn3sM3oQnmvqWSMb4y
    yibo authored
     
    Browse File »
  • Backend (server.js):
    - T11: dance.html gets its own schedule/queue state machine, persisted to
      dance-state.json (gitignored, same as live-state.json). Per MVCP M.8,
      the schedule stores videoId references rather than inlined clip
      snapshots like live's does, joining back to library.json at read time.
      Generalized pickBestIndexByStatus/extracted pickLeastPlayedClip so both
      channels' schedulers share the same selection logic instead of forking
      it; live's random-fill pool now excludes channel:"dance" clips (and
      vice versa) so the two channels' filler picks stay independent, which
      wasn't true before this (T8's dance clips could have leaked into
      live.html's filler).
    - T12: GET /api/dance/wardrobe — public, unauthenticated list of active
      garments.
    - T15: POST /api/dance/pick {garmentId, nickname?} — free path, always
      uses the configured default character, reuses submitGeneration (T8/T9)
      whole including its M.7 dedupe cache, then hands the result to
      danceQueue. In-flight generations are reconciled against generationJobs
      on each schedule tick rather than via a promise chain, so a pick
      request survives a server restart the same way T8's own jobs do.
    - T17: separate danceViewers map and POST /api/dance/queue/vote/:id, so
      viewer counts and votes don't mix with live.html's.
    - SCHEDULE_TICK_MS env var makes both channels' tick interval
      configurable so tests don't wait out a real 2s.
    
    Frontend:
    - dance.html (T13/T14/T16): reuses live.html's visual language via
      live.css, adds dance.css for the 9:16 boxed player and wardrobe grid.
      Left column is a 衣柜/传衣服/传人 tab set (only 衣柜 is wired up —
      the other two need accounts/credits, dev-plan-2.md 第三/四期); right
      column shows the queue with vote buttons instead of live.html's chat.
      Age-confirmation gate (5.1节) blocks the page on first visit via a
      cookie, non-dismissable by clicking the backdrop.
    
    Tests: dance-channel.test.js spins up a mock H3 Console (same approach
    as dressup-generate.test.js) to exercise wardrobe listing, pick
    rejection/happy-path/dedupe, vote, and independent viewer counts
    end to end.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • Static video-gen testing tool (MiniMax native API, then fal.ai) that grew
    into an AI drama live channel backed by an internal H3 Console GPU cluster:
    shared virtual-playhead live playback, prompt submit/match/generate queue,
    admin CRUD for the video library, and bilingual (zh/en) semantic clip names.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    yibo authored
     
    Browse File »